Compare commits
12
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a33bd0264 | ||
|
|
242762ab6b | ||
|
|
8c18d89489 | ||
|
|
041663e1e8 | ||
|
|
fcac0ff8d8 | ||
|
|
d98555328b | ||
|
|
61cbb91db2 | ||
|
|
b79492dbb8 | ||
|
|
bc87c53427 | ||
|
|
030e5bfd96 | ||
|
|
099638c735 | ||
|
|
5172da1b5b |
@@ -1,121 +1,344 @@
|
||||
local cp,c=component,computer;local b_addr=c.getBootAddress();local b_fs=cp.proxy(b_addr)
|
||||
local gpu=cp.list("gpu")() and cp.proxy(cp.list("gpu")())
|
||||
local e_rom=cp.list("eeprom")() and cp.proxy(cp.list("eeprom")())
|
||||
local screens={}
|
||||
for addr in cp.list("screen") do
|
||||
--:Minify:--
|
||||
local args={...}
|
||||
local bootdrive=args[1]
|
||||
local gpu=components:getFirst("gpu")
|
||||
local screenTextBuffer=nil
|
||||
local cursorX,cursorY=0,0
|
||||
local screenSizeX,screenSizeY=128,25
|
||||
|
||||
|
||||
if gpu then
|
||||
gpu.bind(addr)
|
||||
local w,h=gpu.maxResolution()
|
||||
gpu.setResolution(w,h)
|
||||
gpu.fill(1,1,w,h," ")
|
||||
cp.proxy(addr).turnOn()
|
||||
screens[#screens+1] = {cx=1,cy=1,w=w,h=h,addr=addr}
|
||||
end
|
||||
end
|
||||
local function scroll(scr) gpu.copy(1,2,scr.w,scr.h-1,0,-1);gpu.fill(1,scr.h,scr.w,1," ") end
|
||||
local function write(t)
|
||||
if not gpu then return end
|
||||
for s=1, #screens do
|
||||
local scr=screens[s]
|
||||
gpu.bind(scr.addr)
|
||||
for i=1,#t do
|
||||
local char=t:sub(i,i)
|
||||
if char=="\n" then scr.cx=1;scr.cy=scr.cy+1
|
||||
elseif char=="\t" then scr.cx=scr.cx+(4-((scr.cx-1)%4))
|
||||
elseif char=="\b" then if scr.cx>1 then scr.cx=scr.cx-1;gpu.set(scr.cx,scr.cy," ") end
|
||||
else gpu.set(scr.cx,scr.cy,char);scr.cx=scr.cx+1 end
|
||||
if scr.cx>scr.w then scr.cx=1;scr.cy=scr.cy+1 end
|
||||
if scr.cy>scr.h then scroll(scr);scr.cy=scr.cy-1 end
|
||||
screenTextBuffer=gpu:newBuffer(screenSizeX,screenSizeY)
|
||||
for t,v in components:list() do
|
||||
if t == "screen" then
|
||||
gpu:assignBuffer(screenTextBuffer, v)
|
||||
end
|
||||
end
|
||||
end
|
||||
local function throw(err)
|
||||
if gpu then
|
||||
gpu.setBackground(0x0000AA);
|
||||
gpu.setForeground(0xFFFFFF);
|
||||
for i=1, #screens do
|
||||
gpu.fill(1,1,screens[i].w,screens[i].h," ");
|
||||
screens[i].cx,screens[i].cy=1,1;
|
||||
|
||||
local function write(text)
|
||||
cursorX, cursorY = screenTextBuffer:pasteText(cursorX, cursorY, "SCROLL_SPILL_CLEAR", text)
|
||||
cursorY = cursorY + 1
|
||||
cursorX = 0
|
||||
if cursorY >= screenSizeY then
|
||||
cursorY = screenSizeY-1
|
||||
screenTextBuffer:newline()
|
||||
end
|
||||
write("CRITICAL KERNEL ERROR:\n"..tostring(err))
|
||||
end
|
||||
while true do c.pullSignal() end
|
||||
|
||||
local function displaySuperBadError(err)
|
||||
gpu:freeAllBuffers()
|
||||
screenTextBuffer=gpu:newBuffer(screenSizeX,screenSizeY)
|
||||
for t,v in components:list() do
|
||||
if t == "screen" then
|
||||
gpu:assignBuffer(screenTextBuffer, v)
|
||||
end
|
||||
end
|
||||
term.setBackgroundColor(0x1)
|
||||
term.setTextColor(0x4)
|
||||
term.clear()
|
||||
term.setCursorPos(1, 1)
|
||||
term.write("A critical error occurred while loading the system:")
|
||||
term.setCursorPos(1, 3)
|
||||
write(err)
|
||||
while true do end
|
||||
end
|
||||
|
||||
local ok, err = xpcall(function()
|
||||
local apis = {}
|
||||
local _l={coroutine=1,debug=1,_VERSION=1,assert=1,collectgarbage=1,error=1,getmetatable=1,ipairs=1,load=1,math=1,next=1,pairs=1,pcall=1,rawequal=1,rawget=1,rawlen=1,rawset=1,select=1,setmetatable=1,string=1,table=1,tonumber=1,tostring=1,type=1,xpcall=1,_G=1}
|
||||
for k,v in pairs(_G) do if not _l[k] then apis[k]=v;_G[k]=nil end end
|
||||
function sleep(t) local s=c.uptime()+t;while c.uptime()<s do c.pullSignal(s-c.uptime()) end end
|
||||
local function getFile(path)
|
||||
local h,err=b_fs.open(path,"r")
|
||||
if not h then throw("Cannot open: "..path) end
|
||||
local buf,chk="",""
|
||||
repeat chk=b_fs.read(h,math.huge);buf=buf..(chk or "") until not chk
|
||||
b_fs.close(h)
|
||||
return buf
|
||||
|
||||
local lua = {
|
||||
coroutine = true,
|
||||
debug = true,
|
||||
_VERSION = true,
|
||||
assert = true,
|
||||
collectgarbage = true,
|
||||
error = true,
|
||||
gcinfo = true,
|
||||
getmetatable = true,
|
||||
ipairs = true,
|
||||
__inext = true,
|
||||
load = true,
|
||||
math = true,
|
||||
next = true,
|
||||
pairs = true,
|
||||
pcall = true,
|
||||
rawequal = true,
|
||||
rawget = true,
|
||||
rawlen = true,
|
||||
rawset = true,
|
||||
select = true,
|
||||
setmetatable = true,
|
||||
string = true,
|
||||
table = true,
|
||||
tonumber = true,
|
||||
tostring = true,
|
||||
type = true,
|
||||
xpcall = true,
|
||||
_G = true
|
||||
}
|
||||
|
||||
local debug = debug
|
||||
for i, v in pairs(_G) do
|
||||
if not lua[i] or lua[i] == nil then
|
||||
apis[i] = v
|
||||
_G[i] = nil
|
||||
end
|
||||
local Kernel=load(getFile("/kernel.lua"),"@Kernel")
|
||||
local initFs=load(getFile("/oc/initdisks"),"@Init_disks")
|
||||
local fs=load(getFile("/initfs"),"@InitFs")
|
||||
if not Kernel then throw("Kernel load failed.") end
|
||||
if initFs then initFs=initFs(apis, b_fs, b_addr) end
|
||||
if fs then fs=fs() end
|
||||
local eQ={}
|
||||
local function qEv(e,...) table.insert(eQ,{e,...}) end
|
||||
local efi={
|
||||
getEpochMs=function() return math.floor(c.uptime()*1000) end,
|
||||
getUptime=function() return c.uptime()*1000 end,
|
||||
date=function() return tostring(apis.os.date()) end,
|
||||
getMachineEvent=function()
|
||||
if #eQ > 0 then
|
||||
return table.unpack(table.remove(eQ, 1))
|
||||
end
|
||||
|
||||
local function string_file(file)
|
||||
local str = file:read()
|
||||
local buf = {str or ""}
|
||||
local pos = 1
|
||||
local closed = false
|
||||
|
||||
local function content()
|
||||
return table.concat(buf)
|
||||
end
|
||||
|
||||
local function set_content(s)
|
||||
buf = {s}
|
||||
end
|
||||
|
||||
local function flush()
|
||||
file.write(content())
|
||||
end
|
||||
|
||||
local file = {}
|
||||
|
||||
function file.read(n)
|
||||
assert(not closed, "file is closed")
|
||||
|
||||
local s = content()
|
||||
local len = #s
|
||||
|
||||
if not n then
|
||||
local out = s:sub(pos)
|
||||
pos = len + 1
|
||||
return out
|
||||
end
|
||||
|
||||
local out = s:sub(pos, pos + n - 1)
|
||||
pos = pos + #out
|
||||
return out
|
||||
end
|
||||
|
||||
function file.write(data)
|
||||
assert(not closed, "file is closed")
|
||||
|
||||
local s = content()
|
||||
local before = s:sub(1, pos - 1)
|
||||
local after = s:sub(pos + #data)
|
||||
|
||||
set_content(before .. data .. after)
|
||||
pos = pos + #data
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function file.seek(whence, offset)
|
||||
assert(not closed, "file is closed")
|
||||
|
||||
local s = content()
|
||||
local len = #s
|
||||
|
||||
whence = whence or "cur"
|
||||
offset = offset or 0
|
||||
|
||||
if whence == "set" then
|
||||
pos = offset + 1
|
||||
elseif whence == "cur" then
|
||||
pos = pos + offset
|
||||
elseif whence == "end" then
|
||||
pos = len + offset + 1
|
||||
else
|
||||
return nil
|
||||
error("invalid whence")
|
||||
end
|
||||
|
||||
if pos < 1 then pos = 1 end
|
||||
if pos > len + 1 then pos = len + 1 end
|
||||
|
||||
return pos - 1
|
||||
end
|
||||
|
||||
function file:close()
|
||||
assert(not closed, "file is closed")
|
||||
flush()
|
||||
closed = true
|
||||
end
|
||||
|
||||
function file:flush()
|
||||
assert(not closed, "file is closed")
|
||||
flush()
|
||||
end
|
||||
|
||||
return file
|
||||
end
|
||||
|
||||
local function getFile(path)
|
||||
local file = bootdrive:open(path, "r")
|
||||
if not file then
|
||||
displaySuperBadError("Could not open file: " .. path)
|
||||
end
|
||||
local content = file:read()
|
||||
return content
|
||||
end
|
||||
|
||||
local Kernel = load(getFile("/boot/kernel.lua"),"@Kernel")
|
||||
local initFs = load(getFile("/boot/ac/initdisks"),"@Init_disks")(apis)
|
||||
local fs = load(getFile("/boot/initfs"), "@InitFs")()
|
||||
|
||||
if not Kernel then displaySuperBadError("Could not load kernel.") end
|
||||
if not initFs then displaySuperBadError("Could not load initdisks.") end
|
||||
if not fs then displaySuperBadError("Could not load initfs.") end
|
||||
|
||||
local computercomp=apis.components:getFirst("computer")
|
||||
local uefi=apis.components:getFirst("uefi")
|
||||
local computer = {
|
||||
time = function() return apis.os.epoch("utc") end,
|
||||
clock = function() return apis.os.clock() * 1000 end,
|
||||
shutdown = apis.os.shutdown,
|
||||
reboot = apis.os.reboot,
|
||||
getMachineEvent = function()
|
||||
return computercomp:getMachineEvent()
|
||||
end,
|
||||
getEEPROM=function() return e_rom and e_rom.get() or "" end,
|
||||
setEEPROM=function(_,t) if e_rom then e_rom.set(t) end end,
|
||||
getNvram=function() return e_rom and e_rom.getData() or "" end,
|
||||
setNvram=function(_,t) if e_rom then e_rom.setData(t) end end,
|
||||
beep=function(freq, timeMs) c.beep(freq, timeMs / 1000) end,
|
||||
initfs=fs,
|
||||
disks=initFs,
|
||||
architecture="oc",
|
||||
firmware=apis,
|
||||
reboot=false,
|
||||
yield=function() coroutine.yield() end,
|
||||
screenCtl={
|
||||
print=function(_,t) write(tostring(t).."\n") end,
|
||||
printInline=function(_,t) write(tostring(t)) end,
|
||||
clear=function() if gpu then for i=1, #screens do local scr=screens[i];gpu.bind(scr.addr);gpu.fill(1,1,scr.w,scr.h," ");scr.cx,scr.cy=1,1 end end end,
|
||||
resetCursor=function() for i=1, #screens do local scr=screens[i];scr.cx,scr.cy=1,1 end end,
|
||||
setBackgroundColor=function(_,cl) if gpu then gpu.setBackground(cl) end end,
|
||||
setTextColor=function(_,cl) if gpu then gpu.setForeground(cl) end end,
|
||||
enable=function() end,
|
||||
disable=function() end
|
||||
getEEPROM = function() return uefi.data end,
|
||||
setEEPROM = function(_, text)
|
||||
uefi.data=text
|
||||
end
|
||||
}
|
||||
|
||||
local icolors = {
|
||||
[0x1] = 1, -- #000000
|
||||
[0x2] = 2, -- #FFFFFF
|
||||
[0x4] = 3, -- #FF0000
|
||||
[0x8] = 4, -- #00FF00
|
||||
[0x10] = 5, -- #0000FF
|
||||
[0x20] = 6, -- #00FFFF
|
||||
[0x40] = 7, -- #FF00FF
|
||||
[0x80] = 8, -- #FFFF00
|
||||
[0x100] = 9, -- #FF6D00
|
||||
[0x200] = 10, -- #6DFF55
|
||||
[0x400] = 11, -- #24FFFF
|
||||
[0x800] = 12, -- #924900
|
||||
[0x1000] = 13, -- #6D6D55
|
||||
[0x2000] = 14, -- #DBDBAA
|
||||
[0x4000] = 15, -- #6D00FF
|
||||
[0x8000] = 16 -- #B6FF00
|
||||
}
|
||||
local kCo=coroutine.create(function()
|
||||
local s,e=xpcall(Kernel,debug.traceback,efi)
|
||||
if not s and not efi.reboot then throw(e) end
|
||||
if efi.reboot then c.shutdown(true) else c.shutdown() end
|
||||
|
||||
local colors = {
|
||||
0x0001, -- #000000
|
||||
0x0002, -- #FFFFFF
|
||||
0x0004, -- #FF0000
|
||||
0x0008, -- #00FF00
|
||||
0x0010, -- #0000FF
|
||||
0x0020, -- #00FFFF
|
||||
0x0040, -- #FF00FF
|
||||
0x0080, -- #FFFF00
|
||||
0x0100, -- #FF6D00
|
||||
0x0200, -- #6DFF55
|
||||
0x0400, -- #24FFFF
|
||||
0x0800, -- #924900
|
||||
0x1000, -- #6D6D55
|
||||
0x2000, -- #DBDBAA
|
||||
0x4000, -- #6D00FF
|
||||
0x8000 -- #B6FF00
|
||||
}
|
||||
|
||||
apis.term.setBackgroundColor(0x8000)
|
||||
apis.term.setTextColor(0x1000)
|
||||
apis.term.clear()
|
||||
apis.term.setCursorPos(1, 1)
|
||||
|
||||
local kernelCoro = coroutine.create(function()
|
||||
---@diagnostic disable-next-line: param-type-mismatch
|
||||
local ok, err = xpcall(Kernel, debug.traceback, apis, initFs, "cct", "/sbin/init",
|
||||
{
|
||||
print = function(_, text) write(text .. "\n") end,
|
||||
printInline = function(_, text) write(text) end,
|
||||
clear = function()
|
||||
apis.term.clear()
|
||||
apis.term.setCursorPos(1, 1)
|
||||
end,
|
||||
setCursorPos = function(_, x, y)
|
||||
apis.term.setCursorPos(x, y)
|
||||
end,
|
||||
getCursorPos = function() return apis.term.getCursorPos() end,
|
||||
getSize = function() return apis.term.getSize() end,
|
||||
setBackgroundColor = function(_, color)
|
||||
apis.term.setBackgroundColor(colors[color])
|
||||
end,
|
||||
setTextColor = function(_, color)
|
||||
apis.term.setTextColor(colors[color])
|
||||
end,
|
||||
getBackgroundColor = function()
|
||||
return icolors[apis.term.getBackgroundColor()]
|
||||
end,
|
||||
getTextColor = function()
|
||||
return icolors[apis.term.getTextColor()]
|
||||
end
|
||||
}, computer, fs, "$")
|
||||
if not ok then displaySuperBadError(err) end
|
||||
end)
|
||||
efi.screenCtl:print("Loaded in "..tostring(c.uptime()).."s")
|
||||
|
||||
function coroutine.resumeWithTimeout(co, timeout, ...)
|
||||
local startTime = computer.time()
|
||||
debug.sethook(co, function()
|
||||
if computer.time() > startTime + timeout then
|
||||
return coroutine.yield("timeout")
|
||||
end
|
||||
end, "", 1000)
|
||||
local ret = {coroutine.resume(co, ...)}
|
||||
if ret[1] and ret[2] == "timeout" then
|
||||
return "timeout"
|
||||
elseif ret[1] == false then
|
||||
return "error", ret[2]
|
||||
else
|
||||
debug.sethook(co)
|
||||
return "success", table.unpack(ret, 2)
|
||||
end
|
||||
end
|
||||
|
||||
write("Loaded in " .. tostring(apis.os.clock()) .. " seconds.\n")
|
||||
|
||||
while true do
|
||||
local st,e=coroutine.resume(kCo)
|
||||
c.pushSignal("NoSleep")
|
||||
local ex=false
|
||||
while not ex do
|
||||
local ev={c.pullSignal(0)}
|
||||
if ev[1]=="key_down" then qEv("keyPressed",1,ev[3]);qEv("keyTyped",1,string.char(ev[3]))
|
||||
elseif ev[1]=="key_up" then qEv("keyReleased",1,ev[3])
|
||||
local status, err = coroutine.resumeWithTimeout(kernelCoro, 50)
|
||||
apis.os.queueEvent("NoSleep")
|
||||
local exit = false
|
||||
while not exit do
|
||||
local event = {coroutine.yield()}
|
||||
if event[1] == "key" then
|
||||
queueEvent("keyPressed", 1, event[2])
|
||||
if acekeys[event[2]] then
|
||||
queueEvent("keyTyped", 1, acekeys[event[2]])
|
||||
end
|
||||
if ev[1]=="NoSleep" then ex=true else qEv(table.unpack(ev)) end
|
||||
elseif event[1] == "char" then
|
||||
queueEvent("keyTyped", 1, event[2])
|
||||
elseif event[1] == "key_up" then
|
||||
queueEvent("keyReleased", 1, event[2])
|
||||
elseif event[1] == "disk" then
|
||||
queueEvent("componentAdded", "disk")
|
||||
elseif event[1] == "disk_eject" then
|
||||
queueEvent("componentRemoved", "disk")
|
||||
elseif event[1] == "modem_message" then
|
||||
queueEvent("modem_message", table.unpack(event, 2))
|
||||
elseif event[1] == "rednet_message" then
|
||||
queueEvent("rednet_message", table.unpack(event, 2))
|
||||
elseif event[1] == "http_success" then
|
||||
queueEvent("http_success", table.unpack(event, 2))
|
||||
elseif event[1] == "http_failure" then
|
||||
queueEvent("http_failure", table.unpack(event, 2))
|
||||
elseif event[1] == "NoSleep" then
|
||||
exit = true
|
||||
end
|
||||
if st=="error" or coroutine.status(kCo)=="dead" then
|
||||
if efi.reboot then c.shutdown(true) end
|
||||
throw("Kernel fault: "..tostring(e))
|
||||
end
|
||||
if status == "error" or coroutine.status(kernelCoro) == "dead" then
|
||||
displaySuperBadError("Kernel error: " .. tostring(err))
|
||||
coroutine.yield("key")
|
||||
end
|
||||
end
|
||||
end, debug.traceback)
|
||||
if not ok then throw("Boot fault: "..err) end
|
||||
|
||||
if not ok then displaySuperBadError("Fatal error during boot: " .. err) end
|
||||
while true do coroutine.yield() end
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
local init
|
||||
do
|
||||
local component_invoke = component.invoke
|
||||
local function boot_invoke(address, method, ...)
|
||||
local result = table.pack(pcall(component_invoke, address, method, ...))
|
||||
if not result[1] then
|
||||
return nil, result[2]
|
||||
else
|
||||
return table.unpack(result, 2, result.n)
|
||||
end
|
||||
end
|
||||
|
||||
-- backwards compatibility, may remove later
|
||||
local eeprom = component.list("eeprom")()
|
||||
computer.getBootAddress = function()
|
||||
return boot_invoke(eeprom, "getData")
|
||||
end
|
||||
computer.setBootAddress = function(address)
|
||||
return boot_invoke(eeprom, "setData", address)
|
||||
end
|
||||
|
||||
do
|
||||
local screen = component.list("screen")()
|
||||
local gpu = component.list("gpu")()
|
||||
if gpu and screen then
|
||||
boot_invoke(gpu, "bind", screen)
|
||||
end
|
||||
end
|
||||
local function tryLoadFrom(address)
|
||||
local handle, reason = boot_invoke(address, "open", "/oc/boot.lua")
|
||||
if not handle then
|
||||
return nil, reason
|
||||
end
|
||||
local buffer = ""
|
||||
repeat
|
||||
local data, reason = boot_invoke(address, "read", handle, math.maxinteger or math.huge)
|
||||
if not data and reason then
|
||||
return nil, reason
|
||||
end
|
||||
buffer = buffer .. (data or "")
|
||||
until not data
|
||||
boot_invoke(address, "close", handle)
|
||||
return load(buffer, "=init")
|
||||
end
|
||||
local reason
|
||||
if computer.getBootAddress() then
|
||||
init, reason = tryLoadFrom(computer.getBootAddress())
|
||||
end
|
||||
if not init then
|
||||
computer.setBootAddress()
|
||||
for address in component.list("filesystem") do
|
||||
init, reason = tryLoadFrom(address)
|
||||
if init then
|
||||
computer.setBootAddress(address)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if not init then
|
||||
error("no bootable medium found" .. (reason and (": " .. tostring(reason)) or ""), 0)
|
||||
end
|
||||
end
|
||||
local ok, err = xpcall(init,debug.traceback)
|
||||
if not ok then
|
||||
error(err)
|
||||
else
|
||||
return err
|
||||
end
|
||||
@@ -1,136 +0,0 @@
|
||||
local args = {...}
|
||||
local apis = args[1]
|
||||
local bootdrive = args[2]
|
||||
local bootaddr = args[3]
|
||||
local disks = {}
|
||||
local internal = {}
|
||||
|
||||
local function createDisk(id, hw)
|
||||
local disk = {
|
||||
address = id,
|
||||
isReadOnly = function() return hw.isReadOnly() end
|
||||
}
|
||||
|
||||
function disk:spaceUsed() return hw.spaceUsed() end
|
||||
function disk:spaceTotal() return hw.spaceTotal() end
|
||||
|
||||
function disk:list(path)
|
||||
if not hw.exists(path) or not hw.isDirectory(path) then
|
||||
return nil, "not directory"
|
||||
end
|
||||
return hw.list(path)
|
||||
end
|
||||
|
||||
function disk:fileExists(path)
|
||||
return hw.exists(path) and not hw.isDirectory(path)
|
||||
end
|
||||
|
||||
function disk:directoryExists(path)
|
||||
return hw.exists(path) and hw.isDirectory(path)
|
||||
end
|
||||
|
||||
function disk:type(path)
|
||||
if not hw.exists(path) then
|
||||
return nil
|
||||
elseif hw.isDirectory(path) then
|
||||
return "directory"
|
||||
else
|
||||
return "file"
|
||||
end
|
||||
end
|
||||
|
||||
function disk:makeDirectory(path)
|
||||
hw.makeDirectory(path)
|
||||
end
|
||||
|
||||
function disk:remove(path)
|
||||
if hw.exists(path) then hw.remove(path) end
|
||||
end
|
||||
|
||||
function disk:setLabel(label) hw.setLabel(label) end
|
||||
function disk:getLabel() return hw.getLabel() end
|
||||
|
||||
function disk:attributes(path)
|
||||
return {
|
||||
size = hw.size(path),
|
||||
isDir = hw.isDirectory(path),
|
||||
isReadOnly = hw.isReadOnly(),
|
||||
modified = hw.lastModified(path),
|
||||
created = hw.lastModified(path)
|
||||
}
|
||||
end
|
||||
|
||||
function disk:open(path, mode)
|
||||
local fd = hw.open(path, mode)
|
||||
|
||||
if not fd then
|
||||
local dir = path:match("^(.*)/[^/]+$")
|
||||
|
||||
if dir and not hw.exists(dir) then
|
||||
local ok, err = hw.makeDirectory(dir)
|
||||
if not ok then
|
||||
return nil, err or "could not create parent directory"
|
||||
end
|
||||
end
|
||||
|
||||
fd = hw.open(path, mode)
|
||||
if not fd then
|
||||
return nil, "file not found or access denied"
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
read = function(num) return hw.read(fd, num) end,
|
||||
|
||||
readAll = function()
|
||||
local data = {}
|
||||
while true do
|
||||
local chunk = hw.read(fd, math.huge)
|
||||
if not chunk then break end
|
||||
data[#data + 1] = chunk
|
||||
end
|
||||
return table.concat(data)
|
||||
end,
|
||||
|
||||
write = function(data) return hw.write(fd, data) end,
|
||||
seek = function(whence, offset)
|
||||
return hw.seek(fd, whence, offset)
|
||||
end,
|
||||
|
||||
flush = function()
|
||||
hw.close(fd)
|
||||
fd = hw.open(path, mode)
|
||||
end,
|
||||
|
||||
close = function()
|
||||
hw.close(fd)
|
||||
fd = nil
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
return disk
|
||||
end
|
||||
|
||||
internal["$"] = createDisk("$", bootdrive)
|
||||
|
||||
local function refresh()
|
||||
disks = {}
|
||||
for addr in apis.component.list("filesystem") do
|
||||
if addr ~= bootaddr then
|
||||
disks[addr] = createDisk(addr, apis.component.proxy(addr))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function iter()
|
||||
refresh()
|
||||
local combined = {}
|
||||
|
||||
for id, obj in pairs(internal) do combined[id] = obj end
|
||||
for id, obj in pairs(disks) do combined[id] = obj end
|
||||
|
||||
return pairs(combined)
|
||||
end
|
||||
|
||||
return {refresh = refresh, list = iter}
|
||||
@@ -1,15 +0,0 @@
|
||||
--:Minify:--
|
||||
local kernel=...
|
||||
kernel.oc={}
|
||||
kernel.oc.component=kernel.apis.component
|
||||
kernel.oc.computer=kernel.apis.computer
|
||||
|
||||
kernel.log("Installed components:")
|
||||
for addr, typ in kernel.oc.component.list() do
|
||||
local dev=kernel.oc.component.proxy(addr)
|
||||
local tier=""
|
||||
if dev.getTier then
|
||||
tier=dev.getTier()
|
||||
end
|
||||
kernel.log(" "..addr.." : "..typ..tier)
|
||||
end
|
||||
@@ -1,23 +0,0 @@
|
||||
--:Minify:--
|
||||
local kernel=...
|
||||
local component=kernel.oc.component
|
||||
|
||||
local function wrap(p)
|
||||
return function(op, mode)
|
||||
if op=="type" then
|
||||
return "device"
|
||||
elseif op=="open" then
|
||||
if kernel.uid~=0 then error("EACCES") end
|
||||
return component.proxy(p)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for addr, typ in kernel.oc.component.list() do
|
||||
local obj=wrap(addr)
|
||||
kernel.devfs.data["raw"][addr]=obj
|
||||
local typefolder=kernel.devfs.data["raw"]["by-type"][typ]
|
||||
if not typefolder then typefolder={} end
|
||||
typefolder[tostring(#table.keys(typefolder)+1)] = obj
|
||||
kernel.devfs.data["raw"]["by-type"][typ]=typefolder
|
||||
end
|
||||
@@ -1,177 +0,0 @@
|
||||
-- OpenComputers TTY driver
|
||||
|
||||
local kernel = ...
|
||||
local component = kernel.oc.component
|
||||
local computer = kernel.oc.computer
|
||||
|
||||
local plt = {
|
||||
0x000000, 0x000040, 0x000080, 0x0000C0, 0x0000FF,
|
||||
0x002400, 0x002440, 0x002480, 0x0024C0, 0x0024FF,
|
||||
0x004900, 0x004940, 0x004980, 0x0049C0, 0x0049FF,
|
||||
0x006D00, 0x006D40, 0x006D80, 0x006DC0, 0x006DFF,
|
||||
0x009200, 0x009240, 0x009280, 0x0092C0, 0x0092FF,
|
||||
0x00B600, 0x00B640, 0x00B680, 0x00B6C0, 0x00B6FF,
|
||||
0x00DB00, 0x00DB40, 0x00DB80, 0x00DBC0, 0x00DBFF,
|
||||
0x00FF00, 0x00FF40, 0x00FF80, 0x00FFC0, 0x00FFFF,
|
||||
|
||||
0x330000, 0x330040, 0x330080, 0x3300C0, 0x3300FF,
|
||||
0x332400, 0x332440, 0x332480, 0x3324C0, 0x3324FF,
|
||||
0x334900, 0x334940, 0x334980, 0x3349C0, 0x3349FF,
|
||||
0x336D00, 0x336D40, 0x336D80, 0x336DC0, 0x336DFF,
|
||||
0x339200, 0x339240, 0x339280, 0x3392C0, 0x3392FF,
|
||||
0x33B600, 0x33B640, 0x33B680, 0x33B6C0, 0x33B6FF,
|
||||
0x33DB00, 0x33DB40, 0x33DB80, 0x33DBC0, 0x33DBFF,
|
||||
0x33FF00, 0x33FF40, 0x33FF80, 0x33FFC0, 0x33FFFF,
|
||||
|
||||
0x660000, 0x660040, 0x660080, 0x6600C0, 0x6600FF,
|
||||
0x662400, 0x662440, 0x662480, 0x6624C0, 0x6624FF,
|
||||
0x664900, 0x664940, 0x664980, 0x6649C0, 0x6649FF,
|
||||
0x666D00, 0x666D40, 0x666D80, 0x666DC0, 0x666DFF,
|
||||
0x669200, 0x669240, 0x669280, 0x6692C0, 0x6692FF,
|
||||
0x66B600, 0x66B640, 0x66B680, 0x66B6C0, 0x66B6FF,
|
||||
0x66DB00, 0x66DB40, 0x66DB80, 0x66DBC0, 0x66DBFF,
|
||||
0x66FF00, 0x66FF40, 0x66FF80, 0x66FFC0, 0x66FFFF,
|
||||
|
||||
0x990000, 0x990040, 0x990080, 0x9900C0, 0x9900FF,
|
||||
0x992400, 0x992440, 0x992480, 0x9924C0, 0x9924FF,
|
||||
0x994900, 0x994940, 0x994980, 0x9949C0, 0x9949FF,
|
||||
0x996D00, 0x996D40, 0x996D80, 0x996DC0, 0x996DFF,
|
||||
0x999200, 0x999240, 0x999280, 0x9992C0, 0x9992FF,
|
||||
0x99B600, 0x99B640, 0x99B680, 0x99B6C0, 0x99B6FF,
|
||||
0x99DB00, 0x99DB40, 0x99DB80, 0x99DBC0, 0x99DBFF,
|
||||
0x99FF00, 0x99FF40, 0x99FF80, 0x99FFC0, 0x99FFFF,
|
||||
|
||||
0xCC0000, 0xCC0040, 0xCC0080, 0xCC00C0, 0xCC00FF,
|
||||
0xCC2400, 0xCC2440, 0xCC2480, 0xCC24C0, 0xCC24FF,
|
||||
0xCC4900, 0xCC4940, 0xCC4980, 0xCC49C0, 0xCC49FF,
|
||||
0xCC6D00, 0xCC6D40, 0xCC6D80, 0xCC6DC0, 0xCC6DFF,
|
||||
0xCC9200, 0xCC9240, 0xCC9280, 0xCC92C0, 0xCC92FF,
|
||||
0xCCB600, 0xCCB640, 0xCCB680, 0xCCB6C0, 0xCCB6FF,
|
||||
0xCCDB00, 0xCCDB40, 0xCCDB80, 0xCCDBC0, 0xCCDBFF,
|
||||
0xCCFF00, 0xCCFF40, 0xCCFF80, 0xCCFFC0, 0xCCFFFF,
|
||||
|
||||
0xFF0000, 0xFF0040, 0xFF0080, 0xFF00C0, 0xFF00FF,
|
||||
0xFF2400, 0xFF2440, 0xFF2480, 0xFF24C0, 0xFF24FF,
|
||||
0xFF4900, 0xFF4940, 0xFF4980, 0xFF49C0, 0xFF49FF,
|
||||
0xFF6D00, 0xFF6D40, 0xFF6D80, 0xFF6DC0, 0xFF6DFF,
|
||||
0xFF9200, 0xFF9240, 0xFF9280, 0xFF92C0, 0xFF92FF,
|
||||
0xFFB600, 0xFFB640, 0xFFB680, 0xFFB6C0, 0xFFB6FF,
|
||||
0xFFDB00, 0xFFDB40, 0xFFDB80, 0xFFDBC0, 0xFFDBFF,
|
||||
0xFFFF00, 0xFFFF40, 0xFFFF80, 0xFFFFC0, 0xFFFFFF,
|
||||
|
||||
0x000000, 0x0F0F0F, 0x1E1E1E, 0x2D2D2D,
|
||||
0x3C3C3C, 0x4B4B4B, 0x5A5A5A, 0x696969,
|
||||
0x787878, 0x878787, 0x969696, 0xA5A5A5,
|
||||
0xB4B4B4, 0xC3C3C3, 0xD2D2D2, 0xE1E1E1
|
||||
}
|
||||
|
||||
local gpus,screens = {},{}
|
||||
|
||||
for addr, typ in component.list("gpu") do
|
||||
if typ == "gpu" then
|
||||
gpus[#gpus+1]=component.proxy(addr)
|
||||
end
|
||||
end
|
||||
|
||||
if #gpus>0 then
|
||||
for addr, typ in component.list("screen") do
|
||||
if typ == "screen" then
|
||||
gpus[1].bind(addr)
|
||||
local w,h = gpus[1].maxResolution()
|
||||
gpus[1].setResolution(w,h)
|
||||
screens[addr]={cx=1,cy=1,w=w,h=h,addr=addr,fg=0,bg=0,gpu=nil}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local scrnum = 0
|
||||
for i,v in pairs(screens) do
|
||||
scrnum=scrnum+1
|
||||
end
|
||||
|
||||
kernel.log("initialized "..tostring(#gpus).." gpus and "..tostring(scrnum).." screens")
|
||||
|
||||
local binds,newid={},0
|
||||
local curaddr=""
|
||||
local function scroll(scr, gpu) gpu.copy(1,2,scr.w,scr.h-1,0,-1);gpu.fill(1,scr.h,scr.w,1," ") end
|
||||
local function write(text, addr)
|
||||
local g=gpus[1]
|
||||
local scr=screens[addr]
|
||||
if not scr then error("NODEV") end
|
||||
if curaddr~=addr then g.bind(addr); g.setForeground(scr.fg); g.setBackground(scr.bg) end
|
||||
for i=1,#text do
|
||||
local char=text:sub(i,i)
|
||||
if char=="\n" then scr.cx=1;scr.cy=scr.cy+1
|
||||
elseif char=="\t" then scr.cx=scr.cx+(4-((scr.cx-1)%4))
|
||||
elseif char=="\b" then if scr.cx>1 then scr.cx=scr.cx-1;g.set(scr.cx,scr.cy," ") end
|
||||
else g.set(scr.cx,scr.cy,char);scr.cx=scr.cx+1 end
|
||||
if scr.cx>scr.w then scr.cx=1;scr.cy=scr.cy+1 end
|
||||
if scr.cy>scr.h then scroll(scr, g);scr.cy=scr.cy-1 end
|
||||
end
|
||||
end
|
||||
|
||||
local function newtty(addr)
|
||||
newid=newid+1
|
||||
kernel.devfs.data["tty"][tostring(newid)]=function(op, mode)
|
||||
if op=="type" then
|
||||
return "Terminal"
|
||||
elseif op=="open" then
|
||||
local h = {
|
||||
read=function(amount) end,
|
||||
write=function(content)
|
||||
write(content, addr)
|
||||
end,
|
||||
size=function()
|
||||
return screens[addr].w, screens[addr].h
|
||||
end,
|
||||
clear=function()
|
||||
local g=gpus[1]
|
||||
local scr=screens[addr]
|
||||
if addr~=curaddr then g.bind(addr) end
|
||||
g.fill(1,1,scr.w,scr.h," ");
|
||||
scr.cx,scr.cy=1,1
|
||||
end,
|
||||
gpos=function()
|
||||
return screens[addr].cx, screens[addr].cy
|
||||
end,
|
||||
spos=function(x,y)
|
||||
if not tonumber(x) or not tonumber(y) then error("Invailid arg") end
|
||||
screens[addr].cx, screens[addr].cy = x,y
|
||||
end,
|
||||
sfgc=function(c)
|
||||
screens[addr].fg=c
|
||||
end,
|
||||
sbgc=function(c)
|
||||
screens[addr].bg=c
|
||||
end,
|
||||
gfgc=function()
|
||||
return screens[addr].fg
|
||||
end,
|
||||
gbgc=function()
|
||||
return screens[addr].bg
|
||||
end,
|
||||
isvirt=function()
|
||||
return false
|
||||
end,
|
||||
gplt=function()
|
||||
return plt
|
||||
end
|
||||
}
|
||||
if mode=="rw" then
|
||||
return h
|
||||
elseif mode=="r" then
|
||||
h["write"]=nil
|
||||
return h
|
||||
elseif mode=="w" then
|
||||
h["read"]=nil
|
||||
return h
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if #gpus>=1 and scrnum>=1 then
|
||||
for addr,obj in pairs(screens) do
|
||||
newtty(addr)
|
||||
end
|
||||
end
|
||||
@@ -1,113 +0,0 @@
|
||||
--:Minify:--
|
||||
local kernel=...
|
||||
kernel.oc.keyboards={}
|
||||
local kbs=kernel.oc.keyboards
|
||||
|
||||
local kbidx=0
|
||||
local keyboard = {}
|
||||
|
||||
keyboard.keys = {
|
||||
back = 0x0E, -- backspace
|
||||
delete = 0xD3,
|
||||
down = 0xD0,
|
||||
enter = 0x1C,
|
||||
home = 0xC7,
|
||||
lcontrol = 0x1D,
|
||||
left = 0xCB,
|
||||
lmenu = 0x38, -- left Alt
|
||||
lshift = 0x2A,
|
||||
pageDown = 0xD1,
|
||||
rcontrol = 0x9D,
|
||||
right = 0xCD,
|
||||
rmenu = 0xB8, -- right Alt
|
||||
rshift = 0x36,
|
||||
space = 0x39,
|
||||
tab = 0x0F,
|
||||
up = 0xC8,
|
||||
["end"] = 0xCF,
|
||||
numpadenter = 0x9C,
|
||||
}
|
||||
kernel.oc.keys=keyboard.keys
|
||||
|
||||
for i=0, 255 do
|
||||
kernel.oc.keys[string.char(i)]=i
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
function keyboard.isAltDown(addr)
|
||||
return kbs[addr].pressedCodes[keyboard.keys.lmenu] or kbs[addr].pressedCodes[keyboard.keys.rmenu]
|
||||
end
|
||||
|
||||
function keyboard.isControl(char)
|
||||
return type(char) == "number" and (char < 0x20 or (char >= 0x7F and char <= 0x9F))
|
||||
end
|
||||
|
||||
function keyboard.isControlDown(addr)
|
||||
return kbs[addr].pressedCodes[keyboard.keys.lcontrol] or kbs[addr].pressedCodes[keyboard.keys.rcontrol]
|
||||
end
|
||||
|
||||
function keyboard.isKeyDown(addr,charOrCode)
|
||||
if type(charOrCode) == "string" then
|
||||
return kbs[addr].pressedChars[utf8 and utf8.codepoint(charOrCode) or charOrCode:byte()]
|
||||
elseif type(charOrCode) == "number" then
|
||||
return kbs[addr].pressedCodes[charOrCode]
|
||||
end
|
||||
end
|
||||
|
||||
function keyboard.isShiftDown(addr)
|
||||
return kbs[addr].pressedCodes[keyboard.keys.lshift] or kbs[addr].pressedCodes[keyboard.keys.rshift]
|
||||
end
|
||||
kernel.oc.keyboard=keyboard
|
||||
|
||||
local function serializeBool(bool)
|
||||
if bool then
|
||||
return "T"
|
||||
else
|
||||
return "F"
|
||||
end
|
||||
end
|
||||
|
||||
for addr, typ in kernel.oc.component.list("keyboard") do
|
||||
if typ=="keyboard" then
|
||||
kbidx=kbidx+1
|
||||
kbs[addr]={pressedChars = {}, pressedCodes = {}, events=kernel.newFifo()}
|
||||
kernel.devfs.data["input"]["keyboard"..tostring(kbidx)]=function(op,mode)
|
||||
if op=="type" then
|
||||
return "Keyboard"
|
||||
elseif op=="open" then
|
||||
local h = {
|
||||
read=function(amount)
|
||||
local rv=""
|
||||
for i=1, amount or 1 do
|
||||
local event = {kernel.oc.keyboards[addr].events.pop()}
|
||||
if event[1] then
|
||||
rv=rv..event[1]
|
||||
end
|
||||
end
|
||||
if rv=="" then rv=nil end
|
||||
return rv
|
||||
end,
|
||||
write=function(content)
|
||||
end,
|
||||
gctrl=function()
|
||||
return serializeBool(keyboard.isControlDown(addr))..";"..serializeBool(keyboard.isAltDown(addr))
|
||||
end,
|
||||
isKeyDown=function(char)
|
||||
return keyboard.isKeyDown(addr,char)
|
||||
end
|
||||
}
|
||||
if mode=="rw" then
|
||||
return h
|
||||
elseif mode=="r" then
|
||||
h["write"]=nil
|
||||
return h
|
||||
elseif mode=="w" then
|
||||
h["read"]=nil
|
||||
return h
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
--:Minify:--
|
||||
local kernel=...
|
||||
local keys=kernel.oc.keys
|
||||
|
||||
kernel.processes.ocdaemon = function()
|
||||
|
||||
local timeout = false
|
||||
|
||||
kernel.log("OC daemon started")
|
||||
|
||||
local ctrlKeyMap = {
|
||||
[keys.a]=1, [keys.b]=2, [keys.c]=3,
|
||||
[keys.d]=4, [keys.e]=5, [keys.f]=6,
|
||||
[keys.g]=7, [keys.h]=8, [keys.i]=9,
|
||||
[keys.j]=10, [keys.k]=11, [keys.l]=12,
|
||||
[keys.m]=13, [keys.n]=14, [keys.o]=15,
|
||||
[keys.p]=16, [keys.q]=17, [keys.r]=18,
|
||||
[keys.s]=19, [keys.t]=20, [keys.u]=21,
|
||||
[keys.v]=22, [keys.w]=23, [keys.x]=24,
|
||||
[keys.y]=25, [keys.z]=26,
|
||||
}
|
||||
|
||||
local specialKeyMap = {
|
||||
[keys.up] = "\27[A",
|
||||
[keys.down] = "\27[B",
|
||||
[keys.right] = "\27[C",
|
||||
[keys.left] = "\27[D",
|
||||
[keys.home] = "\27[H",
|
||||
[keys["end"]] = "\27[F",
|
||||
--[keys.pageUp] = "\27[5~",
|
||||
--[keys.pageDown] = "\27[6~",
|
||||
[keys.delete] = "\27[3~",
|
||||
[keys.enter] = "\n",
|
||||
[keys.back] = "\b",
|
||||
[keys.tab] = "\t",
|
||||
}
|
||||
|
||||
while true do
|
||||
|
||||
local event = {kernel.EFI.getMachineEvent()}
|
||||
|
||||
if event[1] then
|
||||
|
||||
local eventType = event[1]
|
||||
local addr = event[2]
|
||||
local char = event[3]
|
||||
local keyCode = event[4]
|
||||
|
||||
if eventType == "key_down" then
|
||||
|
||||
local keyboard = kernel.oc.keyboards[addr]
|
||||
|
||||
if keyboard.ctrl then
|
||||
|
||||
local ctrlByte = ctrlKeyMap[keyCode]
|
||||
|
||||
if ctrlByte then
|
||||
if ctrlByte == 3 then
|
||||
|
||||
for _, task in ipairs(syscall.getTasks()) do
|
||||
syscall.sigsend(task, 1)
|
||||
end
|
||||
|
||||
else
|
||||
keyboard.events.push(string.char(ctrlByte))
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
local special = specialKeyMap[keyCode]
|
||||
|
||||
if special then
|
||||
keyboard.events.push(special)
|
||||
|
||||
elseif char and char > 0 then
|
||||
keyboard.events.push(kernel.apis.unicode.char(char))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
elseif eventType == "key_up" then
|
||||
|
||||
end
|
||||
|
||||
timeout = false
|
||||
|
||||
else
|
||||
timeout = true
|
||||
end
|
||||
|
||||
if timeout then
|
||||
sleep(0.05)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
kernel.log("OC daemon queued for execution")
|
||||
@@ -1,146 +0,0 @@
|
||||
--:Minify:--
|
||||
local kernel=...
|
||||
local alpha = 0.85
|
||||
local C_target = 0.01
|
||||
local Tmin = 0.0005
|
||||
local Tmax = 0.5
|
||||
local lambda_budget = 0.08
|
||||
local lambda_clamp = 0.03
|
||||
local lambda_var = 0.02
|
||||
local k_min = 0.5
|
||||
local k_max = 0.5
|
||||
local B = 0.01
|
||||
|
||||
function kernel.main()
|
||||
kernel.log("Starting main loop...")
|
||||
kernel.saveLog()
|
||||
local stopLog=5
|
||||
local logTasks=100
|
||||
|
||||
while not kernel.exitMain do
|
||||
if kernel.config.logTasks then
|
||||
if logTasks<0 then
|
||||
kernel.log("Active Tasks:")
|
||||
for i,v in pairs(kernel.tasks) do
|
||||
kernel.log(v.name.." : "..v.status.." : "..tostring(v.pid).." : "..tostring(v.exit))
|
||||
end
|
||||
kernel.log("[END BLOCK]")
|
||||
logTasks=100
|
||||
end
|
||||
logTasks=logTasks-1
|
||||
end
|
||||
local N = 0
|
||||
local Tmin_hit = 0
|
||||
local Tmax_hit = 0
|
||||
local totalTaskTime = 0
|
||||
local taskTimes = {}
|
||||
|
||||
for pid, task in pairs(kernel.tasks) do
|
||||
if kernel.exitMain then break end
|
||||
|
||||
for _,list in ipairs(kernel.perTaskHooks) do
|
||||
for id,hook in ipairs(list) do
|
||||
local ok,err = xpcall(hook, debug.traceback, task, pid)
|
||||
if not ok then
|
||||
kernel.log("[MAIN HOOK ERR]: "..err, "ERROR", 0xFF0000)
|
||||
list[id]=nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if task.status == "R" then
|
||||
N = N + 1
|
||||
task.timeSlice = math.min(Tmax, math.max(Tmin, B / (N ^ alpha)))
|
||||
if task.status == "R" then
|
||||
local startTime = kernel.EFI:getEpochMs()
|
||||
local ret
|
||||
if stopLog > 0 then
|
||||
kernel.log("Running task " .. tostring(task.pid) .. " (" .. task.name .. ") with time slice " .. string.format("%.3f", task.timeSlice) .. "s", "DBUG", 0x00FFFF)
|
||||
end
|
||||
|
||||
ret = { coroutine.resume(task.coro, table.unpack(task.syscallReturn)) }
|
||||
|
||||
|
||||
local elapsed = kernel.EFI:getEpochMs() - startTime
|
||||
task.lastTime = elapsed
|
||||
task.totalTime = (task.totalTime or 0) + elapsed
|
||||
task.numRuns = (task.numRuns or 0) + 1
|
||||
|
||||
taskTimes[#taskTimes+1] = elapsed
|
||||
totalTaskTime = totalTaskTime + elapsed
|
||||
|
||||
if elapsed <= Tmin then Tmin_hit = Tmin_hit + 1 end
|
||||
if elapsed >= Tmax then Tmax_hit = Tmax_hit + 1 end
|
||||
|
||||
if ret[1] == "error" or ret[1] == false then
|
||||
kernel.log("processHandlerException: " .. tostring(ret[2]), "ERROR", 0xFF0000)
|
||||
task.status = "Z"
|
||||
task.exit = "processHandlerException: " .. tostring(ret[2])
|
||||
|
||||
elseif ret[1] == "timeout" then
|
||||
task.ivs = task.ivs + 1
|
||||
task.syscallReturn = {}
|
||||
|
||||
elseif ret[1] == "success" or ret[1] == true then
|
||||
task.vs = task.vs + 1
|
||||
|
||||
if ret[2] == "syscall" then
|
||||
local scname = ret[3]
|
||||
if kernel.syscalls[scname] then
|
||||
if kernel.config.debugSyscalls then
|
||||
kernel.log("Task " .. task.pid .. " syscall: " .. scname, "DBUG", 0x00FFFF)
|
||||
for i = 4, #ret do
|
||||
kernel.log(" inval[" .. (i-3) .. "] = " .. tostring(ret[i]), "DBUG", 0x00FFFF)
|
||||
end
|
||||
end
|
||||
|
||||
local sysret = { xpcall(kernel.syscalls[scname], debug.traceback, table.unpack(ret, 4)) }
|
||||
|
||||
if kernel.config.debugSyscalls then
|
||||
if not sysret[1] then
|
||||
kernel.log("Task " .. task.pid .. " syscall " .. scname .. " failed: " .. tostring(sysret[2]), "ERROR", 0xFF0000)
|
||||
else
|
||||
kernel.log("Task " .. task.pid .. " syscall " .. scname .. " ok, " .. (#sysret-1) .. " retvals", "DBUG", 0x00FFFF)
|
||||
for i = 2, #sysret do
|
||||
local v = type(sysret[i]) == "table" and table.serialize(sysret[i]) or tostring(sysret[i])
|
||||
kernel.log(" retval[" .. (i-1) .. "] = " .. v, "DBUG", 0x00FFFF)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not sysret[1] then
|
||||
task.syscallReturn = { false, sysret[2] }
|
||||
else
|
||||
task.syscallReturn = { true, table.unpack(sysret, 2) }
|
||||
end
|
||||
else
|
||||
task.syscallReturn = { false, "Unknown syscall: " .. tostring(scname) }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
kernel.EFI:yield()
|
||||
end
|
||||
|
||||
local T_prev_avg = (N > 0) and (totalTaskTime / N) or 0
|
||||
local T_prev_var = 0
|
||||
for _, t in ipairs(taskTimes) do
|
||||
T_prev_var = T_prev_var + (t - T_prev_avg) ^ 2
|
||||
end
|
||||
if N > 0 then T_prev_var = T_prev_var / N end
|
||||
|
||||
if N > 0 then
|
||||
local f_clamp = k_min * (Tmin_hit / N) - k_max * (Tmax_hit / N)
|
||||
local B_budget = (C_target * (N ^ (alpha - 1))) / math.max(T_prev_avg, 1e-8)
|
||||
B = B + lambda_budget * (B_budget - B) + lambda_clamp * f_clamp - lambda_var * T_prev_var
|
||||
end
|
||||
|
||||
kernel.hpv.reapDeadTasks()
|
||||
if stopLog > 0 then
|
||||
kernel.log("Executed " .. N .. " tasks, avg time: " .. string.format("%.2f", T_prev_avg) .. "ms, var: " .. string.format("%.2f", T_prev_var) .. ", B: " .. string.format("%.5f", B))
|
||||
stopLog = stopLog - 1
|
||||
kernel.saveLog()
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -321,7 +321,7 @@ local ok, err = xpcall(function()
|
||||
end
|
||||
end)
|
||||
|
||||
function EFI.resumeWithTimeout(co, timeout, ...)
|
||||
function coroutine.resumeWithTimeout(co, timeout, ...)
|
||||
local startTime = EFI.getEpochMs()
|
||||
debug.sethook(co, function()
|
||||
if EFI.getEpochMs() > startTime + timeout then
|
||||
@@ -342,7 +342,7 @@ local ok, err = xpcall(function()
|
||||
write("Loaded in " .. tostring(apis.os.clock()) .. " seconds.\n")
|
||||
|
||||
while true do
|
||||
local status, err = EFI.resumeWithTimeout(kernelCoro, 50)
|
||||
local status, err = coroutine.resumeWithTimeout(kernelCoro, 50)
|
||||
apis.os.queueEvent("NoSleep")
|
||||
local exit = false
|
||||
while not exit do
|
||||
|
||||
@@ -47,7 +47,7 @@ local function write(text, term)
|
||||
term.setCursorPos(x, y)
|
||||
end
|
||||
|
||||
local function displaySuperBadError(err, noyield)
|
||||
local function displaySuperBadError(err)
|
||||
lterm.setBackgroundColor(0x1)
|
||||
lterm.setTextColor(0x4)
|
||||
lterm.clear()
|
||||
@@ -145,9 +145,9 @@ local ok, err = xpcall(function()
|
||||
return content
|
||||
end
|
||||
|
||||
local Kernel = load(getFile(BOOT_DRIVE_PATH .. "/kernel.lua"),"@Kernel")
|
||||
local initFs = load(getFile(BOOT_DRIVE_PATH .. "/cct/initdisks"),"@Init_disks")(apis)
|
||||
local fs = load(getFile(BOOT_DRIVE_PATH .. "/initfs"), "@InitFs")()
|
||||
local Kernel = load(getFile(BOOT_DRIVE_PATH .. "/boot/kernel.lua"),"@Kernel")
|
||||
local initFs = load(getFile(BOOT_DRIVE_PATH .. "/boot/cct/initdisks"),"@Init_disks")(apis)
|
||||
local fs = load(getFile(BOOT_DRIVE_PATH .. "/boot/initfs"), "@InitFs")()
|
||||
|
||||
if not Kernel then displaySuperBadError("Could not load kernel.") end
|
||||
if not initFs then displaySuperBadError("Could not load initdisks.") end
|
||||
@@ -419,7 +419,6 @@ local ok, err = xpcall(function()
|
||||
end
|
||||
|
||||
local EFI = {
|
||||
yield=function() end,
|
||||
getEpochMs = function() return apis.os.epoch("utc") end,
|
||||
getUptime = function() return apis.os.clock() * 1000 end,
|
||||
date = function() return apis.os.date("!%Y-%m-%dT%H:%M:%SZ", apis.os.epoch("utc") / 1000) end,
|
||||
@@ -507,14 +506,15 @@ local ok, err = xpcall(function()
|
||||
--pf
|
||||
---@diagnostic disable-next-line: param-type-mismatch-
|
||||
local ok, err = xpcall(Kernel, debug.traceback, EFI)
|
||||
if not ok then
|
||||
error(err)
|
||||
if not ok and not EFI.reboot then displaySuperBadError(err) end
|
||||
if err then
|
||||
apis.os.reboot()
|
||||
else
|
||||
apis.os.shutdown()
|
||||
end
|
||||
end)
|
||||
|
||||
function EFI.resumeWithTimeout(co, timeout, ...)
|
||||
function coroutine.resumeWithTimeout(co, timeout, ...)
|
||||
local startTime = EFI.getEpochMs()
|
||||
debug.sethook(co, function()
|
||||
if EFI.getEpochMs() > startTime + timeout then
|
||||
@@ -536,7 +536,7 @@ local ok, err = xpcall(function()
|
||||
--p
|
||||
|
||||
while true do
|
||||
local status, err = EFI.resumeWithTimeout(kernelCoro, 50)
|
||||
local status, err = coroutine.resumeWithTimeout(kernelCoro, 50)
|
||||
apis.os.queueEvent("NoSleep")
|
||||
local exit = false
|
||||
while not exit do
|
||||
|
||||
@@ -58,11 +58,11 @@ function _G.term.native()
|
||||
term.setCursorPos(1, 1)
|
||||
term.setCursorBlink(true)
|
||||
term.clear()
|
||||
local file = fs.open(BOOT_DRIVE_PATH.."/cct/boot.lua", "r")
|
||||
local file = fs.open(BOOT_DRIVE_PATH.."/boot/cct/boot.lua", "r")
|
||||
if file == nil then
|
||||
term.setCursorBlink(false)
|
||||
term.setTextColor(16384)
|
||||
term.write("Could not find /cct/boot.lua. UnBIOS cannot continue.")
|
||||
term.write("Could not find /boot/cct/boot.lua. UnBIOS cannot continue.")
|
||||
term.setCursorPos(1, 2)
|
||||
term.write("Press any key to continue")
|
||||
coroutine.yield("key")
|
||||
@@ -73,7 +73,7 @@ function _G.term.native()
|
||||
if fn == nil then
|
||||
term.setCursorBlink(false)
|
||||
term.setTextColor(16384)
|
||||
term.write("Could not load /cc/boot.lua. UnBIOS cannot continue.")
|
||||
term.write("Could not load /boot/cc/boot.lua. UnBIOS cannot continue.")
|
||||
term.setCursorPos(1, 2)
|
||||
term.write(err)
|
||||
term.setCursorPos(1, 3)
|
||||
|
||||
@@ -250,21 +250,6 @@ internal["rom"] = createDisk("rom", "/rom", true, {
|
||||
end
|
||||
})
|
||||
|
||||
internal["root"] = createDisk("root", "/root", false, {
|
||||
setLabel = function(label)
|
||||
local h = fs.open("/.rootlabel", "w")
|
||||
h.write(label)
|
||||
h.close()
|
||||
end,
|
||||
getLabel = function()
|
||||
local h = fs.open("/.rootlabel", "r")
|
||||
if not h then return "$" end
|
||||
local label = h.readAll()
|
||||
h.close()
|
||||
return label
|
||||
end
|
||||
})
|
||||
|
||||
local function refresh()
|
||||
disks={}
|
||||
for _, disk in ipairs({peripheral.find("drive")}) do
|
||||
|
||||
@@ -191,14 +191,16 @@ local function newtty(obj, id, ev)
|
||||
write(content, obj)
|
||||
end,
|
||||
size=function()
|
||||
return obj.getSize()
|
||||
local s={obj.getSize()}
|
||||
return table.concat(s,";")
|
||||
end,
|
||||
clear=function()
|
||||
obj.clear()
|
||||
obj.setCursorPos(1,1)
|
||||
end,
|
||||
gpos=function()
|
||||
return obj.getCursorPos()
|
||||
local s={obj.getCursorPos()}
|
||||
return table.concat(s,";")
|
||||
end,
|
||||
spos=function(x,y)
|
||||
return obj.setCursorPos(x,y)
|
||||
|
||||
@@ -1,151 +0,0 @@
|
||||
--:Minify:--
|
||||
local kernel=...
|
||||
local alpha = 0.85
|
||||
local C_target = 0.01
|
||||
local Tmin = 0.0005
|
||||
local Tmax = 0.5
|
||||
local lambda_budget = 0.08
|
||||
local lambda_clamp = 0.03
|
||||
local lambda_var = 0.02
|
||||
local k_min = 0.5
|
||||
local k_max = 0.5
|
||||
local B = 0.01
|
||||
|
||||
function kernel.main()
|
||||
kernel.log("Starting main loop...")
|
||||
kernel.saveLog()
|
||||
local stopLog=5
|
||||
local logTasks=100
|
||||
|
||||
while not kernel.exitMain do
|
||||
if kernel.config.logTasks then
|
||||
if logTasks<0 then
|
||||
kernel.log("Active Tasks:")
|
||||
for i,v in pairs(kernel.tasks) do
|
||||
kernel.log(v.name.." : "..v.status.." : "..tostring(v.pid).." : "..tostring(v.exit))
|
||||
end
|
||||
kernel.log("[END BLOCK]")
|
||||
logTasks=100
|
||||
end
|
||||
logTasks=logTasks-1
|
||||
end
|
||||
local N = 0
|
||||
local Tmin_hit = 0
|
||||
local Tmax_hit = 0
|
||||
local totalTaskTime = 0
|
||||
local taskTimes = {}
|
||||
|
||||
for pid, task in pairs(kernel.tasks) do
|
||||
if kernel.exitMain then break end
|
||||
|
||||
for _,list in ipairs(kernel.perTaskHooks) do
|
||||
for id,hook in ipairs(list) do
|
||||
local ok,err = xpcall(hook, debug.traceback, task, pid)
|
||||
if not ok then
|
||||
kernel.log("[MAIN HOOK ERR]: "..err, "ERROR", 0xFF0000)
|
||||
list[id]=nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if task.status == "R" then
|
||||
N = N + 1
|
||||
task.timeSlice = math.min(Tmax, math.max(Tmin, B / (N ^ alpha)))
|
||||
if task.status == "R" then
|
||||
local startTime = kernel.EFI:getEpochMs()
|
||||
local ret
|
||||
if stopLog > 0 then
|
||||
kernel.log("Running task " .. tostring(task.pid) .. " (" .. task.name .. ") with time slice " .. string.format("%.3f", task.timeSlice) .. "s", "DBUG", 0x00FFFF)
|
||||
end
|
||||
if kernel.config.preempt then
|
||||
if not task.debugger then
|
||||
ret = { kernel.EFI.resumeWithTimeout(task.coro, task.timeSlice, table.unpack(task.syscallReturn)) }
|
||||
else
|
||||
ret = { coroutine.resume(task.coro, table.unpack(task.syscallReturn)) }
|
||||
end
|
||||
else
|
||||
ret = { coroutine.resume(task.coro, table.unpack(task.syscallReturn)) }
|
||||
end
|
||||
|
||||
local elapsed = kernel.EFI:getEpochMs() - startTime
|
||||
task.lastTime = elapsed
|
||||
task.totalTime = (task.totalTime or 0) + elapsed
|
||||
task.numRuns = (task.numRuns or 0) + 1
|
||||
|
||||
taskTimes[#taskTimes+1] = elapsed
|
||||
totalTaskTime = totalTaskTime + elapsed
|
||||
|
||||
if elapsed <= Tmin then Tmin_hit = Tmin_hit + 1 end
|
||||
if elapsed >= Tmax then Tmax_hit = Tmax_hit + 1 end
|
||||
|
||||
if ret[1] == "error" or ret[1] == false then
|
||||
kernel.log("processHandlerException: " .. tostring(ret[2]), "ERROR", 0xFF0000)
|
||||
task.status = "Z"
|
||||
task.exit = "processHandlerException: " .. tostring(ret[2])
|
||||
|
||||
elseif ret[1] == "timeout" then
|
||||
task.ivs = task.ivs + 1
|
||||
task.syscallReturn = {}
|
||||
|
||||
elseif ret[1] == "success" or ret[1] == true then
|
||||
task.vs = task.vs + 1
|
||||
|
||||
if ret[2] == "syscall" then
|
||||
local scname = ret[3]
|
||||
if kernel.syscalls[scname] then
|
||||
if kernel.config.debugSyscalls then
|
||||
kernel.log("Task " .. task.pid .. " syscall: " .. scname, "DBUG", 0x00FFFF)
|
||||
for i = 4, #ret do
|
||||
kernel.log(" inval[" .. (i-3) .. "] = " .. tostring(ret[i]), "DBUG", 0x00FFFF)
|
||||
end
|
||||
end
|
||||
|
||||
local sysret = { xpcall(kernel.syscalls[scname], debug.traceback, table.unpack(ret, 4)) }
|
||||
|
||||
if kernel.config.debugSyscalls then
|
||||
if not sysret[1] then
|
||||
kernel.log("Task " .. task.pid .. " syscall " .. scname .. " failed: " .. tostring(sysret[2]), "ERROR", 0xFF0000)
|
||||
else
|
||||
kernel.log("Task " .. task.pid .. " syscall " .. scname .. " ok, " .. (#sysret-1) .. " retvals", "DBUG", 0x00FFFF)
|
||||
for i = 2, #sysret do
|
||||
local v = type(sysret[i]) == "table" and table.serialize(sysret[i]) or tostring(sysret[i])
|
||||
kernel.log(" retval[" .. (i-1) .. "] = " .. v, "DBUG", 0x00FFFF)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not sysret[1] then
|
||||
task.syscallReturn = { false, sysret[2] }
|
||||
else
|
||||
task.syscallReturn = { true, table.unpack(sysret, 2) }
|
||||
end
|
||||
else
|
||||
task.syscallReturn = { false, "Unknown syscall: " .. tostring(scname) }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local T_prev_avg = (N > 0) and (totalTaskTime / N) or 0
|
||||
local T_prev_var = 0
|
||||
for _, t in ipairs(taskTimes) do
|
||||
T_prev_var = T_prev_var + (t - T_prev_avg) ^ 2
|
||||
end
|
||||
if N > 0 then T_prev_var = T_prev_var / N end
|
||||
|
||||
if N > 0 then
|
||||
local f_clamp = k_min * (Tmin_hit / N) - k_max * (Tmax_hit / N)
|
||||
local B_budget = (C_target * (N ^ (alpha - 1))) / math.max(T_prev_avg, 1e-8)
|
||||
B = B + lambda_budget * (B_budget - B) + lambda_clamp * f_clamp - lambda_var * T_prev_var
|
||||
end
|
||||
|
||||
kernel.hpv.reapDeadTasks()
|
||||
if stopLog > 0 then
|
||||
kernel.log("Executed " .. N .. " tasks, avg time: " .. string.format("%.2f", T_prev_avg) .. "ms, var: " .. string.format("%.2f", T_prev_var) .. ", B: " .. string.format("%.5f", B))
|
||||
stopLog = stopLog - 1
|
||||
kernel.saveLog()
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,3 +1 @@
|
||||
Hyperion
|
||||
Astronand
|
||||
Xtimhedae
|
||||
@@ -1,121 +1,41 @@
|
||||
local cp,c=component,computer;local b_addr=c.getBootAddress();local b_fs=cp.proxy(b_addr)
|
||||
local gpu=cp.list("gpu")() and cp.proxy(cp.list("gpu")())
|
||||
local e_rom=cp.list("eeprom")() and cp.proxy(cp.list("eeprom")())
|
||||
local screens={}
|
||||
for addr in cp.list("screen") do
|
||||
if gpu then
|
||||
gpu.bind(addr)
|
||||
local w,h=gpu.maxResolution()
|
||||
gpu.setResolution(w,h)
|
||||
gpu.fill(1,1,w,h," ")
|
||||
cp.proxy(addr).turnOn()
|
||||
screens[#screens+1] = {cx=1,cy=1,w=w,h=h,addr=addr}
|
||||
end
|
||||
end
|
||||
local function scroll(scr) gpu.copy(1,2,scr.w,scr.h-1,0,-1);gpu.fill(1,scr.h,scr.w,1," ") end
|
||||
local function write(t)
|
||||
if not gpu then return end
|
||||
for s=1, #screens do
|
||||
local scr=screens[s]
|
||||
gpu.bind(scr.addr)
|
||||
for i=1,#t do
|
||||
local char=t:sub(i,i)
|
||||
if char=="\n" then scr.cx=1;scr.cy=scr.cy+1
|
||||
elseif char=="\t" then scr.cx=scr.cx+(4-((scr.cx-1)%4))
|
||||
elseif char=="\b" then if scr.cx>1 then scr.cx=scr.cx-1;gpu.set(scr.cx,scr.cy," ") end
|
||||
else gpu.set(scr.cx,scr.cy,char);scr.cx=scr.cx+1 end
|
||||
if scr.cx>scr.w then scr.cx=1;scr.cy=scr.cy+1 end
|
||||
if scr.cy>scr.h then scroll(scr);scr.cy=scr.cy-1 end
|
||||
end
|
||||
end
|
||||
end
|
||||
local function throw(err)
|
||||
if gpu then
|
||||
gpu.setBackground(0x0000AA);
|
||||
gpu.setForeground(0xFFFFFF);
|
||||
for i=1, #screens do
|
||||
gpu.fill(1,1,screens[i].w,screens[i].h," ");
|
||||
screens[i].cx,screens[i].cy=1,1;
|
||||
end
|
||||
write("CRITICAL KERNEL ERROR:\n"..tostring(err))
|
||||
end
|
||||
while true do c.pullSignal() end
|
||||
end
|
||||
local ok,err=xpcall(function()
|
||||
local lua = {
|
||||
coroutine = true,
|
||||
debug = true,
|
||||
_HOST = true,
|
||||
_VERSION = true,
|
||||
assert = true,
|
||||
collectgarbage = true,
|
||||
error = true,
|
||||
gcinfo = true,
|
||||
getfenv = true,
|
||||
getmetatable = true,
|
||||
ipairs = true,
|
||||
__inext = true,
|
||||
load = true,
|
||||
math = true,
|
||||
next = true,
|
||||
pairs = true,
|
||||
pcall = true,
|
||||
rawequal = true,
|
||||
rawget = true,
|
||||
rawlen = true,
|
||||
rawset = true,
|
||||
select = true,
|
||||
setfenv = true,
|
||||
setmetatable = true,
|
||||
string = true,
|
||||
table = true,
|
||||
tonumber = true,
|
||||
tostring = true,
|
||||
type = true,
|
||||
xpcall = true,
|
||||
_G=true
|
||||
}
|
||||
|
||||
local apis={}
|
||||
local _l={coroutine=1,debug=1,_VERSION=1,assert=1,collectgarbage=1,error=1,getmetatable=1,ipairs=1,load=1,math=1,next=1,pairs=1,pcall=1,rawequal=1,rawget=1,rawlen=1,rawset=1,select=1,setmetatable=1,string=1,table=1,tonumber=1,tostring=1,type=1,xpcall=1,_G=1}
|
||||
for k,v in pairs(_G) do if not _l[k] then apis[k]=v;_G[k]=nil end end
|
||||
function sleep(t) local s=c.uptime()+t;while c.uptime()<s do c.pullSignal(s-c.uptime()) end end
|
||||
local function getFile(path)
|
||||
local h,err=b_fs.open(path,"r")
|
||||
if not h then throw("Cannot open: "..path) end
|
||||
local buf,chk="",""
|
||||
repeat chk=b_fs.read(h,math.huge);buf=buf..(chk or "") until not chk
|
||||
b_fs.close(h)
|
||||
return buf
|
||||
end
|
||||
local Kernel=load(getFile("/kernel.lua"),"@Kernel")
|
||||
local initFs=load(getFile("/oc/initdisks"),"@Init_disks")
|
||||
local fs=load(getFile("/initfs"),"@InitFs")
|
||||
if not Kernel then throw("Kernel load failed.") end
|
||||
if initFs then initFs=initFs(apis, b_fs, b_addr) end
|
||||
if fs then fs=fs() end
|
||||
local eQ={}
|
||||
local function qEv(e,...) table.insert(eQ,{e,...}) end
|
||||
local efi={
|
||||
getEpochMs=function() return math.floor(c.uptime()*1000) end,
|
||||
getUptime=function() return c.uptime()*1000 end,
|
||||
date=function() return tostring(apis.os.date()) end,
|
||||
getMachineEvent=function()
|
||||
if #eQ > 0 then
|
||||
return table.unpack(table.remove(eQ, 1))
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end,
|
||||
getEEPROM=function() return e_rom and e_rom.get() or "" end,
|
||||
setEEPROM=function(_,t) if e_rom then e_rom.set(t) end end,
|
||||
getNvram=function() return e_rom and e_rom.getData() or "" end,
|
||||
setNvram=function(_,t) if e_rom then e_rom.setData(t) end end,
|
||||
beep=function(freq, timeMs) c.beep(freq, timeMs / 1000) end,
|
||||
initfs=fs,
|
||||
disks=initFs,
|
||||
architecture="oc",
|
||||
firmware=apis,
|
||||
reboot=false,
|
||||
yield=function() coroutine.yield() end,
|
||||
screenCtl={
|
||||
print=function(_,t) write(tostring(t).."\n") end,
|
||||
printInline=function(_,t) write(tostring(t)) end,
|
||||
clear=function() if gpu then for i=1, #screens do local scr=screens[i];gpu.bind(scr.addr);gpu.fill(1,1,scr.w,scr.h," ");scr.cx,scr.cy=1,1 end end end,
|
||||
resetCursor=function() for i=1, #screens do local scr=screens[i];scr.cx,scr.cy=1,1 end end,
|
||||
setBackgroundColor=function(_,cl) if gpu then gpu.setBackground(cl) end end,
|
||||
setTextColor=function(_,cl) if gpu then gpu.setForeground(cl) end end,
|
||||
enable=function() end,
|
||||
disable=function() end
|
||||
}
|
||||
}
|
||||
local kCo=coroutine.create(function()
|
||||
local s,e=xpcall(Kernel,debug.traceback,efi)
|
||||
if not s and not efi.reboot then throw(e) end
|
||||
if efi.reboot then c.shutdown(true) else c.shutdown() end
|
||||
end)
|
||||
efi.screenCtl:print("Loaded in "..tostring(c.uptime()).."s")
|
||||
while true do
|
||||
local st,e=coroutine.resume(kCo)
|
||||
c.pushSignal("NoSleep")
|
||||
local ex=false
|
||||
while not ex do
|
||||
local ev={c.pullSignal(0)}
|
||||
if ev[1]=="key_down" then qEv("keyPressed",1,ev[3]);qEv("keyTyped",1,string.char(ev[3]))
|
||||
elseif ev[1]=="key_up" then qEv("keyReleased",1,ev[3])
|
||||
end
|
||||
if ev[1]=="NoSleep" then ex=true else qEv(table.unpack(ev)) end
|
||||
end
|
||||
if st=="error" or coroutine.status(kCo)=="dead" then
|
||||
if efi.reboot then c.shutdown(true) end
|
||||
throw("Kernel fault: "..tostring(e))
|
||||
for i,v in pairs(_G) do
|
||||
if not lua[i] or lua[i]==nil then
|
||||
apis[i]=v
|
||||
_G[i]=nil
|
||||
end
|
||||
end
|
||||
end,debug.traceback)
|
||||
if not ok then throw("Boot fault: "..err) end
|
||||
@@ -1,68 +1,18 @@
|
||||
local init
|
||||
do
|
||||
local component_invoke = component.invoke
|
||||
local function boot_invoke(address, method, ...)
|
||||
local result = table.pack(pcall(component_invoke, address, method, ...))
|
||||
if not result[1] then
|
||||
return nil, result[2]
|
||||
else
|
||||
return table.unpack(result, 2, result.n)
|
||||
checkArg=nil
|
||||
local oldcomputer=computer
|
||||
_G.computer=nil
|
||||
local os=os
|
||||
_G.os=nil
|
||||
|
||||
function component.wrap(address)
|
||||
local methods=oldcomponent.methods(address)
|
||||
local object={}
|
||||
for _,method in ipairs(methods) do
|
||||
object[method]=function(_,...)
|
||||
return oldcomponent.invoke(address,method,...)
|
||||
end
|
||||
end
|
||||
return object
|
||||
end
|
||||
|
||||
-- backwards compatibility, may remove later
|
||||
local eeprom = component.list("eeprom")()
|
||||
computer.getBootAddress = function()
|
||||
return boot_invoke(eeprom, "getData")
|
||||
end
|
||||
computer.setBootAddress = function(address)
|
||||
return boot_invoke(eeprom, "setData", address)
|
||||
end
|
||||
|
||||
do
|
||||
local screen = component.list("screen")()
|
||||
local gpu = component.list("gpu")()
|
||||
if gpu and screen then
|
||||
boot_invoke(gpu, "bind", screen)
|
||||
end
|
||||
end
|
||||
local function tryLoadFrom(address)
|
||||
local handle, reason = boot_invoke(address, "open", "/oc/boot.lua")
|
||||
if not handle then
|
||||
return nil, reason
|
||||
end
|
||||
local buffer = ""
|
||||
repeat
|
||||
local data, reason = boot_invoke(address, "read", handle, math.maxinteger or math.huge)
|
||||
if not data and reason then
|
||||
return nil, reason
|
||||
end
|
||||
buffer = buffer .. (data or "")
|
||||
until not data
|
||||
boot_invoke(address, "close", handle)
|
||||
return load(buffer, "=init")
|
||||
end
|
||||
local reason
|
||||
if computer.getBootAddress() then
|
||||
init, reason = tryLoadFrom(computer.getBootAddress())
|
||||
end
|
||||
if not init then
|
||||
computer.setBootAddress()
|
||||
for address in component.list("filesystem") do
|
||||
init, reason = tryLoadFrom(address)
|
||||
if init then
|
||||
computer.setBootAddress(address)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if not init then
|
||||
error("no bootable medium found" .. (reason and (": " .. tostring(reason)) or ""), 0)
|
||||
end
|
||||
end
|
||||
local ok, err = xpcall(init,debug.traceback)
|
||||
if not ok then
|
||||
error(err)
|
||||
else
|
||||
return err
|
||||
end
|
||||
local
|
||||
@@ -1,136 +0,0 @@
|
||||
local args = {...}
|
||||
local apis = args[1]
|
||||
local bootdrive = args[2]
|
||||
local bootaddr = args[3]
|
||||
local disks = {}
|
||||
local internal = {}
|
||||
|
||||
local function createDisk(id, hw)
|
||||
local disk = {
|
||||
address = id,
|
||||
isReadOnly = function() return hw.isReadOnly() end
|
||||
}
|
||||
|
||||
function disk:spaceUsed() return hw.spaceUsed() end
|
||||
function disk:spaceTotal() return hw.spaceTotal() end
|
||||
|
||||
function disk:list(path)
|
||||
if not hw.exists(path) or not hw.isDirectory(path) then
|
||||
return nil, "not directory"
|
||||
end
|
||||
return hw.list(path)
|
||||
end
|
||||
|
||||
function disk:fileExists(path)
|
||||
return hw.exists(path) and not hw.isDirectory(path)
|
||||
end
|
||||
|
||||
function disk:directoryExists(path)
|
||||
return hw.exists(path) and hw.isDirectory(path)
|
||||
end
|
||||
|
||||
function disk:type(path)
|
||||
if not hw.exists(path) then
|
||||
return nil
|
||||
elseif hw.isDirectory(path) then
|
||||
return "directory"
|
||||
else
|
||||
return "file"
|
||||
end
|
||||
end
|
||||
|
||||
function disk:makeDirectory(path)
|
||||
hw.makeDirectory(path)
|
||||
end
|
||||
|
||||
function disk:remove(path)
|
||||
if hw.exists(path) then hw.remove(path) end
|
||||
end
|
||||
|
||||
function disk:setLabel(label) hw.setLabel(label) end
|
||||
function disk:getLabel() return hw.getLabel() end
|
||||
|
||||
function disk:attributes(path)
|
||||
return {
|
||||
size = hw.size(path),
|
||||
isDir = hw.isDirectory(path),
|
||||
isReadOnly = hw.isReadOnly(),
|
||||
modified = hw.lastModified(path),
|
||||
created = hw.lastModified(path)
|
||||
}
|
||||
end
|
||||
|
||||
function disk:open(path, mode)
|
||||
local fd = hw.open(path, mode)
|
||||
|
||||
if not fd then
|
||||
local dir = path:match("^(.*)/[^/]+$")
|
||||
|
||||
if dir and not hw.exists(dir) then
|
||||
local ok, err = hw.makeDirectory(dir)
|
||||
if not ok then
|
||||
return nil, err or "could not create parent directory"
|
||||
end
|
||||
end
|
||||
|
||||
fd = hw.open(path, mode)
|
||||
if not fd then
|
||||
return nil, "file not found or access denied"
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
read = function(num) return hw.read(fd, num) end,
|
||||
|
||||
readAll = function()
|
||||
local data = {}
|
||||
while true do
|
||||
local chunk = hw.read(fd, math.huge)
|
||||
if not chunk then break end
|
||||
data[#data + 1] = chunk
|
||||
end
|
||||
return table.concat(data)
|
||||
end,
|
||||
|
||||
write = function(data) return hw.write(fd, data) end,
|
||||
seek = function(whence, offset)
|
||||
return hw.seek(fd, whence, offset)
|
||||
end,
|
||||
|
||||
flush = function()
|
||||
hw.close(fd)
|
||||
fd = hw.open(path, mode)
|
||||
end,
|
||||
|
||||
close = function()
|
||||
hw.close(fd)
|
||||
fd = nil
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
return disk
|
||||
end
|
||||
|
||||
internal["$"] = createDisk("$", bootdrive)
|
||||
|
||||
local function refresh()
|
||||
disks = {}
|
||||
for addr in apis.component.list("filesystem") do
|
||||
if addr ~= bootaddr then
|
||||
disks[addr] = createDisk(addr, apis.component.proxy(addr))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function iter()
|
||||
refresh()
|
||||
local combined = {}
|
||||
|
||||
for id, obj in pairs(internal) do combined[id] = obj end
|
||||
for id, obj in pairs(disks) do combined[id] = obj end
|
||||
|
||||
return pairs(combined)
|
||||
end
|
||||
|
||||
return {refresh = refresh, list = iter}
|
||||
@@ -0,0 +1 @@
|
||||
local fs={}
|
||||
@@ -1,15 +0,0 @@
|
||||
--:Minify:--
|
||||
local kernel=...
|
||||
kernel.oc={}
|
||||
kernel.oc.component=kernel.apis.component
|
||||
kernel.oc.computer=kernel.apis.computer
|
||||
|
||||
kernel.log("Installed components:")
|
||||
for addr, typ in kernel.oc.component.list() do
|
||||
local dev=kernel.oc.component.proxy(addr)
|
||||
local tier=""
|
||||
if dev.getTier then
|
||||
tier=dev.getTier()
|
||||
end
|
||||
kernel.log(" "..addr.." : "..typ..tier)
|
||||
end
|
||||
@@ -1,23 +0,0 @@
|
||||
--:Minify:--
|
||||
local kernel=...
|
||||
local component=kernel.oc.component
|
||||
|
||||
local function wrap(p)
|
||||
return function(op, mode)
|
||||
if op=="type" then
|
||||
return "device"
|
||||
elseif op=="open" then
|
||||
if kernel.uid~=0 then error("EACCES") end
|
||||
return component.proxy(p)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for addr, typ in kernel.oc.component.list() do
|
||||
local obj=wrap(addr)
|
||||
kernel.devfs.data["raw"][addr]=obj
|
||||
local typefolder=kernel.devfs.data["raw"]["by-type"][typ]
|
||||
if not typefolder then typefolder={} end
|
||||
typefolder[tostring(#table.keys(typefolder)+1)] = obj
|
||||
kernel.devfs.data["raw"]["by-type"][typ]=typefolder
|
||||
end
|
||||
@@ -1,177 +0,0 @@
|
||||
-- OpenComputers TTY driver
|
||||
|
||||
local kernel = ...
|
||||
local component = kernel.oc.component
|
||||
local computer = kernel.oc.computer
|
||||
|
||||
local plt = {
|
||||
0x000000, 0x000040, 0x000080, 0x0000C0, 0x0000FF,
|
||||
0x002400, 0x002440, 0x002480, 0x0024C0, 0x0024FF,
|
||||
0x004900, 0x004940, 0x004980, 0x0049C0, 0x0049FF,
|
||||
0x006D00, 0x006D40, 0x006D80, 0x006DC0, 0x006DFF,
|
||||
0x009200, 0x009240, 0x009280, 0x0092C0, 0x0092FF,
|
||||
0x00B600, 0x00B640, 0x00B680, 0x00B6C0, 0x00B6FF,
|
||||
0x00DB00, 0x00DB40, 0x00DB80, 0x00DBC0, 0x00DBFF,
|
||||
0x00FF00, 0x00FF40, 0x00FF80, 0x00FFC0, 0x00FFFF,
|
||||
|
||||
0x330000, 0x330040, 0x330080, 0x3300C0, 0x3300FF,
|
||||
0x332400, 0x332440, 0x332480, 0x3324C0, 0x3324FF,
|
||||
0x334900, 0x334940, 0x334980, 0x3349C0, 0x3349FF,
|
||||
0x336D00, 0x336D40, 0x336D80, 0x336DC0, 0x336DFF,
|
||||
0x339200, 0x339240, 0x339280, 0x3392C0, 0x3392FF,
|
||||
0x33B600, 0x33B640, 0x33B680, 0x33B6C0, 0x33B6FF,
|
||||
0x33DB00, 0x33DB40, 0x33DB80, 0x33DBC0, 0x33DBFF,
|
||||
0x33FF00, 0x33FF40, 0x33FF80, 0x33FFC0, 0x33FFFF,
|
||||
|
||||
0x660000, 0x660040, 0x660080, 0x6600C0, 0x6600FF,
|
||||
0x662400, 0x662440, 0x662480, 0x6624C0, 0x6624FF,
|
||||
0x664900, 0x664940, 0x664980, 0x6649C0, 0x6649FF,
|
||||
0x666D00, 0x666D40, 0x666D80, 0x666DC0, 0x666DFF,
|
||||
0x669200, 0x669240, 0x669280, 0x6692C0, 0x6692FF,
|
||||
0x66B600, 0x66B640, 0x66B680, 0x66B6C0, 0x66B6FF,
|
||||
0x66DB00, 0x66DB40, 0x66DB80, 0x66DBC0, 0x66DBFF,
|
||||
0x66FF00, 0x66FF40, 0x66FF80, 0x66FFC0, 0x66FFFF,
|
||||
|
||||
0x990000, 0x990040, 0x990080, 0x9900C0, 0x9900FF,
|
||||
0x992400, 0x992440, 0x992480, 0x9924C0, 0x9924FF,
|
||||
0x994900, 0x994940, 0x994980, 0x9949C0, 0x9949FF,
|
||||
0x996D00, 0x996D40, 0x996D80, 0x996DC0, 0x996DFF,
|
||||
0x999200, 0x999240, 0x999280, 0x9992C0, 0x9992FF,
|
||||
0x99B600, 0x99B640, 0x99B680, 0x99B6C0, 0x99B6FF,
|
||||
0x99DB00, 0x99DB40, 0x99DB80, 0x99DBC0, 0x99DBFF,
|
||||
0x99FF00, 0x99FF40, 0x99FF80, 0x99FFC0, 0x99FFFF,
|
||||
|
||||
0xCC0000, 0xCC0040, 0xCC0080, 0xCC00C0, 0xCC00FF,
|
||||
0xCC2400, 0xCC2440, 0xCC2480, 0xCC24C0, 0xCC24FF,
|
||||
0xCC4900, 0xCC4940, 0xCC4980, 0xCC49C0, 0xCC49FF,
|
||||
0xCC6D00, 0xCC6D40, 0xCC6D80, 0xCC6DC0, 0xCC6DFF,
|
||||
0xCC9200, 0xCC9240, 0xCC9280, 0xCC92C0, 0xCC92FF,
|
||||
0xCCB600, 0xCCB640, 0xCCB680, 0xCCB6C0, 0xCCB6FF,
|
||||
0xCCDB00, 0xCCDB40, 0xCCDB80, 0xCCDBC0, 0xCCDBFF,
|
||||
0xCCFF00, 0xCCFF40, 0xCCFF80, 0xCCFFC0, 0xCCFFFF,
|
||||
|
||||
0xFF0000, 0xFF0040, 0xFF0080, 0xFF00C0, 0xFF00FF,
|
||||
0xFF2400, 0xFF2440, 0xFF2480, 0xFF24C0, 0xFF24FF,
|
||||
0xFF4900, 0xFF4940, 0xFF4980, 0xFF49C0, 0xFF49FF,
|
||||
0xFF6D00, 0xFF6D40, 0xFF6D80, 0xFF6DC0, 0xFF6DFF,
|
||||
0xFF9200, 0xFF9240, 0xFF9280, 0xFF92C0, 0xFF92FF,
|
||||
0xFFB600, 0xFFB640, 0xFFB680, 0xFFB6C0, 0xFFB6FF,
|
||||
0xFFDB00, 0xFFDB40, 0xFFDB80, 0xFFDBC0, 0xFFDBFF,
|
||||
0xFFFF00, 0xFFFF40, 0xFFFF80, 0xFFFFC0, 0xFFFFFF,
|
||||
|
||||
0x000000, 0x0F0F0F, 0x1E1E1E, 0x2D2D2D,
|
||||
0x3C3C3C, 0x4B4B4B, 0x5A5A5A, 0x696969,
|
||||
0x787878, 0x878787, 0x969696, 0xA5A5A5,
|
||||
0xB4B4B4, 0xC3C3C3, 0xD2D2D2, 0xE1E1E1
|
||||
}
|
||||
|
||||
local gpus,screens = {},{}
|
||||
|
||||
for addr, typ in component.list("gpu") do
|
||||
if typ == "gpu" then
|
||||
gpus[#gpus+1]=component.proxy(addr)
|
||||
end
|
||||
end
|
||||
|
||||
if #gpus>0 then
|
||||
for addr, typ in component.list("screen") do
|
||||
if typ == "screen" then
|
||||
gpus[1].bind(addr)
|
||||
local w,h = gpus[1].maxResolution()
|
||||
gpus[1].setResolution(w,h)
|
||||
screens[addr]={cx=1,cy=1,w=w,h=h,addr=addr,fg=0,bg=0,gpu=nil}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local scrnum = 0
|
||||
for i,v in pairs(screens) do
|
||||
scrnum=scrnum+1
|
||||
end
|
||||
|
||||
kernel.log("initialized "..tostring(#gpus).." gpus and "..tostring(scrnum).." screens")
|
||||
|
||||
local binds,newid={},0
|
||||
local curaddr=""
|
||||
local function scroll(scr, gpu) gpu.copy(1,2,scr.w,scr.h-1,0,-1);gpu.fill(1,scr.h,scr.w,1," ") end
|
||||
local function write(text, addr)
|
||||
local g=gpus[1]
|
||||
local scr=screens[addr]
|
||||
if not scr then error("NODEV") end
|
||||
if curaddr~=addr then g.bind(addr); g.setForeground(scr.fg); g.setBackground(scr.bg) end
|
||||
for i=1,#text do
|
||||
local char=text:sub(i,i)
|
||||
if char=="\n" then scr.cx=1;scr.cy=scr.cy+1
|
||||
elseif char=="\t" then scr.cx=scr.cx+(4-((scr.cx-1)%4))
|
||||
elseif char=="\b" then if scr.cx>1 then scr.cx=scr.cx-1;g.set(scr.cx,scr.cy," ") end
|
||||
else g.set(scr.cx,scr.cy,char);scr.cx=scr.cx+1 end
|
||||
if scr.cx>scr.w then scr.cx=1;scr.cy=scr.cy+1 end
|
||||
if scr.cy>scr.h then scroll(scr, g);scr.cy=scr.cy-1 end
|
||||
end
|
||||
end
|
||||
|
||||
local function newtty(addr)
|
||||
newid=newid+1
|
||||
kernel.devfs.data["tty"][tostring(newid)]=function(op, mode)
|
||||
if op=="type" then
|
||||
return "Terminal"
|
||||
elseif op=="open" then
|
||||
local h = {
|
||||
read=function(amount) end,
|
||||
write=function(content)
|
||||
write(content, addr)
|
||||
end,
|
||||
size=function()
|
||||
return screens[addr].w, screens[addr].h
|
||||
end,
|
||||
clear=function()
|
||||
local g=gpus[1]
|
||||
local scr=screens[addr]
|
||||
if addr~=curaddr then g.bind(addr) end
|
||||
g.fill(1,1,scr.w,scr.h," ");
|
||||
scr.cx,scr.cy=1,1
|
||||
end,
|
||||
gpos=function()
|
||||
return screens[addr].cx, screens[addr].cy
|
||||
end,
|
||||
spos=function(x,y)
|
||||
if not tonumber(x) or not tonumber(y) then error("Invailid arg") end
|
||||
screens[addr].cx, screens[addr].cy = x,y
|
||||
end,
|
||||
sfgc=function(c)
|
||||
screens[addr].fg=c
|
||||
end,
|
||||
sbgc=function(c)
|
||||
screens[addr].bg=c
|
||||
end,
|
||||
gfgc=function()
|
||||
return screens[addr].fg
|
||||
end,
|
||||
gbgc=function()
|
||||
return screens[addr].bg
|
||||
end,
|
||||
isvirt=function()
|
||||
return false
|
||||
end,
|
||||
gplt=function()
|
||||
return plt
|
||||
end
|
||||
}
|
||||
if mode=="rw" then
|
||||
return h
|
||||
elseif mode=="r" then
|
||||
h["write"]=nil
|
||||
return h
|
||||
elseif mode=="w" then
|
||||
h["read"]=nil
|
||||
return h
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if #gpus>=1 and scrnum>=1 then
|
||||
for addr,obj in pairs(screens) do
|
||||
newtty(addr)
|
||||
end
|
||||
end
|
||||
@@ -1,113 +0,0 @@
|
||||
--:Minify:--
|
||||
local kernel=...
|
||||
kernel.oc.keyboards={}
|
||||
local kbs=kernel.oc.keyboards
|
||||
|
||||
local kbidx=0
|
||||
local keyboard = {}
|
||||
|
||||
keyboard.keys = {
|
||||
back = 0x0E, -- backspace
|
||||
delete = 0xD3,
|
||||
down = 0xD0,
|
||||
enter = 0x1C,
|
||||
home = 0xC7,
|
||||
lcontrol = 0x1D,
|
||||
left = 0xCB,
|
||||
lmenu = 0x38, -- left Alt
|
||||
lshift = 0x2A,
|
||||
pageDown = 0xD1,
|
||||
rcontrol = 0x9D,
|
||||
right = 0xCD,
|
||||
rmenu = 0xB8, -- right Alt
|
||||
rshift = 0x36,
|
||||
space = 0x39,
|
||||
tab = 0x0F,
|
||||
up = 0xC8,
|
||||
["end"] = 0xCF,
|
||||
numpadenter = 0x9C,
|
||||
}
|
||||
kernel.oc.keys=keyboard.keys
|
||||
|
||||
for i=0, 255 do
|
||||
kernel.oc.keys[string.char(i)]=i
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
function keyboard.isAltDown(addr)
|
||||
return kbs[addr].pressedCodes[keyboard.keys.lmenu] or kbs[addr].pressedCodes[keyboard.keys.rmenu]
|
||||
end
|
||||
|
||||
function keyboard.isControl(char)
|
||||
return type(char) == "number" and (char < 0x20 or (char >= 0x7F and char <= 0x9F))
|
||||
end
|
||||
|
||||
function keyboard.isControlDown(addr)
|
||||
return kbs[addr].pressedCodes[keyboard.keys.lcontrol] or kbs[addr].pressedCodes[keyboard.keys.rcontrol]
|
||||
end
|
||||
|
||||
function keyboard.isKeyDown(addr,charOrCode)
|
||||
if type(charOrCode) == "string" then
|
||||
return kbs[addr].pressedChars[utf8 and utf8.codepoint(charOrCode) or charOrCode:byte()]
|
||||
elseif type(charOrCode) == "number" then
|
||||
return kbs[addr].pressedCodes[charOrCode]
|
||||
end
|
||||
end
|
||||
|
||||
function keyboard.isShiftDown(addr)
|
||||
return kbs[addr].pressedCodes[keyboard.keys.lshift] or kbs[addr].pressedCodes[keyboard.keys.rshift]
|
||||
end
|
||||
kernel.oc.keyboard=keyboard
|
||||
|
||||
local function serializeBool(bool)
|
||||
if bool then
|
||||
return "T"
|
||||
else
|
||||
return "F"
|
||||
end
|
||||
end
|
||||
|
||||
for addr, typ in kernel.oc.component.list("keyboard") do
|
||||
if typ=="keyboard" then
|
||||
kbidx=kbidx+1
|
||||
kbs[addr]={pressedChars = {}, pressedCodes = {}, events=kernel.newFifo()}
|
||||
kernel.devfs.data["input"]["keyboard"..tostring(kbidx)]=function(op,mode)
|
||||
if op=="type" then
|
||||
return "Keyboard"
|
||||
elseif op=="open" then
|
||||
local h = {
|
||||
read=function(amount)
|
||||
local rv=""
|
||||
for i=1, amount or 1 do
|
||||
local event = {kernel.oc.keyboards[addr].events.pop()}
|
||||
if event[1] then
|
||||
rv=rv..event[1]
|
||||
end
|
||||
end
|
||||
if rv=="" then rv=nil end
|
||||
return rv
|
||||
end,
|
||||
write=function(content)
|
||||
end,
|
||||
gctrl=function()
|
||||
return serializeBool(keyboard.isControlDown(addr))..";"..serializeBool(keyboard.isAltDown(addr))
|
||||
end,
|
||||
isKeyDown=function(char)
|
||||
return keyboard.isKeyDown(addr,char)
|
||||
end
|
||||
}
|
||||
if mode=="rw" then
|
||||
return h
|
||||
elseif mode=="r" then
|
||||
h["write"]=nil
|
||||
return h
|
||||
elseif mode=="w" then
|
||||
h["read"]=nil
|
||||
return h
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
--:Minify:--
|
||||
local kernel=...
|
||||
local keys=kernel.oc.keys
|
||||
|
||||
kernel.processes.ocdaemon = function()
|
||||
|
||||
local timeout = false
|
||||
|
||||
kernel.log("OC daemon started")
|
||||
|
||||
local ctrlKeyMap = {
|
||||
[keys.a]=1, [keys.b]=2, [keys.c]=3,
|
||||
[keys.d]=4, [keys.e]=5, [keys.f]=6,
|
||||
[keys.g]=7, [keys.h]=8, [keys.i]=9,
|
||||
[keys.j]=10, [keys.k]=11, [keys.l]=12,
|
||||
[keys.m]=13, [keys.n]=14, [keys.o]=15,
|
||||
[keys.p]=16, [keys.q]=17, [keys.r]=18,
|
||||
[keys.s]=19, [keys.t]=20, [keys.u]=21,
|
||||
[keys.v]=22, [keys.w]=23, [keys.x]=24,
|
||||
[keys.y]=25, [keys.z]=26,
|
||||
}
|
||||
|
||||
local specialKeyMap = {
|
||||
[keys.up] = "\27[A",
|
||||
[keys.down] = "\27[B",
|
||||
[keys.right] = "\27[C",
|
||||
[keys.left] = "\27[D",
|
||||
[keys.home] = "\27[H",
|
||||
[keys["end"]] = "\27[F",
|
||||
--[keys.pageUp] = "\27[5~",
|
||||
--[keys.pageDown] = "\27[6~",
|
||||
[keys.delete] = "\27[3~",
|
||||
[keys.enter] = "\n",
|
||||
[keys.back] = "\b",
|
||||
[keys.tab] = "\t",
|
||||
}
|
||||
|
||||
while true do
|
||||
|
||||
local event = {kernel.EFI.getMachineEvent()}
|
||||
|
||||
if event[1] then
|
||||
|
||||
local eventType = event[1]
|
||||
local addr = event[2]
|
||||
local char = event[3]
|
||||
local keyCode = event[4]
|
||||
|
||||
if eventType == "key_down" then
|
||||
|
||||
local keyboard = kernel.oc.keyboards[addr]
|
||||
|
||||
if keyboard.ctrl then
|
||||
|
||||
local ctrlByte = ctrlKeyMap[keyCode]
|
||||
|
||||
if ctrlByte then
|
||||
if ctrlByte == 3 then
|
||||
|
||||
for _, task in ipairs(syscall.getTasks()) do
|
||||
syscall.sigsend(task, 1)
|
||||
end
|
||||
|
||||
else
|
||||
keyboard.events.push(string.char(ctrlByte))
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
local special = specialKeyMap[keyCode]
|
||||
|
||||
if special then
|
||||
keyboard.events.push(special)
|
||||
|
||||
elseif char and char > 0 then
|
||||
keyboard.events.push(kernel.apis.unicode.char(char))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
elseif eventType == "key_up" then
|
||||
|
||||
end
|
||||
|
||||
timeout = false
|
||||
|
||||
else
|
||||
timeout = true
|
||||
end
|
||||
|
||||
if timeout then
|
||||
sleep(0.05)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
kernel.log("OC daemon queued for execution")
|
||||
@@ -1,150 +0,0 @@
|
||||
--:Minify:--
|
||||
local kernel=...
|
||||
local alpha = 0.85
|
||||
local C_target = 0.01
|
||||
local Tmin = 0.0005
|
||||
local Tmax = 0.5
|
||||
local lambda_budget = 0.08
|
||||
local lambda_clamp = 0.03
|
||||
local lambda_var = 0.02
|
||||
local k_min = 0.5
|
||||
local k_max = 0.5
|
||||
local B = 0.01
|
||||
local nextyield=0
|
||||
|
||||
function kernel.main()
|
||||
kernel.log("Starting main loop...")
|
||||
kernel.saveLog()
|
||||
local stopLog=5
|
||||
local logTasks=100
|
||||
|
||||
while not kernel.exitMain do
|
||||
if kernel.config.logTasks then
|
||||
if logTasks<0 then
|
||||
kernel.log("Active Tasks:")
|
||||
for i,v in pairs(kernel.tasks) do
|
||||
kernel.log(v.name.." : "..v.status.." : "..tostring(v.pid).." : "..tostring(v.exit))
|
||||
end
|
||||
kernel.log("[END BLOCK]")
|
||||
logTasks=100
|
||||
end
|
||||
logTasks=logTasks-1
|
||||
end
|
||||
local N = 0
|
||||
local Tmin_hit = 0
|
||||
local Tmax_hit = 0
|
||||
local totalTaskTime = 0
|
||||
local taskTimes = {}
|
||||
|
||||
for pid, task in pairs(kernel.tasks) do
|
||||
if kernel.exitMain then break end
|
||||
|
||||
for _,list in ipairs(kernel.perTaskHooks) do
|
||||
for id,hook in ipairs(list) do
|
||||
local ok,err = xpcall(hook, debug.traceback, task, pid)
|
||||
if not ok then
|
||||
kernel.log("[MAIN HOOK ERR]: "..err, "ERROR", 0xFF0000)
|
||||
list[id]=nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if task.status == "R" then
|
||||
N = N + 1
|
||||
task.timeSlice = math.min(Tmax, math.max(Tmin, B / (N ^ alpha)))
|
||||
if task.status == "R" then
|
||||
local startTime = kernel.EFI:getEpochMs()
|
||||
local ret
|
||||
if stopLog > 0 then
|
||||
kernel.log("Running task " .. tostring(task.pid) .. " (" .. task.name .. ") with time slice " .. string.format("%.3f", task.timeSlice) .. "s", "DBUG", 0x00FFFF)
|
||||
end
|
||||
|
||||
ret = { coroutine.resume(task.coro, table.unpack(task.syscallReturn)) }
|
||||
|
||||
|
||||
local elapsed = kernel.EFI:getEpochMs() - startTime
|
||||
task.lastTime = elapsed
|
||||
task.totalTime = (task.totalTime or 0) + elapsed
|
||||
task.numRuns = (task.numRuns or 0) + 1
|
||||
|
||||
taskTimes[#taskTimes+1] = elapsed
|
||||
totalTaskTime = totalTaskTime + elapsed
|
||||
|
||||
if elapsed <= Tmin then Tmin_hit = Tmin_hit + 1 end
|
||||
if elapsed >= Tmax then Tmax_hit = Tmax_hit + 1 end
|
||||
|
||||
if ret[1] == "error" or ret[1] == false then
|
||||
kernel.log("processHandlerException: " .. tostring(ret[2]), "ERROR", 0xFF0000)
|
||||
task.status = "Z"
|
||||
task.exit = "processHandlerException: " .. tostring(ret[2])
|
||||
|
||||
elseif ret[1] == "timeout" then
|
||||
task.ivs = task.ivs + 1
|
||||
task.syscallReturn = {}
|
||||
|
||||
elseif ret[1] == "success" or ret[1] == true then
|
||||
task.vs = task.vs + 1
|
||||
|
||||
if ret[2] == "syscall" then
|
||||
local scname = ret[3]
|
||||
if kernel.syscalls[scname] then
|
||||
if kernel.config.debugSyscalls then
|
||||
kernel.log("Task " .. task.pid .. " syscall: " .. scname, "DBUG", 0x00FFFF)
|
||||
for i = 4, #ret do
|
||||
kernel.log(" inval[" .. (i-3) .. "] = " .. tostring(ret[i]), "DBUG", 0x00FFFF)
|
||||
end
|
||||
end
|
||||
|
||||
local sysret = { xpcall(kernel.syscalls[scname], debug.traceback, table.unpack(ret, 4)) }
|
||||
|
||||
if kernel.config.debugSyscalls then
|
||||
if not sysret[1] then
|
||||
kernel.log("Task " .. task.pid .. " syscall " .. scname .. " failed: " .. tostring(sysret[2]), "ERROR", 0xFF0000)
|
||||
else
|
||||
kernel.log("Task " .. task.pid .. " syscall " .. scname .. " ok, " .. (#sysret-1) .. " retvals", "DBUG", 0x00FFFF)
|
||||
for i = 2, #sysret do
|
||||
local v = type(sysret[i]) == "table" and table.serialize(sysret[i]) or tostring(sysret[i])
|
||||
kernel.log(" retval[" .. (i-1) .. "] = " .. v, "DBUG", 0x00FFFF)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not sysret[1] then
|
||||
task.syscallReturn = { false, sysret[2] }
|
||||
else
|
||||
task.syscallReturn = { true, table.unpack(sysret, 2) }
|
||||
end
|
||||
else
|
||||
task.syscallReturn = { false, "Unknown syscall: " .. tostring(scname) }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if kernel.EFI:getEpochMs()>=nextyield then
|
||||
kernel.EFI:yield()
|
||||
nextyield=kernel.EFI:getEpochMs()+5000
|
||||
end
|
||||
end
|
||||
|
||||
local T_prev_avg = (N > 0) and (totalTaskTime / N) or 0
|
||||
local T_prev_var = 0
|
||||
for _, t in ipairs(taskTimes) do
|
||||
T_prev_var = T_prev_var + (t - T_prev_avg) ^ 2
|
||||
end
|
||||
if N > 0 then T_prev_var = T_prev_var / N end
|
||||
|
||||
if N > 0 then
|
||||
local f_clamp = k_min * (Tmin_hit / N) - k_max * (Tmax_hit / N)
|
||||
local B_budget = (C_target * (N ^ (alpha - 1))) / math.max(T_prev_avg, 1e-8)
|
||||
B = B + lambda_budget * (B_budget - B) + lambda_clamp * f_clamp - lambda_var * T_prev_var
|
||||
end
|
||||
|
||||
kernel.hpv.reapDeadTasks()
|
||||
if stopLog > 0 then
|
||||
kernel.log("Executed " .. N .. " tasks, avg time: " .. string.format("%.2f", T_prev_avg) .. "ms, var: " .. string.format("%.2f", T_prev_var) .. ", B: " .. string.format("%.5f", B))
|
||||
stopLog = stopLog - 1
|
||||
kernel.saveLog()
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1 +1 @@
|
||||
firmware for Opencomputers mod
|
||||
firmware for Opencomputers
|
||||
@@ -1 +1 @@
|
||||
1.0.0
|
||||
0.1.0
|
||||
@@ -1,4 +1,4 @@
|
||||
U $;/boot/
|
||||
V devfs0000;/dev/
|
||||
V tmpfs0000;/tmp/
|
||||
V procfs0000;/proc/
|
||||
U $;/
|
||||
U devfs0000;/dev/
|
||||
U tmpfs0000;/tmp/
|
||||
U procfs0000;/proc/
|
||||
|
||||
@@ -77,7 +77,7 @@ end
|
||||
function fs.load(path) return load(fs.readAllText(path), path) end
|
||||
|
||||
function fs.mount(disk, mountPoint)
|
||||
if not disks[disk] then error("NODISK : "..disk) end
|
||||
if not disks[disk] then return end
|
||||
mounts[mountPoint] = disk
|
||||
end
|
||||
|
||||
|
||||
@@ -68,7 +68,6 @@ function kernel.PANIC(msg)
|
||||
kernel.exitMain = true
|
||||
end
|
||||
while true do
|
||||
EFI:yield()
|
||||
local event={EFI:getMachineEvent()}
|
||||
if event[1]=="keyPressed" then
|
||||
break
|
||||
@@ -99,7 +98,7 @@ kernel.disks={}
|
||||
for _,v in disks.list() do
|
||||
kernel.disks[v.address] = v
|
||||
end
|
||||
ifs.mount("$", "/boot/")
|
||||
ifs.mount("$", "/")
|
||||
|
||||
local fstab=ifs.readAllText("/boot/fstab")
|
||||
local split = function(str, delim, maxResultCountOrNil)
|
||||
@@ -139,10 +138,8 @@ end
|
||||
kernel.config = config
|
||||
|
||||
local skip=false
|
||||
local mounted={}
|
||||
local root=false
|
||||
for i,v in ipairs(split(fstab,"\n")) do
|
||||
if v:sub(1,1)=="U" or v:sub(1,1)=="F" then
|
||||
if v:sub(1,1)=="U" then
|
||||
local id=""
|
||||
for i=3,#v do
|
||||
if v:sub(i,i)==";" then
|
||||
@@ -152,43 +149,12 @@ for i,v in ipairs(split(fstab,"\n")) do
|
||||
end
|
||||
if not skip then
|
||||
local path=v:sub(#id+4)
|
||||
if path=="/" then root=true end
|
||||
mounted[id]=true
|
||||
ifs.mount(id,path)
|
||||
else
|
||||
skip=false
|
||||
end
|
||||
end
|
||||
end
|
||||
if not root then
|
||||
kernel.log("No rootdisk found, prompting user...", "WARN", 0xFF8800)
|
||||
screen:setTextColor(0xDDDDDD)
|
||||
screen:print("Disk to mount to /:")
|
||||
local idx=1
|
||||
local canadates={}
|
||||
for i,v in pairs(kernel.disks) do
|
||||
if not mounted[i] then
|
||||
screen:print("("..idx..") : "..i)
|
||||
canadates[idx]=i
|
||||
idx=idx+1
|
||||
end
|
||||
end
|
||||
while true do
|
||||
EFI:yield()
|
||||
local event={EFI:getMachineEvent()}
|
||||
if event[1]=="keyTyped" then
|
||||
if tonumber(event[3]) then
|
||||
if canadates[tonumber(event[3])] then
|
||||
ifs.writeAllText("/boot/fstab", "U "..canadates[tonumber(event[3])]..";/\n"..fstab)
|
||||
fstab="U "..canadates[tonumber(event[3])]..";/\n"..fstab
|
||||
ifs.mount(canadates[tonumber(event[3])], "/")
|
||||
break
|
||||
end
|
||||
end
|
||||
screen:print(event[1], event[3])
|
||||
end
|
||||
end
|
||||
end
|
||||
kernel.log("Disks initialized")
|
||||
|
||||
function kernel.saveLog()
|
||||
@@ -355,26 +321,6 @@ kernel.processes={}
|
||||
kernel.fstab=fstab
|
||||
kernel.denied={}
|
||||
kernel.loadingModule="kernel"
|
||||
kernel.perTaskHooks={}
|
||||
kernel.mainHooks={}
|
||||
kernel.runhooks={}
|
||||
|
||||
-- args {taskobj}
|
||||
function kernel.execPerTask(func, prior)
|
||||
if not kernel.perTaskHooks[prior] then kernel.perTaskHooks[prior]={} end
|
||||
kernel.perTaskHooks[prior][#kernel.perTaskHooks[prior]+1] = func
|
||||
return #kernel.perTaskHooks[prior]
|
||||
end
|
||||
|
||||
function kernel.execOnMain(func)
|
||||
kernel.mainHooks[#kernel.mainHooks+1] = func
|
||||
return #kernel.mainHooks
|
||||
end
|
||||
|
||||
function kernel.runWhenLoaded(func)
|
||||
kernel.runhooks[#kernel.runhooks+1] = func
|
||||
return #kernel.runhooks
|
||||
end
|
||||
|
||||
kernel.kernelTask = {
|
||||
name="kernel",
|
||||
@@ -483,17 +429,11 @@ for _,p in ipairs(modules) do
|
||||
end
|
||||
end
|
||||
|
||||
for i=1, #kernel.runhooks do
|
||||
local ok,err = xpcall(kernel.runhooks[i], debug.traceback)
|
||||
if not ok then kernel.panic(err) end
|
||||
end
|
||||
|
||||
kernel.log("Kernel initialized successfully.")
|
||||
kernel.saveLog()
|
||||
kernel.status="running"
|
||||
kernel.loadingModule=nil
|
||||
screen:disable()
|
||||
if not kernel.main then kernel.panic("No scheduler implemented from firmware") end
|
||||
local ok,err = xpcall(kernel.main, debug.traceback)
|
||||
if not ok then
|
||||
kernel.panic(err)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
0:0:root:/root:/bin/hysh
|
||||
@@ -2,7 +2,7 @@
|
||||
local kernel = ...
|
||||
local vfs = {}
|
||||
kernel.vfs = vfs
|
||||
vfs.mounts = {}
|
||||
vfs.mounts = {["$"] = "/"}
|
||||
vfs.disks = kernel.disks
|
||||
|
||||
-- Metafile format (version 2)
|
||||
@@ -556,8 +556,7 @@ function vfs.newfd(fdobj)
|
||||
return fd
|
||||
end
|
||||
|
||||
function vfs.mount(target, diskOrId, bind, floating)
|
||||
if not floating and target ~= "/" then
|
||||
function vfs.mount(target, diskOrId, bind)
|
||||
local _euid = (kernel.currentTask and (kernel.currentTask.euid or kernel.currentTask.uid)) or kernel.uid
|
||||
if _euid ~= 0 then error("EPERM") end
|
||||
if not target then error("EINVAL") end
|
||||
@@ -569,7 +568,6 @@ function vfs.mount(target, diskOrId, bind, floating)
|
||||
if drive:type(path) ~= "directory" then
|
||||
error("EINVAL")
|
||||
end
|
||||
end
|
||||
local disk, id
|
||||
-- bind mount
|
||||
if bind then
|
||||
@@ -1068,9 +1066,8 @@ function vfs.chown(path, uid, gid)
|
||||
if kernel.unixSockets[namei(path)] then error("EINVAL") end
|
||||
local disk = resolveMount(path)
|
||||
if disk:isReadOnly() then error("ERDONLY") end
|
||||
local meta = getFileMeta(path)
|
||||
local euid = (kernel.currentTask and (kernel.currentTask.euid or kernel.currentTask.uid)) or kernel.uid
|
||||
if euid ~= 0 and euid ~= meta.owner then error("EPERM") end
|
||||
local _euid = (kernel.currentTask and (kernel.currentTask.euid or kernel.currentTask.uid)) or kernel.uid
|
||||
if _euid ~= 0 then error("EPERM") end
|
||||
updateMeta(path, function(e) e.owner = uid; e.group = gid end)
|
||||
end
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
--:Minify:--
|
||||
local kernel = ...
|
||||
|
||||
kernel.vfs.remove("/tmp")
|
||||
kernel.vfs.mkdir("/tmp")
|
||||
if not kernel.config.tmpToDisk then
|
||||
local proxy = {}
|
||||
local data = {}
|
||||
@@ -136,8 +138,4 @@ if not kernel.config.tmpToDisk then
|
||||
else
|
||||
kernel.log("tmpToDisk enabled, skipping tmpfs module")
|
||||
kernel.log("tmpfs0000 will passthrough to /tmp on the disk")
|
||||
kernel.runWhenLoaded(function()
|
||||
kernel.vfs.remove("/tmp")
|
||||
kernel.vfs.mkdir("/tmp")
|
||||
end)
|
||||
end
|
||||
@@ -11,7 +11,7 @@ end
|
||||
|
||||
for _, line in ipairs(string.split(kernel.fstab, "\n")) do
|
||||
line = trim(line)
|
||||
if line:sub(1,1) == "U" or line:sub(1,1) == "V" or line:sub(1,1) == "F" then
|
||||
if line ~= "" and line:sub(1,1) == "U" then
|
||||
local semicolon_pos
|
||||
for i = 3, #line do
|
||||
if line:sub(i,i) == ";" then
|
||||
@@ -26,7 +26,9 @@ for _, line in ipairs(string.split(kernel.fstab, "\n")) do
|
||||
local id = line:sub(3, semicolon_pos - 1)
|
||||
local path = trim(line:sub(semicolon_pos + 1))
|
||||
kernel.log("Mounting '"..id.."' to '"..path.."'")
|
||||
kernel.vfs.mount(path, id, nil, line:sub(1,1) == "F")
|
||||
if id ~= "$" then
|
||||
kernel.vfs.mount(path, id)
|
||||
end
|
||||
kernel.log("Mounted "..id.." to "..path)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -32,31 +32,6 @@ function signal.sigignore()
|
||||
task.sigd=nil
|
||||
end
|
||||
|
||||
kernel.execPerTask(function(task)
|
||||
if task.status=="R" then
|
||||
if task.sigq and #task.sigq ~= 0 and task.sigh then
|
||||
local coro = coroutine.create(task.sigh)
|
||||
local status,err=coroutine.resume(coro, table.remove(task.sigq, 1))
|
||||
EFI:yeild()
|
||||
if status=="error" or status==false then
|
||||
task.sigd.error=err or "Unknown"
|
||||
task.sigd.active=false
|
||||
task.sigh=nil
|
||||
task.sigq=nil
|
||||
task.sigd=nil
|
||||
elseif status=="success" or status==true then
|
||||
if err=="syscall" then
|
||||
task.sigd.error="Cannot execute syscalls from signals"
|
||||
task.sigd.active=false
|
||||
task.sigh=nil
|
||||
task.sigq=nil
|
||||
task.sigd=nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end,2)
|
||||
|
||||
local s=kernel.syscalls
|
||||
s["sigsend"] = signal.sigsend
|
||||
s["sigcatch"] = signal.sigcatch
|
||||
|
||||
@@ -155,21 +155,7 @@ end
|
||||
|
||||
local function hashPassword(password, salt)
|
||||
local key = (pepper .. salt)
|
||||
return blake2s(password..salt, key)
|
||||
end
|
||||
|
||||
if not kernel.vfs.exists("/etc/passwd") then
|
||||
kernel.log("PASSWD FILE NOT FOUND CREATING...", "WARN", 0xFF8800)
|
||||
local handle = kernel.vfs.open("/etc/passwd", "w")
|
||||
kernel.vfs.write(handle, "0:0:root:/root:/bin/hysh")
|
||||
kernel.vfs.close(handle)
|
||||
end
|
||||
|
||||
if not kernel.vfs.exists("/etc/shadow") then
|
||||
kernel.log("SHADOW FILE NOT FOUND CREATING...", "WARN", 0xFF8800)
|
||||
local handle = kernel.vfs.open("/etc/shadow", "w")
|
||||
kernel.vfs.write(handle, "")
|
||||
kernel.vfs.close(handle)
|
||||
return blake2s(password, key)
|
||||
end
|
||||
|
||||
local passwdFile = getFile("/etc/passwd")
|
||||
|
||||
@@ -5,6 +5,7 @@ local sys = {}
|
||||
local nextpid = 2
|
||||
kernel.exitMain = false
|
||||
|
||||
local resumeWithTimeout = coroutine.resumeWithTimeout
|
||||
|
||||
local function bit_is_set(num, bit)
|
||||
return math.floor(num / (2 ^ bit)) % 2 == 1
|
||||
@@ -30,18 +31,10 @@ local function loadExecutable(path)
|
||||
return func, euid, suid_set
|
||||
end
|
||||
|
||||
local function createTask(func, name, envars, args, tgid, real_uid, eff_uid, clearFds)
|
||||
local function createTask(func, name, envars, args, tgid, real_uid, eff_uid)
|
||||
local id = nextpid
|
||||
nextpid = nextpid + 1
|
||||
|
||||
local fds={}
|
||||
if not clearFds then
|
||||
for id, file in pairs(kernel.currentTask.fd) do
|
||||
file.refcount=file.refcount+1
|
||||
fds[id]=file
|
||||
end
|
||||
end
|
||||
|
||||
tasks[tostring(id)] = {
|
||||
coro = coroutine.create(function()
|
||||
local ok, err = xpcall(func, debug.traceback, table.unpack(args or {}))
|
||||
@@ -78,7 +71,7 @@ local function createTask(func, name, envars, args, tgid, real_uid, eff_uid, cle
|
||||
euid = eff_uid,
|
||||
gid = (kernel.currentTask and kernel.currentTask.gid) or 0,
|
||||
groups = (kernel.currentTask and kernel.currentTask.groups) or {},
|
||||
fd = fds,
|
||||
fd = {},
|
||||
sleep = 0,
|
||||
ivs = 0,
|
||||
vs = 0,
|
||||
@@ -100,14 +93,14 @@ local function createTask(func, name, envars, args, tgid, real_uid, eff_uid, cle
|
||||
return id
|
||||
end
|
||||
|
||||
function sys.spawn(func, name, envars, args, tgid, clearFds)
|
||||
function sys.spawn(func, name, envars, args, tgid)
|
||||
local caller = kernel.currentTask
|
||||
local real_uid = caller and caller.uid or kernel.uid
|
||||
local eff_uid = caller and caller.euid or real_uid
|
||||
return createTask(func, name, envars, args, tgid, real_uid, eff_uid, clearFds)
|
||||
return createTask(func, name, envars, args, tgid, real_uid, eff_uid)
|
||||
end
|
||||
|
||||
function sys.execspawn(path, name, envars, args, tgid, keepFds)
|
||||
function sys.execspawn(path, name, envars, args, tgid)
|
||||
local func, euid, suid_active = loadExecutable(path, kernel._U)
|
||||
|
||||
local caller = kernel.currentTask
|
||||
@@ -121,23 +114,22 @@ function sys.execspawn(path, name, envars, args, tgid, keepFds)
|
||||
)
|
||||
end
|
||||
|
||||
return createTask(func, name or path, envars, args, tgid, real_uid, euid, not keepFds)
|
||||
return createTask(func, name or path, envars, args, tgid, real_uid, euid)
|
||||
end
|
||||
|
||||
function sys.exec(path, args, envars)
|
||||
local task = kernel.currentTask
|
||||
local func, euid, _ = loadExecutable(path, kernel._U)
|
||||
|
||||
-- no idea why this is here?
|
||||
--if task.fd then
|
||||
-- for fd, _ in pairs(task.fd) do
|
||||
-- if fd > 2 then pcall(kernel.vfs.close, fd) end
|
||||
-- end
|
||||
--end
|
||||
if task.fd then
|
||||
for fd, _ in pairs(task.fd) do
|
||||
if fd > 2 then pcall(kernel.vfs.close, fd) end
|
||||
end
|
||||
end
|
||||
|
||||
task.euid = euid
|
||||
task.args = args or {}
|
||||
task.envars = envars or task.envars or {}
|
||||
task.envars = envars or task.envars
|
||||
task.name = path
|
||||
|
||||
task.coro = coroutine.create(function()
|
||||
@@ -309,7 +301,7 @@ end
|
||||
|
||||
function sys.getuid() return kernel.currentTask.uid end
|
||||
|
||||
function sys.reapDeadTasks()
|
||||
local function reapDeadTasks()
|
||||
for pid, task in pairs(tasks) do
|
||||
if task.status == "Z" and not task.reapTime then
|
||||
if task.pid == 1 then kernel.panic("Attempted to gc init!") end
|
||||
@@ -346,7 +338,43 @@ function sys.reapDeadTasks()
|
||||
end
|
||||
end
|
||||
|
||||
kernel.execPerTask(function(task)
|
||||
local alpha = 0.85
|
||||
local C_target = 0.01
|
||||
local Tmin = 0.0005
|
||||
local Tmax = 0.5
|
||||
local lambda_budget = 0.08
|
||||
local lambda_clamp = 0.03
|
||||
local lambda_var = 0.02
|
||||
local k_min = 0.5
|
||||
local k_max = 0.5
|
||||
local B = 0.01
|
||||
|
||||
function kernel.main()
|
||||
kernel.log("Starting main loop...")
|
||||
kernel.saveLog()
|
||||
local stopLog=5
|
||||
local logTasks=100
|
||||
|
||||
while not kernel.exitMain do
|
||||
if kernel.config.logTasks then
|
||||
if logTasks<0 then
|
||||
kernel.log("Active Tasks:")
|
||||
for i,v in pairs(tasks) do
|
||||
kernel.log(v.name.." : "..v.status.." : "..tostring(v.pid).." : "..tostring(v.exit))
|
||||
end
|
||||
kernel.log("[END BLOCK]")
|
||||
logTasks=100
|
||||
end
|
||||
logTasks=logTasks-1
|
||||
end
|
||||
local N = 0
|
||||
local Tmin_hit = 0
|
||||
local Tmax_hit = 0
|
||||
local totalTaskTime = 0
|
||||
local taskTimes = {}
|
||||
|
||||
for pid, task in pairs(tasks) do
|
||||
if kernel.exitMain then break end
|
||||
kernel.currentTask = task
|
||||
kernel.uid = task.euid or task.uid
|
||||
kernel.process = task.name
|
||||
@@ -380,7 +408,135 @@ kernel.execPerTask(function(task)
|
||||
end
|
||||
end
|
||||
end
|
||||
end,1)
|
||||
|
||||
if task.status == "R" then
|
||||
N = N + 1
|
||||
|
||||
task.timeSlice = math.min(Tmax, math.max(Tmin, B / (N ^ alpha)))
|
||||
|
||||
if task.sigq and #task.sigq ~= 0 and task.sigh then
|
||||
local coro = coroutine.create(task.sigh)
|
||||
local status,err
|
||||
if kernel.config.preempt then
|
||||
status,err=coroutine.resumeWithTimeout(coro, 100, table.remove(task.sigq, 1))
|
||||
else
|
||||
status,err=coroutine.resume(coro, table.remove(task.sigq, 1))
|
||||
end
|
||||
if status=="error" or status==false then
|
||||
task.sigd.error=err or "Unknown"
|
||||
task.sigd.active=false
|
||||
task.sigh=nil
|
||||
task.sigq=nil
|
||||
task.sigd=nil
|
||||
elseif status=="success" or status==true then
|
||||
if err=="syscall" then
|
||||
task.sigd.error="Cannot execute syscalls from signals"
|
||||
task.sigd.active=false
|
||||
task.sigh=nil
|
||||
task.sigq=nil
|
||||
task.sigd=nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if task.status == "R" then
|
||||
local startTime = kernel.EFI:getEpochMs()
|
||||
local ret
|
||||
if stopLog > 0 then
|
||||
kernel.log("Running task " .. tostring(task.pid) .. " (" .. task.name .. ") with time slice " .. string.format("%.3f", task.timeSlice) .. "s", "DBUG", 0x00FFFF)
|
||||
end
|
||||
if kernel.config.preempt then
|
||||
if not task.debugger then
|
||||
ret = { resumeWithTimeout(task.coro, task.timeSlice, table.unpack(task.syscallReturn)) }
|
||||
else
|
||||
ret = { coroutine.resume(task.coro, table.unpack(task.syscallReturn)) }
|
||||
end
|
||||
else
|
||||
ret = { coroutine.resume(task.coro, table.unpack(task.syscallReturn)) }
|
||||
end
|
||||
|
||||
local elapsed = kernel.EFI:getEpochMs() - startTime
|
||||
task.lastTime = elapsed
|
||||
task.totalTime = (task.totalTime or 0) + elapsed
|
||||
task.numRuns = (task.numRuns or 0) + 1
|
||||
|
||||
taskTimes[#taskTimes+1] = elapsed
|
||||
totalTaskTime = totalTaskTime + elapsed
|
||||
|
||||
if elapsed <= Tmin then Tmin_hit = Tmin_hit + 1 end
|
||||
if elapsed >= Tmax then Tmax_hit = Tmax_hit + 1 end
|
||||
|
||||
if ret[1] == "error" or ret[1] == false then
|
||||
kernel.log("processHandlerException: " .. tostring(ret[2]), "ERROR", 0xFF0000)
|
||||
task.status = "Z"
|
||||
task.exit = "processHandlerException: " .. tostring(ret[2])
|
||||
|
||||
elseif ret[1] == "timeout" then
|
||||
task.ivs = task.ivs + 1
|
||||
task.syscallReturn = {}
|
||||
|
||||
elseif ret[1] == "success" or ret[1] == true then
|
||||
task.vs = task.vs + 1
|
||||
|
||||
if ret[2] == "syscall" then
|
||||
local scname = ret[3]
|
||||
if kernel.syscalls[scname] then
|
||||
if kernel.config.debugSyscalls then
|
||||
kernel.log("Task " .. task.pid .. " syscall: " .. scname, "DBUG", 0x00FFFF)
|
||||
for i = 4, #ret do
|
||||
kernel.log(" inval[" .. (i-3) .. "] = " .. tostring(ret[i]), "DBUG", 0x00FFFF)
|
||||
end
|
||||
end
|
||||
|
||||
local sysret = { xpcall(kernel.syscalls[scname], debug.traceback, table.unpack(ret, 4)) }
|
||||
|
||||
if kernel.config.debugSyscalls then
|
||||
if not sysret[1] then
|
||||
kernel.log("Task " .. task.pid .. " syscall " .. scname .. " failed: " .. tostring(sysret[2]), "ERROR", 0xFF0000)
|
||||
else
|
||||
kernel.log("Task " .. task.pid .. " syscall " .. scname .. " ok, " .. (#sysret-1) .. " retvals", "DBUG", 0x00FFFF)
|
||||
for i = 2, #sysret do
|
||||
local v = type(sysret[i]) == "table" and table.serialize(sysret[i]) or tostring(sysret[i])
|
||||
kernel.log(" retval[" .. (i-1) .. "] = " .. v, "DBUG", 0x00FFFF)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not sysret[1] then
|
||||
task.syscallReturn = { false, sysret[2] }
|
||||
else
|
||||
task.syscallReturn = { true, table.unpack(sysret, 2) }
|
||||
end
|
||||
else
|
||||
task.syscallReturn = { false, "Unknown syscall: " .. tostring(scname) }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local T_prev_avg = (N > 0) and (totalTaskTime / N) or 0
|
||||
local T_prev_var = 0
|
||||
for _, t in ipairs(taskTimes) do
|
||||
T_prev_var = T_prev_var + (t - T_prev_avg) ^ 2
|
||||
end
|
||||
if N > 0 then T_prev_var = T_prev_var / N end
|
||||
|
||||
if N > 0 then
|
||||
local f_clamp = k_min * (Tmin_hit / N) - k_max * (Tmax_hit / N)
|
||||
local B_budget = (C_target * (N ^ (alpha - 1))) / math.max(T_prev_avg, 1e-8)
|
||||
B = B + lambda_budget * (B_budget - B) + lambda_clamp * f_clamp - lambda_var * T_prev_var
|
||||
end
|
||||
|
||||
reapDeadTasks()
|
||||
if stopLog > 0 then
|
||||
kernel.log("Executed " .. N .. " tasks, avg time: " .. string.format("%.2f", T_prev_avg) .. "ms, var: " .. string.format("%.2f", T_prev_var) .. ", B: " .. string.format("%.5f", B))
|
||||
stopLog = stopLog - 1
|
||||
kernel.saveLog()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local sysc = kernel.syscalls
|
||||
sysc["spawn"] = sys.spawn
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
local kernel = ...
|
||||
|
||||
if kernel.firstBoot then
|
||||
kernel.log("Seeding filesystem permissions...")
|
||||
|
||||
local P = kernel.vfs.P
|
||||
local PERM = kernel.vfs.PERM
|
||||
|
||||
@@ -16,44 +14,107 @@ if kernel.firstBoot then
|
||||
local RWXRWXRWX = PERM.RWXRWXRWX
|
||||
local SUID_755 = PERM.SUID_755
|
||||
|
||||
local function seed(root, data)
|
||||
for i=1,#data do
|
||||
local entry=data[1]
|
||||
kernel.vfs.chmod(root..entry[1],entry[2],entry[3])
|
||||
kernel.vfs.chown(root..entry[1],entry[4])
|
||||
local META_VERSION = 0x02
|
||||
local rootDisk = kernel.disks["$"]
|
||||
|
||||
local function makeEntry(name, etype, owner, group, perms, cmeta)
|
||||
cmeta = cmeta or ""
|
||||
local plo = perms % 256
|
||||
local phi = math.floor(perms / 256) % 256
|
||||
local olo = (owner or 0) % 256
|
||||
local ohi = math.floor((owner or 0) / 256) % 256
|
||||
local glo = (group or 0) % 256
|
||||
local ghi = math.floor((group or 0) / 256) % 256
|
||||
return string.char(#name) .. name
|
||||
.. string.char(etype, olo, ohi, glo, ghi, plo, phi)
|
||||
.. string.char(#cmeta) .. cmeta
|
||||
end
|
||||
|
||||
local REG = 0x00
|
||||
|
||||
local function mergeMeta(dir, entries)
|
||||
local diskDir = dir
|
||||
if diskDir:sub(1,1) == "/" then diskDir = diskDir:sub(2) end
|
||||
local metaPath = (diskDir == "" and ".meta" or diskDir .. "/.meta")
|
||||
|
||||
local existing = {}
|
||||
local rok, rf = pcall(function() return rootDisk:open(metaPath, "r") end)
|
||||
if rok and rf then
|
||||
local raw = rf.read(65535)
|
||||
if rf.close then rf.close() end
|
||||
existing = (kernel.vfs._parseMetafile and kernel.vfs._parseMetafile(raw)) or {}
|
||||
end
|
||||
|
||||
for _, e in ipairs(entries) do
|
||||
local name = e[1]
|
||||
local etype = e[2] or REG
|
||||
local owner = e[3] or 0
|
||||
local group = e[4] or 0
|
||||
local perms = e[5] or RWX_RX_RX
|
||||
local cmeta = e[6] or ""
|
||||
existing[name] = {
|
||||
etype = etype,
|
||||
owner = owner,
|
||||
group = group,
|
||||
perms = perms,
|
||||
cmeta = cmeta,
|
||||
}
|
||||
end
|
||||
|
||||
local data = string.char(META_VERSION)
|
||||
for name, m in pairs(existing) do
|
||||
data = data .. makeEntry(
|
||||
name,
|
||||
m.etype or REG,
|
||||
m.owner or 0,
|
||||
m.group or 0,
|
||||
m.perms or RWX_RX_RX,
|
||||
m.cmeta or ""
|
||||
)
|
||||
end
|
||||
|
||||
local ok, err = pcall(function()
|
||||
local f = rootDisk:open(metaPath, "w")
|
||||
f.write(data)
|
||||
f.close()
|
||||
end)
|
||||
if not ok then
|
||||
kernel.log("permissions: failed to write " .. metaPath .. ": " .. tostring(err), "WARN", 0xFF8800)
|
||||
end
|
||||
end
|
||||
|
||||
seed("/", {
|
||||
{"bin", 0, 0, RWX_RX_RX},
|
||||
{"boot", 0, 0, RWX_RX_RX},
|
||||
{"dev", 0, 0, RWXRWXRWX},
|
||||
{"etc", 0, 0, RWX_RX_RX},
|
||||
{"home", 0, 0, RWX_RX_RX},
|
||||
{"lib", 0, 0, RWX_RX_RX},
|
||||
{"proc", 0, 0, RWXRWXRWX},
|
||||
{"root", 0, 0, RW____ },
|
||||
{"sbin", 0, 0, RWX_RX_RX},
|
||||
{"tmp", 0, 0, RWXRWXRWX},
|
||||
{"usr", 0, 0, RWX_RX_RX},
|
||||
{"var", 0, 0, RWXRWXRWX},
|
||||
{"opt", 0, 0, RWX_RX_RX},
|
||||
kernel.log("Seeding filesystem permissions...")
|
||||
|
||||
mergeMeta("/", {
|
||||
{"bin", REG, 0, 0, RWX_RX_RX},
|
||||
{"boot", REG, 0, 0, RWX_RX_RX},
|
||||
{"dev", REG, 0, 0, RWXRWXRWX},
|
||||
{"etc", REG, 0, 0, RWX_RX_RX},
|
||||
{"home", REG, 0, 0, RWX_RX_RX},
|
||||
{"lib", REG, 0, 0, RWX_RX_RX},
|
||||
{"proc", REG, 0, 0, RWXRWXRWX},
|
||||
{"root", REG, 0, 0, RW____ },
|
||||
{"sbin", REG, 0, 0, RWX_RX_RX},
|
||||
{"tmp", REG, 0, 0, RWXRWXRWX},
|
||||
{"usr", REG, 0, 0, RWX_RX_RX},
|
||||
{"var", REG, 0, 0, RWXRWXRWX},
|
||||
{"opt", REG, 0, 0, RWX_RX_RX},
|
||||
})
|
||||
|
||||
seed("/bin/", {
|
||||
{"login", 0, 0, SUID_755 },
|
||||
{"su", 0, 0, SUID_755 },
|
||||
{"sudo", 0, 0, SUID_755 },
|
||||
mergeMeta("/bin", {
|
||||
{"login", REG, 0, 0, SUID_755 },
|
||||
{"su", REG, 0, 0, SUID_755 },
|
||||
{"sudo", REG, 0, 0, SUID_755 },
|
||||
})
|
||||
|
||||
seed("/etc/", {
|
||||
{"passwd", 0, 0, RW_R_R },
|
||||
{"shadow", 0, 0, RW____ },
|
||||
{"pam.d", 0, 0, RW____ },
|
||||
mergeMeta("/etc", {
|
||||
{"passwd", REG, 0, 0, RW_R_R },
|
||||
{"shadow", REG, 0, 0, RW____ },
|
||||
{"pam.d", REG, 0, 0, RW____ },
|
||||
})
|
||||
|
||||
seed("/etc/pam.d/", {
|
||||
{"secret", 0, 0, RW____},
|
||||
mergeMeta("/etc/pam.d", {
|
||||
{"secret", REG, 0, 0, RW____},
|
||||
})
|
||||
|
||||
kernel.log("Filesystem permissions seeded.")
|
||||
|
||||
@@ -3,7 +3,6 @@ syscall.open("/dev/input/keyboard1", "r") --stdin (fd 0)
|
||||
syscall.open("/dev/tty/1", "w") --stdout (fd 1)
|
||||
syscall.open("/dev/null", "w") --stderr (fd 2)
|
||||
|
||||
local fs=require("fs")
|
||||
|
||||
local MAX_ATTEMPTS = 3
|
||||
|
||||
@@ -101,9 +100,7 @@ local function spawnShell(username, uid, shell, homedir)
|
||||
pcall(syscall.chdir, "/")
|
||||
end
|
||||
|
||||
local shellfunc, err = load(fs.readAllText(shell))
|
||||
|
||||
local ok, err = pcall(syscall.spawn, shellfunc, username .. ":shell", nil,nil,nil,true)
|
||||
local ok, err = pcall(syscall.execspawn, shell, username .. ":shell")
|
||||
if not ok then
|
||||
syscall.write(1, "login: failed to launch shell: " .. tostring(err) .. "\n")
|
||||
sleep(2)
|
||||
@@ -148,7 +145,7 @@ local function doLogin()
|
||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
||||
sleep(0.3)
|
||||
|
||||
pcall(spawnShell, username, uid, shell, homedir)
|
||||
spawnShell(username, uid, shell, homedir)
|
||||
return -- back to login prompt
|
||||
else
|
||||
attempts = attempts + 1
|
||||
|
||||
@@ -3,7 +3,6 @@ syscall.open("/dev/input/keyboard1", "r") --stdin (fd 0)
|
||||
syscall.open("/dev/tty/1", "w") --stdout (fd 1)
|
||||
syscall.open("/dev/null", "w") --stderr (fd 2)
|
||||
|
||||
local fs=require("fs")
|
||||
|
||||
local MAX_ATTEMPTS = 3
|
||||
|
||||
@@ -101,9 +100,7 @@ local function spawnShell(username, uid, shell, homedir)
|
||||
pcall(syscall.chdir, "/")
|
||||
end
|
||||
|
||||
local shellfunc, err = load(fs.readAllText(shell))
|
||||
|
||||
local ok, err = pcall(syscall.spawn, shellfunc, username .. ":shell", nil,nil,nil,true)
|
||||
local ok, err = pcall(syscall.execspawn, shell, username .. ":shell")
|
||||
if not ok then
|
||||
syscall.write(1, "login: failed to launch shell: " .. tostring(err) .. "\n")
|
||||
sleep(2)
|
||||
@@ -148,7 +145,7 @@ local function doLogin()
|
||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
||||
sleep(0.3)
|
||||
|
||||
pcall(spawnShell, username, uid, shell, homedir)
|
||||
spawnShell(username, uid, shell, homedir)
|
||||
return -- back to login prompt
|
||||
else
|
||||
attempts = attempts + 1
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
--:Minify:--
|
||||
local lib = {}
|
||||
|
||||
function lib.frame(frame)
|
||||
local handle = {}
|
||||
|
||||
function handle.setPixel(x,y,color24)
|
||||
|
||||
end
|
||||
|
||||
function handle.getPixel(x,y)
|
||||
|
||||
end
|
||||
|
||||
function handle.setPixels(x,y,framebuffer)
|
||||
|
||||
end
|
||||
|
||||
function handle.getPixels(x,y,w,h)
|
||||
|
||||
end
|
||||
|
||||
function handle.frame(x,y,w,h,writeonly)
|
||||
|
||||
end
|
||||
|
||||
function handle.framectl(id,x,y,w,h,writeonly)
|
||||
|
||||
end
|
||||
|
||||
function handle.drawframe()
|
||||
|
||||
end
|
||||
|
||||
function handle.line()
|
||||
|
||||
end
|
||||
|
||||
return handle
|
||||
end
|
||||
-256
@@ -1,256 +0,0 @@
|
||||
#000000
|
||||
#0b0b0b
|
||||
#222222
|
||||
#444444
|
||||
#555555
|
||||
#777777
|
||||
#888888
|
||||
#aaaaaa
|
||||
#bbbbbb
|
||||
#dddddd
|
||||
#eeeeee
|
||||
#00000b
|
||||
#000022
|
||||
#000044
|
||||
#000055
|
||||
#000077
|
||||
#000088
|
||||
#0000aa
|
||||
#0000bb
|
||||
#0000dd
|
||||
#0000ee
|
||||
#000b00
|
||||
#002200
|
||||
#004400
|
||||
#005500
|
||||
#007700
|
||||
#008800
|
||||
#00aa00
|
||||
#00bb00
|
||||
#00dd00
|
||||
#00ee00
|
||||
#0b0000
|
||||
#220000
|
||||
#440000
|
||||
#550000
|
||||
#770000
|
||||
#880000
|
||||
#aa0000
|
||||
#bb0000
|
||||
#dd0000
|
||||
#ee0000
|
||||
#000033
|
||||
#000066
|
||||
#000099
|
||||
#0000cc
|
||||
#0000ff
|
||||
#003300
|
||||
#003333
|
||||
#003366
|
||||
#003399
|
||||
#0033cc
|
||||
#0033ff
|
||||
#006600
|
||||
#006633
|
||||
#006666
|
||||
#006699
|
||||
#0066cc
|
||||
#0066ff
|
||||
#009900
|
||||
#009933
|
||||
#009966
|
||||
#009999
|
||||
#0099cc
|
||||
#0099ff
|
||||
#00cc00
|
||||
#00cc33
|
||||
#00cc66
|
||||
#00cc99
|
||||
#00cccc
|
||||
#00ccff
|
||||
#00ff00
|
||||
#00ff33
|
||||
#00ff66
|
||||
#00ff99
|
||||
#00ffcc
|
||||
#00ffff
|
||||
#330000
|
||||
#330033
|
||||
#330066
|
||||
#330099
|
||||
#3300cc
|
||||
#3300ff
|
||||
#333300
|
||||
#333333
|
||||
#333366
|
||||
#333399
|
||||
#3333cc
|
||||
#3333ff
|
||||
#336600
|
||||
#336633
|
||||
#336666
|
||||
#336699
|
||||
#3366cc
|
||||
#3366ff
|
||||
#339900
|
||||
#339933
|
||||
#339966
|
||||
#339999
|
||||
#3399cc
|
||||
#3399ff
|
||||
#33cc00
|
||||
#33cc33
|
||||
#33cc66
|
||||
#33cc99
|
||||
#33cccc
|
||||
#33ccff
|
||||
#33ff00
|
||||
#33ff33
|
||||
#33ff66
|
||||
#33ff99
|
||||
#33ffcc
|
||||
#33ffff
|
||||
#660000
|
||||
#660033
|
||||
#660066
|
||||
#660099
|
||||
#6600cc
|
||||
#6600ff
|
||||
#663300
|
||||
#663333
|
||||
#663366
|
||||
#663399
|
||||
#6633cc
|
||||
#6633ff
|
||||
#666600
|
||||
#666633
|
||||
#666666
|
||||
#666699
|
||||
#6666cc
|
||||
#6666ff
|
||||
#669900
|
||||
#669933
|
||||
#669966
|
||||
#669999
|
||||
#6699cc
|
||||
#6699ff
|
||||
#66cc00
|
||||
#66cc33
|
||||
#66cc66
|
||||
#66cc99
|
||||
#66cccc
|
||||
#66ccff
|
||||
#66ff00
|
||||
#66ff33
|
||||
#66ff66
|
||||
#66ff99
|
||||
#66ffcc
|
||||
#66ffff
|
||||
#990000
|
||||
#990033
|
||||
#990066
|
||||
#990099
|
||||
#9900cc
|
||||
#9900ff
|
||||
#993300
|
||||
#993333
|
||||
#993366
|
||||
#993399
|
||||
#9933cc
|
||||
#9933ff
|
||||
#996600
|
||||
#996633
|
||||
#996666
|
||||
#996699
|
||||
#9966cc
|
||||
#9966ff
|
||||
#999900
|
||||
#999933
|
||||
#999966
|
||||
#999999
|
||||
#9999cc
|
||||
#9999ff
|
||||
#99cc00
|
||||
#99cc33
|
||||
#99cc66
|
||||
#99cc99
|
||||
#99cccc
|
||||
#99ccff
|
||||
#99ff00
|
||||
#99ff33
|
||||
#99ff66
|
||||
#99ff99
|
||||
#99ffcc
|
||||
#99ffff
|
||||
#cc0000
|
||||
#cc0033
|
||||
#cc0066
|
||||
#cc0099
|
||||
#cc00cc
|
||||
#cc00ff
|
||||
#cc3300
|
||||
#cc3333
|
||||
#cc3366
|
||||
#cc3399
|
||||
#cc33cc
|
||||
#cc33ff
|
||||
#cc6600
|
||||
#cc6633
|
||||
#cc6666
|
||||
#cc6699
|
||||
#cc66cc
|
||||
#cc66ff
|
||||
#cc9900
|
||||
#cc9933
|
||||
#cc9966
|
||||
#cc9999
|
||||
#cc99cc
|
||||
#cc99ff
|
||||
#cccc00
|
||||
#cccc33
|
||||
#cccc66
|
||||
#cccc99
|
||||
#cccccc
|
||||
#ccccff
|
||||
#ccff00
|
||||
#ccff33
|
||||
#ccff66
|
||||
#ccff99
|
||||
#ccffcc
|
||||
#ccffff
|
||||
#ff0000
|
||||
#ff0033
|
||||
#ff0066
|
||||
#ff0099
|
||||
#ff00cc
|
||||
#ff00ff
|
||||
#ff3300
|
||||
#ff3333
|
||||
#ff3366
|
||||
#ff3399
|
||||
#ff33cc
|
||||
#ff33ff
|
||||
#ff6600
|
||||
#ff6633
|
||||
#ff6666
|
||||
#ff6699
|
||||
#ff66cc
|
||||
#ff66ff
|
||||
#ff9900
|
||||
#ff9933
|
||||
#ff9966
|
||||
#ff9999
|
||||
#ff99cc
|
||||
#ff99ff
|
||||
#ffcc00
|
||||
#ffcc33
|
||||
#ffcc66
|
||||
#ffcc99
|
||||
#ffcccc
|
||||
#ffccff
|
||||
#ffff00
|
||||
#ffff33
|
||||
#ffff66
|
||||
#ffff99
|
||||
#ffffcc
|
||||
#ffffff
|
||||
@@ -1,350 +0,0 @@
|
||||
term.setGraphicsMode(2)
|
||||
local w,h = term.getSize(2)
|
||||
local fb={}
|
||||
for i=1, h do
|
||||
fb[i]={}
|
||||
for x=1, w do
|
||||
fb[i][x]=0
|
||||
end
|
||||
end
|
||||
|
||||
local function setPixel(x,y,c)
|
||||
--local old=fb[y]
|
||||
--fb[y]=string.sub(old,1,x-1)..string.char(c)..string.sub(old,x+1)
|
||||
fb[y][x]=c
|
||||
end
|
||||
|
||||
local function setPixels(x,y,frame)
|
||||
local w,h = #fb[1], #fb
|
||||
for i=1, #frame do
|
||||
for j=1, #frame[i] do
|
||||
fb[y+i-1][x+j-1]=frame[i][j]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function getPixel(x,y)
|
||||
return fb[y][x]
|
||||
end
|
||||
|
||||
local function getPixels(x,y,w,h)
|
||||
local ret={}
|
||||
for i=y, y+h do
|
||||
ret[#ret+1] = {table.unpack(fb[i], x, x+w)}
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
local colors = {
|
||||
[0]=0x000000,
|
||||
0x0b0b0b,
|
||||
0x222222,
|
||||
0x444444,
|
||||
0x555555,
|
||||
0x777777,
|
||||
0x888888,
|
||||
0xaaaaaa,
|
||||
0xbbbbbb,
|
||||
0xdddddd,
|
||||
0xeeeeee,
|
||||
0x00000b,
|
||||
0x000022,
|
||||
0x000044,
|
||||
0x000055,
|
||||
0x000077,
|
||||
0x000088,
|
||||
0x0000aa,
|
||||
0x0000bb,
|
||||
0x0000dd,
|
||||
0x0000ee,
|
||||
0x000b00,
|
||||
0x002200,
|
||||
0x004400,
|
||||
0x005500,
|
||||
0x007700,
|
||||
0x008800,
|
||||
0x00aa00,
|
||||
0x00bb00,
|
||||
0x00dd00,
|
||||
0x00ee00,
|
||||
0x0b0000,
|
||||
0x220000,
|
||||
0x440000,
|
||||
0x550000,
|
||||
0x770000,
|
||||
0x880000,
|
||||
0xaa0000,
|
||||
0xbb0000,
|
||||
0xdd0000,
|
||||
0xee0000,
|
||||
0x000033,
|
||||
0x000066,
|
||||
0x000099,
|
||||
0x0000cc,
|
||||
0x0000ff,
|
||||
0x003300,
|
||||
0x003333,
|
||||
0x003366,
|
||||
0x003399,
|
||||
0x0033cc,
|
||||
0x0033ff,
|
||||
0x006600,
|
||||
0x006633,
|
||||
0x006666,
|
||||
0x006699,
|
||||
0x0066cc,
|
||||
0x0066ff,
|
||||
0x009900,
|
||||
0x009933,
|
||||
0x009966,
|
||||
0x009999,
|
||||
0x0099cc,
|
||||
0x0099ff,
|
||||
0x00cc00,
|
||||
0x00cc33,
|
||||
0x00cc66,
|
||||
0x00cc99,
|
||||
0x00cccc,
|
||||
0x00ccff,
|
||||
0x00ff00,
|
||||
0x00ff33,
|
||||
0x00ff66,
|
||||
0x00ff99,
|
||||
0x00ffcc,
|
||||
0x00ffff,
|
||||
0x330000,
|
||||
0x330033,
|
||||
0x330066,
|
||||
0x330099,
|
||||
0x3300cc,
|
||||
0x3300ff,
|
||||
0x333300,
|
||||
0x333333,
|
||||
0x333366,
|
||||
0x333399,
|
||||
0x3333cc,
|
||||
0x3333ff,
|
||||
0x336600,
|
||||
0x336633,
|
||||
0x336666,
|
||||
0x336699,
|
||||
0x3366cc,
|
||||
0x3366ff,
|
||||
0x339900,
|
||||
0x339933,
|
||||
0x339966,
|
||||
0x339999,
|
||||
0x3399cc,
|
||||
0x3399ff,
|
||||
0x33cc00,
|
||||
0x33cc33,
|
||||
0x33cc66,
|
||||
0x33cc99,
|
||||
0x33cccc,
|
||||
0x33ccff,
|
||||
0x33ff00,
|
||||
0x33ff33,
|
||||
0x33ff66,
|
||||
0x33ff99,
|
||||
0x33ffcc,
|
||||
0x33ffff,
|
||||
0x660000,
|
||||
0x660033,
|
||||
0x660066,
|
||||
0x660099,
|
||||
0x6600cc,
|
||||
0x6600ff,
|
||||
0x663300,
|
||||
0x663333,
|
||||
0x663366,
|
||||
0x663399,
|
||||
0x6633cc,
|
||||
0x6633ff,
|
||||
0x666600,
|
||||
0x666633,
|
||||
0x666666,
|
||||
0x666699,
|
||||
0x6666cc,
|
||||
0x6666ff,
|
||||
0x669900,
|
||||
0x669933,
|
||||
0x669966,
|
||||
0x669999,
|
||||
0x6699cc,
|
||||
0x6699ff,
|
||||
0x66cc00,
|
||||
0x66cc33,
|
||||
0x66cc66,
|
||||
0x66cc99,
|
||||
0x66cccc,
|
||||
0x66ccff,
|
||||
0x66ff00,
|
||||
0x66ff33,
|
||||
0x66ff66,
|
||||
0x66ff99,
|
||||
0x66ffcc,
|
||||
0x66ffff,
|
||||
0x990000,
|
||||
0x990033,
|
||||
0x990066,
|
||||
0x990099,
|
||||
0x9900cc,
|
||||
0x9900ff,
|
||||
0x993300,
|
||||
0x993333,
|
||||
0x993366,
|
||||
0x993399,
|
||||
0x9933cc,
|
||||
0x9933ff,
|
||||
0x996600,
|
||||
0x996633,
|
||||
0x996666,
|
||||
0x996699,
|
||||
0x9966cc,
|
||||
0x9966ff,
|
||||
0x999900,
|
||||
0x999933,
|
||||
0x999966,
|
||||
0x999999,
|
||||
0x9999cc,
|
||||
0x9999ff,
|
||||
0x99cc00,
|
||||
0x99cc33,
|
||||
0x99cc66,
|
||||
0x99cc99,
|
||||
0x99cccc,
|
||||
0x99ccff,
|
||||
0x99ff00,
|
||||
0x99ff33,
|
||||
0x99ff66,
|
||||
0x99ff99,
|
||||
0x99ffcc,
|
||||
0x99ffff,
|
||||
0xcc0000,
|
||||
0xcc0033,
|
||||
0xcc0066,
|
||||
0xcc0099,
|
||||
0xcc00cc,
|
||||
0xcc00ff,
|
||||
0xcc3300,
|
||||
0xcc3333,
|
||||
0xcc3366,
|
||||
0xcc3399,
|
||||
0xcc33cc,
|
||||
0xcc33ff,
|
||||
0xcc6600,
|
||||
0xcc6633,
|
||||
0xcc6666,
|
||||
0xcc6699,
|
||||
0xcc66cc,
|
||||
0xcc66ff,
|
||||
0xcc9900,
|
||||
0xcc9933,
|
||||
0xcc9966,
|
||||
0xcc9999,
|
||||
0xcc99cc,
|
||||
0xcc99ff,
|
||||
0xcccc00,
|
||||
0xcccc33,
|
||||
0xcccc66,
|
||||
0xcccc99,
|
||||
0xcccccc,
|
||||
0xccccff,
|
||||
0xccff00,
|
||||
0xccff33,
|
||||
0xccff66,
|
||||
0xccff99,
|
||||
0xccffcc,
|
||||
0xccffff,
|
||||
0xff0000,
|
||||
0xff0033,
|
||||
0xff0066,
|
||||
0xff0099,
|
||||
0xff00cc,
|
||||
0xff00ff,
|
||||
0xff3300,
|
||||
0xff3333,
|
||||
0xff3366,
|
||||
0xff3399,
|
||||
0xff33cc,
|
||||
0xff33ff,
|
||||
0xff6600,
|
||||
0xff6633,
|
||||
0xff6666,
|
||||
0xff6699,
|
||||
0xff66cc,
|
||||
0xff66ff,
|
||||
0xff9900,
|
||||
0xff9933,
|
||||
0xff9966,
|
||||
0xff9999,
|
||||
0xff99cc,
|
||||
0xff99ff,
|
||||
0xffcc00,
|
||||
0xffcc33,
|
||||
0xffcc66,
|
||||
0xffcc99,
|
||||
0xffcccc,
|
||||
0xffccff,
|
||||
0xffff00,
|
||||
0xffff33,
|
||||
0xffff66,
|
||||
0xffff99,
|
||||
0xffffcc,
|
||||
0xffffff,
|
||||
}
|
||||
|
||||
for i=0,255 do
|
||||
term.setPaletteColor(i,colors[i])
|
||||
end
|
||||
term.drawPixels(0,0,fb)
|
||||
|
||||
for i=0,255 do
|
||||
for y=1+i, h-i do
|
||||
for x=1+i, w-i do
|
||||
setPixel(x,y,i)
|
||||
end
|
||||
end
|
||||
term.drawPixels(1,1,fb)
|
||||
os.queueEvent("nosleep")
|
||||
os.pullEvent()
|
||||
end
|
||||
|
||||
for i=1, 1000 do
|
||||
pcall(function()
|
||||
setPixels(math.random(1,w),math.random(1,h),getPixels(math.random(1,w),math.random(1,h),math.random(1,w),math.random(1,h)))
|
||||
end)
|
||||
term.drawPixels(1,1,fb)
|
||||
os.queueEvent("nosleep")
|
||||
os.pullEvent()
|
||||
end
|
||||
setPixels(1,1,getPixels(w-50,h-50,50,50))
|
||||
term.drawPixels(0,0,fb)
|
||||
|
||||
local i=0
|
||||
for x=1, 16*4, 4 do
|
||||
for y=1, 16*4, 4 do
|
||||
setPixel(x,y,i)
|
||||
setPixel(x+1,y,i)
|
||||
setPixel(x+2,y,i)
|
||||
setPixel(x+3,y,i)
|
||||
setPixel(x,y+1,i)
|
||||
setPixel(x+1,y+1,i)
|
||||
setPixel(x+2,y+1,i)
|
||||
setPixel(x+3,y+1,i)
|
||||
setPixel(x,y+2,i)
|
||||
setPixel(x+1,y+2,i)
|
||||
setPixel(x+2,y+2,i)
|
||||
setPixel(x+3,y+2,i)
|
||||
setPixel(x,y+3,i)
|
||||
setPixel(x+1,y+3,i)
|
||||
setPixel(x+2,y+3,i)
|
||||
setPixel(x+3,y+3,i)
|
||||
i=i+1
|
||||
end
|
||||
end
|
||||
term.drawPixels(0,0,fb)
|
||||
|
||||
sleep(5)
|
||||
term.setGraphicsMode(false)
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
--:Minify:--
|
||||
local lib = {}
|
||||
|
||||
--[[
|
||||
Example framebuffer object
|
||||
|
||||
fb = {
|
||||
r={
|
||||
"","" -- repeat for # of rows length of string is the # of collums
|
||||
},
|
||||
g = {
|
||||
"",""
|
||||
},
|
||||
b = {
|
||||
"",""
|
||||
}
|
||||
}
|
||||
|
||||
Example font object
|
||||
|
||||
font = {
|
||||
width=int,
|
||||
hight=int,
|
||||
data={
|
||||
A={
|
||||
"Ga","gs","Gk" -- length of string is byte alligned with the string being a binary bitmap
|
||||
}
|
||||
}
|
||||
}
|
||||
]]
|
||||
|
||||
function lib.newFbObj(fb)
|
||||
local handle = {}
|
||||
|
||||
function handle.setPixel(x,y,color24)
|
||||
|
||||
end
|
||||
|
||||
function handle.line(x1,y1,x2,y2,color24)
|
||||
|
||||
end
|
||||
|
||||
function handle.box(x1,y1,x2,y2,color24)
|
||||
|
||||
end
|
||||
|
||||
function handle.filledBox(x1,y1,x2,y2,color24)
|
||||
|
||||
end
|
||||
|
||||
function handle.tri(x1,y1,x2,y2,x3,y3,color24)
|
||||
|
||||
end
|
||||
|
||||
function handle.filledTri(x1,y1,x2,y2,x3,y3,color24)
|
||||
|
||||
end
|
||||
|
||||
function handle.window(id,x,y,w,h,writeonly)
|
||||
|
||||
end
|
||||
|
||||
function handle.editWindow(id,x,y,w,h)
|
||||
|
||||
end
|
||||
|
||||
function handle.text(x,y,font,color24)
|
||||
|
||||
end
|
||||
|
||||
function handle.draw()
|
||||
|
||||
end
|
||||
|
||||
function handle.getPixel(x,y)
|
||||
|
||||
end
|
||||
|
||||
function handle.getPixels(x1y1,x2,y2)
|
||||
|
||||
end
|
||||
|
||||
return handle
|
||||
end
|
||||
@@ -239,7 +239,9 @@ else
|
||||
for _, cmd in ipairs(COMMANDS) do addCmd(cmd) end
|
||||
end
|
||||
|
||||
local screenW, screenH = syscall.devctl(1, "size")
|
||||
local sizeStr = syscall.devctl(1, "size")
|
||||
local screenW = tonumber(sizeStr:match("^(%d+)")) or 51
|
||||
local screenH = tonumber(sizeStr:match(";(%d+)")) or 19
|
||||
local pageSize = screenH - 2
|
||||
|
||||
local scroll = 0
|
||||
|
||||
+17
-8
@@ -1009,7 +1009,9 @@ local function getUserInput()
|
||||
syscall.write(1, syscall.getcwd())
|
||||
syscall.devctl(1,"sfgc",0xFFFFFF)
|
||||
syscall.write(1, "$ ")
|
||||
local curOffsetX,curOffsetY = syscall.devctl(1, "gpos")
|
||||
local curOffsetStr = syscall.devctl(1, "gpos")
|
||||
local curOffsetX = tonumber(curOffsetStr:sub(1, curOffsetStr:find(";")-1))
|
||||
local curOffsetY = tonumber(curOffsetStr:sub(curOffsetStr:find(";")+1))
|
||||
|
||||
local input = ""
|
||||
local blinkState = false
|
||||
@@ -1107,10 +1109,14 @@ local function getUserInput()
|
||||
local newInput, newCursor, needsRedraw = doTabComplete(input, cursorPos)
|
||||
if needsRedraw then
|
||||
input = newInput; cursorPos = newCursor
|
||||
local px,py = syscall.devctl(1, "gpos")
|
||||
local posStr = syscall.devctl(1, "gpos")
|
||||
local sep = posStr:find(";")
|
||||
local px = tonumber(posStr:sub(1, sep-1))
|
||||
local py = tonumber(posStr:sub(sep+1))
|
||||
if px > 1 then
|
||||
syscall.devctl(1,"spos",1,py)
|
||||
local tw = syscall.devctl(1,"size")
|
||||
local tsz = syscall.devctl(1,"size") or "51;19"
|
||||
local tw = tonumber(tsz:match("^(%d+)")) or 51
|
||||
syscall.write(1, string.rep(" ", tw))
|
||||
syscall.devctl(1,"spos",1,py)
|
||||
end
|
||||
@@ -1118,7 +1124,10 @@ local function getUserInput()
|
||||
syscall.devctl(1,"sfgc",0xFFFFFF); syscall.write(1, ":")
|
||||
syscall.devctl(1,"sfgc",0x00FFFF); syscall.write(1, syscall.getcwd())
|
||||
syscall.devctl(1,"sfgc",0xFFFFFF); syscall.write(1, "$ ")
|
||||
curOffsetX,curOffsetY = syscall.devctl(1, "gpos")
|
||||
posStr = syscall.devctl(1, "gpos")
|
||||
sep = posStr:find(";")
|
||||
curOffsetX = tonumber(posStr:sub(1, sep-1))
|
||||
curOffsetY = tonumber(posStr:sub(sep+1))
|
||||
dirty = true
|
||||
end
|
||||
elseif key=="\b" then
|
||||
@@ -1206,9 +1215,9 @@ local function runCommand(command)
|
||||
|
||||
local proc = syscall.spawn(function()
|
||||
-- Open standard fds so programs that don't do it themselves work correctly.
|
||||
--syscall.open("/proc/self/parent/fd/0", "r") -- fd 0 stdin
|
||||
--syscall.open("/proc/self/parent/fd/1", "w") -- fd 1 stdout
|
||||
--syscall.open("/proc/self/parent/fd/2", "w") -- fd 2 stderr
|
||||
syscall.open("/proc/self/parent/fd/0", "r") -- fd 0 stdin
|
||||
syscall.open("/proc/self/parent/fd/1", "w") -- fd 1 stdout
|
||||
syscall.open("/proc/self/parent/fd/2", "w") -- fd 2 stderr
|
||||
-- exec replaces this coroutine's code with a fresh isolated environment
|
||||
-- compiled from disk by the kernel (via loadExecutable -> freshUserEnv),
|
||||
-- so the child cannot share any upvalue or syscall table state with hysh.
|
||||
@@ -1222,7 +1231,7 @@ local function runCommand(command)
|
||||
return
|
||||
end
|
||||
if terminate then
|
||||
local ok2 = syscall.kill(proc, true)
|
||||
local ok2 = syscall.kill(proc)
|
||||
if ok2 then
|
||||
syscall.devctl(1,"sbgc",16); syscall.devctl(1,"sfgc",0xFF0000)
|
||||
print("\nProgram Terminated."); syscall.devctl(1,"sfgc",0xFFFFFF)
|
||||
|
||||
@@ -91,7 +91,8 @@ local function humanSize(size)
|
||||
return math.floor(size) .. sizePrefixes[scale]
|
||||
end
|
||||
|
||||
local sizeX = syscall.devctl(1, "size")
|
||||
local screenSizeStr = syscall.devctl(1, "size")
|
||||
local sizeX = tonumber(screenSizeStr:match("^(%d+)")) or 80
|
||||
|
||||
local list = fs.list(dir)
|
||||
list[#list+1] = "."
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
--:Minify:--
|
||||
local args={...}
|
||||
if #args<1 then print("trace [filepath] args") syscall.exit() end
|
||||
local fs=require("fs")
|
||||
local file = fs.readAllText(args[1])
|
||||
if not file then print("File not found") end
|
||||
local func, err = load(file, args[1], "t", _G)
|
||||
if not func then print(err) syscall.exit() end
|
||||
local ok,err = xpcall(func, debug.traceback, table.unpack(args, 2))
|
||||
if not ok then print(err) end
|
||||
@@ -237,7 +237,9 @@ end
|
||||
|
||||
local function getUserInput(prompt, history)
|
||||
c(C_PROMPT); w(prompt); c(1)
|
||||
local ox, oy = syscall.devctl(1, "gpos")
|
||||
local pos = syscall.devctl(1, "gpos")
|
||||
local ox = tonumber(pos:sub(1, pos:find(";")-1))
|
||||
local oy = tonumber(pos:sub(pos:find(";")+1))
|
||||
|
||||
local input = ""
|
||||
local cursor = 1
|
||||
|
||||
@@ -12,7 +12,9 @@
|
||||
local args = { ... }
|
||||
|
||||
local function termSize()
|
||||
return syscall.devctl(1, "size")
|
||||
local s = syscall.devctl(1, "size")
|
||||
return tonumber(s:match("^(%d+)")) or 80,
|
||||
tonumber(s:match(";(%d+)$")) or 24
|
||||
end
|
||||
local function tpos(x,y) syscall.devctl(1,"spos",x,y) end
|
||||
local function tfg(c) syscall.devctl(1,"sfgc",c) end
|
||||
|
||||
+14
-49
@@ -20,8 +20,7 @@ local spm = function(...)
|
||||
sysroot = "",
|
||||
init = false,
|
||||
help = false,
|
||||
overwrite = false,
|
||||
clean = false
|
||||
overwrite = false
|
||||
}
|
||||
|
||||
local i = 1
|
||||
@@ -217,7 +216,8 @@ local spm = function(...)
|
||||
|
||||
local function printpkgs(list)
|
||||
local colWidth=0
|
||||
local sizeX, sizeY = syscall.devctl(1, "size")
|
||||
local tmp = syscall.devctl(1, "size")
|
||||
local sizeX, sizeY = tonumber(tmp:sub(1, tmp:find(";")-1)), tonumber(tmp:sub(tmp:find(";")+1))
|
||||
for _, v in ipairs(list) do
|
||||
if #v + 2 > colWidth then colWidth = #v + 2 end
|
||||
end
|
||||
@@ -547,7 +547,7 @@ local spm = function(...)
|
||||
if cloptions.u then
|
||||
for i,v in ipairs(table.keys(pkgdb)) do
|
||||
local pkg, err = getPkg(v)
|
||||
if pkg and not found[v] then
|
||||
if pkg then
|
||||
needed[#needed+1] = pkg
|
||||
found[v]=true
|
||||
end
|
||||
@@ -586,7 +586,7 @@ local spm = function(...)
|
||||
|
||||
local files = {}
|
||||
for _,v in ipairs(needed) do
|
||||
if (not pkgdb[v.id]) or pkgdb[v.id].hash~=v.hash or cloptions.clean then
|
||||
if not pkgdb[v.id] or not pkgdb[v.id].hash==v.hash then
|
||||
w("Downloading "..v.id)
|
||||
local resp = get(v.tar)
|
||||
if not resp then
|
||||
@@ -689,46 +689,6 @@ local spm = function(...)
|
||||
syscall.exit()
|
||||
end
|
||||
end
|
||||
w("Writing files...")
|
||||
for i,v in pairs(files) do
|
||||
w("Writing package "..i)
|
||||
for f,c in pairs(v.data) do
|
||||
if not block[f] then
|
||||
fs.writeAllText(f,c)
|
||||
end
|
||||
end
|
||||
end
|
||||
w("Proccessing control files...")
|
||||
for i,v in pairs(files) do
|
||||
if v.control then
|
||||
for f,c in pairs(v.control) do
|
||||
if f=="symlinks.json" then
|
||||
local symlinks=json.decode(c)
|
||||
for src,dest in pairs(symlinks) do
|
||||
if syscall.exists(src) then
|
||||
if syscall.type(src)~="symlink" then
|
||||
if not v.data[src] then
|
||||
w("Failed to create symlink "..src)
|
||||
end
|
||||
else
|
||||
syscall.remove(src)
|
||||
end
|
||||
end
|
||||
w(src.." -> "..dest)
|
||||
syscall.symlink(dest, src)
|
||||
end
|
||||
elseif f=="setup.lua" then
|
||||
local func, err = load(c, "setupscript", "t", _G)
|
||||
if not func then
|
||||
w("Failed to load setup script for package "..i)
|
||||
else
|
||||
local ok, err = xpcall(func, debug.traceback)
|
||||
if not ok then w("Setup script for package "..i.." exited with error: "..err) end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
w("Updatating db...")
|
||||
for i,v in pairs(files) do
|
||||
local content={}
|
||||
@@ -737,12 +697,17 @@ local spm = function(...)
|
||||
content.files[f]=md5(c)
|
||||
end
|
||||
content.hash=v.hash
|
||||
content.symlinks={}
|
||||
if v.control and v.control["symlinks.json"] then
|
||||
content.symlinks=json.decode(v.control["symlinks.json"])
|
||||
end
|
||||
fs.writeAllText("var/spm/db/installed/"..i, json.encode(content))
|
||||
end
|
||||
w("Writing changes...")
|
||||
for i,v in pairs(files) do
|
||||
w("Writing "..i)
|
||||
for f,c in pairs(v.data) do
|
||||
if not block[f] then
|
||||
fs.writeAllText(f,c)
|
||||
end
|
||||
end
|
||||
end
|
||||
w("Install complete")
|
||||
log.close()
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ for i,v in pairs(kernel.processes) do
|
||||
else
|
||||
kernel.log("Successfully executed kernel task: " .. i)
|
||||
end
|
||||
end, i, nil,nil,nil,true)
|
||||
end, i)
|
||||
end
|
||||
|
||||
-- config file path setup
|
||||
@@ -36,16 +36,15 @@ for i,v in ipairs(files) do
|
||||
kernel.log("Error loading startup script '" .. filepath .. "': " .. err, "ERROR", 0xFF0000)
|
||||
else
|
||||
syscall.spawn(function()
|
||||
local status, err = xpcall(startupFunc, debug.traceback)
|
||||
local status, err = pcall(startupFunc)
|
||||
if not status then
|
||||
kernel.log("Error executing startup script '" .. filepath .. "': " .. err, "ERROR", 0xFF0000)
|
||||
else
|
||||
kernel.log("Successfully executed startup script: " .. filepath)
|
||||
end
|
||||
end, "startup:" .. v, nil,nil,nil,true)
|
||||
end, "startup:" .. v)
|
||||
end
|
||||
end
|
||||
kernel.log("sysinit complete")
|
||||
kernel.saveLog()
|
||||
|
||||
while true do
|
||||
|
||||
@@ -142,19 +142,13 @@ def process_root(src_root: Path, out_root: Path, minify: bool, micro: bool, arch
|
||||
|
||||
|
||||
def install_bootloader(arch: str, release: bool):
|
||||
boot_dir = BUILD_ROOT / "root" / ARCH_BOOT_DIR[arch]
|
||||
boot_dir = BUILD_ROOT / "$" / ARCH_BOOT_DIR[arch]
|
||||
eeprom = boot_dir / "eeprom"
|
||||
|
||||
eeprom_dst_name = "startup.lua" if release else "eeprom"
|
||||
print(f" Installing: eeprom -> Build/{eeprom_dst_name}")
|
||||
shutil.copy2(eeprom, BUILD_ROOT / eeprom_dst_name)
|
||||
|
||||
if arch=="cct":
|
||||
with open(BUILD_ROOT / "root/boot/fstab", "r") as file:
|
||||
content=file.read()
|
||||
with open(BUILD_ROOT / "root/boot/fstab", "w") as file:
|
||||
file.write("U root;/\n"+content)
|
||||
|
||||
|
||||
def run_build(minify: bool, micro: bool, include_test: bool, arch: Union[str, None], release: bool, prod: bool):
|
||||
clean()
|
||||
@@ -163,7 +157,7 @@ def run_build(minify: bool, micro: bool, include_test: bool, arch: Union[str, No
|
||||
cleanprod()
|
||||
PROD_ROOT.mkdir()
|
||||
|
||||
out_root = BUILD_ROOT / "root" if arch else BUILD_ROOT
|
||||
out_root = BUILD_ROOT / "$" if arch else BUILD_ROOT
|
||||
|
||||
process_root(SRC_ROOT, out_root, minify, micro, arch, False)
|
||||
if prod:
|
||||
@@ -176,11 +170,6 @@ def run_build(minify: bool, micro: bool, include_test: bool, arch: Union[str, No
|
||||
print("Installing bootloader files ...")
|
||||
install_bootloader(arch, release)
|
||||
print()
|
||||
boot_root = out_root / "boot"
|
||||
disk_root = BUILD_ROOT / "$"
|
||||
boot_root.rename(disk_root)
|
||||
|
||||
|
||||
|
||||
|
||||
def _make_firstboot_kmod(users):
|
||||
|
||||
+4
-30
@@ -2,8 +2,8 @@
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
import shutil, io
|
||||
import tarfile, gzip
|
||||
import shutil
|
||||
import tarfile
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent
|
||||
@@ -89,15 +89,6 @@ def read_dependencies(folder):
|
||||
|
||||
return dependencies if dependencies else DEFAULT_DEPENDENCIES
|
||||
|
||||
def reproducible_filter(info):
|
||||
info.mtime = 0
|
||||
info.uid = 0
|
||||
info.gid = 0
|
||||
info.uname = ""
|
||||
info.gname = ""
|
||||
|
||||
return info
|
||||
|
||||
|
||||
def create_package(folder):
|
||||
name = folder.name
|
||||
@@ -111,25 +102,8 @@ def create_package(folder):
|
||||
|
||||
debug(f"Packing {name}")
|
||||
|
||||
# Create deterministic TAR
|
||||
tar_data = io.BytesIO()
|
||||
|
||||
with tarfile.open(fileobj=tar_data, mode="w") as archive:
|
||||
archive.add(
|
||||
folder,
|
||||
arcname=name,
|
||||
filter=reproducible_filter,
|
||||
)
|
||||
|
||||
# Create deterministic gzip
|
||||
compressed = gzip.compress(
|
||||
tar_data.getvalue(),
|
||||
compresslevel=9,
|
||||
mtime=0,
|
||||
)
|
||||
|
||||
with open(tarball, "wb") as file:
|
||||
file.write(compressed)
|
||||
with tarfile.open(tarball, "w:gz") as archive:
|
||||
archive.add(folder, arcname=name, filter=exclude)
|
||||
|
||||
package_hash = sha256(tarball)
|
||||
|
||||
|
||||
@@ -7,6 +7,6 @@
|
||||
],
|
||||
"dependencies": [],
|
||||
"version": "1.0.0",
|
||||
"hash": "32ab474f175e911f0625c8ab33202fae",
|
||||
"hash": "10231c287c97ab72adf77117886d2de3",
|
||||
"tarball": "https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/packages/raw/Hyperion-core.tar.gz"
|
||||
}
|
||||
|
||||
@@ -8,6 +8,6 @@
|
||||
],
|
||||
"dependencies": [],
|
||||
"version": "1.0.0",
|
||||
"hash": "a4e33985213691b829940e014685ba0d",
|
||||
"hash": "a44f05701db0feef517f196047a198d7",
|
||||
"tarball": "https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/packages/raw/Hyperion-firmware-ac.tar.gz"
|
||||
}
|
||||
|
||||
@@ -4,6 +4,6 @@
|
||||
"authors": [],
|
||||
"dependencies": [],
|
||||
"version": "0.0.0",
|
||||
"hash": "dd93f2bd27640aea671155c26c3c47c5",
|
||||
"hash": "cba0823f33d942e92ddad54c2d4a7004",
|
||||
"tarball": "https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/packages/raw/Hyperion-firmware-addon-cct.tar.gz"
|
||||
}
|
||||
|
||||
@@ -7,6 +7,6 @@
|
||||
],
|
||||
"dependencies": [],
|
||||
"version": "1.0.0",
|
||||
"hash": "b6c3a1bff52636f79f4c8f39def03aa2",
|
||||
"hash": "4021ef17d9a26200b255e5fdad3766cc",
|
||||
"tarball": "https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/packages/raw/Hyperion-firmware-ccpc.tar.gz"
|
||||
}
|
||||
|
||||
@@ -7,6 +7,6 @@
|
||||
],
|
||||
"dependencies": [],
|
||||
"version": "1.3.0",
|
||||
"hash": "15dbb52d9c151a30de521f13e2a16278",
|
||||
"hash": "341e92ee642399fb7b6892be669ad881",
|
||||
"tarball": "https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/packages/raw/Hyperion-firmware-cct.tar.gz"
|
||||
}
|
||||
|
||||
@@ -4,6 +4,6 @@
|
||||
"authors": [],
|
||||
"dependencies": [],
|
||||
"version": "0.0.0",
|
||||
"hash": "c8fec163cdbcda36fe01d8bb9fd4e327",
|
||||
"hash": "f9fcd282170185f174fd5c1e7b9cb93e",
|
||||
"tarball": "https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/packages/raw/Hyperion-firmware-lua.tar.gz"
|
||||
}
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
{
|
||||
"id": "Hyperion-firmware-oc",
|
||||
"description": "firmware for Opencomputers mod",
|
||||
"description": "firmware for Opencomputers",
|
||||
"authors": [
|
||||
"Hyperion",
|
||||
"Astronand",
|
||||
"Xtimhedae"
|
||||
"Hyperion"
|
||||
],
|
||||
"dependencies": [],
|
||||
"version": "1.0.0",
|
||||
"hash": "913d68c1c1a42afd42bfbab61a10729e",
|
||||
"version": "0.1.0",
|
||||
"hash": "3090e7b03b8212052fb697987b1f5024",
|
||||
"tarball": "https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/packages/raw/Hyperion-firmware-oc.tar.gz"
|
||||
}
|
||||
|
||||
@@ -4,6 +4,6 @@
|
||||
"authors": [],
|
||||
"dependencies": [],
|
||||
"version": "0.0.0",
|
||||
"hash": "c7971267c5306ee06ba943e241647e64",
|
||||
"hash": "ceb96ec6a50538e6d162215639698077",
|
||||
"tarball": "https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/packages/raw/Hyperion-firmware-vm.tar.gz"
|
||||
}
|
||||
|
||||
@@ -8,6 +8,6 @@
|
||||
],
|
||||
"dependencies": [],
|
||||
"version": "1.5.0",
|
||||
"hash": "d45b18adc188a3090e5f1d9aca687347",
|
||||
"hash": "21a9ab0c0637273e97527870acc24bba",
|
||||
"tarball": "https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/packages/raw/Hyperion-kernel.tar.gz"
|
||||
}
|
||||
|
||||
+1
-1
@@ -7,6 +7,6 @@
|
||||
],
|
||||
"dependencies": [],
|
||||
"version": "1.0.0",
|
||||
"hash": "85daa009881b6be44b84b3641138670a",
|
||||
"hash": "89efe44800c2559b125c3e5315a5d5a4",
|
||||
"tarball": "https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/packages/raw/bit32.tar.gz"
|
||||
}
|
||||
|
||||
@@ -7,6 +7,6 @@
|
||||
],
|
||||
"dependencies": [],
|
||||
"version": "1.0.0",
|
||||
"hash": "4193c27a6b98ed75bfcaaddc3e21f967",
|
||||
"hash": "c41dc8025c5bcf657e5b52c40ddfe6be",
|
||||
"tarball": "https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/packages/raw/blake2s.tar.gz"
|
||||
}
|
||||
|
||||
@@ -8,6 +8,6 @@
|
||||
],
|
||||
"dependencies": [],
|
||||
"version": "1.0.0",
|
||||
"hash": "34996938f359f52e92a388483c3fb5c9",
|
||||
"hash": "988c894f0faa19ff79f26270e6567c5f",
|
||||
"tarball": "https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/packages/raw/coreutils.tar.gz"
|
||||
}
|
||||
|
||||
@@ -7,6 +7,6 @@
|
||||
],
|
||||
"dependencies": [],
|
||||
"version": "1.0.0-release",
|
||||
"hash": "821c762d067ab72abe100351c2f74f63",
|
||||
"hash": "23ef21eef7e266d416bddee1eb673e30",
|
||||
"tarball": "https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/packages/raw/deflate.tar.gz"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"id": "gfx",
|
||||
"id": "gfxterm",
|
||||
"description": "package providing kernel support for framebuffers and graphics",
|
||||
"authors": [
|
||||
"Hyperion",
|
||||
@@ -7,6 +7,6 @@
|
||||
],
|
||||
"dependencies": [],
|
||||
"version": "1.0.0",
|
||||
"hash": "aaf9664adb4d85aa6d0d504692e8ec26",
|
||||
"tarball": "https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/packages/raw/gfx.tar.gz"
|
||||
"hash": "5c423cc612d946e70e54fb517a71d22e",
|
||||
"tarball": "https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/packages/raw/gfxterm.tar.gz"
|
||||
}
|
||||
+1
-1
@@ -7,6 +7,6 @@
|
||||
],
|
||||
"dependencies": [],
|
||||
"version": "1.3.0",
|
||||
"hash": "cbc352d49cb9837ee825471351dd9ffc",
|
||||
"hash": "c3c914f7aecc642464cb5b14f2e135fa",
|
||||
"tarball": "https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/packages/raw/hysh.tar.gz"
|
||||
}
|
||||
|
||||
@@ -7,6 +7,6 @@
|
||||
],
|
||||
"dependencies": [],
|
||||
"version": "1.0.0",
|
||||
"hash": "1f69e2cfa0d86c419ab1927221230ae8",
|
||||
"hash": "81177ba78d1febbd6fff59bb23a16080",
|
||||
"tarball": "https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/packages/raw/iniparse.tar.gz"
|
||||
}
|
||||
|
||||
@@ -7,6 +7,6 @@
|
||||
],
|
||||
"dependencies": [],
|
||||
"version": "1.0.0",
|
||||
"hash": "897e5abc980bda9051fff8f72c864251",
|
||||
"hash": "203ace7ad9135d21691e2a6b9e62be9f",
|
||||
"tarball": "https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/packages/raw/installer.tar.gz"
|
||||
}
|
||||
|
||||
+1
-1
@@ -7,6 +7,6 @@
|
||||
],
|
||||
"dependencies": [],
|
||||
"version": "1.0.0",
|
||||
"hash": "f22c3b6c445f9390195654246b6dca03",
|
||||
"hash": "6602fa70ec8e1288015168eddf817664",
|
||||
"tarball": "https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/packages/raw/json.tar.gz"
|
||||
}
|
||||
|
||||
+1
-1
@@ -7,6 +7,6 @@
|
||||
],
|
||||
"dependencies": [],
|
||||
"version": "1.2.0",
|
||||
"hash": "7479232dae56ad762119a8c57767e617",
|
||||
"hash": "31e0103563ca3443e5c3ab8257325138",
|
||||
"tarball": "https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/packages/raw/lua.tar.gz"
|
||||
}
|
||||
|
||||
+1
-1
@@ -7,6 +7,6 @@
|
||||
],
|
||||
"dependencies": [],
|
||||
"version": "1.0.0",
|
||||
"hash": "8fa15ac698fe19927d0d860f9b813c5f",
|
||||
"hash": "916d8f4dabdcef58524e9a4c59ea8957",
|
||||
"tarball": "https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/packages/raw/micro.tar.gz"
|
||||
}
|
||||
|
||||
+1
-1
@@ -8,6 +8,6 @@
|
||||
],
|
||||
"dependencies": [],
|
||||
"version": "1.0.0",
|
||||
"hash": "a6f6beecb0828a355cca23f90c77dbd9",
|
||||
"hash": "87cb37074598899bf446d76bee0945a4",
|
||||
"tarball": "https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/packages/raw/minify.tar.gz"
|
||||
}
|
||||
|
||||
+1
-1
@@ -7,6 +7,6 @@
|
||||
],
|
||||
"dependencies": [],
|
||||
"version": "1.0.0",
|
||||
"hash": "90583ad14ffc68fbbec09f03b926cdaf",
|
||||
"hash": "c48c7078c5b5c9309ed3d6ee4fb38c2c",
|
||||
"tarball": "https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/packages/raw/pid.tar.gz"
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user