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