From b5d155a9cf24f42b6657a557b2fd820b3cfa0a8c Mon Sep 17 00:00:00 2001 From: Jane Roxanne Date: Wed, 18 Mar 2020 16:02:05 -0500 Subject: [PATCH] New initram format. --- release.lua | 4 +- src/zy-neo/builtins/init_managed/init.lua | 4 +- src/zy-neo/builtins/util_tsar.lua | 73 ++++++++++++++++++++++ src/zy-neo/zinit.lua | 4 +- utils/make_tsar.lua | 76 +++++++++++++++++++++++ utils/selfextract.lua | 46 +++++++++++++- utils/ser.lua | 76 ++++++++++++++++++++--- 7 files changed, 265 insertions(+), 18 deletions(-) create mode 100644 src/zy-neo/builtins/util_tsar.lua create mode 100644 utils/make_tsar.lua diff --git a/release.lua b/release.lua index bbbf7c8..1b00c8b 100644 --- a/release.lua +++ b/release.lua @@ -13,7 +13,7 @@ os.execute("mkdir -p pkg/bios") status("Building EEPROM...") os.execute("luacomp src/loader.lua -O pkg/bios/managed.bios") ---os.execute("luacomp src/zy-neo/zinit.lua -O debug.lua") +os.execute("luacomp src/zy-neo/zinit.lua -O debug.lua") if (os.execute("[[ $(stat --printf=%s pkg/bios/managed.bios) > 4096 ]]")) then io.stderr:write("WARNING: BIOS is over 4KiB!\n") end @@ -36,6 +36,6 @@ status("Library build complete.\n\nBuilding installer...") os.execute("cp utils/ser.lua pkg/init.lua") os.execute("cp -r installer_dat pkg") status("Packing installer...") -os.execute("cd pkg; find * -depth | cpio -o | lua ../utils/mkselfextract.lua > ../zorya-neo-installer.lua") +os.execute("cd pkg; find * -depth | lua ../utils/make_tsar.lua | lua ../utils/mkselfextract.lua > ../zorya-neo-installer.lua") status("Build complete.") status(string.format("Took %ds.", os.time()-start)) \ No newline at end of file diff --git a/src/zy-neo/builtins/init_managed/init.lua b/src/zy-neo/builtins/init_managed/init.lua index db98be6..13e8987 100644 --- a/src/zy-neo/builtins/init_managed/init.lua +++ b/src/zy-neo/builtins/init_managed/init.lua @@ -19,9 +19,9 @@ local cfg = component.proxy(component.list("eeprom")()).getData() local baddr = cfg:sub(1, 36) local bootfs = component.proxy(baddr) -assert(bootfs.exists(".zy2/image.romfs"), "No boot image!") +assert(bootfs.exists(".zy2/image.tsar"), "No boot image!") -local romfs_file = assert(bootfs.open(".zy2/image.romfs", "rb")) +local romfs_file = assert(bootfs.open(".zy2/image.tsar", "rb")) local romfs_dev = romfs.read(function(a) local c = "" diff --git a/src/zy-neo/builtins/util_tsar.lua b/src/zy-neo/builtins/util_tsar.lua new file mode 100644 index 0000000..cfe4cff --- /dev/null +++ b/src/zy-neo/builtins/util_tsar.lua @@ -0,0 +1,73 @@ +local magic = 0x5f7d +local magic_rev = 0x7d5f +local header_fmt = "I2I2I2I2I2I6I6" +local en = string.unpack("=I2", string.char(0x7d, 0x5f)) == magic -- true = LE, false = BE +local function get_end(e) + return (e and "<") or ">" +end +local function read_header(dat) + local e = get_end(en) + local m = string.unpack(e.."I2", dat) + if m ~= magic and m ~= magic_rev then return nil, "bad magic" end + if m ~= magic then + e = get_end(not en) + end + local ent = {} + ent.magic, ent.namesize, ent.mode, ent.uid, ent.gid, ent.filesize, ent.mtime = string.unpack(e..header_fmt, dat) + return ent +end + +local arc = {} + +function arc:fetch(path) + for i=1, #self.tbl do + if (self.tbl[i].name == path and self.tbl[i].mode & 32768 > 0) then + self.seek(self.tbl[i].pos-self.seek(0)) + return self.read(self.tbl[i].filesize), self.tbl[i] + end + end + return nil, "file not found" +end + +function arc:exists(path) + for i=1, #self.tbl do + if (self.tbl[i].name == path) then + return true + end + end + return false +end + +function arc:list(path) + if path:sub(#path) ~= "/" then path = path .. "/" end + local ent = {} + for i=1, #self.tbl do + if (self.tbl[i].name:sub(1, #path) == path and not self.tbl[i].name:find("/", #path+1, false)) then + ent[#ent+1] = self.tbl[i].name + end + end + return ent +end + +function arc:close() + self.close() +end + +local tsar = { + read = function(read, seek, close) + local tbl = {} + local lname = "" + while lname ~= "TRAILER!!!" do + local dat = read(22) + local e = read_header(dat) + e.name = read(e.namesize) + e.pos = seek(e.namesize & 1) + seek(e.filesize + (e.filesize & 1)) + lname = e.name + if lname ~= "TRAILER!!!" then + tbl[#tbl+1] = e + end + end + return setmetatable({tbl = tbl, read = read, seek = seek, close = close}, {__index=tsar}) + end +} \ No newline at end of file diff --git a/src/zy-neo/zinit.lua b/src/zy-neo/zinit.lua index 9a50b88..e662004 100644 --- a/src/zy-neo/zinit.lua +++ b/src/zy-neo/zinit.lua @@ -36,7 +36,7 @@ end local builtins = {} --#include "src/zy-neo/utils.lua" ---#include "src/zy-neo/builtins/util_romfs.lua" +--#include "src/zy-neo/builtins/util_tsar.lua" sys.add_lib("zorya", (function() @@ -54,7 +54,7 @@ sys.add_lib("zorya", (function() local loaded_mods = {} - loaded_mods.util_romfs = romfs + loaded_mods.util_tsar = tsar function zy.loadmod(mod) if (loaded_mods[mod]) then return loaded_mods[mod] end diff --git a/utils/make_tsar.lua b/utils/make_tsar.lua new file mode 100644 index 0000000..e517d8a --- /dev/null +++ b/utils/make_tsar.lua @@ -0,0 +1,76 @@ +--Makes a TSAR file +local lfs = require("lfs") +local files = {} +for l in io.stdin:lines() do + files[#files+1] = l +end +local attr = {} +local modes = { + ["fifo"] = 1, + ["char device"] = 2, + ["directory"] = 4, + ["block device"] = 6, + ["file"] = 8, + ["link"] = 0xA, + ["socket"] = 0xC +} +local function getperm() + local md = 0 + for i=1, 9 do + if (attr.permissions:sub(i,i) ~= "-") then + md = md | (1 << (i-1)) + end + end + return md | (modes[attr.mode] << 12) +end +local size = 0 +for i=1, #files do + lfs.attributes(files[i], attr) + local ent = { + magic = 0x5f7d, + namesize = #files[i], + name = files[i], + mode = getperm(), + uid = attr.uid, + gid = attr.gid, + filesize = attr.size, + mtime = attr.modification + } + if attr.mode ~= "file" then + ent.filesize = 0 + end + io.stdout:write(string.pack("=I2I2I2I2I2I6I6", ent.magic, ent.namesize, ent.mode, ent.uid, ent.gid, ent.filesize, ent.mtime)) + size = size+22 + io.stdout:write(ent.name) + size = size + ent.namesize + if ent.namesize & 1 > 0 then + io.stdout:write("\0") + size = size+1 + end + if attr.mode == "file" then + local h = io.open(files[i], "rb") + io.stdout:write(h:read("*a")) + h:close() + size = size+ent.filesize + if ent.filesize & 1 > 0 then + io.stdout:write("\0") + size = size+1 + end + end +end +do + local ent = { + magic = 0x5f7d, + namesize = 10, + name = "TRAILER!!!", + mode = 0, + uid = 0, + gid = 0, + filesize = 0, + mtime = 0 + } + io.stdout:write(string.pack("=I2I2I2I2I2I6I6", ent.magic, ent.namesize, ent.mode, ent.uid, ent.gid, ent.filesize, ent.mtime)) + io.stdout:write(ent.name) + size = size + 32 +end +io.stderr:write((size//512).." blocks.\n") \ No newline at end of file diff --git a/utils/selfextract.lua b/utils/selfextract.lua index 9657877..26a5bce 100644 --- a/utils/selfextract.lua +++ b/utils/selfextract.lua @@ -48,12 +48,17 @@ local tbl = {} local pos = 1 local function read(n) - local d = dat:sub(pos, pos+n) + local d = dat:sub(pos, pos+n-1) pos = pos + n return d end -local function readint(amt, rev) +local function seek(n) + pos = pos + n + return pos +end + +--[[local function readint(amt, rev) local tmp = 0 for i=(rev and amt) or 1, (rev and 1) or amt, (rev and -1) or 1 do tmp = tmp | (read(1):byte() << ((i-1)*8)) @@ -95,6 +100,39 @@ while true do end tbl[#tbl+1] = dent end +]] + +local magic = 0x5f7d +local magic_rev = 0x7d5f +local header_fmt = "I2I2I2I2I2I6I6" +local en = string.unpack("=I2", string.char(0x7d, 0x5f)) == magic -- true = LE, false = BE +local function get_end(e) + return (e and "<") or ">" +end +local function read_header(dat) + local e = get_end(en) + local m = string.unpack(e.."I2", dat) + if m ~= magic and m ~= magic_rev then return nil, "bad magic" end + if m ~= magic then + e = get_end(not en) + end + local ent = {} + ent.magic, ent.namesize, ent.mode, ent.uid, ent.gid, ent.filesize, ent.mtime = string.unpack(e..header_fmt, dat) + return ent +end + +local lname = "" +while lname ~= "TRAILER!!!" do + local dat = read(22) + local e = read_header(dat) + e.name = read(e.namesize) + e.pos = seek(e.namesize & 1) + seek(e.filesize + (e.filesize & 1)) + lname = e.name + if lname ~= "TRAILER!!!" then + tbl[#tbl+1] = e + end +end local unpack = unpack or table.unpack @@ -102,4 +140,6 @@ for i=1, #tbl do if (tbl[i].name == "init.lua") then load(dat:sub(tbl[i].pos, tbl[i].pos+tbl[i].filesize-1))(tbl, dat, unpack(arg)) end -end \ No newline at end of file +end + +error("Init not found.") \ No newline at end of file diff --git a/utils/ser.lua b/utils/ser.lua index 3fd808d..e7ea93b 100644 --- a/utils/ser.lua +++ b/utils/ser.lua @@ -111,22 +111,80 @@ fs.makeDirectory(".zy2") fs.makeDirectory(".zy2/mods") fs.makeDirectory(".zy2/lib") -local romfs = fs.open(".zy2/image.romfs", "w") -fs.write(romfs, "romfs\1\0") +local romfs = fs.open(".zy2/image.tsar", "w") +--fs.write(romfs, "romfs\1\0") + +local modes = { + ["fifo"] = 1, + ["char device"] = 2, + ["directory"] = 4, + ["block device"] = 6, + ["file"] = 8, + ["link"] = 0xA, + ["socket"] = 0xC +} +local function getperm(ftype, perm) + local md = 0 + for i=1, 9 do + if (perm:sub(i,i) ~= "-") then + md = md | (1 << (i-1)) + end + end + return md | (modes[ftype] << 12) +end + +function makeDirectory(path) + local ent = { + name = path, + namesize = #path, + magic = 0x5f7d, + mode = getperm("directory", "r-xr-xr-x"), + uid = 0, + gid = 0, + filesize = 0, + mtime = os.time() + } + fs.write(romfs, string.pack("=I2I2I2I2I2I6I6", ent.magic, ent.namesize, ent.mode, ent.uid, ent.gid, ent.filesize, ent.mtime)) + fs.write(romfs, path) +end + +makeDirectory(".zy2") +makeDirectory(".zy2/mods") +makeDirectory(".zy2/lib") function writeFile(path, data) --local hand = fs.open(path, "w") --fs.write(hand, data) --fs.close(hand) - fs.write(romfs, string.char(#path)..path) - local ext = path:sub(#path-2) - fs.write(romfs, string.pack(" 0 then + io.stdout:write("\0") end fs.write(romfs, data) + if ent.filesize & 1 > 0 then + io.stdout:write("\0") + size = size+1 + end end setStatus("Getting file list...")