Compare commits
12
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a33bd0264 | ||
|
|
242762ab6b | ||
|
|
8c18d89489 | ||
|
|
041663e1e8 | ||
|
|
fcac0ff8d8 | ||
|
|
d98555328b | ||
|
|
61cbb91db2 | ||
|
|
b79492dbb8 | ||
|
|
bc87c53427 | ||
|
|
030e5bfd96 | ||
|
|
099638c735 | ||
|
|
5172da1b5b |
No files matched your search
Vendored
+2
-2
@@ -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
|
|
||||||
@@ -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
|
|
||||||
File renamed without changes.
@@ -1,5 +0,0 @@
|
|||||||
--:Minify:--
|
|
||||||
local kernel=...
|
|
||||||
if kernel.arch~="cct" then
|
|
||||||
kernel.deny("cc-tweaked/31_keyboards.kmod")
|
|
||||||
end
|
|
||||||
File renamed without changes.
@@ -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
|
||||||
File renamed without changes.
File renamed without changes.
@@ -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("[nS")
|
kernel.cct.fifo.push("[nS")
|
||||||
kernel.cct.mouse.fifo.push("[nS")
|
|
||||||
else
|
else
|
||||||
kernel.cct.fifo.push("[nT")
|
kernel.cct.fifo.push("[nT")
|
||||||
kernel.cct.mouse.fifo.push("[nT")
|
|
||||||
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
|
|
||||||
--"[C;X;Y;C"
|
|
||||||
-- 1 = left
|
|
||||||
-- 2 = right
|
|
||||||
-- 3 = middle
|
|
||||||
kernel.cct.mouse.fifo.push("[C;"..tostring(event[3])..";"..tostring(event[4])..";"..tostring(event[2]))
|
|
||||||
elseif eventType == "mouse_drag" then
|
|
||||||
kernel.cct.mouse.fifo.push("[D;"..tostring(event[3])..";"..tostring(event[4])..";"..tostring(event[2]))
|
|
||||||
elseif eventType == "mouse_up" then
|
|
||||||
kernel.cct.mouse.fifo.push("[U;"..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 +1 @@
|
|||||||
Hyperion
|
Hyperion
|
||||||
Astronand
|
|
||||||
Xtimhedae
|
|
||||||
@@ -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
|
|
||||||
@@ -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 @@
|
|||||||
firmware for Opencomputers mod
|
firmware for Opencomputers
|
||||||
@@ -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")
|
|
||||||
@@ -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/
|
||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
0:0:root:/root:/bin/hysh
|
||||||
File renamed without changes.
@@ -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 @@
|
|||||||
1.2.4
|
1.5.0
|
||||||
@@ -1 +0,0 @@
|
|||||||
Hyperion
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
Hyperion-kernel
|
|
||||||
Hyperion-core
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
HyperionOS install package-group
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
1.2.4
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
Hyperion
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
Hyperion-kernel
|
|
||||||
Hyperion-core
|
|
||||||
coreutils
|
|
||||||
spm
|
|
||||||
sysinit
|
|
||||||
hysh
|
|
||||||
lua
|
|
||||||
micro
|
|
||||||
Hypersplash
|
|
||||||
math
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
HyperionOS install package-group
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
1.2.4
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
Hyperion
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
Hyperion-kernel
|
|
||||||
Hyperion-core
|
|
||||||
coreutils
|
|
||||||
hysh
|
|
||||||
lua
|
|
||||||
wget
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
HyperionOS install package-group
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
1.2.4
|
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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 +0,0 @@
|
|||||||
vector
|
|
||||||
@@ -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()
|
|
||||||
@@ -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.
@@ -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.
File renamed without changes.
File renamed without changes.
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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] = "."
|
||||||
|
|||||||
@@ -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
Reference in new issue
Block a user