This commit is contained in:
Jane Roxanne 2020-06-02 01:14:26 -05:00
parent 14fdfdce70
commit e44d6177a0
51 changed files with 1351 additions and 508 deletions

View File

@ -0,0 +1,2 @@
os.execute("mkdir -p build")
os.execute("rm -rf build/*")

211
.buildactions/01_velx.lua Normal file
View File

@ -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 <http://unlicense.org/>
--]]----------------------------------------------------------------------------
--------------------------------------------------------------------------------
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

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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

View File

@ -0,0 +1,5 @@
function actions.debug()
for i=1, #actions do
actions[actions[i]](true)
end
end

View File

@ -0,0 +1,5 @@
function actions.clean()
print("Cleaning up...")
--os.execute("rm -rf .docs")
--os.execute("rm -rf .ktmp")
end

235
build.lua
View File

@ -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 <http://unlicense.org/>
--]]----------------------------------------------------------------------------
--------------------------------------------------------------------------------
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 = {} local actions = {}
function actions.kernel() @[[local h = io.popen("ls .buildactions", "r")
-- This builds Tsuki into a VELX executable. for line in h:lines() do]]
os.execute("mkdir -p build/kernel") --#include @[{".buildactions/"..line}]
print("Compiling kernel...") @[[end]]
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
function actions.crescent() --[[function actions.debug()
os.execute("mkdir -p build/crescent") actions.kernel(true)
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()
actions.crescent() actions.crescent()
actions.velxboot() actions.velxboot()
actions.clean() actions.clean()
end]]
function actions.all()
for i=1, #actions do
actions[actions[i]]()
end
end end
if not arg[1] then if not arg[1] then

2
build.sh Executable file
View File

@ -0,0 +1,2 @@
#!/usr/bin/env sh
luacomp build.lua 2>/dev/null | lua - "$@"

57
coreutils/init.lua Normal file
View File

@ -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

45
coreutils/multicall.lua Normal file
View File

@ -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](...)

5
coreutils/reboot.lua Normal file
View File

@ -0,0 +1,5 @@
if (kernel) then
kernel.sig_push {
sigtype = "shutdown"
}
end

0
coreutils/sh.lua Normal file
View File

10
coreutils/shutdown.lua Normal file
View File

@ -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

6
coreutils/svc-ctl.lua Normal file
View File

@ -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

View File

@ -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

58
coreutils/uname.lua Normal file
View File

@ -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")

505
debug.lua
View File

