forked from Hyperion/HyperionOS
stuff.mp4
This commit is contained in:
308
Test/Hyperion-firmware-cct-v1.0.0/boot/cct/boot.lua
Normal file
308
Test/Hyperion-firmware-cct-v1.0.0/boot/cct/boot.lua
Normal file
@@ -0,0 +1,308 @@
|
||||
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
|
||||
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*1000)
|
||||
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/kernel.lua"),"@Kernel")
|
||||
local initFs = load(getFile("/$/boot/cct/initdisks","@Init_disks"))(apis)
|
||||
local fs = load(getFile("/$/boot/initfs"),"@InitFs")()
|
||||
if not Kernel then
|
||||
displaySuperBadError("Could not load kernel.")
|
||||
end
|
||||
if not initFs then
|
||||
displaySuperBadError("Could not load initdisks.")
|
||||
end
|
||||
if not fs then
|
||||
displaySuperBadError("Could not load initfs.")
|
||||
end
|
||||
|
||||
-- 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 = apis.os.clock,
|
||||
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]=="timeout" then
|
||||
return true, "Coroutine timed out"
|
||||
elseif ret[1]==false then
|
||||
return false, ret[2]
|
||||
else
|
||||
debug.sethook(co)
|
||||
return computer.time()-startTime, table.unpack(ret)
|
||||
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 == false 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
|
||||
Reference in New Issue
Block a user