Compare commits
114 Commits
6e363a688e
...
1.2.3
| Author | SHA1 | Date | |
|---|---|---|---|
| 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")
|
||||
@@ -1,40 +0,0 @@
|
||||
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
|
||||
}
|
||||
|
||||
for i,v in pairs(_G) do
|
||||
if not lua[i] or lua[i]==nil then
|
||||
apis[i]=v
|
||||
_G[i]=nil
|
||||
end
|
||||
end
|
||||
@@ -1,18 +0,0 @@
|
||||
checkArg=nil
|
||||
local oldcomputer=computer
|
||||
_G.computer=nil
|
||||
local os=os
|
||||
_G.os=nil
|
||||
|
||||
function component.wrap(address)
|
||||
local methods=oldcomponent.methods(address)
|
||||
local object={}
|
||||
for _,method in ipairs(methods) do
|
||||
object[method]=function(_,...)
|
||||
return oldcomponent.invoke(address,method,...)
|
||||
end
|
||||
end
|
||||
return object
|
||||
end
|
||||
|
||||
local
|
||||
@@ -1,11 +0,0 @@
|
||||
-- DO NOT EDIT THIS FILE IF YOU DO NOT KNOW WHAT YOU ARE DOING!
|
||||
-- DOING SO MAY RENDER YOUR SYSTEM UNBOOTABLE!
|
||||
|
||||
-- This file is auto-generated during the build process.
|
||||
-- RECOVERY BOOT CONFIGURATION FILE
|
||||
return {
|
||||
initPath = "/sbin/init.lua",
|
||||
maxOpenFiles = 128,
|
||||
maxFilesPerTask = 16,
|
||||
preempt=true
|
||||
}
|
||||
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 +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=...local debug=debug;a._G.debug={getinfo=debug.getinfo,traceback=debug.traceback}
|
||||
@@ -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...")
|
||||
File diff suppressed because one or more lines are too long
@@ -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
|
||||
|
||||
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,9 +0,0 @@
|
||||
local deflate=require("LibDeflate")
|
||||
local lib={}
|
||||
lib.compress=function(data)
|
||||
return deflate:CompressDeflate(data)
|
||||
end
|
||||
lib.decompress=function(data)
|
||||
return deflate:DecompressDeflate(data)
|
||||
end
|
||||
return lib
|
||||
@@ -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
|
||||
@@ -1,32 +1,32 @@
|
||||
--:Minify:--
|
||||
local fs={}
|
||||
|
||||
-- "VFS_open" : open
|
||||
-- "VFS_read" : read
|
||||
-- "VFS_write" : write
|
||||
-- "VFS_close" : close
|
||||
-- "open" : open
|
||||
-- "read" : read
|
||||
-- "write" : write
|
||||
-- "close" : close
|
||||
|
||||
function fs.open(path, mode)
|
||||
local fd=syscall.VFS_open(path,mode)
|
||||
local fd=syscall.open(path,mode)
|
||||
local ret={
|
||||
close=function()
|
||||
-- close file
|
||||
return syscall.VFS_close(fd)
|
||||
return syscall.close(fd)
|
||||
end,
|
||||
flush=function()
|
||||
-- close and reopen file to flush buffers
|
||||
syscall.VFS_close(fd)
|
||||
fd=syscall.VFS_open(path,mode)
|
||||
syscall.fsync(fd)
|
||||
end
|
||||
}
|
||||
if mode=="r" then
|
||||
ret.read=function(count)
|
||||
local data = syscall.VFS_read(fd,count)
|
||||
local data = syscall.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)
|
||||
local chunk=syscall.read(fd,chunkSize or 65536)
|
||||
if chunk==nil or #chunk==0 then break end
|
||||
table.insert(chunks,chunk)
|
||||
end
|
||||
@@ -59,7 +59,7 @@ function fs.open(path, mode)
|
||||
end
|
||||
|
||||
-- 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
|
||||
eof = true
|
||||
else
|
||||
@@ -70,12 +70,12 @@ function fs.open(path, mode)
|
||||
elseif mode=="w" then
|
||||
ret.write=function(data)
|
||||
-- write data to file
|
||||
return syscall.VFS_write(fd,data)
|
||||
return syscall.write(fd,data)
|
||||
end
|
||||
elseif mode=="a" then
|
||||
ret.write=function(data)
|
||||
-- append data to file
|
||||
return syscall.VFS_write(fd,data)
|
||||
return syscall.write(fd,data)
|
||||
end
|
||||
else
|
||||
error("Invalid mode '"..mode.."'",2)
|
||||
@@ -105,35 +105,39 @@ function fs.appendAllText(path, data)
|
||||
end
|
||||
|
||||
function fs.mkdir(path)
|
||||
return syscall.VFS_mkdir(path)
|
||||
return syscall.mkdir(path)
|
||||
end
|
||||
|
||||
function fs.remove(path)
|
||||
return syscall.VFS_remove(path)
|
||||
return syscall.remove(path)
|
||||
end
|
||||
|
||||
function fs.list(path)
|
||||
return syscall.VFS_list(path)
|
||||
return syscall.listdir(path)
|
||||
end
|
||||
|
||||
function fs.type(path)
|
||||
return syscall.VFS_type(path)
|
||||
return syscall.type(path)
|
||||
end
|
||||
|
||||
function fs.attributes(path)
|
||||
return syscall.VFS_attributes(path)
|
||||
function fs.stat(path)
|
||||
return syscall.stat(path)
|
||||
end
|
||||
|
||||
function fs.exists(path)
|
||||
return syscall.VFS_exists(path)
|
||||
return syscall.exists(path)
|
||||
end
|
||||
|
||||
function fs.getcwd()
|
||||
return syscall.VFS_getcwd()
|
||||
return syscall.getcwd()
|
||||
end
|
||||
|
||||
function fs.setcwd(path)
|
||||
return syscall.VFS_setcwd(path)
|
||||
function fs.chdir(path)
|
||||
return syscall.chdir(path)
|
||||
end
|
||||
|
||||
function fs.isDir(path)
|
||||
return syscall.type(path) == "directory"
|
||||
end
|
||||
|
||||
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
|
||||
316
Src/Hyperion-firmware-ccpc/boot/cct/boot.lua
Normal file
316
Src/Hyperion-firmware-ccpc/boot/cct/boot.lua
Normal file
@@ -0,0 +1,316 @@
|
||||
-- :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,
|
||||
getfenv = true,
|
||||
getmetatable = true,
|
||||
ipairs = true,
|
||||
__inext = true,
|
||||
load = true,
|
||||
math = true,
|
||||
next = true,
|
||||
pairs = true,
|
||||
pcall = true,
|
||||
rawequal = true,
|
||||
rawget = true,
|
||||
rawlen = true,
|
||||
rawset = true,
|
||||
select = true,
|
||||
setfenv = true,
|
||||
setmetatable = true,
|
||||
string = true,
|
||||
table = true,
|
||||
tonumber = true,
|
||||
tostring = true,
|
||||
type = true,
|
||||
xpcall = true,
|
||||
_G = true
|
||||
}
|
||||
|
||||
local 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
|
||||
|
||||
local eventQueue = {}
|
||||
|
||||
local function queueEvent(event, ...)
|
||||
table.insert(eventQueue, {event, ...})
|
||||
end
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
local icolors = {
|
||||
[0x1] = 1, -- #000000
|
||||
[0x2] = 2, -- #FFFFFF
|
||||
[0x4] = 3, -- #FF0000
|
||||
[0x8] = 4, -- #00FF00
|
||||
[0x10] = 5, -- #0000FF
|
||||
[0x20] = 6, -- #00FFFF
|
||||
[0x40] = 7, -- #FF00FF
|
||||
[0x80] = 8, -- #FFFF00
|
||||
[0x100] = 9, -- #FF6D00
|
||||
[0x200] = 10, -- #6DFF55
|
||||
[0x400] = 11, -- #24FFFF
|
||||
[0x800] = 12, -- #924900
|
||||
[0x1000] = 13, -- #6D6D55
|
||||
[0x2000] = 14, -- #DBDBAA
|
||||
[0x4000] = 15, -- #6D00FF
|
||||
[0x8000] = 16 -- #B6FF00
|
||||
}
|
||||
|
||||
local colors = {
|
||||
0x0001, -- #000000
|
||||
0x0002, -- #FFFFFF
|
||||
0x0004, -- #FF0000
|
||||
0x0008, -- #00FF00
|
||||
0x0010, -- #0000FF
|
||||
0x0020, -- #00FFFF
|
||||
0x0040, -- #FF00FF
|
||||
0x0080, -- #FFFF00
|
||||
0x0100, -- #FF6D00
|
||||
0x0200, -- #6DFF55
|
||||
0x0400, -- #24FFFF
|
||||
0x0800, -- #924900
|
||||
0x1000, -- #6D6D55
|
||||
0x2000, -- #DBDBAA
|
||||
0x4000, -- #6D00FF
|
||||
0x8000 -- #B6FF00
|
||||
}
|
||||
|
||||
apis.term.setBackgroundColor(0x8000)
|
||||
apis.term.setTextColor(0x1000)
|
||||
apis.term.clear()
|
||||
apis.term.setCursorPos(1, 1)
|
||||
|
||||
local kernelCoro = coroutine.create(function()
|
||||
---@diagnostic disable-next-line: param-type-mismatch
|
||||
local ok, err = xpcall(Kernel, debug.traceback, apis, initFs, "cct", "/sbin/init",
|
||||
{
|
||||
print = function(_, text) write(text .. "\n") end,
|
||||
printInline = function(_, text) write(text) end,
|
||||
clear = function()
|
||||
apis.term.clear()
|
||||
apis.term.setCursorPos(1, 1)
|
||||
end,
|
||||
setCursorPos = function(_, x, y)
|
||||
apis.term.setCursorPos(x, y)
|
||||
end,
|
||||
getCursorPos = function() return apis.term.getCursorPos() end,
|
||||
getSize = function() return apis.term.getSize() end,
|
||||
setBackgroundColor = function(_, color)
|
||||
apis.term.setBackgroundColor(colors[color])
|
||||
end,
|
||||
setTextColor = function(_, color)
|
||||
apis.term.setTextColor(colors[color])
|
||||
end,
|
||||
getBackgroundColor = function()
|
||||
return icolors[apis.term.getBackgroundColor()]
|
||||
end,
|
||||
getTextColor = function()
|
||||
return icolors[apis.term.getTextColor()]
|
||||
end
|
||||
}, computer, fs, "$")
|
||||
if not ok then displaySuperBadError(err) end
|
||||
end)
|
||||
|
||||
function coroutine.resumeWithTimeout(co, timeout, ...)
|
||||
local startTime = computer.time()
|
||||
debug.sethook(co, function()
|
||||
if computer.time() > startTime + timeout then
|
||||
return coroutine.yield("timeout")
|
||||
end
|
||||
end, "", 1000)
|
||||
local ret = {coroutine.resume(co, ...)}
|
||||
if ret[1] and ret[2] == "timeout" then
|
||||
return "timeout"
|
||||
elseif ret[1] == false then
|
||||
return "error", ret[2]
|
||||
else
|
||||
debug.sethook(co)
|
||||
return "success", table.unpack(ret, 2)
|
||||
end
|
||||
end
|
||||
|
||||
write("Loaded in " .. tostring(apis.os.clock()) .. " seconds.\n")
|
||||
|
||||
while true do
|
||||
local status, err = coroutine.resumeWithTimeout(kernelCoro, 50)
|
||||
apis.os.queueEvent("NoSleep")
|
||||
local exit = false
|
||||
while not exit do
|
||||
local event = {coroutine.yield()}
|
||||
if event[1] == "key" then
|
||||
queueEvent("keyPressed", 1, event[2])
|
||||
if acekeys[event[2]] then
|
||||
queueEvent("keyTyped", 1, acekeys[event[2]])
|
||||
end
|
||||
elseif event[1] == "char" then
|
||||
queueEvent("keyTyped", 1, event[2])
|
||||
elseif event[1] == "key_up" then
|
||||
queueEvent("keyReleased", 1, event[2])
|
||||
elseif event[1] == "disk" then
|
||||
queueEvent("componentAdded", "disk")
|
||||
elseif event[1] == "disk_eject" then
|
||||
queueEvent("componentRemoved", "disk")
|
||||
elseif event[1] == "modem_message" then
|
||||
queueEvent("modem_message", table.unpack(event, 2))
|
||||
elseif event[1] == "rednet_message" then
|
||||
queueEvent("rednet_message", table.unpack(event, 2))
|
||||
elseif event[1] == "http_success" then
|
||||
queueEvent("http_success", table.unpack(event, 2))
|
||||
elseif event[1] == "http_failure" then
|
||||
queueEvent("http_failure", table.unpack(event, 2))
|
||||
elseif event[1] == "NoSleep" then
|
||||
exit = true
|
||||
end
|
||||
end
|
||||
if status == "error" or coroutine.status(kernelCoro) == "dead" then
|
||||
displaySuperBadError("Kernel error: " .. tostring(err))
|
||||
coroutine.yield("key")
|
||||
end
|
||||
end
|
||||
end, debug.traceback)
|
||||
|
||||
if not ok then displaySuperBadError("Fatal error during boot: " .. err) end
|
||||
while true do coroutine.yield() end
|
||||
@@ -1,6 +1,5 @@
|
||||
--:Minify:--
|
||||
sleep(1)
|
||||
local BOOT_DRIVE_PATH="/$"
|
||||
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
|
||||
@@ -16,7 +15,6 @@ local BOOT_DRIVE_PATH="/$"
|
||||
-- * `turtle.equip[Left|Right]`
|
||||
-- Licensed under the MIT license
|
||||
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 t = {}
|
||||
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
|
||||
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
|
||||
_G._HOST = _G._HOST .. " (UnBIOS)"
|
||||
-- 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
|
||||
@@ -88,7 +85,7 @@ function _G.term.native()
|
||||
local oldshutdown = os.shutdown
|
||||
os.shutdown = function()
|
||||
os.shutdown = oldshutdown
|
||||
return fn(table.unpack(args))
|
||||
return fn(BOOT_DRIVE_PATH)
|
||||
end
|
||||
end
|
||||
if debug then
|
||||
@@ -1,18 +1,17 @@
|
||||
--:Minify:--
|
||||
-- :Minify:--
|
||||
local apis = ({...})[1]
|
||||
local BOOT_DRIVE_PATH="/$"
|
||||
local BOOT_DRIVE_PATH = apis.BOOT_DRIVE_PATH or "/$"
|
||||
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
|
||||
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
|
||||
if native.hasType(side, "peripheral_hub") and
|
||||
native.call(side, "isPresentRemote", name) then
|
||||
return native.call(side, "getTypeRemote", name)
|
||||
end
|
||||
end
|
||||
@@ -23,9 +22,7 @@ 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.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
|
||||
@@ -36,37 +33,30 @@ function peripheral.getNames()
|
||||
return names
|
||||
end
|
||||
|
||||
---------------------------------------------------------
|
||||
-- STORAGE
|
||||
---------------------------------------------------------
|
||||
local disks = {} -- real disks
|
||||
local internal = {} -- "$" disk
|
||||
local disks = {}
|
||||
local internal = {}
|
||||
|
||||
---------------------------------------------------------
|
||||
-- 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}
|
||||
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: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
|
||||
if not fs.exists(p) or not fs.isDir(p) then
|
||||
return nil, "not directory"
|
||||
end
|
||||
return fs.list(p)
|
||||
end
|
||||
|
||||
@@ -103,13 +93,9 @@ local function createDisk(id, basePath, readonly, periph)
|
||||
return true
|
||||
end
|
||||
|
||||
function disk:setLabel(label)
|
||||
periph.setLabel(label)
|
||||
end
|
||||
function disk:setLabel(label) periph.setLabel(label) end
|
||||
|
||||
function disk:getLabel(label)
|
||||
return periph.getLabel()
|
||||
end
|
||||
function disk:getLabel(label) return periph.getLabel() end
|
||||
|
||||
function disk:attributes(path)
|
||||
local p = fs.combine(basePath, path)
|
||||
@@ -120,39 +106,30 @@ local function createDisk(id, basePath, readonly, periph)
|
||||
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)
|
||||
setLabel = function(label)
|
||||
local h = fs.open("/.label", "w")
|
||||
h.write(label)
|
||||
h.close()
|
||||
end,
|
||||
getLabel=function()
|
||||
getLabel = function()
|
||||
local h = fs.open("/.label", "r")
|
||||
if not h then return "$" end
|
||||
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
|
||||
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
|
||||
@@ -165,28 +142,14 @@ local function refresh()
|
||||
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
|
||||
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
|
||||
}
|
||||
return {refresh = refresh, list = iter}
|
||||
394
Src/Hyperion-firmware-ccpc/lib/modules/CC-Tweaked/25_tty.kmod
Normal file
394
Src/Hyperion-firmware-ccpc/lib/modules/CC-Tweaked/25_tty.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.computer: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,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
|
||||
|
||||
314
Src/Hyperion-firmware-cct/boot/cct/boot.lua
Normal file
314
Src/Hyperion-firmware-cct/boot/cct/boot.lua
Normal file
@@ -0,0 +1,314 @@
|
||||
-- :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
|
||||
|
||||
local eventQueue = {}
|
||||
|
||||
local function queueEvent(event, ...)
|
||||
table.insert(eventQueue, {event, ...})
|
||||
end
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
155
Src/Hyperion-firmware-cct/boot/cct/initdisks
Normal file
155
Src/Hyperion-firmware-cct/boot/cct/initdisks
Normal file
@@ -0,0 +1,155 @@
|
||||
-- :Minify:--
|
||||
local apis = ({...})[1]
|
||||
local BOOT_DRIVE_PATH = apis.BOOT_DRIVE_PATH or "/$"
|
||||
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
|
||||
|
||||
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
|
||||
})
|
||||
|
||||
local function refresh()
|
||||
for id, _ in pairs(disks) do
|
||||
if not peripheral.getType(id) then disks[id] = nil end
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
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}
|
||||
410
Src/Hyperion-firmware-cct/lib/modules/CC-Tweaked/25_tty.kmod
Normal file
410
Src/Hyperion-firmware-cct/lib/modules/CC-Tweaked/25_tty.kmod
Normal file
@@ -0,0 +1,410 @@
|
||||
--: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)
|
||||
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 "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.computer: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 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"
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
local fs={}
|
||||
@@ -32,6 +32,7 @@ local lua = {
|
||||
_G=true
|
||||
}
|
||||
|
||||
local apis={}
|
||||
for i,v in pairs(_G) do
|
||||
if not lua[i] or lua[i]==nil then
|
||||
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,3 +0,0 @@
|
||||
--:Minify:--
|
||||
local kernel=...
|
||||
kernel.tty.bind("tty0")
|
||||
@@ -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 disks = {}
|
||||
local mounts = {}
|
||||
@@ -15,39 +15,42 @@ local function resolve(path)
|
||||
local newPath = path:sub(#mountPoint + 1)
|
||||
return disks[mounts[mountPoint]], newPath
|
||||
end
|
||||
---------------------------------------------------------
|
||||
|
||||
function fs.update(initdisks)
|
||||
disks = {}
|
||||
for k, v in initdisks.list() do
|
||||
disks[k] = v
|
||||
end
|
||||
for k, v in initdisks.list() do disks[k] = v end
|
||||
end
|
||||
|
||||
function fs.exists(path)
|
||||
local disk, newPath = resolve(path)
|
||||
return disk:directoryExists(newPath) or disk:fileExists(newPath)
|
||||
end
|
||||
|
||||
function fs.isFile(path)
|
||||
local disk, newPath = resolve(path)
|
||||
return disk:fileExists(newPath)
|
||||
end
|
||||
|
||||
function fs.isDir(path)
|
||||
local disk, newPath = resolve(path)
|
||||
return disk:directoryExists(newPath)
|
||||
end
|
||||
|
||||
function fs.list(path)
|
||||
local disk, newPath = resolve(path)
|
||||
return disk:list(newPath)
|
||||
end
|
||||
|
||||
function fs.makeDir(path)
|
||||
local disk, newPath = resolve(path)
|
||||
return disk:makeDirectory(newPath)
|
||||
end
|
||||
|
||||
function fs.remove(path)
|
||||
local disk, newPath = resolve(path)
|
||||
return disk:remove(newPath)
|
||||
end
|
||||
|
||||
function fs.readAllText(path)
|
||||
local disk, newPath = resolve(path)
|
||||
local handle = disk:open(newPath, "r")
|
||||
@@ -56,23 +59,26 @@ function fs.readAllText(path)
|
||||
handle.close()
|
||||
return content
|
||||
end
|
||||
|
||||
function fs.writeAllText(path, text)
|
||||
local disk, newPath = resolve(path)
|
||||
local handle = disk:open(newPath, "w")
|
||||
handle.write(text)
|
||||
handle.close()
|
||||
end
|
||||
|
||||
function fs.appendAllText(path, text)
|
||||
local disk, newPath = resolve(path)
|
||||
local handle = disk:open(newPath, "a")
|
||||
handle.write(text)
|
||||
handle.close()
|
||||
end
|
||||
function fs.load(path)
|
||||
return load(fs.readAllText(path), path)
|
||||
end
|
||||
|
||||
function fs.load(path) return load(fs.readAllText(path), path) end
|
||||
|
||||
function fs.mount(disk, mountPoint)
|
||||
if not disks[disk] then return end
|
||||
mounts[mountPoint] = disk
|
||||
end
|
||||
return fs
|
||||
|
||||
return fs
|
||||
@@ -6,12 +6,13 @@ local arch = args[3]
|
||||
local screen = args[5]
|
||||
local computer = args[6]
|
||||
local ifs = args[7]
|
||||
local LOG_Text = ""
|
||||
local kernel = {}
|
||||
kernel.LOG_Text=""
|
||||
kernel.version="HyperionOS V1.2.3"
|
||||
kernel.process = "Kernel"
|
||||
kernel.user = "root"
|
||||
kernel.group = "root"
|
||||
kernel.groups = {0}
|
||||
kernel.users={[0]="root",[1]="User"}
|
||||
kernel.hostname = "hyperion"
|
||||
kernel.groups = {}
|
||||
kernel.uid = 0
|
||||
kernel.gid = 0
|
||||
kernel.status = "start"
|
||||
@@ -24,14 +25,17 @@ kernel.sleep=sleep
|
||||
_G.sleep=nil
|
||||
local windowsExp = false
|
||||
|
||||
function kernel.log(msg, level)
|
||||
LOG_Text = LOG_Text..tostring(computer:time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n"
|
||||
function kernel.log(msg, level, c)
|
||||
c=c or 12
|
||||
kernel.LOG_Text = kernel.LOG_Text..string.format("%X",c-1).." "..tostring(computer:time()).." "..kernel.users[kernel.uid].." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n"
|
||||
if kernel.status == "start" then
|
||||
screen:print(tostring(computer:time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg)
|
||||
elseif kernel.status == "init" then
|
||||
screen:setTextColor(c)
|
||||
screen:print(tostring(computer:time()).." "..kernel.users[kernel.uid].." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg)
|
||||
elseif kernel.status == "term" then
|
||||
kernel.standbyTask=kernel.currentTask
|
||||
kernel.currentTask=kernel.kernelTask
|
||||
kernel.tty.print(tostring(computer:time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg)
|
||||
kernel.vfs.devctl(1,"sfgc",c)
|
||||
kernel.vfs.write(1,tostring(computer:time()).." "..kernel.users[kernel.uid].." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n")
|
||||
kernel.currentTask=kernel.standbyTask
|
||||
end
|
||||
end
|
||||
@@ -43,14 +47,15 @@ function kernel.PANIC(msg)
|
||||
kernel.status="Panic"
|
||||
kernel.reason=msg
|
||||
screen:setTextColor(2)
|
||||
screen:setBackgroundColor(0)
|
||||
screen:setBackgroundColor(16)
|
||||
screen:clear()
|
||||
screen:setCursorPos(1,1)
|
||||
screen:print(LOG_Text)
|
||||
screen:print(kernel.LOG_Text)
|
||||
screen:print("KERNEL PANIC!\n"..msg.."\nSystem halted.")
|
||||
screen:print("Press any key to continue...")
|
||||
kernel.exitMain = true
|
||||
end
|
||||
while true do
|
||||
while true do
|
||||
local event={computer:getMachineEvent()}
|
||||
if event[1]=="keyPressed" then
|
||||
break
|
||||
@@ -108,8 +113,9 @@ local split = function(str, delim, maxResultCountOrNil)
|
||||
end
|
||||
|
||||
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", 3)
|
||||
ifs.writeAllText("/boot/boot.cfg",ifs.readAllText("/boot/safeboot.cfg"))
|
||||
kernel.firstBoot=true
|
||||
end
|
||||
|
||||
local initCfgFunc, err = load(ifs.readAllText("/boot/boot.cfg"), "@boot.cfg")
|
||||
@@ -117,6 +123,7 @@ if not initCfgFunc then
|
||||
kernel.PANIC("Failed to load /boot/boot.cfg: "..tostring(err))
|
||||
end
|
||||
|
||||
---@diagnostic disable-next-line: param-type-mismatch
|
||||
local initCfgStatus, config = pcall(initCfgFunc)
|
||||
if not initCfgStatus then
|
||||
kernel.PANIC("Error in /boot/boot.cfg: "..tostring(config))
|
||||
@@ -140,16 +147,13 @@ end
|
||||
kernel.log("Disks initialized")
|
||||
|
||||
function kernel.saveLog()
|
||||
ifs.writeAllText("/var/log/syslog.log", LOG_Text)
|
||||
ifs.writeAllText("/var/log/syslog.log", kernel.LOG_Text)
|
||||
end
|
||||
|
||||
ifs.remove("/tmp")
|
||||
ifs.makeDir("/tmp")
|
||||
|
||||
function kernel.newFifo()
|
||||
local fifo = {}
|
||||
fifo.push=function(data)
|
||||
table.insert(data)
|
||||
table.insert(fifo, data)
|
||||
end
|
||||
fifo.pop=function()
|
||||
return table.remove(fifo,1)
|
||||
@@ -181,9 +185,16 @@ end
|
||||
|
||||
kernel.log("Gathering modules")
|
||||
for _, i in ipairs(ifs.list("/lib/modules")) do
|
||||
for _,v in ipairs(ifs.list("/lib/modules/"..i)) do
|
||||
local prior=tonumber(v:sub(1,2))
|
||||
modules[prior+1][#modules[prior+1]+1]="/lib/modules/"..i.."/"..v
|
||||
local modlist = ifs.list("/lib/modules/"..i)
|
||||
if not modlist then
|
||||
kernel.log("WARNING: could not list /lib/modules/"..i.." (skipping)", "WARN", 8)
|
||||
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
|
||||
|
||||
@@ -201,7 +212,6 @@ kernel.kernelTask = {
|
||||
status="R",
|
||||
pid=0,
|
||||
tgid=0,
|
||||
user="root",
|
||||
uid=0,
|
||||
fd={},
|
||||
exit="",
|
||||
@@ -218,26 +228,60 @@ kernel.kernelTask = {
|
||||
}
|
||||
kernel.currentTask = kernel.kernelTask
|
||||
|
||||
kernel.syscalls["OS_time"]=function() return kernel.computer:time() end
|
||||
kernel.syscalls["OS_log"]=kernel.log
|
||||
function kernel.shutdown()
|
||||
kernel.computer:shutdown()
|
||||
end
|
||||
|
||||
function kernel.reboot()
|
||||
kernel.computer:reboot()
|
||||
end
|
||||
|
||||
kernel.syscalls["time"]=function() return kernel.computer:time() end
|
||||
kernel.syscalls["log"]=kernel.log
|
||||
kernel.syscalls["getUptime"]=function() return kernel.computer:clock() 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"]=function()
|
||||
kernel.computer:reboot()
|
||||
end
|
||||
kernel.syscalls["shutdown"]=function()
|
||||
kernel.computer:reboot()
|
||||
end
|
||||
|
||||
kernel.log("Running modules")
|
||||
for _,p in ipairs(modules) do
|
||||
for _,v in ipairs(p) do
|
||||
if kernel.config.showModLoad then kernel.log("Loading module "..v, "DBUG", 5) end
|
||||
local code=ifs.readAllText(v)
|
||||
if not code then
|
||||
kernel.log("ModuReadErr: "..v, "WARN")
|
||||
if not code then
|
||||
kernel.log("ModuReadErr: "..v, "WARN", 8)
|
||||
goto skip
|
||||
end
|
||||
local func,err=load(code,"@"..v)
|
||||
if not func then kernel.panic("ModuLoadErr: "..tostring(err)) goto skip end
|
||||
local status, err = xpcall(func,debug.traceback, kernel)
|
||||
if not status then kernel.panic("ModuRunErr: "..tostring(err)) end
|
||||
if kernel.config.showModLoad then kernel.log("Loaded module "..v, "DBUG", 5) end
|
||||
::skip::
|
||||
end
|
||||
end
|
||||
|
||||
kernel.log("Kernel initialized successfully.")
|
||||
--kernel.status="running"
|
||||
kernel.saveLog()
|
||||
kernel.status="running"
|
||||
kernel.main()
|
||||
if kernel.status=="panic" then
|
||||
kernel.panic()
|
||||
end
|
||||
kernel.PANIC("Execution complete")
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user