diff --git a/.buildactions/00_setup.lua b/.buildactions/00_setup.lua new file mode 100644 index 0000000..09ff1af --- /dev/null +++ b/.buildactions/00_setup.lua @@ -0,0 +1,2 @@ +os.execute("mkdir -p build") +os.execute("rm -rf build/*") \ No newline at end of file diff --git a/.buildactions/01_velx.lua b/.buildactions/01_velx.lua new file mode 100644 index 0000000..30a2eeb --- /dev/null +++ b/.buildactions/01_velx.lua @@ -0,0 +1,211 @@ +-- VELX builder + +--[[---------------------------------------------------------------------------- + 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 + + +local function struct(tbl) + local pat = tbl.endian or "=" + local args = {} + for i=1, #tbl do + local a, b = pairs(tbl[i]) + local k, v = a(b) + args[i] = k + pat = pat .. v + end + return setmetatable({}, {__call=function(_, arg) + --checkArg(1, arg, "string", "table") + if (type(arg) == "string") then + local sval = {string.unpack(pat, arg)} + local rtn = {} + for i=1, #args do + rtn[args[i]] = sval[i] + end + return rtn, sval[#sval] + elseif (type(arg) == "table") then + local sval = {} + for i=1, #args do + sval[i] = arg[args[i]] + end + return string.pack(pat, unpack(sval)) + end + end, __len=function() + return string.packsize(pat) + end}) +end + + +local velx_spec = struct { + endian = "<", + {magic="c5"}, + {fver="B"}, + {compression="B"}, + {lver="B"}, + {os="B"}, + {arctype="c4"}, + {psize="I3"}, + {lsize="I3"}, + {ssize="I3"}, + {rsize="I4"} +} + +local function velx_multistep(path, arcpath, args, steps) + local shell_args = "" + for k, v in pairs(args) do + shell_args = shell_args .. k .. "=\"".. v .."\" " + end + steps.precomp() + local h = io.popen(shell_args.."luacomp "..path, "r") + local prog = h:read("*a") + h:close() + prog = steps.postcomp(prog) + steps.prearc() + local arc = "" + if arcpath then + h = io.popen("find "..arcpath.." -depth | tsar -o", "r") + arc = h:read("*a") + h:close() + steps.postarc() + end + if (not args.noz) then + steps.prez() + prog = M.compress(prog) + steps.postz() + end + local header = velx_spec({ + magic = "\27VelX", + compression = (args.noz and 0) or 1, + lver = 0x53, + fver = 1, + os = 0x7F, + psize = #prog, + lsize=0, + ssize=0, + rsize=#arc, + arctype=(arcpath and "tsar") or "" + }) + return header .. prog .. arc +end + +local function velx(path, arcpath, args) + return velx_multistep(path, arcpath, args, { + precomp = function()end, + postcomp = function(prog) return prog end, + prearc = function()end, + postarc = function()end, + prez = function()end, + postz = function()end, + }) +end \ No newline at end of file diff --git a/.buildactions/11_kernel.lua b/.buildactions/11_kernel.lua new file mode 100644 index 0000000..a10e27a --- /dev/null +++ b/.buildactions/11_kernel.lua @@ -0,0 +1,50 @@ +local TSUKI_RELEASE = "0.0.1" +local tz = os.date("%z") +tz = tz:sub(1, 3)..":"..tz:sub(4) +local TSUKI_VERSION = "Lua 5.3 "..os.date("%Y-%m-%dT%H:%M:%S")..tz +local TSUKI_TARGET = os.getenv("TSUKI_TARGET") or "OC" + +function actions.kernel(dbg) + os.execute("mkdir -p build/kernel") + print("Compiling kernel...") + local h = io.open("build/kernel/tkrnl.velx", "wb") + h:write(velx_multistep("ksrc/init.lua", ".doc", { + TSUKI_RELEASE = TSUKI_RELEASE, + TSUKI_VERSION = TSUKI_VERSION, + TSUKI_TARGET = TSUKI_TARGET, + PRINT_DMESG_LEVEL = ((dbg and 0) or 1) + }, { + precomp = function() + print("Compiling kernel...") + end, + postcomp = function(krnl) + os.execute("mkdir .doc") + local h = io.open("build/kernel/debug.lua", "w") + h:write(krnl) + h:close() + print("Generating docs and stripping comments...") + h = io.popen("lua utils/gendocs.lua .doc 2>.ktmp", "w") + h:write(krnl) + h:close() + h = io.open(".ktmp", "rb") + local data = h:read("*a") + h:close() + os.execute("rm -rf .ktmp") + return data + end, + prearc = function() + print("Storing docs...") + end, + postarc = function() + os.execute("rm -rf .doc") + end, + prez = function() + print("Compressing kernel...") + end, + postz = function() + print("Writing kernel out...") + end + })) +end + +actions[#actions+1] = "kernel" \ No newline at end of file diff --git a/.buildactions/20_crescent.lua b/.buildactions/20_crescent.lua new file mode 100644 index 0000000..8fd7b14 --- /dev/null +++ b/.buildactions/20_crescent.lua @@ -0,0 +1,7 @@ +function actions.crescent() + os.execute("mkdir -p build/crescent") + os.execute("cd extras; lua ../utils/mkvelx.lua crescent/init.lua ../build/crescent/boot.velx") + os.execute("cp extras/crescent/bootvelxloader.lua build/crescent/init.lua") +end + +actions[#actions+1] = "crescent" \ No newline at end of file diff --git a/.buildactions/30_velxboot.lua b/.buildactions/30_velxboot.lua new file mode 100644 index 0000000..57ada86 --- /dev/null +++ b/.buildactions/30_velxboot.lua @@ -0,0 +1,7 @@ +function actions.velxboot() + os.execute("mkdir -p build/velxboot") + os.execute("cd extras; luacomp velxboot/init.lua -O ../build/velxboot/bios.lua") + os.execute("cd extras; luacomp velxboot/flashvelxboot.lua -O ../build/velxboot/flashvelxboot.lua") +end + +actions[#actions+1] = "velxboot" \ No newline at end of file diff --git a/.buildactions/40_coreutils.lua b/.buildactions/40_coreutils.lua new file mode 100644 index 0000000..b64340a --- /dev/null +++ b/.buildactions/40_coreutils.lua @@ -0,0 +1,37 @@ +do + --local coreutils = {} + --local function add_coreutil(name, outfolder, args) + -- args = args or {} + -- if not os.execute("[[ -d build/coreutils/"..outfolder.." ]]") then + -- os.execute("mkdir -p build/coreutils/"..outfolder) + -- end + -- actions["coreutil_"..name] = function() + -- local data = velx("coreutils/"..name..".lua", nil, args) + -- local h = io.open("build/coreutils/"..outfolder.."/"..name..".velx", "w") + -- h:write(data) + -- h:close() + -- end + -- coreutils[#coreutils+1] = name + --end + + --add_coreutil("init", "sbin") + --add_coreutil("shutdown", "sbin") + --add_coreutil("sh", "sbin") + --add_coreutil("uname", "sbin") + + --function actions.coreutils() + -- for i=1, #coreutils do + -- actions["coreutil_"..coreutils[i]]() + -- end + --end + local version = "0.1" + function actions.coreutils() + print("Building coreutils...") + os.execute("mkdir -p build/coreutils") + local sks = io.open("build/coreutils/sks.velx", "w") + sks:write(velx("coreutils/multicall.lua", false, { + SKS_COREUTILS_VERSION = version + })) + end + actions[#actions+1] = "coreutils" +end \ No newline at end of file diff --git a/.buildactions/fe_debug.lua b/.buildactions/fe_debug.lua new file mode 100644 index 0000000..481c71e --- /dev/null +++ b/.buildactions/fe_debug.lua @@ -0,0 +1,5 @@ +function actions.debug() + for i=1, #actions do + actions[actions[i]](true) + end +end \ No newline at end of file diff --git a/.buildactions/ff_clean.lua b/.buildactions/ff_clean.lua new file mode 100644 index 0000000..6cf7ace --- /dev/null +++ b/.buildactions/ff_clean.lua @@ -0,0 +1,5 @@ +function actions.clean() + print("Cleaning up...") + --os.execute("rm -rf .docs") + --os.execute("rm -rf .ktmp") +end \ No newline at end of file diff --git a/build.lua b/build.lua index c089ff7..d527266 100644 --- a/build.lua +++ b/build.lua @@ -1,232 +1,21 @@ -os.execute("mkdir -p build") -os.execute("rm -rf build/*") - ---[[---------------------------------------------------------------------------- - 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 - - -local function struct(tbl) - local pat = tbl.endian or "=" - local args = {} - for i=1, #tbl do - local a, b = pairs(tbl[i]) - local k, v = a(b) - args[i] = k - pat = pat .. v - end - return setmetatable({}, {__call=function(_, arg) - --checkArg(1, arg, "string", "table") - if (type(arg) == "string") then - local sval = {string.unpack(pat, arg)} - local rtn = {} - for i=1, #args do - rtn[args[i]] = sval[i] - end - return rtn, sval[#sval] - elseif (type(arg) == "table") then - local sval = {} - for i=1, #args do - sval[i] = arg[args[i]] - end - return string.pack(pat, unpack(sval)) - end - end, __len=function() - return string.packsize(pat) - end}) -end - - -local velx_spec = struct { - endian = "<", - {magic="c5"}, - {fver="B"}, - {compression="B"}, - {lver="B"}, - {os="B"}, - {arctype="c4"}, - {psize="I3"}, - {lsize="I3"}, - {ssize="I3"}, - {rsize="I4"} -} local actions = {} -function actions.kernel() - -- This builds Tsuki into a VELX executable. - os.execute("mkdir -p build/kernel") - print("Compiling kernel...") - local h = io.popen("luacomp ksrc/init.lua", "r") - local krnl = h:read("*a") - h:close() - os.execute("luacomp ksrc/init.lua -O build/kernel/debug.lua 2>/dev/null") - print("Generating docs and stripping comments...") - os.execute("mkdir .docs") - h = io.popen("lua utils/gendocs.lua .docs 2>.ktmp", "w") - h:write(krnl) - h:close() - h = io.popen("find .docs -depth | tsar -o", "r") - local arc = h:read("*a") - h:close() - h = io.open(".ktmp", "rb") - local data = h:read("*a") - h:close() - print("Compressing kernel...") - data = M.compress(data) - print("Writing out tkrnl.velx...") - local h = io.open("build/kernel/tkrnl.velx", "wb") - local header = velx_spec({ - magic = "\27VelX", - compression = 1, - lver = 0x53, - fver = 1, - os = 0x7F, - psize = #data, - lsize=0, - ssize=0, - rsize=#arc, - arctype="tsar" - }) - h:write(header) - h:write(data) - h:write(arc) - h:close() -end +@[[local h = io.popen("ls .buildactions", "r") +for line in h:lines() do]] +--#include @[{".buildactions/"..line}] +@[[end]] -function actions.crescent() - os.execute("mkdir -p build/crescent") - os.execute("cd extras; lua ../utils/mkvelx.lua crescent/init.lua ../build/crescent/boot.velx") - os.execute("cp extras/crescent/bootvelxloader.lua build/crescent/init.lua") -end - -function actions.velxboot() - os.execute("mkdir -p build/velxboot") - os.execute("cd extras; luacomp velxboot/init.lua -O ../build/velxboot/bios.lua") - os.execute("cd extras; luacomp velxboot/flashvelxboot.lua -O ../build/velxboot/flashvelxboot.lua") -end - -function actions.clean() - print("Cleaning up...") - os.execute("rm -rf .docs") - os.execute("rm -rf .ktmp") -end - -function actions.all() - actions.kernel() +--[[function actions.debug() + actions.kernel(true) actions.crescent() actions.velxboot() actions.clean() +end]] + +function actions.all() + for i=1, #actions do + actions[actions[i]]() + end end if not arg[1] then diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..bca1ec4 --- /dev/null +++ b/build.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env sh +luacomp build.lua 2>/dev/null | lua - "$@" \ No newline at end of file diff --git a/coreutils/init.lua b/coreutils/init.lua new file mode 100644 index 0000000..58e02c6 --- /dev/null +++ b/coreutils/init.lua @@ -0,0 +1,57 @@ +local kargs = ... +local kio = kernel.kmode_run("return kio") +local tty = kernel.kmode_run("return tty") +local exec = kernel.kmode_run("return exec") +local thd = require("thread") +local fs = require("filesystem") +local security = require("security") + +kernel.dmesg(kernel.loglevel.INFO, "ksysinit started") +local function run_hooks(hook, args) + local hooks = fs.list("/etc/ksysinit/"..hook) + for i=1, #hooks do + local path = fs.resolve("/etc/ksysinit/"..hook.."/"..hooks[i]) + local stat = fs.stat(path) + if (stat.mode == "file" and stat.uid == 0 and stat.gid == 0 and mode & 2 == 0) then + local f, err = loadfile(path) + if not f then + kernel.dmesg(kernel.loglevel.WARNING, "Failed to load startup hook `"..hooks[i].."': "..err) + goto continue + end + xpcall(function() + f(table.unpack(args)) + end, function(err) + kernel.dmesg(kernel.loglevel.ERROR, "Error in startup hook `"..hooks[i].."': "..debug.traceback(err)) + end) + end + ::continue:: + end +end + +kernel.dmesg(kernel.loglevel.INFO, "running startup hooks") +run_hooks("startup", {}) + +kernel.dmesg(kernel.loglevel.INFO, "starting ttys") +for i=1, tonumber(kargs["tty.count"]) or 1 do + local pty = tty.get(i) + exec.loadfile("/sbin/login.velx", true, { + uid = 0, + gid = 0, + tty = pty + }) +end + +-- Now we wait for shutdown or other things +while true do + local siginfo = kernel.sig_pull() + if siginfo.type == "shutdown" then + run_hooks("shutdown", {}) + kernel.kmode_run([[computer.shutdown()]]) + elseif siginfo.type == "reboot" then + run_hooks("shutdown", {}) + kernel.kmode_run([[computer.shutdown(true)]]) + elseif siginfo.type == "ipc" and siginfo.message[1] == "svcrun" and security.hasperm("svc", siginfo.uid, siginfo.gid) then + table.pack(table.unpack(siginfo.message, 4)) + run_hooks("services/"..siginfo.message[2].."/"..siginfo.message[3], table.pack(table.unpack(siginfo.message, 4))) + end +end \ No newline at end of file diff --git a/coreutils/multicall.lua b/coreutils/multicall.lua new file mode 100644 index 0000000..17a1702 --- /dev/null +++ b/coreutils/multicall.lua @@ -0,0 +1,45 @@ +local calls = {} + +local function version_info() + print("SKS Coreutils version $[{SKS_COREUTILS_VERSION}]") +end + +@[[function add_util(name)]] +calls["@[{name}]"] = function(...) +--#include @[{"coreutils/"..name..".lua"}] +end +@[[end]] + +@[[ +add_util("init") +add_util("reboot") +add_util("sh") +add_util("shutdown") +add_util("svc-ctl") +add_util("uname") +]] + +calls.sks = function(prog, ...) + if not prog then + version_info() + print("SKS Coreutils multicall binary.\n") + print("Calls:") + local t = {} + for k, v in pairs(calls) do + t[#t+1] = k + end + print(table.concat(t, " ")) + return 0 + end + return calls[prog](...) +end + +setmetatable(calls, {__index=function(_, i) + return function() + io.stderr:write("call "..i.." not found. run `sks' without args for list of calls.\n") + end +end}) + +local call = os.getenv("_"):match("/(.+)%.[^%.]+") + +return calls[call](...) \ No newline at end of file diff --git a/coreutils/reboot.lua b/coreutils/reboot.lua new file mode 100644 index 0000000..c7fa770 --- /dev/null +++ b/coreutils/reboot.lua @@ -0,0 +1,5 @@ +if (kernel) then + kernel.sig_push { + sigtype = "shutdown" + } +end \ No newline at end of file diff --git a/coreutils/sh.lua b/coreutils/sh.lua new file mode 100644 index 0000000..e69de29 diff --git a/coreutils/shutdown.lua b/coreutils/shutdown.lua new file mode 100644 index 0000000..687b90a --- /dev/null +++ b/coreutils/shutdown.lua @@ -0,0 +1,10 @@ +if (kernel) then + if (os.getenv("_"):match("reboot.velx")) then + kernel.sig_push {sigtype = "reboot"} + else + kernel.sig_push {sigtype = "shutdown"} + end +else + io.stderr:write("must be run as root\n") + os.exit(-1) +end \ No newline at end of file diff --git a/coreutils/svc-ctl.lua b/coreutils/svc-ctl.lua new file mode 100644 index 0000000..8b2bd24 --- /dev/null +++ b/coreutils/svc-ctl.lua @@ -0,0 +1,6 @@ +if (kernel) then +--#include "coreutils/svc-ctl/init.lua" +else + io.stderr:write("must be run as root\n") + os.exit(-1) +end \ No newline at end of file diff --git a/coreutils/svc-ctl/init.lua b/coreutils/svc-ctl/init.lua new file mode 100644 index 0000000..7d92061 --- /dev/null +++ b/coreutils/svc-ctl/init.lua @@ -0,0 +1,26 @@ +local args = {...} +local thread = require("thread") +local ipc = require("ipc") +local fs = require("filesystem") + +if not args[1] then + local svcs = {} + for f in fs.list("/etc/ksysinit/services") do + svcs[#svcs+1] = f + end + print(table.concat(svcs, ", ")) + return 0 +elseif args[1] and not args[2] then + local svcs = {} + for f in fs.list("/etc/ksysinit/services/"..args[1]) do + svcs[#svcs+1] = f + end + print(table.concat(svcs, ", ")) + return 0 +elseif not fs.exists("/etc/ksysinit/services/"..args[1].."/"..args[2]) then + io.stderr:write("hook `"..args[2].."' not found for `"..args[1].."'\n") + return 1 +else + local proc = thread.get("/sbin/init") + ipc.send(proc, "svcrun", args[1], args[2]) +end diff --git a/coreutils/uname.lua b/coreutils/uname.lua new file mode 100644 index 0000000..64392b1 --- /dev/null +++ b/coreutils/uname.lua @@ -0,0 +1,58 @@ +local sharg = require("sh_arg") +local args = sharg({ + name = "uname", + desc = [[Print certain system information. With no OPTION, same as -s]], + options = { + {"kernel-name", "s", "print the kernel name"}, + {"nodename", "n", "print the network node hostname"}, + {"kernel-release", "r", "print the kernel release"}, + {"kernel-version", "v", "print the kernel release"}, + {"machine", "m", "print the machine hardware name"}, + {"operating-system", "o", "print the operating system"}, + {"version", false, "output version information and exit"} + }, +}, ...) + +if (args.version) then + version_info() + return 0 +end + +if (args.a or args.all) then + args.s = true + args.r = true + args.v = true + args.n = true + args.m = true + args.o = true +end + +if table.select("#", ...) == 0 then + args.s = true +end + +if (args.s) then + io.stdout:write(_KINFO.name.." ") +end + +if (args.n) then + io.stdout:write(os.getenv("HOSTNAME").." ") +end + +if (args.r) then + io.stdout:write(_KINFO.release.." ") +end + +if (args.v) then + io.stdout:write(_KINFO.version.." ") +end + +if (args.m) then + io.stdout:write(_KINFO.machine.." ") +end + +if (args.o) then + io.stdout:write("SKS/Tsuki ") +end + +io.stdout:write("\n") \ No newline at end of file diff --git a/debug.lua b/debug.lua index 9a7d096..c8dbb0d 100644 --- a/debug.lua +++ b/debug.lua @@ -1,15 +1,140 @@ +os.execute("mkdir -p build") +os.execute("rm -rf build/*") -function struct(tbl) +local actions = {} + + + + +-- VELX builder + +--[[---------------------------------------------------------------------------- + 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 + + +local function struct(tbl) local pat = tbl.endian or "=" local args = {} - for i=1, do + for i=1, #tbl do local a, b = pairs(tbl[i]) local k, v = a(b) args[i] = k pat = pat .. v end return setmetatable({}, {__call=function(_, arg) - checkArg(1, arg, "string", "table") + --checkArg(1, arg, "string", "table") if (type(arg) == "string") then local sval = {string.unpack(pat, arg)} local rtn = {} @@ -29,57 +154,6 @@ function struct(tbl) end}) end -function string.trim(self) - return self:gsub("^%s+", ""):gsub("%s+$", "") -end - -function string.explode(self, pat) - local t, ll - t={} - ll=0 - if(#p == 1) then - return {p} - end - while true do - l = string.find(self, pat, ll, true) -- find the next d in the string - if l ~= nil then -- if "not not" found then.. - table.insert(t, string.sub(self,ll,l-1)) -- Save it in our array. - ll = l + 1 -- save just after where we found it for searching next time. - else - table.insert(t, string.sub(self,ll)) -- Save what's left in our array. - break -- Break at end, as it should be, according to the lua manual. - end - end - return t -end - - - ----@module security Security -local security = {} - ----@func checkacl ----@arg permission string "The permission to check." ----@return boolean "True if the current process has this permission." -function security.checkacl(permission) - local perms = acl.get("group", thread.info().egid, {}) -end - ----@func getmode ----@return string "The current security mode." -function security.getmode() - -end - -function security.init() - klog("security", 1, "Security init started.") - -end - - - -local velx = (function() - local velx_spec = struct { endian = "<", @@ -88,237 +162,150 @@ local velx_spec = struct { {compression="B"}, {lver="B"}, {os="B"}, + {arctype="c4"}, {psize="I3"}, {lsize="I3"}, {ssize="I3"}, {rsize="I4"} } -local velx = {} - -local exec = {} - -function velx.identify(path) - local h = io.open(path, "rb") - local header = velx_spec(h:read(#velx_spec)) +local function velx_multistep(path, arcpath, args, steps) + local shell_args = "" + for k, v in pairs(args) do + shell_args = shell_args .. k .. "=".. v .." " + end + steps.precomp() + local h = io.popen(shell_args.."luacomp "..path, "r") + local prog = h:read("*a") h:close() - return header.magic == "\27VelX" -end - -function velx.load(path) - -end - -function velx.verify(path) - local h = io.open(path, "rb") - local header = velx_spec(h:read(#velx_spec)) - local code = h:read(header.psize) - h:seek("cur", lsize) - local sig = h:read(header.ssize) + prog = steps.postcomp(prog) + steps.prearc() + h = io.popen("find .docs -depth | tsar -o", "r") + local arc = h:read("*a") h:close() - return security.verify(code, sig) + steps.postarc() + if (not args.noz) then + steps.prez() + prog = M.compress(prog) + steps.postz() + end + local header = velx_spec({ + magic = "\27VelX", + compression = (args.noz and 0 or) 1, + lver = 0x53, + fver = 1, + os = 0x7F, + psize = #prog, + lsize=0, + ssize=0, + rsize=#arc, + arctype="tsar" + }) + return header .. prog .. arc end -function exec:link() - self.file:seek("set", #velx_spec+self.header.psize) - local linkinfo = self.file:read(self.header.lsize) - local linker = {} - local pos = 1 - while true do - local size = string.unpack(".ktmp", "w") + h:write(krnl) + h:close() + h = io.open(".ktmp", "rb") + local data = h:read("*a") + h:close() + os.execute("rm -rf .ktmp") + return data + end, + prearc = function() + print("Storing docs...") + end, + postarc = function() + os.execute("rm -rf .docs") + end, + precomp = function() + print("Compressing kernel...") + end, + postcomp = function() + print("Writing kernel out...") end - linker[#linker+1] = {name, library} - end - local linkscript = "" - for i=1, #linker do - linkscript = linkscript .. "local " .. linker[i][1] .. "=require(\"" .. linker[i][2] .. "\")\n" - end - self.code = linkscript .. self.code - return true + })) end -function exec:load() - self.file:seek("set", #velx_spec) - local code = self.file:read(self.header.psize) - if (self.header.compression == 0) then - self.code = code - elseif (self.header.compression == 1) then - self.code = lzss.decompress(self.code) - else - return nil, "invalid compression method" - end - return true +actions[#actions+1] = "kernel" + +function actions.crescent() + os.execute("mkdir -p build/crescent") + os.execute("cd extras; lua ../utils/mkvelx.lua crescent/init.lua ../build/crescent/boot.velx") + os.execute("cp extras/crescent/bootvelxloader.lua build/crescent/init.lua") end -function exec:run(args, evar) - system.load(self.code, args, system.getglobalenv({_ARCHIVE=self.arc}), system.getevars(evar)) +actions[#actions+1] = "crescent" + +function actions.velxboot() + os.execute("mkdir -p build/velxboot") + os.execute("cd extras; luacomp velxboot/init.lua -O ../build/velxboot/bios.lua") + os.execute("cd extras; luacomp velxboot/flashvelxboot.lua -O ../build/velxboot/flashvelxboot.lua") end -end)() +actions[#actions+1] = "velxboot" -local zlua = (function() +function actions.clean() + print("Cleaning up...") + os.execute("rm -rf .docs") + os.execute("rm -rf .ktmp") +end -local zlua = {} -return {} -end) +--[[function actions.debug() + actions.kernel(true) + actions.crescent() + actions.velxboot() + actions.clean() +end]] --- Executable loading process: --- - Link --- - Load --- - Execute - -if () - -local fox = {} -do - -local struct_inode = struct { - endian = "<", - {mode="H"}, - {uid="H"}, - {fsize="I6"}, - {atime="I6"}, - {ctime="I6"}, - {mtime="I6"}, - {dtime="I6"}, - {gid="H"}, - {sec_count="I4"}, - {flags="I4"}, - {osval="I4"}, - {dbp0="I4"}, - {dbp1="I4"}, - {dbp2="I4"}, - {dbp3="I4"}, - {dbp4="I4"}, - {dbp5="I4"}, - {dbp6="I4"}, - {dbp7="I4"}, - {dbp8="I4"}, - {dbp9="I4"}, - {dbp10="I4"}, - {dbp11="I4"}, - {sibp="I4"}, - {dibp="I4"}, - {tibp="I4"}, - {gen="H"}, - {acl="I4"}, - {fragaddr="I4"}, - {osval2="c10"} -} - -local dirent = struct { - endian="<", - {inode="I4"}, - {name_size="H"}, - {etype="B"} -} - -local superblock = struct { - endian = "<", - {sig="H"}, - {ver_maj="H"}, - {ver_min="H"}, - {state="H"}, - {total_inodes="I4"}, - {total_blocks="I4"}, - {reserved_blocks="I4"}, - {total_unalloc_blocks="I4"}, - {total_unalloc_inodes="I4"}, - {total_unalloc_inodes="I4"}, -} - -local blkstr = {} - - function fox.proxy(blkdev) - -- Read the superblock +function actions.all() + for i=1, #actions do + actions[actions[i]]() end end -local tty = {} -do - local _tty = {} - function _tty:getgpu() - return self.gpu.address - end - - function _tty:getkb() - return self.kb.address - end - - function _tty:getscreen() - return self.screen.address - end +if not arg[1] then + arg[1] = "all" end ----@section biosfixes "BIOS fixes" +actions[arg[1]]() -local _biossupport = {} - - - - ----@page zorya_legacy "Zorya 1.x (Zorya Legacy)" ----@doc "Zorya 1.x puts a few things in the global space that need to be removed. These include:" ----@doc "- The OEFI library" ----@doc "- The Zorya library" ----@doc "" ----@doc "Note: This *should* also apply to any forks of Zorya Legacy." -_biossupport["zoryalegacy"] = { - quirks = function() - -zorya = nil - end, - info = function() - -return { - name = "Zorya", - version = {_ZVER//1, tonumber(tostring(_ZVER):match("%.(%d+)")), _ZPAT, string = _ZVER..".".._ZPAT}, - oefiver = oefi.getAPIVersion() -} - end, - detect = function() - -return _LOAD == "Zorya" - end, - name = "zoryalegacy" -} - - - ----@page zorya_neo "Zorya NEO (Zorya 2.0)" ----@doc "There's not much to be done for Zorya NEO as the included Zorya module starts Tsuki with a nice enviroment." -_biossupport["zoryaneo"] = { - quirks = function() - - - end, - info = function() - -return { - name = "Zorya NEO", - version = {_ZVER//1, tonumber(tostring(_ZVER):match("%.(%d+)")), _ZPAT, git = _ZGIT, string = _ZVSTR}, - loader = _ZLOADER -} - end, - detect = function() - -return _BIOS == "Zorya NEO" - end, - name = "zoryaneo" -} - - - - --- Mount the rootfs -vfs.mount() \ No newline at end of file +print("Build complete.") \ No newline at end of file diff --git a/ksrc/acl.lua b/ksrc/acl.lua index 92eec56..82985d7 100644 --- a/ksrc/acl.lua +++ b/ksrc/acl.lua @@ -2,15 +2,20 @@ local acl = {} do local acl = struct({ meta = "B", - id = "H", - permname = "B" + id = "H" }) local function acl_readstream(stream) + local a = acl(stream:read(#acl)) + local perm = stream:read(a.meta & 0x3f) + local + end + + function acl.read(stream, dperm, gid, uid) end - function acl.read(stream) + function _acl:get_effective_perm(id, group, perm) end end \ No newline at end of file diff --git a/ksrc/ads.lua b/ksrc/ads.lua new file mode 100644 index 0000000..70e8f0b --- /dev/null +++ b/ksrc/ads.lua @@ -0,0 +1,9 @@ +local ads = {} + +function ads.get(path) + +end + +function ads.list(path) + +end \ No newline at end of file diff --git a/ksrc/archives.lua b/ksrc/archives.lua new file mode 100644 index 0000000..c800a71 --- /dev/null +++ b/ksrc/archives.lua @@ -0,0 +1,10 @@ +local archives = {} +archives.tsar = (function() +--#include "ksrc/arcs/tsar/init.lua" +end)() + +function archive.parse(stream, atype) + if archives[atype] then + return archives[atype].read(stream) + end +end \ No newline at end of file diff --git a/ksrc/arcs/tsar/init.lua b/ksrc/arcs/tsar/init.lua index 3f0c841..49abc08 100644 --- a/ksrc/arcs/tsar/init.lua +++ b/ksrc/arcs/tsar/init.lua @@ -16,7 +16,7 @@ end local arc = {} -function arc:handle(path) +function arc:read(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)) @@ -55,12 +55,55 @@ function arc:meta(path) return nil, "file not found" end +function arc:stream(path) + for i=1, #self.tbl do + if (self.tbl[i].name == path) then + return kio.create_stream({dev=self.dev, start=self.tbl[i].pos, size=self.tbl[i].filesize, pos=1}, { + read = function(self, amt) + self.dev:seek("set", self.pos+self.start-1) + if (self.pos+amt-1 > self.size) then + amt = self.size-self.pos + end + local dat = self.dev:read(amt) + self.pos = self.pos + #dat + return dat + end, + seek = function(self, whence, amt) + self.pos = kio.calc_seek(whence, amt, self.size, self.pos) + return self.pos + end, + write = function(self) + return kio.get_error(kio.errno.UNSUPPORTED_OPERATION) + end, + close = function(self) + + end + }) + end + end +end + +function arc:trailer() + self.dev:seek("set", self.tbl.trailer.pos) + return self.dev:read(self.tbl.trailer.filesize) +end + function arc:close() self.close() end return { - read = function(read, seek, close) + read = function(dev) + local function read(a) + return dev:read(a) + end + local function seek(a) + return dev:seek("cur", a) + end + local function close() + return dev:close() + end + local start = seek(0) local tbl = {} local lname = "" while lname ~= "TRAILER!!!" do @@ -72,8 +115,10 @@ return { lname = et.name if lname ~= "TRAILER!!!" then tbl[#tbl+1] = et + else + tbl.trailer = et end end - return setmetatable({tbl = tbl, read = read, seek = seek, close = close}, {__index=arc}) + return setmetatable({tbl = tbl, read = read, seek = seek, close = close, dev=dev, start=true}, {__index=arc}) end } \ No newline at end of file diff --git a/ksrc/bios/unknown/detect.lua b/ksrc/bios/unknown/detect.lua new file mode 100644 index 0000000..2a92563 --- /dev/null +++ b/ksrc/bios/unknown/detect.lua @@ -0,0 +1 @@ +return true \ No newline at end of file diff --git a/ksrc/bios/unknown/docs.lua b/ksrc/bios/unknown/docs.lua new file mode 100644 index 0000000..2bd31d4 --- /dev/null +++ b/ksrc/bios/unknown/docs.lua @@ -0,0 +1,2 @@ +---@page unknown "Unknown" +---@doc "This is for if Tsuki doesn't know what BIOS is in use." diff --git a/ksrc/bios/unknown/info.lua b/ksrc/bios/unknown/info.lua new file mode 100644 index 0000000..4437c50 --- /dev/null +++ b/ksrc/bios/unknown/info.lua @@ -0,0 +1,4 @@ +return { + name = "Unknown", + version = {0, 0, 0, string="0.0.0"} +} \ No newline at end of file diff --git a/ksrc/bios/unknown/quirks.lua b/ksrc/bios/unknown/quirks.lua new file mode 100644 index 0000000..e69de29 diff --git a/ksrc/biosfixes.lua b/ksrc/biosfixes.lua index ec6db52..f74c1b5 100644 --- a/ksrc/biosfixes.lua +++ b/ksrc/biosfixes.lua @@ -1,5 +1,7 @@ ---@section biosfixes "BIOS fixes" +@[[do +local i=1]] local _biossupport = {} @[[function biosfix(bios)]] --#include @[{"ksrc/bios/"..bios.."/docs.lua"}] @@ -13,11 +15,16 @@ _biossupport["@[{bios}]"] = { detect = function() --#include @[{"ksrc/bios/"..bios.."/detect.lua"}] end, - name = "@[{bios}]" + name = "@[{bios}]", + id = @[{i}] } +_biossupport[@[{i}]] = "@[{bios}]" +@[[i=i+1]] @[[end]] @[[biosfix("zoryalegacy")]] @[[biosfix("zoryaneo")]] -@[[biosfix = nil]] \ No newline at end of file +@[[biosfix("unknown")]] +@[[biosfix = nil]] +@[[end]] \ No newline at end of file diff --git a/ksrc/blk/eeprom.lua b/ksrc/blk/eeprom.lua index e69de29..fe6f1b7 100644 --- a/ksrc/blk/eeprom.lua +++ b/ksrc/blk/eeprom.lua @@ -0,0 +1,5 @@ +local eeprom = {} + +function eeprom.proxy(addr) + +end \ No newline at end of file diff --git a/ksrc/blkdev.lua b/ksrc/blkdev.lua index e69de29..e35cdab 100644 --- a/ksrc/blkdev.lua +++ b/ksrc/blkdev.lua @@ -0,0 +1,4 @@ +--#include "ksrc/blk/eeprom.lua" +--#include "ksrc/blk/hdd.lua" +--#include "ksrc/blk/partition.lua" +--#include "ksrc/blk/promcard.lua" diff --git a/ksrc/exec.lua b/ksrc/exec.lua index 8ddeb63..20db066 100644 --- a/ksrc/exec.lua +++ b/ksrc/exec.lua @@ -7,7 +7,28 @@ local zlua = (function() --#include "ksrc/execs/zlua/init.lua" end) +local lua = (function() +--#include "ksrc/execs/lua/init.lua" +end) + -- Executable loading process: -- - Link -- - Load --- - Execute \ No newline at end of file +-- - Execute + +function exec.loadfile(path, env, runinfo) + local stat = vfs.stat(path) + if (stat & 0x400 > 0) then + runinfo.gid = stat.gid + end + if (stat & 0x800 > 0) then + runinfo.uid = stat.uid + end + if (velx.identify(path)) then + + elseif (zlua.identify(path)) then + + else -- Load Lua...if we can. + + end +end \ No newline at end of file diff --git a/ksrc/execs/lua/init.lua b/ksrc/execs/lua/init.lua new file mode 100644 index 0000000..e69de29 diff --git a/ksrc/execs/velx_spec/velxspec.lua b/ksrc/execs/velx_spec/velxspec.lua index 957fb45..fe17526 100644 --- a/ksrc/execs/velx_spec/velxspec.lua +++ b/ksrc/execs/velx_spec/velxspec.lua @@ -24,7 +24,11 @@ function velx.identify(path) end function velx.load(path) - + local h = io.open(path, "rb") + local header = velx_spec(h:read(#velx_spec)) + local code = h:read(header.psize) + h:seek("cur", lsize) + local sig = h:read(header.ssize) end function velx.verify(path) diff --git a/ksrc/fs/arcfs/init.lua b/ksrc/fs/arcfs/init.lua new file mode 100644 index 0000000..60257cd --- /dev/null +++ b/ksrc/fs/arcfs/init.lua @@ -0,0 +1 @@ +local afs = {} diff --git a/ksrc/fs/foxfs/ads.lua b/ksrc/fs/foxfs/ads.lua new file mode 100644 index 0000000..8e99bdf --- /dev/null +++ b/ksrc/fs/foxfs/ads.lua @@ -0,0 +1,21 @@ +function prox:getadses(path) + local inode = fox_getnode(self, path) + local adsl = fox_readdir(self, inode.ads) + return adsl +end + +function prox:makeads(path, stream) + +end + +function prox:getads(path, stream) + local inode = fox_getnode(self, path) + local adsl = fox_readdir(self, inode.ads) + for i=1, do + if (adsl[i].name == stream) then + local node = fox_getinode(self, adsl[i].inode) + return {node=node, pos=1, mode=mode, dev=self} + end + end + return nil, "not found" +end \ No newline at end of file diff --git a/ksrc/fs/foxfs/dir.lua b/ksrc/fs/foxfs/dir.lua index d84f359..a91c406 100644 --- a/ksrc/fs/foxfs/dir.lua +++ b/ksrc/fs/foxfs/dir.lua @@ -3,4 +3,12 @@ local dirent = struct { {inode="I4"}, {name_size="H"}, {etype="B"} -} \ No newline at end of file +} + +local function fox_readdir(self, inode) + +end + +function prox:list(path) + +end \ No newline at end of file diff --git a/ksrc/fs/foxfs/filehand.lua b/ksrc/fs/foxfs/filehand.lua new file mode 100644 index 0000000..aa408c5 --- /dev/null +++ b/ksrc/fs/foxfs/filehand.lua @@ -0,0 +1,21 @@ +function prox:open(path, mode) + local node = fox_getnode(self, path) + if not node then return nil, "file not found" end + return {node=node, pos=1, mode=mode, dev=self} +end + +function prox:read(hand, amt) + +end + +function prox:write(hand, data) + +end + +function prox:seek(hand, amt) + +end + +function prox:close(hand) + +end \ No newline at end of file diff --git a/ksrc/fs/foxfs/init.lua b/ksrc/fs/foxfs/init.lua index cd152f0..62cdab6 100644 --- a/ksrc/fs/foxfs/init.lua +++ b/ksrc/fs/foxfs/init.lua @@ -7,11 +7,16 @@ do local prox = {} - function fox.proxy(blkdev) + function fox.proxy(dev) -- Read the superblock + sb:seek("set", 1025) + local sb = superblock(dev:read(#superblock)) + local prox = { + super = sb + } end local function fox_getinode(prox, inode) - prox.dev:size() + end end \ No newline at end of file diff --git a/ksrc/fs/foxfs/inode.lua b/ksrc/fs/foxfs/inode.lua index 42bfad8..281ebd2 100644 --- a/ksrc/fs/foxfs/inode.lua +++ b/ksrc/fs/foxfs/inode.lua @@ -27,7 +27,7 @@ local struct_inode = struct { {dibp="I4"}, {tibp="I4"}, {gen="H"}, - {acl="I4"}, + {ads="I4"}, {fragaddr="I4"}, {osval2="c10"} } \ No newline at end of file diff --git a/ksrc/init.lua b/ksrc/init.lua index 1d89ff3..2c47a5f 100644 --- a/ksrc/init.lua +++ b/ksrc/init.lua @@ -1,5 +1,12 @@ +--#include "ksrc/kstrings.lua" +--#include "ksrc/kargs.lua" +--#include "ksrc/kio.lua" +--#include "ksrc/vfs.lua" --#include "ksrc/struct.lua" --#include "ksrc/string.lua" +--#include "ksrc/archives.lua" +--#include "ksrc/ads.lua" +--#include "ksrc/blkdev.lua" --#include "ksrc/acl.lua" --#include "ksrc/security.lua" --#include "ksrc/exec.lua" @@ -7,7 +14,25 @@ --#include "ksrc/tty.lua" --#include "ksrc/biosfixes.lua" --#include "ksrc/buffer.lua" ---#include "ksrc/kio.lua" +--#include "ksrc/threads.lua" +--#include "ksrc/net.lua" --- Mount the rootfs -vfs.mount() \ No newline at end of file +kio.dmesg(1, "Starting Tsuki kernel.") +kio.init() + +-- Mount the initramfs, if there is one. +if (kargs.iramfs or kargs.root == "$") then + vfs.mount("/", arcfs.proxy(_ARCHIVE)) +end + +-- Eventually... +do + local pty = tty.get(0) + kio.dmesg(1, "Passing off to init.") + exec.startfile(kargs.init or "/bin/init.velx", true, { + uid = 0, + gid = 0, + tty = pty, + args = {kargs} + }) +end \ No newline at end of file diff --git a/ksrc/kargs.lua b/ksrc/kargs.lua new file mode 100644 index 0000000..e69de29 diff --git a/ksrc/kio.lua b/ksrc/kio.lua index aa35c3b..44987b6 100644 --- a/ksrc/kio.lua +++ b/ksrc/kio.lua @@ -1,8 +1,299 @@ ----@module kio "Kernel I/O" -local kio = {} +@[[if not svar.get("PRINT_DMESG_LEVEL") then + svar.set("PRINT_DMESG_LEVEL", "1") +end]] +---@module kio "Kernel I/O" +kio = {} + +local _stream = {} +function _stream:read(amt) + local buf = "" + local lc = "" + if (amt == "*l") then -- Our line ending is \n + repeat + lc = self.proto.read(self.udat, 1) + if (lc ~= "\n") then + buf = buf .. (lc or "") + end + until not lc or lc == "" or lc == "\n" + return buf + --elseif (amt == "*n") then + + elseif (amt == "*a") then + local pos = self:seek("cur", 0) + local send = self:seek("end", 0) + self:seek("set", pos) + amt = send - pos + end + return self.proto.read(self.udat, amt) +end + +function _stream:write(data) + return self.proto.write(self.udat, data) +end + +function _stream:seek(whence, amt) + if not amt then + amt = whence or 0 + whence = "cur" + end + return self.proto.seek(self.udat, whence, amt) +end + +function _stream:eof() + local pos = self:seek("cur", 0) + local send = self:seek("end", 0) + self:seek("set", pos) + return pos == send +end + +function _stream:close() + return self.proto.close(self.udat) +end + +function _stream:size() + local pos = self:seek("cur", 0) + local send = self:seek("end", 0) + self:seek("set", pos) + return send +end + +function kio.create_stream(udat, proto) + return setmetatable({udat=udat, proto=proto}, {__index=_stream}) +end + +@[[local kio_errc = 0 +function kio_err(name, rtn)]] +kio.errno["@[{name}]"] = @[{kio_errc}] +kio_errors[@[{kio_errc}]] = "@[{rtn}]" +@[[kio_errc = kio_errc + 1 +end]] + +kio.errno = {} +local kio_errors = {} +@[[ +kio_err("FILE_NOT_FOUND", "not found") +kio_err("FILE_DIRECTORY", "file is a directory") +kio_err("DEV_TIMEOUT", "device timeout") +kio_err("IO_ERROR", "generic i/o error") +kio_err("UNSUPPORTED_OPERATION", "unsupported operation") +kio_err("NOT_ALLOWED", "not allowed") +kio_err("TOO_MANY_SYMLINKS", "too many symlinks") +kio_err("DEV_FULL", "device is full") +kio_err("DEV_READ_ONLY", "device is read only") +]] + +kio.geterror = function(e) + return nil, kio_errors[e] or "generic error" +end + +function kio.invoke(path, method, ...) + local dev, rpath = vfs.resolve(path) + return dev.dev[method](dev.dev, rpath, ...) +end + +function kio.has_ads(path) + +end + +function kio.ads_exists(path, ads) + +end + +function kio.has_acl(path) + +end + +---@func calc_seek +---@arg whence string "Like io.seek's whence." +---@arg amt integer "The amount to seek." +---@arg size integer "The size of the stream." +---@arg pos integer "The current position." +---@return integer "The new position" +---@desc "This function calculates the new position for seeking." +function kio.calc_seek(whence, amt, size, pos) + if (whence == "cur") then + pos = pos + amt + elseif (whence == "end") then + pos = size + amt + elseif (whence == "set") then + pos = amt + end + if pos > size then + pos = size + elseif pos < 1 then + pos = 1 + end + return pos +end + +---@func filestream +---@arg path string "Path to the file" +---@arg mode string "File mode" +---@return stream "The stream for the file." +---@desc "This creates a stream from a file." +function kio.filestream(path, mode) + local dev, rpath = vfs.resolve(path) + local h = dev:open(rpath, mode) + local stat = dev:stat(rpath) + return kio.create_stream({dev=dev, hand=h, stat=stat}, { + read = function(self, amt) + return self.dev:read(self.hand, amt) + end, + seek = function(self, whence, amt) + local pos = self.dev:seek(self.hand, 0) + local npos = kio.calc_seek(whence, amt, self.stat.size, pos) + return self.dev:seek(self.hand, npos-pos) + end, + write = function(self, data) + return self.dev:write(self.hand, data) + end, + close = function(self) + return self.dev:close(self.hand) + end + }) +end + +---@func dir +---@arg udat table "The data to pass to to prototype" +---@arg proto function "The prototype function for the iterator" +---@return function "The iterator." +---@desc "Creates a directory iterator." +function kio.dir(udat, proto) + return function() + return proto(udat) + end +end + +---@func memstream +---@arg str string "The string to create a stream of." +---@arg write boolean "If the stream should be writable or not." +---@return stream "The memory stream." +---@desc "Creates a memory stream." +---@note "stream:close() returns the string." +function kio.memstream(str, write) + return kio.create_stream({str=str, pos=1, write=write}, { + read = function(self, amt) + local dat = self.str:sub(self.pos, self.pos+amt-1) + self.pos = self.pos+#dat + return dat + end, + write = function(self, dat) + if (write) then + local startstr = self.str:sub(1, self.pos-1) + local endstr = self.str:sub(self.pos+#dat) + self.str = startstr..dat..endstr + self.pos = self.pos + #dat + end + end, + seek = function(self, whence, amt) + self.pos = kio.calc_seek(whence, amt, #self.str, self.pos) + return self.pos + end, + close = function(self) + return self.str + end + }) +end + +kio.loglevel = { + DEBUG = 0, + INFO = 1, + WARNING = 2, + ERROR = 3, + PANIC = 255 +} + +kio.levels = { + [0] = "DEBUG", + "INFO", + "WARNING", + "ERROR", + [255] = "PANIC" +} + +---@func dprint +---@arg level integer "The log level" +---@arg status string "The message." +---@desc "This method logs to the kernel log and wherever else is set up to be printed to." +function kio.dprint(level, status) + local stack = {} + local lkexec = {} + local i = 0 + while lkexec do + lkexec = debug.getinfo(i) + stack[#stack+1] = lkexec + end + local src = stack[#stack].source:sub(2) + local spart = vfs.parts(src) + local exec = spart[#spart]:match("^(.+)%.([^%.]+)$") + local message = string.format("[%.2f] [%s] [%s] %s", computer.uptime(), levels[level], exec, status) + dmesgs[#dmesgs+1] = {ut=computer.uptime,lvl=level,x=exec,st=status} + if (level < $[{PRINT_DMESG_LEVEL}]) then + sig.push { + type = "dprint", + msg = message + } + end +end + +---@func dmesg +---@see kio.dprint +kio.dmesg = dprint + +---@func panic +---@arg msg string "The error message to display." +function kio.panic(msg) + dmesg(255, "Kernel panic!") +end + +---@func create_pipe +---@return stream "Pipe in" +---@return stream "Pipe out" +---@desc "Creates a pipe." +function kio.create_pipe() + local pipecore = kio.memstream() + local pipein = kio.create_stream({ + dat = pipecore + }, { + read = function() + -- no + end, + seek = function() + -- no + end, + write = function(self, dat) + self.dat:seek("end", 0) + self.dat:write(dat) + end, + close = function() + -- *no* + end + }) + local pipeout = kio.create_stream({ + dat = pipecore, + pos = 1 + }, { + read = function(self, amt) + self.dat:seek("set", self.pos) + local dat = self.dat:read() + self.pos = self.pos+#dat + return dat + end, + seek = function()end, + write = function()end, + close = function()end + }) + return pipein, pipeout +end + +---@func init +---@desc "Only called once. Sets up the kio library." +function kio.init() ---@func create_buffer ---@arg blocking boolean "True if read calls to a buffer that doesn't contain enough data block." ---@arg pid integer "This is set to the PID of the process which handles the buffers." ---@return table "The buffer for use anywhere." -kio.create_buffer = create_buffer \ No newline at end of file + kio.create_buffer = create_buffer + kio.init = false +end \ No newline at end of file diff --git a/ksrc/kstrings.lua b/ksrc/kstrings.lua new file mode 100644 index 0000000..91dea55 --- /dev/null +++ b/ksrc/kstrings.lua @@ -0,0 +1,6 @@ +_KINFO = { + name = "Tsuki", + release = "$[{TSUKI_RELEASE}]", + version = "$[{TSUKI_VERSION}]", + machine = "$[{TSUKI_TARGET}]", -- OC or LuPI2 +} \ No newline at end of file diff --git a/ksrc/net.lua b/ksrc/net.lua new file mode 100644 index 0000000..6013e71 --- /dev/null +++ b/ksrc/net.lua @@ -0,0 +1,6 @@ +--#include "ksrc/net/tsukinet/init.lua" + +local net = {} +function net.open(netinfo) + +end \ No newline at end of file diff --git a/ksrc/stdlib/err.lua b/ksrc/stdlib/err.lua new file mode 100644 index 0000000..332e808 --- /dev/null +++ b/ksrc/stdlib/err.lua @@ -0,0 +1,6 @@ +_P.pcall = pcall +_P.xpcall = xpcall + +_P.error = {} +_P.error.geterror = kio.geterror +_P.error.errno = kio.errno \ No newline at end of file diff --git a/ksrc/stdlib/init.lua b/ksrc/stdlib/init.lua index c5cb84b..b922e62 100644 --- a/ksrc/stdlib/init.lua +++ b/ksrc/stdlib/init.lua @@ -4,5 +4,7 @@ function _P.load(...) end end +--#include "ksrc/stdlib/err.lua" --#include "ksrc/stdlib/string.lua" ---#include "ksrc/stdlib/thread.lua" \ No newline at end of file +--#include "ksrc/stdlib/thread.lua" +--#include "ksrc/stdlib/err.lua" \ No newline at end of file diff --git a/ksrc/stdlib/io.lua b/ksrc/stdlib/io.lua new file mode 100644 index 0000000..e69de29 diff --git a/ksrc/string.lua b/ksrc/string.lua index 3c1524e..d920355 100644 --- a/ksrc/string.lua +++ b/ksrc/string.lua @@ -1,3 +1,5 @@ +string.newline = "\n" + function string.trim(self) return self:gsub("^%s+", ""):gsub("%s+$", "") end diff --git a/ksrc/vfs.lua b/ksrc/vfs.lua new file mode 100644 index 0000000..be6989e --- /dev/null +++ b/ksrc/vfs.lua @@ -0,0 +1,13 @@ +local vfs = {} + +function vfs.mount(path, proxy) + +end + +function vfs.resolve(path) + +end + +function vfs.umount(pathorproxy) + +end \ No newline at end of file diff --git a/tkrnl.velx b/tkrnl.velx index 8c31f96..988217a 100644 Binary files a/tkrnl.velx and b/tkrnl.velx differ diff --git a/utils/gendocs.lua b/utils/gendocs.lua index f2d3e8f..7a6c24c 100644 --- a/utils/gendocs.lua +++ b/utils/gendocs.lua @@ -157,7 +157,7 @@ for line in io.stdin:lines() do } elseif (rline:match("^%-@return") and cfunc.type == "func") then local args = parse_line(rline:sub(10)) - cfunc.ret[#cfunc.args+1] = { + cfunc.ret[#cfunc.ret+1] = { type = args[1], doc = args[2], } @@ -169,7 +169,17 @@ for line in io.stdin:lines() do elseif (rline:match("^%-@see")) then local args = parse_line(rline:sub(7)) cfunc.doc[#cfunc.doc+1] = { - doc = "See \27_S"..arg[2].."\27_E" + doc = "See \27_S"..args[1].."\27_E" + } + elseif (rline:match("^%-@note")) then + local args = parse_line(rline:sub(8)) + cfunc.doc[#cfunc.doc+1] = { + doc = "NOTE: "..args[1] + } + elseif (rline:match("^%-@desc")) then + local args = parse_line(rline:sub(8)) + cfunc.doc[#cfunc.doc+1] = { + doc = args[1] } elseif (rline:match("^%-@vararg")) then cfunc.vararg = true @@ -237,7 +247,7 @@ for i=1, #docs do else rettext = "No return." end - docc = docc .. fun .. "\n\nArguments:\n"..argtext.."\n\nReturns:\n"..rettext + docc = docc .. fun .. "\n\nArguments:\n"..argtext.."\n\nReturns:\n"..rettext.."\n\n" else docc = docc .. docs[i].methods[j].print_name .. "\n\n" end