This commit is contained in:
sam 2020-05-24 23:50:51 -04:00
parent 501561ba4a
commit 14fdfdce70
17 changed files with 703 additions and 53 deletions

3
.gitignore vendored
View File

@ -1,4 +1,3 @@
*.velx
/.doc
.ktmp
debug.lua
/build/**

View File

@ -1,3 +1,6 @@
os.execute("mkdir -p build")
os.execute("rm -rf build/*")
--[[----------------------------------------------------------------------------
LZSS - encoder / decoder
This is free and unencumbered software released into the public domain.
@ -158,29 +161,32 @@ local velx_spec = struct {
{ssize="I3"},
{rsize="I4"}
}
local actions = {}
-- This builds Tsuki into a VELX executable.
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 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("tkrnl.velx", "wb")
local header = velx_spec({
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,
@ -191,12 +197,42 @@ local header = velx_spec({
ssize=0,
rsize=#arc,
arctype="tsar"
})
h:write(header)
h:write(data)
h:write(arc)
h:close()
print("Cleaning up...")
os.execute("rm -rf .docs")
os.execute("rm -rf .ktmp")
})
h:write(header)
h:write(data)
h:write(arc)
h:close()
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()
actions.crescent()
actions.velxboot()
actions.clean()
end
if not arg[1] then
arg[1] = "all"
end
actions[arg[1]]()
print("Build complete.")

324
debug.lua Normal file
View File

@ -0,0 +1,324 @@
function struct(tbl)
local pat = tbl.endian or "="
local args = {}
for i=1, 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
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 = "<",
{magic="c5"},
{fver="B"},
{compression="B"},
{lver="B"},
{os="B"},
{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))
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)
h:close()
return security.verify(code, sig)
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("<H", linkinfo:sub(pos))
pos = pos + 2
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
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
end
function exec:run(args, evar)
system.load(self.code, args, system.getglobalenv({_ARCHIVE=self.arc}), system.getevars(evar))
end
end)()
local zlua = (function()
local zlua = {}
return {}
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
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
end
---@section biosfixes "BIOS fixes"
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()

View File

@ -0,0 +1,16 @@
local eeprom = component.proxy(component.list("eeprom")())
local function lzss_decompress(a)local b,c,d,e,j,i,h,g=1,'',''while b<=#a do
e=c.byte(a,b)b=b+1
for k=0,7 do h=c.sub
g=h(a,b,b)if e>>k&1<1 and b<#a then
i=c.unpack('>I2',a,b)j=1+(i>>4)g=h(d,j,j+(i&15)+2)b=b+1
end
b=b+1
c=c..g
d=h(d..g,-4^6)end
end
return c end
local drive, part = eeprom.getData():match("^([%x%-]+);(%d)$")
part = tonumber(part)

View File

@ -0,0 +1,16 @@
local fs = component.proxy(computer.getBootAddress())
local f = fs.open("boot.velx")
fs.seek(f, "set", 14)
local psize = string.unpack("<I3", fs.read(f, 3))
fs.seek(f, "set", 27)
local rdat = psize
local dat = ""
local buf = ""
repeat
buf = fs.read(f, rdat)
if (buf) then
dat = dat .. buf
end
rdat = psize - #dat
until rdat == 0 or not buf or buf == ""
load(dat, "=boot.velx")()

View File

@ -1,3 +1,7 @@
@[[if not svar.get("CRESCENT_KARGS") then
svar.set("CRESCENT_KARGS", "")
end]]
local version = "1.0"
local gpu = component.list("gpu")()
@ -46,3 +50,4 @@ end
--#include "crescent/loader.lua"
status("crescent loader v"..version)
boot_kernel("--root=$ --security=none"..$(CRESCENT_KARGS))

View File

@ -1,6 +1,7 @@
function boot_kernel(...)
function boot_kernel(kargs)
local knl, env = load_velx(computer.getBootAddress(), "kernel.velx")
local iramfs = load_tsar(computer.getBootAddress(), "initramfs.tsar")
env._ARCHIVE = iramfs
knl(...)
status("kernel.velx "..kargs)
knl(kargs)
end

View File

@ -0,0 +1,97 @@
local magic = 0x5f7d
local magic_rev = 0x7d5f
local header_fmt = "I2I2I2I2I2I6I6"
local en = string.unpack("=I2", string.char(0x7d, 0x5f)) == magic -- true = LE, false = BE
local function get_end(e)
return (e and "<") or ">"
end
local function read_header(dat)
local e = get_end(en)
local m = string.unpack(e.."I2", dat)
if m ~= magic and m ~= magic_rev then return nil, "bad magic" end
if m ~= magic then
e = get_end(not en)
end
local ent = {}
ent.magic, ent.namesize, ent.mode, ent.uid, ent.gid, ent.filesize, ent.mtime = string.unpack(e..header_fmt, dat)
return ent
end
local arc = {}
function arc:fetch(path)
for i=1, #self.tbl do
if (self.tbl[i].name == path and self.tbl[i].mode & 32768 > 0) then
self.seek(self.tbl[i].pos-self.seek(0))
return self.read(self.tbl[i].filesize), self.tbl[i]
end
end
return nil, "file not found"
end
function arc:exists(path)
for i=1, #self.tbl do
if (self.tbl[i].name == path) then
return true
end
end
return false
end
function arc:list(path)
if path:sub(#path) ~= "/" then path = path .. "/" end
local ent = {}
for i=1, #self.tbl do
if (self.tbl[i].name:sub(1, #path) == path and not self.tbl[i].name:find("/", #path+1, false)) then
ent[#ent+1] = self.tbl[i].name
end
end
return ent
end
function arc:close()
self.close()
end
function load_tsar(addr, path)
local fs = component.proxy(addr)
local h = fs.open(path)
status("loading initramfs... "..lsc())
local dat = ""
local buf = ""
repeat
buf = fs.read(h, math.huge)
if (buf) then
dat = dat .. buf
end
y = y - 1
status("loading initramfs... "..lsc())
until not buf or buf == ""
local idx = 1
local function read(a)
local dat = buf:sub(idx, idx+a-1)
idx = idx + a
return dat
end
local function seek(a)
idx = idx + a
return idx
end
local function close()end
local tbl = {}
local lname = ""
while lname ~= "TRAILER!!!" do
y = y - 1
status("loading initramfs... "..lsc())
local dat = read(22)
local et = read_header(dat)
et.name = read(et.namesize)
et.pos = seek(et.namesize & 1)
seek(et.filesize + (et.filesize & 1))
lname = et.name
if lname ~= "TRAILER!!!" then
tbl[#tbl+1] = et
end
end
return setmetatable({tbl = tbl, read = read, seek = seek, close = close}, {__index=arc})
end

View File

@ -34,6 +34,9 @@ local function load_velx(addr, path)
status("loading kernel... ")
if (comp == 1) then
status("decompressing kernel...")
buf = lzss_decompress(buf)
dat = lzss_decompress(dat)
end
local env = {}
env._G = env
return load(dat, "="..path, "t", setmetatable(env, {__index=_G})), env
end

View File

@ -0,0 +1,72 @@
local component = require("component")
local computer = require("computer")
print("Flashing velxboot...")
component.eeprom.set([[
--#include "velxboot/init.lua"
]])
component.eeprom.setData(computer.getBootAddress()..";boot.velx")
print("Creating boot.velx...")
local f = io.open("/init.lua")
local prog = f:read("*a")
f:close()
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"}
}
f = io.open("/boot.velx", "wb")
f:write(velx_spec({
magic="\27VelX",
fver=1,
compression=0,
lver=0x53,
os=127,
arctype="",
psize=#prog
lsize=0,
ssize=0,
rsize=0,
}))
f:write(prog)
f:close()

View File

@ -1,3 +1,4 @@
local eeprom = component.proxy(component.list("eeprom")())
local function lzss_decompress(a)local b,c,d,e,j,i,h,g=1,'',''while b<=#a do
e=c.byte(a,b)b=b+1
for k=0,7 do h=c.sub
@ -27,12 +28,26 @@ local function boot_velx(addr, path)
rdat = psize - #dat
until rdat == 0 or not buf or buf == ""
if (comp == 1) then
buf = lzss_decompress(buf)
dat = lzss_decompress(dat)
end
assert(load(buf, "="..path))()
local baddr = addr
local bpath = path
function computer.getBootAddress()
return baddr
end
function computer.getBootPath()
return bpath
end
function computer.setBootAddress(a)
eeprom.setData(a..";"..path)
addr = a
end
function computer.setBootPath(p)
eeprom.setData(addr..";"..p)
path = p
end
assert(load(dat, "="..path))()
end
local eeprom = component.proxy(component.list("eeprom")())
local config = eeprom.getData()
local addr, path = config:match("^(.+);(.+)$")
if not addr then

0
ksrc/blk/eeprom.lua Normal file
View File

0
ksrc/blk/hdd.lua Normal file
View File

0
ksrc/blk/partition.lua Normal file
View File

0
ksrc/blk/promcard.lua Normal file
View File

64
utils/mkvelx.lua Normal file
View File

@ -0,0 +1,64 @@
local f = io.popen("luacomp "..arg[1], "r")
local prog = f:read("*a")
f:close()
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"}
}
f = io.open(arg[2], "wb")
f:write(velx_spec({
magic="\27VelX",
fver=1,
compression=0,
lver=0x53,
os=127,
arctype="",
psize=#prog,
lsize=0,
ssize=0,
rsize=0,
}))
f:write(prog)
f:close()

View File

@ -195,9 +195,11 @@ compression[header.compression] or "Unknown",
os[header.os & 0x7F] or "Unknown",
lver,
header.arctype:gsub("\0", "")),"\n")
local h = io.popen(commands[header.arctype:gsub("\0", "")], "w")
h:write(archive)
h:close()
if (header.arctype ~= "\0\0\0\0" and archive ~= "") then
local h = io.popen(commands[header.arctype:gsub("\0", "")], "w")
h:write(archive)
h:close()
end
if (header.compression == 1) then
io.stderr:write(M.decompress(program))
elseif (header.compression == 0) then