diff --git a/installer_dat/package_list.lua b/installer_dat/package_list.lua index ff8bca0..51a5d0a 100644 --- a/installer_dat/package_list.lua +++ b/installer_dat/package_list.lua @@ -1,13 +1,14 @@ { {name="zlan", cat="util", path="lib/util_zlan.zy2l"}, - --{name="openos", cat="loader", path="mods/loader_openos.zy2m"}, + {name="openos", cat="loader", path="mods/loader_openos.zy2m"}, + {name="fuchas", cat="loader", path="mods/loader_fuchas.zy2m"}, --{name="tsuki", cat="loader", path="mods/loader_tsuki.zy2m"}, --{name="romfs", cat="util", path="mods/util_romfs.zy2m"}, - --{name="cpio", cat="util", path="mods/util_cpio.zy2m"}, + {name="cpio", cat="util", path="lib/util_cpio.zy2l"}, --{name="frequest", cat="util", path="mods/util_frequest.zy2m"}, --{name="loadfile", cat="loader", path="mods/loader_loadfile.zy2m"}, {name="minitel", cat="net", path="lib/net_minitel.zy2l"}, - {name="vdev", cat="util", path="mods/util_vdev.zy2m"}, + --{name="vdev", cat="util", path="mods/util_vdev.zy2m"}, {name="menu", cat="menu", path="mods/menu_classic.zy2m"}, --{name="vdevrt", cat="rtmod", path="mods/rtmod_vdevrt.zy2m"}, --{name="tsukinet", cat="net", path="mods/net_tsukinet"}, diff --git a/ksrc/libs/thd.lua b/ksrc/libs/thd.lua index 036b4df..7fb19df 100644 --- a/ksrc/libs/thd.lua +++ b/ksrc/libs/thd.lua @@ -52,6 +52,9 @@ function thd.run() if (c_status(threads[i][2]) ~= "running") then local er, dl = c_resume(threads[i][2], unpack(last_sig)) if (not er) then error(threads[i][1]..": "..dl) end + if (dl == "k") then + threads[i][6] = true + end dl = computer.uptime() + (dl or math.huge) threads[i][4] = dl sigs[#sigs+1] = {ps(0)} @@ -59,13 +62,11 @@ function thd.run() end end local t = {} - for k,v in pairs(threads) do + for i=1, #threads do + local v = threads[i] if (c_status(v[2]) ~= "dead" and not v[6]) then - if (type(k) == "number") then - t[#t+1] = v - else - t[k] = v - end + t[#t+1] = v + t[v[2]] = v end end threads = t diff --git a/lib/util_cpio/init.lua b/lib/util_cpio/init.lua index e69de29..eec7488 100644 --- a/lib/util_cpio/init.lua +++ b/lib/util_cpio/init.lua @@ -0,0 +1,82 @@ +local comp = component +local cpio = {} +local arc = {} + +local function read(f, h, n) + local d = f.read(h, n) + return d +end + +local function readint(f, h, 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(f, h, 1):byte() << ((i-1)*8)) + end + return tmp +end + +function cpio.read(drive, path) + local f = comp.proxy(drive) + local h = f.open(path) + local tbl = {} + while true do + local dent = {} + dent.magic = readint(f, h, 2) + local rev = false + if (dent.magic ~= tonumber("070707", 8)) then rev = true end + dent.dev = readint(f, h, 2) + dent.ino = readint(f, h, 2) + dent.mode = readint(f, h, 2) + dent.uid = readint(f, h, 2) + dent.gid = readint(f, h, 2) + dent.nlink = readint(f, h, 2) + dent.rdev = readint(f, h, 2) + dent.mtime = (readint(f, h, 2) << 16) | readint(f, h, 2) + dent.namesize = readint(f, h, 2) + dent.filesize = (readint(f, h, 2) << 16) | readint(f, h, 2) + local name = read(f, h, dent.namesize):sub(1, dent.namesize-1) + if (name == "TRAILER!!!") then break end + --for k, v in pairs(dent) do + -- print(k, v) + --end + dent.name = name + if (dent.namesize % 2 ~= 0) then + f.seek(h, "cur", 1) + end + if (dent.mode & 32768 ~= 0) then + --fwrite() + end + dent.pos = f.seek(h, "cur", 0) + f.seek(h, "cur", dent.filesize) + if (dent.filesize % 2 ~= 0) then + f.seek(h, "cur", 1) + end + tbl[#tbl+1] = dent + end + return setmetatable({ + tbl = tbl, + fs = f, + handle = h + }, {__index=arc}) +end + +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.fs.seek(self.handle, "set", self.tbl[i].pos) + return self.fs.read(self.handle, self.tbl[i].filesize) + end + end + return nil, "file not found" +end + +function arc:close() + self.fs.close(self.handle) + self.tbl = {} +end + +function arc:list_dir(path) + --soon:tm: +end + +return cpio \ No newline at end of file diff --git a/lib/util_urf/init.lua b/lib/util_urf/init.lua index 0e7a46c..3af592f 100644 --- a/lib/util_urf/init.lua +++ b/lib/util_urf/init.lua @@ -17,6 +17,283 @@ local function read_ali(fs, h) return tmp end +local function read_int(fs, h, count) + local tmp = 0 + for i=0, count-1 do + tmp = tmp | (fs.read(h, 1):byte() << (count*8)) + end + return tmp +end + +local function read_string(fs, h) + local len = read_ali(fs, h) + return fs.read(h, len) +end + +local xdec = { + ["NAME"] = function(fs, h) + return read_string(fs, h) + end, + ["PERM"] = function(fs, h) + return read_int(fs, h, 2) + end, + ["W32P"] = function(fs, h) + return fs.read(h, 1):byte() + end, + ["OTIM"] = function(fs, h) + return read_int(fs, h, 8) + end, + ["MTIM"] = function(fs, h) + return read_int(fs, h, 8) + end, + ["CTIM"] = function(fs, h) + return read_int(fs, h, 8) + end, + ["ATIM"] = function(fs, h) + return read_int(fs, h, 8) + end,, + ["SCOS"] = function(fs, h) + return read_string(fs, h) + end +} + +local decode = { + ["X"] = function(fs, h, size) + local oid = read_ali(fs, h) + local xtype = fs.read(h, 4) + return { + type = "meta", + id = oid, + key = xtype, + value = xdec[xtype](fs, h) + } + end, + ["F"] = function(fs, h, size) + return { + type="file", + name = read_string(fs, h), + offset = read_ali(fs, h), + size = read_ali(fs, h), + id = read_ali(fs, h), + pid = read_ali(fs, h) + } + end, + ["D"] = function(fs, h, size) + return { + type="dir", + name = read_string(fs, h), + id = read_ali(fs, h), + pid = read_ali(fs, h) + } + end, + ["Z"] = function(fs, h, size) + return { + type="eoh" + size = read_ali(fs, h) + } + end +} + local function read_entrydat(fs, h) - local etype = fs.read(h, 1):byte() -end \ No newline at end of file + local etype = fs.read(h, 1) + local ebyte = etype:byte() + local size = read_ali(fs, h) + if (ebyte & flag_crit > 0 and not decode[etype]) then error("Unknown critical entry.") end + if (ebyte & flag_required == 0) then error("Required flag not set.") end + if (decode[etype]) then + return decode[etype](fs, h, size) + end + return {type="unknown"} +end + +local function get_offset(fs, h) + fs.seek(h, "set", 9) + local ent = {} + while ent.type ~= "eoh" do + ent = read_entrydat(fs, h) + end + return fs.seek(h, "cur", 0), ent.size +end + +local function path_part_iter(path) + path = path:gsub("/+", "/"):gsub("^/", ""):gsub("/$", "") + local lpos = 1 + return function() + if not lpos then return nil end + local s, e = path:find("(.-)/", lpos) + if not s then + local lp = lpos + lpos = nil + return path:sub(lp) + end + local rtn = path:sub(s, e-1) + lpos = e+1 + return rtn + end +end + +local unpack = unpack or table.unpack + +local function sfpcall(a, func, ...) + local ptr = a.fs.seek(a.h, "cur", 0) + local rv = {func(...)} + a.fs.seek(a.h, "set", ptr) + return unpack(rv) +end + +local function cache_obj(a, objdat) + a.cache = a.cache or {} + a.cache[#a.cache+1] = objdat +end + +local function get_obj_prop(a, obj, name) + name = name:upper() + if (a.cache) then + for i=1, #a.cache do + if (a.cache[i].type=="meta" and a.cache[i].id==obj and a.cache[i].key == name) then return a.cache[i].value end + end + end + fs.seek(h, "set", 9) + local ent = {} + while ent.type ~= "eoh" do + ent = read_entrydat(fs, h) + if (ent.type=="meta" and ent.id==obj and ent.key == name) then + cache_obj(a, ent) + return ent.value + end + end +end + +local function path_to_obj(a, path) + if (path == "/" or path == "") then + return { + type = "dir", + name = "/root\\", + id = 0, + pid = 0 + } + end + local tbl = {} + for p in path_part_iter(path) do + tbl[#tbl+1] = p + end + local part = 1 + local pid = 0 + --search cache + if (a.cache) then + local i = 0 + while i < #a.cache do + i = i+1 + if (a.cache[i].type == "file" or a.cache[i].type == "dir") then + if (a.cache[i].pid == pid and (a.cache[i].name == tbl[part] or get_obj_prop(a, a.cache[i].id, "NAME") == tbl[part])) then + part = part+1 + pid = a.cache[i].id + i=0 + if (part == #tbl) then + return a.cache[i], pid + end + end + end + end + end + -- Now we search the hard way, then cache along the way. + fs.seek(h, "set", 9) + local ent = {} + while ent.type ~= "eoh" do + ent = read_entrydat(fs, h) + if (ent.type == "file" or ent.type=="dir") then + if (ent.name == tbl[part] or sfpcall(get_obj_prop, a, ent.id, "NAME") == tbl[part]) then + pid = ent.id + cache_obj(a, ent) + part = part + 1 + end + if (part == #tbl) then + break + end + end + end + return ent, pid +end + +local function get_by_id(a, id) + if (a.cache) then + for i=1, #a.cache do + if ((a.cache[i].type=="file" or a.cache[i].type=="dir") and a.cache[i].id==id) then return a.cache[i] end + end + end + fs.seek(h, "set", 9) + local ent = {} + while ent.type ~= "eoh" do + ent = read_entrydat(fs, h) + if ((ent.type=="file" or ent.type=="dir") and ent.id==id) then + cache_obj(a, ent) + return ent + end + end +end + +local function id_to_path(a, id) + local ne = get_by_id(a, id) + if not ne then return nil, "not found" end + local path = get_obj_prop(a, id, "NAME") or ne.name + path = "/" .. path + while ne and ne.pid > 0 do + ne = get_by_id(a, ne.pid) + if not ne then return nil, "not found" end + path = "/" .. (get_obj_prop(a, ne.id, "NAME") or ne.name) .. path + end + return path +end + +local urf = {} +function urf.open(drive, path) + local fs = component.proxy(drive) + local hand = fs.open(path) + if fs.read(hand, 8) ~= "URF\x11\1\1\x12\0" then return nil, "bad signature" end + local e, z = get_offset(fs, hand) + return setmetatable({ + fs = fs, + h = hand, + cache = {}, + epos = e, + bsize = z + }, {__index=arc}) +end + +local arc = {} +function arc:fetch(path) + local obj = path_to_obj(self, path) + if (obj.type ~= "file") then return nil, "not a file" end + self.fs.seek(self.h, "set", self.epos+obj.offset) + return self.fs.read(self.h, obj.size) +end + +function arc:close() + self.cache = nil + self.fs.close(self.h) + self.fs = nil +end + +function arc:list_dir(path) + local obj = path_to_obj(self, path) + if (obj.type ~= "dir") then return nil, "not a dir" end + local objects = {} + for i=1, self.cache do + if (self.cache[i].pid == obj.id) then + objects[#objects+1] = (get_obj_prop(self, self.cache[i].id, "NAME") or self.cache[i].name) + end + end + + self.fs.seek(self.h, "set", 9) + local ent = {} + while ent.type ~= "eoh" do + ent = read_entrydat(self.fs, self.h) + if ((ent.type=="file" or ent.type=="dir") and ent.pid==obj.id) then + cache_obj(self, ent) + objects[#objects+1] = sfpcall(get_obj_prop, self, ent.id, "NAME") or ent.name + end + end + return objects +end + +return urf \ No newline at end of file diff --git a/mods/loader_fuchas/init.lua b/mods/loader_fuchas/init.lua new file mode 100644 index 0000000..2867af1 --- /dev/null +++ b/mods/loader_fuchas/init.lua @@ -0,0 +1,22 @@ +local zy = krequire("zorya") +--zy.loadmod("vdev_biosdev") +local utils = krequire("utils") +local thd = krequire("thd") +--local vdev = krequire("zorya").loadmod("util_vdev") +local oefi = zy.loadmod("util_oefiv2") +-- No low-level loading yet. +return function(addr, args) + --oefi.getExtensions().ZyNeo_ExecOEFIApp(addr, ".efi/fuchas.efi2", ...) + --We don't do that here. + local env = oefi.getExtensions().ZyNeo_GetOEFIEnv(addr) + env.computer.supportsOEFI = function() + return true + end + env.os_arguments = args + env.loadfile = env.oefi.loadfile + thd.add("fuchas", function() + env.loadfile("Fuchas/Kernel/boot.lua")() --This is how we do. + computer.pushSignal("fuchas_dead") + end) + while true do if computer.pullSignal() == "fuchas_dead" then break end end +end \ No newline at end of file diff --git a/mods/loader_openos/init.lua b/mods/loader_openos/init.lua new file mode 100644 index 0000000..2b06879 --- /dev/null +++ b/mods/loader_openos/init.lua @@ -0,0 +1,17 @@ +local zy = krequire("zorya") +--zy.loadmod("vdev_biosdev") +local utils = krequire("utils") +--local vdev = krequire("zorya").loadmod("util_vdev") +return function(addr) + local fs = component.proxy(addr) + local kr = krequire + krequire = nil + --vdev.overwrite(_G) + function computer.getBootAddress() + return addr + end + function computer.setBootAddress()end + --log(env, env.computer, env.computer.getBootAddress, env.computer.getBootAddress()) + load(utils.readfile(fs.address, fs.open("init.lua")), "=init.lua", "t")() + krequire = kr +end \ No newline at end of file diff --git a/mods/loader_removable_media/init.lua b/mods/loader_removable_media/init.lua new file mode 100644 index 0000000..3e33fd9 --- /dev/null +++ b/mods/loader_removable_media/init.lua @@ -0,0 +1,10 @@ +return function(filter) + filter = filter or function() return true end + return function() + for f in component.list("filesystem") do + if (filter(f) and component.invoke(f, "spaceTotal") ) then + + end + end + end +end \ No newline at end of file diff --git a/mods/loader_tsuki/init.lua b/mods/loader_tsuki/init.lua new file mode 100644 index 0000000..e69de29 diff --git a/mods/menu_bios/init.lua b/mods/menu_bios/init.lua index 7b5782c..911a01a 100644 --- a/mods/menu_bios/init.lua +++ b/mods/menu_bios/init.lua @@ -5,4 +5,5 @@ gpu.bind(component.list("screen")()) gpu.set(1, 1, "Zorya NEO v2.0 BIOS/Bootloader") gpu.set(1, 2, "(c) 2020 Adorable-Catgirl") -gpu.set(1, 4, "Memory: "..math.floor(computer.totalMemory()/1024).."K") \ No newline at end of file +gpu.set(1, 4, "Memory: "..math.floor(computer.totalMemory()/1024).."K") +--gpu.set(1, 5) \ No newline at end of file diff --git a/mods/menu_classic/init.lua b/mods/menu_classic/init.lua index 83bfaf9..1530383 100644 --- a/mods/menu_classic/init.lua +++ b/mods/menu_classic/init.lua @@ -35,7 +35,8 @@ function menu.draw() gpu.setForeground(fg) cls() --Draw some things - gpu.set((w/2)-7, 1, "Zorya NEO BIOS") + local namestr = _BIOS .. " " .. string.format("%.1f.%d %s", _ZVER, _ZPAT, _ZGIT) + gpu.set((w/2)-(#namestr/2), 1, namestr) gpu.set(1, 2, border_chars[1]) gpu.set(2, 2, border_chars[2]:rep(w-2)) gpu.set(w, 2, border_chars[3]) diff --git a/mods/util_oefiv1/init.lua b/mods/util_oefiv1/init.lua new file mode 100644 index 0000000..1a91f11 --- /dev/null +++ b/mods/util_oefiv1/init.lua @@ -0,0 +1,59 @@ +local comp = component +local computer = computer +local thd = krequire("thd") +local zy = krequire("zorya") +local utils = krequire("utils") + +local oefi = {} + +local function load_oefi(drive, path, uuid) + local oefi_env = {} + local env = {} + utils.deepcopy(_G, env) + env.krequire = nil + env._BIOS = nil + env._ZVER = nil + env._ZVSTR = nil + env._ZPAT = nil + env.oefi = setmetatable(oefi_env, {__index=oefi}) + function env.computer.getBootAddress() + return drive + end + function oefi_env.returnToOEFI() + computer.pushSignal("oefi_killall") + computer.pullSignal("k") --It actually kills the application + end + local h = comp.invoke(drive, "open", path) + local dat = utils.readfile(drive, h) + comp.invoke(drive, "close", h) + return load(dat, "="..path, "t", env) +end + +function oefi.getAPIVersion() + return 1 +end + +function oefi.getImplementationName() + return _BIOS +end + +function oefi.getImplementationVersion() + return _ZVER +end + +function oefi.execOEFIApp(fs, path) + local uuid = string.char(math.random(0,255),math.random(0,255),math.random(0,255),math.random(0,255)) + local func, manifest = load_oefi(drive, path, uuid) + local args = {} + local name = "oefi$"..manifest.name:gsub(" ", "_") + thd.add(name, function() + func(unpack(args)) + os.pushSignal("oefi_end", uuid) + end) --ez + while true do + local s, i = computer.pullSignal() + if (s == "oefi_end" and i == uuid) or s == "oefi_killall" then + break + end + end +end \ No newline at end of file diff --git a/mods/util_oefiv2/bios.lua b/mods/util_oefiv2/bios.lua new file mode 100644 index 0000000..7f7d41d --- /dev/null +++ b/mods/util_oefiv2/bios.lua @@ -0,0 +1,25 @@ +local function gen_proto(drive) + return { + methods = { + get = function() + return "< Virtual BIOS >" + end, + getData = function() + return string.char(2)..drive.."Zorya NEO BIOS"..string.char(0):rep(6) + end, + setData = function() + return "" + end, + set = function() + return "" + end, + getLabel = function() + return "Virtual OEFI BIOS" + end, + setLabel = function() + return "Virtual OEFI BIOS" + end + }, + docs = {} + } +end \ No newline at end of file diff --git a/mods/util_oefiv2/init.lua b/mods/util_oefiv2/init.lua index e69de29..e1bc28b 100644 --- a/mods/util_oefiv2/init.lua +++ b/mods/util_oefiv2/init.lua @@ -0,0 +1,166 @@ +local comp = component +local computer = computer +local thd = krequire("thd") +local zy = krequire("zorya") +local utils = krequire("utils") +local oefi = {} + +local ext = {} + +local unpack = unpack or table.unpack + +---#include "bios.lua" + +local function load_oefi_env(file, envx) + utils.debug_log(file, envx.fs) + local cpio = krequire("util_cpio") + local vdev = zy.loadmod("util_vdev") + local arc = cpio.read(envx.fs, file) + local oefi_env = {} + local env = {} + utils.deepcopy(_G, env) + env.krequire = nil + env._BIOS = nil + env._ZVER = nil + env._ZVSTR = nil + env._ZPAT = nil + env.oefi = setmetatable(oefi_env, {__index=oefi}) + local fs = component.proxy(envx.fs) + function oefi_env.loadfile(path) + local h = fs.open(path) + local fd = utils.readfile(envx.fs, h) + fs.close(h) + return load(fd, "="..path, "t", env) + end + function oefi_env.loadInternalFile(path) + return arc:fetch(path) + end + function oefi_env.returnToOEFI() + computer.pushSignal("oefi_killall") + computer.pullSignal("k") --It actually kills the application + end + function env.computer.pullSignal(...) + local s = {computer.pullSignal(...)} + if (s[1] == "oefi_killall") then + computer.pullSignal("k") + end + return unpack(s) + end + function oefi_env.getBootAddress() + return envx.fs + end + --vdev.overwrite(env) + --vdev.register_type("eeprom_oefiemu", gen_proto(baddr(envx.fs.address))) + --vdev.add_device("biosemu", "eeprom_oefiemu") + local dat = env.oefi.loadInternalFile("app.exe") + local func = load(dat, "="..file..":/app.exe", "t", env) + local cfgdat = env.oefi.loadInternalFile("app.cfg") + local cfg = {} + for line in cfgdat:gmatch("(.-)[\r\n]+") do + utils.debug_log("CONFIG", line) + local k, v = line:match("(.+)=(.+)") + utils.debug_log("PARSED", k, v) + cfg[k] = v + end + return func, cfg +end + +local function load_oefi(drive, path) + local ext = path:sub(#path-4, #path) + return load_oefi_env(path, {fs = drive, uuid=uuid}) +end + +function oefi.getAPIVersion() + return 2.1 +end + +function oefi.getImplementationName() + return _BIOS +end + +function oefi.getImplementationVersion() + return _ZVER +end + +function oefi.execOEFIApp(drive, path) + local uuid = string.char(math.random(0,255),math.random(0,255),math.random(0,255),math.random(0,255)) + local func, manifest = load_oefi(drive, path, uuid) + local args = {} + local name = "oefi$"..manifest.name:gsub(" ", "_") + thd.add(name, function() + func(unpack(args)) + os.pushSignal("oefi_end", uuid) + end) --ez + while true do + local s, i = computer.pullSignal() + if (s == "oefi_end" and i == uuid) or s == "oefi_killall" then + break + end + end +end + +function oefi.getExtensions() + return ext +end + +function oefi.getApplications() + return {} +end + +function ext.ZyNeo_GetOEFIEnv(drive, arc) + local oefi_env = {} + local env = {} + utils.deepcopy(_G, env) + env.krequire = nil + env._BIOS = nil + env._ZVER = nil + env._ZVSTR = nil + env._ZPAT = nil + env.oefi = setmetatable(oefi_env, {__index=oefi}) + local fs = component.proxy(drive) + function oefi_env.loadfile(path) + local h = fs.open(path) + local fd = utils.readfile(drive, h) + fs.close(h) + return load(fd, "="..path, "t", env) + end + function oefi_env.loadInternalFile(path) + if (arc) then + return arc:fetch(path) + end + end + function oefi_env.returnToOEFI() + computer.pushSignal("oefi_killall") + computer.pullSignal("k") --It actually kills the application + end + function env.computer.pullSignal(...) + local s = {computer.pullSignal(...)} + if (s[1] == "oefi_killall") then + computer.pullSignal("k") + end + return unpack(s) + end + function oefi_env.getBootAddress() + return drive + end + return env +end + +function ext.ZyNeo_ExecOEFIApp(drive, path, ...) + local uuid = string.char(math.random(0,255),math.random(0,255),math.random(0,255),math.random(0,255)) + local func, manifest = load_oefi(drive, path, uuid) + local args = {...} + local name = "oefi$"..manifest.name:gsub(" ", "_") + thd.add(name, function() + func(unpack(args)) + os.pushSignal("oefi_end", uuid) + end) --ez + while true do + local s, i = computer.pullSignal() + if (s == "oefi_end" and i == uuid) or s == "oefi_killall" then + break + end + end +end + +return oefi \ No newline at end of file diff --git a/mods/util_vdev/init.lua b/mods/util_vdev/init.lua index 4b82d6b..16ee207 100644 --- a/mods/util_vdev/init.lua +++ b/mods/util_vdev/init.lua @@ -38,13 +38,15 @@ end local cdevinfo = computer.getDeviceInfo -component = {} +vdev.component = {} +vdev.computer = {} for k, v in pairs(comp) do - component[k] = v + vdev.component[k] = v end -function component.list(dtype) +function vdev.component.list(dtype, match) + dtype = dtype or "" local lpos = 0 local func = comp.list(dtype) local ft = {} @@ -52,7 +54,7 @@ function component.list(dtype) ft[k] = v end for i=1, #devices do - if (devices[i].type:find(dtype, true) == 1) then + if (dtype == devices[i].type or (not match and devices[i].type:sub(1, #dtype) == dtype)) then ft[ devices[i].addr ] = devices[i].type end end @@ -65,22 +67,28 @@ function component.list(dtype) if (lpos > #devices) then return func() end - if (devices[lpos].type:find(dtype, true) == 1) then + if (dtype == devices[lpos].type or (not match and devices[lpos].type:sub(1, #dtype) == dtype)) then return devices[lpos].addr end end end}) end -function component.proxy(addr) +local function debug_log(...) + log("return", ...) + return ... +end + +function vdev.component.proxy(addr) for i=1, #devices do if (devices[i].addr == addr) then return setmetatable({}, {__index=function(self, index) if (types[devices[i].type].methods[index]) then local func = setmetatable({}, {__call=function(...) + log("proxy", addr, index, ...) return types[devices[i].type].methods[index](devices[i].addr, ...) end, __tostring = function() - return types[devices[i].type].doc[index] + return types[devices[i].type].doc[index] or (index.."(...):any") end}) self[index] = func end @@ -90,22 +98,23 @@ function component.proxy(addr) return comp.proxy(addr) end -function component.invoke(addr, meth, ...) +function vdev.component.invoke(addr, meth, ...) + log("invoke", addr, meth, ...) for i=1, #devices do if (devices[i].addr == addr) then - if (types[devices[i].type][meth]) then - types[devices[i].type].methods[meth](addr, ...) + if (types[devices[i].type].methods[meth]) then + return debug_log("invoke", types[devices[i].type].methods[meth](addr, ...)) end end end return comp.invoke(addr, meth, ...) end -function component.doc(addr, meth) +function vdev.component.doc(addr, meth) for i=1, #devices do if (devices[i].addr == addr) then if (types[devices[i].type].methods[meth]) then - return types[devices[i].type].doc[meth] + return types[devices[i].type].doc[meth] or (index.."(...):any") end return end @@ -113,7 +122,7 @@ function component.doc(addr, meth) return comp.doc(addr, meth) end -function component.type(addr) +function vdev.component.type(addr) for i=1, #devices do if (devices[i].addr == addr) then return devices[i].type @@ -122,7 +131,7 @@ function component.type(addr) return comp.type(addr) end -function component.slot(addr) +function vdev.component.slot(addr) for i=1, #devices do if (devices[i].addr == addr) then return -1 @@ -131,7 +140,7 @@ function component.slot(addr) return comp.slot(addr) end -function component.methods(addr) +function vdev.component.methods(addr) for i=1, #devices do if (devices[i].addr == addr) then local m = {} @@ -144,7 +153,7 @@ function component.methods(addr) return comp.methods(addr) end -function computer.getDeviceInfo() +function vdev.computer.getDeviceInfo() local tbl = cdevinfo() for i=1, #devices do local info = {} @@ -158,4 +167,14 @@ function computer.getDeviceInfo() return tbl end +function vdev.overwrite(env) + for k, v in pairs(vdev) do + if (type(v) == "table") then + for j, b in pairs(v) do + env[k][j] = b + end + end + end +end + return vdev \ No newline at end of file diff --git a/mods/vdev_biosdev/init.lua b/mods/vdev_biosdev/init.lua index e69de29..b7b4e68 100644 --- a/mods/vdev_biosdev/init.lua +++ b/mods/vdev_biosdev/init.lua @@ -0,0 +1,31 @@ +local zy = krequire("zorya") +local vdev = zy.loadmod("util_vdev") +vdev.register_type("zybios", { + methods = { + get_threads_info = function() + local threads = {} + for i=1, zy.lkthdn() do + local info = zy.lkthdi(i) + threads[i] = { + name = info[1], + deadline = info[6] + } + end + return threads + end, + get_version = function() + return string.format("%f.%d", _ZVER, _ZPAT) + end, + get_git_revision = function() + return _ZGIT + end + }, + docs = { + get_threads_info = "get_threads_info():table -- Returns the BIOS thread information.", + get_version = "get_version():string -- Returns the Zorya NEO version.", + get_git_revision = "get_git_revision():string -- Returns the git revision of the build." + } +}) +vdev.add_device("ZORYA_BIOS", "zybios") + +return true \ No newline at end of file diff --git a/release.lua b/release.lua index 956457a..7a864db 100644 --- a/release.lua +++ b/release.lua @@ -1,19 +1,40 @@ --Makes a release CPIO +local start = os.time() +function status(s) + io.stderr:write(s.."\n") +end +status("Cleaning last build...") os.execute("rm -rf pkg") + +status("Making directories...") os.execute("mkdir -p pkg/mods") os.execute("mkdir -p pkg/lib") os.execute("mkdir -p pkg/bios") + +status("Building EEPROM...") os.execute("luacomp src/loader.lua -O pkg/bios/managed.bios") +if (os.execute("[[ $(stat --printf=%s pkg/bios/managed.bios) > 4096 ]]")) then + io.stderr:write("WARNING: BIOS is over 4KiB!\n") +end + +status("\n\nBuilding modules.") if (os.execute("stat mods 1>/dev/null 2>&1")) then for l in io.popen("ls mods"):lines() do - os.execute("zsh -c 'cd mods/"..l.."; luacomp init.lua | lua ../../utils/zlua.lua > ../../pkg/mods/"..l..".zy2m'") + status("MOD\t"..l) + os.execute("zsh -c 'cd mods/"..l.."; luacomp init.lua -mnone | lua ../../utils/zlua.lua > ../../pkg/mods/"..l..".zy2m'") end end +status("Module build complete.\n\nBuilding libraries.") if (os.execute("stat lib 1>/dev/null 2>&1")) then for l in io.popen("ls lib"):lines() do - os.execute("zsh -c 'cd lib/"..l.."; luacomp init.lua -mluamin | lua ../../utils/zlua.lua > ../../pkg/lib/"..l..".zy2l'") + status("LIB\t"..l) + os.execute("zsh -c 'cd lib/"..l.."; luacomp init.lua -mnone | lua ../../utils/zlua.lua > ../../pkg/lib/"..l..".zy2l'") end end +status("Library build complete.\n\nBuilding installer...") os.execute("cp utils/ser.lua pkg/init.lua") os.execute("cp -r installer_dat pkg") -os.execute("cd pkg; find * -depth | cpio -o | lua ../utils/mkselfextract.lua > ../zorya-neo-installer.lua") \ No newline at end of file +status("Packing installer...") +os.execute("cd pkg; find * -depth | cpio -o | 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/utils.lua b/src/zy-neo/utils.lua new file mode 100644 index 0000000..da22d25 --- /dev/null +++ b/src/zy-neo/utils.lua @@ -0,0 +1,61 @@ + +builtins.utils = function() +local utils = {} + +function utils.debug_log(...) + local sb = component.list("sandbox")() or component.list("ocemu")() + if (sb) then component.invoke(sb, "log", ...) end +end + +function utils.baddr(address) + local address = address:gsub("-", "", true) + local b = "" + for i=1, #address, 2 do + b = b .. string.char(tonumber(address:sub(i, i+1), 16)) + end + return b +end + +function utils.readfile(f,h) + local b="" + local d,r=component.invoke(f,"read",h,math.huge) + if not d and r then error(r)end + b=d + while d do + local d,r=component.invoke(f,"read",h,math.huge) + b=b..(d or "") + if(not d)then break end + end + component.invoke(f,"close",h) + return b +end + +-- Hell yeah, deepcopy time. +function utils.deepcopy(src, dest) + dest = dest or {} + local coppied = {[src] = dest} + local cin = {src} + local cout = {dest} + while #cin > 0 do + for k, v in pairs(cin[1]) do + if (type(v) ~= "table") then + cout[1][k] = v + else + if (coppied[v]) then + cout[1][k] = coppied[v] + else + local t = {} + cout[1][k] = t + cin[#cin+1] = v + cout[#cout+1] = t + coppied[v] = t + end + end + end + table.remove(cout, 1) + table.remove(cin, 1) + end + return dest +end +return utils +end \ No newline at end of file diff --git a/src/zy-neo/zinit.lua b/src/zy-neo/zinit.lua index c34815c..d1eb9e0 100644 --- a/src/zy-neo/zinit.lua +++ b/src/zy-neo/zinit.lua @@ -1,9 +1,10 @@ -local lzss_decompress = {...} +local lzss_decompress = ... --Zorya NEO itself. _BIOS = "Zorya NEO" _ZVSTR = "2.0" _ZVER = 2.0 _ZPAT = 0 +_ZGIT = "$[[git rev-parse --short HEAD]]" --#include "ksrc/kinit.lua" local thd = krequire("thd") local util = krequire("util") @@ -12,32 +13,39 @@ local component = component local computer = computer local booted = false local zcfg = {} - +function log(...) + component.proxy(component.list("ocemu")()).log(...) +end local th_i = 0 local function th_a(func) thd.add("zyneo$"..th_i, func) end local builtins = {} +--#include "src/zy-neo/utils.lua" sys.add_lib("zorya", (function() local mod_search = {} local zy = {} - function zy.get_bootlist() + --function zy.get_bootlist() - end + --end - function zy.boot(i) - th_a(zcfg[i][2](zcfg[i][3])) - booted = true - end + --function zy.boot(i) + -- th_a(zcfg[i][2](zcfg[i][3])) + -- booted = true + --end + + local loaded_mods = {} function zy.loadmod(mod) + if (loaded_mods[mod]) then return loaded_mods[mod] end for i=1, #mod_search do + log(i, #mod_search, mod) local r = mod_search[i](mod) - if r then return r end + if r then loaded_mods[mod] = r return r end end end @@ -47,6 +55,7 @@ sys.add_lib("zorya", (function() function zy.add_mod_search(func) mod_search[#mod_search+1] = func + log(#mod_search) end function zy.lkthdn() @@ -61,15 +70,11 @@ end)()) --#include "src/zy-neo/init.lua" -builtins["menu"] = (function() ---#include "src/zy-neo/builtins/mod_menu/init.lua" -end) - local function load_lua(src, ...) if (src:sub(1, 4) == "\27ZLS") then src = lzss_decompress(src:sub(5)) end - return assert(load(src, ...)) + return load(src, ...) end -- Zorya's handler thread. @@ -77,23 +82,23 @@ th_a(function() local er xpcall(function() local zy = krequire("zorya") - zy.add_mod_search(function(mod) - if (builtins[mod]) then - return builtins[mod] - end - end) zy.add_mod_search(function(mod) if (bfs.exists(".zy2/mods/"..mod..".zy2m")) then - return assert(load_lua(bfs.getfile(".zy2/mods/"..mod..".zy2m"), "=.zy2/mods/"..mod..".zy2m")()) + return load_lua(bfs.getfile(".zy2/mods/"..mod..".zy2m"), "=.zy2/mods/"..mod..".zy2m")() elseif (bfs.exists(".zy2/mods/"..mod.."/init.zy2m")) then return load_lua(bfs.getfile(".zy2/mods/"..mod.."/init.zy2m"), "=.zy2/mods/"..mod.."/init.zy2m")() end end) + sys.add_search(function(mod) + if (builtins[mod]) then + return builtins[mod] + end + end) sys.add_search(function(mod) if (bfs.exists(".zy2/lib/"..mod..".zy2l")) then - return load_lua(bfs.getfile(".zy2/lib/"..mod.."..zy2l"), "=.zy2/lib/"..mod.."..zy2l")() + return load_lua(bfs.getfile(".zy2/lib/"..mod..".zy2l"), "=.zy2/lib/"..mod..".zy2l") elseif (bfs.exists(".zy2/lib/"..mod.."/init..zy2l")) then - return load_lua(bfs.getfile(".zy2/lib/"..mod.."/init..zy2l"), "=.zy2/lib/"..mod.."/init..zy2l")() + return load_lua(bfs.getfile(".zy2/lib/"..mod.."/init.zy2l"), "=.zy2/lib/"..mod.."/init.zy2l") end end) local zycfg = bfs.getfile(".zy2/cfg.lua") diff --git a/utils/mkluastring.lua b/utils/mkluastring.lua index 5deaf19..308d4d8 100644 --- a/utils/mkluastring.lua +++ b/utils/mkluastring.lua @@ -17,19 +17,20 @@ for i=1, #f do end end io.stdout:write("\"\n")]] +local rep = { + ["\0"] = "\\0", + ["\\"] = "\\\\", + ["\""] = "\\\"", + ["\n"] = "\\n", + ["\r"] = "\\r", + ["\t"] = "\\t", + [" "] = "\x20" +} local function mkstr(d) local dat = "\"" for i=1, #f do - if (d:byte(i) == 0) then - dat = dat .. "\0" - elseif (d:sub(i,i) == "\\") then - dat = dat .. ("\\\\") - elseif (d:sub(i,i) == "\"") then - dat = dat .. ("\\\"") - elseif (d:sub(i,i) == "\n") then - dat = dat .. ("\\n") - elseif (d:sub(i,i) == "\r") then - dat = dat .. ("\\r") + if (rep[d:sub(i, i)]) then + dat = dat .. rep[d:sub(i, i)] else dat = dat .. (d:sub(i,i)) end diff --git a/utils/selfextract.lua b/utils/selfextract.lua index 10150d2..9657877 100644 --- a/utils/selfextract.lua +++ b/utils/selfextract.lua @@ -41,7 +41,7 @@ function lzss_decompress(input) return table.concat(output) end -print("Decompressing CPIO...") +--print("Decompressing CPIO...") local code = lzss_decompress(@[{io.stdin:read("*a")}]) local dat = code local tbl = {} diff --git a/utils/ser.lua b/utils/ser.lua index b993094..3d541cc 100644 --- a/utils/ser.lua +++ b/utils/ser.lua @@ -41,7 +41,7 @@ local characters = { } local computer = computer or require("computer") local fsaddr = args[1] or computer.getBootAddress() -print(fsaddr) +--print(fsaddr) local component = component or require("component") local proxy, list = component.proxy, component.list local gpu = proxy(list("gpu")()) @@ -87,6 +87,7 @@ function setBar(pos) gpu.fill(8, (h/2)+1, w-16, 1, " ") gpu.setBackground(2, true) gpu.fill(8, (h/2)+1, ((w-16)/100)*pos, 1, " ") + computer.pullSignal(0) end function writeFile(fs, path, data) @@ -146,6 +147,13 @@ eeprom.setData(fs.address) eeprom.setLabel("Zorya NEO BIOS v2.0") setBar(100) setStatus("Rebooting in 5 seconds...") +if not fs.exists(".zy2/cfg.lua") then + writeFile(fs, ".zy2/cfg.lua", string.format([[local menu = loadmod("menu_classic") +menu.add("OpenOS on %s", function() + return loadmod("loader_openos")("%s") +end) +menu.draw()]], fsaddr:sub(1, 3), fsaddr)) +end computer = computer or require("computer") local stime = computer.uptime() while true do diff --git a/utils/unzlua.lua b/utils/unzlua.lua new file mode 100644 index 0000000..af01132 --- /dev/null +++ b/utils/unzlua.lua @@ -0,0 +1,119 @@ +local f = io.stdin:read("*a") +if (f:sub(1, 4) ~= "\27ZLS") then io.stderr:write("Not a zlua script!\n") os.exit(1) end + +--[[---------------------------------------------------------------------------- + LZSS - encoder / decoder + This is free and unencumbered software released into the public domain. + Anyone is free to copy, modify, publish, use, compile, sell, or + distribute this software, either in source code form or as a compiled + binary, for any purpose, commercial or non-commercial, and by any + means. + In jurisdictions that recognize copyright laws, the author or authors + of this software dedicate any and all copyright interest in the + software to the public domain. We make this dedication for the benefit + of the public at large and to the detriment of our heirs and + successors. We intend this dedication to be an overt act of + relinquishment in perpetuity of all present and future rights to this + software under copyright law. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + For more information, please refer to +--]]---------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +local M = {} +local string, table = string, table + +-------------------------------------------------------------------------------- +local POS_BITS = 12 +local LEN_BITS = 16 - POS_BITS +local POS_SIZE = 1 << POS_BITS +local LEN_SIZE = 1 << LEN_BITS +local LEN_MIN = 3 + +-------------------------------------------------------------------------------- +function M.compress(input) + local offset, output = 1, {} + local window = '' + + local function search() + for i = LEN_SIZE + LEN_MIN - 1, LEN_MIN, -1 do + local str = string.sub(input, offset, offset + i - 1) + local pos = string.find(window, str, 1, true) + if pos then + return pos, str + end + end + end + + while offset <= #input do + local flags, buffer = 0, {} + + for i = 0, 7 do + if offset <= #input then + local pos, str = search() + if pos and #str >= LEN_MIN then + local tmp = ((pos - 1) << LEN_BITS) | (#str - LEN_MIN) + buffer[#buffer + 1] = string.pack('>I2', tmp) + else + flags = flags | (1 << i) + str = string.sub(input, offset, offset) + buffer[#buffer + 1] = str + end + window = string.sub(window .. str, -POS_SIZE) + offset = offset + #str + else + break + end + end + + if #buffer > 0 then + output[#output + 1] = string.char(flags) + output[#output + 1] = table.concat(buffer) + end + end + + return table.concat(output) +end + +-------------------------------------------------------------------------------- +function M.decompress(input) + local offset, output = 1, {} + local window = '' + + while offset <= #input do + local flags = string.byte(input, offset) + offset = offset + 1 + + for i = 1, 8 do + local str = nil + if (flags & 1) ~= 0 then + if offset <= #input then + str = string.sub(input, offset, offset) + offset = offset + 1 + end + else + if offset + 1 <= #input then + local tmp = string.unpack('>I2', input, offset) + offset = offset + 2 + local pos = (tmp >> LEN_BITS) + 1 + local len = (tmp & (LEN_SIZE - 1)) + LEN_MIN + str = string.sub(window, pos, pos + len - 1) + end + end + flags = flags >> 1 + if str then + output[#output + 1] = str + window = string.sub(window .. str, -POS_SIZE) + end + end + end + + return table.concat(output) +end + +io.stdout:write(M.decompress(f:sub(5))) \ No newline at end of file