Compare commits
147 Commits
6e363a688e
...
1.2.4-dev_
| Author | SHA1 | Date | |
|---|---|---|---|
| 22b5021e9d | |||
| 462c74686a | |||
| 0072547beb | |||
| 7deefc83ca | |||
| df62414229 | |||
| 055dd4e606 | |||
| 5755dd9cbe | |||
| 8e11faf9ec | |||
| 0ea42f9454 | |||
| d0f26a937f | |||
| 9b338328f0 | |||
| 4f9eebade2 | |||
| d08935b68a | |||
| 45b46cf3c4 | |||
| aeea68bc9b | |||
| f983b13d56 | |||
| 03c5b106c4 | |||
| 08323e00ff | |||
| 5e3cdbe40c | |||
| 8762b8f022 | |||
| 677b2cccec | |||
| a5e8624368 | |||
| bbda3b3937 | |||
| 585d39bec2 | |||
| b08b14763a | |||
| de6696003b | |||
| 9220281365 | |||
| 813ddabd9d | |||
| 5177639d71 | |||
| 528b4f31bd | |||
| 60162c7c57 | |||
| 18f5c454bb | |||
| 849ecb7dd6 | |||
| e41bd6bee7 | |||
| 359198c1ea | |||
| beebf01223 | |||
| 2d4ea1bbf4 | |||
| ea3a7e99a7 | |||
| be0fe5dc5a | |||
| 12669d9f82 | |||
| f12159bfb9 | |||
| 1590e1f3f7 | |||
| a69f945b91 | |||
| 7da67899db | |||
| 62e032e4c5 | |||
| 6fefa2d9ff | |||
| bb354cc706 | |||
| fabc061731 | |||
| 82c3e2b346 | |||
| e2e1d5b8a5 | |||
| 9342b9b2b3 | |||
| 9a7db6c243 | |||
| c7545e6947 | |||
| b7f52dd17b | |||
| eb5bed0f09 | |||
| 1827a463eb | |||
| b532a63fc6 | |||
| 4e5a4172bf | |||
| 31ce894fda | |||
| 16c900de84 | |||
| 413afd96de | |||
| a0a0ac69d4 | |||
| 17453983ad | |||
| a6550aa069 | |||
| 02e7b3897c | |||
| 34b89a8e34 | |||
| 0eabfebd0f | |||
| 5b2e5eac65 | |||
| 415064480a | |||
| f00453f703 | |||
| ab1e847d1c | |||
| 62a03bfe6b | |||
| e77a8b3636 | |||
| 6bb7f03a3e | |||
| 8798a2f4fe | |||
| a6d2f6dca7 | |||
| b015d5880a | |||
| 6694711423 | |||
| 40c97ca000 | |||
| dd2437d4af | |||
| d026cfbb03 | |||
| aad7efd055 | |||
| 93c3bab263 | |||
| 5bd16b8fd4 | |||
| 3cc1459769 | |||
| 0655f2a39e | |||
| 57b1d46837 | |||
| 875759022a | |||
|
|
bb14ea34c3 | ||
|
|
149fb18564 | ||
| 10bc775e64 | |||
| 287b146621 | |||
|
|
371954373e | ||
|
|
ecef2c6cb0 | ||
|
|
6770533581 | ||
| 19a9c72c6d | |||
| fdb18d4ac5 | |||
|
|
303449e13c | ||
| b6d1b9398f | |||
| bb829cdd8e | |||
| 6b9bed5047 | |||
|
|
753c34bffa | ||
| 403178c832 | |||
| 33cd291c21 | |||
| 1c4f48bd65 | |||
| ec5e63898d | |||
| ea2a0e0e94 | |||
| 4f50d90b79 | |||
| bf1dc9da7a | |||
| 1a455a6025 | |||
| c9ac447484 | |||
| cb73f49962 | |||
| d9caf655fb | |||
| 1c3d2c8b48 | |||
| 9bd9cdaba4 | |||
| 72bfce7b08 | |||
| 6e48fcd5b9 | |||
| 2d98ff64ce | |||
| 6a14b87f44 | |||
| 63bcc2df5c | |||
| fd7ee1aa3b | |||
| 1073362007 | |||
| da5ad3b5cb | |||
| e77fbcaf5d | |||
| 111fe764f8 | |||
|
|
83857d7e87 | ||
| 83814311e5 | |||
| 55fdddeff8 | |||
| 1b21c87654 | |||
| df4823940d | |||
| 70532f6e2c | |||
| bd8fe50770 | |||
| e5d6ec9725 | |||
| c620c4f1ba | |||
| 6b48e80157 | |||
| fbbb8b8d65 | |||
|
|
a88bdc9639 | ||
| 96c22f5237 | |||
| 231b0ced48 | |||
| 4100ecf0a1 | |||
|
|
968f4c54d7 | ||
| 70526c76ba | |||
| 3a8be2bdb7 | |||
| efffc8f0d2 | |||
| b48f926053 | |||
| 7d8055a703 | |||
| 1141193fc8 |
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# Build output
|
||||||
|
/Build/
|
||||||
|
/build/
|
||||||
|
Build/
|
||||||
|
build/
|
||||||
|
|
||||||
|
# VSCodeCounter
|
||||||
|
/.VSCodeCounter/
|
||||||
|
.VSCodeCounter/
|
||||||
11
.vscode/settings.json
vendored
Normal file
11
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"Lua.diagnostics.globals": [
|
||||||
|
"isEqualToAny",
|
||||||
|
"isEqualToAll",
|
||||||
|
"syscall",
|
||||||
|
"printf",
|
||||||
|
"printInline",
|
||||||
|
"toHex",
|
||||||
|
"loadcstr"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
print(".. *. ..")
|
|
||||||
print(" *= +@* +* ")
|
|
||||||
print(" .@#. -@@@= :#@. ")
|
|
||||||
print(" =@@+ *@@@# +@@= ")
|
|
||||||
print(" %@@%: *@@@# -%@@% ")
|
|
||||||
print(" :@@@@+ *@@@# .*@@@@: ")
|
|
||||||
print(" :*@@@%- *@@@# -@@@@*: ")
|
|
||||||
print(" =%@@#. *@@@# .#@@%= ")
|
|
||||||
print(" :=. :*@@= *@@@# =@@+: .=: ")
|
|
||||||
print(" %@#=..*# +@@@# #*..=#@# ")
|
|
||||||
print(" .@@@@+=# .%@%: #=+@@@@. ")
|
|
||||||
print(" .....=# -@= *+...:. ")
|
|
||||||
print(" -*%*-@= - =@-*%*- ")
|
|
||||||
print(" -@*. -@%. :%@- :*@- ")
|
|
||||||
print(" .#@#@* ")
|
|
||||||
print(" -#- ")
|
|
||||||
print(" ")
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
print("hello from hello.lua")
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
|||||||
sleep(1)local a="/$"local b={...}if _HOST:find("UnBIOS")then return end;local c={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 d={}for e in pairs(_G)do if not c[e]then table.insert(d,e)end end;for f,e in ipairs(d)do _G[e]=nil end;local g=_G.term.native()for f,h in ipairs{"nativePaletteColor","nativePaletteColour","screenshot"}do g[h]=_G.term[h]end;_G.term=g;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 i={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 e,j in pairs(i)do for f,k in ipairs(j)do _G[e][k]=nil end end;_G._HOST=_G._HOST.." (UnBIOS)"local l=error;_G.error=function()end;_G.term.redirect=function()end;function _G.term.native()_G.term.native=nil;_G.term.redirect=nil;_G.error=l;term.setBackgroundColor(32768)term.setTextColor(1)term.setCursorPos(1,1)term.setCursorBlink(true)term.clear()local m=fs.open(a.."/boot/cct/boot.lua","r")if m==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 n,o=loadstring(m.readAll(),"@bootloader")m.close()if n==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(o)term.setCursorPos(1,3)term.write("Press any key to continue")coroutine.yield("key")os.shutdown()end;setfenv(n,_G)local p=os.shutdown;os.shutdown=function()os.shutdown=p;return n(table.unpack(b))end end;if debug then local function q(r,s,t,u)local v,w,x=1,debug.getupvalue(r[s],u)while w~=t and w~=nil do w,x=debug.getupvalue(r[s],v)v=v+1 end;r[s]=x or r[s]end;q(_G,"loadstring","nativeloadstring",1)q(_G,"load","nativeload",5)if http then q(http,"request","nativeHTTPRequest",3)end;q(os,"shutdown","nativeShutdown",1)q(os,"reboot","nativeReboot",1)if turtle then q(turtle,"equipLeft","v",1)q(turtle,"equipRight","v",1)end;do local v,w,x=1,debug.getupvalue(peripheral.isPresent,2)while w~="native"and w~=nil do w,x=debug.getupvalue(peripheral.isPresent,v)v=v+1 end;_G.peripheral=x or peripheral end end
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
local a=({...})[1]local b="/$"local c=a.fs;local d=a.peripheral;local e={}local f={"top","bottom","left","right","front","back"}function e.getType(g)if d.isPresent(g)then return d.getType(g)end;for h=1,#f do local i=f[h]if d.hasType(i,"peripheral_hub")and d.call(i,"isPresentRemote",g)then return d.call(i,"getTypeRemote",g)end end;return nil end;function e.getNames()local j={}for h=1,#f do local i=f[h]if d.isPresent(i)then table.insert(j,i)end;if d.hasType(i,"peripheral_hub")then local k=d.call(i,"getConnectedSides")for l,m in ipairs(k)do table.insert(j,m)end end end;return j end;local n={}local o={}local function p(q)if not q or q==""then return"/"end;return c.combine("/",q)end;local function r(s,t,u,v)t=p(t)local disk={address=s,isReadOnly=function()return u end}function disk:spaceUsed()return c.getCapacity(t)-c.getFreeSpace(t)end;function disk:spaceTotal()return c.getCapacity(t)end;function disk:list(q)local w=c.combine(t,q)if not c.exists(w)or not c.isDir(w)then return nil,"not directory"end;return c.list(w)end;function disk:fileExists(q)local w=c.combine(t,q)return c.exists(w)and not c.isDir(w)end;function disk:directoryExists(q)local w=c.combine(t,q)return c.exists(w)and c.isDir(w)end;function disk:type(q)local w=c.combine(t,q)if not c.exists(w)then return nil elseif c.isDir(w)then return"directory"else return"file"end end;function disk:makeDirectory(q)local w=c.combine(t,q)c.makeDir(w)return true end;function disk:remove(q)local w=c.combine(t,q)if c.exists(w)then c.delete(w)end;return true end;function disk:setLabel(x)v.setLabel(x)end;function disk:getLabel(x)return v.getLabel()end;function disk:attributes(q)local w=c.combine(t,q)return c.attributes(w)end;function disk:open(q,y)local w=c.combine(t,q)return c.open(w,y)end;return disk end;o["$"]=r("$",b,false,{setLabel=function(x)local z=c.open("/.label","w")z.write(x)z.close()end,getLabel=function()local z=c.open("/.label","r")local x=z.readAll()z.close()return x end})local function A()for s,l in pairs(n)do if not e.getType(s)then n[s]=nil end end;for l,g in ipairs(e.getNames())do if e.getType(g)=="disk"then if not n[g]then local B=disk.getMountPath(g)if B then n[g]=r(g,B,false,disk)end end end end end;local function C()A()local D={}for s,E in pairs(o)do D[s]=E end;for s,E in pairs(n)do D[s]=E end;return pairs(D)end;return{refresh=A,list=C}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
U $;/
|
|
||||||
U devfs0000;/dev/
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
local a={}local b={}local c={}local function d(e)local f="/"for g,h in pairs(c)do if e:sub(1,#g)==g then if not f or#g>#f then f=g end end end;local i=e:sub(#f+1)return b[c[f]],i end;function a.update(j)b={}for k,l in j.list()do b[k]=l end end;function a.exists(e)local h,i=d(e)return h:directoryExists(i)or h:fileExists(i)end;function a.isFile(e)local h,i=d(e)return h:fileExists(i)end;function a.isDir(e)local h,i=d(e)return h:directoryExists(i)end;function a.list(e)local h,i=d(e)return h:list(i)end;function a.makeDir(e)local h,i=d(e)return h:makeDirectory(i)end;function a.remove(e)local h,i=d(e)return h:remove(i)end;function a.readAllText(e)local h,i=d(e)local m=h:open(i,"r")if not m then return nil end;local n=m.readAll()m.close()return n end;function a.writeAllText(e,o)local h,i=d(e)local m=h:open(i,"w")m.write(o)m.close()end;function a.appendAllText(e,o)local h,i=d(e)local m=h:open(i,"a")m.write(o)m.close()end;function a.load(e)return load(a.readAllText(e),e)end;function a.mount(h,f)if not b[h]then return end;c[f]=h end;return a
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
local a={...}local b=a[1]local c=a[2]local d=a[3]local e=a[5]local f=a[6]local g=a[7]local h=""local i={}i.process="Kernel"i.user="root"i.group="root"i.groups={0}i.uid=0;i.gid=0;i.status="start"i.key={}i.cache={}i.cache.preload={}i._G=_G;i.sleep=sleep;_G.sleep=nil;local j=false;function i.log(k,l)h=h..tostring(f:time()).." "..i.user.." "..i.process.."["..tostring(l or"INFO").."]: "..k.."\n"if i.status=="start"then e:print(tostring(f:time()).." "..i.user.." "..i.process.."["..tostring(l or"INFO").."]: "..k)elseif i.status=="init"then i.standbyTask=i.currentTask;i.currentTask=i.kernelTask;i.tty.print(tostring(f:time()).." "..i.user.." "..i.process.."["..tostring(l or"INFO").."]: "..k)i.currentTask=i.standbyTask end end;function i.PANIC(k)if i.status~="Panic"then i.log("PANIC: "..k,"PANIC")pcall(i["saveLog"])i.status="Panic"i.reason=k;e:setTextColor(2)e:setBackgroundColor(0)e:clear()e:setCursorPos(1,1)e:print(h)e:print("KERNEL PANIC!\n"..k.."\nSystem halted.")e:print("Press any key to continue...")end;while true do local m={f:getMachineEvent()}if m[1]=="keyPressed"then break end end;f:reboot()end;i.panic=i.PANIC;if j then e:setTextColor(1)e:setBackgroundColor(4)e:clear()local n,o=e:getSize()e:setCursorPos(3,5)e:print(":(")e:setCursorPos(3,7)e:print("Your PC ran into a problem and needs to restart. We're just collecting some error")e:setCursorPos(3,8)e:print("info, and then we'll restart for you.\n")e:setCursorPos(3,o-5)e:print("Stop code: average windows experience")e:setCursorPos(1,o)e:print("Press any key to continue... jk reboot it yourself lazy")while true do end end;i.log("Kernel loaded.")i.log("Mounting init disks...")c.refresh()g.update(c)i.disks={}for p,q in c.list()do i.disks[q.address]=q end;g.mount("$","/")local r=g.readAllText("/boot/fstab")local s=function(t,u,v)assert(#u==1,"only delim len 1 supported for now")v=(v or 0)-1;local w={}local x=""for y=1,#t do local z=string.sub(t,y,y)if#w~=v and z==u then table.insert(w,x)x=""else x=x..z end end;table.insert(w,x)return w end;if not g.isFile("/boot/boot.cfg")then i.log("boot.cfg missing or corrupted!, Attempting to write recovery boot.cfg","ERROR")g.writeAllText("/boot/boot.cfg",g.readAllText("/boot/safeboot.cfg"))end;local A,B=load(g.readAllText("/boot/boot.cfg"),"@boot.cfg")if not A then i.PANIC("Failed to load /boot/boot.cfg: "..tostring(B))end;local C,D=pcall(A)if not C then i.PANIC("Error in /boot/boot.cfg: "..tostring(D))end;i.config=D;for y,q in ipairs(s(r,"\n"))do if q:sub(1,1)=="U"then local E=""for y=3,#q do if q:sub(y,y)==";"then if y==3 then i.log("Invalid fstab line... Skipping.","WARN")goto F end;E=q:sub(3,y-1)end end;local G=q:sub(#E+4)g.mount(E,G)::F::end end;i.log("Disks initialized")function i.saveLog()g.writeAllText("/var/log/syslog.log",h)end;g.remove("/tmp")g.makeDir("/tmp")function i.newFifo()local H={}H.push=function(I)table.insert(I)end;H.pop=function()return table.remove(H,1)end;return H end;function i.newUUID()local J="xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"local K=""for y=1,#J do local z=J:sub(y,y)if z=="x"then K=K..string.format("%x",math.random(0,15))elseif z=="y"then K=K..string.format("%x",math.random(8,11))else K=K..z end end;return K end;i.syscalls={}local L={[0]={}}for y=0,100 do L[y]={}end;i.log("Gathering modules")for p,y in ipairs(g.list("/lib/modules"))do for p,q in ipairs(g.list("/lib/modules/"..y))do local M=tonumber(q:sub(1,2))L[M+1][#L[M+1]+1]="/lib/modules/"..y.."/"..q end end;i.ifs=g;i.apis=b;i.computer=f;i.arch=d;i.initdisks=c;i.screen=e;i.processes={}i.fstab=r;i.kernelTask={name="kernel",status="R",pid=0,tgid=0,user="root",uid=0,fd={},exit="",sleep=0,ivs=0,vs=0,children={},syscallReturn={},cwd="/",timeSlice=0,lastTime=0,totalTime=0,numRuns=0}i.currentTask=i.kernelTask;i.syscalls["OS_time"]=function()return i.computer:time()end;i.syscalls["OS_log"]=i.log;i.log("Running modules")for p,N in ipairs(L)do for p,q in ipairs(N)do local O=g.readAllText(q)if not O then i.log("ModuReadErr: "..q,"WARN")goto P end;local Q,B=load(O,"@"..q)if not Q then i.panic("ModuLoadErr: "..tostring(B))goto P end;local R,B=xpcall(Q,debug.traceback,i)if not R then i.panic("ModuRunErr: "..tostring(B))end::P::end end;i.log("Kernel initialized successfully.")i.main()i.PANIC("Execution complete")
|
|
||||||
151
Build/lib/bit32
151
Build/lib/bit32
@@ -1,151 +0,0 @@
|
|||||||
-- bit32.lua
|
|
||||||
-- Full pure-Lua implementation of Lua 5.2 bit32 library
|
|
||||||
-- NO Lua 5.3 operators used
|
|
||||||
|
|
||||||
local bit32 = {}
|
|
||||||
|
|
||||||
local MOD32 = 2^32
|
|
||||||
local MOD31 = 2^31
|
|
||||||
|
|
||||||
local function norm(x)
|
|
||||||
return x % MOD32
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Convert number to bit table
|
|
||||||
local function tobits(x)
|
|
||||||
x = norm(x)
|
|
||||||
local t = {}
|
|
||||||
for i = 0, 31 do
|
|
||||||
local b = x % 2
|
|
||||||
t[i] = b
|
|
||||||
x = (x - b) / 2
|
|
||||||
end
|
|
||||||
return t
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Convert bit table to number
|
|
||||||
local function frombits(t)
|
|
||||||
local x = 0
|
|
||||||
local p = 1
|
|
||||||
for i = 0, 31 do
|
|
||||||
if t[i] == 1 then
|
|
||||||
x = x + p
|
|
||||||
end
|
|
||||||
p = p * 2
|
|
||||||
end
|
|
||||||
return norm(x)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- ===== Logical ops =====
|
|
||||||
|
|
||||||
function bit32.band(...)
|
|
||||||
local args = {...}
|
|
||||||
if #args == 0 then return 0xFFFFFFFF end
|
|
||||||
local bits = tobits(args[1])
|
|
||||||
for i = 2, #args do
|
|
||||||
local b = tobits(args[i])
|
|
||||||
for j = 0, 31 do
|
|
||||||
bits[j] = (bits[j] == 1 and b[j] == 1) and 1 or 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return frombits(bits)
|
|
||||||
end
|
|
||||||
|
|
||||||
function bit32.bor(...)
|
|
||||||
local args = {...}
|
|
||||||
if #args == 0 then return 0 end
|
|
||||||
local bits = tobits(args[1])
|
|
||||||
for i = 2, #args do
|
|
||||||
local b = tobits(args[i])
|
|
||||||
for j = 0, 31 do
|
|
||||||
bits[j] = (bits[j] == 1 or b[j] == 1) and 1 or 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return frombits(bits)
|
|
||||||
end
|
|
||||||
|
|
||||||
function bit32.bxor(...)
|
|
||||||
local args = {...}
|
|
||||||
if #args == 0 then return 0 end
|
|
||||||
local bits = tobits(args[1])
|
|
||||||
for i = 2, #args do
|
|
||||||
local b = tobits(args[i])
|
|
||||||
for j = 0, 31 do
|
|
||||||
bits[j] = (bits[j] ~= b[j]) and 1 or 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return frombits(bits)
|
|
||||||
end
|
|
||||||
|
|
||||||
function bit32.bnot(x)
|
|
||||||
local bits = tobits(x)
|
|
||||||
for i = 0, 31 do
|
|
||||||
bits[i] = bits[i] == 1 and 0 or 1
|
|
||||||
end
|
|
||||||
return frombits(bits)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- ===== Shifts =====
|
|
||||||
|
|
||||||
function bit32.lshift(x, n)
|
|
||||||
return norm(norm(x) * 2^n)
|
|
||||||
end
|
|
||||||
|
|
||||||
function bit32.rshift(x, n)
|
|
||||||
return math.floor(norm(x) / 2^n)
|
|
||||||
end
|
|
||||||
|
|
||||||
function bit32.arshift(x, n)
|
|
||||||
x = norm(x)
|
|
||||||
if x >= MOD31 then
|
|
||||||
return math.floor((x - MOD32) / 2^n)
|
|
||||||
else
|
|
||||||
return math.floor(x / 2^n)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- ===== Rotates =====
|
|
||||||
|
|
||||||
function bit32.lrotate(x, n)
|
|
||||||
n = n % 32
|
|
||||||
x = norm(x)
|
|
||||||
local left = (x * 2^n) % MOD32
|
|
||||||
local right = math.floor(x / 2^(32 - n))
|
|
||||||
return norm(left + right)
|
|
||||||
end
|
|
||||||
|
|
||||||
function bit32.rrotate(x, n)
|
|
||||||
n = n % 32
|
|
||||||
x = norm(x)
|
|
||||||
local right = math.floor(x / 2^n)
|
|
||||||
local left = (x * 2^(32 - n)) % MOD32
|
|
||||||
return norm(left + right)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- ===== Bit fields =====
|
|
||||||
|
|
||||||
function bit32.extract(x, field, width)
|
|
||||||
width = width or 1
|
|
||||||
return bit32.band(bit32.rshift(x, field), 2^width - 1)
|
|
||||||
end
|
|
||||||
|
|
||||||
function bit32.replace(x, v, field, width)
|
|
||||||
width = width or 1
|
|
||||||
local mask = bit32.lshift(2^width - 1, field)
|
|
||||||
x = bit32.band(x, bit32.bnot(mask))
|
|
||||||
return bit32.bor(x, bit32.lshift(v, field))
|
|
||||||
end
|
|
||||||
|
|
||||||
-- ===== Test =====
|
|
||||||
|
|
||||||
function bit32.test(x, ...)
|
|
||||||
local args = {...}
|
|
||||||
for i = 1, #args do
|
|
||||||
if bit32.band(x, args[i]) ~= 0 then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
return bit32
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
local args={...}
|
|
||||||
local kernel=args[1]
|
|
||||||
local driver={}
|
|
||||||
|
|
||||||
driver.name="CCT Term Module"
|
|
||||||
driver.version="0.1.0"
|
|
||||||
driver.type="gpio"
|
|
||||||
driver.description="CCT redstone Module Kernel Module"
|
|
||||||
driver.arch="cct"
|
|
||||||
driver.author="HyperionOS Dev Team"
|
|
||||||
driver.license="MIT"
|
|
||||||
driver.api={}
|
|
||||||
|
|
||||||
function driver.load()
|
|
||||||
-- will
|
|
||||||
end
|
|
||||||
|
|
||||||
function driver.unload()
|
|
||||||
-- Nothing to unload
|
|
||||||
end
|
|
||||||
|
|
||||||
function driver.main()
|
|
||||||
-- Nothing to run
|
|
||||||
end
|
|
||||||
|
|
||||||
-- kernel.drivers.register(driver)
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
local a=...local b=a.apis;local c=b.term;local d=b.peripheral;local e={"top","bottom","left","right","front","back"}local function f(g)if d.isPresent(g)then return d.getType(g)end;for h=1,#e do local i=e[h]if d.hasType(i,"peripheral_hub")and d.call(i,"isPresentRemote",g)then return d.call(i,"getTypeRemote",g)end end;return nil end;local function j()local k={}for h=1,#e do local i=e[h]if d.isPresent(i)then table.insert(k,i)end;if d.hasType(i,"peripheral_hub")then local l=d.call(i,"getConnectedSides")for m,n in ipairs(l)do table.insert(k,n)end end end;return k end;local function o(g)if d.isPresent(g)then return o(g)end;for h=1,#e do local i=e[h]if d.hasType(i,"peripheral_hub")and d.call(i,"isPresentRemote",g)then return d.call(i,"wrapRemote",g)end end;return nil end;local p={[0]=0x000000,0xFFFFFF,0xFF0000,0x00FF00,0x0000FF,0x00FFFF,0xFF00FF,0xFFFF00,0xFF6D00,0x6DFF55,0x24FFFF,0x924900,0x6D6D55,0xDBDBAA,0x6D00FF,0xB6FF00}local q={[0x1]=0,[0x2]=1,[0x4]=2,[0x8]=3,[0x10]=4,[0x20]=5,[0x40]=6,[0x80]=7,[0x100]=8,[0x200]=9,[0x400]=10,[0x800]=11,[0x1000]=12,[0x2000]=13,[0x4000]=14,[0x8000]=15}local function r(s,t)local u,v=t.getCursorPos()local w,x=t.getSize()for y=1,#s do local z=s:sub(y,y)if z=="\n"then v=v+1;u=1 elseif z=="\t"then local A=4;local B=A-(u-1)%A;t.write(string.rep(" ",B))u=u+B elseif z=="\b"then if u>1 then u=u-1;t.setCursorPos(u,v)t.write(" ")t.setCursorPos(u,v)end else if u<=w and v<=x then t.setCursorPos(u,v)t.write(z)u=u+1 end end;if u>w then u=1;v=v+1 end;if v-1>x then t.scroll(1)v=x;t.setCursorPos(u,v)end end;t.setCursorPos(u,v)end;local function C(t)local D={}function D.print(s)r(s.."\n",t)end;function D.printInline(s)r(s,t)end;function D.clear()t.clear()t.setCursorPos(1,1)end;function D.setCursorPos(u,v)t.setCursorPos(u,v)end;function D.getCursorPos()return t.getCursorPos()end;function D.getSize()return t.getSize()end;function D.setBackgroundColor(E)t.setBackgroundColor(p[E])end;function D.setTextColor(E)t.setTextColor(p[E])end;function D.getBackgroundColor()return q[t.getBackgroundColor()]end;function D.getTextColor()return q[t.getTextColor()]end;return D end;a.tty.register("tty0",C(c))for m,g in ipairs(j())do local F=f(g)if F=="monitor"then local G=o(g)G.setTextScale(0.5)a.tty.register(g,C(G))end end
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
function string.hasSuffix(a,b)return string.sub(a,#b+1)==b end;function string.hasPrefix(a,c)return string.sub(a,1,#c)==c end;function string.getSuffix(a,c)return string.sub(a,#c+1)end;function string.getPrefix(a,b)return string.sub(a,1,#b)end;function string.join(a,...)return table.concat(table.pack(a,...))end;function string.delim(a,...)return table.concat(table.pack(...),a)end;function string.split(a,d,e)assert(#d==1,"only delim len 1 supported for now")e=(e or 0)-1;local f={}local g=""for h=1,#a do local i=string.sub(a,h,h)if#f~=e and i==d then table.insert(f,g)g=""else g=g..i end end;table.insert(f,g)return f end;function string.replace(a,j,k)local f=""local l=1;local h=1;while h<#a do if string.sub(a,h,h+#j-1)==j then f=f..string.sub(a,l,h-1)..k;h=h+#j;l=h end;h=h+1 end;return f..string.sub(a,l)end;function table.deepcopy(m,n)n=n or{}if type(m)~='table'then return m elseif n[m]then return n[m]end;local o={}n[m]=o;for p,q in next,m,nil do local r=table.deepcopy(p,n)local s=table.deepcopy(q,n)o[r]=s end;return o end;function table.hasKey(t,u)for h,q in pairs(t)do if h==u then return true end end;return false end;function table.hasVal(t,u)for h,q in pairs(t)do if q==u then return true end end;return false end;function table.proxy(v)local w=setmetatable({},{__mode="k"})local function x(y)if type(y)~="table"then return y end;if w[y]then return w[y]end;local z={}w[y]=z;local A;A={__index=function(B,p)local C=y[p]if type(C)=="table"then return x(C)else return C end end,__newindex=function()error("Attempt to modify table proxy",2)end,__pairs=function()return function(B,p)local D,E=next(y,p)if type(E)=="table"then E=x(E)end;return D,E end,nil,nil end,__ipairs=function()local h=0;local F=#y;return function()h=h+1;if h<=F then local q=y[h]if type(q)=="table"then q=x(q)end;return h,q end end end,__metatable=false}setmetatable(z,A)return z end;return x(v)end;local function G(table)local H="{"for h,q in pairs(table)do local I=true;if type(h)=="string"then H=H.."[\""..h.."\"]="elseif type(h)=="number"then H=H.."["..tostring(h).."]="end;if type(q)=="table"then if q==table then H=string.sub(H,1,#H-(#h+1))I=false else H=H..G(q)end elseif type(q)=="string"then H=H.."[=["..q.."]=]"elseif type(q)=="number"then H=H..tostring(q)elseif type(q)=="boolean"then if q==true then H=H.."true"else H=H.."false"end elseif type(q)=="function"then H=H..tostring(q)else error("serialization of type \""..type(q).."\" is not supported")end;if I then H=H..","end end;if#table>0 or string.sub(H,#H,#H)==","then H=string.sub(H,1,#H-1)end;H=H.."}"return H end;local J=type;local K=getmetatable;function type(L,M)if M then return J(L)end;if J(L)~="table"then return J(L)else if J(K(L))=="table"then local N=K(L)if N.__type then return N.__type end else return"table"end end end;function getmetatable(L)if J(L)~="table"then return end;if J(K(L))=="table"then if K(L).__isuserdata then if J(K(L).__usermeta)=="function"then return K(L).__usermeta()else return K(L).__usermeta end else return K(L)end else return K(L)end end;function isEqualToAny(O,...)local P={...}for h=0,#P do if O==P[h]then return true end end;return false end;function isEqualToAll(O,...)local P={...}for h=0,#P do if O~=P[h]then return false end end;return true end;function table.keys(y)local O={}for F in pairs(y)do table.insert(O,F)end;return O end;function table.values(y)local O={}for B,F in pairs(y)do table.insert(O,F)end;return O end;function table.indexOf(y,C)for h,q in ipairs(y)do if q==C then return h end end;return-1 end;syscall=setmetatable({},{__index=function(self,Q)return function(...)local R=table.pack(coroutine.yield("syscall",Q,...))if R[1]then return table.unpack(R,2,R.n)else error(R[2],2)end end end})table.serialize=G
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
local a=...local b={}b.mounts={["$"]="/"}local c=a.disks;local function d(e)local f={}for g in e:gmatch("[^/]+")do if g==".."then if#f>0 then table.remove(f)end elseif g~="."and g~=""then table.insert(f,g)end end;return"/"..table.concat(f,"/")..(e:sub(-1)=="/"and"/"or"")end;local function h(e)local i=a.currentTask;local j=i.cwd or"/"if e:sub(1,1)~="/"then e=j..e end;e=d(e)local k="/"local l="$"for m,n in pairs(b.mounts)do if e:sub(1,#n)==n and#n>#k then k=n;l=m end end;local o=e:sub(#k+1)return c[l],o end;local function p(q,r,s,e)return{disk=q,handle=r,mode=s,path=e,refcount=1}end;local function t(i)local u=0;while i.fd[u]do u=u+1 end;return u end;local function t(i)local v=0;for w in pairs(i.fd)do v=v+1 end;if v>=a.config.maxFilesPerTask then error("EMFILE")end;local u=0;while i.fd[u]do u=u+1 end;return u end;local function x()local y=0;for w,i in pairs(a.tasks or{})do for w in pairs(i.fd)do y=y+1 end end;if y>=a.config.maxOpenFiles then error("ENFILE")end end;function b.open(e,s)local i=a.currentTask;x()local q,o=h(e)if not q then error("No disk mounted for path '"..e.."'")end;local r=q:open(o,s)if not r then return nil end;local z=p(q.address,r,s,e)local u=t(i)i.fd[u]=z;return u end;function b.close(u)local i=a.currentTask;local z=i.fd[u]if not z then error("EBADF")end;i.fd[u]=nil;z.refcount=z.refcount-1;if z.refcount==0 then z.handle.close()end;return true end;function b.read(u,v)local z=a.currentTask.fd[u]if not z then error("EBADF")end;if not z.mode:find("r")then error("File not open for reading")end;return z.handle.read(v)end;function b.write(u,A)local z=a.currentTask.fd[u]if not z then error("EBADF")end;if not z.mode:find("w")then error("File not open for writing")end;return z.handle.write(A)end;function b.whereis(u)local z=a.currentTask.fd[u]if not z then error("EBADF")end;return z.path end;function b.mkdir(e)local q,o=h(e)if not q then error("No disk mounted")end;return q:makeDirectory(o)end;function b.remove(e)local q,o=h(e)if not q then error("No disk mounted")end;return q:remove(o)end;function b.attributes(e)if type(e)=="number"then local z=a.currentTask.fd[e]if not z then error("EBADF")end;return c[z.disk]:attributes(z.path)end;local q,o=h(e)if not q then error("No disk mounted")end;return q:attributes(o)end;function b.list(e)local q,o=h(e)if not q then error("No disk mounted")end;return q:list(o)end;function b.exists(e)local q,o=h(e)if not q then return false end;return q:directoryExists(o)or q:fileExists(o)end;function b.type(e)if type(e)=="number"then local z=a.currentTask.fd[e]if not z then error("EBADF")end;return c[z.disk]:type(z.path)end;local q,o=h(e)if not q then error("No disk mounted")end;return q:type(o)end;function b.getcwd()return a.currentTask.cwd end;function b.setcwd(e)if e:sub(-1)~="/"then e=e.."/"end;if e:sub(1,1)~="/"then e="/"..e end;a.currentTask.cwd=d(e)end;function b.mount(B,e)if a.uid~=0 then error("Permission denied")end;if not c[B]then error("Unknown disk '"..B.."'")end;if e:sub(-1)~="/"then e=e.."/"end;for w,n in pairs(b.mounts)do if n==e then error("Mount point already used")end end;b.mounts[B]=e end;function b.unmount(e)if a.uid~=0 then error("Permission denied")end;for m,n in pairs(b.mounts)do if n==e then b.mounts[m]=nil;return true end end;return false end;function b.getMounts()return b.mounts end;function b.virtdisk(C)a.disks[C.address]=C;a.log("Registered virtual disk at "..C.address)end;function b.dup(D)local i=a.currentTask;local z=i.fd[D]if not z then error("EBADF")end;local E=t(i)i.fd[E]=z;z.refcount=z.refcount+1;return E end;function b.dup2(D,E)local i=a.currentTask;local z=i.fd[D]if not z then error("EBADF")end;if D==E then return E end;if i.fd[E]then b.close(E)end;i.fd[E]=z;z.refcount=z.refcount+1;return E end;a.vfs=b;a.syscalls["VFS_open"]=b.open;a.syscalls["VFS_read"]=b.read;a.syscalls["VFS_write"]=b.write;a.syscalls["VFS_close"]=b.close;a.syscalls["VFS_list"]=b.list;a.syscalls["VFS_type"]=b.type;a.syscalls["VFS_attributes"]=b.attributes;a.syscalls["VFS_mkdir"]=b.mkdir;a.syscalls["VFS_remove"]=b.remove;a.syscalls["VFS_exists"]=b.exists;a.syscalls["VFS_mount"]=b.mount;a.syscalls["VFS_unmount"]=b.unmount;a.syscalls["VFS_getcwd"]=b.getcwd;a.syscalls["VFS_setcwd"]=b.setcwd;a.syscalls["VFS_whereis"]=b.whereis;a.syscalls["VFS_dup"]=b.dup;a.syscalls["VFS_dup2"]=b.dup2;a.log("VFS module loaded")
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
local a=...local b={}local c={"/lib/?.lua","/lib/?","/usr/lib/?.lua","/usr/lib/?","/usr/local/lib/?.lua","/usr/local/lib/?","?.lua","?"}function require(d,...)if b[d]then return b[d]end;local e=d:gsub("%.","/")local f={}for g,h in ipairs(c)do local i=string.gsub(h,"%?",e)if i:sub(1,1)~="/"then i=a.currentTask.cwd..i end;if a.vfs.exists(i)then if a.vfs.type(i)=="directory"then i=i.."/init"end;if a.vfs.exists(i)then local j=a.vfs.open(i,"r")local k=a.vfs.read(j,1024*1024*4)a.vfs.close(j)return assert(load(k,i,"t",a._U))(...)else table.insert(f,i)end else table.insert(f,i)end end;error("Module not found: "..d.." (searched paths: "..table.concat(f,", ")..")")end
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
local a=...local b={}local c={}b.address="devfs0000"b.isReadOnly=false;b.spaceUsed=function()return 0 end;b.spaceTotal=function()return 0 end;b.makeDirectory=function()error("Permission denied")end;b.remove=function()error("Permission denied")end;b.setLabel=function()error("Permission denied")end;b.getLabel=function()return"devfs"end;b.attributes=function(d)return{type=b.type(d),isReadOnly=false,size=0,lastModified=0,created=0,Permissions="666",owner="root",group="root"}end;local function e(d)local f=string.split(d,"/")if f[1]==""then table.remove(f,1)end;local g=c;for h,i in ipairs(f)do if g[i]then g=g[i]else return nil end end;return g end;b.type=function(d)local g=e(d)if g then return g.type else return nil end end;b.list=function(d)local g=e(d)if g and g.type=="directory"then local j=table.keys(g)table.remove(j,table.indexOf(j,"type"))return j else error("Not a directory")end end;b.open=function(d,k)local g=e(d)if g and(g.type=="file"or g.type=="character device")then if k=="r"then return{read=g.read,close=function()end}elseif k=="w"then return{write=g.write,close=function()end}else error("Invalid mode")end else error("Not a file"..type(g))end end;local function l(j)return{type="file",read=function()return j end,write=function(m)j=m end}end;local function n()return{type="directory"}end;c["random"]={type="character device",read=function(o)local p=""for h=1,o do p=p..string.char(math.random(0,255))end;return p end,write=function()error("Permission denied")end}c["null"]={type="character device",read=function()return""end,write=function()end}c["zero"]={type="character device",read=function(o)return string.rep("\0",o)end,write=function()error("Permission denied")end}c["rtc"]={type="character device",read=function()return a.computer:time()end,write=function()error("Permission denied")end}c["rtc0"]={type="character device",read=function()return a.computer:time()end,write=function()error("Permission denied")end}c["eeprom"]={type="character device",read=function()return a.computer:getEEPROM()end,write=function(c)if a.uid~=0 then error("Permission denied")end;a.computer:setEEPROM(c)end}local q=a.newFifo()local r=a.newFifo()c["input"]=n()c["input"]["keyboard"]={type="pipe",read=function(o)return q.pop()end,write=function()error("Permission denied")end}c["input"]["mouse"]={type="pipe",read=function(o)return r.pop()end,write=function()error("Permission denied")end}c["pts"]=n()a.devfs={}a.devfs.keyboard=q;a.devfs.mouse=r;a.devfs.proxy=b;a.devfs.data=c;a.vfs.virtdisk(b)
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
local a=...a.processes.keventd=function()while true do local b={a.computer:getMachineEvent()}if b[1]then if b[1]=="key"or b[1]=="keyPressed"or b[1]=="keyReleased"then a.devfs.keyboard.push(b)end end end end
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
local a=...for b,c in ipairs(string.split(a.fstab,"\n"))do if c:sub(1,1)=="U"then local d=""for b=3,#c do if c:sub(b,b)==";"then if b==3 then a.log("Invalid fstab line... Skipping.","WARN")goto e end;d=c:sub(3,b-1)end end;local f=c:sub(#d+4)if d~="$"then a.vfs.mount(d,f)end::e::end end
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
local a=...local b={}local c={}local d={}function d.open(e)if not b[e]then local f=a.newUUID()b[e]={owner=a.currentProcess.pid,handle=f,messages={}}return b[e].handle end;error("Port already opened")end;function d.close(e)if b[e]then if b[e].owner==a.currentProcess.pid then b[e]=nil;return true else error("Cannot close port you do not own")end end;error("Port not opened")end;function d.send(e,g)if b[e]then table.insert(b[e].messages,{from=a.currentProcess.pid,message=g})if c[b[e].owner]then c[b[e].owner](e,g)end;return true end;error("Port not opened")end;function d.receive(e)if b[e]then if#b[e].messages>0 then return table.remove(b[e].messages,1)else return nil end end;error("Port not opened")end;function d.setSignalHandler(h,i)c[h]=i end;function d.clearSignalHandler(h)c[h]=nil end;function d.sendSignal(h,...)coroutine.resumeWithTimeout(coroutine.create(function(...)if c[h]then c[h](...)return true end end),100)return false end;a.ipc=d;a.syscalls["ipc_open"]=d.open;a.syscalls["ipc_close"]=d.close;a.syscalls["ipc_send"]=d.send;a.syscalls["ipc_receive"]=d.receive;a.syscalls["ipc_setSignalHandler"]=d.setSignalHandler;a.syscalls["ipc_clearSignalHandler"]=d.clearSignalHandler;a.syscalls["ipc_sendSignal"]=d.sendSignal;a.log("Loaded IPC module")
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
local a={...}local b=a[1]b._G=_G;b._U=setmetatable({},{__index=b._G,__newindex=function(c,d,e)if b.config.allowGlobalOverwrites or b.allowGlobalOverwrites then rawset(c,d,e)return end;error("Attempt to modify global variable '"..d.."'",2)end,__metatable=false})b.allowGlobalOverwrites=true;b._U._G=b._U;b.allowGlobalOverwrites=false
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
local a=...local b={}a.pam=b;local c={}local function d(e)local f=a.vfs.open(e,"r")if not f then error("Failed to open file: "..e)end;local g=a.vfs.read(f,1024000)a.vfs.close(f)return g end;local h=require("crypto.blake2s")if not h then error("Failed to load blake2s")end;if not a.vfs.exists("/etc/pam.d/secret")then local i=""for j=1,256 do i=i..string.char(math.random(1,255))end;local k=a.vfs.open("/etc/pam.d/secret","w")a.vfs.write(k,i)a.vfs.close(k)end;local l=d("/etc/pam.d/secret")function b.authenticate(m,n)local o=d("/etc/passwd")local p=d("/etc/shadow")local q=string.split(o,"\n")local r=string.split(p,"\n")local s={}local t={}for u,v in ipairs(q)do local w=string.split(v,":")s[w[1]]=w end;for u,v in ipairs(r)do local w=string.split(v,":")t[w[1]]=w end;for x,w in pairs(s)do if x==m then local y=string.split(t[x][2],"$")local z=y[2]local A=h(n..z,l)if A==y[3]then c[m]=a.newUUID()return c[m]else return false end end end end;function b.authToken(m,B)return c[m]==B end
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
local a=...local b={}local c={}local d=2;a.exitMain=false;function c.spawn(e,f,g,h,i,j)local k=d;d=d+1;b[tostring(k)]={coro=coroutine.create(function()local l,m=xpcall(e,debug.traceback,table.unpack(h or{}))if not l then b[tostring(k)].status="Z"b[tostring(k)].exit=tostring(m)else b[tostring(k)].status="Z"b[tostring(k)].exit=m end end),name=f or"task"..tostring(k),envars=g or{},args=h or{},status="R",pid=k,tgid=i or a.currentTask.tgid,user=a.user,uid=a.uid,fd=j or{},exit="",sleep=0,ivs=0,vs=0,children={},parent=a.currentTask,siblings=a.currentTask.children,syscallReturn={},cwd=a.currentTask.cwd,term=a.currentTask.term,timeSlice=0,lastTime=0,totalTime=0,numRuns=0}table.insert(a.currentTask.children,b[tostring(k)])end;function c.sleep(n)a.currentTask.status="S"a.currentTask.sleep=a.computer:time()+n;coroutine.yield()end;a.syscalls["HPV_spawn"]=c.spawn;a.syscalls["HPV_sleep"]=c.sleep;a._G.sleep=function(...)coroutine.yield("syscall","HPV_sleep",...)end;local function o()for p,q in pairs(b)do if q.status=="Z"and not q.reapTime then q.coro=nil;q.ivs=nil;q.vs=nil;q.args=nil;q.envars=nil;q.cwd=nil;q.term=nil;q.numRuns=nil;q.totalTime=nil;q.lastTime=nil;q.timeSlice=nil;q.syscallReturn=nil;q.sleep=nil;for r,s in pairs(q.fd)do a.vfs.close(s)end;q.fd=nil;q.reapTime=a.computer:time()+30000 elseif q.reapTime and a.computer:time()>q.reapTime then for t,u in ipairs(q.children)do u.parent=b["1"]u.siblings=b["1"].children;table.insert(b["1"].children,u)end;for v,w in ipairs(q.siblings)do if w.pid==q.pid then table.remove(q.siblings,v)break end end;b[p]=nil end end end;local x=0.85;local y=0.01;local z=0.0005;local A=0.5;local B=0.08;local C=0.03;local D=0.02;local E=0.5;local F=0.5;local G=0.01;function a.main()while not a.exitMain do local H=0;local I=0;local J=0;local K=0;local L={}for p,q in pairs(b)do if q.status=="S"then if a.computer:time()>=q.sleep then q.status="R"q.sleep=0 end end;if q.status=="R"then a.currentTask=q;a.vfs.cwd=q.cwd;a.user=q.user;a.uid=q.uid;H=H+1;q.timeSlice=math.min(A,math.max(z,G/H^x))local M=a.computer:time()local N;if a.config.preempt then N={coroutine.resumeWithTimeout(q.coro,q.timeSlice,table.unpack(q.syscallReturn))}else N={coroutine.resume(q.coro,table.unpack(q.syscallReturn))}end;local O=a.computer:time()-M;q.lastTime=O;q.totalTime=(q.totalTime or 0)+O;q.numRuns=(q.numRuns or 0)+1;L[#L+1]=O;K=K+O;if O<=z then I=I+1 end;if O>=A then J=J+1 end;if N[1]=="error"then a.log("processHandlerException: "..N[2])q.status="Z"q.exit="processHandlerException: "..N[2]elseif N[1]=="timeout"then q.ivs=q.ivs+1;q.syscallReturn={}elseif N[1]=="success"then q.vs=q.vs+1;if N[2]=="syscall"then if a.syscalls[N[3]]then if a.config.debugSyscalls then a.log("Task "..q.pid.." invoking syscall: "..N[3],"DBUG")end;local P={xpcall(a.syscalls[N[3]],debug.traceback,table.unpack(N,4))}if a.config.debugSyscalls then if not P[1]then a.log("Task "..q.pid.." syscall "..N[3].." failed: "..tostring(P[2]))else a.log("Task "..q.pid.." syscall "..N[3].." completed returning "..tostring(#P-1).." values","DBUG")for v=2,#P do a.log(" retval["..tostring(v-1).."] = "..tostring(P[v]),"DBUG")end end end;if not P[1]then q.syscallReturn={false,P[2]}else q.syscallReturn={true,table.unpack(P,2)}end else q.syscallReturn={false,"Unknown syscall: "..tostring(N[3])}end end end end end;local Q=H>0 and K/H or 0;local R=0;for t,S in ipairs(L)do R=R+(S-Q)^2 end;if H>0 then R=R/H end;if H>0 then local T=E*I/H-F*J/H;local U=y*H^(x-1)/math.max(Q,1e-8)G=G+B*(U-G)+C*T-D*R end;o()end end;a.tasks=b;a.hpv=c
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
local a=...a.tty={}function a.tty.register(b,c)a.tty[b]=c end;function a.tty.print(d)local e=a.currentTask.term;if e and a.tty[e]then a.tty[e].print(d)end end;function a.tty.printInline(d)local e=a.currentTask.term;if e and a.tty[e]then a.tty[e].printInline(d)end end;function a.tty.size()local e=a.currentTask.term;if e and a.tty[e]then return a.tty[e].size()end end;function a.tty.setCursorPos(f,g)local e=a.currentTask.term;if e and a.tty[e]then return a.tty[e].setCursorPos(f,g)end end;function a.tty.getCursorPos()local e=a.currentTask.term;if e and a.tty[e]then return a.tty[e].getCursorPos()end end;function a.tty.clear()local e=a.currentTask.term;if e and a.tty[e]then return a.tty[e].clear()end end;function a.tty.setTextColor(h)local e=a.currentTask.term;if e and a.tty[e]then return a.tty[e].setTextColor(h)end end;function a.tty.setBackgroundColor(h)local e=a.currentTask.term;if e and a.tty[e]then return a.tty[e].setBackgroundColor(h)end end;function a.tty.scroll(i)local e=a.currentTask.term;if e and a.tty[e]then return a.tty[e].scroll(i)end end;function a.tty.getTextColor()local e=a.currentTask.term;if e and a.tty[e]and a.tty[e].getTextColor then return a.tty[e].getTextColor()end end;function a.tty.getBackgroundColor()local e=a.currentTask.term;if e and a.tty[e]and a.tty[e].getBackgroundColor then return a.tty[e].getBackgroundColor()end end;function a.tty.bind(j)if not j then return false,"No TTY ID specified"end;if not a.tty[j]then return false,"TTY "..tostring(j).." not registered"end;a.currentTask.term=j;return true end;function a.tty.unbind()a.currentTask.term=false end;function a.tty.isBound()return a.currentTask.term~=nil end;function a.tty.getBoundTTY()return a.currentTask.term end;a.syscalls["TTY_print"]=a.tty.print;a.syscalls["TTY_printInline"]=a.tty.printInline;a.syscalls["TTY_size"]=a.tty.size;a.syscalls["TTY_setCursorPos"]=a.tty.setCursorPos;a.syscalls["TTY_getCursorPos"]=a.tty.getCursorPos;a.syscalls["TTY_clear"]=a.tty.clear;a.syscalls["TTY_setTextColor"]=a.tty.setTextColor;a.syscalls["TTY_setBackgroundColor"]=a.tty.setBackgroundColor;a.syscalls["TTY_scroll"]=a.tty.scroll;a.syscalls["TTY_getTextColor"]=a.tty.getTextColor;a.syscalls["TTY_getBackgroundColor"]=a.tty.getBackgroundColor;a.syscalls["TTY_bind"]=a.tty.bind;a.syscalls["TTY_unbind"]=a.tty.unbind;a.syscalls["TTY_isBound"]=a.tty.isBound;a.syscalls["TTY_getBoundTTY"]=a.tty.getBoundTTY;a.log("TTY module loaded attempting to register console tty")a.status="init"
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
local a=...a.tty.bind("tty0")
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
local a=...function print(...)coroutine.yield()local b={...}local c=""for d=1,#b do c=c..tostring(b[d]).."\t"end;c=c:sub(1,-2)a.tty.print(c)end;function printf(e,...)coroutine.yield()local c=string.format(e,...)a.tty.print(c)end;function printInline(...)coroutine.yield()local b={...}local c=""for d=1,#b do c=c..tostring(b[d]).."\t"end;c=c:sub(1,-2)a.tty.printInline(c)end
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
local a=...a.log("Loading init system...")a.log("InitPath: "..a.config.initPath)local b=a.vfs.open(a.config.initPath,"r")local c=a.vfs.read(b,1024*1024*4)a.vfs.close(b)local d,e=load(c,"@sysinit")if not d then error("Failed to load init system: "..e)end;a.tasks["1"]={coro=coroutine.create(function()local f,e=xpcall(d,debug.traceback,a)if not f then a.panic("Init system crashed: "..tostring(e))else a.panic("Init system exited: "..tostring(e))end end),name="sysinit",status="R",pid=1,tgid=1,user="root",uid=0,fd={},exit="",sleep=0,ivs=0,vs=0,parent=a.kernelTask,siblings=a.kernelTask.children,children={},syscallReturn={},cwd="/",timeSlice=0,lastTime=0,totalTime=0,numRuns=0}a.log("created init task with PID 1")a.log("Initializing init system...")
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
local sys = {}
|
|
||||||
local fs = require("sys.fs")
|
|
||||||
|
|
||||||
function sys.spawn(func, name, envars, args)
|
|
||||||
return coroutine.yield(0x10, func, name, envars, args)
|
|
||||||
end
|
|
||||||
|
|
||||||
function sys.spawnFromFile(path, name, envars, args)
|
|
||||||
local data = fs.readAllText(path)
|
|
||||||
if not data then
|
|
||||||
error("File not found: "..path,2)
|
|
||||||
end
|
|
||||||
local func, err = load(data, "@"..path)
|
|
||||||
if not func then
|
|
||||||
error("Error loading file "..path..": "..tostring(err),2)
|
|
||||||
end
|
|
||||||
return coroutine.yield(0x10, func, name, envars, args)
|
|
||||||
end
|
|
||||||
|
|
||||||
function sys.spawnAndWait(func, name, envars, args)
|
|
||||||
local task = coroutine.yield(0x10, func, name, envars, args)
|
|
||||||
local oldsignal = sys.getSignalHandler(17)
|
|
||||||
local exit = false
|
|
||||||
sys.setSignalHandler(17, function()
|
|
||||||
local tasks = sys.getChildrenTasks(task)
|
|
||||||
if not tasks[task] then
|
|
||||||
exit = true
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
while not exit do
|
|
||||||
coroutine.yield()
|
|
||||||
end
|
|
||||||
sys.setSignalHandler(17, oldsignal)
|
|
||||||
return task
|
|
||||||
end
|
|
||||||
|
|
||||||
function sys.spawnFromFileAndWait(path, name, envars, args)
|
|
||||||
local data = fs.readAllText(path)
|
|
||||||
if not data then
|
|
||||||
error("File not found: "..path,2)
|
|
||||||
end
|
|
||||||
local func, err = load(data, "@"..path)
|
|
||||||
if not func then
|
|
||||||
error("Error loading file "..path..": "..tostring(err),2)
|
|
||||||
end
|
|
||||||
return sys.spawnAndWait(func, name, envars, args)
|
|
||||||
end
|
|
||||||
|
|
||||||
function sys.exit(code)
|
|
||||||
return coroutine.yield(0x11, code)
|
|
||||||
end
|
|
||||||
|
|
||||||
function sys.getTaskInfo(task)
|
|
||||||
return coroutine.yield(0x12, task)
|
|
||||||
end
|
|
||||||
|
|
||||||
return sys
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
local sys = {}
|
|
||||||
sys.fs = require("sys.fs")
|
|
||||||
sys.hpv = require("sys.hpv")
|
|
||||||
sys.ipc = require("sys.ipc")
|
|
||||||
return sys
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
local ipc = {}
|
|
||||||
|
|
||||||
return ipc
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
local term = {}
|
|
||||||
|
|
||||||
function term.clear()
|
|
||||||
coroutine.yield("VFS_write", 1, "\27C\25")
|
|
||||||
end
|
|
||||||
|
|
||||||
function term.setCursorPos(x, y)
|
|
||||||
coroutine.yield("VFS_write", 1, "\27cs"..tostring(y)..";"..tostring(x).."\25")
|
|
||||||
end
|
|
||||||
|
|
||||||
function term.size()
|
|
||||||
coroutine.yield("VFS_write", 1, "\27ts\25")
|
|
||||||
local ok, data = coroutine.yield("VFS_read", 0, 16) -- read response
|
|
||||||
if not ok then error("Failed to get terminal size") end
|
|
||||||
local x, y = string.match(data, "%R(%d+);(%d+)\25")
|
|
||||||
return tonumber(x), tonumber(y)
|
|
||||||
end
|
|
||||||
|
|
||||||
function term.getCursorPos()
|
|
||||||
coroutine.yield("VFS_write", 1, "\27gc\25")
|
|
||||||
local ok, data = coroutine.yield("VFS_read", 0, 16) -- read response
|
|
||||||
if not ok then error("Failed to get cursor position") end
|
|
||||||
local y, x = string.match(data, "%R(%d+);(%d+)\25")
|
|
||||||
return tonumber(x), tonumber(y)
|
|
||||||
end
|
|
||||||
|
|
||||||
function term.write(data)
|
|
||||||
coroutine.yield("VFS_write", 1, data)
|
|
||||||
end
|
|
||||||
|
|
||||||
function term.setTextColor(color)
|
|
||||||
local ok, err = coroutine.yield("VFS_type", 1)
|
|
||||||
if not ok then error(err) end
|
|
||||||
if ok ~= "tty" then return end
|
|
||||||
coroutine.yield("VFS_write", 1, "\27f"..tostring(color).."\25")
|
|
||||||
end
|
|
||||||
|
|
||||||
function term.setBackgroundColor(color)
|
|
||||||
local ok, err = coroutine.yield("VFS_type", 1)
|
|
||||||
if not ok then error(err) end
|
|
||||||
if ok ~= "tty" then return end
|
|
||||||
coroutine.yield("VFS_write", 1, "\27b"..tostring(color).."\25")
|
|
||||||
end
|
|
||||||
|
|
||||||
function term.isColor()
|
|
||||||
local ok, err = coroutine.yield("VFS_type", 1)
|
|
||||||
if not ok then error(err) end
|
|
||||||
return ok == "tty"
|
|
||||||
end
|
|
||||||
|
|
||||||
function term.scroll(n)
|
|
||||||
coroutine.yield("VFS_write", 1, "\27S"..tostring(n).."\25")
|
|
||||||
end
|
|
||||||
|
|
||||||
function term.setDefault(color, layer)
|
|
||||||
if layer then
|
|
||||||
coroutine.yield("VFS_write", 1, "\27F"..tostring(color).."\25")
|
|
||||||
else
|
|
||||||
coroutine.yield("VFS_write", 1, "\27B"..tostring(color).."\25")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function term.showCursor(show)
|
|
||||||
if show then
|
|
||||||
coroutine.yield("VFS_write", 1, "\27sc\25")
|
|
||||||
else
|
|
||||||
coroutine.yield("VFS_write", 1, "\27hc\25")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return term
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
local kernel=...
|
|
||||||
local fs=require("sys.fs")
|
|
||||||
syscall.TTY_bind("tty0")
|
|
||||||
|
|
||||||
local files = fs.list("/bin/startup")
|
|
||||||
if not files then error("Failed to list /bin/startup") end
|
|
||||||
for i,v in ipairs(files) do
|
|
||||||
if v:sub(-4) == ".lua" then
|
|
||||||
local filepath = "/bin/startup/" .. v
|
|
||||||
kernel.log("Executing startup script: " .. filepath, "INFO")
|
|
||||||
local startupFunc, err = load(fs.readAllText(filepath), "@" .. filepath)
|
|
||||||
if not startupFunc then
|
|
||||||
kernel.log("Error loading startup script '" .. filepath .. "': " .. err, "ERROR")
|
|
||||||
else
|
|
||||||
kernel.hpv.spawn(function()
|
|
||||||
local status, err = pcall(startupFunc)
|
|
||||||
if not status then
|
|
||||||
kernel.log("Error executing startup script '" .. filepath .. "': " .. err, "ERROR")
|
|
||||||
else
|
|
||||||
kernel.log("Successfully executed startup script: " .. filepath, "INFO")
|
|
||||||
end
|
|
||||||
end, "startup:" .. v)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function serialize(table, seen)
|
|
||||||
seen = seen or {}
|
|
||||||
if seen[tostring(table)] then
|
|
||||||
return "\"<circular reference>\""
|
|
||||||
end
|
|
||||||
seen[tostring(table)] = true
|
|
||||||
local output = "{"
|
|
||||||
for i,v in pairs(table) do
|
|
||||||
local coma=true
|
|
||||||
if type(i) == "string" then
|
|
||||||
output=output.."[\""..i.."\"]="
|
|
||||||
elseif type(i) == "number" then
|
|
||||||
output=output.."["..tostring(i).."]="
|
|
||||||
end
|
|
||||||
if type(v) == "table" then
|
|
||||||
if v == table then
|
|
||||||
output=string.sub(output,1,#output-(#i+1))
|
|
||||||
coma=false
|
|
||||||
else
|
|
||||||
output=output..serialize(v, seen)
|
|
||||||
end
|
|
||||||
elseif type(v) == "string" then
|
|
||||||
output=output.."[=["..v.."]=]"
|
|
||||||
elseif type(v) == "number" then
|
|
||||||
output=output..tostring(v)
|
|
||||||
elseif type(v) == "boolean" then
|
|
||||||
if v == true then
|
|
||||||
output=output.."true"
|
|
||||||
else
|
|
||||||
output=output.."false"
|
|
||||||
end
|
|
||||||
elseif type(v) == "function" then
|
|
||||||
output=output..tostring(v)
|
|
||||||
elseif type(v) == "userdata" then
|
|
||||||
output=output..tostring(v)
|
|
||||||
elseif type(v) == "thread" then
|
|
||||||
output=output..tostring(v)
|
|
||||||
else
|
|
||||||
error("serialization of type \""..type(v).."\" is not supported")
|
|
||||||
end
|
|
||||||
if coma then
|
|
||||||
output=output..","
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if #table>0 or string.sub(output,#output,#output) == "," then
|
|
||||||
output=string.sub(output,1,#output-1)
|
|
||||||
end
|
|
||||||
output=output.."}"
|
|
||||||
return output
|
|
||||||
end
|
|
||||||
|
|
||||||
while true do
|
|
||||||
--kernel.log(serialize(kernel.tasks))
|
|
||||||
kernel.saveLog()
|
|
||||||
sleep(1000)
|
|
||||||
end
|
|
||||||
20
Makefile
Normal file
20
Makefile
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
PYTHON := python3
|
||||||
|
ARCH_FLAG := $(if $(ARCH),--arch $(ARCH),)
|
||||||
|
MODE_FLAG := $(if $(DEV),--dev,--release)
|
||||||
|
|
||||||
|
.PHONY: build build-mini build-test build-mini-test clean
|
||||||
|
|
||||||
|
build:
|
||||||
|
$(PYTHON) build.py build $(ARCH_FLAG) $(MODE_FLAG)
|
||||||
|
|
||||||
|
build-mini:
|
||||||
|
$(PYTHON) build.py build-mini $(ARCH_FLAG) $(MODE_FLAG)
|
||||||
|
|
||||||
|
build-test:
|
||||||
|
$(PYTHON) build.py build-test $(ARCH_FLAG) $(MODE_FLAG)
|
||||||
|
|
||||||
|
build-mini-test:
|
||||||
|
$(PYTHON) build.py build-mini-test $(ARCH_FLAG) $(MODE_FLAG)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(PYTHON) build.py clean
|
||||||
52
README.md
52
README.md
@@ -1,3 +1,53 @@
|
|||||||
|
[](https://pinestore.cc/projects/225/hyperionos)
|
||||||
# HyperionOS
|
# HyperionOS
|
||||||
|
|
||||||
WIP
|
HyperionOS is a modular, hybrid kernel operating system written entirely in Lua. It features a custom task scheduler, virtual filesystem, syscall interface, and separates core functionality from user-space services.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
See `building.md`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Functionality is split into kernel modules (`.kmod`)
|
||||||
|
- Task-based lightweight thread/task preemptive scheduler with process isolation and IPC support
|
||||||
|
- Virtual filesystem unified interface for disk, RAM, and virtual filesystems
|
||||||
|
- TTY & Shell
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Kernel Modules
|
||||||
|
|
||||||
|
Modules are loaded in priority order from `/lib/modules/`.
|
||||||
|
|
||||||
|
You can add your own `.kmod` files to extend kernel functionality without modifying the core.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Debugging & Logging
|
||||||
|
|
||||||
|
The kernel logs to `/var/log/syslog.log` during runtime.
|
||||||
|
you can add to it by doing `syscall.log(text, tag, color)`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Contributions are welcome, though please follow these guidelines:
|
||||||
|
|
||||||
|
1. No AI-generated kernel code, keep the core human written.
|
||||||
|
2. Modularize, new features should go into kernel modules where possible.
|
||||||
|
3. Document, update comments and docs when adding/changing functionality.
|
||||||
|
4. Test, ensure your changes don’t break existing functionality.
|
||||||
|
|
||||||
|
Add your name to `contributors.md` when your PR is merged.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This project is licensed under the MIT License. See the LICENSE file for details.
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"Name": "Hyperion bash",
|
|
||||||
"Version": "1.0.0",
|
|
||||||
"Publishers": ["HyperionOS Dev Team"],
|
|
||||||
"Description": "basic bash shell",
|
|
||||||
"Dependencies": [
|
|
||||||
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-core-v1.0.0.pkg"
|
|
||||||
],
|
|
||||||
"Tar": "https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-bash-v1.0.0.tar"
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
print(".. *. ..")
|
|
||||||
print(" *= +@* +* ")
|
|
||||||
print(" .@#. -@@@= :#@. ")
|
|
||||||
print(" =@@+ *@@@# +@@= ")
|
|
||||||
print(" %@@%: *@@@# -%@@% ")
|
|
||||||
print(" :@@@@+ *@@@# .*@@@@: ")
|
|
||||||
print(" :*@@@%- *@@@# -@@@@*: ")
|
|
||||||
print(" =%@@#. *@@@# .#@@%= ")
|
|
||||||
print(" :=. :*@@= *@@@# =@@+: .=: ")
|
|
||||||
print(" %@#=..*# +@@@# #*..=#@# ")
|
|
||||||
print(" .@@@@+=# .%@%: #=+@@@@. ")
|
|
||||||
print(" .....=# -@= *+...:. ")
|
|
||||||
print(" -*%*-@= - =@-*%*- ")
|
|
||||||
print(" -@*. -@%. :%@- :*@- ")
|
|
||||||
print(" .#@#@* ")
|
|
||||||
print(" -#- ")
|
|
||||||
print(" ")
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"Name": "Hyperion core",
|
|
||||||
"Version": "1.0.0",
|
|
||||||
"Publishers": ["HyperionOS Dev Team"],
|
|
||||||
"Description": "Core system files and librarys for HyperionOS",
|
|
||||||
"Dependencies": [
|
|
||||||
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-kernel-v1.0.0.pkg"
|
|
||||||
],
|
|
||||||
"Tar": "https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-core-v1.0.0.tar"
|
|
||||||
}
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
-- blake2s.lua
|
|
||||||
-- Pure Lua 5.2, 32-bit only, supports keyed hashing
|
|
||||||
|
|
||||||
local bit32 = require("bit32")
|
|
||||||
local band, bor, bxor = bit32.band, bit32.bor, bit32.bxor
|
|
||||||
local rshift, lshift = bit32.rshift, bit32.lshift
|
|
||||||
|
|
||||||
local MOD32 = 2^32
|
|
||||||
|
|
||||||
local function rotr(x, n)
|
|
||||||
return bor(rshift(x, n), lshift(x, 32 - n))
|
|
||||||
end
|
|
||||||
|
|
||||||
local IV = {
|
|
||||||
0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
|
|
||||||
0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
|
|
||||||
}
|
|
||||||
|
|
||||||
local SIGMA = {
|
|
||||||
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15},
|
|
||||||
{14,10,4,8,9,15,13,6,1,12,0,2,11,7,5,3},
|
|
||||||
{11,8,12,0,5,2,15,13,10,14,3,6,7,1,9,4},
|
|
||||||
{7,9,3,1,13,12,11,14,2,6,5,10,4,0,15,8},
|
|
||||||
{9,0,5,7,2,4,10,15,14,1,11,12,6,8,3,13},
|
|
||||||
{2,12,6,10,0,11,8,3,4,13,7,5,15,14,1,9},
|
|
||||||
{12,5,1,15,14,13,4,10,0,7,6,3,9,2,8,11},
|
|
||||||
{13,11,7,14,12,1,3,9,5,0,15,4,8,6,2,10},
|
|
||||||
{6,15,14,9,11,3,0,8,12,2,13,7,1,4,10,5},
|
|
||||||
{10,2,8,4,7,6,1,5,15,11,9,14,3,12,13,0}
|
|
||||||
}
|
|
||||||
|
|
||||||
local function G(v, a, b, c, d, x, y)
|
|
||||||
v[a] = (v[a] + v[b] + x) % MOD32
|
|
||||||
v[d] = rotr(bxor(v[d], v[a]), 16)
|
|
||||||
v[c] = (v[c] + v[d]) % MOD32
|
|
||||||
v[b] = rotr(bxor(v[b], v[c]), 12)
|
|
||||||
v[a] = (v[a] + v[b] + y) % MOD32
|
|
||||||
v[d] = rotr(bxor(v[d], v[a]), 8)
|
|
||||||
v[c] = (v[c] + v[d]) % MOD32
|
|
||||||
v[b] = rotr(bxor(v[b], v[c]), 7)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function compress(h, block, t, last)
|
|
||||||
local v = {}
|
|
||||||
for i = 1, 8 do v[i] = h[i] end
|
|
||||||
for i = 1, 8 do v[i + 8] = IV[i] end
|
|
||||||
|
|
||||||
v[13] = bxor(v[13], t)
|
|
||||||
if last then
|
|
||||||
v[15] = bxor(v[15], 0xFFFFFFFF)
|
|
||||||
end
|
|
||||||
|
|
||||||
local m = {}
|
|
||||||
for i = 0, 15 do
|
|
||||||
local p = i * 4 + 1
|
|
||||||
m[i] =
|
|
||||||
(block:byte(p) or 0) +
|
|
||||||
((block:byte(p + 1) or 0) * 0x100) +
|
|
||||||
((block:byte(p + 2) or 0) * 0x10000) +
|
|
||||||
((block:byte(p + 3) or 0) * 0x1000000)
|
|
||||||
end
|
|
||||||
|
|
||||||
for r = 1, 10 do
|
|
||||||
local s = SIGMA[r]
|
|
||||||
G(v,1,5,9,13, m[s[1]], m[s[2]])
|
|
||||||
G(v,2,6,10,14, m[s[3]], m[s[4]])
|
|
||||||
G(v,3,7,11,15, m[s[5]], m[s[6]])
|
|
||||||
G(v,4,8,12,16, m[s[7]], m[s[8]])
|
|
||||||
G(v,1,6,11,16, m[s[9]], m[s[10]])
|
|
||||||
G(v,2,7,12,13, m[s[11]], m[s[12]])
|
|
||||||
G(v,3,8,9,14, m[s[13]], m[s[14]])
|
|
||||||
G(v,4,5,10,15, m[s[15]], m[s[16]])
|
|
||||||
end
|
|
||||||
|
|
||||||
for i = 1, 8 do
|
|
||||||
h[i] = bxor(h[i], v[i], v[i + 8])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function blake2s(msg, key)
|
|
||||||
key = key or ""
|
|
||||||
|
|
||||||
local h = {}
|
|
||||||
for i = 1, 8 do h[i] = IV[i] end
|
|
||||||
|
|
||||||
local outlen = 32 -- bytes
|
|
||||||
h[1] = bxor(
|
|
||||||
h[1],
|
|
||||||
0x01010000 + lshift(#key, 8) + outlen
|
|
||||||
)
|
|
||||||
|
|
||||||
local t = 0
|
|
||||||
|
|
||||||
if #key > 0 then
|
|
||||||
local block = key .. string.rep("\0", 64 - #key)
|
|
||||||
t = #key
|
|
||||||
compress(h, block, t, false)
|
|
||||||
end
|
|
||||||
|
|
||||||
for i = 1, #msg, 64 do
|
|
||||||
local block = msg:sub(i, i + 63)
|
|
||||||
if #block < 64 then
|
|
||||||
block = block .. string.rep("\0", 64 - #block)
|
|
||||||
end
|
|
||||||
t = t + math.min(64, #msg - i + 1)
|
|
||||||
compress(h, block, t, i + 64 > #msg)
|
|
||||||
end
|
|
||||||
|
|
||||||
local out = ""
|
|
||||||
for i = 1, 8 do
|
|
||||||
out = out .. string.format("%08x", h[i])
|
|
||||||
end
|
|
||||||
return out
|
|
||||||
end
|
|
||||||
|
|
||||||
return blake2s
|
|
||||||
@@ -1,139 +0,0 @@
|
|||||||
local fs={}
|
|
||||||
|
|
||||||
-- "VFS_open" : open
|
|
||||||
-- "VFS_read" : read
|
|
||||||
-- "VFS_write" : write
|
|
||||||
-- "VFS_close" : close
|
|
||||||
|
|
||||||
function fs.open(path, mode)
|
|
||||||
local fd=syscall.VFS_open(path,mode)
|
|
||||||
local ret={
|
|
||||||
close=function()
|
|
||||||
-- close file
|
|
||||||
return syscall.VFS_close(fd)
|
|
||||||
end,
|
|
||||||
flush=function()
|
|
||||||
-- close and reopen file to flush buffers
|
|
||||||
syscall.VFS_close(fd)
|
|
||||||
fd=syscall.VFS_open(path,mode)
|
|
||||||
end
|
|
||||||
}
|
|
||||||
if mode=="r" then
|
|
||||||
ret.read=function(count)
|
|
||||||
local data = syscall.VFS_read(fd,count)
|
|
||||||
return data
|
|
||||||
end
|
|
||||||
ret.readAll=function(chunkSize)
|
|
||||||
local chunks={} -- to store read chunks
|
|
||||||
while true do
|
|
||||||
local chunk=syscall.VFS_read(fd,chunkSize or 65536)
|
|
||||||
if chunk==nil or #chunk==0 then break end
|
|
||||||
table.insert(chunks,chunk)
|
|
||||||
end
|
|
||||||
return table.concat(chunks)
|
|
||||||
end
|
|
||||||
ret.readLine = function(chunkSize)
|
|
||||||
local buffer = {} -- stores leftover data
|
|
||||||
local buffer_str = "" -- concatenated buffer
|
|
||||||
local chunk_size = chunkSize or 65536 -- adjust chunk size for performance
|
|
||||||
local eof = false
|
|
||||||
|
|
||||||
while true do
|
|
||||||
-- Try to find a newline in the current buffer
|
|
||||||
local line_end = buffer_str:find("\n")
|
|
||||||
if line_end then
|
|
||||||
local line = buffer_str:sub(1, line_end - 1)
|
|
||||||
buffer_str = buffer_str:sub(line_end + 1)
|
|
||||||
return line
|
|
||||||
end
|
|
||||||
|
|
||||||
-- If EOF was reached previously and buffer is empty, stop
|
|
||||||
if eof then
|
|
||||||
if buffer_str ~= "" then
|
|
||||||
local last_line = buffer_str
|
|
||||||
buffer_str = ""
|
|
||||||
return last_line
|
|
||||||
else
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Read the next chunk
|
|
||||||
local chunk = syscall.VFS_read(fd, chunk_size)
|
|
||||||
if not chunk or chunk == "" then
|
|
||||||
eof = true
|
|
||||||
else
|
|
||||||
buffer_str = buffer_str .. chunk
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
elseif mode=="w" then
|
|
||||||
ret.write=function(data)
|
|
||||||
-- write data to file
|
|
||||||
return syscall.VFS_write(fd,data)
|
|
||||||
end
|
|
||||||
elseif mode=="a" then
|
|
||||||
ret.write=function(data)
|
|
||||||
-- append data to file
|
|
||||||
return syscall.VFS_write(fd,data)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
error("Invalid mode '"..mode.."'",2)
|
|
||||||
end
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
|
|
||||||
function fs.readAllText(path)
|
|
||||||
local file=fs.open(path,"r")
|
|
||||||
if not file then return false end
|
|
||||||
local content=file.readAll()
|
|
||||||
file.close()
|
|
||||||
return content
|
|
||||||
end
|
|
||||||
|
|
||||||
function fs.writeAllText(path, data)
|
|
||||||
local file=fs.open(path,"w")
|
|
||||||
file.write(data)
|
|
||||||
file.close()
|
|
||||||
end
|
|
||||||
|
|
||||||
function fs.appendAllText(path, data)
|
|
||||||
local file=fs.open(path,"a")
|
|
||||||
if not file then return false end
|
|
||||||
file.write(data)
|
|
||||||
file.close()
|
|
||||||
end
|
|
||||||
|
|
||||||
function fs.mkdir(path)
|
|
||||||
return syscall.VFS_mkdir(path)
|
|
||||||
end
|
|
||||||
|
|
||||||
function fs.remove(path)
|
|
||||||
return syscall.VFS_remove(path)
|
|
||||||
end
|
|
||||||
|
|
||||||
function fs.list(path)
|
|
||||||
return syscall.VFS_list(path)
|
|
||||||
end
|
|
||||||
|
|
||||||
function fs.type(path)
|
|
||||||
return syscall.VFS_type(path)
|
|
||||||
end
|
|
||||||
|
|
||||||
function fs.attributes(path)
|
|
||||||
return syscall.VFS_attributes(path)
|
|
||||||
end
|
|
||||||
|
|
||||||
function fs.exists(path)
|
|
||||||
return syscall.VFS_exists(path)
|
|
||||||
end
|
|
||||||
|
|
||||||
function fs.getcwd()
|
|
||||||
return syscall.VFS_getcwd()
|
|
||||||
end
|
|
||||||
|
|
||||||
function fs.setcwd(path)
|
|
||||||
return syscall.VFS_setcwd(path)
|
|
||||||
end
|
|
||||||
|
|
||||||
return fs
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
local sys = {}
|
|
||||||
local fs = require("sys.fs")
|
|
||||||
|
|
||||||
function sys.spawn(func, name, envars, args)
|
|
||||||
return coroutine.yield(0x10, func, name, envars, args)
|
|
||||||
end
|
|
||||||
|
|
||||||
function sys.spawnFromFile(path, name, envars, args)
|
|
||||||
local data = fs.readAllText(path)
|
|
||||||
if not data then
|
|
||||||
error("File not found: "..path,2)
|
|
||||||
end
|
|
||||||
local func, err = load(data, "@"..path)
|
|
||||||
if not func then
|
|
||||||
error("Error loading file "..path..": "..tostring(err),2)
|
|
||||||
end
|
|
||||||
return coroutine.yield(0x10, func, name, envars, args)
|
|
||||||
end
|
|
||||||
|
|
||||||
function sys.spawnAndWait(func, name, envars, args)
|
|
||||||
local task = coroutine.yield(0x10, func, name, envars, args)
|
|
||||||
local oldsignal = sys.getSignalHandler(17)
|
|
||||||
local exit = false
|
|
||||||
sys.setSignalHandler(17, function()
|
|
||||||
local tasks = sys.getChildrenTasks(task)
|
|
||||||
if not tasks[task] then
|
|
||||||
exit = true
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
while not exit do
|
|
||||||
coroutine.yield()
|
|
||||||
end
|
|
||||||
sys.setSignalHandler(17, oldsignal)
|
|
||||||
return task
|
|
||||||
end
|
|
||||||
|
|
||||||
function sys.spawnFromFileAndWait(path, name, envars, args)
|
|
||||||
local data = fs.readAllText(path)
|
|
||||||
if not data then
|
|
||||||
error("File not found: "..path,2)
|
|
||||||
end
|
|
||||||
local func, err = load(data, "@"..path)
|
|
||||||
if not func then
|
|
||||||
error("Error loading file "..path..": "..tostring(err),2)
|
|
||||||
end
|
|
||||||
return sys.spawnAndWait(func, name, envars, args)
|
|
||||||
end
|
|
||||||
|
|
||||||
function sys.exit(code)
|
|
||||||
return coroutine.yield(0x11, code)
|
|
||||||
end
|
|
||||||
|
|
||||||
function sys.getTaskInfo(task)
|
|
||||||
return coroutine.yield(0x12, task)
|
|
||||||
end
|
|
||||||
|
|
||||||
return sys
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
local sys = {}
|
|
||||||
sys.fs = require("sys.fs")
|
|
||||||
sys.hpv = require("sys.hpv")
|
|
||||||
sys.ipc = require("sys.ipc")
|
|
||||||
return sys
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
local ipc = {}
|
|
||||||
|
|
||||||
return ipc
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
local term = {}
|
|
||||||
|
|
||||||
function term.clear()
|
|
||||||
coroutine.yield("VFS_write", 1, "\27C\25")
|
|
||||||
end
|
|
||||||
|
|
||||||
function term.setCursorPos(x, y)
|
|
||||||
coroutine.yield("VFS_write", 1, "\27cs"..tostring(y)..";"..tostring(x).."\25")
|
|
||||||
end
|
|
||||||
|
|
||||||
function term.size()
|
|
||||||
coroutine.yield("VFS_write", 1, "\27ts\25")
|
|
||||||
local ok, data = coroutine.yield("VFS_read", 0, 16) -- read response
|
|
||||||
if not ok then error("Failed to get terminal size") end
|
|
||||||
local x, y = string.match(data, "%R(%d+);(%d+)\25")
|
|
||||||
return tonumber(x), tonumber(y)
|
|
||||||
end
|
|
||||||
|
|
||||||
function term.getCursorPos()
|
|
||||||
coroutine.yield("VFS_write", 1, "\27gc\25")
|
|
||||||
local ok, data = coroutine.yield("VFS_read", 0, 16) -- read response
|
|
||||||
if not ok then error("Failed to get cursor position") end
|
|
||||||
local y, x = string.match(data, "%R(%d+);(%d+)\25")
|
|
||||||
return tonumber(x), tonumber(y)
|
|
||||||
end
|
|
||||||
|
|
||||||
function term.write(data)
|
|
||||||
coroutine.yield("VFS_write", 1, data)
|
|
||||||
end
|
|
||||||
|
|
||||||
function term.setTextColor(color)
|
|
||||||
local ok, err = coroutine.yield("VFS_type", 1)
|
|
||||||
if not ok then error(err) end
|
|
||||||
if ok ~= "tty" then return end
|
|
||||||
coroutine.yield("VFS_write", 1, "\27f"..tostring(color).."\25")
|
|
||||||
end
|
|
||||||
|
|
||||||
function term.setBackgroundColor(color)
|
|
||||||
local ok, err = coroutine.yield("VFS_type", 1)
|
|
||||||
if not ok then error(err) end
|
|
||||||
if ok ~= "tty" then return end
|
|
||||||
coroutine.yield("VFS_write", 1, "\27b"..tostring(color).."\25")
|
|
||||||
end
|
|
||||||
|
|
||||||
function term.isColor()
|
|
||||||
local ok, err = coroutine.yield("VFS_type", 1)
|
|
||||||
if not ok then error(err) end
|
|
||||||
return ok == "tty"
|
|
||||||
end
|
|
||||||
|
|
||||||
function term.scroll(n)
|
|
||||||
coroutine.yield("VFS_write", 1, "\27S"..tostring(n).."\25")
|
|
||||||
end
|
|
||||||
|
|
||||||
function term.setDefault(color, layer)
|
|
||||||
if layer then
|
|
||||||
coroutine.yield("VFS_write", 1, "\27F"..tostring(color).."\25")
|
|
||||||
else
|
|
||||||
coroutine.yield("VFS_write", 1, "\27B"..tostring(color).."\25")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function term.showCursor(show)
|
|
||||||
if show then
|
|
||||||
coroutine.yield("VFS_write", 1, "\27sc\25")
|
|
||||||
else
|
|
||||||
coroutine.yield("VFS_write", 1, "\27hc\25")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return term
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
local kernel=...
|
|
||||||
local fs=require("sys.fs")
|
|
||||||
syscall.TTY_bind("tty0")
|
|
||||||
|
|
||||||
local files = fs.list("/bin/startup")
|
|
||||||
if not files then error("Failed to list /bin/startup") end
|
|
||||||
for i,v in ipairs(files) do
|
|
||||||
if v:sub(-4) == ".lua" then
|
|
||||||
local filepath = "/bin/startup/" .. v
|
|
||||||
kernel.log("Executing startup script: " .. filepath, "INFO")
|
|
||||||
local startupFunc, err = load(fs.readAllText(filepath), "@" .. filepath)
|
|
||||||
if not startupFunc then
|
|
||||||
kernel.log("Error loading startup script '" .. filepath .. "': " .. err, "ERROR")
|
|
||||||
else
|
|
||||||
kernel.hpv.spawn(function()
|
|
||||||
local status, err = pcall(startupFunc)
|
|
||||||
if not status then
|
|
||||||
kernel.log("Error executing startup script '" .. filepath .. "': " .. err, "ERROR")
|
|
||||||
else
|
|
||||||
kernel.log("Successfully executed startup script: " .. filepath, "INFO")
|
|
||||||
end
|
|
||||||
end, "startup:" .. v)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function serialize(table, seen)
|
|
||||||
seen = seen or {}
|
|
||||||
if seen[tostring(table)] then
|
|
||||||
return "\"<circular reference>\""
|
|
||||||
end
|
|
||||||
seen[tostring(table)] = true
|
|
||||||
local output = "{"
|
|
||||||
for i,v in pairs(table) do
|
|
||||||
local coma=true
|
|
||||||
if type(i) == "string" then
|
|
||||||
output=output.."[\""..i.."\"]="
|
|
||||||
elseif type(i) == "number" then
|
|
||||||
output=output.."["..tostring(i).."]="
|
|
||||||
end
|
|
||||||
if type(v) == "table" then
|
|
||||||
if v == table then
|
|
||||||
output=string.sub(output,1,#output-(#i+1))
|
|
||||||
coma=false
|
|
||||||
else
|
|
||||||
output=output..serialize(v, seen)
|
|
||||||
end
|
|
||||||
elseif type(v) == "string" then
|
|
||||||
output=output.."[=["..v.."]=]"
|
|
||||||
elseif type(v) == "number" then
|
|
||||||
output=output..tostring(v)
|
|
||||||
elseif type(v) == "boolean" then
|
|
||||||
if v == true then
|
|
||||||
output=output.."true"
|
|
||||||
else
|
|
||||||
output=output.."false"
|
|
||||||
end
|
|
||||||
elseif type(v) == "function" then
|
|
||||||
output=output..tostring(v)
|
|
||||||
elseif type(v) == "userdata" then
|
|
||||||
output=output..tostring(v)
|
|
||||||
elseif type(v) == "thread" then
|
|
||||||
output=output..tostring(v)
|
|
||||||
else
|
|
||||||
error("serialization of type \""..type(v).."\" is not supported")
|
|
||||||
end
|
|
||||||
if coma then
|
|
||||||
output=output..","
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if #table>0 or string.sub(output,#output,#output) == "," then
|
|
||||||
output=string.sub(output,1,#output-1)
|
|
||||||
end
|
|
||||||
output=output.."}"
|
|
||||||
return output
|
|
||||||
end
|
|
||||||
|
|
||||||
while true do
|
|
||||||
--kernel.log(serialize(kernel.tasks))
|
|
||||||
kernel.saveLog()
|
|
||||||
sleep(1000)
|
|
||||||
end
|
|
||||||
18
Src/Hyperion-core/lib/colors
Normal file
18
Src/Hyperion-core/lib/colors
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
--:Minify:--
|
||||||
|
return {
|
||||||
|
white=0xFFFFFF,
|
||||||
|
red=0xFF0000,
|
||||||
|
green=0x00FF00,
|
||||||
|
blue=0x0000FF,
|
||||||
|
cyan=0x00FFFF,
|
||||||
|
yellow=0xFFFF00,
|
||||||
|
purple=0xFF00FF,
|
||||||
|
black=0x000000,
|
||||||
|
gray=0x888888,
|
||||||
|
lightgrey=0xBBBBBB,
|
||||||
|
darkgrey=0x444444,
|
||||||
|
orange=0xFF8800,
|
||||||
|
mint=0x00FF88,
|
||||||
|
brown=0xa52a2a,
|
||||||
|
chocolate=0xd2691e
|
||||||
|
}
|
||||||
@@ -1,32 +1,32 @@
|
|||||||
|
--:Minify:--
|
||||||
local fs={}
|
local fs={}
|
||||||
|
|
||||||
-- "VFS_open" : open
|
-- "open" : open
|
||||||
-- "VFS_read" : read
|
-- "read" : read
|
||||||
-- "VFS_write" : write
|
-- "write" : write
|
||||||
-- "VFS_close" : close
|
-- "close" : close
|
||||||
|
|
||||||
function fs.open(path, mode)
|
function fs.open(path, mode)
|
||||||
local fd=syscall.VFS_open(path,mode)
|
local fd=syscall.open(path,mode)
|
||||||
local ret={
|
local ret={
|
||||||
close=function()
|
close=function()
|
||||||
-- close file
|
-- close file
|
||||||
return syscall.VFS_close(fd)
|
return syscall.close(fd)
|
||||||
end,
|
end,
|
||||||
flush=function()
|
flush=function()
|
||||||
-- close and reopen file to flush buffers
|
-- close and reopen file to flush buffers
|
||||||
syscall.VFS_close(fd)
|
syscall.fsync(fd)
|
||||||
fd=syscall.VFS_open(path,mode)
|
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
if mode=="r" then
|
if mode=="r" then
|
||||||
ret.read=function(count)
|
ret.read=function(count)
|
||||||
local data = syscall.VFS_read(fd,count)
|
local data = syscall.read(fd,count)
|
||||||
return data
|
return data
|
||||||
end
|
end
|
||||||
ret.readAll=function(chunkSize)
|
ret.readAll=function(chunkSize)
|
||||||
local chunks={} -- to store read chunks
|
local chunks={} -- to store read chunks
|
||||||
while true do
|
while true do
|
||||||
local chunk=syscall.VFS_read(fd,chunkSize or 65536)
|
local chunk=syscall.read(fd,chunkSize or 65536)
|
||||||
if chunk==nil or #chunk==0 then break end
|
if chunk==nil or #chunk==0 then break end
|
||||||
table.insert(chunks,chunk)
|
table.insert(chunks,chunk)
|
||||||
end
|
end
|
||||||
@@ -59,7 +59,7 @@ function fs.open(path, mode)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Read the next chunk
|
-- Read the next chunk
|
||||||
local chunk = syscall.VFS_read(fd, chunk_size)
|
local chunk = syscall.read(fd, chunk_size)
|
||||||
if not chunk or chunk == "" then
|
if not chunk or chunk == "" then
|
||||||
eof = true
|
eof = true
|
||||||
else
|
else
|
||||||
@@ -70,12 +70,12 @@ function fs.open(path, mode)
|
|||||||
elseif mode=="w" then
|
elseif mode=="w" then
|
||||||
ret.write=function(data)
|
ret.write=function(data)
|
||||||
-- write data to file
|
-- write data to file
|
||||||
return syscall.VFS_write(fd,data)
|
return syscall.write(fd,data)
|
||||||
end
|
end
|
||||||
elseif mode=="a" then
|
elseif mode=="a" then
|
||||||
ret.write=function(data)
|
ret.write=function(data)
|
||||||
-- append data to file
|
-- append data to file
|
||||||
return syscall.VFS_write(fd,data)
|
return syscall.write(fd,data)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
error("Invalid mode '"..mode.."'",2)
|
error("Invalid mode '"..mode.."'",2)
|
||||||
@@ -105,35 +105,39 @@ function fs.appendAllText(path, data)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function fs.mkdir(path)
|
function fs.mkdir(path)
|
||||||
return syscall.VFS_mkdir(path)
|
return syscall.mkdir(path)
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.remove(path)
|
function fs.remove(path)
|
||||||
return syscall.VFS_remove(path)
|
return syscall.remove(path)
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.list(path)
|
function fs.list(path)
|
||||||
return syscall.VFS_list(path)
|
return syscall.listdir(path)
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.type(path)
|
function fs.type(path)
|
||||||
return syscall.VFS_type(path)
|
return syscall.type(path)
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.attributes(path)
|
function fs.stat(path)
|
||||||
return syscall.VFS_attributes(path)
|
return syscall.stat(path)
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.exists(path)
|
function fs.exists(path)
|
||||||
return syscall.VFS_exists(path)
|
return syscall.exists(path)
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.getcwd()
|
function fs.getcwd()
|
||||||
return syscall.VFS_getcwd()
|
return syscall.getcwd()
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.setcwd(path)
|
function fs.chdir(path)
|
||||||
return syscall.VFS_setcwd(path)
|
return syscall.chdir(path)
|
||||||
|
end
|
||||||
|
|
||||||
|
function fs.isDir(path)
|
||||||
|
return syscall.type(path) == "directory"
|
||||||
end
|
end
|
||||||
|
|
||||||
return fs
|
return fs
|
||||||
6
Src/Hyperion-core/lib/io
Normal file
6
Src/Hyperion-core/lib/io
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
local io = {}
|
||||||
|
local fs = require("fs")
|
||||||
|
|
||||||
|
function io.open(path, mode)
|
||||||
|
return fs.open(path, mode)
|
||||||
|
end
|
||||||
344
Src/Hyperion-firmware-ac/boot/ac/boot.lua
Normal file
344
Src/Hyperion-firmware-ac/boot/ac/boot.lua
Normal file
@@ -0,0 +1,344 @@
|
|||||||
|
--:Minify:--
|
||||||
|
local args={...}
|
||||||
|
local bootdrive=args[1]
|
||||||
|
local gpu=components:getFirst("gpu")
|
||||||
|
local screenTextBuffer=nil
|
||||||
|
local cursorX,cursorY=0,0
|
||||||
|
local screenSizeX,screenSizeY=128,25
|
||||||
|
|
||||||
|
|
||||||
|
if gpu then
|
||||||
|
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
|
||||||
387
Src/Hyperion-firmware-ccpc/boot/ccpc/boot.lua
Normal file
387
Src/Hyperion-firmware-ccpc/boot/ccpc/boot.lua
Normal file
@@ -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
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
--:Minify:--
|
--:Minify:--
|
||||||
sleep(1)
|
local BOOT_DRIVE_PATH=({...})[1] or "/$"
|
||||||
local BOOT_DRIVE_PATH="/$"
|
|
||||||
-- UnBIOS by JackMacWindows
|
-- 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
|
-- 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
|
-- To use, just place a `bios.lua` in the root of the drive, and run this program
|
||||||
@@ -16,7 +15,6 @@ local BOOT_DRIVE_PATH="/$"
|
|||||||
-- * `turtle.equip[Left|Right]`
|
-- * `turtle.equip[Left|Right]`
|
||||||
-- Licensed under the MIT license
|
-- Licensed under the MIT license
|
||||||
local args = {...}
|
local args = {...}
|
||||||
if _HOST:find("UnBIOS") then return end
|
|
||||||
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 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 = {}
|
local t = {}
|
||||||
for k in pairs(_G) do if not keptAPIs[k] then table.insert(t, k) end end
|
for k in pairs(_G) do if not keptAPIs[k] then table.insert(t, k) end end
|
||||||
@@ -32,7 +30,6 @@ if _G.commands then _G.commands = _G.commands.native end
|
|||||||
if _G.turtle then _G.turtle.native, _G.turtle.craft = nil 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"}}
|
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
|
for k,v in pairs(delete) do for _,a in ipairs(v) do _G[k][a] = nil end end
|
||||||
_G._HOST = _G._HOST .. " (UnBIOS)"
|
|
||||||
-- Set up TLCO
|
-- Set up TLCO
|
||||||
-- This functions by crashing `rednet.run` by removing `os.pullEventRaw`. Normally
|
-- 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
|
-- this would cause `parallel` to throw an error, but we replace `error` with an
|
||||||
@@ -88,7 +85,7 @@ function _G.term.native()
|
|||||||
local oldshutdown = os.shutdown
|
local oldshutdown = os.shutdown
|
||||||
os.shutdown = function()
|
os.shutdown = function()
|
||||||
os.shutdown = oldshutdown
|
os.shutdown = oldshutdown
|
||||||
return fn(table.unpack(args))
|
return fn(BOOT_DRIVE_PATH)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if debug then
|
if debug then
|
||||||
272
Src/Hyperion-firmware-ccpc/boot/ccpc/initdisks
Normal file
272
Src/Hyperion-firmware-ccpc/boot/ccpc/initdisks
Normal file
@@ -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}
|
||||||
394
Src/Hyperion-firmware-ccpc/lib/modules/ccpc/25_gfx.kmod
Normal file
394
Src/Hyperion-firmware-ccpc/lib/modules/ccpc/25_gfx.kmod
Normal file
@@ -0,0 +1,394 @@
|
|||||||
|
--:Minify:--
|
||||||
|
local kernel = ...
|
||||||
|
local apis = kernel.apis
|
||||||
|
local native = apis.peripheral
|
||||||
|
local sides = {"top", "bottom", "left", "right", "front", "back"}
|
||||||
|
local peripheral={}
|
||||||
|
|
||||||
|
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 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
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
kernel.devfs.data.tty={}
|
||||||
|
local ctrl,alt = false, false
|
||||||
|
|
||||||
|
local function serializeBool(bool)
|
||||||
|
if bool then
|
||||||
|
return "T"
|
||||||
|
else
|
||||||
|
return "F"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function newtty(obj, id, ev)
|
||||||
|
kernel.devfs.data["tty"][id] = function(op, mode)
|
||||||
|
if op=="type" then
|
||||||
|
return "character device"
|
||||||
|
elseif op=="open" then
|
||||||
|
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(content, obj)
|
||||||
|
end,
|
||||||
|
size=function()
|
||||||
|
local s={obj.getSize()}
|
||||||
|
return table.concat(s,";")
|
||||||
|
end,
|
||||||
|
clear=function()
|
||||||
|
obj.clear()
|
||||||
|
obj.setCursorPos(1,1)
|
||||||
|
end,
|
||||||
|
gpos=function()
|
||||||
|
local s={obj.getCursorPos()}
|
||||||
|
return table.concat(s,";")
|
||||||
|
end,
|
||||||
|
spos=function(x,y)
|
||||||
|
return obj.setCursorPos(x,y)
|
||||||
|
end,
|
||||||
|
sfgc=function(c)
|
||||||
|
return obj.setTextColor(colors[c])
|
||||||
|
end,
|
||||||
|
sbgc=function(c)
|
||||||
|
return obj.setBackgroundColor(colors[c])
|
||||||
|
end,
|
||||||
|
gfgc=function()
|
||||||
|
return icolors[obj.getTextColor()]
|
||||||
|
end,
|
||||||
|
gbgc=function()
|
||||||
|
return icolors[obj.getBackgroundColor()]
|
||||||
|
end,
|
||||||
|
gctrl=function()
|
||||||
|
return serializeBool(ctrl)..";"..serializeBool(alt)
|
||||||
|
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
|
||||||
|
|
||||||
|
local fifo = kernel.newFifo()
|
||||||
|
|
||||||
|
kernel.processes.cctmond = function()
|
||||||
|
local timeout = false
|
||||||
|
while true do
|
||||||
|
local event = {kernel.EFI:getMachineEvent()}
|
||||||
|
|
||||||
|
if event[1] then
|
||||||
|
local eventType = event[1]
|
||||||
|
local charOrKey = event[3]
|
||||||
|
|
||||||
|
local ctrlKeyMap = {
|
||||||
|
[apis.keys.a]=1, [apis.keys.b]=2, [apis.keys.c]=3,
|
||||||
|
[apis.keys.d]=4, [apis.keys.e]=5, [apis.keys.f]=6,
|
||||||
|
[apis.keys.g]=7, [apis.keys.h]=8, [apis.keys.i]=9,
|
||||||
|
[apis.keys.j]=10, [apis.keys.k]=11, [apis.keys.l]=12,
|
||||||
|
[apis.keys.m]=13, [apis.keys.n]=14, [apis.keys.o]=15,
|
||||||
|
[apis.keys.p]=16, [apis.keys.q]=17, [apis.keys.r]=18,
|
||||||
|
[apis.keys.s]=19, [apis.keys.t]=20, [apis.keys.u]=21,
|
||||||
|
[apis.keys.v]=22, [apis.keys.w]=23, [apis.keys.x]=24,
|
||||||
|
[apis.keys.y]=25, [apis.keys.z]=26,
|
||||||
|
}
|
||||||
|
|
||||||
|
if eventType == "keyPressed" then
|
||||||
|
if charOrKey == apis.keys.leftCtrl or charOrKey == apis.keys.rightCtrl then
|
||||||
|
ctrl = true
|
||||||
|
elseif charOrKey == apis.keys.leftAlt or charOrKey == apis.keys.rightAlt then
|
||||||
|
alt = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if ctrl then
|
||||||
|
local ctrlByte = ctrlKeyMap[charOrKey]
|
||||||
|
if ctrlByte then
|
||||||
|
if ctrlByte == 3 then
|
||||||
|
for _, task in ipairs(syscall.getTasks()) do
|
||||||
|
syscall.sigsend(task, 1)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
fifo.push(string.char(ctrlByte))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local specialKeyMap = {
|
||||||
|
[apis.keys.up] = "[A",
|
||||||
|
[apis.keys.down] = "[B",
|
||||||
|
[apis.keys.right] = "[C",
|
||||||
|
[apis.keys.left] = "[D",
|
||||||
|
[apis.keys.home] = "[H",
|
||||||
|
[apis.keys["end"]] = "[F",
|
||||||
|
[apis.keys.pageUp] = "[5~",
|
||||||
|
[apis.keys.pageDown] = "[6~",
|
||||||
|
[apis.keys.delete] = "[3~",
|
||||||
|
}
|
||||||
|
local special = specialKeyMap[charOrKey]
|
||||||
|
if special then fifo.push(special) end
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif eventType == "keyReleased" then
|
||||||
|
if charOrKey == apis.keys.leftCtrl or charOrKey == apis.keys.rightCtrl then
|
||||||
|
ctrl = false
|
||||||
|
elseif charOrKey == apis.keys.leftAlt or charOrKey == apis.keys.rightAlt then
|
||||||
|
alt = false
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif eventType == "keyTyped" then
|
||||||
|
if charOrKey then fifo.push(charOrKey) end
|
||||||
|
end
|
||||||
|
|
||||||
|
timeout = false
|
||||||
|
else
|
||||||
|
timeout = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if timeout then
|
||||||
|
sleep(0.05)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
newtty(apis.term, "1", fifo.pop)
|
||||||
|
|
||||||
|
for i,v in ipairs({peripheral.find("monitor")}) do
|
||||||
|
v.setTextScale(.5)
|
||||||
|
v.write("Initializing...")
|
||||||
|
newtty(v,tostring(i+1),function () end)
|
||||||
|
end
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"Name": "Hyperion CCT Firmware",
|
|
||||||
"Version": "1.0.0",
|
|
||||||
"Publishers": ["HyperionOS Dev Team"],
|
|
||||||
"Description": "The ComputerCraftTweaked firmware package for HyperionOS.",
|
|
||||||
"Dependencies": [
|
|
||||||
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-kernel-v1.0.0.pkg"
|
|
||||||
],
|
|
||||||
"Tar": "https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-firmware-cct-v1.0.0.tar",
|
|
||||||
"BuildCommand": "sudo cp boot/cct/eeprom /dev/eeprom"
|
|
||||||
}
|
|
||||||
@@ -1,312 +0,0 @@
|
|||||||
--:Minify:--
|
|
||||||
local BOOT_DRIVE_PATH="/$"
|
|
||||||
local term = term
|
|
||||||
local os = os
|
|
||||||
-- Function to write text to the terminal with special character handling
|
|
||||||
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
|
|
||||||
|
|
||||||
-- Handle wrapping if we go past right edge
|
|
||||||
if x > w then
|
|
||||||
x = 1
|
|
||||||
y = y + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Handle scrolling if we go past bottom
|
|
||||||
if y-1 > h then
|
|
||||||
term.scroll(1)
|
|
||||||
y = h
|
|
||||||
term.setCursorPos(x, y)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
term.setCursorPos(x, y)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Function to display critical errors and halt the system
|
|
||||||
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
|
|
||||||
|
|
||||||
-- Wrap all in xpcall to catch errors
|
|
||||||
local ok, err = xpcall(function()
|
|
||||||
local apis={}
|
|
||||||
|
|
||||||
-- List of standard Lua globals
|
|
||||||
local lua = {
|
|
||||||
coroutine = true,
|
|
||||||
debug = true,
|
|
||||||
_HOST = true,
|
|
||||||
_VERSION = true,
|
|
||||||
assert = true,
|
|
||||||
collectgarbage = true,
|
|
||||||
error = true,
|
|
||||||
gcinfo = true,
|
|
||||||
getfenv = true,
|
|
||||||
getmetatable = true,
|
|
||||||
ipairs = true,
|
|
||||||
__inext = true,
|
|
||||||
load = true,
|
|
||||||
math = true,
|
|
||||||
next = true,
|
|
||||||
pairs = true,
|
|
||||||
pcall = true,
|
|
||||||
rawequal = true,
|
|
||||||
rawget = true,
|
|
||||||
rawlen = true,
|
|
||||||
rawset = true,
|
|
||||||
select = true,
|
|
||||||
setfenv = true,
|
|
||||||
setmetatable = true,
|
|
||||||
string = true,
|
|
||||||
table = true,
|
|
||||||
tonumber = true,
|
|
||||||
tostring = true,
|
|
||||||
type = true,
|
|
||||||
xpcall = true,
|
|
||||||
_G=true
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Move all non-Lua standard library globals into the apis table
|
|
||||||
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
|
|
||||||
|
|
||||||
function sleep(time)
|
|
||||||
local stoptime = apis.os.clock() + (time)
|
|
||||||
while stoptime > apis.os.clock() do end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Set up terminal default colors
|
|
||||||
apis.term.setPaletteColor(0x1, 0x000000) -- #000000
|
|
||||||
apis.term.setPaletteColor(0x2, 0xFFFFFF) -- #FFFFFF
|
|
||||||
apis.term.setPaletteColor(0x4, 0xFF0000) -- #FF0000
|
|
||||||
apis.term.setPaletteColor(0x8, 0x00FF00) -- #00FF00
|
|
||||||
apis.term.setPaletteColor(0x10, 0x0000FF) -- #0000FF
|
|
||||||
apis.term.setPaletteColor(0x20, 0x00FFFF) -- #00FFFF
|
|
||||||
apis.term.setPaletteColor(0x40, 0xFF00FF) -- #FF00FF
|
|
||||||
apis.term.setPaletteColor(0x80, 0xFFFF00) -- #FFFF00
|
|
||||||
apis.term.setPaletteColor(0x100, 0xFF6D00) -- #FF6D00
|
|
||||||
apis.term.setPaletteColor(0x200, 0x6DFF55) -- #6DFF55
|
|
||||||
apis.term.setPaletteColor(0x400, 0x24FFFF) -- #24FFFF
|
|
||||||
apis.term.setPaletteColor(0x800, 0x924900) -- #924900
|
|
||||||
apis.term.setPaletteColor(0x1000, 0x6D6D55) -- #6D6D55
|
|
||||||
apis.term.setPaletteColor(0x2000, 0xDBDBAA) -- #DBDBAA
|
|
||||||
apis.term.setPaletteColor(0x4000, 0x6D00FF) -- #6D00FF
|
|
||||||
apis.term.setPaletteColor(0x8000, 0xB6FF00) -- #B6FF00
|
|
||||||
|
|
||||||
-- Wrapper to read files
|
|
||||||
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
|
|
||||||
|
|
||||||
-- Load kernel first if it fails, we can't continue so we display an error
|
|
||||||
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
|
|
||||||
|
|
||||||
-- Set up event queue
|
|
||||||
local eventQueue = {}
|
|
||||||
local lkeys={}
|
|
||||||
lkeys[apis.keys.enter]="\n"
|
|
||||||
lkeys[apis.keys.backspace]="\b"
|
|
||||||
lkeys[apis.keys.tab]="\t"
|
|
||||||
|
|
||||||
-- Function to queue events
|
|
||||||
local function queueEvent(event, ...)
|
|
||||||
table.insert(eventQueue, {event, ...})
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Set up computer api
|
|
||||||
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()
|
|
||||||
if #eventQueue > 0 then
|
|
||||||
return table.unpack(table.remove(eventQueue, 1))
|
|
||||||
else
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
getEEPROM = function()
|
|
||||||
return getFile("/startup.lua")
|
|
||||||
end,
|
|
||||||
setEEPROM = function(_,text)
|
|
||||||
local h = apis.fs.open("/startup.lua", "w")
|
|
||||||
h.write(text)
|
|
||||||
h.close()
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Set up terminal colors
|
|
||||||
local icolors={
|
|
||||||
[0x1] =0, -- #000000
|
|
||||||
[0x2] =1, -- #FFFFFF
|
|
||||||
[0x4] =2, -- #FF0000
|
|
||||||
[0x8] =3, -- #00FF00
|
|
||||||
[0x10] =4, -- #0000FF
|
|
||||||
[0x20] =5, -- #00FFFF
|
|
||||||
[0x40] =6, -- #FF00FF
|
|
||||||
[0x80] =7, -- #FFFF00
|
|
||||||
[0x100] =8, -- #FF6D00
|
|
||||||
[0x200] =9, -- #6DFF55
|
|
||||||
[0x400] =10, -- #24FFFF
|
|
||||||
[0x800] =11, -- #924900
|
|
||||||
[0x1000] =12, -- #6D6D55
|
|
||||||
[0x2000] =13, -- #DBDBAA
|
|
||||||
[0x4000] =14, -- #6D00FF
|
|
||||||
[0x8000] =15 -- #B6FF00
|
|
||||||
}
|
|
||||||
|
|
||||||
local colors={
|
|
||||||
[0]=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(0x1)
|
|
||||||
apis.term.setTextColor(0x1000)
|
|
||||||
apis.term.clear()
|
|
||||||
apis.term.setCursorPos(1, 1)
|
|
||||||
|
|
||||||
-- Make the kernel coroutine so we can hook its execution
|
|
||||||
local kernelCoro = coroutine.create(function()
|
|
||||||
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)
|
|
||||||
|
|
||||||
-- Diffine a coroutine.resumeWithTimeout function to avoid hanging the system, time is in milliseconds
|
|
||||||
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")
|
|
||||||
|
|
||||||
-- Main loop to run the kernel coroutine
|
|
||||||
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] == "char" then
|
|
||||||
queueEvent("keyTyped", 1, event[2])
|
|
||||||
elseif event[1] == "key" then
|
|
||||||
queueEvent("keyPressed", 1, event[2])
|
|
||||||
if lkeys[event[2]] then
|
|
||||||
queueEvent("keyTyped", 1, lkeys[event[2]])
|
|
||||||
end
|
|
||||||
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] == "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,192 +0,0 @@
|
|||||||
--:Minify:--
|
|
||||||
local apis = ({...})[1]
|
|
||||||
local BOOT_DRIVE_PATH="/$"
|
|
||||||
local fs = apis.fs
|
|
||||||
local native = apis.peripheral
|
|
||||||
local peripheral = {}
|
|
||||||
local sides = {"top", "bottom", "left", "right", "front", "back"}
|
|
||||||
|
|
||||||
function peripheral.getType(name)
|
|
||||||
if native.isPresent(name) then
|
|
||||||
return native.getType(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, "getTypeRemote", name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function peripheral.getNames()
|
|
||||||
local names = {}
|
|
||||||
for n = 1, #sides do
|
|
||||||
local side = sides[n]
|
|
||||||
if native.isPresent(side) then
|
|
||||||
table.insert(names, side)
|
|
||||||
end
|
|
||||||
if native.hasType(side, "peripheral_hub") then
|
|
||||||
local hubSides = native.call(side, "getConnectedSides")
|
|
||||||
for _, hubSide in ipairs(hubSides) do
|
|
||||||
table.insert(names, hubSide)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return names
|
|
||||||
end
|
|
||||||
|
|
||||||
---------------------------------------------------------
|
|
||||||
-- STORAGE
|
|
||||||
---------------------------------------------------------
|
|
||||||
local disks = {} -- real disks
|
|
||||||
local internal = {} -- "$" disk
|
|
||||||
|
|
||||||
---------------------------------------------------------
|
|
||||||
-- HELPERS
|
|
||||||
---------------------------------------------------------
|
|
||||||
local function norm(path)
|
|
||||||
if not path or path == "" then return "/" end
|
|
||||||
return fs.combine("/", path)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Creates a disk object given a base path
|
|
||||||
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 DISK "$" (mapped to "/")
|
|
||||||
---------------------------------------------------------
|
|
||||||
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")
|
|
||||||
local label = h.readAll()
|
|
||||||
h.close()
|
|
||||||
return label
|
|
||||||
end
|
|
||||||
})
|
|
||||||
|
|
||||||
---------------------------------------------------------
|
|
||||||
-- SCAN REAL DISK PERIPHERALS
|
|
||||||
---------------------------------------------------------
|
|
||||||
local function refresh()
|
|
||||||
-- remove disks that no longer exist
|
|
||||||
for id, _ in pairs(disks) do
|
|
||||||
if not peripheral.getType(id) then
|
|
||||||
disks[id] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- detect new disks
|
|
||||||
for _, name in ipairs(peripheral.getNames()) do
|
|
||||||
if peripheral.getType(name) == "disk" then
|
|
||||||
if not disks[name] then
|
|
||||||
local mount = disk.getMountPath(name)
|
|
||||||
if mount then
|
|
||||||
disks[name] = createDisk(name, mount, false, disk)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
---------------------------------------------------------
|
|
||||||
-- ITERATOR
|
|
||||||
---------------------------------------------------------
|
|
||||||
local function iter()
|
|
||||||
refresh()
|
|
||||||
-- first internal
|
|
||||||
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
|
|
||||||
|
|
||||||
---------------------------------------------------------
|
|
||||||
-- MODULE RETURN
|
|
||||||
---------------------------------------------------------
|
|
||||||
return {
|
|
||||||
refresh = refresh,
|
|
||||||
list = iter
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
local args={...}
|
|
||||||
local kernel=args[1]
|
|
||||||
local driver={}
|
|
||||||
|
|
||||||
driver.name="CCT Term Module"
|
|
||||||
driver.version="0.1.0"
|
|
||||||
driver.type="gpio"
|
|
||||||
driver.description="CCT redstone Module Kernel Module"
|
|
||||||
driver.arch="cct"
|
|
||||||
driver.author="HyperionOS Dev Team"
|
|
||||||
driver.license="MIT"
|
|
||||||
driver.api={}
|
|
||||||
|
|
||||||
function driver.load()
|
|
||||||
-- will
|
|
||||||
end
|
|
||||||
|
|
||||||
function driver.unload()
|
|
||||||
-- Nothing to unload
|
|
||||||
end
|
|
||||||
|
|
||||||
function driver.main()
|
|
||||||
-- Nothing to run
|
|
||||||
end
|
|
||||||
|
|
||||||
-- kernel.drivers.register(driver)
|
|
||||||
@@ -1,182 +0,0 @@
|
|||||||
--:Minify:--
|
|
||||||
local kernel=...
|
|
||||||
local apis=kernel.apis
|
|
||||||
local main=apis.term
|
|
||||||
local native=apis.peripheral
|
|
||||||
local sides = {"top", "bottom", "left", "right", "front", "back"}
|
|
||||||
|
|
||||||
local function getType(name)
|
|
||||||
if native.isPresent(name) then
|
|
||||||
return native.getType(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, "getTypeRemote", name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
local function getNames()
|
|
||||||
local names = {}
|
|
||||||
for n = 1, #sides do
|
|
||||||
local side = sides[n]
|
|
||||||
if native.isPresent(side) then
|
|
||||||
table.insert(names, side)
|
|
||||||
end
|
|
||||||
if native.hasType(side, "peripheral_hub") then
|
|
||||||
local hubSides = native.call(side, "getConnectedSides")
|
|
||||||
for _, hubSide in ipairs(hubSides) do
|
|
||||||
table.insert(names, hubSide)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return names
|
|
||||||
end
|
|
||||||
|
|
||||||
local function wrapPeripheral(name)
|
|
||||||
if native.isPresent(name) then
|
|
||||||
return wrapPeripheral(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, "wrapRemote", name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
local colors={
|
|
||||||
[0]=0x000000, -- #000000
|
|
||||||
0xFFFFFF, -- #FFFFFF
|
|
||||||
0xFF0000, -- #FF0000
|
|
||||||
0x00FF00, -- #00FF00
|
|
||||||
0x0000FF, -- #0000FF
|
|
||||||
0x00FFFF, -- #00FFFF
|
|
||||||
0xFF00FF, -- #FF00FF
|
|
||||||
0xFFFF00, -- #FFFF00
|
|
||||||
0xFF6D00, -- #FF6D00
|
|
||||||
0x6DFF55, -- #6DFF55
|
|
||||||
0x24FFFF, -- #24FFFF
|
|
||||||
0x924900, -- #924900
|
|
||||||
0x6D6D55, -- #6D6D55
|
|
||||||
0xDBDBAA, -- #DBDBAA
|
|
||||||
0x6D00FF, -- #6D00FF
|
|
||||||
0xB6FF00 -- #B6FF00
|
|
||||||
}
|
|
||||||
|
|
||||||
local icolors={
|
|
||||||
[0x1] =0, -- #000000
|
|
||||||
[0x2] =1, -- #FFFFFF
|
|
||||||
[0x4] =2, -- #FF0000
|
|
||||||
[0x8] =3, -- #00FF00
|
|
||||||
[0x10] =4, -- #0000FF
|
|
||||||
[0x20] =5, -- #00FFFF
|
|
||||||
[0x40] =6, -- #FF00FF
|
|
||||||
[0x80] =7, -- #FFFF00
|
|
||||||
[0x100] =8, -- #FF6D00
|
|
||||||
[0x200] =9, -- #6DFF55
|
|
||||||
[0x400] =10, -- #24FFFF
|
|
||||||
[0x800] =11, -- #924900
|
|
||||||
[0x1000] =12, -- #6D6D55
|
|
||||||
[0x2000] =13, -- #DBDBAA
|
|
||||||
[0x4000] =14, -- #6D00FF
|
|
||||||
[0x8000] =15 -- #B6FF00
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
-- Handle wrapping if we go past right edge
|
|
||||||
if x > w then
|
|
||||||
x = 1
|
|
||||||
y = y + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Handle scrolling if we go past bottom
|
|
||||||
if y-1 > h then
|
|
||||||
term.scroll(1)
|
|
||||||
y = h
|
|
||||||
term.setCursorPos(x, y)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
term.setCursorPos(x, y)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function newTTY(term)
|
|
||||||
local ret={}
|
|
||||||
function ret.print(text)
|
|
||||||
write(text.."\n", term)
|
|
||||||
end
|
|
||||||
function ret.printInline(text)
|
|
||||||
write(text, term)
|
|
||||||
end
|
|
||||||
function ret.clear()
|
|
||||||
term.clear()
|
|
||||||
term.setCursorPos(1,1)
|
|
||||||
end
|
|
||||||
function ret.setCursorPos(x,y)
|
|
||||||
term.setCursorPos(x,y)
|
|
||||||
end
|
|
||||||
function ret.getCursorPos()
|
|
||||||
return term.getCursorPos()
|
|
||||||
end
|
|
||||||
function ret.getSize()
|
|
||||||
return term.getSize()
|
|
||||||
end
|
|
||||||
function ret.setBackgroundColor(color)
|
|
||||||
term.setBackgroundColor(colors[color])
|
|
||||||
end
|
|
||||||
function ret.setTextColor(color)
|
|
||||||
term.setTextColor(colors[color])
|
|
||||||
end
|
|
||||||
function ret.getBackgroundColor()
|
|
||||||
return icolors[term.getBackgroundColor()]
|
|
||||||
end
|
|
||||||
function ret.getTextColor()
|
|
||||||
return icolors[term.getTextColor()]
|
|
||||||
end
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
|
|
||||||
kernel.tty.register("tty0", newTTY(main))
|
|
||||||
|
|
||||||
for _, name in ipairs(getNames()) do
|
|
||||||
local t = getType(name)
|
|
||||||
if t == "monitor" then
|
|
||||||
local monitorTerm = wrapPeripheral(name)
|
|
||||||
monitorTerm.setTextScale(0.5)
|
|
||||||
kernel.tty.register(name, newTTY(monitorTerm))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
544
Src/Hyperion-firmware-cct/boot/cct/boot.lua
Normal file
544
Src/Hyperion-firmware-cct/boot/cct/boot.lua
Normal file
@@ -0,0 +1,544 @@
|
|||||||
|
--: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
|
||||||
|
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
|
||||||
|
|
||||||
|
local peripheral={}
|
||||||
|
local native = apis.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 allscreens = {peripheral.find("monitor")}
|
||||||
|
for i=1, #allscreens do
|
||||||
|
allscreens[i].setTextScale(.5)
|
||||||
|
allscreens[i].clear()
|
||||||
|
allscreens[i].setCursorPos(1,1)
|
||||||
|
allscreens[i].write("Initializing...")
|
||||||
|
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,
|
||||||
|
beep=function() end
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
EFI.screenCtl:print("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
|
||||||
119
Src/Hyperion-firmware-cct/boot/cct/eeprom
Normal file
119
Src/Hyperion-firmware-cct/boot/cct/eeprom
Normal file
@@ -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
|
||||||
272
Src/Hyperion-firmware-cct/boot/cct/initdisks
Normal file
272
Src/Hyperion-firmware-cct/boot/cct/initdisks
Normal file
@@ -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}
|
||||||
152
Src/Hyperion-firmware-cct/lib/modules/cc-tweaked/01_periph.kmod
Normal file
152
Src/Hyperion-firmware-cct/lib/modules/cc-tweaked/01_periph.kmod
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
--:Minify:--
|
||||||
|
-- CCT driver peripheral helper
|
||||||
|
local kernel=...
|
||||||
|
kernel.cct={}
|
||||||
|
kernel.cct.peripheral={}
|
||||||
|
local peripheral=kernel.cct.peripheral
|
||||||
|
local apis = kernel.apis
|
||||||
|
local native = apis.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
|
||||||
252
Src/Hyperion-firmware-cct/lib/modules/cc-tweaked/25_tty.kmod
Normal file
252
Src/Hyperion-firmware-cct/lib/modules/cc-tweaked/25_tty.kmod
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
--:Minify:--
|
||||||
|
local kernel = ...
|
||||||
|
local peripheral=kernel.cct.peripheral
|
||||||
|
|
||||||
|
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 plt = {
|
||||||
|
0xFFFFFF,
|
||||||
|
0xFF0000,
|
||||||
|
0x00FF00,
|
||||||
|
0x0000FF,
|
||||||
|
0x00FFFF,
|
||||||
|
0xFF00FF,
|
||||||
|
0xFFFF00,
|
||||||
|
0xFF6D00,
|
||||||
|
0x6DFF55,
|
||||||
|
0x24FFFF,
|
||||||
|
0x924900,
|
||||||
|
0x6D6D55,
|
||||||
|
0xDBDBAA,
|
||||||
|
0x6D00FF,
|
||||||
|
0xB6FF00,
|
||||||
|
0x000000
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
kernel.devfs.data.tty={}
|
||||||
|
kernel.cct.ctrl,kernel.cct.alt = false, false
|
||||||
|
|
||||||
|
local function serializeBool(bool)
|
||||||
|
if bool then
|
||||||
|
return "T"
|
||||||
|
else
|
||||||
|
return "F"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function newtty(obj, id, ev)
|
||||||
|
obj.setPaletteColor(0x1, 0xFFFFFF) -- #000000
|
||||||
|
obj.setPaletteColor(0x2, 0xFF0000) -- #FFFFFF
|
||||||
|
obj.setPaletteColor(0x4, 0x00FF00) -- #FF0000
|
||||||
|
obj.setPaletteColor(0x8, 0x0000FF) -- #00FF00
|
||||||
|
obj.setPaletteColor(0x10, 0x00FFFF) -- #0000FF
|
||||||
|
obj.setPaletteColor(0x20, 0xFF00FF) -- #00FFFF
|
||||||
|
obj.setPaletteColor(0x40, 0xFFFF00) -- #FF00FF
|
||||||
|
obj.setPaletteColor(0x80, 0xFF6D00) -- #FFFF00
|
||||||
|
obj.setPaletteColor(0x100, 0x6DFF55) -- #FF6D00
|
||||||
|
obj.setPaletteColor(0x200, 0x24FFFF) -- #6DFF55
|
||||||
|
obj.setPaletteColor(0x400, 0x924900) -- #24FFFF
|
||||||
|
obj.setPaletteColor(0x800, 0x6D6D55) -- #924900
|
||||||
|
obj.setPaletteColor(0x1000, 0xDBDBAA) -- #6D6D55
|
||||||
|
obj.setPaletteColor(0x2000, 0x6D00FF) -- #DBDBAA
|
||||||
|
obj.setPaletteColor(0x4000, 0xB6FF00) -- #6D00FF
|
||||||
|
obj.setPaletteColor(0x8000, 0x000000) -- #B6FF00
|
||||||
|
kernel.devfs.data["tty"][id] = function(op, mode)
|
||||||
|
if op=="type" then
|
||||||
|
return "Terminal"
|
||||||
|
elseif op=="open" then
|
||||||
|
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(content, obj)
|
||||||
|
end,
|
||||||
|
size=function()
|
||||||
|
local s={obj.getSize()}
|
||||||
|
return table.concat(s,";")
|
||||||
|
end,
|
||||||
|
clear=function()
|
||||||
|
obj.clear()
|
||||||
|
obj.setCursorPos(1,1)
|
||||||
|
end,
|
||||||
|
gpos=function()
|
||||||
|
local s={obj.getCursorPos()}
|
||||||
|
return table.concat(s,";")
|
||||||
|
end,
|
||||||
|
spos=function(x,y)
|
||||||
|
return obj.setCursorPos(x,y)
|
||||||
|
end,
|
||||||
|
sfgc=function(c)
|
||||||
|
fg=c
|
||||||
|
return obj.setTextColor(aprox(c))
|
||||||
|
end,
|
||||||
|
sbgc=function(c)
|
||||||
|
bg=c
|
||||||
|
return obj.setBackgroundColor(aprox(c))
|
||||||
|
end,
|
||||||
|
gfgc=function()
|
||||||
|
return fg
|
||||||
|
end,
|
||||||
|
gbgc=function()
|
||||||
|
return bg
|
||||||
|
end,
|
||||||
|
gctrl=function()
|
||||||
|
return serializeBool(kernel.cct.ctrl)..";"..serializeBool(kernel.cct.alt)
|
||||||
|
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
|
||||||
|
|
||||||
|
local fifo = kernel.newFifo()
|
||||||
|
kernel.cct.fifo=fifo
|
||||||
|
|
||||||
|
newtty(kernel.apis.term, "1", fifo.pop)
|
||||||
|
|
||||||
|
for i,v in ipairs({peripheral.find("monitor")}) do
|
||||||
|
v.setTextScale(.5)
|
||||||
|
v.write("Initializing...")
|
||||||
|
newtty(v,tostring(i+1),function () end)
|
||||||
|
end
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
--:Minify:--
|
||||||
|
local kernel=...
|
||||||
|
local keys=kernel.apis.keys
|
||||||
|
|
||||||
|
kernel.processes.cctdeamon = function()
|
||||||
|
local timeout = false
|
||||||
|
while true do
|
||||||
|
local event = {kernel.EFI:getMachineEvent()}
|
||||||
|
|
||||||
|
if event[1] then
|
||||||
|
local eventType = event[1]
|
||||||
|
local charOrKey = event[3]
|
||||||
|
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
|
||||||
|
if eventType == "keyPressed" then
|
||||||
|
if charOrKey == keys.leftCtrl or charOrKey == keys.rightCtrl then
|
||||||
|
kernel.cct.ctrl = true
|
||||||
|
elseif charOrKey == keys.leftAlt or charOrKey == keys.rightAlt then
|
||||||
|
kernel.cct.alt = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if kernel.cct.ctrl then
|
||||||
|
local ctrlByte = ctrlKeyMap[charOrKey]
|
||||||
|
if ctrlByte then
|
||||||
|
if ctrlByte == 3 then
|
||||||
|
for _, task in ipairs(syscall.getTasks()) do
|
||||||
|
syscall.sigsend(task, 1)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
kernel.cct.fifo.push(string.char(ctrlByte))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local specialKeyMap = {
|
||||||
|
[keys.up] = "[A",
|
||||||
|
[keys.down] = "[B",
|
||||||
|
[keys.right] = "[C",
|
||||||
|
[keys.left] = "[D",
|
||||||
|
[keys.home] = "[H",
|
||||||
|
[keys["end"]] = "[F",
|
||||||
|
[keys.pageUp] = "[5~",
|
||||||
|
[keys.pageDown] = "[6~",
|
||||||
|
[keys.delete] = "[3~",
|
||||||
|
}
|
||||||
|
local special = specialKeyMap[charOrKey]
|
||||||
|
if special then kernel.cct.fifo.push(special) end
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif eventType == "keyReleased" then
|
||||||
|
if charOrKey == keys.leftCtrl or charOrKey == keys.rightCtrl then
|
||||||
|
kernel.cct.ctrl = false
|
||||||
|
elseif charOrKey == keys.leftAlt or charOrKey == keys.rightAlt then
|
||||||
|
kernel.cct.alt = false
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif eventType == "keyTyped" then
|
||||||
|
if charOrKey then kernel.cct.fifo.push(charOrKey) end
|
||||||
|
elseif eventType == "http_success" then
|
||||||
|
kernel.cct.httpqueue[event[2]]=nil
|
||||||
|
kernel.cct.httpresponse[event[2]]=event[3]
|
||||||
|
elseif eventType == "http_failure" then
|
||||||
|
kernel.cct.httpqueue[event[2]]=nil
|
||||||
|
kernel.cct.httperror[event[2]]=event[3]
|
||||||
|
end
|
||||||
|
|
||||||
|
timeout = false
|
||||||
|
else
|
||||||
|
timeout = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if timeout then
|
||||||
|
sleep(0.05)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
--:Minify:--
|
||||||
|
local kernel=...
|
||||||
|
local rs=kernel.apis.rs
|
||||||
|
local sides = {top=1, bottom=2, left=3, right=4, front=5, back=6}
|
||||||
|
local function newGPIO(side)
|
||||||
|
return function(mode, data)
|
||||||
|
if mode=="w" then
|
||||||
|
if type(data)~="boolean" then error("data: expected bool") end
|
||||||
|
rs.setOutput(side, data)
|
||||||
|
elseif mode=="wa" then
|
||||||
|
if type(data)~="number" then error("data: expected bool") end
|
||||||
|
rs.setAnalogOutput(side, data)
|
||||||
|
elseif mode=="r" then
|
||||||
|
return rs.getInput(side)
|
||||||
|
elseif mode=="ra" then
|
||||||
|
return rs.getAnalogInput(side)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for side, alt in pairs(sides) do
|
||||||
|
local func=newGPIO(side)
|
||||||
|
kernel.gpio[side]=func
|
||||||
|
kernel.gpio[alt]=func
|
||||||
|
end
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"Name": "Hyperion OC Firmware",
|
|
||||||
"Version": "1.0.0",
|
|
||||||
"Publishers": ["HyperionOS Dev Team"],
|
|
||||||
"Description": "The OpenComputers firmware package for HyperionOS.",
|
|
||||||
"Dependencies": [
|
|
||||||
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-kernel-v1.0.0.pkg"
|
|
||||||
],
|
|
||||||
"Tar": "https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-firmware-oc-v1.0.0.tar",
|
|
||||||
"BuildCommand": "cp boot/oc/eeprom /dev/eeprom"
|
|
||||||
}
|
|
||||||
@@ -32,6 +32,7 @@ local lua = {
|
|||||||
_G=true
|
_G=true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local apis={}
|
||||||
for i,v in pairs(_G) do
|
for i,v in pairs(_G) do
|
||||||
if not lua[i] or lua[i]==nil then
|
if not lua[i] or lua[i]==nil then
|
||||||
apis[i]=v
|
apis[i]=v
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"Name": "Hyperion Kernel",
|
|
||||||
"Version": "1.0.0",
|
|
||||||
"Publishers": ["HyperionOS Dev Team"],
|
|
||||||
"Description": "The kernel package for HyperionOS.",
|
|
||||||
"Dependencies": [],
|
|
||||||
"Tar": "https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-kernel-v1.0.0.tar"
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
U $;/
|
|
||||||
U devfs0000;/dev/
|
|
||||||
@@ -1,285 +0,0 @@
|
|||||||
--:Minify:--
|
|
||||||
function string.hasSuffix(str, suffix)
|
|
||||||
return string.sub(str, #suffix+1) == suffix
|
|
||||||
end
|
|
||||||
|
|
||||||
function string.hasPrefix(str, prefix)
|
|
||||||
return string.sub(str, 1, #prefix) == prefix
|
|
||||||
end
|
|
||||||
|
|
||||||
function string.getSuffix(str, prefix)
|
|
||||||
return string.sub(str, #prefix+1)
|
|
||||||
end
|
|
||||||
|
|
||||||
function string.getPrefix(str, suffix)
|
|
||||||
return string.sub(str, 1, #suffix)
|
|
||||||
end
|
|
||||||
|
|
||||||
function string.join(str, ...)
|
|
||||||
return table.concat(table.pack(str, ...))
|
|
||||||
end
|
|
||||||
|
|
||||||
function string.delim(str, ...)
|
|
||||||
return table.concat(table.pack(...), str)
|
|
||||||
end
|
|
||||||
|
|
||||||
function string.split(str, delim, maxResultCountOrNil)
|
|
||||||
assert(#delim == 1, "only delim len 1 supported for now")
|
|
||||||
maxResultCountOrNil = (maxResultCountOrNil or 0)-1
|
|
||||||
local rv = {}
|
|
||||||
local buf = ""
|
|
||||||
for i = 1, #str do
|
|
||||||
local c = string.sub(str,i,i)
|
|
||||||
if #rv ~= maxResultCountOrNil and c == delim then
|
|
||||||
table.insert(rv, buf)
|
|
||||||
buf = ""
|
|
||||||
else
|
|
||||||
buf = buf..c
|
|
||||||
end
|
|
||||||
end
|
|
||||||
table.insert(rv, buf)
|
|
||||||
return rv
|
|
||||||
end
|
|
||||||
|
|
||||||
function string.replace(str, search, replacement)
|
|
||||||
local rv = ""
|
|
||||||
local consumedLen = 1
|
|
||||||
local i = 1
|
|
||||||
while i<#str do
|
|
||||||
if string.sub(str, i, i+#search-1) == search then
|
|
||||||
rv = rv .. string.sub(str, consumedLen, i-1) .. replacement
|
|
||||||
i=i+#search
|
|
||||||
consumedLen = i
|
|
||||||
end
|
|
||||||
i=i+1
|
|
||||||
end
|
|
||||||
return rv .. string.sub(str, consumedLen)
|
|
||||||
end
|
|
||||||
|
|
||||||
function table.deepcopy(orig, copies)
|
|
||||||
copies = copies or {}
|
|
||||||
|
|
||||||
if type(orig) ~= 'table' then
|
|
||||||
return orig
|
|
||||||
elseif copies[orig] then
|
|
||||||
return copies[orig]
|
|
||||||
end
|
|
||||||
|
|
||||||
local copy = {}
|
|
||||||
copies[orig] = copy
|
|
||||||
|
|
||||||
for k, v in next, orig, nil do
|
|
||||||
local copied_key = table.deepcopy(k, copies)
|
|
||||||
local copied_val = table.deepcopy(v, copies)
|
|
||||||
copy[copied_key] = copied_val
|
|
||||||
end
|
|
||||||
|
|
||||||
return copy
|
|
||||||
end
|
|
||||||
|
|
||||||
function table.hasKey(tabl, query)
|
|
||||||
for i,v in pairs(tabl) do
|
|
||||||
if i==query then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
function table.hasVal(tabl, query)
|
|
||||||
for i,v in pairs(tabl) do
|
|
||||||
if v==query then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
function table.proxy(tbl)
|
|
||||||
local proxies = setmetatable({}, {__mode = "k"}) -- Weak table to avoid cycles
|
|
||||||
|
|
||||||
local function createProxy(t)
|
|
||||||
if type(t) ~= "table" then return t end
|
|
||||||
if proxies[t] then return proxies[t] end -- reuse proxy for the same table (handle cycles)
|
|
||||||
|
|
||||||
local proxy = {}
|
|
||||||
proxies[t] = proxy
|
|
||||||
|
|
||||||
local mt
|
|
||||||
mt = {
|
|
||||||
__index = function(_, k)
|
|
||||||
local value = t[k]
|
|
||||||
if type(value) == "table" then
|
|
||||||
return createProxy(value) -- recursively proxy subtables
|
|
||||||
else
|
|
||||||
return value
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
__newindex = function()
|
|
||||||
error("Attempt to modify table proxy", 2)
|
|
||||||
end,
|
|
||||||
__pairs = function()
|
|
||||||
return function(_, k)
|
|
||||||
local nextKey, nextValue = next(t, k)
|
|
||||||
if type(nextValue) == "table" then
|
|
||||||
nextValue = createProxy(nextValue)
|
|
||||||
end
|
|
||||||
return nextKey, nextValue
|
|
||||||
end, nil, nil
|
|
||||||
end,
|
|
||||||
__ipairs = function()
|
|
||||||
local i = 0
|
|
||||||
local n = #t
|
|
||||||
return function()
|
|
||||||
i = i + 1
|
|
||||||
if i <= n then
|
|
||||||
local v = t[i]
|
|
||||||
if type(v) == "table" then
|
|
||||||
v = createProxy(v)
|
|
||||||
end
|
|
||||||
return i, v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
__metatable = false
|
|
||||||
}
|
|
||||||
|
|
||||||
setmetatable(proxy, mt)
|
|
||||||
return proxy
|
|
||||||
end
|
|
||||||
|
|
||||||
return createProxy(tbl)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function serialize(table)
|
|
||||||
local output = "{"
|
|
||||||
for i,v in pairs(table) do
|
|
||||||
local coma=true
|
|
||||||
if type(i) == "string" then
|
|
||||||
output=output.."[\""..i.."\"]="
|
|
||||||
elseif type(i) == "number" then
|
|
||||||
output=output.."["..tostring(i).."]="
|
|
||||||
end
|
|
||||||
if type(v) == "table" then
|
|
||||||
if v == table then
|
|
||||||
output=string.sub(output,1,#output-(#i+1))
|
|
||||||
coma=false
|
|
||||||
else
|
|
||||||
output=output..serialize(v)
|
|
||||||
end
|
|
||||||
elseif type(v) == "string" then
|
|
||||||
output=output.."[=["..v.."]=]"
|
|
||||||
elseif type(v) == "number" then
|
|
||||||
output=output..tostring(v)
|
|
||||||
elseif type(v) == "boolean" then
|
|
||||||
if v == true then
|
|
||||||
output=output.."true"
|
|
||||||
else
|
|
||||||
output=output.."false"
|
|
||||||
end
|
|
||||||
elseif type(v) == "function" then
|
|
||||||
output=output..tostring(v)
|
|
||||||
else
|
|
||||||
error("serialization of type \""..type(v).."\" is not supported")
|
|
||||||
end
|
|
||||||
if coma then
|
|
||||||
output=output..","
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if #table>0 or string.sub(output,#output,#output) == "," then
|
|
||||||
output=string.sub(output,1,#output-1)
|
|
||||||
end
|
|
||||||
output=output.."}"
|
|
||||||
return output
|
|
||||||
end
|
|
||||||
|
|
||||||
local oldtype=type
|
|
||||||
local oldgetmetatable=getmetatable
|
|
||||||
function type(object, trueType)
|
|
||||||
if trueType then
|
|
||||||
return oldtype(object)
|
|
||||||
end
|
|
||||||
if oldtype(object)~="table" then
|
|
||||||
return oldtype(object)
|
|
||||||
else
|
|
||||||
if oldtype(oldgetmetatable(object))=="table" then
|
|
||||||
local metatable = oldgetmetatable(object)
|
|
||||||
if metatable.__type then return metatable.__type end
|
|
||||||
else
|
|
||||||
return "table"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function getmetatable(object)
|
|
||||||
if oldtype(object)~="table" then return end
|
|
||||||
if oldtype(oldgetmetatable(object))=="table" then
|
|
||||||
if oldgetmetatable(object).__isuserdata then
|
|
||||||
if oldtype(oldgetmetatable(object).__usermeta)=="function" then
|
|
||||||
return oldgetmetatable(object).__usermeta()
|
|
||||||
else
|
|
||||||
return oldgetmetatable(object).__usermeta
|
|
||||||
end
|
|
||||||
else
|
|
||||||
return oldgetmetatable(object)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
return oldgetmetatable(object)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function isEqualToAny(a, ...)
|
|
||||||
local args={...}
|
|
||||||
for i=0, #args do
|
|
||||||
if a==args[i] then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
function isEqualToAll(a, ...)
|
|
||||||
local args={...}
|
|
||||||
for i=0, #args do
|
|
||||||
if a~=args[i] then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
function table.keys(t)
|
|
||||||
local a = {}
|
|
||||||
for n in pairs(t) do table.insert(a, n) end
|
|
||||||
return a
|
|
||||||
end
|
|
||||||
|
|
||||||
function table.values(t)
|
|
||||||
local a = {}
|
|
||||||
for _, n in pairs(t) do table.insert(a, n) end
|
|
||||||
return a
|
|
||||||
end
|
|
||||||
|
|
||||||
function table.indexOf(t, value)
|
|
||||||
for i,v in ipairs(t) do
|
|
||||||
if v==value then
|
|
||||||
return i
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return -1
|
|
||||||
end
|
|
||||||
|
|
||||||
syscall = setmetatable({}, {
|
|
||||||
__index = function(self, name)
|
|
||||||
return function(...)
|
|
||||||
local res = table.pack(coroutine.yield("syscall", name, ...))
|
|
||||||
if res[1] then
|
|
||||||
return table.unpack(res, 2, res.n)
|
|
||||||
else
|
|
||||||
error(res[2], 2)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
})
|
|
||||||
|
|
||||||
table.serialize=serialize
|
|
||||||
@@ -1,278 +0,0 @@
|
|||||||
--:Minify:--
|
|
||||||
local kernel = ...
|
|
||||||
local vfs = {}
|
|
||||||
vfs.mounts = { ["$"] = "/" }
|
|
||||||
local disks = kernel.disks
|
|
||||||
|
|
||||||
-- Path handling
|
|
||||||
local function normalizePath(path)
|
|
||||||
local parts = {}
|
|
||||||
for part in path:gmatch("[^/]+") do
|
|
||||||
if part == ".." then
|
|
||||||
if #parts > 0 then table.remove(parts) end
|
|
||||||
elseif part ~= "." and part ~= "" then
|
|
||||||
table.insert(parts, part)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return "/" .. table.concat(parts, "/") .. (path:sub(-1) == "/" and "/" or "")
|
|
||||||
end
|
|
||||||
|
|
||||||
local function resolvePath(path)
|
|
||||||
local task = kernel.currentTask
|
|
||||||
local cwd = task.cwd or "/"
|
|
||||||
|
|
||||||
if path:sub(1,1) ~= "/" then
|
|
||||||
path = cwd .. path
|
|
||||||
end
|
|
||||||
|
|
||||||
path = normalizePath(path)
|
|
||||||
|
|
||||||
local mountPoint = "/"
|
|
||||||
local mountId = "$"
|
|
||||||
for k,v in pairs(vfs.mounts) do
|
|
||||||
if path:sub(1,#v) == v and #v > #mountPoint then
|
|
||||||
mountPoint = v
|
|
||||||
mountId = k
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local diskPath = path:sub(#mountPoint + 1)
|
|
||||||
return disks[mountId], diskPath
|
|
||||||
end
|
|
||||||
|
|
||||||
-- File object creation
|
|
||||||
local function newFileObject(disk, handle, mode, path)
|
|
||||||
return {
|
|
||||||
disk = disk,
|
|
||||||
handle = handle,
|
|
||||||
mode = mode,
|
|
||||||
path = path,
|
|
||||||
refcount = 1
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
local function allocFD(task)
|
|
||||||
local fd = 0
|
|
||||||
while task.fd[fd] do fd = fd + 1 end
|
|
||||||
return fd
|
|
||||||
end
|
|
||||||
|
|
||||||
local function allocFD(task)
|
|
||||||
-- enforce per-task limit
|
|
||||||
local count = 0
|
|
||||||
for _ in pairs(task.fd) do count = count + 1 end
|
|
||||||
if count >= kernel.config.maxFilesPerTask then
|
|
||||||
error("EMFILE") -- Too many open files in this task
|
|
||||||
end
|
|
||||||
|
|
||||||
-- find first free FD
|
|
||||||
local fd = 0
|
|
||||||
while task.fd[fd] do fd = fd + 1 end
|
|
||||||
return fd
|
|
||||||
end
|
|
||||||
|
|
||||||
local function checkSystemLimit()
|
|
||||||
-- enforce system-wide limit
|
|
||||||
local total = 0
|
|
||||||
for _, task in pairs(kernel.tasks or {}) do
|
|
||||||
for _ in pairs(task.fd) do total = total + 1 end
|
|
||||||
end
|
|
||||||
if total >= kernel.config.maxOpenFiles then
|
|
||||||
error("ENFILE") -- Too many open files in the system
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- VFS syscalls
|
|
||||||
function vfs.open(path, mode)
|
|
||||||
local task = kernel.currentTask
|
|
||||||
|
|
||||||
-- check limits
|
|
||||||
checkSystemLimit()
|
|
||||||
|
|
||||||
local disk, diskPath = resolvePath(path)
|
|
||||||
if not disk then
|
|
||||||
error("No disk mounted for path '"..path.."'")
|
|
||||||
end
|
|
||||||
|
|
||||||
local handle = disk:open(diskPath, mode)
|
|
||||||
if not handle then return nil end
|
|
||||||
|
|
||||||
local file = newFileObject(disk.address, handle, mode, path)
|
|
||||||
local fd = allocFD(task)
|
|
||||||
task.fd[fd] = file
|
|
||||||
|
|
||||||
return fd
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.close(fd)
|
|
||||||
local task = kernel.currentTask
|
|
||||||
local file = task.fd[fd]
|
|
||||||
if not file then error("EBADF") end
|
|
||||||
|
|
||||||
task.fd[fd] = nil
|
|
||||||
file.refcount = file.refcount - 1
|
|
||||||
if file.refcount == 0 then
|
|
||||||
file.handle.close()
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.read(fd, count)
|
|
||||||
local file = kernel.currentTask.fd[fd]
|
|
||||||
if not file then error("EBADF") end
|
|
||||||
if not file.mode:find("r") then error("File not open for reading") end
|
|
||||||
return file.handle.read(count)
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.write(fd, data)
|
|
||||||
local file = kernel.currentTask.fd[fd]
|
|
||||||
if not file then error("EBADF") end
|
|
||||||
if not file.mode:find("w") then error("File not open for writing") end
|
|
||||||
return file.handle.write(data)
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.whereis(fd)
|
|
||||||
local file = kernel.currentTask.fd[fd]
|
|
||||||
if not file then error("EBADF") end
|
|
||||||
return file.path
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Filesystem operations
|
|
||||||
function vfs.mkdir(path)
|
|
||||||
local disk, diskPath = resolvePath(path)
|
|
||||||
if not disk then error("No disk mounted") end
|
|
||||||
return disk:makeDirectory(diskPath)
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.remove(path)
|
|
||||||
local disk, diskPath = resolvePath(path)
|
|
||||||
if not disk then error("No disk mounted") end
|
|
||||||
return disk:remove(diskPath)
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.attributes(path)
|
|
||||||
if type(path) == "number" then
|
|
||||||
local file = kernel.currentTask.fd[path]
|
|
||||||
if not file then error("EBADF") end
|
|
||||||
return disks[file.disk]:attributes(file.path)
|
|
||||||
end
|
|
||||||
local disk, diskPath = resolvePath(path)
|
|
||||||
if not disk then error("No disk mounted") end
|
|
||||||
return disk:attributes(diskPath)
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.list(path)
|
|
||||||
local disk, diskPath = resolvePath(path)
|
|
||||||
if not disk then error("No disk mounted") end
|
|
||||||
return disk:list(diskPath)
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.exists(path)
|
|
||||||
local disk, diskPath = resolvePath(path)
|
|
||||||
if not disk then return false end
|
|
||||||
return disk:directoryExists(diskPath) or disk:fileExists(diskPath)
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.type(path)
|
|
||||||
if type(path) == "number" then
|
|
||||||
local file = kernel.currentTask.fd[path]
|
|
||||||
if not file then error("EBADF") end
|
|
||||||
return disks[file.disk]:type(file.path)
|
|
||||||
end
|
|
||||||
local disk, diskPath = resolvePath(path)
|
|
||||||
if not disk then error("No disk mounted") end
|
|
||||||
return disk:type(diskPath)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- CWD
|
|
||||||
function vfs.getcwd()
|
|
||||||
return kernel.currentTask.cwd
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.setcwd(path)
|
|
||||||
if path:sub(-1) ~= "/" then path = path .. "/" end
|
|
||||||
if path:sub(1,1) ~= "/" then path = "/" .. path end
|
|
||||||
kernel.currentTask.cwd = normalizePath(path)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Mounting
|
|
||||||
function vfs.mount(diskId, path)
|
|
||||||
if kernel.uid ~= 0 then error("Permission denied") end
|
|
||||||
if not disks[diskId] then error("Unknown disk '"..diskId.."'") end
|
|
||||||
if path:sub(-1) ~= "/" then path = path .. "/" end
|
|
||||||
|
|
||||||
for _,v in pairs(vfs.mounts) do
|
|
||||||
if v == path then error("Mount point already used") end
|
|
||||||
end
|
|
||||||
vfs.mounts[diskId] = path
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.unmount(path)
|
|
||||||
if kernel.uid ~= 0 then error("Permission denied") end
|
|
||||||
for k,v in pairs(vfs.mounts) do
|
|
||||||
if v == path then
|
|
||||||
vfs.mounts[k] = nil
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.getMounts()
|
|
||||||
return vfs.mounts
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.virtdisk(obj)
|
|
||||||
kernel.disks[obj.address] = obj
|
|
||||||
kernel.log("Registered virtual disk at "..obj.address)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Redirect file operations to VFS
|
|
||||||
function vfs.dup(oldfd)
|
|
||||||
local task = kernel.currentTask
|
|
||||||
local file = task.fd[oldfd]
|
|
||||||
if not file then error("EBADF") end
|
|
||||||
|
|
||||||
local newfd = allocFD(task)
|
|
||||||
task.fd[newfd] = file
|
|
||||||
file.refcount = file.refcount + 1
|
|
||||||
return newfd
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.dup2(oldfd, newfd)
|
|
||||||
local task = kernel.currentTask
|
|
||||||
local file = task.fd[oldfd]
|
|
||||||
if not file then error("EBADF") end
|
|
||||||
|
|
||||||
if oldfd == newfd then return newfd end
|
|
||||||
|
|
||||||
if task.fd[newfd] then
|
|
||||||
vfs.close(newfd)
|
|
||||||
end
|
|
||||||
|
|
||||||
task.fd[newfd] = file
|
|
||||||
file.refcount = file.refcount + 1
|
|
||||||
return newfd
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Syscall registration
|
|
||||||
kernel.vfs = vfs
|
|
||||||
kernel.syscalls["VFS_open"] = vfs.open
|
|
||||||
kernel.syscalls["VFS_read"] = vfs.read
|
|
||||||
kernel.syscalls["VFS_write"] = vfs.write
|
|
||||||
kernel.syscalls["VFS_close"] = vfs.close
|
|
||||||
kernel.syscalls["VFS_list"] = vfs.list
|
|
||||||
kernel.syscalls["VFS_type"] = vfs.type
|
|
||||||
kernel.syscalls["VFS_attributes"] = vfs.attributes
|
|
||||||
kernel.syscalls["VFS_mkdir"] = vfs.mkdir
|
|
||||||
kernel.syscalls["VFS_remove"] = vfs.remove
|
|
||||||
kernel.syscalls["VFS_exists"] = vfs.exists
|
|
||||||
kernel.syscalls["VFS_mount"] = vfs.mount
|
|
||||||
kernel.syscalls["VFS_unmount"] = vfs.unmount
|
|
||||||
kernel.syscalls["VFS_getcwd"] = vfs.getcwd
|
|
||||||
kernel.syscalls["VFS_setcwd"] = vfs.setcwd
|
|
||||||
kernel.syscalls["VFS_whereis"] = vfs.whereis
|
|
||||||
kernel.syscalls["VFS_dup"] = vfs.dup
|
|
||||||
kernel.syscalls["VFS_dup2"] = vfs.dup2
|
|
||||||
|
|
||||||
kernel.log("VFS module loaded")
|
|
||||||
@@ -1,173 +0,0 @@
|
|||||||
--:Minify:--
|
|
||||||
local kernel = ...
|
|
||||||
|
|
||||||
local proxy = {}
|
|
||||||
local data = {}
|
|
||||||
|
|
||||||
proxy.address = "devfs0000"
|
|
||||||
proxy.isReadOnly = false
|
|
||||||
proxy.spaceUsed = function() return 0 end
|
|
||||||
proxy.spaceTotal = function() return 0 end
|
|
||||||
proxy.makeDirectory = function() error("Permission denied") end
|
|
||||||
proxy.remove = function() error("Permission denied") end
|
|
||||||
proxy.setLabel = function() error("Permission denied") end
|
|
||||||
proxy.getLabel = function() return "devfs" end
|
|
||||||
proxy.attributes = function(path) return {
|
|
||||||
type = proxy.type(path),
|
|
||||||
isReadOnly = false,
|
|
||||||
size = 0,
|
|
||||||
lastModified = 0,
|
|
||||||
created = 0,
|
|
||||||
Permissions = "666",
|
|
||||||
owner = "root",
|
|
||||||
group = "root"
|
|
||||||
} end
|
|
||||||
|
|
||||||
local function getNode(path)
|
|
||||||
local parts = string.split(path, "/")
|
|
||||||
if parts[1] == "" then
|
|
||||||
table.remove(parts, 1)
|
|
||||||
end
|
|
||||||
|
|
||||||
local node = data
|
|
||||||
for _, part in ipairs(parts) do
|
|
||||||
if node[part] then
|
|
||||||
node = node[part]
|
|
||||||
else
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return node
|
|
||||||
end
|
|
||||||
|
|
||||||
proxy.type = function(path)
|
|
||||||
local node = getNode(path)
|
|
||||||
if node then
|
|
||||||
return node.type
|
|
||||||
else
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
proxy.list = function(path)
|
|
||||||
local node = getNode(path)
|
|
||||||
if node and node.type == "directory" then
|
|
||||||
local content = table.keys(node)
|
|
||||||
table.remove(content, table.indexOf(content, "type"))
|
|
||||||
return content
|
|
||||||
else
|
|
||||||
error("Not a directory")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
proxy.open = function(path, mode)
|
|
||||||
local node = getNode(path)
|
|
||||||
if node and (node.type == "file" or node.type == "character device") then
|
|
||||||
if mode == "r" then
|
|
||||||
return {
|
|
||||||
read = node.read,
|
|
||||||
close = function() end
|
|
||||||
}
|
|
||||||
elseif mode == "w" then
|
|
||||||
return {
|
|
||||||
write = node.write,
|
|
||||||
close = function() end
|
|
||||||
}
|
|
||||||
else
|
|
||||||
error("Invalid mode")
|
|
||||||
end
|
|
||||||
else
|
|
||||||
error("Not a file"..type(node))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function newStringFile(content)
|
|
||||||
return {
|
|
||||||
type = "file",
|
|
||||||
read = function() return content end,
|
|
||||||
write = function(newContent) content = newContent end
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
local function newDirectory()
|
|
||||||
return {
|
|
||||||
type = "directory"
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
data["random"] = {
|
|
||||||
type = "character device",
|
|
||||||
read = function(amount)
|
|
||||||
local result = ""
|
|
||||||
for _ = 1, amount do
|
|
||||||
result = result .. string.char(math.random(0, 255))
|
|
||||||
end
|
|
||||||
return result
|
|
||||||
end,
|
|
||||||
write = function() error("Permission denied") end
|
|
||||||
}
|
|
||||||
|
|
||||||
data["null"] = {
|
|
||||||
type = "character device",
|
|
||||||
read = function() return "" end,
|
|
||||||
write = function() end
|
|
||||||
}
|
|
||||||
|
|
||||||
data["zero"] = {
|
|
||||||
type = "character device",
|
|
||||||
read = function(amount)
|
|
||||||
return string.rep("\0", amount)
|
|
||||||
end,
|
|
||||||
write = function() error("Permission denied") end
|
|
||||||
}
|
|
||||||
|
|
||||||
data["rtc"] = {
|
|
||||||
type = "character device",
|
|
||||||
read = function() return kernel.computer:time() end,
|
|
||||||
write = function() error("Permission denied") end
|
|
||||||
}
|
|
||||||
|
|
||||||
data["rtc0"] = {
|
|
||||||
type = "character device",
|
|
||||||
read = function() return kernel.computer:time() end,
|
|
||||||
write = function() error("Permission denied") end
|
|
||||||
}
|
|
||||||
|
|
||||||
data["eeprom"] = {
|
|
||||||
type = "character device",
|
|
||||||
read = function() return kernel.computer:getEEPROM() end,
|
|
||||||
write = function(data)
|
|
||||||
if kernel.uid ~= 0 then
|
|
||||||
error("Permission denied")
|
|
||||||
end
|
|
||||||
kernel.computer:setEEPROM(data)
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
local keyboard = kernel.newFifo()
|
|
||||||
local mouse = kernel.newFifo()
|
|
||||||
data["input"] = newDirectory()
|
|
||||||
data["input"]["keyboard"] = {
|
|
||||||
type = "pipe",
|
|
||||||
read = function(amount)
|
|
||||||
return keyboard.pop()
|
|
||||||
end,
|
|
||||||
write = function() error("Permission denied") end
|
|
||||||
}
|
|
||||||
data["input"]["mouse"] = {
|
|
||||||
type = "pipe",
|
|
||||||
read = function(amount)
|
|
||||||
return mouse.pop()
|
|
||||||
end,
|
|
||||||
write = function() error("Permission denied") end
|
|
||||||
}
|
|
||||||
|
|
||||||
data["pts"] = newDirectory()
|
|
||||||
|
|
||||||
kernel.devfs = {}
|
|
||||||
kernel.devfs.keyboard = keyboard
|
|
||||||
kernel.devfs.mouse = mouse
|
|
||||||
kernel.devfs.proxy = proxy
|
|
||||||
kernel.devfs.data = data
|
|
||||||
kernel.vfs.virtdisk(proxy)
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
--:Minify:--
|
|
||||||
local kernel = ...
|
|
||||||
|
|
||||||
kernel.processes.keventd = function()
|
|
||||||
while true do
|
|
||||||
local event = {kernel.computer:getMachineEvent()}
|
|
||||||
if event[1] then
|
|
||||||
if event[1] == "key" or event[1] == "keyPressed" or event[1] == "keyReleased" then
|
|
||||||
kernel.devfs.keyboard.push(event)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
--:Minify:--
|
|
||||||
local kernel=...
|
|
||||||
for i,v in ipairs(string.split(kernel.fstab,"\n")) do
|
|
||||||
if v:sub(1,1)=="U" then
|
|
||||||
local id=""
|
|
||||||
for i=3,#v do
|
|
||||||
if v:sub(i,i)==";" then
|
|
||||||
if i==3 then kernel.log("Invalid fstab line... Skipping.","WARN") goto endline end
|
|
||||||
id=v:sub(3,i-1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local path=v:sub(#id+4)
|
|
||||||
if id~="$" then
|
|
||||||
kernel.vfs.mount(id,path)
|
|
||||||
end
|
|
||||||
::endline::
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
--:Minify:--
|
|
||||||
local kernel = ...
|
|
||||||
local ports = {}
|
|
||||||
local signals = {}
|
|
||||||
local ipc = {}
|
|
||||||
|
|
||||||
function ipc.open(port)
|
|
||||||
if not ports[port] then
|
|
||||||
local handle = kernel.newUUID()
|
|
||||||
ports[port] = {owner = kernel.currentProcess.pid, handle = handle, messages = {}}
|
|
||||||
return ports[port].handle
|
|
||||||
end
|
|
||||||
error("Port already opened")
|
|
||||||
end
|
|
||||||
|
|
||||||
function ipc.close(port)
|
|
||||||
if ports[port] then
|
|
||||||
if ports[port].owner == kernel.currentProcess.pid then
|
|
||||||
ports[port] = nil
|
|
||||||
return true
|
|
||||||
else
|
|
||||||
error("Cannot close port you do not own")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
error("Port not opened")
|
|
||||||
end
|
|
||||||
|
|
||||||
function ipc.send(port, message)
|
|
||||||
if ports[port] then
|
|
||||||
table.insert(ports[port].messages, {from = kernel.currentProcess.pid, message = message})
|
|
||||||
if signals[ports[port].owner] then
|
|
||||||
signals[ports[port].owner](port, message)
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
error("Port not opened")
|
|
||||||
end
|
|
||||||
|
|
||||||
function ipc.receive(port)
|
|
||||||
if ports[port] then
|
|
||||||
if #ports[port].messages > 0 then
|
|
||||||
return table.remove(ports[port].messages, 1)
|
|
||||||
else
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
error("Port not opened")
|
|
||||||
end
|
|
||||||
|
|
||||||
function ipc.setSignalHandler(pid, handler)
|
|
||||||
signals[pid] = handler
|
|
||||||
end
|
|
||||||
|
|
||||||
function ipc.clearSignalHandler(pid)
|
|
||||||
signals[pid] = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function ipc.sendSignal(pid, ...)
|
|
||||||
coroutine.resumeWithTimeout(coroutine.create(function(...)
|
|
||||||
if signals[pid] then
|
|
||||||
signals[pid](...)
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end), 100)
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
kernel.ipc = ipc
|
|
||||||
kernel.syscalls["ipc_open"] = ipc.open
|
|
||||||
kernel.syscalls["ipc_close"] = ipc.close
|
|
||||||
kernel.syscalls["ipc_send"] = ipc.send
|
|
||||||
kernel.syscalls["ipc_receive"] = ipc.receive
|
|
||||||
kernel.syscalls["ipc_setSignalHandler"] = ipc.setSignalHandler
|
|
||||||
kernel.syscalls["ipc_clearSignalHandler"] = ipc.clearSignalHandler
|
|
||||||
kernel.syscalls["ipc_sendSignal"] = ipc.sendSignal
|
|
||||||
kernel.log("Loaded IPC module")
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
--:Minify:--
|
|
||||||
local args={...}
|
|
||||||
local kernel=args[1]
|
|
||||||
kernel._G=_G
|
|
||||||
kernel._U=setmetatable({},{
|
|
||||||
__index = kernel._G,
|
|
||||||
__newindex = function(t,k,v)
|
|
||||||
if kernel.config.allowGlobalOverwrites or kernel.allowGlobalOverwrites then
|
|
||||||
rawset(t,k,v)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
error("Attempt to modify global variable '"..k.."'",2)
|
|
||||||
end,
|
|
||||||
__metatable = false
|
|
||||||
})
|
|
||||||
kernel.allowGlobalOverwrites=true
|
|
||||||
kernel._U._G=kernel._U
|
|
||||||
kernel.allowGlobalOverwrites=false
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
--:Minify:--
|
|
||||||
local kernel = ...
|
|
||||||
local pam = {}
|
|
||||||
kernel.pam = pam
|
|
||||||
local loggedIn = {}
|
|
||||||
|
|
||||||
local function getFile(path)
|
|
||||||
local file = kernel.vfs.open(path, "r")
|
|
||||||
if not file then error("Failed to open file: "..path) end
|
|
||||||
local content = kernel.vfs.read(file, 1024000)
|
|
||||||
kernel.vfs.close(file)
|
|
||||||
return content
|
|
||||||
end
|
|
||||||
|
|
||||||
local blake2s = require("crypto.blake2s")
|
|
||||||
if not blake2s then error("Failed to load blake2s") end
|
|
||||||
|
|
||||||
if not kernel.vfs.exists("/etc/pam.d/secret") then
|
|
||||||
local key = ""
|
|
||||||
for i=1, 256 do
|
|
||||||
key=key..string.char(math.random(1,255))
|
|
||||||
end
|
|
||||||
local handle = kernel.vfs.open("/etc/pam.d/secret", "w")
|
|
||||||
kernel.vfs.write(handle, key)
|
|
||||||
kernel.vfs.close(handle)
|
|
||||||
end
|
|
||||||
|
|
||||||
local pepper = getFile("/etc/pam.d/secret")
|
|
||||||
|
|
||||||
function pam.authenticate(username, password)
|
|
||||||
local fpasswd = getFile("/etc/passwd")
|
|
||||||
local fshadow = getFile("/etc/shadow")
|
|
||||||
|
|
||||||
local passwdLines = string.split(fpasswd, "\n")
|
|
||||||
local shadowLines = string.split(fshadow, "\n")
|
|
||||||
|
|
||||||
local passwd = {}
|
|
||||||
local shadow = {}
|
|
||||||
for _, line in ipairs(passwdLines) do
|
|
||||||
local fields = string.split(line, ":")
|
|
||||||
passwd[fields[1]] = fields
|
|
||||||
end
|
|
||||||
for _, line in ipairs(shadowLines) do
|
|
||||||
local fields = string.split(line, ":")
|
|
||||||
shadow[fields[1]] = fields
|
|
||||||
end
|
|
||||||
|
|
||||||
for user, fields in pairs(passwd) do
|
|
||||||
if user == username then
|
|
||||||
local shadowPasswd = string.split(shadow[user][2], "$")
|
|
||||||
local salt = shadowPasswd[2]
|
|
||||||
local hashedPassword = blake2s(password .. salt, pepper)
|
|
||||||
if hashedPassword == shadowPasswd[3] then
|
|
||||||
loggedIn[username] = kernel.newUUID()
|
|
||||||
return loggedIn[username]
|
|
||||||
else
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function pam.authToken(username, token)
|
|
||||||
return loggedIn[username] == token
|
|
||||||
end
|
|
||||||
|
|
||||||
@@ -1,213 +0,0 @@
|
|||||||
--:Minify:--
|
|
||||||
local kernel = ...
|
|
||||||
local tasks = {}
|
|
||||||
local sys = {}
|
|
||||||
local nextpid = 2
|
|
||||||
kernel.exitMain=false
|
|
||||||
|
|
||||||
function sys.spawn(func, name, envars, args, tgid, fshandles)
|
|
||||||
local id = nextpid
|
|
||||||
nextpid = nextpid + 1
|
|
||||||
tasks[tostring(id)] = {
|
|
||||||
coro=coroutine.create(function()
|
|
||||||
local ok, err = xpcall(func, debug.traceback, table.unpack(args or {}))
|
|
||||||
if not ok then
|
|
||||||
tasks[tostring(id)].status="Z"
|
|
||||||
tasks[tostring(id)].exit=tostring(err)
|
|
||||||
else
|
|
||||||
tasks[tostring(id)].status="Z"
|
|
||||||
tasks[tostring(id)].exit=err
|
|
||||||
end
|
|
||||||
end),
|
|
||||||
name=name or "task"..tostring(id),
|
|
||||||
envars=envars or {},
|
|
||||||
args=args or {},
|
|
||||||
status="R",
|
|
||||||
pid=id,
|
|
||||||
tgid=tgid or kernel.currentTask.tgid,
|
|
||||||
user=kernel.user,
|
|
||||||
uid=kernel.uid,
|
|
||||||
fd=fshandles or {},
|
|
||||||
exit="",
|
|
||||||
sleep=0,
|
|
||||||
ivs=0,
|
|
||||||
vs=0,
|
|
||||||
children={},
|
|
||||||
parent=kernel.currentTask,
|
|
||||||
siblings=kernel.currentTask.children,
|
|
||||||
syscallReturn={},
|
|
||||||
cwd=kernel.currentTask.cwd,
|
|
||||||
term=kernel.currentTask.term,
|
|
||||||
timeSlice=0,
|
|
||||||
lastTime=0,
|
|
||||||
totalTime=0,
|
|
||||||
numRuns=0
|
|
||||||
}
|
|
||||||
table.insert(kernel.currentTask.children, tasks[tostring(id)])
|
|
||||||
end
|
|
||||||
|
|
||||||
function sys.sleep(ms)
|
|
||||||
kernel.currentTask.status="S"
|
|
||||||
kernel.currentTask.sleep=kernel.computer:time()+ms
|
|
||||||
coroutine.yield()
|
|
||||||
end
|
|
||||||
|
|
||||||
kernel.syscalls["HPV_spawn"]=sys.spawn
|
|
||||||
kernel.syscalls["HPV_sleep"]=sys.sleep
|
|
||||||
kernel._G.sleep=function(...)coroutine.yield("syscall","HPV_sleep",...)end
|
|
||||||
|
|
||||||
local function reapDeadTasks()
|
|
||||||
for pid, task in pairs(tasks) do
|
|
||||||
if task.status == "Z" and not task.reapTime then
|
|
||||||
task.coro = nil
|
|
||||||
task.ivs = nil
|
|
||||||
task.vs = nil
|
|
||||||
task.args = nil
|
|
||||||
task.envars = nil
|
|
||||||
task.cwd = nil
|
|
||||||
task.term = nil
|
|
||||||
task.numRuns = nil
|
|
||||||
task.totalTime = nil
|
|
||||||
task.lastTime = nil
|
|
||||||
task.timeSlice = nil
|
|
||||||
task.syscallReturn = nil
|
|
||||||
task.sleep = nil
|
|
||||||
for k,v in pairs(task.fd) do
|
|
||||||
kernel.vfs.close(v)
|
|
||||||
end
|
|
||||||
task.fd = nil
|
|
||||||
task.reapTime = kernel.computer:time() + 30000
|
|
||||||
elseif task.reapTime and kernel.computer:time() > task.reapTime then
|
|
||||||
for _,child in ipairs(task.children) do
|
|
||||||
child.parent = tasks["1"]
|
|
||||||
child.siblings = tasks["1"].children
|
|
||||||
table.insert(tasks["1"].children, child)
|
|
||||||
end
|
|
||||||
for i, sibling in ipairs(task.siblings) do
|
|
||||||
if sibling.pid == task.pid then
|
|
||||||
table.remove(task.siblings, i)
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
tasks[pid] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
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()
|
|
||||||
while not kernel.exitMain do
|
|
||||||
local N = 0
|
|
||||||
local Tmin_hit = 0
|
|
||||||
local Tmax_hit = 0
|
|
||||||
local totalTaskTime = 0
|
|
||||||
local taskTimes = {}
|
|
||||||
|
|
||||||
for pid, task in pairs(tasks) do
|
|
||||||
if task.status == "S" then
|
|
||||||
if kernel.computer:time() >= task.sleep then
|
|
||||||
task.status="R"
|
|
||||||
task.sleep=0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if task.status == "R" then
|
|
||||||
kernel.currentTask = task
|
|
||||||
kernel.vfs.cwd = task.cwd
|
|
||||||
kernel.user = task.user
|
|
||||||
kernel.uid = task.uid
|
|
||||||
N = N + 1
|
|
||||||
|
|
||||||
-- assign adaptive time slice
|
|
||||||
task.timeSlice = math.min(Tmax, math.max(Tmin, B / (N ^ alpha)))
|
|
||||||
|
|
||||||
-- measure execution time
|
|
||||||
local startTime = kernel.computer:time()
|
|
||||||
local ret
|
|
||||||
if kernel.config.preempt then
|
|
||||||
ret = {coroutine.resumeWithTimeout(task.coro, task.timeSlice, table.unpack(task.syscallReturn))}
|
|
||||||
else
|
|
||||||
ret = {coroutine.resume(task.coro, table.unpack(task.syscallReturn))}
|
|
||||||
end
|
|
||||||
|
|
||||||
local elapsed = kernel.computer:time() - 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
|
|
||||||
|
|
||||||
-- handle task results
|
|
||||||
if ret[1] == "error" then
|
|
||||||
kernel.log("processHandlerException: "..ret[2])
|
|
||||||
task.status = "Z"
|
|
||||||
task.exit = "processHandlerException: "..ret[2]
|
|
||||||
elseif ret[1] == "timeout" then
|
|
||||||
task.ivs=task.ivs+1
|
|
||||||
task.syscallReturn = {}
|
|
||||||
elseif ret[1] == "success" then
|
|
||||||
task.vs=task.vs+1
|
|
||||||
if ret[2]=="syscall" then
|
|
||||||
if kernel.syscalls[ret[3]] then
|
|
||||||
if kernel.config.debugSyscalls then
|
|
||||||
kernel.log("Task "..task.pid.." invoking syscall: "..ret[3], "DBUG")
|
|
||||||
end
|
|
||||||
local sysret = {xpcall(kernel.syscalls[ret[3]], debug.traceback, table.unpack(ret, 4))}
|
|
||||||
if kernel.config.debugSyscalls then
|
|
||||||
if not sysret[1] then
|
|
||||||
kernel.log("Task "..task.pid.." syscall "..ret[3].." failed: "..tostring(sysret[2]))
|
|
||||||
else
|
|
||||||
kernel.log("Task "..task.pid.." syscall "..ret[3].." completed returning "..tostring(#sysret-1).." values", "DBUG")
|
|
||||||
for i=2,#sysret do
|
|
||||||
kernel.log(" retval["..tostring(i-1).."] = "..tostring(sysret[i]), "DBUG")
|
|
||||||
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(ret[3])}
|
|
||||||
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
|
|
||||||
|
|
||||||
-- clean up dead tasks
|
|
||||||
reapDeadTasks()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
kernel.tasks=tasks
|
|
||||||
kernel.hpv=sys
|
|
||||||
@@ -1,126 +0,0 @@
|
|||||||
--:Minify:--
|
|
||||||
local kernel=...
|
|
||||||
kernel.tty={}
|
|
||||||
|
|
||||||
function kernel.tty.register(tty, ttyo)
|
|
||||||
kernel.tty[tty]=ttyo
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.tty.print(text)
|
|
||||||
local term=kernel.currentTask.term
|
|
||||||
if term and kernel.tty[term] then
|
|
||||||
kernel.tty[term].print(text)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.tty.printInline(text)
|
|
||||||
local term=kernel.currentTask.term
|
|
||||||
if term and kernel.tty[term] then
|
|
||||||
kernel.tty[term].printInline(text)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.tty.size()
|
|
||||||
local term=kernel.currentTask.term
|
|
||||||
if term and kernel.tty[term] then
|
|
||||||
return kernel.tty[term].size()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.tty.setCursorPos(x,y)
|
|
||||||
local term=kernel.currentTask.term
|
|
||||||
if term and kernel.tty[term] then
|
|
||||||
return kernel.tty[term].setCursorPos(x,y)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.tty.getCursorPos()
|
|
||||||
local term=kernel.currentTask.term
|
|
||||||
if term and kernel.tty[term] then
|
|
||||||
return kernel.tty[term].getCursorPos()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.tty.clear()
|
|
||||||
local term=kernel.currentTask.term
|
|
||||||
if term and kernel.tty[term] then
|
|
||||||
return kernel.tty[term].clear()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.tty.setTextColor(color)
|
|
||||||
local term=kernel.currentTask.term
|
|
||||||
if term and kernel.tty[term] then
|
|
||||||
return kernel.tty[term].setTextColor(color)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.tty.setBackgroundColor(color)
|
|
||||||
local term=kernel.currentTask.term
|
|
||||||
if term and kernel.tty[term] then
|
|
||||||
return kernel.tty[term].setBackgroundColor(color)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.tty.scroll(n)
|
|
||||||
local term=kernel.currentTask.term
|
|
||||||
if term and kernel.tty[term] then
|
|
||||||
return kernel.tty[term].scroll(n)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.tty.getTextColor()
|
|
||||||
local term=kernel.currentTask.term
|
|
||||||
if term and kernel.tty[term] and kernel.tty[term].getTextColor then
|
|
||||||
return kernel.tty[term].getTextColor()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.tty.getBackgroundColor()
|
|
||||||
local term=kernel.currentTask.term
|
|
||||||
if term and kernel.tty[term] and kernel.tty[term].getBackgroundColor then
|
|
||||||
return kernel.tty[term].getBackgroundColor()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.tty.bind(ttyid)
|
|
||||||
if not ttyid then
|
|
||||||
return false, "No TTY ID specified"
|
|
||||||
end
|
|
||||||
if not kernel.tty[ttyid] then
|
|
||||||
return false, "TTY "..tostring(ttyid).." not registered"
|
|
||||||
end
|
|
||||||
kernel.currentTask.term=ttyid
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.tty.unbind()
|
|
||||||
kernel.currentTask.term=false
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.tty.isBound()
|
|
||||||
return kernel.currentTask.term ~= nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.tty.getBoundTTY()
|
|
||||||
return kernel.currentTask.term
|
|
||||||
end
|
|
||||||
|
|
||||||
kernel.syscalls["TTY_print"]=kernel.tty.print
|
|
||||||
kernel.syscalls["TTY_printInline"]=kernel.tty.printInline
|
|
||||||
kernel.syscalls["TTY_size"]=kernel.tty.size
|
|
||||||
kernel.syscalls["TTY_setCursorPos"]=kernel.tty.setCursorPos
|
|
||||||
kernel.syscalls["TTY_getCursorPos"]=kernel.tty.getCursorPos
|
|
||||||
kernel.syscalls["TTY_clear"]=kernel.tty.clear
|
|
||||||
kernel.syscalls["TTY_setTextColor"]=kernel.tty.setTextColor
|
|
||||||
kernel.syscalls["TTY_setBackgroundColor"]=kernel.tty.setBackgroundColor
|
|
||||||
kernel.syscalls["TTY_scroll"]=kernel.tty.scroll
|
|
||||||
kernel.syscalls["TTY_getTextColor"]=kernel.tty.getTextColor
|
|
||||||
kernel.syscalls["TTY_getBackgroundColor"]=kernel.tty.getBackgroundColor
|
|
||||||
kernel.syscalls["TTY_bind"]=kernel.tty.bind
|
|
||||||
kernel.syscalls["TTY_unbind"]=kernel.tty.unbind
|
|
||||||
kernel.syscalls["TTY_isBound"]=kernel.tty.isBound
|
|
||||||
kernel.syscalls["TTY_getBoundTTY"]=kernel.tty.getBoundTTY
|
|
||||||
|
|
||||||
kernel.log("TTY module loaded attempting to register console tty")
|
|
||||||
kernel.status="init"
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
--:Minify:--
|
|
||||||
local kernel=...
|
|
||||||
function print(...)
|
|
||||||
coroutine.yield()
|
|
||||||
local args={...}
|
|
||||||
local output=""
|
|
||||||
for i=1,#args do
|
|
||||||
output=output..tostring(args[i]).."\t"
|
|
||||||
end
|
|
||||||
output=output:sub(1,-2)
|
|
||||||
kernel.tty.print(output)
|
|
||||||
end
|
|
||||||
|
|
||||||
function printf(fmt, ...)
|
|
||||||
coroutine.yield()
|
|
||||||
local output=string.format(fmt,...)
|
|
||||||
kernel.tty.print(output)
|
|
||||||
end
|
|
||||||
|
|
||||||
function printInline(...)
|
|
||||||
coroutine.yield()
|
|
||||||
local args={...}
|
|
||||||
local output=""
|
|
||||||
for i=1,#args do
|
|
||||||
output=output..tostring(args[i]).."\t"
|
|
||||||
end
|
|
||||||
output=output:sub(1,-2)
|
|
||||||
kernel.tty.printInline(output)
|
|
||||||
end
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
--:Minify:--
|
|
||||||
local kernel = ...
|
|
||||||
kernel.log("Loading init system...")
|
|
||||||
kernel.log("InitPath: "..kernel.config.initPath)
|
|
||||||
local handle = kernel.vfs.open(kernel.config.initPath, "r")
|
|
||||||
local data = kernel.vfs.read(handle, 1024 * 1024 * 4)
|
|
||||||
kernel.vfs.close(handle)
|
|
||||||
|
|
||||||
local initFunc, err = load(data, "@sysinit")
|
|
||||||
if not initFunc then
|
|
||||||
error("Failed to load init system: "..err)
|
|
||||||
end
|
|
||||||
|
|
||||||
kernel.tasks["1"] = {
|
|
||||||
coro=coroutine.create(function()
|
|
||||||
local ok, err = xpcall(initFunc, debug.traceback, kernel)
|
|
||||||
if not ok then
|
|
||||||
kernel.panic("Init system crashed: "..tostring(err))
|
|
||||||
else
|
|
||||||
kernel.panic("Init system exited: "..tostring(err))
|
|
||||||
end
|
|
||||||
end),
|
|
||||||
name="sysinit",
|
|
||||||
status="R",
|
|
||||||
pid=1,
|
|
||||||
tgid=1,
|
|
||||||
user="root",
|
|
||||||
uid=0,
|
|
||||||
fd={},
|
|
||||||
exit="",
|
|
||||||
sleep=0,
|
|
||||||
ivs=0,
|
|
||||||
vs=0,
|
|
||||||
parent=kernel.kernelTask,
|
|
||||||
siblings=kernel.kernelTask.children,
|
|
||||||
children={},
|
|
||||||
syscallReturn={},
|
|
||||||
cwd="/",
|
|
||||||
timeSlice=0,
|
|
||||||
lastTime=0,
|
|
||||||
totalTime=0,
|
|
||||||
numRuns=0
|
|
||||||
}
|
|
||||||
kernel.log("created init task with PID 1")
|
|
||||||
kernel.log("Initializing init system...")
|
|
||||||
4
Src/Hyperion-kernel/boot/fstab
Normal file
4
Src/Hyperion-kernel/boot/fstab
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
U $;/
|
||||||
|
U devfs0000;/dev/
|
||||||
|
U tmpfs0000;/tmp/
|
||||||
|
U procfs0000;/proc/
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
--:Minify:--
|
-- :Minify:--
|
||||||
local fs = {}
|
local fs = {}
|
||||||
local disks = {}
|
local disks = {}
|
||||||
local mounts = {}
|
local mounts = {}
|
||||||
@@ -15,39 +15,42 @@ local function resolve(path)
|
|||||||
local newPath = path:sub(#mountPoint + 1)
|
local newPath = path:sub(#mountPoint + 1)
|
||||||
return disks[mounts[mountPoint]], newPath
|
return disks[mounts[mountPoint]], newPath
|
||||||
end
|
end
|
||||||
---------------------------------------------------------
|
|
||||||
|
|
||||||
function fs.update(initdisks)
|
function fs.update(initdisks)
|
||||||
disks = {}
|
disks = {}
|
||||||
for k, v in initdisks.list() do
|
for k, v in initdisks.list() do disks[k] = v end
|
||||||
disks[k] = v
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.exists(path)
|
function fs.exists(path)
|
||||||
local disk, newPath = resolve(path)
|
local disk, newPath = resolve(path)
|
||||||
return disk:directoryExists(newPath) or disk:fileExists(newPath)
|
return disk:directoryExists(newPath) or disk:fileExists(newPath)
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.isFile(path)
|
function fs.isFile(path)
|
||||||
local disk, newPath = resolve(path)
|
local disk, newPath = resolve(path)
|
||||||
return disk:fileExists(newPath)
|
return disk:fileExists(newPath)
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.isDir(path)
|
function fs.isDir(path)
|
||||||
local disk, newPath = resolve(path)
|
local disk, newPath = resolve(path)
|
||||||
return disk:directoryExists(newPath)
|
return disk:directoryExists(newPath)
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.list(path)
|
function fs.list(path)
|
||||||
local disk, newPath = resolve(path)
|
local disk, newPath = resolve(path)
|
||||||
return disk:list(newPath)
|
return disk:list(newPath)
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.makeDir(path)
|
function fs.makeDir(path)
|
||||||
local disk, newPath = resolve(path)
|
local disk, newPath = resolve(path)
|
||||||
return disk:makeDirectory(newPath)
|
return disk:makeDirectory(newPath)
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.remove(path)
|
function fs.remove(path)
|
||||||
local disk, newPath = resolve(path)
|
local disk, newPath = resolve(path)
|
||||||
return disk:remove(newPath)
|
return disk:remove(newPath)
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.readAllText(path)
|
function fs.readAllText(path)
|
||||||
local disk, newPath = resolve(path)
|
local disk, newPath = resolve(path)
|
||||||
local handle = disk:open(newPath, "r")
|
local handle = disk:open(newPath, "r")
|
||||||
@@ -56,23 +59,26 @@ function fs.readAllText(path)
|
|||||||
handle.close()
|
handle.close()
|
||||||
return content
|
return content
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.writeAllText(path, text)
|
function fs.writeAllText(path, text)
|
||||||
local disk, newPath = resolve(path)
|
local disk, newPath = resolve(path)
|
||||||
local handle = disk:open(newPath, "w")
|
local handle = disk:open(newPath, "w")
|
||||||
handle.write(text)
|
handle.write(text)
|
||||||
handle.close()
|
handle.close()
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.appendAllText(path, text)
|
function fs.appendAllText(path, text)
|
||||||
local disk, newPath = resolve(path)
|
local disk, newPath = resolve(path)
|
||||||
local handle = disk:open(newPath, "a")
|
local handle = disk:open(newPath, "a")
|
||||||
handle.write(text)
|
handle.write(text)
|
||||||
handle.close()
|
handle.close()
|
||||||
end
|
end
|
||||||
function fs.load(path)
|
|
||||||
return load(fs.readAllText(path), path)
|
function fs.load(path) return load(fs.readAllText(path), path) end
|
||||||
end
|
|
||||||
function fs.mount(disk, mountPoint)
|
function fs.mount(disk, mountPoint)
|
||||||
if not disks[disk] then return end
|
if not disks[disk] then return end
|
||||||
mounts[mountPoint] = disk
|
mounts[mountPoint] = disk
|
||||||
end
|
end
|
||||||
|
|
||||||
return fs
|
return fs
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
--:Minify:--
|
--:Minify:--
|
||||||
local args = {...}
|
local EFI=...
|
||||||
local apis = args[1]
|
EFI.beep(440, 500)
|
||||||
local disks = args[2]
|
local screen=EFI.screenCtl
|
||||||
local arch = args[3]
|
local ifs=EFI.initfs
|
||||||
local screen = args[5]
|
local disks=EFI.disks
|
||||||
local computer = args[6]
|
local arch=EFI.architecture
|
||||||
local ifs = args[7]
|
|
||||||
local LOG_Text = ""
|
|
||||||
local kernel = {}
|
local kernel = {}
|
||||||
|
kernel.LOG_Text=""
|
||||||
|
kernel.version="HyperionOS V1.2.4"
|
||||||
kernel.process = "Kernel"
|
kernel.process = "Kernel"
|
||||||
kernel.user = "root"
|
kernel.users={[0]="root",[1]="User"}
|
||||||
kernel.group = "root"
|
kernel.hostname = "hyperion"
|
||||||
kernel.groups = {0}
|
kernel.groups = {}
|
||||||
kernel.uid = 0
|
kernel.uid = 0
|
||||||
kernel.gid = 0
|
kernel.gid = 0
|
||||||
kernel.status = "start"
|
kernel.status = "start"
|
||||||
@@ -24,45 +24,53 @@ kernel.sleep=sleep
|
|||||||
_G.sleep=nil
|
_G.sleep=nil
|
||||||
local windowsExp = false
|
local windowsExp = false
|
||||||
|
|
||||||
function kernel.log(msg, level)
|
function kernel.log(msg, level, c)
|
||||||
LOG_Text = LOG_Text..tostring(computer:time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n"
|
c=c or 0x6D6D6D
|
||||||
|
kernel.LOG_Text = kernel.LOG_Text..tostring(EFI:date()).." "..kernel.users[kernel.uid].." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n"
|
||||||
if kernel.status == "start" then
|
if kernel.status == "start" then
|
||||||
screen:print(tostring(computer:time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg)
|
screen:setTextColor(c)
|
||||||
elseif kernel.status == "init" then
|
screen:print(tostring(EFI:date()).." "..kernel.users[kernel.uid].." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg)
|
||||||
|
elseif kernel.status == "term" then
|
||||||
kernel.standbyTask=kernel.currentTask
|
kernel.standbyTask=kernel.currentTask
|
||||||
kernel.currentTask=kernel.kernelTask
|
kernel.currentTask=kernel.kernelTask
|
||||||
kernel.tty.print(tostring(computer:time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg)
|
local file=kernel.vfs.open("/dev/console", "w")
|
||||||
|
kernel.vfs.devctl(file,"sfgc",c)
|
||||||
|
kernel.vfs.write(file,tostring(EFI:date()).." "..kernel.users[kernel.uid].." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n")
|
||||||
|
kernel.vfs.close(file)
|
||||||
kernel.currentTask=kernel.standbyTask
|
kernel.currentTask=kernel.standbyTask
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function kernel.PANIC(msg)
|
function kernel.PANIC(msg)
|
||||||
if kernel.status~="Panic" then
|
if kernel.status~="Panic" then
|
||||||
kernel.log("PANIC: "..msg, "PANIC")
|
kernel.log("PANIC: "..msg, "PANIC", 0xFF0000)
|
||||||
pcall(kernel["saveLog"])
|
pcall(kernel["saveLog"])
|
||||||
kernel.status="Panic"
|
kernel.status="Panic"
|
||||||
kernel.reason=msg
|
kernel.reason=msg
|
||||||
screen:setTextColor(2)
|
screen:enable()
|
||||||
screen:setBackgroundColor(0)
|
screen:setTextColor(0xFF0000)
|
||||||
|
screen:setBackgroundColor(0x000000)
|
||||||
screen:clear()
|
screen:clear()
|
||||||
screen:setCursorPos(1,1)
|
screen:setCursorPos(1,1)
|
||||||
screen:print(LOG_Text)
|
screen:print(kernel.LOG_Text)
|
||||||
screen:print("KERNEL PANIC!\n"..msg.."\nSystem halted.")
|
screen:print("KERNEL PANIC!\n"..msg.."\nSystem halted.")
|
||||||
screen:print("Press any key to continue...")
|
screen:print("Press any key to continue...")
|
||||||
|
kernel.exitMain = true
|
||||||
end
|
end
|
||||||
while true do
|
while true do
|
||||||
local event={computer:getMachineEvent()}
|
local event={EFI:getMachineEvent()}
|
||||||
if event[1]=="keyPressed" then
|
if event[1]=="keyPressed" then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
computer:reboot()
|
EFI.reboot=true
|
||||||
|
error("KERNEL PANIC")
|
||||||
end
|
end
|
||||||
kernel.panic=kernel.PANIC
|
kernel.panic=kernel.PANIC
|
||||||
|
|
||||||
if windowsExp then
|
if windowsExp then
|
||||||
screen:setTextColor(1)
|
screen:setTextColor(0xFFFFFF)
|
||||||
screen:setBackgroundColor(4)
|
screen:setBackgroundColor(0x0000FF)
|
||||||
screen:clear()
|
screen:clear()
|
||||||
local w,h = screen:getSize()
|
local w,h = screen:getSize()
|
||||||
screen:setCursorPos(3,5)
|
screen:setCursorPos(3,5)
|
||||||
@@ -108,8 +116,9 @@ local split = function(str, delim, maxResultCountOrNil)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if not ifs.isFile("/boot/boot.cfg") then
|
if not ifs.isFile("/boot/boot.cfg") then
|
||||||
kernel.log("boot.cfg missing or corrupted!, Attempting to write recovery boot.cfg", "ERROR")
|
kernel.log("First boot detected writing boot.cfg", "INFO", 0x00FF00)
|
||||||
ifs.writeAllText("/boot/boot.cfg",ifs.readAllText("/boot/safeboot.cfg"))
|
ifs.writeAllText("/boot/boot.cfg",ifs.readAllText("/boot/safeboot.cfg"))
|
||||||
|
kernel.firstBoot=true
|
||||||
end
|
end
|
||||||
|
|
||||||
local initCfgFunc, err = load(ifs.readAllText("/boot/boot.cfg"), "@boot.cfg")
|
local initCfgFunc, err = load(ifs.readAllText("/boot/boot.cfg"), "@boot.cfg")
|
||||||
@@ -117,39 +126,47 @@ if not initCfgFunc then
|
|||||||
kernel.PANIC("Failed to load /boot/boot.cfg: "..tostring(err))
|
kernel.PANIC("Failed to load /boot/boot.cfg: "..tostring(err))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@diagnostic disable-next-line: param-type-mismatch
|
||||||
local initCfgStatus, config = pcall(initCfgFunc)
|
local initCfgStatus, config = pcall(initCfgFunc)
|
||||||
if not initCfgStatus then
|
if not initCfgStatus then
|
||||||
kernel.PANIC("Error in /boot/boot.cfg: "..tostring(config))
|
kernel.PANIC("Error in /boot/boot.cfg: "..tostring(config))
|
||||||
end
|
end
|
||||||
kernel.config = config
|
kernel.config = config
|
||||||
|
|
||||||
|
local skip=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" 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
|
||||||
if i==3 then kernel.log("Invalid fstab line... Skipping.","WARN") goto endline end
|
if i==3 then kernel.log("Invalid fstab line... Skipping.","WARN", 0xFF8800) skip = true break end
|
||||||
id=v:sub(3,i-1)
|
id=v:sub(3,i-1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local path=v:sub(#id+4)
|
if not skip then
|
||||||
ifs.mount(id,path)
|
local path=v:sub(#id+4)
|
||||||
::endline::
|
ifs.mount(id,path)
|
||||||
|
else
|
||||||
|
skip=false
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
kernel.log("Disks initialized")
|
kernel.log("Disks initialized")
|
||||||
|
|
||||||
function kernel.saveLog()
|
function kernel.saveLog()
|
||||||
ifs.writeAllText("/var/log/syslog.log", LOG_Text)
|
if kernel.status=="running" then
|
||||||
|
local file = kernel.vfs.open("/var/log/syslog.log", "w")
|
||||||
|
kernel.vfs.write(file, kernel.LOG_Text)
|
||||||
|
kernel.vfs.close(file)
|
||||||
|
else
|
||||||
|
ifs.writeAllText("/var/log/syslog.log", kernel.LOG_Text)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
ifs.remove("/tmp")
|
|
||||||
ifs.makeDir("/tmp")
|
|
||||||
|
|
||||||
function kernel.newFifo()
|
function kernel.newFifo()
|
||||||
local fifo = {}
|
local fifo = {}
|
||||||
fifo.push=function(data)
|
fifo.push=function(data)
|
||||||
table.insert(data)
|
table.insert(fifo, data)
|
||||||
end
|
end
|
||||||
fifo.pop=function()
|
fifo.pop=function()
|
||||||
return table.remove(fifo,1)
|
return table.remove(fifo,1)
|
||||||
@@ -181,15 +198,22 @@ end
|
|||||||
|
|
||||||
kernel.log("Gathering modules")
|
kernel.log("Gathering modules")
|
||||||
for _, i in ipairs(ifs.list("/lib/modules")) do
|
for _, i in ipairs(ifs.list("/lib/modules")) do
|
||||||
for _,v in ipairs(ifs.list("/lib/modules/"..i)) do
|
local modlist = ifs.list("/lib/modules/"..i)
|
||||||
local prior=tonumber(v:sub(1,2))
|
if not modlist then
|
||||||
modules[prior+1][#modules[prior+1]+1]="/lib/modules/"..i.."/"..v
|
kernel.log("WARNING: could not list /lib/modules/"..i.." (skipping)", "WARN", 0xFF8800)
|
||||||
|
else
|
||||||
|
for _,v in ipairs(modlist) do
|
||||||
|
local prior=tonumber(v:sub(1,2))
|
||||||
|
if prior then
|
||||||
|
modules[prior+1][#modules[prior+1]+1]="/lib/modules/"..i.."/"..v
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
kernel.ifs=ifs
|
kernel.ifs=ifs
|
||||||
kernel.apis=apis
|
kernel.apis=EFI.firmware
|
||||||
kernel.computer=computer
|
kernel.EFI=EFI
|
||||||
kernel.arch=arch
|
kernel.arch=arch
|
||||||
kernel.initdisks=disks
|
kernel.initdisks=disks
|
||||||
kernel.screen=screen
|
kernel.screen=screen
|
||||||
@@ -201,7 +225,6 @@ kernel.kernelTask = {
|
|||||||
status="R",
|
status="R",
|
||||||
pid=0,
|
pid=0,
|
||||||
tgid=0,
|
tgid=0,
|
||||||
user="root",
|
|
||||||
uid=0,
|
uid=0,
|
||||||
fd={},
|
fd={},
|
||||||
exit="",
|
exit="",
|
||||||
@@ -218,26 +241,61 @@ kernel.kernelTask = {
|
|||||||
}
|
}
|
||||||
kernel.currentTask = kernel.kernelTask
|
kernel.currentTask = kernel.kernelTask
|
||||||
|
|
||||||
kernel.syscalls["OS_time"]=function() return kernel.computer:time() end
|
function kernel.shutdown()
|
||||||
kernel.syscalls["OS_log"]=kernel.log
|
kernel.exitMain=true
|
||||||
|
kernel.status="shutdown"
|
||||||
|
end
|
||||||
|
|
||||||
|
function kernel.reboot()
|
||||||
|
kernel.exitMain=true
|
||||||
|
kernel.status="reboot"
|
||||||
|
end
|
||||||
|
|
||||||
|
kernel.syscalls["time"]=function() return kernel.EFI:getEpochMs() end
|
||||||
|
kernel.syscalls["date"]=function() return kernel.EFI:date() end
|
||||||
|
kernel.syscalls["log"]=kernel.log
|
||||||
|
kernel.syscalls["getUptime"]=function() return kernel.EFI:getUptime() end
|
||||||
|
kernel.syscalls["getUsername"]=function(uid) return kernel.users[uid or kernel.uid] end
|
||||||
|
kernel.syscalls["getHostname"]=function() return kernel.hostname end
|
||||||
|
kernel.syscalls["getHost"]=function() return kernel.apis._HOST end
|
||||||
|
kernel.syscalls["version"]=function() return kernel.version end
|
||||||
|
kernel.syscalls["setHostname"]=function(name) if kernel.uid~=0 then error("Permission denied") end kernel.hostname=name end
|
||||||
|
kernel.syscalls["arch"]=function() return arch end
|
||||||
|
kernel.syscalls["sysdump"]=function()
|
||||||
|
local rv={}
|
||||||
|
for i,v in pairs(kernel.syscalls) do
|
||||||
|
rv[#rv+1] = i
|
||||||
|
end
|
||||||
|
return rv
|
||||||
|
end
|
||||||
|
kernel.syscalls["reboot"]=kernel.reboot
|
||||||
|
kernel.syscalls["shutdown"]=kernel.shutdown
|
||||||
|
|
||||||
kernel.log("Running modules")
|
kernel.log("Running modules")
|
||||||
for _,p in ipairs(modules) do
|
for _,p in ipairs(modules) do
|
||||||
for _,v in ipairs(p) do
|
for _,v in ipairs(p) do
|
||||||
|
if kernel.config.showModLoad then kernel.log("Loading module "..v, "DBUG", 0x00FFFF) end
|
||||||
local code=ifs.readAllText(v)
|
local code=ifs.readAllText(v)
|
||||||
if not code then
|
if not code then
|
||||||
kernel.log("ModuReadErr: "..v, "WARN")
|
kernel.panic("Failed to read module "..v)
|
||||||
goto skip
|
|
||||||
end
|
end
|
||||||
local func,err=load(code,"@"..v)
|
local func,err=load(code,"@"..v)
|
||||||
if not func then kernel.panic("ModuLoadErr: "..tostring(err)) goto skip 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
|
||||||
::skip::
|
if kernel.config.showModLoad then kernel.log("Loaded module "..v, "DBUG", 0x00FFFF) end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
kernel.log("Kernel initialized successfully.")
|
kernel.log("Kernel initialized successfully.")
|
||||||
--kernel.status="running"
|
kernel.saveLog()
|
||||||
|
kernel.status="running"
|
||||||
|
screen:disable()
|
||||||
kernel.main()
|
kernel.main()
|
||||||
kernel.PANIC("Execution complete")
|
if kernel.status=="panic" then
|
||||||
|
kernel.panic(kernel.reason)
|
||||||
|
end
|
||||||
|
if kernel.status=="reboot" then
|
||||||
|
EFI.reboot=true
|
||||||
|
return true
|
||||||
|
end
|
||||||
@@ -4,8 +4,9 @@
|
|||||||
-- This file is auto-generated during the build process.
|
-- This file is auto-generated during the build process.
|
||||||
-- DEFAULT BOOT CONFIGURATION FILE
|
-- DEFAULT BOOT CONFIGURATION FILE
|
||||||
return {
|
return {
|
||||||
initPath = "/sbin/init.lua",
|
initPath = "/sbin/init",
|
||||||
maxOpenFiles = 128,
|
maxOpenFiles = 128,
|
||||||
maxFilesPerTask = 16,
|
maxFilesPerTask = 16,
|
||||||
preempt=true
|
preempt=true,
|
||||||
|
logTaskExit=true
|
||||||
}
|
}
|
||||||
1
Src/Hyperion-kernel/etc/passwd
Normal file
1
Src/Hyperion-kernel/etc/passwd
Normal file
@@ -0,0 +1 @@
|
|||||||
|
0:0:root:/root:/bin/hysh
|
||||||
258
Src/Hyperion-kernel/lib/modules/hyperion/01_stdlib.kmod
Normal file
258
Src/Hyperion-kernel/lib/modules/hyperion/01_stdlib.kmod
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
--:Minify:--
|
||||||
|
--- @diagnostic disable: duplicate-set-field
|
||||||
|
local kernel = ...
|
||||||
|
kernel.allowGlobalOverwrites = true
|
||||||
|
|
||||||
|
function string.hasSuffix(str, suffix)
|
||||||
|
return string.sub(str, #suffix + 1) == suffix
|
||||||
|
end
|
||||||
|
|
||||||
|
function string.hasPrefix(str, prefix)
|
||||||
|
return string.sub(str, 1, #prefix) == prefix
|
||||||
|
end
|
||||||
|
|
||||||
|
function string.getSuffix(str, prefix) return string.sub(str, #prefix + 1) end
|
||||||
|
|
||||||
|
function string.getPrefix(str, suffix) return string.sub(str, 1, #suffix) end
|
||||||
|
|
||||||
|
function string.join(str, ...) return table.concat(table.pack(str, ...)) end
|
||||||
|
|
||||||
|
function string.delim(str, ...) return table.concat(table.pack(...), str) end
|
||||||
|
|
||||||
|
function string.split(str, delim, maxResultCountOrNil)
|
||||||
|
assert(#delim == 1, "only delim len 1 supported for now")
|
||||||
|
if not str then return false end
|
||||||
|
maxResultCountOrNil = (maxResultCountOrNil or 0) - 1
|
||||||
|
local rv = {}
|
||||||
|
local buf = ""
|
||||||
|
for i = 1, #str do
|
||||||
|
local c = string.sub(str, i, i)
|
||||||
|
if #rv ~= maxResultCountOrNil and c == delim then
|
||||||
|
table.insert(rv, buf)
|
||||||
|
buf = ""
|
||||||
|
else
|
||||||
|
buf = buf .. c
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.insert(rv, buf)
|
||||||
|
return rv
|
||||||
|
end
|
||||||
|
|
||||||
|
function table.deepcopy(orig, copies)
|
||||||
|
copies = copies or {}
|
||||||
|
|
||||||
|
if type(orig) ~= 'table' then
|
||||||
|
return orig
|
||||||
|
elseif copies[orig] then
|
||||||
|
return copies[orig]
|
||||||
|
end
|
||||||
|
|
||||||
|
local copy = {}
|
||||||
|
copies[orig] = copy
|
||||||
|
|
||||||
|
for k, v in next, orig, nil do
|
||||||
|
local copied_key = table.deepcopy(k, copies)
|
||||||
|
local copied_val = table.deepcopy(v, copies)
|
||||||
|
copy[copied_key] = copied_val
|
||||||
|
end
|
||||||
|
|
||||||
|
return copy
|
||||||
|
end
|
||||||
|
|
||||||
|
function table.hasKey(tabl, query)
|
||||||
|
for i, v in pairs(tabl) do if i == query then return v end end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function table.hasVal(tabl, query)
|
||||||
|
for i, v in pairs(tabl) do if v == query then return i end end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local function serialize(tbl, seen)
|
||||||
|
seen = seen or {}
|
||||||
|
|
||||||
|
if seen[tbl] then return '"[Circular Reference]"' end
|
||||||
|
|
||||||
|
seen[tbl] = true
|
||||||
|
|
||||||
|
local output = "{"
|
||||||
|
local first = true
|
||||||
|
|
||||||
|
for i, v in pairs(tbl) do
|
||||||
|
if not first then output = output .. "," end
|
||||||
|
first = false
|
||||||
|
|
||||||
|
if type(i) == "string" then
|
||||||
|
output = output .. "[\"" .. i .. "\"]="
|
||||||
|
elseif type(i) == "number" then
|
||||||
|
output = output .. "[" .. tostring(i) .. "]="
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(v) == "table" then
|
||||||
|
output = output .. serialize(v, seen)
|
||||||
|
elseif type(v) == "string" then
|
||||||
|
output = output .. "[=[" .. v .. "]=]"
|
||||||
|
elseif type(v) == "number" or type(v) == "boolean" then
|
||||||
|
output = output .. tostring(v)
|
||||||
|
elseif type(v) == "function" then
|
||||||
|
output = output .. "\"" .. tostring(v) .. "\""
|
||||||
|
elseif type(v) == "thread" then
|
||||||
|
output = output .. "\"" .. tostring(v) .. "\""
|
||||||
|
else
|
||||||
|
error("serialization of type \"" .. type(v) .. "\" is not supported")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
seen[tbl] = nil
|
||||||
|
|
||||||
|
output = output .. "}"
|
||||||
|
return output
|
||||||
|
end
|
||||||
|
|
||||||
|
local oldtype = type
|
||||||
|
local oldgetmetatable = getmetatable
|
||||||
|
function type(object, trueType)
|
||||||
|
if trueType then return oldtype(object) end
|
||||||
|
if oldtype(object) ~= "table" then
|
||||||
|
return oldtype(object)
|
||||||
|
else
|
||||||
|
if oldtype(oldgetmetatable(object)) == "table" then
|
||||||
|
local metatable = oldgetmetatable(object)
|
||||||
|
---@diagnostic disable-next-line: need-check-nil
|
||||||
|
if metatable.__type then return metatable.__type end
|
||||||
|
else
|
||||||
|
return "table"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function getmetatable(object)
|
||||||
|
if oldtype(object) ~= "table" then return end
|
||||||
|
if oldtype(oldgetmetatable(object)) == "table" then
|
||||||
|
if oldgetmetatable(object).__isuserdata then
|
||||||
|
if oldtype(oldgetmetatable(object).__usermeta) == "function" then
|
||||||
|
return oldgetmetatable(object).__usermeta()
|
||||||
|
else
|
||||||
|
return oldgetmetatable(object).__usermeta
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return oldgetmetatable(object)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return oldgetmetatable(object)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function isEqualToAny(a, ...)
|
||||||
|
local args = {...}
|
||||||
|
for i = 0, #args do if a == args[i] then return true end end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function isEqualToAll(a, ...)
|
||||||
|
local args = {...}
|
||||||
|
for i = 0, #args do if a ~= args[i] then return false end end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function table.keys(t)
|
||||||
|
local a = {}
|
||||||
|
for n in pairs(t) do table.insert(a, n) end
|
||||||
|
return a
|
||||||
|
end
|
||||||
|
|
||||||
|
function table.values(t)
|
||||||
|
local a = {}
|
||||||
|
for _, n in pairs(t) do table.insert(a, n) end
|
||||||
|
return a
|
||||||
|
end
|
||||||
|
|
||||||
|
function table.indexOf(t, value)
|
||||||
|
for i, v in ipairs(t) do if v == value then return i end end
|
||||||
|
return -1
|
||||||
|
end
|
||||||
|
|
||||||
|
function table.merge(...)
|
||||||
|
local args={...}
|
||||||
|
local out = {}
|
||||||
|
local outi = {}
|
||||||
|
|
||||||
|
for _,t in ipairs(args) do
|
||||||
|
for i,v in pairs(t) do
|
||||||
|
out[i]=v
|
||||||
|
end
|
||||||
|
for i,v in ipairs(t) do
|
||||||
|
outi[#outi+1]=v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for i,v in ipairs(outi) do
|
||||||
|
out[i]=v
|
||||||
|
end
|
||||||
|
|
||||||
|
return out
|
||||||
|
end
|
||||||
|
|
||||||
|
function string.replace(s, target, repl)
|
||||||
|
local result = {}
|
||||||
|
local i = 1
|
||||||
|
local n = #s
|
||||||
|
local t_len = #target
|
||||||
|
|
||||||
|
while i <= n do
|
||||||
|
local match = true
|
||||||
|
if i + t_len - 1 <= n then
|
||||||
|
for j = 1, t_len do
|
||||||
|
if s:sub(i + j - 1, i + j - 1) ~= target:sub(j, j) then
|
||||||
|
match = false
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
match = false
|
||||||
|
end
|
||||||
|
|
||||||
|
if match then
|
||||||
|
table.insert(result, repl)
|
||||||
|
i = i + t_len
|
||||||
|
else
|
||||||
|
table.insert(result, s:sub(i, i))
|
||||||
|
i = i + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return table.concat(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
function toHex(num)
|
||||||
|
return string.format("%X", num)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function makeSyscallProxy()
|
||||||
|
local backing = {}
|
||||||
|
return setmetatable(backing, {
|
||||||
|
__index = function(self, name)
|
||||||
|
local raw = rawget(self, name)
|
||||||
|
if raw ~= nil then return raw end
|
||||||
|
return function(...)
|
||||||
|
local res = table.pack(coroutine.yield("syscall", name, ...))
|
||||||
|
if res[1] then
|
||||||
|
return table.unpack(res, 2, res.n)
|
||||||
|
else
|
||||||
|
error(res[2], 2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
__newindex = function(self, k, v)
|
||||||
|
rawset(self, k, v)
|
||||||
|
end,
|
||||||
|
__metatable=false
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
syscall = makeSyscallProxy()
|
||||||
|
|
||||||
|
_makeSyscallProxy = makeSyscallProxy
|
||||||
|
|
||||||
|
table.serialize = serialize
|
||||||
1119
Src/Hyperion-kernel/lib/modules/hyperion/10_vfs.kmod
Normal file
1119
Src/Hyperion-kernel/lib/modules/hyperion/10_vfs.kmod
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user