@ -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 <http://unlicense.org/>
--]]----------------------------------------------------------------------------
--------------------------------------------------------------------------------
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 pat = tbl.endian or "="
local args = {} local args = {}
for i=1, do for i=1, #tbl do
local a, b = pairs(tbl[i]) local a, b = pairs(tbl[i])
local k, v = a(b) local k, v = a(b)
args[i] = k args[i] = k
pat = pat .. v pat = pat .. v
end end
return setmetatable({}, {__call=function(_, arg) return setmetatable({}, {__call=function(_, arg)
checkArg(1, arg, "string", "table") --checkArg(1, arg, "string", "table")
if (type(arg) == "string") then if (type(arg) == "string") then
local sval = {string.unpack(pat, arg)} local sval = {string.unpack(pat, arg)}
local rtn = {} local rtn = {}
@ -29,57 +154,6 @@ function struct(tbl)
end}) end})
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 { local velx_spec = struct {
endian = "<", endian = "<",
@ -88,237 +162,150 @@ local velx_spec = struct {
{compression="B"}, {compression="B"},
{lver="B"}, {lver="B"},
{os="B"}, {os="B"},
{arctype="c4"},
{psize="I3"}, {psize="I3"},
{lsize="I3"}, {lsize="I3"},
{ssize="I3"}, {ssize="I3"},
{rsize="I4"} {rsize="I4"}
} }
local velx = {} local function velx_multistep(path, arcpath, args, steps)
local shell_args = ""
local exec = {} for k, v in pairs(args) do
shell_args = shell_args .. k .. "=".. v .." "
function velx.identify(path) end
local h = io.open(path, "rb") steps.precomp()
local header = velx_spec(h:read(#velx_spec)) local h = io.popen(shell_args.."luacomp "..path, "r")
local prog = h:read("*a")
h:close() h:close()
return header.magic == "\27VelX" prog = steps.postcomp(prog)
end steps.prearc()
h = io.popen("find .docs -depth | tsar -o", "r")
function velx.load(path) local arc = h:read("*a")
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)
h:close() 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 end
function exec:link() local function velx(path, arcpath, args)
self.file:seek("set", #velx_spec+self.header.psize) return velx_multistep(path, arcpath, args, {
local linkinfo = self.file:read(self.header.lsize) precomp = function()end
local linker = {} postcomp = function(prog) return prog end
local pos = 1 prearc = function()end
while true do postarc = function()end
local size = string.unpack("<H", linkinfo:sub(pos)) prez = function()end
pos = pos + 2 postz = function()end
local name = linkinfo:sub(pos, pos+size-1) })
pos = pos + size
size = string.unpack("<H", linkinfo:sub(pos))
pos = pos + 2
local library = linkinfo:sub(pos, pos+size-1)
pos = pos + size
if (name == "" or library == "") then
break
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 end
function exec:load() local TSUKI_RELEASE = "0.0.1"
self.file:seek("set", #velx_spec) local tz = os.date("%z")
local code = self.file:read(self.header.psize) tz = tz:sub(1, 3)..":"..tz:sub(4)
if (self.header.compression == 0) then local TSUKI_VERSION = "Lua 5.3 "..os.date("%Y-%m-%dT%H:%M:%S")..tz
self.code = code local TSUKI_TARGET = os.getenv("TSUKI_TARGET") or "OC"
elseif (self.header.compression == 1) then
self.code = lzss.decompress(self.code) function actions.kernel(dbg)
else os.execute("mkdir -p build/kernel")
return nil, "invalid compression method" print("Compiling kernel...")
local h = io.open("build/kernel/tkrnl.velx", "wb")
h:write(velx_multistep("ksrc/init.lua", ".docs", {
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 .docs")
local h = io.open("build/kernel/debug.lua")
h:write(krnl)
h:close()
print("Generating docs and stripping comments...")
h = io.popen("lua utils/gendocs.lua .docs 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 .docs")
end,
precomp = function()
print("Compressing kernel...")
end,
postcomp = function()
print("Writing kernel out...")
end end
return true }))
end end
function exec:run(args, evar) actions[#actions+1] = "kernel"
system.load(self.code, args, system.getglobalenv({_ARCHIVE=self.arc}), system.getevars(evar))
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 end
end)() actions[#actions+1] = "crescent"
local zlua = (function() 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
local zlua = {} actions[#actions+1] = "velxboot"
return {} function actions.clean()
end) print("Cleaning up...")
os.execute("rm -rf .docs")
os.execute("rm -rf .ktmp")
end
-- Executable loading process:
-- - Link
-- - Load
-- - Execute
if () --[[function actions.debug()
actions.kernel(true)
actions.crescent()
actions.velxboot()
actions.clean()
end]]
local fox = {} function actions.all()
do for i=1, #actions do
actions[actions[i]]()
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
end end
end end
local tty = {} if not arg[1] then
do arg[1] = "all"
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
end end
---@section biosfixes "BIOS fixes" actions[arg[1]]()
local _biossupport = {} print("Build complete.")
---@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()

View File

@ -2,15 +2,20 @@ local acl = {}
do do
local acl = struct({ local acl = struct({
meta = "B", meta = "B",
id = "H", id = "H"
permname = "B"
}) })
local function acl_readstream(stream) 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 end
function acl.read(stream) function _acl:get_effective_perm(id, group, perm)
end end
end end

9
ksrc/ads.lua Normal file
View File

@ -0,0 +1,9 @@
local ads = {}
function ads.get(path)
end
function ads.list(path)
end

10
ksrc/archives.lua Normal file
View File

@ -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

View File

@ -16,7 +16,7 @@ end
local arc = {} local arc = {}
function arc:handle(path) function arc:read(path)
for i=1, #self.tbl do for i=1, #self.tbl do
if (self.tbl[i].name == path and self.tbl[i].mode & 32768 > 0) then if (self.tbl[i].name == path and self.tbl[i].mode & 32768 > 0) then
self.seek(self.tbl[i].pos-self.seek(0)) self.seek(self.tbl[i].pos-self.seek(0))
@ -55,12 +55,55 @@ function arc:meta(path)
return nil, "file not found" return nil, "file not found"
end 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() function arc:close()
self.close() self.close()
end end
return { 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 tbl = {}
local lname = "" local lname = ""
while lname ~= "TRAILER!!!" do while lname ~= "TRAILER!!!" do
@ -72,8 +115,10 @@ return {
lname = et.name lname = et.name
if lname ~= "TRAILER!!!" then if lname ~= "TRAILER!!!" then
tbl[#tbl+1] = et tbl[#tbl+1] = et
else
tbl.trailer = et
end end
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 end
} }

View File

@ -0,0 +1 @@
return true

View File

@ -0,0 +1,2 @@
---@page unknown "Unknown"
---@doc "This is for if Tsuki doesn't know what BIOS is in use."

View File

@ -0,0 +1,4 @@
return {
name = "Unknown",
version = {0, 0, 0, string="0.0.0"}
}

View File

View File

@ -1,5 +1,7 @@
---@section biosfixes "BIOS fixes" ---@section biosfixes "BIOS fixes"
@[[do
local i=1]]
local _biossupport = {} local _biossupport = {}
@[[function biosfix(bios)]] @[[function biosfix(bios)]]
--#include @[{"ksrc/bios/"..bios.."/docs.lua"}] --#include @[{"ksrc/bios/"..bios.."/docs.lua"}]
@ -13,11 +15,16 @@ _biossupport["@[{bios}]"] = {
detect = function() detect = function()
--#include @[{"ksrc/bios/"..bios.."/detect.lua"}] --#include @[{"ksrc/bios/"..bios.."/detect.lua"}]
end, end,
name = "@[{bios}]" name = "@[{bios}]",
id = @[{i}]
} }
_biossupport[@[{i}]] = "@[{bios}]"
@[[i=i+1]]
@[[end]] @[[end]]
@[[biosfix("zoryalegacy")]] @[[biosfix("zoryalegacy")]]
@[[biosfix("zoryaneo")]] @[[biosfix("zoryaneo")]]
@[[biosfix("unknown")]]
@[[biosfix = nil]] @[[biosfix = nil]]
@[[end]]

View File

@ -0,0 +1,5 @@
local eeprom = {}
function eeprom.proxy(addr)
end

View File

@ -0,0 +1,4 @@
--#include "ksrc/blk/eeprom.lua"
--#include "ksrc/blk/hdd.lua"
--#include "ksrc/blk/partition.lua"
--#include "ksrc/blk/promcard.lua"

View File

@ -7,7 +7,28 @@ local zlua = (function()
--#include "ksrc/execs/zlua/init.lua" --#include "ksrc/execs/zlua/init.lua"
end) end)
local lua = (function()
--#include "ksrc/execs/lua/init.lua"
end)
-- Executable loading process: -- Executable loading process:
-- - Link -- - Link
-- - Load -- - Load
-- - Execute -- - 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

0
ksrc/execs/lua/init.lua Normal file
View File

View File

@ -24,7 +24,11 @@ function velx.identify(path)
end end
function velx.load(path) 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 end
function velx.verify(path) function velx.verify(path)

1
ksrc/fs/arcfs/init.lua Normal file
View File

@ -0,0 +1 @@
local afs = {}

21
ksrc/fs/foxfs/ads.lua Normal file
View File

@ -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

View File

@ -4,3 +4,11 @@ local dirent = struct {
{name_size="H"}, {name_size="H"},
{etype="B"} {etype="B"}
} }
local function fox_readdir(self, inode)
end
function prox:list(path)
end

View File

@ -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

View File

@ -7,11 +7,16 @@ do
local prox = {} local prox = {}
function fox.proxy(blkdev) function fox.proxy(dev)
-- Read the superblock -- Read the superblock
sb:seek("set", 1025)
local sb = superblock(dev:read(#superblock))
local prox = {
super = sb
}
end end
local function fox_getinode(prox, inode) local function fox_getinode(prox, inode)
prox.dev:size()
end end
end end

View File

@ -27,7 +27,7 @@ local struct_inode = struct {
{dibp="I4"}, {dibp="I4"},
{tibp="I4"}, {tibp="I4"},
{gen="H"}, {gen="H"},
{acl="I4"}, {ads="I4"},
{fragaddr="I4"}, {fragaddr="I4"},
{osval2="c10"} {osval2="c10"}
} }

View File

@ -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/struct.lua"
--#include "ksrc/string.lua" --#include "ksrc/string.lua"
--#include "ksrc/archives.lua"
--#include "ksrc/ads.lua"
--#include "ksrc/blkdev.lua"
--#include "ksrc/acl.lua" --#include "ksrc/acl.lua"
--#include "ksrc/security.lua" --#include "ksrc/security.lua"
--#include "ksrc/exec.lua" --#include "ksrc/exec.lua"
@ -7,7 +14,25 @@
--#include "ksrc/tty.lua" --#include "ksrc/tty.lua"
--#include "ksrc/biosfixes.lua" --#include "ksrc/biosfixes.lua"
--#include "ksrc/buffer.lua" --#include "ksrc/buffer.lua"
--#include "ksrc/kio.lua" --#include "ksrc/threads.lua"
--#include "ksrc/net.lua"
-- Mount the rootfs kio.dmesg(1, "Starting Tsuki kernel.")
vfs.mount() 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

0
ksrc/kargs.lua Normal file
View File

View File

@ -1,8 +1,299 @@
---@module kio "Kernel I/O" @[[if not svar.get("PRINT_DMESG_LEVEL") then
local kio = {} 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 ---@func create_buffer
---@arg blocking boolean "True if read calls to a buffer that doesn't contain enough data block." ---@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." ---@arg pid integer "This is set to the PID of the process which handles the buffers."
---@return table "The buffer for use anywhere." ---@return table "The buffer for use anywhere."
kio.create_buffer = create_buffer kio.create_buffer = create_buffer
kio.init = false
end

6
ksrc/kstrings.lua Normal file
View File

@ -0,0 +1,6 @@
_KINFO = {
name = "Tsuki",
release = "$[{TSUKI_RELEASE}]",
version = "$[{TSUKI_VERSION}]",
machine = "$[{TSUKI_TARGET}]", -- OC or LuPI2
}

6
ksrc/net.lua Normal file
View File

@ -0,0 +1,6 @@
--#include "ksrc/net/tsukinet/init.lua"
local net = {}
function net.open(netinfo)
end

6
ksrc/stdlib/err.lua Normal file
View File

@ -0,0 +1,6 @@
_P.pcall = pcall
_P.xpcall = xpcall
_P.error = {}
_P.error.geterror = kio.geterror
_P.error.errno = kio.errno

View File

@ -4,5 +4,7 @@ function _P.load(...)
end end
end end
--#include "ksrc/stdlib/err.lua"
--#include "ksrc/stdlib/string.lua" --#include "ksrc/stdlib/string.lua"
--#include "ksrc/stdlib/thread.lua" --#include "ksrc/stdlib/thread.lua"
--#include "ksrc/stdlib/err.lua"

0
ksrc/stdlib/io.lua Normal file
View File

View File

@ -1,3 +1,5 @@
string.newline = "\n"
function string.trim(self) function string.trim(self)
return self:gsub("^%s+", ""):gsub("%s+$", "") return self:gsub("^%s+", ""):gsub("%s+$", "")
end end

13
ksrc/vfs.lua Normal file
View File

@ -0,0 +1,13 @@
local vfs = {}
function vfs.mount(path, proxy)
end
function vfs.resolve(path)
end
function vfs.umount(pathorproxy)
end

Binary file not shown.

View File

@ -157,7 +157,7 @@ for line in io.stdin:lines() do
} }
elseif (rline:match("^%-@return") and cfunc.type == "func") then elseif (rline:match("^%-@return") and cfunc.type == "func") then
local args = parse_line(rline:sub(10)) local args = parse_line(rline:sub(10))
cfunc.ret[#cfunc.args+1] = { cfunc.ret[#cfunc.ret+1] = {
type = args[1], type = args[1],
doc = args[2], doc = args[2],
} }
@ -169,7 +169,17 @@ for line in io.stdin:lines() do
elseif (rline:match("^%-@see")) then elseif (rline:match("^%-@see")) then
local args = parse_line(rline:sub(7)) local args = parse_line(rline:sub(7))
cfunc.doc[#cfunc.doc+1] = { 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 elseif (rline:match("^%-@vararg")) then
cfunc.vararg = true cfunc.vararg = true
@ -237,7 +247,7 @@ for i=1, #docs do
else else
rettext = "No return." rettext = "No return."
end 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 else
docc = docc .. docs[i].methods[j].print_name .. "\n\n" docc = docc .. docs[i].methods[j].print_name .. "\n\n"
end end