12 Commits
192 changed files with 5539 additions and 4567 deletions

No files matched your search

+2 -2
View File
@@ -6,10 +6,10 @@
"printf", "printf",
"printInline", "printInline",
"toHex", "toHex",
"loadcstr",
"userinput" "userinput"
], ],
"Lua.diagnostics.disable": [ "Lua.diagnostics.disable": [
"need-check-nil", "need-check-nil"
"param-type-mismatch"
] ]
} }
@@ -1,318 +0,0 @@
--:Minify:--
local kernel=...
if not kernel.cct then return end
local plt={
[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,
}
local iplt={}
for i=0, #plt do
iplt[plt[i]]=i
end
local l1f,l1d,l2,ops={},{},{},0
local function findClosest(tbl, target)
local closest = nil
local smallestDiff = math.huge
for k, _ in pairs(tbl) do
if k==target then return k end
local diff = math.abs(k - target)
if diff < smallestDiff then
smallestDiff = diff
closest = k
end
end
return closest
end
local function aprox(c24)
ops = ops + 1
if ops % 1024 == 0 then
l1d = {}
l1f = {}
end
if ops % 8192 == 0 then
l2 = {}
end
if l2[c24] ~= nil then
return l2[c24]
end
if l1d[c24] ~= nil then
l1f[c24] = l1f[c24] + 1
if l1f[c24] >= 16 then
l2[c24] = l1d[c24]
l1d[c24] = nil
l1f[c24] = nil
return l2[c24]
end
return l1d[c24]
end
local closestKey = findClosest(iplt, c24)
if not closestKey then return nil end
local value = iplt[closestKey]
l1d[c24] = value
l1f[c24] = 1
return value
end
local function splitFramebufferToStrings(fb, w)
local rows = {}
for i = 1, #fb, w do
local row_chars = {}
for j = 0, w - 1 do
local val = fb[i + j]
if val ~= nil then
table.insert(row_chars, string.char(aprox(val)))
else
break
end
end
table.insert(rows, table.concat(row_chars))
end
return rows
end
local function creategfx(term, id)
local active=false
term.setGraphicsMode(2)
for i=0, #plt do
term.setPaletteColor(i,plt[i])
end
term.setGraphicsMode(false)
term.setPaletteColor(0x1, 0xFFFFFF)
term.setPaletteColor(0x2, 0xFF0000)
term.setPaletteColor(0x4, 0x00FF00)
term.setPaletteColor(0x8, 0x0000FF)
term.setPaletteColor(0x10, 0x00FFFF)
term.setPaletteColor(0x20, 0xFF00FF)
term.setPaletteColor(0x40, 0xFFFF00)
term.setPaletteColor(0x80, 0xFF6D00)
term.setPaletteColor(0x100, 0x6DFF55)
term.setPaletteColor(0x200, 0x24FFFF)
term.setPaletteColor(0x400, 0x924900)
term.setPaletteColor(0x800, 0x6D6D55)
term.setPaletteColor(0x1000, 0xDBDBAA)
term.setPaletteColor(0x2000, 0x6D00FF)
term.setPaletteColor(0x4000, 0xB6FF00)
term.setPaletteColor(0x8000, 0x000000)
local handle={
gplt=function()
return setmetatable({},{__index=plt,__usermeta=false,__pairs=function() return pairs(plt) end})
end,
spixel=function(x,y,c)
term.setPixel(x,y,aprox(c))
end,
gpixel=function(x,y)
return term.getPixel()
end,
drawFB=function(x,y,fb,w)
local f=splitFramebufferToStrings(fb,w)
term.drawPixels(x,y,f)
end,
box=function(x,y,w,h,c,fill)
c=aprox(c)
if not fill then
term.drawPixels(x,y,c,w,1)
term.drawPixels(x,y,c,1,h)
term.drawPixels(x+w-1,y,c,1,h)
term.drawPixels(x,y+h-1,c,w,1)
else
term.drawPixels(x,y,c,w,h)
end
end,
circle=function(xc,yc,r,c,fill)
c=aprox(c)
if not fill then
local x = 0
local y = r
local d = 3 - 2 * r
-- Helper function to plot all 8 symmetric points
local function plot8Points(x, y)
term.setPixel(xc + x, yc + y, c)
term.setPixel(xc - x, yc + y, c)
term.setPixel(xc + x, yc - y, c)
term.setPixel(xc - x, yc - y, c)
term.setPixel(xc + y, yc + x, c)
term.setPixel(xc - y, yc + x, c)
term.setPixel(xc + y, yc - x, c)
term.setPixel(xc - y, yc - x, c)
end
plot8Points(x, y)
while y >= x do
x = x + 1
if d > 0 then
y = y - 1
d = d + 4 * (x - y) + 10
else
d = d + 4 * x + 6
end
plot8Points(x, y)
end
else
local x = 0
local y = r
local d = 3 - 2 * r
-- Helper to fill rows using symmetry
local function fillRows(x, y)
-- Width is (2 * coordinate) + 1 to include the center column
local strX = string.rep(string.char(c), 2 * x + 1)
local strY = string.rep(string.char(c), 2 * y + 1)
-- Draw the horizontal spans
term.drawPixels(xc - x, yc + y, {strX})
term.drawPixels(xc - x, yc - y, {strX})
term.drawPixels(xc - y, yc + x, {strY})
term.drawPixels(xc - y, yc - x, {strY})
end
fillRows(x, y)
while y >= x do
x = x + 1
if d > 0 then
y = y - 1
d = d + 4 * (x - y) + 10
else
d = d + 4 * x + 6
end
fillRows(x, y)
end
end
end,
line=function(x1,y1,x2,y2,c)
x1=math.floor(x1+0.5)
y1=math.floor(y1+0.5)
x2=math.floor(x2+0.5)
y2=math.floor(y2+0.5)
c=aprox(c)
local w,h=term.getSize(2)
local dx=math.abs(x2-x1)
local dy=math.abs(y2-y1)
local sx=x1<x2 and 1 or -1
local sy=y1<y2 and 1 or -1
local err=dx-dy
while true do
if 0<x1 and x1<=w and 0<y1 and y1<=h then
term.setPixel(x1,y1,c)
end
if x1==x2 and y1==y2 then
break
end
local e2=2*err
if e2>-dy then
err=err-dy
x1=x1+sx
end
if e2<dx then
err=err+dx
y1=y1+sy
end
end
end,
setMode=function(state)
if state then
term.setGraphicsMode(2)
for i=0, #plt do
term.setPaletteColor(i,plt[i])
end
active=true
else
term.setGraphicsMode(false)
term.setPaletteColor(0x1, 0xFFFFFF)
term.setPaletteColor(0x2, 0xFF0000)
term.setPaletteColor(0x4, 0x00FF00)
term.setPaletteColor(0x8, 0x0000FF)
term.setPaletteColor(0x10, 0x00FFFF)
term.setPaletteColor(0x20, 0xFF00FF)
term.setPaletteColor(0x40, 0xFFFF00)
term.setPaletteColor(0x80, 0xFF6D00)
term.setPaletteColor(0x100, 0x6DFF55)
term.setPaletteColor(0x200, 0x24FFFF)
term.setPaletteColor(0x400, 0x924900)
term.setPaletteColor(0x800, 0x6D6D55)
term.setPaletteColor(0x1000, 0xDBDBAA)
term.setPaletteColor(0x2000, 0x6D00FF)
term.setPaletteColor(0x4000, 0xB6FF00)
term.setPaletteColor(0x8000, 0x000000)
active=false
end
end,
getMode=function()
return active
end,
size=function()
return term.getSize(2)
end,
drawRun=function(y,x1,x2,c)
term.drawPixels(x1,y,c,{string.rep(string.char(aprox(c)),x1-x2)})
end
}
return handle
end
for id,obj in pairs(kernel.cct.term) do
if obj.setGraphicsMode then
kernel.cct.gfx[id]=creategfx(obj, id)
end
end
+344 -3
View File
@@ -1,3 +1,344 @@
---@diagnostic disable-next-line: undefined-global --:Minify:--
local bootdrive=__UEFI.bootDrive 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
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 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
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 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
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
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 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 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)
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 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
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
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 displaySuperBadError("Fatal error during boot: " .. err) end
while true do coroutine.yield() end
@@ -1,146 +0,0 @@
local comp,disks,autocomplete,ev,ent,data,path,exit,dirty,ls,eb,sb,bp=components,{},false,nil,true,"","",false,true,{},false
local c,gpu=comp:getFirst("computer"),comp:getFirst("gpu")
if gpu then sb=gpu:newBuffer(48,32) end
--c.nvram.data="1/ac/boot.lua"
local function resetScreens()
sb=gpu:newBuffer(64,48)
for typ, obj in comp:list() do
if typ=="screen" then gpu:assignBuffer(sb,obj) end
end
end
resetScreens()
local function displayError(err)
if not gpu then return end
gpu:freeAllBuffers()
resetScreens()
sb:pasteText(0,0,"FILL_SPILL",err)
end
local function bootloader()
for typ, obj in comp:list() do
if typ~="massStorage" then goto skip end
disks[tostring(obj.diskId)]=obj
::skip::
end
local function display(text)
print(text)
if not sb then print("NO_SB") return end
sb:pasteText(0,0,"FILL_SPILL",text)
end
local function boot()
local pos = path:find("/", 1, true)
if not pos then displayError("EINVAL") sleep(5) return end
local id,p = path:sub(1,pos-1),path:sub(pos)
if not disks[id] then displayError("ENODEV") sleep(5) return end
local init,err=load(disks[id]:open(p):read(-1),"@init","t",_G)
if err then displayError(err) sleep(5) return end
local ret = {xpcall(init, debug.traceback)}
if not ret[1] then
displayError("EFI PROGRAM ERROR: "..err)
sleep(5)
return false
else
if ret[2]=="ENTER_BIOS" then
c.nvram.ENTER_BIOS=true
return true
end
return table.unpack(ret, 2)
end
end
if c.nvram then
path=c.nvram.data or ""
eb=c.nvram.ENTER_BIOS
c.nvram.ENTER_BIOS=false
end
local function drainev()
repeat
ev={c:getMachineEvent()}
if ev[1]=="charTyped" then ent=false end
until not ev[1]
end
if path=="" or eb then drainev() ent=false else
display("Press key to enter boot menu...")
sleep(3)
drainev()
if ent then return boot() end
end
local function proc(key)
if key=="\n" then exit=true
elseif key=="\b" then path=path:sub(1,#path-1) dirty=true
elseif key=="\t" then print("autocomplete")
else path=path..key dirty=true end
end
local function get()
data=""
local pos = path:find("/", 1, true)
local trailingslash=false
if path:sub(#path)=="/" then trailingslash=true end
if not pos then
for id in pairs(disks) do
if id:sub(1,#path)==path then
data=data..id.."\n"
end
end
else
if not trailingslash then
local n=""
for i=#path, 0, -1 do
if path:sub(i,i)~="/" then
n=path:sub(i,i)..n
else break end
end
local ok,ret=pcall(function()
return disks[path:sub(1,pos-1)]:list(path:sub(pos,#path-#n))
end)
if ok then
ls = ret
end
for _,p in ipairs(ls) do
if p:sub(1,#n) == n then
data=data..p.."\n"
end
end
else
local ok,ret=pcall(function()
return disks[path:sub(1,pos-1)]:list(path:sub(pos))
end)
if ok then
ls=ret
for _,p in ipairs(ls) do
data=data..p.."\n"
end
end
end
end
end
if not ent then
while true do
get()
if dirty then
for i=0,31 do sb:clearRow(i) end
display("Select boot file...\n"..path.."\n\n"..data)
dirty=false
end
ev={c:getMachineEvent()}
if ev[1]=="charTyped" then proc(ev[2]) end
if exit then return boot() end
end
end
end
local ret={xpcall(bootloader,debug.traceback)}
if not ret[1] then
displayError(ret[2])
error(ret[2])
else
return table.unpack(ret, 2)
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
@@ -1,5 +0,0 @@
--:Minify:--
local kernel=...
if kernel.arch~="cct" then
kernel.deny("cc-tweaked/31_keyboards.kmod")
end
@@ -0,0 +1,387 @@
--:Minify:--
local BOOT_DRIVE_PATH = ({...})[1] or "/$"
---@diagnostic disable-next-line: undefined-global
local term = term
local os = os
local function write(text)
local x, y = term.getCursorPos()
local w, h = term.getSize()
for i = 1, #text do
local c = text:sub(i, i)
if c == "\n" then
y = y + 1
x = 1
elseif c == "\t" then
local tabSize = 4
local spaces = tabSize - ((x - 1) % tabSize)
term.write(string.rep(" ", spaces))
x = x + spaces
elseif c == "\b" then
if x > 1 then
x = x - 1
term.setCursorPos(x, y)
term.write(" ")
term.setCursorPos(x, y)
end
else
if x <= w and y <= h then
term.setCursorPos(x, y)
term.write(c)
x = x + 1
end
end
if x > w then
x = 1
y = y + 1
end
if y - 1 >= h then
term.scroll(1)
y = h
term.setCursorPos(x, y)
end
end
term.setCursorPos(x, y)
end
local function displaySuperBadError(err)
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
term.setCursorBlink(false)
local ok, err = xpcall(function()
local apis = {BOOT_DRIVE_PATH = BOOT_DRIVE_PATH}
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
end
local acekeys={
[apis.keys.enter]="\n",
[apis.keys.tab]="\t",
[apis.keys.backspace]="\b",
[apis.keys.up]="\17",
[apis.keys.down]="\18",
[apis.keys.left]="\19",
[apis.keys.right]="\20",
}
function sleep(time)
local stoptime = apis.os.clock() + (time)
while stoptime > apis.os.clock() do end
end
apis.term.setPaletteColor(0x1, 0xFFFFFF) -- #000000
apis.term.setPaletteColor(0x2, 0xFF0000) -- #FFFFFF
apis.term.setPaletteColor(0x4, 0x00FF00) -- #FF0000
apis.term.setPaletteColor(0x8, 0x0000FF) -- #00FF00
apis.term.setPaletteColor(0x10, 0x00FFFF) -- #0000FF
apis.term.setPaletteColor(0x20, 0xFF00FF) -- #00FFFF
apis.term.setPaletteColor(0x40, 0xFFFF00) -- #FF00FF
apis.term.setPaletteColor(0x80, 0xFF6D00) -- #FFFF00
apis.term.setPaletteColor(0x100, 0x6DFF55) -- #FF6D00
apis.term.setPaletteColor(0x200, 0x24FFFF) -- #6DFF55
apis.term.setPaletteColor(0x400, 0x924900) -- #24FFFF
apis.term.setPaletteColor(0x800, 0x6D6D55) -- #924900
apis.term.setPaletteColor(0x1000, 0xDBDBAA) -- #6D6D55
apis.term.setPaletteColor(0x2000, 0x6D00FF) -- #DBDBAA
apis.term.setPaletteColor(0x4000, 0xB6FF00) -- #6D00FF
apis.term.setPaletteColor(0x8000, 0x000000) -- #B6FF00
local function getFile(path)
local file = apis.fs.open(path, "r")
if not file then
displaySuperBadError("Could not open file: " .. path)
end
local content = file.readAll()
file.close()
return content
end
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
if not fs then displaySuperBadError("Could not load initfs.") end
if not apis.fs.exists("/nvram.dat") then
local file = apis.fs.open("/nvram.dat", "w")
file.write("Hello, World!")
file.close()
end
local eeprom
if apis.fs.exists("/startup.lua") then
eeprom="/startup.lua"
elseif apis.fs.exists("/eeprom") then
eeprom="/eeprom"
end
local eventQueue = {}
local function queueEvent(event, ...)
table.insert(eventQueue, {event, ...})
end
local colors = {
[0x000000]=0x0001,
[0xFFFFFF]=0x0002,
[0xFF0000]=0x0004,
[0x00FF00]=0x0008,
[0x0000FF]=0x0010,
[0x00FFFF]=0x0020,
[0xFF00FF]=0x0040,
[0xFFFF00]=0x0080,
[0xFF6D00]=0x0100,
[0x6DFF55]=0x0200,
[0x24FFFF]=0x0400,
[0x924900]=0x0800,
[0x6D6D55]=0x1000,
[0xDBDBAA]=0x2000,
[0x6D00FF]=0x4000,
[0xB6FF00]=0x8000
}
local fg,bg=0x6D6D55,0x000000
local l1f,l1d,l2,ops={},{},{},0
local function findClosest(tbl, target)
local closest = nil
local smallestDiff = math.huge
for k, _ in pairs(tbl) do
local diff = math.abs(k - target)
if diff < smallestDiff then
smallestDiff = diff
closest = k
end
end
return closest
end
local function aprox(c24)
ops = ops + 1
if ops % 1024 == 0 then
l1d = {}
l1f = {}
end
if ops % 8192 == 0 then
l2 = {}
end
if l2[c24] ~= nil then
return l2[c24]
end
if l1d[c24] ~= nil then
l1f[c24] = l1f[c24] + 1
if l1f[c24] >= 16 then
l2[c24] = l1d[c24]
l1d[c24] = nil
l1f[c24] = nil
return l2[c24]
end
return l1d[c24]
end
local closestKey = findClosest(colors, c24)
if not closestKey then return nil end
local value = colors[closestKey]
l1d[c24] = value
l1f[c24] = 1
return value
end
local EFI = {
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,
getMachineEvent = function()
if #eventQueue > 0 then
return table.unpack(table.remove(eventQueue, 1))
else
return nil
end
end,
getEEPROM = function() return getFile(eeprom) end,
setEEPROM = function(_, text)
local h = apis.fs.open(eeprom, "w")
h.write(text)
h.close()
end,
initfs=fs,
disks=initFs,
screenCtl={
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(aprox(color))
end,
setTextColor = function(_, color)
apis.term.setTextColor(aprox(color))
end,
getBackgroundColor = function()
return bg
end,
getTextColor = function()
return fg
end,
enable=function() end,
disable=function() end
},
architecture="cct",
getNvram = function() return getFile("/nvram.dat") end,
setNvram = function(_, text)
local h = apis.fs.open("/nvram.dat", "w")
h.write(text)
h.close()
end,
firmware=apis,
reboot=false
}
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, EFI)
if not ok and not EFI.reboot then displaySuperBadError(err) end
if err then
apis.os.reboot()
else
apis.os.shutdown()
end
end)
function coroutine.resumeWithTimeout(co, timeout, ...)
local startTime = EFI.getEpochMs()
debug.sethook(co, function()
if EFI.getEpochMs() > 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 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
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
end
if status == "error" or coroutine.status(kernelCoro) == "dead" then
if EFI.reboot then
apis.os.reboot()
end
displaySuperBadError("Kernel error: " .. tostring(err))
coroutine.yield("key")
end
initFs:refresh()
end
end, debug.traceback)
if not ok then displaySuperBadError("Fatal error during boot: " .. err) end
while true do coroutine.yield("key") end
@@ -0,0 +1,119 @@
--:Minify:--
local BOOT_DRIVE_PATH=({...})[1] or "/$"
-- UnBIOS by JackMacWindows
-- This will undo most of the changes/additions made in the BIOS, but some things may remain wrapped if `debug` is unavailable
-- To use, just place a `bios.lua` in the root of the drive, and run this program
-- Here's a list of things that are irreversibly changed:
-- * both `bit` and `bit32` are kept for compatibility
-- * string metatable blocking (on old versions of CC)
-- In addition, if `debug` is not available these things are also irreversibly changed:
-- * old Lua 5.1 `load` function (for loading from a function)
-- * `loadstring` prefixing (before CC:T 1.96.0)
-- * `http.request`
-- * `os.shutdown` and `os.reboot`
-- * `peripheral`
-- * `turtle.equip[Left|Right]`
-- Licensed under the MIT license
local args = {...}
local keptAPIs = {keys=true, bit32 = true, bit = true, ccemux = true, config = true, coroutine = true, debug = true, fs = true, http = true, mounter = true, os = true, periphemu = true, peripheral = true, redstone = true, rs = true, term = true, utf8 = true, _HOST = true, _CC_DEFAULT_SETTINGS = true, _CC_DISABLE_LUA51_FEATURES = true, _VERSION = true, assert = true, collectgarbage = true, error = true, gcinfo = true, getfenv = true, getmetatable = true, ipairs = true, __inext = true,load = true, loadstring = true, math = true, newproxy = 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, unpack = true, xpcall = true, turtle = true, pocket = true, commands = true, _G = true}
local t = {}
for k in pairs(_G) do if not keptAPIs[k] then table.insert(t, k) end end
for _,k in ipairs(t) do _G[k] = nil end
local native = _G.term.native()
for _, method in ipairs {"nativePaletteColor", "nativePaletteColour", "screenshot"} do native[method] = _G.term[method] end
_G.term = native
if _G.http then
_G.http.checkURL = _G.http.checkURLAsync
_G.http.websocket = _G.http.websocketAsync
end
if _G.commands then _G.commands = _G.commands.native end
if _G.turtle then _G.turtle.native, _G.turtle.craft = nil end
local delete = {os = {"version", "pullEventRaw", "pullEvent", "run", "loadAPI", "unloadAPI", "sleep"}, http = _G.http and {"get", "post", "put", "delete", "patch", "options", "head", "trace", "listen", "checkURLAsync", "websocketAsync"}, fs = {"complete", "isDriveRoot"}}
for k,v in pairs(delete) do for _,a in ipairs(v) do _G[k][a] = nil end end
-- Set up TLCO
-- This functions by crashing `rednet.run` by removing `os.pullEventRaw`. Normally
-- this would cause `parallel` to throw an error, but we replace `error` with an
-- empty placeholder to let it continue and return without throwing. This results
-- in the `pcall` returning successfully, preventing the error-displaying code
-- from running - essentially making it so that `os.shutdown` is called immediately
-- after the new BIOS exits.
--
-- From there, the setup code is placed in `term.native` since it's the first
-- thing called after `parallel` exits. This loads the new BIOS and prepares it
-- for execution. Finally, it overwrites `os.shutdown` with the new function to
-- allow it to be the last function called in the original BIOS, and returns.
-- From there execution continues, calling the `term.redirect` dummy, skipping
-- over the error-handling code (since `pcall` returned ok), and calling
-- `os.shutdown()`. The real `os.shutdown` is re-added, and the new BIOS is tail
-- called, which effectively makes it run as the main chunk.
local olderror = error
_G.error = function() end
_G.term.redirect = function() end
function _G.term.native()
_G.term.native = nil
_G.term.redirect = nil
_G.error = olderror
term.setBackgroundColor(32768)
term.setTextColor(1)
term.setCursorPos(1, 1)
term.setCursorBlink(true)
term.clear()
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 /boot/cct/boot.lua. UnBIOS cannot continue.")
term.setCursorPos(1, 2)
term.write("Press any key to continue")
coroutine.yield("key")
os.shutdown()
end
local fn, err = loadstring(file.readAll(), "@bootloader")
file.close()
if fn == nil then
term.setCursorBlink(false)
term.setTextColor(16384)
term.write("Could not load /boot/cc/boot.lua. UnBIOS cannot continue.")
term.setCursorPos(1, 2)
term.write(err)
term.setCursorPos(1, 3)
term.write("Press any key to continue")
coroutine.yield("key")
os.shutdown()
end
setfenv(fn, _G)
local oldshutdown = os.shutdown
os.shutdown = function()
os.shutdown = oldshutdown
return fn(BOOT_DRIVE_PATH)
end
end
if debug then
-- Restore functions that were overwritten in the BIOS
-- Apparently this has to be done *after* redefining term.native
local function restoreValue(tab, idx, name, hint)
local i, key, value = 1, debug.getupvalue(tab[idx], hint)
while key ~= name and key ~= nil do
key, value = debug.getupvalue(tab[idx], i)
i=i+1
end
tab[idx] = value or tab[idx]
end
restoreValue(_G, "loadstring", "nativeloadstring", 1)
restoreValue(_G, "load", "nativeload", 5)
if http then restoreValue(http, "request", "nativeHTTPRequest", 3) end
restoreValue(os, "shutdown", "nativeShutdown", 1)
restoreValue(os, "reboot", "nativeReboot", 1)
if turtle then
restoreValue(turtle, "equipLeft", "v", 1)
restoreValue(turtle, "equipRight", "v", 1)
end
do
local i, key, value = 1, debug.getupvalue(peripheral.isPresent, 2)
while key ~= "native" and key ~= nil do
key, value = debug.getupvalue(peripheral.isPresent, i)
i=i+1
end
_G.peripheral = value or peripheral
end
end
@@ -0,0 +1,272 @@
--:Minify:--
local apis = ({...})[1]
local BOOT_DRIVE_PATH = apis.BOOT_DRIVE_PATH
local fs = apis.fs
local native = apis.peripheral
local peripheral = {}
local sides = {"top", "bottom", "left", "right", "front", "back"}
function peripheral.getNames()
local results = {}
for n = 1, #sides do
local side = sides[n]
if native.isPresent(side) then
table.insert(results, side)
if native.hasType(side, "peripheral_hub") then
local remote = native.call(side, "getNamesRemote")
for _, name in ipairs(remote) do
table.insert(results, name)
end
end
end
end
return results
end
function peripheral.isPresent(name)
if native.isPresent(name) then
return true
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
return true
end
end
return false
end
function peripheral.getType(peripheral)
if type(peripheral) == "string" then
if native.isPresent(peripheral) then
return native.getType(peripheral)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then
return native.call(side, "getTypeRemote", peripheral)
end
end
return nil
else
local mt = getmetatable(peripheral)
if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then
error("bad argument #1 (table is not a peripheral)", 2)
end
return table.unpack(mt.types)
end
end
function peripheral.hasType(peripheral, peripheral_type)
if type(peripheral) == "string" then
if native.isPresent(peripheral) then
return native.hasType(peripheral, peripheral_type)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then
return native.call(side, "hasTypeRemote", peripheral, peripheral_type)
end
end
return nil
else
local mt = getmetatable(peripheral)
if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then
error("bad argument #1 (table is not a peripheral)", 2)
end
return mt.types[peripheral_type] ~= nil
end
end
function peripheral.getMethods(name)
if native.isPresent(name) then
return native.getMethods(name)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
return native.call(side, "getMethodsRemote", name)
end
end
return nil
end
function peripheral.getName(peripheral)
local mt = getmetatable(peripheral)
if not mt or mt.__name ~= "peripheral" or type(mt.name) ~= "string" then
error("bad argument #1 (table is not a peripheral)", 2)
end
return mt.name
end
function peripheral.call(name, method, ...)
if native.isPresent(name) then
return native.call(name, method, ...)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
return native.call(side, "callRemote", name, method, ...)
end
end
return nil
end
function peripheral.wrap(name)
local methods = peripheral.getMethods(name)
if not methods then
return nil
end
local types = { peripheral.getType(name) }
for i = 1, #types do types[types[i]] = true end
local result = setmetatable({}, {
__name = "peripheral",
name = name,
type = types[1],
types = types,
})
for _, method in ipairs(methods) do
result[method] = function(...)
return peripheral.call(name, method, ...)
end
end
return result
end
function peripheral.find(ty, filter)
local results = {}
for _, name in ipairs(peripheral.getNames()) do
if peripheral.hasType(name, ty) then
local wrapped = peripheral.wrap(name)
if filter == nil or filter(name, wrapped) then
table.insert(results, wrapped)
end
end
end
return table.unpack(results)
end
local disks = {}
local internal = {}
local function norm(path)
if not path or path == "" then return "/" end
return fs.combine("/", path)
end
local function createDisk(id, basePath, readonly, periph)
basePath = norm(basePath)
local disk = {address = id, isReadOnly = function() return readonly end}
function disk:spaceUsed()
return fs.getCapacity(basePath) - fs.getFreeSpace(basePath)
end
function disk:spaceTotal() return fs.getCapacity(basePath) end
function disk:list(path)
local p = fs.combine(basePath, path)
if not fs.exists(p) or not fs.isDir(p) then
return nil, "not directory"
end
return fs.list(p)
end
function disk:fileExists(path)
local p = fs.combine(basePath, path)
return fs.exists(p) and not fs.isDir(p)
end
function disk:directoryExists(path)
local p = fs.combine(basePath, path)
return fs.exists(p) and fs.isDir(p)
end
function disk:type(path)
local p = fs.combine(basePath, path)
if not fs.exists(p) then
return nil
elseif fs.isDir(p) then
return "directory"
else
return "file"
end
end
function disk:makeDirectory(path)
local p = fs.combine(basePath, path)
fs.makeDir(p)
return true
end
function disk:remove(path)
local p = fs.combine(basePath, path)
if fs.exists(p) then fs.delete(p) end
return true
end
function disk:setLabel(label) periph.setLabel(label) end
function disk:getLabel(label) return periph.getLabel() end
function disk:attributes(path)
local p = fs.combine(basePath, path)
return fs.attributes(p)
end
function disk:open(path, mode)
local p = fs.combine(basePath, path)
return fs.open(p, mode)
end
return disk
end
internal["$"] = createDisk("$", BOOT_DRIVE_PATH, false, {
setLabel = function(label)
local h = fs.open("/.label", "w")
h.write(label)
h.close()
end,
getLabel = function()
local h = fs.open("/.label", "r")
if not h then return "$" end
local label = h.readAll()
h.close()
return label
end
})
internal["rom"] = createDisk("rom", "/rom", true, {
setLabel = function(label)
error("Device is read-only")
end,
getLabel = function()
return "cctrom"
end
})
local function refresh()
disks={}
for _, disk in ipairs({peripheral.find("drive")}) do
if disk.isDiskPresent() then
disks[tostring(disk.getDiskID())]=createDisk("cctdisk"..tostring(disk.getDiskID()), disk.getMountPath(), false, fs)
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,6 @@
--:Minify:--
local kernel=...
if kernel.gfx then
end
@@ -47,7 +47,7 @@ local function write(text, term)
term.setCursorPos(x, y) term.setCursorPos(x, y)
end end
local function displaySuperBadError(err, noyield) local function displaySuperBadError(err)
lterm.setBackgroundColor(0x1) lterm.setBackgroundColor(0x1)
lterm.setTextColor(0x4) lterm.setTextColor(0x4)
lterm.clear() lterm.clear()
@@ -145,9 +145,9 @@ local ok, err = xpcall(function()
return content return content
end end
local Kernel = load(getFile(BOOT_DRIVE_PATH .. "/kernel.lua"),"@Kernel") local Kernel = load(getFile(BOOT_DRIVE_PATH .. "/boot/kernel.lua"),"@Kernel")
local initFs = load(getFile(BOOT_DRIVE_PATH .. "/cct/initdisks"),"@Init_disks")(apis) local initFs = load(getFile(BOOT_DRIVE_PATH .. "/boot/cct/initdisks"),"@Init_disks")(apis)
local fs = load(getFile(BOOT_DRIVE_PATH .. "/initfs"), "@InitFs")() local fs = load(getFile(BOOT_DRIVE_PATH .. "/boot/initfs"), "@InitFs")()
if not Kernel then displaySuperBadError("Could not load kernel.") end if not Kernel then displaySuperBadError("Could not load kernel.") end
if not initFs then displaySuperBadError("Could not load initdisks.") end if not initFs then displaySuperBadError("Could not load initdisks.") end
@@ -419,7 +419,6 @@ local ok, err = xpcall(function()
end end
local EFI = { local EFI = {
yield=function() end,
getEpochMs = function() return apis.os.epoch("utc") end, getEpochMs = function() return apis.os.epoch("utc") end,
getUptime = function() return apis.os.clock() * 1000 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, date = function() return apis.os.date("!%Y-%m-%dT%H:%M:%SZ", apis.os.epoch("utc") / 1000) end,
@@ -494,7 +493,7 @@ local ok, err = xpcall(function()
h.close() h.close()
end, end,
firmware=apis, firmware=apis,
status="running", reboot=false,
beep=function() end beep=function() end
} }
@@ -505,16 +504,17 @@ local ok, err = xpcall(function()
local kernelCoro = coroutine.create(function() local kernelCoro = coroutine.create(function()
--pf --pf
---@diagnostic disable-next-line: param-type-mismatch ---@diagnostic disable-next-line: param-type-mismatch-
local ok, err = xpcall(Kernel, debug.traceback, EFI) local ok, err = xpcall(Kernel, debug.traceback, EFI)
if not ok then if not ok and not EFI.reboot then displaySuperBadError(err) end
error(err) if err then
apis.os.reboot()
else else
apis.os.shutdown() apis.os.shutdown()
end end
end) end)
function EFI.resumeWithTimeout(co, timeout, ...) function coroutine.resumeWithTimeout(co, timeout, ...)
local startTime = EFI.getEpochMs() local startTime = EFI.getEpochMs()
debug.sethook(co, function() debug.sethook(co, function()
if EFI.getEpochMs() > startTime + timeout then if EFI.getEpochMs() > startTime + timeout then
@@ -536,7 +536,7 @@ local ok, err = xpcall(function()
--p --p
while true do while true do
local status, err = EFI.resumeWithTimeout(kernelCoro, 50) local status, err = coroutine.resumeWithTimeout(kernelCoro, 50)
apis.os.queueEvent("NoSleep") apis.os.queueEvent("NoSleep")
local exit = false local exit = false
while not exit do while not exit do
@@ -569,18 +569,14 @@ local ok, err = xpcall(function()
end end
end end
if status == "error" or coroutine.status(kernelCoro) == "dead" then if status == "error" or coroutine.status(kernelCoro) == "dead" then
if EFI.status=="reboot" then if EFI.reboot then
apis.os.reboot() apis.os.reboot()
elseif EFI.status=="shutdown" then
apis.os.shutdown()
end end
displaySuperBadError("Kernel error: " .. tostring(err)) displaySuperBadError("Kernel error: " .. tostring(err))
coroutine.yield("key") coroutine.yield("key")
elseif status == "success" then elseif status == "success" then
if EFI.status=="reboot" then if EFI.reboot then
apis.os.reboot() apis.os.reboot()
elseif EFI.status=="shutdown" then
apis.os.shutdown()
end end
displaySuperBadError("Kernel error: Attempted to yield main thread\n"..debug.traceback(kernelCoro, "Attempted to yield main thread")) displaySuperBadError("Kernel error: Attempted to yield main thread\n"..debug.traceback(kernelCoro, "Attempted to yield main thread"))
coroutine.yield("key") coroutine.yield("key")
@@ -58,11 +58,11 @@ function _G.term.native()
term.setCursorPos(1, 1) term.setCursorPos(1, 1)
term.setCursorBlink(true) term.setCursorBlink(true)
term.clear() 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 if file == nil then
term.setCursorBlink(false) term.setCursorBlink(false)
term.setTextColor(16384) 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.setCursorPos(1, 2)
term.write("Press any key to continue") term.write("Press any key to continue")
coroutine.yield("key") coroutine.yield("key")
@@ -73,7 +73,7 @@ function _G.term.native()
if fn == nil then if fn == nil then
term.setCursorBlink(false) term.setCursorBlink(false)
term.setTextColor(16384) 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.setCursorPos(1, 2)
term.write(err) term.write(err)
term.setCursorPos(1, 3) term.setCursorPos(1, 3)
@@ -163,7 +163,7 @@ local function createDisk(id, basePath, readonly, periph)
local disk = {address = id, isReadOnly = function() return readonly end} local disk = {address = id, isReadOnly = function() return readonly end}
function disk:spaceUsed() function disk:spaceUsed()
return (fs.getCapacity(basePath) or 0) - (fs.getFreeSpace(basePath) or 0) return fs.getCapacity(basePath) - fs.getFreeSpace(basePath)
end end
function disk:spaceTotal() return fs.getCapacity(basePath) end function disk:spaceTotal() return fs.getCapacity(basePath) end
@@ -250,21 +250,6 @@ internal["rom"] = createDisk("rom", "/rom", true, {
end 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() local function refresh()
disks={} disks={}
for _, disk in ipairs({peripheral.find("drive")}) do for _, disk in ipairs({peripheral.find("drive")}) do
@@ -1,12 +0,0 @@
--:Minify:--
local kernel=...
if kernel.arch~="cct" then
kernel.deny("cc-tweaked/01_periph.kmod")
kernel.deny("cc-tweaked/13_devraw.kmod")
kernel.deny("cc-tweaked/22_http.kmod")
kernel.deny("cc-tweaked/25_mouse.kmod")
kernel.deny("cc-tweaked/25_tty.kmod")
kernel.deny("cc-tweaked/30_daemon.kmod")
kernel.deny("cc-tweaked/46_scheduler.kmod")
kernel.deny("cc-tweaked/51_gpio.kmod")
end
@@ -1,25 +0,0 @@
--:Minify:--
local kernel=...
local fifo=kernel.newFifo()
kernel.devfs.data["input"]["mouse1"] = function(op, mode)
if op=="type" then
return "Mouse"
elseif op=="open" then
local h = {
read=function(amount)
local rv=""
for i=1, amount or 1 do
local event = {fifo.pop()}
if event[1] then
rv=rv..event[1]
end
end
---@diagnostic disable-next-line: cast-local-type
if rv=="" then rv=nil end
return rv
end
}
return h
end
end
kernel.cct.mouse={fifo=fifo}
@@ -1,8 +1,6 @@
--:Minify:-- --:Minify:--
local kernel = ... local kernel = ...
local peripheral=kernel.cct.peripheral local peripheral=kernel.cct.peripheral
kernel.cct.gfx={}
kernel.cct.term={}
local colors = { local colors = {
[0xFFFFFF]=0x0001, [0xFFFFFF]=0x0001,
@@ -157,7 +155,6 @@ local function serializeBool(bool)
end end
local function newtty(obj, id, ev) local function newtty(obj, id, ev)
kernel.cct.term[id]=obj
obj.setPaletteColor(0x1, 0xFFFFFF) -- #000000 obj.setPaletteColor(0x1, 0xFFFFFF) -- #000000
obj.setPaletteColor(0x2, 0xFF0000) -- #FFFFFF obj.setPaletteColor(0x2, 0xFF0000) -- #FFFFFF
obj.setPaletteColor(0x4, 0x00FF00) -- #FF0000 obj.setPaletteColor(0x4, 0x00FF00) -- #FF0000
@@ -179,18 +176,31 @@ local function newtty(obj, id, ev)
return "Terminal" return "Terminal"
elseif op=="open" then elseif op=="open" then
local h = { local h = {
read=function(amount)
local rv=""
for i=1, amount or 1 do
local event = {ev()}
if event[1] then
rv=rv..event[1]
end
end
if rv=="" then rv=nil end
return rv
end,
write=function(content) write=function(content)
write(content, obj) write(content, obj)
end, end,
size=function() size=function()
return obj.getSize() local s={obj.getSize()}
return table.concat(s,";")
end, end,
clear=function() clear=function()
obj.clear() obj.clear()
obj.setCursorPos(1,1) obj.setCursorPos(1,1)
end, end,
gpos=function() gpos=function()
return obj.getCursorPos() local s={obj.getCursorPos()}
return table.concat(s,";")
end, end,
spos=function(x,y) spos=function(x,y)
return obj.setCursorPos(x,y) return obj.setCursorPos(x,y)
@@ -213,16 +223,18 @@ local function newtty(obj, id, ev)
return false return false
end, end,
gplt=function() gplt=function()
return table.deepcopy(plt) return plt
end,
gfx=function(...)
if kernel.cct.gfx[id] then return kernel.cct.gfx[id] else return false end
end,
id=function()
return id
end end
} }
return h 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
end end
@@ -249,14 +261,23 @@ kernel.devfs.data["input"]["keyboard1"] = function(op, mode)
rv=rv..event[1] rv=rv..event[1]
end end
end end
---@diagnostic disable-next-line: cast-local-type
if rv=="" then rv=nil end if rv=="" then rv=nil end
return rv return rv
end, end,
write=function(content)
end,
gctrl=function() gctrl=function()
return serializeBool(kernel.cct.ctrl)..";"..serializeBool(kernel.cct.alt) return serializeBool(kernel.cct.ctrl)..";"..serializeBool(kernel.cct.alt)
end end
} }
return h 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
@@ -71,10 +71,8 @@ kernel.processes.cctdaemon = function()
elseif eventType == "mouse_scroll" then elseif eventType == "mouse_scroll" then
if event[2] == 1 then if event[2] == 1 then
kernel.cct.fifo.push("S") kernel.cct.fifo.push("S")
kernel.cct.mouse.fifo.push("S")
else else
kernel.cct.fifo.push("T") kernel.cct.fifo.push("T")
kernel.cct.mouse.fifo.push("T")
end end
elseif eventType == "http_success" then elseif eventType == "http_success" then
if kernel.cct.httpqueue[event[2]] then if kernel.cct.httpqueue[event[2]] then
@@ -87,16 +85,6 @@ kernel.processes.cctdaemon = function()
kernel.cct.httperror[event[2]]=event[3] kernel.cct.httperror[event[2]]=event[3]
kernel.cct.httpresponse[event[2]]=event[4] kernel.cct.httpresponse[event[2]]=event[4]
end end
elseif eventType == "mouse_click" then
--";X;Y;C"
-- 1 = left
-- 2 = right
-- 3 = middle
kernel.cct.mouse.fifo.push(";"..tostring(event[3])..";"..tostring(event[4])..";"..tostring(event[2]))
elseif eventType == "mouse_drag" then
kernel.cct.mouse.fifo.push(";"..tostring(event[3])..";"..tostring(event[4])..";"..tostring(event[2]))
elseif eventType == "mouse_up" then
kernel.cct.mouse.fifo.push(";"..tostring(event[3])..";"..tostring(event[4])..";"..tostring(event[2]))
else else
if kernel.cct.eventhooks[eventType] then if kernel.cct.eventhooks[eventType] then
local ok,err = xpcall(kernel.cct.eventhooks[eventType], debug.traceback, table.unpack(event)) local ok,err = xpcall(kernel.cct.eventhooks[eventType], debug.traceback, table.unpack(event))
@@ -1,161 +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 id,hook in ipairs(kernel.mainHooks) do
local ok,err = xpcall(hook, debug.traceback)
if not ok then
kernel.log("[MAIN HOOK ERR]: "..err, "ERROR", 0xFF0000)
kernel.mainHooks[id]=nil
end
end
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("[TASK 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
kernel.log("Exited main")
kernel.saveLog()
end
+1 -3
View File
@@ -1,3 +1 @@
Hyperion Hyperion
Astronand
Xtimhedae
+41 -122
View File
@@ -1,122 +1,41 @@
---@diagnostic disable-next-line: undefined-global local lua = {
local cp,c=component,computer;local b_addr=c.getBootAddress();local b_fs=cp.proxy(b_addr) coroutine = true,
local gpu=cp.list("gpu")() and cp.proxy(cp.list("gpu")()) debug = true,
local e_rom=cp.list("eeprom")() and cp.proxy(cp.list("eeprom")()) _HOST = true,
local screens={} _VERSION = true,
for addr in cp.list("screen") do assert = true,
if gpu then collectgarbage = true,
gpu.bind(addr) error = true,
local w,h=gpu.maxResolution() gcinfo = true,
gpu.setResolution(w,h) getfenv = true,
gpu.fill(1,1,w,h," ") getmetatable = true,
cp.proxy(addr).turnOn() ipairs = true,
screens[#screens+1] = {cx=1,cy=1,w=w,h=h,addr=addr} __inext = true,
end load = true,
end math = true,
local function scroll(scr) gpu.copy(1,2,scr.w,scr.h-1,0,-1);gpu.fill(1,scr.h,scr.w,1," ") end next = true,
local function write(t) pairs = true,
if not gpu then return end pcall = true,
for s=1, #screens do rawequal = true,
local scr=screens[s] rawget = true,
gpu.bind(scr.addr) rawlen = true,
for i=1,#t do rawset = true,
local char=t:sub(i,i) select = true,
if char=="\n" then scr.cx=1;scr.cy=scr.cy+1 setfenv = true,
elseif char=="\t" then scr.cx=scr.cx+(4-((scr.cx-1)%4)) setmetatable = true,
elseif char=="\b" then if scr.cx>1 then scr.cx=scr.cx-1;gpu.set(scr.cx,scr.cy," ") end string = true,
else gpu.set(scr.cx,scr.cy,char);scr.cx=scr.cx+1 end table = true,
if scr.cx>scr.w then scr.cx=1;scr.cy=scr.cy+1 end tonumber = true,
if scr.cy>scr.h then scroll(scr);scr.cy=scr.cy-1 end tostring = true,
end type = true,
end xpcall = true,
end _G=true
local function throw(err) }
if gpu then
gpu.setBackground(0x0000AA); local apis={}
gpu.setForeground(0xFFFFFF); for i,v in pairs(_G) do
for i=1, #screens do if not lua[i] or lua[i]==nil then
gpu.fill(1,1,screens[i].w,screens[i].h," "); apis[i]=v
screens[i].cx,screens[i].cy=1,1; _G[i]=nil
end end
write("CRITICAL KERNEL ERROR:\n"..tostring(err)) end
end
while true do c.pullSignal() 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
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))
end
end
end,debug.traceback)
if not ok then throw("Boot fault: "..err) end
+18 -68
View File
@@ -1,68 +1,18 @@
local init checkArg=nil
do local oldcomputer=computer
local component_invoke = component.invoke _G.computer=nil
local function boot_invoke(address, method, ...) local os=os
local result = table.pack(pcall(component_invoke, address, method, ...)) _G.os=nil
if not result[1] then
return nil, result[2] function component.wrap(address)
else local methods=oldcomponent.methods(address)
return table.unpack(result, 2, result.n) local object={}
end for _,method in ipairs(methods) do
end object[method]=function(_,...)
return oldcomponent.invoke(address,method,...)
-- backwards compatibility, may remove later end
local eeprom = component.list("eeprom")() end
computer.getBootAddress = function() return object
return boot_invoke(eeprom, "getData") end
end
computer.setBootAddress = function(address) local
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,142 +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
local ret={}
for i,v in ipairs(hw.list(path)) do
if v:sub(-1)=="/" then
ret[i]=v:sub(1,#v-1)
else ret[i]=v end
end
return ret
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,11 +0,0 @@
--:Minify:--
local kernel=...
if kernel.arch~="oc" then
kernel.deny("opencomputers/01_devices.kmod")
kernel.deny("opencomputers/13_devraw.kmod")
kernel.deny("opencomputers/22_http.kmod")
kernel.deny("opencomputers/25_tty.kmod")
kernel.deny("opencomputers/26_keyboards.kmod")
kernel.deny("opencomputers/30_daemon.kmod")
kernel.deny("opencomputers/36_scheduler.kmod")
end
@@ -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,180 +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,
gfx=function()
return false
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,147 +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
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
+1 -1
View File
@@ -1 +1 @@
firmware for Opencomputers mod firmware for Opencomputers
+1 -1
View File
@@ -1 +1 @@
1.0.0 0.1.0
@@ -1,593 +0,0 @@
--:Minify:--
local BOOT_DRIVE_PATH = ({...})[1] or "/$"
---@diagnostic disable-next-line: undefined-global
local lterm = term
local function write(text, term)
local x, y = term.getCursorPos()
local w, h = term.getSize()
for i = 1, #text do
local c = text:sub(i, i)
if c == "\n" then
y = y + 1
x = 1
elseif c == "\t" then
local tabSize = 4
local spaces = tabSize - ((x - 1) % tabSize)
term.write(string.rep(" ", spaces))
x = x + spaces
elseif c == "\b" then
if x > 1 then
x = x - 1
term.setCursorPos(x, y)
term.write(" ")
term.setCursorPos(x, y)
end
else
if x <= w and y <= h then
term.setCursorPos(x, y)
term.write(c)
x = x + 1
end
end
if x > w then
x = 1
y = y + 1
end
if y - 1 >= h then
term.scroll(1)
y = h
term.setCursorPos(x, y)
end
end
term.setCursorPos(x, y)
end
local function displaySuperBadError(err, noyield)
lterm.setBackgroundColor(0x1)
lterm.setTextColor(0x4)
lterm.clear()
lterm.setCursorPos(1, 1)
lterm.write("A critical error occurred while loading the system:")
lterm.setCursorPos(1, 3)
write(err, lterm)
coroutine.yield("key")
end
term.setCursorBlink(false)
local ok, err = xpcall(function()
--p
local apis = {BOOT_DRIVE_PATH = BOOT_DRIVE_PATH}
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
end
--p
local acekeys={
[apis.keys.enter]="\n",
[apis.keys.tab]="\t",
[apis.keys.backspace]="\b",
[apis.keys.up]="\17",
[apis.keys.down]="\18",
[apis.keys.left]="\19",
[apis.keys.right]="\20",
}
function sleep(time)
local stoptime = apis.os.clock() + (time)
while stoptime > apis.os.clock() do end
end
apis.term.setPaletteColor(0x1, 0xFFFFFF) -- #000000
apis.term.setPaletteColor(0x2, 0xFF0000) -- #FFFFFF
apis.term.setPaletteColor(0x4, 0x00FF00) -- #FF0000
apis.term.setPaletteColor(0x8, 0x0000FF) -- #00FF00
apis.term.setPaletteColor(0x10, 0x00FFFF) -- #0000FF
apis.term.setPaletteColor(0x20, 0xFF00FF) -- #00FFFF
apis.term.setPaletteColor(0x40, 0xFFFF00) -- #FF00FF
apis.term.setPaletteColor(0x80, 0xFF6D00) -- #FFFF00
apis.term.setPaletteColor(0x100, 0x6DFF55) -- #FF6D00
apis.term.setPaletteColor(0x200, 0x24FFFF) -- #6DFF55
apis.term.setPaletteColor(0x400, 0x924900) -- #24FFFF
apis.term.setPaletteColor(0x800, 0x6D6D55) -- #924900
apis.term.setPaletteColor(0x1000, 0xDBDBAA) -- #6D6D55
apis.term.setPaletteColor(0x2000, 0x6D00FF) -- #DBDBAA
apis.term.setPaletteColor(0x4000, 0xB6FF00) -- #6D00FF
apis.term.setPaletteColor(0x8000, 0x000000) -- #B6FF00
local function getFile(path)
local file = apis.fs.open(path, "r")
if not file then
displaySuperBadError("Could not open file: " .. path)
end
local content = file.readAll()
file.close()
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")()
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
if not apis.fs.exists("/nvram.dat") then
local file = apis.fs.open("/nvram.dat", "w")
file.write("Hello, World!")
file.close()
end
local eeprom
if apis.fs.exists("/startup.lua") then
eeprom="/startup.lua"
elseif apis.fs.exists("/eeprom") then
eeprom="/eeprom"
end
local eventQueue = {}
local function queueEvent(event, ...)
table.insert(eventQueue, {event, ...})
end
local colors = {
[0xFFFFFF]=0x0001,
[0xFF0000]=0x0002,
[0x00FF00]=0x0004,
[0x0000FF]=0x0008,
[0x00FFFF]=0x0010,
[0xFF00FF]=0x0020,
[0xFFFF00]=0x0040,
[0xFF6D00]=0x0080,
[0x6DFF55]=0x0100,
[0x24FFFF]=0x0200,
[0x924900]=0x0400,
[0x6D6D55]=0x0800,
[0xDBDBAA]=0x1000,
[0x6D00FF]=0x2000,
[0xB6FF00]=0x4000,
[0x000000]=0x8000
}
local fg,bg=0x6D6D55,0x000000
local l1f,l1d,l2,ops={},{},{},0
local function findClosest(tbl, target)
local closest = nil
local smallestDiff = math.huge
for k, _ in pairs(tbl) do
if k==target then return k end
local diff = math.abs(k - target)
if diff < smallestDiff then
smallestDiff = diff
closest = k
end
end
return closest
end
local function aprox(c24)
ops = ops + 1
if ops % 1024 == 0 then
l1d = {}
l1f = {}
end
if ops % 8192 == 0 then
l2 = {}
end
if l2[c24] ~= nil then
return l2[c24]
end
if l1d[c24] ~= nil then
l1f[c24] = l1f[c24] + 1
if l1f[c24] >= 16 then
l2[c24] = l1d[c24]
l1d[c24] = nil
l1f[c24] = nil
return l2[c24]
end
return l1d[c24]
end
local closestKey = findClosest(colors, c24)
if not closestKey then return nil end
local value = colors[closestKey]
l1d[c24] = value
l1f[c24] = 1
return value
end
--p
local p={}
local native = apis.peripheral
local sides = {"top", "bottom", "left", "right", "front", "back"}
function p.getNames()
local results = {}
for n = 1, #sides do
local side = sides[n]
if native.isPresent(side) then
table.insert(results, side)
if native.hasType(side, "peripheral_hub") then
local remote = native.call(side, "getNamesRemote")
for _, name in ipairs(remote) do
table.insert(results, name)
end
end
end
end
return results
end
function p.isPresent(name)
if native.isPresent(name) then
return true
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
return true
end
end
return false
end
function p.getType(peripheral)
if type(peripheral) == "string" then
if native.isPresent(peripheral) then
return native.getType(peripheral)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then
return native.call(side, "getTypeRemote", peripheral)
end
end
return nil
else
local mt = getmetatable(peripheral)
if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then
error("bad argument #1 (table is not a peripheral)", 2)
end
return table.unpack(mt.types)
end
end
function p.hasType(peripheral, peripheral_type)
if type(peripheral) == "string" then
if native.isPresent(peripheral) then
return native.hasType(peripheral, peripheral_type)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then
return native.call(side, "hasTypeRemote", peripheral, peripheral_type)
end
end
return nil
else
local mt = getmetatable(peripheral)
if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then
error("bad argument #1 (table is not a peripheral)", 2)
end
return mt.types[peripheral_type] ~= nil
end
end
function p.getMethods(name)
if native.isPresent(name) then
return native.getMethods(name)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
return native.call(side, "getMethodsRemote", name)
end
end
return nil
end
function p.getName(peripheral)
local mt = getmetatable(peripheral)
if not mt or mt.__name ~= "peripheral" or type(mt.name) ~= "string" then
error("bad argument #1 (table is not a peripheral)", 2)
end
return mt.name
end
function p.call(name, method, ...)
if native.isPresent(name) then
return native.call(name, method, ...)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
return native.call(side, "callRemote", name, method, ...)
end
end
return nil
end
function p.wrap(name)
local methods = p.getMethods(name)
if not methods then
return nil
end
local types = { p.getType(name) }
for i = 1, #types do types[types[i]] = true end
local result = setmetatable({}, {
__name = "peripheral",
name = name,
type = types[1],
types = types,
})
for _, method in ipairs(methods) do
result[method] = function(...)
return p.call(name, method, ...)
end
end
return result
end
function p.find(ty, filter)
local results = {}
for _, name in ipairs(p.getNames()) do
if p.hasType(name, ty) then
local wrapped = p.wrap(name)
if filter == nil or filter(name, wrapped) then
table.insert(results, wrapped)
end
end
end
return table.unpack(results)
end
--p
local allscreens = {p.find("monitor")}
for i=1, #allscreens do
allscreens[i].setTextScale(.5)
allscreens[i].clear()
allscreens[i].setCursorPos(1,1)
end
allscreens[#allscreens+1] = apis.term
local callAsyncQueue = {}
local callAsyncReturn = {}
apis.callAsyncReturn = callAsyncReturn
local callidx=0
function apis.callAsync(func, ...)
callidx=callidx+1
callAsyncQueue[#callAsyncQueue+1] = {callidx, func, ...}
return callidx
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,
getMachineEvent = function()
if #eventQueue > 0 then
return table.unpack(table.remove(eventQueue, 1))
else
return nil
end
end,
getEEPROM = function() return getFile(eeprom) end,
setEEPROM = function(_, text)
local h = apis.fs.open(eeprom, "w")
h.write(text)
h.close()
end,
initfs=fs,
disks=initFs,
screenCtl={
print = function(_, text)
for i=1, #allscreens do
write(text.."\n", allscreens[i])
end
end,
printInline = function(_, text)
for i=1, #allscreens do
write(text, allscreens[i])
end
end,
clear = function()
for i=1, #allscreens do
allscreens[i].clear()
allscreens[i].setCursorPos(1, 1)
end
end,
resetCursor = function()
for i=1, #allscreens do
allscreens[i].setCursorPos(1, 1)
end
end,
setBackgroundColor = function(_, color)
bg=color
for i=1, #allscreens do
allscreens[i].setBackgroundColor(aprox(color))
end
end,
setTextColor = function(_, color)
fg=color
for i=1, #allscreens do
allscreens[i].setTextColor(aprox(color))
end
end,
getBackgroundColor = function()
return bg
end,
getTextColor = function()
return fg
end,
enable=function()
for i=1, #allscreens do
allscreens[i].clear()
allscreens[i].setCursorPos(1, 1)
end
end,
disable=function() end
},
architecture="cct",
getNvram = function() return getFile("/nvram.dat") end,
setNvram = function(_, text)
local h = apis.fs.open("/nvram.dat", "w")
h.write(text)
h.close()
end,
firmware=apis,
status="running",
beep=function() end
}
apis.term.setBackgroundColor(0x8000)
apis.term.setTextColor(0x1000)
apis.term.clear()
apis.term.setCursorPos(1, 1)
local kernelCoro = coroutine.create(function()
--pf
---@diagnostic disable-next-line: param-type-mismatch
local ok, err = xpcall(Kernel, debug.traceback, EFI)
if not ok then
error(err)
else
apis.os.shutdown()
end
end)
function EFI.resumeWithTimeout(co, timeout, ...)
local startTime = EFI.getEpochMs()
debug.sethook(co, function()
if EFI.getEpochMs() > 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
EFI.screenCtl:print("Loaded in " .. tostring(apis.os.clock()) .. " seconds.\n")
--p
while true do
local status, err = EFI.resumeWithTimeout(kernelCoro, 50)
apis.os.queueEvent("NoSleep")
local exit = false
while not exit do
local event = {coroutine.yield()}
if event[1] == "key" then
queueEvent(table.unpack(event))
queueEvent("keyPressed", 1, event[2])
if acekeys[event[2]] then
queueEvent("keyTyped", 1, acekeys[event[2]])
end
elseif event[1] == "char" then
queueEvent(table.unpack(event))
queueEvent("keyTyped", 1, event[2])
elseif event[1] == "key_up" then
queueEvent(table.unpack(event))
queueEvent("keyReleased", 1, event[2])
elseif event[1] == "NoSleep" then
exit = true
else
queueEvent(table.unpack(event))
end
end
while #callAsyncQueue>0 do
local bundle = table.remove(callAsyncQueue, 1)
local ret = {xpcall(bundle[2], debug.traceback, table.unpack(bundle, 3))}
if not ret[1] then
callAsyncReturn[bundle[1]]={false, ret[2]}
else
callAsyncReturn[bundle[1]]={true, table.unpack(ret,2)}
end
end
if status == "error" or coroutine.status(kernelCoro) == "dead" then
if EFI.status=="reboot" then
apis.os.reboot()
elseif EFI.status=="shutdown" then
apis.os.shutdown()
end
displaySuperBadError("Kernel error: " .. tostring(err))
coroutine.yield("key")
elseif status == "success" then
if EFI.status=="reboot" then
apis.os.reboot()
elseif EFI.status=="shutdown" then
apis.os.shutdown()
end
displaySuperBadError("Kernel error: Attempted to yield main thread\n"..debug.traceback(kernelCoro, "Attempted to yield main thread"))
coroutine.yield("key")
end
initFs:refresh()
end
end, debug.traceback)
if not ok then displaySuperBadError("Fatal error during boot: " .. err) end
while true do coroutine.yield("key") end
@@ -1 +0,0 @@
print("Hyperion OS PUC bootloader")
+4 -4
View File
@@ -1,4 +1,4 @@
U $;/boot/ U $;/
V devfs0000;/dev/ U devfs0000;/dev/
V tmpfs0000;/tmp/ U tmpfs0000;/tmp/
V procfs0000;/proc/ U procfs0000;/proc/
+1 -1
View File
@@ -77,7 +77,7 @@ end
function fs.load(path) return load(fs.readAllText(path), path) end function fs.load(path) return load(fs.readAllText(path), path) end
function fs.mount(disk, mountPoint) function fs.mount(disk, mountPoint)
if not disks[disk] then error("NODISK : "..disk) end if not disks[disk] then return end
mounts[mountPoint] = disk mounts[mountPoint] = disk
end end
+6 -69
View File
@@ -68,13 +68,12 @@ function kernel.PANIC(msg)
kernel.exitMain = true kernel.exitMain = true
end end
while true do while true do
EFI:yield()
local event={EFI:getMachineEvent()} local event={EFI:getMachineEvent()}
if event[1]=="keyPressed" then if event[1]=="keyPressed" then
break break
end end
end end
EFI.status="reboot" EFI.reboot=true
error("KERNEL PANIC") error("KERNEL PANIC")
end end
kernel.panic=kernel.PANIC kernel.panic=kernel.PANIC
@@ -99,7 +98,7 @@ kernel.disks={}
for _,v in disks.list() do for _,v in disks.list() do
kernel.disks[v.address] = v kernel.disks[v.address] = v
end end
ifs.mount("$", "/boot/") ifs.mount("$", "/")
local fstab=ifs.readAllText("/boot/fstab") local fstab=ifs.readAllText("/boot/fstab")
local split = function(str, delim, maxResultCountOrNil) local split = function(str, delim, maxResultCountOrNil)
@@ -139,10 +138,8 @@ end
kernel.config = config kernel.config = config
local skip=false local skip=false
local mounted={}
local root=false
for i,v in ipairs(split(fstab,"\n")) do 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="" local id=""
for i=3,#v do for i=3,#v do
if v:sub(i,i)==";" then if v:sub(i,i)==";" then
@@ -152,42 +149,12 @@ for i,v in ipairs(split(fstab,"\n")) do
end end
if not skip then if not skip then
local path=v:sub(#id+4) local path=v:sub(#id+4)
if path=="/" then root=true end
mounted[id]=true
ifs.mount(id,path) ifs.mount(id,path)
else else
skip=false skip=false
end end
end 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
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") kernel.log("Disks initialized")
function kernel.saveLog() function kernel.saveLog()
@@ -354,26 +321,6 @@ kernel.processes={}
kernel.fstab=fstab kernel.fstab=fstab
kernel.denied={} kernel.denied={}
kernel.loadingModule="kernel" kernel.loadingModule="kernel"
kernel.perTaskHooks={}
kernel.mainHooks={}
kernel.runhooks={}
-- args {taskobj, pid}
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 = { kernel.kernelTask = {
name="kernel", name="kernel",
@@ -459,7 +406,6 @@ kernel.syscalls["saveLog"]=function()
end end
end end
ifs.writeAllText("/boot/fstab", fstab)
kernel.saveLog() kernel.saveLog()
kernel.log("Running modules") kernel.log("Running modules")
for _,p in ipairs(modules) do for _,p in ipairs(modules) do
@@ -471,7 +417,7 @@ for _,p in ipairs(modules) do
if not code then if not code then
kernel.panic("Failed to read module "..v) kernel.panic("Failed to read module "..v)
end end
local func,err=load(code,"@"..v,"t",_G) local func,err=load(code,"@"..v)
if not func then kernel.panic("ModuLoadErr: "..tostring(err)) end if not func then kernel.panic("ModuLoadErr: "..tostring(err)) end
local status, err = xpcall(func,debug.traceback, kernel) local status, err = xpcall(func,debug.traceback, kernel)
if not status then kernel.panic("ModuRunErr: "..tostring(err)) end if not status then kernel.panic("ModuRunErr: "..tostring(err)) end
@@ -483,17 +429,11 @@ for _,p in ipairs(modules) do
end end
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.log("Kernel initialized successfully.")
kernel.saveLog() kernel.saveLog()
kernel.status="running" kernel.status="running"
kernel.loadingModule=nil kernel.loadingModule=nil
screen:disable() screen:disable()
if not kernel.main then kernel.panic("No scheduler implemented from firmware") end
local ok,err = xpcall(kernel.main, debug.traceback) local ok,err = xpcall(kernel.main, debug.traceback)
if not ok then if not ok then
kernel.panic(err) kernel.panic(err)
@@ -502,13 +442,10 @@ if kernel.status=="panic" then
kernel.panic(kernel.reason) kernel.panic(kernel.reason)
end end
if kernel.status=="reboot" then if kernel.status=="reboot" then
EFI.status="reboot" EFI.reboot=true
return true return true
elseif kernel.status=="halt" then elseif kernel.status=="halt" then
kernel.log("System halted.") kernel.log("System halted.")
kernel.saveLog() kernel.saveLog()
while true do EFI:yield() end while true do end
else
EFI.status="shutdown"
return true
end end
+1
View File
@@ -0,0 +1 @@
0:0:root:/root:/bin/hysh
@@ -2,16 +2,6 @@
--- @diagnostic disable: duplicate-set-field --- @diagnostic disable: duplicate-set-field
local kernel = ... local kernel = ...
kernel.allowGlobalOverwrites = true kernel.allowGlobalOverwrites = true
local oldtype = type
local oldgetmetatable = getmetatable
function math.round(x)
if x>=0 then
return math.floor(x+0.5)
else
return math.ceil(x-0.5)
end
end
function string.hasSuffix(str, suffix) function string.hasSuffix(str, suffix)
return string.sub(str, #suffix + 1) == suffix return string.sub(str, #suffix + 1) == suffix
@@ -80,10 +70,6 @@ function table.hasVal(tabl, query)
return false return false
end end
function table.readOnly(tabl, typ)
return setmetatable({},{__index=tabl,__newindex=function()error("Table is read-only")end,__usermeta=false,__type=typ})
end
local function serialize(tbl, seen) local function serialize(tbl, seen)
seen = seen or {} seen = seen or {}
@@ -114,8 +100,6 @@ local function serialize(tbl, seen)
output = output .. "\"" .. tostring(v) .. "\"" output = output .. "\"" .. tostring(v) .. "\""
elseif type(v) == "thread" then elseif type(v) == "thread" then
output = output .. "\"" .. tostring(v) .. "\"" output = output .. "\"" .. tostring(v) .. "\""
elseif oldgetmetatable(v) and oldgetmetatable(v).__tostring then
output = output .. tostring(v)
else else
error("serialization of type \"" .. type(v) .. "\" is not supported") error("serialization of type \"" .. type(v) .. "\" is not supported")
end end
@@ -127,6 +111,8 @@ local function serialize(tbl, seen)
return output return output
end end
local oldtype = type
local oldgetmetatable = getmetatable
function type(object, trueType) function type(object, trueType)
if trueType then return oldtype(object) end if trueType then return oldtype(object) end
if oldtype(object) ~= "table" then if oldtype(object) ~= "table" then
@@ -145,7 +131,7 @@ end
function getmetatable(object) function getmetatable(object)
if oldtype(object) ~= "table" then return end if oldtype(object) ~= "table" then return end
if oldtype(oldgetmetatable(object)) == "table" then if oldtype(oldgetmetatable(object)) == "table" then
if oldgetmetatable(object).__usermeta then if oldgetmetatable(object).__isuserdata then
if oldtype(oldgetmetatable(object).__usermeta) == "function" then if oldtype(oldgetmetatable(object).__usermeta) == "function" then
return oldgetmetatable(object).__usermeta() return oldgetmetatable(object).__usermeta()
else else
@@ -265,6 +251,8 @@ local function makeSyscallProxy()
local backing = {} local backing = {}
return setmetatable(backing, { return setmetatable(backing, {
__index = function(self, name) __index = function(self, name)
local raw = rawget(self, name)
if raw ~= nil then return raw end
return function(...) return function(...)
local res = table.pack(coroutine.yield("syscall", name, ...)) local res = table.pack(coroutine.yield("syscall", name, ...))
if res[1] then if res[1] then
@@ -275,7 +263,7 @@ local function makeSyscallProxy()
end end
end, end,
__newindex = function(self, k, v) __newindex = function(self, k, v)
error("Table is read-only") rawset(self, k, v)
end, end,
__metatable=false __metatable=false
}) })
@@ -283,5 +271,6 @@ end
syscall = makeSyscallProxy() syscall = makeSyscallProxy()
table.serialize = serialize _makeSyscallProxy = makeSyscallProxy
table.serialize = serialize
@@ -2,7 +2,7 @@
local kernel = ... local kernel = ...
local vfs = {} local vfs = {}
kernel.vfs = vfs kernel.vfs = vfs
vfs.mounts = {} vfs.mounts = {["$"] = "/"}
vfs.disks = kernel.disks vfs.disks = kernel.disks
-- Metafile format (version 2) -- Metafile format (version 2)
@@ -299,7 +299,6 @@ local function namei(path, noFollow, symDepth)
if not target or target == "" then if not target or target == "" then
error("ENOENT: empty symlink target") error("ENOENT: empty symlink target")
end end
if kernel.config.logSymlinkTraverse then kernel.log(curPath .. " > " .. target) end
local symIsAbs, symTokens = tokenizePath(target) local symIsAbs, symTokens = tokenizePath(target)
@@ -557,19 +556,17 @@ function vfs.newfd(fdobj)
return fd return fd
end end
function vfs.mount(target, diskOrId, bind, floating) function vfs.mount(target, diskOrId, bind)
if not floating and target ~= "/" then local _euid = (kernel.currentTask and (kernel.currentTask.euid or kernel.currentTask.uid)) or kernel.uid
local _euid = (kernel.currentTask and (kernel.currentTask.euid or kernel.currentTask.uid)) or kernel.uid if _euid ~= 0 then error("EPERM") end
if _euid ~= 0 then error("EPERM") end if not target then error("EINVAL") end
if not target then error("EINVAL") end target = normalizeMountPoint(target)
target = normalizeMountPoint(target) local drive, path = resolvePath(target)
local drive, path = resolvePath(target) if not drive:directoryExists(path) then
if not drive:directoryExists(path) then drive:makeDirectory(path)
drive:makeDirectory(path) end
end if drive:type(path) ~= "directory" then
if drive:type(path) ~= "directory" then error("EINVAL")
error("EINVAL")
end
end end
local disk, id local disk, id
-- bind mount -- bind mount
@@ -694,7 +691,7 @@ function vfs.open(path, mode)
if disk:type(diskPath) ~= "directory" then if disk:type(diskPath) ~= "directory" then
handle = disk:open(diskPath, mode) handle = disk:open(diskPath, mode)
if type(handle, true) ~= "table" then if type(handle, true) ~= "table" then
error("ENFILE".." KERR="..type(handle,true)) error("ENFILE")
end end
end end
@@ -1069,9 +1066,8 @@ function vfs.chown(path, uid, gid)
if kernel.unixSockets[namei(path)] then error("EINVAL") end if kernel.unixSockets[namei(path)] then error("EINVAL") end
local disk = resolveMount(path) local disk = resolveMount(path)
if disk:isReadOnly() then error("ERDONLY") end 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
local euid = (kernel.currentTask and (kernel.currentTask.euid or kernel.currentTask.uid)) or kernel.uid if _euid ~= 0 then error("EPERM") end
if euid ~= 0 and euid ~= meta.owner then error("EPERM") end
updateMeta(path, function(e) e.owner = uid; e.group = gid end) updateMeta(path, function(e) e.owner = uid; e.group = gid end)
end end
@@ -1159,27 +1155,7 @@ function vfs.devlst(fd)
return table.keys(kernel.currentTask.fd[fd].handle) return table.keys(kernel.currentTask.fd[fd].handle)
end end
function vfs.getOpenFds()
local out={}
for i,v in ipairs(kernel.currentTask.fd) do
out[i]=v.path
end
return out
end
function vfs.fsinfo()
local out={mounts={},disks={}}
for i,v in pairs(vfs.mounts) do
out.mounts[i]=v
end
for i,v in pairs(vfs.disks) do
out.disks[i]={size=vfs.disks[i].spaceTotal(),used=vfs.disks[i].spaceUsed(),label=vfs.disks[i].getLabel(),readOnly=vfs.disks[i].isReadOnly(),isVirt=vfs.disks[i].isvirt,address=vfs.disks[i].addressz}
end
return out
end
vfs.resolveMount = resolveMount vfs.resolveMount = resolveMount
vfs.updateMeta = updateMeta
local sys = kernel.syscalls local sys = kernel.syscalls
sys["open"] = vfs.open sys["open"] = vfs.open
@@ -1219,7 +1195,5 @@ sys["fget_suid"] = function(fd)
local fobj = kernel.currentTask and kernel.currentTask.fd[fd] local fobj = kernel.currentTask and kernel.currentTask.fd[fd]
return fobj and fobj.suid_owner or nil return fobj and fobj.suid_owner or nil
end end
sys["getOpenFds"]= vfs.getOpenFds
sys["fsinfo"] = vfs.fsinfo
kernel.log("VFS module loaded") kernel.log("VFS module loaded")
@@ -7,12 +7,8 @@ kernel.searchpaths = {
} }
kernel.reqcache = cache kernel.reqcache = cache
local function wrap(lib)
return setmetatable({},{__index=lib,__newindex=function()error("Table is read-only")end,__usermeta=false,__call=function(s,...) return lib.new(...) end})
end
local function require(module, ...) local function require(module, ...)
if cache[module] then return wrap(cache[module].ret) end if cache[module] then return cache[module].ret end
local args = {...} local args = {...}
for _, path in ipairs(kernel.searchpaths) do for _, path in ipairs(kernel.searchpaths) do
local filepath = path:gsub("?", module) local filepath = path:gsub("?", module)
@@ -40,8 +36,8 @@ local function require(module, ...)
if not ok then if not ok then
error("Error running module "..module..": "..tostring(ret)) error("Error running module "..module..": "..tostring(ret))
end end
cache[module] = {ret = ret} cache[module] = {ret = ret, expires = kernel.EFI:getEpochMs() + 120000}
return wrap(ret) return ret
end end
coroutine.yield() coroutine.yield()
end end
@@ -103,7 +103,7 @@ local function newtaskproxy(task)
children[tostring(v.pid)]="/proc/"..tostring(v.pid) children[tostring(v.pid)]="/proc/"..tostring(v.pid)
end end
return { return {
[".meta"]=strFile(buildMeta({cwd=task.cwd,parent="/proc/"..tostring(task.parent.pid),root=task.root or "/"})), [".meta"]=strFile(buildMeta({cwd=task.cwd,parent="/proc/"..tostring(task.parent.pid)})),
uid=strFile(task.uid), uid=strFile(task.uid),
comm=strFile(task.name), comm=strFile(task.name),
fd={ fd={
@@ -115,9 +115,7 @@ local function newtaskproxy(task)
children={ children={
[".meta"]=strFile(buildMeta(children)) [".meta"]=strFile(buildMeta(children))
}, },
pid=strFile(task.pid), pid=strFile(task.pid)
ivs=strFile(task.ivs),
vs=strFile(task.vs)
} }
end end
@@ -1,3 +0,0 @@
--:Minify:--
local kernel = ...
@@ -1,82 +0,0 @@
--:Minify:--
local kernel = ...
local proxy = {}
local data = {}
proxy.address = "devfs0000"
proxy.isvirt = true
proxy.isReadOnly = function() return false end
proxy.spaceUsed = function() return 0 end
proxy.spaceTotal = function() return 0 end
proxy.makeDirectory = function() error("EACCES") end
proxy.remove = function() error("EACCES") end
proxy.setLabel = function() error("EACCES") end
proxy.getLabel = function() return "devfs" end
proxy.attributes = function(path) return {
size = 0,
modified = 0,
created = 0
} end
function proxy:open(path, mode)
local steps = kernel.vfs.splitPath(path)
local step = data
for i=1, #steps-1 do
local dat = step[steps[i]]
if type(dat) ~= "table" then error("ENFILE") end
step=dat
end
if type(step[steps[#steps]]) == "function" then
return step[steps[#steps]]("open", mode)
end
error("ENFILE")
end
function proxy:type(path, mode)
local steps = kernel.vfs.splitPath(path)
local step = data
if #steps == 0 then
return "directory"
end
for i=1, #steps-1 do
local dat = step[steps[i]]
if type(dat) ~= "table" then error("ENFILE") end
step=dat
end
if type(step[steps[#steps]]) == "function" then
return step[steps[#steps]]("type", mode)
end
if type(step[steps[#steps]]) == "table" then
return "directory"
end
error("ENOENT")
end
function proxy:list(path)
local steps = kernel.vfs.splitPath(path)
local step = data
if #steps == 0 then
return table.keys(data)
end
for i=1, #steps-1 do
local dat = step[steps[i]]
if type(dat) ~= "table" then error("ENOENT") end
step=dat
end
if type(step[steps[#steps]]) == "table" then
return table.keys(step[steps[#steps]])
end
error("ENOENT")
end
function proxy:fileExists(path)
local ok = pcall(function()
return self:type(path)
end)
return ok
end
kernel.sysfs={}
kernel.sysfs.proxy=proxy
kernel.disks["sysfs0000"]=proxy
@@ -1,6 +1,8 @@
--:Minify:-- --:Minify:--
local kernel = ... local kernel = ...
kernel.vfs.remove("/tmp")
kernel.vfs.mkdir("/tmp")
if not kernel.config.tmpToDisk then if not kernel.config.tmpToDisk then
local proxy = {} local proxy = {}
local data = {} local data = {}
@@ -136,8 +138,4 @@ if not kernel.config.tmpToDisk then
else else
kernel.log("tmpToDisk enabled, skipping tmpfs module") kernel.log("tmpToDisk enabled, skipping tmpfs module")
kernel.log("tmpfs0000 will passthrough to /tmp on the disk") kernel.log("tmpfs0000 will passthrough to /tmp on the disk")
kernel.runWhenLoaded(function()
kernel.vfs.remove("/tmp")
kernel.vfs.mkdir("/tmp")
end)
end end
@@ -11,7 +11,7 @@ end
for _, line in ipairs(string.split(kernel.fstab, "\n")) do for _, line in ipairs(string.split(kernel.fstab, "\n")) do
line = trim(line) 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 local semicolon_pos
for i = 3, #line do for i = 3, #line do
if line:sub(i,i) == ";" then 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 id = line:sub(3, semicolon_pos - 1)
local path = trim(line:sub(semicolon_pos + 1)) local path = trim(line:sub(semicolon_pos + 1))
kernel.log("Mounting '"..id.."' to '"..path.."'") 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) kernel.log("Mounted "..id.." to "..path)
end end
end end
@@ -32,31 +32,6 @@ function signal.sigignore()
task.sigd=nil task.sigd=nil
end 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))
kernel.EFI:yield()
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 local s=kernel.syscalls
s["sigsend"] = signal.sigsend s["sigsend"] = signal.sigsend
s["sigcatch"] = signal.sigcatch s["sigcatch"] = signal.sigcatch
@@ -2,5 +2,3 @@
local kernel=... local kernel=...
kernel.unixSockets={} kernel.unixSockets={}
local socket=kernel.socket local socket=kernel.socket
--socket.registerProtocal()
@@ -58,12 +58,10 @@ kernel._U.load = function(a,b,c,d) return origLoad(a,b,c,d or kernel._U) end
function kernel.freshUserEnv() function kernel.freshUserEnv()
local locals = {} local locals = {}
locals.syscall = _makeSyscallProxy()
local env = setmetatable(locals, { local env = setmetatable(locals, {
__index = kernel._U, __index = kernel._U,
__pairs = function(self)
return pairs(kernel._U)
end,
__newindex = function(_, k, v) rawset(locals, k, v) end, __newindex = function(_, k, v) rawset(locals, k, v) end,
__metatable=false __metatable=false
}) })
@@ -33,7 +33,7 @@ local function createVt(id, width, height)
end end
end end
function vt.obj.write(content) function vt.obj:write(content)
local x, y = vt.cursorX, vt.cursorY local x, y = vt.cursorX, vt.cursorY
if x>vt.width then return end if x>vt.width then return end
if y>vt.height then return end if y>vt.height then return end
@@ -79,36 +79,36 @@ local function createVt(id, width, height)
vt.cursorX, vt.cursorY = x, y vt.cursorX, vt.cursorY = x, y
end end
function vt.obj.spos(x, y) function vt.obj:spos(x, y)
vt.cursorX = tonumber(x) vt.cursorX = tonumber(x)
vt.cursorY = tonumber(y) vt.cursorY = tonumber(y)
end end
function vt.obj.gpos() function vt.obj:gpos()
return vt.cursorX, vt.cursorY return tostring(vt.cursorX)..";"..tostring(vt.cursorY)
end end
function vt.obj.sfgc(color) function vt.obj:sfgc(color)
vt.fgColor = tonumber(color) vt.fgColor = tonumber(color)
end end
function vt.obj.sbgc(color) function vt.obj:sbgc(color)
vt.bgColor = tonumber(color) vt.bgColor = tonumber(color)
end end
function vt.obj.gfgc() function vt.obj:gfgc()
return vt.fgColor return vt.fgColor
end end
function vt.obj.gbgc() function vt.obj:gbgc()
return vt.bgColor return vt.bgColor
end end
function vt.obj.gplt() function vt.obj:gplt()
return 24 return 24
end end
function vt.obj.clear() function vt.obj:clear()
for y = 1, vt.height do for y = 1, vt.height do
for x = 1, vt.width do for x = 1, vt.width do
vt.buffer[y][x] = {char = " ", fgColor = vt.fgColor, bgColor = vt.bgColor} vt.buffer[y][x] = {char = " ", fgColor = vt.fgColor, bgColor = vt.bgColor}
@@ -117,12 +117,12 @@ local function createVt(id, width, height)
vt.cursorX, vt.cursorY = 1, 1 vt.cursorX, vt.cursorY = 1, 1
end end
function vt.obj.isvirt() function vt.obj:isvirt()
return true return true
end end
function vt.obj.gfx() function vt.obj:gctrl()
return serializeBool(vt.ctrl)..";"..serializeBool(vt.alt)
end end
return vt return vt
@@ -155,21 +155,7 @@ end
local function hashPassword(password, salt) local function hashPassword(password, salt)
local key = (pepper .. salt) local key = (pepper .. salt)
return blake2s(password..salt, key) return blake2s(password, 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)
end end
local passwdFile = getFile("/etc/passwd") local passwdFile = getFile("/etc/passwd")
@@ -5,6 +5,7 @@ local sys = {}
local nextpid = 2 local nextpid = 2
kernel.exitMain = false kernel.exitMain = false
local resumeWithTimeout = coroutine.resumeWithTimeout
local function bit_is_set(num, bit) local function bit_is_set(num, bit)
return math.floor(num / (2 ^ bit)) % 2 == 1 return math.floor(num / (2 ^ bit)) % 2 == 1
@@ -30,18 +31,10 @@ local function loadExecutable(path)
return func, euid, suid_set return func, euid, suid_set
end 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 local id = nextpid
nextpid = nextpid + 1 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)] = { tasks[tostring(id)] = {
coro = coroutine.create(function() coro = coroutine.create(function()
local ok, err = xpcall(func, debug.traceback, table.unpack(args or {})) 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, euid = eff_uid,
gid = (kernel.currentTask and kernel.currentTask.gid) or 0, gid = (kernel.currentTask and kernel.currentTask.gid) or 0,
groups = (kernel.currentTask and kernel.currentTask.groups) or {}, groups = (kernel.currentTask and kernel.currentTask.groups) or {},
fd = fds, fd = {},
sleep = 0, sleep = 0,
ivs = 0, ivs = 0,
vs = 0, vs = 0,
@@ -100,15 +93,15 @@ local function createTask(func, name, envars, args, tgid, real_uid, eff_uid, cle
return id return id
end end
function sys.spawn(func, name, envars, args, tgid, clearFds) function sys.spawn(func, name, envars, args, tgid)
local caller = kernel.currentTask local caller = kernel.currentTask
local real_uid = caller and caller.uid or kernel.uid local real_uid = caller and caller.uid or kernel.uid
local eff_uid = caller and caller.euid or real_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 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) local func, euid, suid_active = loadExecutable(path, kernel._U)
local caller = kernel.currentTask local caller = kernel.currentTask
local real_uid = caller and caller.uid or kernel.uid local real_uid = caller and caller.uid or kernel.uid
@@ -121,26 +114,22 @@ function sys.execspawn(path, name, envars, args, tgid, keepFds)
) )
end 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 end
function sys.exec(path, args, envars, clearFds) function sys.exec(path, args, envars)
local task = kernel.currentTask local task = kernel.currentTask
local func, euid, _ = loadExecutable(path) local func, euid, _ = loadExecutable(path, kernel._U)
-- no idea why this is here? if task.fd then
-- Figured it out it is to close fds on su for fd, _ in pairs(task.fd) do
if clearFds then if fd > 2 then pcall(kernel.vfs.close, fd) end
if task.fd then
for fd, _ in pairs(task.fd) do
if fd > 2 then pcall(kernel.vfs.close, fd) end
end
end end
end end
task.euid = euid task.euid = euid
task.args = args or {} task.args = args or {}
task.envars = envars or task.envars or {} task.envars = envars or task.envars
task.name = path task.name = path
task.coro = coroutine.create(function() task.coro = coroutine.create(function()
@@ -312,7 +301,7 @@ end
function sys.getuid() return kernel.currentTask.uid end function sys.getuid() return kernel.currentTask.uid end
function sys.reapDeadTasks() local function reapDeadTasks()
for pid, task in pairs(tasks) do for pid, task in pairs(tasks) do
if task.status == "Z" and not task.reapTime then if task.status == "Z" and not task.reapTime then
if task.pid == 1 then kernel.panic("Attempted to gc init!") end if task.pid == 1 then kernel.panic("Attempted to gc init!") end
@@ -349,41 +338,205 @@ function sys.reapDeadTasks()
end end
end end
kernel.execPerTask(function(task) local alpha = 0.85
kernel.currentTask = task local C_target = 0.01
kernel.uid = task.euid or task.uid local Tmin = 0.0005
kernel.process = task.name 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
if task.status == "S" and kernel.EFI:getEpochMs() >= task.sleep then function kernel.main()
task.status = "R" kernel.log("Starting main loop...")
task.sleep = 0 kernel.saveLog()
end local stopLog=5
local logTasks=100
if task.status == "ST" and kernel.EFI:getEpochMs() >= task.sleep then while not kernel.exitMain do
task.status = "T" if kernel.config.logTasks then
task.sleep = 0 if logTasks<0 then
end 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 = {}
if task.status == "DS" and kernel.EFI:getEpochMs() >= task.sleep then for pid, task in pairs(tasks) do
task.status = "D" if kernel.exitMain then break end
task.sleep = 0 kernel.currentTask = task
end kernel.uid = task.euid or task.uid
kernel.process = task.name
if task.status == "D" then if task.status == "S" and kernel.EFI:getEpochMs() >= task.sleep then
if task.io then
local ret = {xpcall(task.io, debug.traceback)}
if not ret[1] then
task.syscallReturn = {false, table.unpack(ret, 2)}
task.status = "R" task.status = "R"
task.io=nil task.sleep = 0
elseif #ret>1 then end
task.syscallReturn = {true, table.unpack(ret, 2)}
task.status = "R" if task.status == "ST" and kernel.EFI:getEpochMs() >= task.sleep then
task.io=nil task.status = "T"
task.sleep = 0
end
if task.status == "DS" and kernel.EFI:getEpochMs() >= task.sleep then
task.status = "D"
task.sleep = 0
end
if task.status == "D" then
if task.io then
local ret = {xpcall(task.io, debug.traceback)}
if not ret[1] then
task.syscallReturn = {false, table.unpack(ret, 2)}
task.status = "R"
task.io=nil
elseif #ret>1 then
task.syscallReturn = {true, table.unpack(ret, 2)}
task.status = "R"
task.io=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.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
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
end,1) end
local sysc = kernel.syscalls local sysc = kernel.syscalls
sysc["spawn"] = sys.spawn sysc["spawn"] = sys.spawn
@@ -1,7 +1,7 @@
--:Minify:-- --:Minify:--
local kernel=... local kernel=...
kernel.debug=debug local debug=debug
kernel._G.debug={ kernel._G.debug={
getinfo=kernel.debug.getinfo, getinfo=debug.getinfo,
traceback=kernel.debug.traceback traceback=debug.traceback
} }
@@ -14,22 +14,11 @@ local data = kernel.vfs.read(handle, 1024 * 1024 * 4)
if not handle then kernel.panic("Failed to read "..kernel.config.initPath) end if not handle then kernel.panic("Failed to read "..kernel.config.initPath) end
kernel.vfs.close(handle) kernel.vfs.close(handle)
local initFunc, err = load(data, "@init", "t", kernel._U) local initFunc, err = load(data, "@sysinit", "t", kernel._U)
if not initFunc then kernel.PANIC("Failed to load init system: " .. err) end if not initFunc then kernel.PANIC("Failed to load init system: " .. err) end
kernel.tasks["1"] = { kernel.tasks["1"] = {
coro = coroutine.create(function() coro = coroutine.create(function()
for i,v in pairs(kernel.processes) do
kernel.log("Spawning kernel task "..i)
syscall.spawn(function()
local status, err = pcall(v)
if not status then
kernel.log("Error executing kernel task '" .. i .. "': " .. err, "ERROR", 0xFF0000)
else
kernel.log("Successfully executed kernel task: " .. i)
end
end, i, nil,nil,nil,true)
end
local ok, err = xpcall(initFunc, debug.traceback, kernel) local ok, err = xpcall(initFunc, debug.traceback, kernel)
if not ok then if not ok then
kernel.panic("Init system crashed: " .. tostring(err)) kernel.panic("Init system crashed: " .. tostring(err))
@@ -39,7 +28,7 @@ kernel.tasks["1"] = {
kernel.saveLog() kernel.saveLog()
end), end),
name = "init", name = "sysinit",
status = "R", status = "R",
pid = 1, pid = 1,
tgid = 1, tgid = 1,
@@ -2,11 +2,11 @@
local kernel = ... local kernel = ...
kernel.processes.kgc = function() kernel.processes.kgc = function()
while true do while true do
--for i,v in pairs(kernel.reqcache) do for i,v in pairs(kernel.reqcache) do
-- if v.expires and kernel.EFI:getEpochMs() > v.expires then if v.expires and kernel.EFI:getEpochMs() > v.expires then
-- kernel.reqcache[i] = nil kernel.reqcache[i] = nil
-- end end
--end end
sleep(5) sleep(5)
end end
end end
@@ -1,12 +1,7 @@
--:Minify:-- --:Minify:--
local kernel = ... local kernel = ...
if kernel.firstBoot or kernel.config.resetPerms then if kernel.firstBoot then
if kernel.config.resetPerms then
kernel.log("resetPerms is active, disable it in /boot/boot.cfg", "WARN", 0xFFFF00)
end
kernel.log("Seeding filesystem permissions...")
local P = kernel.vfs.P local P = kernel.vfs.P
local PERM = kernel.vfs.PERM local PERM = kernel.vfs.PERM
@@ -19,47 +14,107 @@ if kernel.firstBoot or kernel.config.resetPerms then
local RWXRWXRWX = PERM.RWXRWXRWX local RWXRWXRWX = PERM.RWXRWXRWX
local SUID_755 = PERM.SUID_755 local SUID_755 = PERM.SUID_755
local function seed(root, data) local META_VERSION = 0x02
for i=1,#data do local rootDisk = kernel.disks["$"]
local entry=data[i]
if kernel.vfs.exists(root..entry[1]) then local function makeEntry(name, etype, owner, group, perms, cmeta)
kernel.vfs.updateMeta(root..entry[1],function(e) cmeta = cmeta or ""
e.perms=entry[4] local plo = perms % 256
e.group=entry[3] local phi = math.floor(perms / 256) % 256
e.owner=entry[2] local olo = (owner or 0) % 256
end) local ohi = math.floor((owner or 0) / 256) % 256
end 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
end end
seed("/", { kernel.log("Seeding filesystem permissions...")
{"bin", 0, 0, RWX_RX_RX},
{"boot", 0, 0, RWX_RX_RX}, mergeMeta("/", {
{"etc", 0, 0, RWX_RX_RX}, {"bin", REG, 0, 0, RWX_RX_RX},
{"home", 0, 0, RWX_RX_RX}, {"boot", REG, 0, 0, RWX_RX_RX},
{"lib", 0, 0, RWX_RX_RX}, {"dev", REG, 0, 0, RWXRWXRWX},
{"root", 0, 0, RW____ }, {"etc", REG, 0, 0, RWX_RX_RX},
{"sbin", 0, 0, RWX_RX_RX}, {"home", REG, 0, 0, RWX_RX_RX},
{"tmp", 0, 0, RWXRWXRWX}, {"lib", REG, 0, 0, RWX_RX_RX},
{"usr", 0, 0, RWX_RX_RX}, {"proc", REG, 0, 0, RWXRWXRWX},
{"var", 0, 0, RWXRWXRWX}, {"root", REG, 0, 0, RW____ },
{"opt", 0, 0, RWX_RX_RX}, {"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/", { mergeMeta("/bin", {
{"login", 0, 0, SUID_755 }, {"login", REG, 0, 0, SUID_755 },
{"su", 0, 0, SUID_755 }, {"su", REG, 0, 0, SUID_755 },
{"sudo", 0, 0, SUID_755 }, {"sudo", REG, 0, 0, SUID_755 },
}) })
seed("/etc/", { mergeMeta("/etc", {
{"passwd", 0, 0, RW_R_R }, {"passwd", REG, 0, 0, RW_R_R },
{"shadow", 0, 0, RW____ }, {"shadow", REG, 0, 0, RW____ },
{"pam.d", 0, 0, RW____ }, {"pam.d", REG, 0, 0, RW____ },
}) })
seed("/etc/pam.d/", { mergeMeta("/etc/pam.d", {
{"secret", 0, 0, RW____}, {"secret", REG, 0, 0, RW____},
}) })
kernel.log("Filesystem permissions seeded.") kernel.log("Filesystem permissions seeded.")
+1 -1
View File
@@ -1 +1 @@
1.2.4 1.5.0
-1
View File
@@ -1 +0,0 @@
Hyperion
-2
View File
@@ -1,2 +0,0 @@
Hyperion-kernel
Hyperion-core
-1
View File
@@ -1 +0,0 @@
HyperionOS install package-group
-1
View File
@@ -1 +0,0 @@
1.2.4
-1
View File
@@ -1 +0,0 @@
Hyperion
-10
View File
@@ -1,10 +0,0 @@
Hyperion-kernel
Hyperion-core
coreutils
spm
sysinit
hysh
lua
micro
Hypersplash
math
-1
View File
@@ -1 +0,0 @@
HyperionOS install package-group
-1
View File
@@ -1 +0,0 @@
1.2.4
-1
View File
@@ -1 +0,0 @@
Hyperion
-6
View File
@@ -1,6 +0,0 @@
Hyperion-kernel
Hyperion-core
coreutils
hysh
lua
wget
-1
View File
@@ -1 +0,0 @@
HyperionOS install package-group
-1
View File
@@ -1 +0,0 @@
1.2.4
+2 -5
View File
@@ -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/tty/1", "w") --stdout (fd 1)
syscall.open("/dev/null", "w") --stderr (fd 2) syscall.open("/dev/null", "w") --stderr (fd 2)
local fs=require("fs")
local MAX_ATTEMPTS = 3 local MAX_ATTEMPTS = 3
@@ -101,9 +100,7 @@ local function spawnShell(username, uid, shell, homedir)
pcall(syscall.chdir, "/") pcall(syscall.chdir, "/")
end end
local shellfunc, err = load(fs.readAllText(shell)) local ok, err = pcall(syscall.execspawn, shell, username .. ":shell")
local ok, err = pcall(syscall.spawn, shellfunc, username .. ":shell", nil,nil,nil,true)
if not ok then if not ok then
syscall.write(1, "login: failed to launch shell: " .. tostring(err) .. "\n") syscall.write(1, "login: failed to launch shell: " .. tostring(err) .. "\n")
sleep(2) sleep(2)
@@ -148,7 +145,7 @@ local function doLogin()
syscall.devctl(1, "sfgc", 0xFFFFFF) syscall.devctl(1, "sfgc", 0xFFFFFF)
sleep(0.3) sleep(0.3)
pcall(spawnShell, username, uid, shell, homedir) spawnShell(username, uid, shell, homedir)
return -- back to login prompt return -- back to login prompt
else else
attempts = attempts + 1 attempts = attempts + 1
+1 -1
View File
@@ -58,7 +58,7 @@ syscall.setEnviron("HOME", homedir)
syscall.setEnviron("USER", username) syscall.setEnviron("USER", username)
syscall.setEnviron("SHELL", shell) syscall.setEnviron("SHELL", shell)
local ok, err = pcall(syscall.exec, shell, nil, true) local ok, err = pcall(syscall.exec, shell)
if not ok then if not ok then
print("su: cannot exec shell '" .. shell .. "': " .. tostring(err)) print("su: cannot exec shell '" .. shell .. "': " .. tostring(err))
syscall.exit(1) syscall.exit(1)
+2 -5
View File
@@ -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/tty/1", "w") --stdout (fd 1)
syscall.open("/dev/null", "w") --stderr (fd 2) syscall.open("/dev/null", "w") --stderr (fd 2)
local fs=require("fs")
local MAX_ATTEMPTS = 3 local MAX_ATTEMPTS = 3
@@ -101,9 +100,7 @@ local function spawnShell(username, uid, shell, homedir)
pcall(syscall.chdir, "/") pcall(syscall.chdir, "/")
end end
local shellfunc, err = load(fs.readAllText(shell)) local ok, err = pcall(syscall.execspawn, shell, username .. ":shell")
local ok, err = pcall(syscall.spawn, shellfunc, username .. ":shell", nil,nil,nil,true)
if not ok then if not ok then
syscall.write(1, "login: failed to launch shell: " .. tostring(err) .. "\n") syscall.write(1, "login: failed to launch shell: " .. tostring(err) .. "\n")
sleep(2) sleep(2)
@@ -148,7 +145,7 @@ local function doLogin()
syscall.devctl(1, "sfgc", 0xFFFFFF) syscall.devctl(1, "sfgc", 0xFFFFFF)
sleep(0.3) sleep(0.3)
pcall(spawnShell, username, uid, shell, homedir) spawnShell(username, uid, shell, homedir)
return -- back to login prompt return -- back to login prompt
else else
attempts = attempts + 1 attempts = attempts + 1
-1
View File
@@ -1 +0,0 @@
vector
-19
View File
@@ -1,19 +0,0 @@
function lib.load(fd)
function handle.setPixel(x,y,color24)
function handle.getPixel(x,y)
function handle.setPixels(x,y,w,framebuffer)
function handle.getPixels(x,y,w,h)
function handle.frame(x,y,w,h,writeonly)
integer id
recurse lib.load
function handle.framectl(id)
function frame.move(x,y)
function frame.resize(w,h)
function frame.free()
function handle.sync()
function handle.line(x1,y1,x2,y2)
function handle.box(x,y,w,h,c,fill)
function handle.filledBox(x,y,w,h,c)
function handle.text(x,y,font,text)
function handle.free()
function handle.size()
-256
View File
@@ -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
File renamed without changes.
+84
View File
@@ -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
File renamed without changes.
File renamed without changes.
File renamed without changes.
+3 -1
View File
@@ -239,7 +239,9 @@ else
for _, cmd in ipairs(COMMANDS) do addCmd(cmd) end for _, cmd in ipairs(COMMANDS) do addCmd(cmd) end
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 pageSize = screenH - 2
local scroll = 0 local scroll = 0
+21 -17
View File
@@ -6,7 +6,6 @@ syscall.open("/dev/tty/1","w") --stdout (Device 1)
syscall.open("/dev/null","w") --stderr (device 2) syscall.open("/dev/null","w") --stderr (device 2)
local fs = require("fs") local fs = require("fs")
local gfx = syscall.devctl(1,"gfx")
syscall.devctl(1,"clear") syscall.devctl(1,"clear")
syscall.devctl(1,"sfgc",0xFFFFFF) syscall.devctl(1,"sfgc",0xFFFFFF)
@@ -243,7 +242,6 @@ builtinCmds.clear = function()
syscall.devctl(1,"clear") syscall.devctl(1,"clear")
syscall.devctl(1,"sfgc",0xFFFFFF) syscall.devctl(1,"sfgc",0xFFFFFF)
syscall.devctl(1,"spos",1,1) syscall.devctl(1,"spos",1,1)
if gfx then local w,h=gfx.size() gfx.box(0,0,w+5,h+5,0,true) end
end end
builtinCmds.whoami = function() builtinCmds.whoami = function()
@@ -822,11 +820,10 @@ builtinCmds.df = function(...)
end end
local function fmt(n) return opts.h and hfmt(n) or tostring(n) end local function fmt(n) return opts.h and hfmt(n) or tostring(n) end
print(string.format("%-20s %10s %10s %10s %6s %-s","Filesystem","Size","Used","Avail","Use%","Mounted on")) print(string.format("%-20s %10s %10s %10s %6s %-s","Filesystem","Size","Used","Avail","Use%","Mounted on"))
local fsinfo = syscall.fsinfo() local mounts = {{"$","/"}, {"devfs0000","/dev/"}, {"tmpfs0000","/tmp/"}}
for id, obj in pairs(fsinfo.disks) do for _, m in ipairs(mounts) do
local use = ((obj.size/obj.used)-1)*100 local id, mp = m[1], m[2]
local avail = obj.size-obj.used print(string.format("%-20s %10s %10s %10s %6s %-s", id, "?", "?", "?", "?%", mp))
print(string.format("%-20s %10s %10s %10s %6s %-s", id, tostring(obj.size), tostring(obj.used), avail, tostring(use).."%", fsinfo.mounts[id] or ""))
end end
end end
@@ -1012,7 +1009,9 @@ local function getUserInput()
syscall.write(1, syscall.getcwd()) syscall.write(1, syscall.getcwd())
syscall.devctl(1,"sfgc",0xFFFFFF) syscall.devctl(1,"sfgc",0xFFFFFF)
syscall.write(1, "$ ") 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 input = ""
local blinkState = false local blinkState = false
@@ -1110,10 +1109,14 @@ local function getUserInput()
local newInput, newCursor, needsRedraw = doTabComplete(input, cursorPos) local newInput, newCursor, needsRedraw = doTabComplete(input, cursorPos)
if needsRedraw then if needsRedraw then
input = newInput; cursorPos = newCursor 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 if px > 1 then
syscall.devctl(1,"spos",1,py) 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.write(1, string.rep(" ", tw))
syscall.devctl(1,"spos",1,py) syscall.devctl(1,"spos",1,py)
end end
@@ -1121,7 +1124,10 @@ local function getUserInput()
syscall.devctl(1,"sfgc",0xFFFFFF); syscall.write(1, ":") syscall.devctl(1,"sfgc",0xFFFFFF); syscall.write(1, ":")
syscall.devctl(1,"sfgc",0x00FFFF); syscall.write(1, syscall.getcwd()) syscall.devctl(1,"sfgc",0x00FFFF); syscall.write(1, syscall.getcwd())
syscall.devctl(1,"sfgc",0xFFFFFF); syscall.write(1, "$ ") 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 dirty = true
end end
elseif key=="\b" then elseif key=="\b" then
@@ -1209,9 +1215,9 @@ local function runCommand(command)
local proc = syscall.spawn(function() local proc = syscall.spawn(function()
-- Open standard fds so programs that don't do it themselves work correctly. -- 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/0", "r") -- fd 0 stdin
--syscall.open("/proc/self/parent/fd/1", "w") -- fd 1 stdout 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/2", "w") -- fd 2 stderr
-- exec replaces this coroutine's code with a fresh isolated environment -- exec replaces this coroutine's code with a fresh isolated environment
-- compiled from disk by the kernel (via loadExecutable -> freshUserEnv), -- compiled from disk by the kernel (via loadExecutable -> freshUserEnv),
-- so the child cannot share any upvalue or syscall table state with hysh. -- so the child cannot share any upvalue or syscall table state with hysh.
@@ -1221,14 +1227,12 @@ local function runCommand(command)
while true do while true do
local exited, code = syscall.collect(proc) local exited, code = syscall.collect(proc)
if exited then if exited then
if gfx then gfx.setMode(false) end
if code then print("\nTask exited with code:\n"..tostring(code)) end if code then print("\nTask exited with code:\n"..tostring(code)) end
return return
end end
if terminate then if terminate then
local ok2 = syscall.kill(proc, true) local ok2 = syscall.kill(proc)
if ok2 then if ok2 then
if gfx then gfx.setMode(false) end
syscall.devctl(1,"sbgc",16); syscall.devctl(1,"sfgc",0xFF0000) syscall.devctl(1,"sbgc",16); syscall.devctl(1,"sfgc",0xFF0000)
print("\nProgram Terminated."); syscall.devctl(1,"sfgc",0xFFFFFF) print("\nProgram Terminated."); syscall.devctl(1,"sfgc",0xFFFFFF)
end end
+2 -1
View File
@@ -91,7 +91,8 @@ local function humanSize(size)
return math.floor(size) .. sizePrefixes[scale] return math.floor(size) .. sizePrefixes[scale]
end 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) local list = fs.list(dir)
list[#list+1] = "." list[#list+1] = "."
-10
View File
@@ -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
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loaded 100 of 192 files, more files were not shown because too many files have changed in this diff. Show more