345 lines
9.9 KiB
Lua
345 lines
9.9 KiB
Lua
--:Minify:--
|
|
local args={...}
|
|
local bootdrive=args[1]
|
|
local gpu=components:getFirst("gpu")
|
|
local screenTextBuffer=nil
|
|
local cursorX,cursorY=0,0
|
|
local screenSizeX,screenSizeY=128,25
|
|
|
|
|
|
if gpu then
|
|
screenTextBuffer=gpu:newBuffer(screenSizeX,screenSizeY)
|
|
for t,v in components:list() do
|
|
if t == "screen" then
|
|
gpu:assignBuffer(screenTextBuffer, v)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function write(text)
|
|
cursorX, cursorY = screenTextBuffer:pasteText(cursorX, cursorY, "SCROLL_SPILL_CLEAR", text)
|
|
cursorY = cursorY + 1
|
|
cursorX = 0
|
|
if cursorY >= screenSizeY then
|
|
cursorY = screenSizeY-1
|
|
screenTextBuffer:newline()
|
|
end
|
|
end
|
|
|
|
local function displaySuperBadError(err)
|
|
gpu:freeAllBuffers()
|
|
screenTextBuffer=gpu:newBuffer(screenSizeX,screenSizeY)
|
|
for t,v in components:list() do
|
|
if t == "screen" then
|
|
gpu:assignBuffer(screenTextBuffer, v)
|
|
end
|
|
end
|
|
term.setBackgroundColor(0x1)
|
|
term.setTextColor(0x4)
|
|
term.clear()
|
|
term.setCursorPos(1, 1)
|
|
term.write("A critical error occurred while loading the system:")
|
|
term.setCursorPos(1, 3)
|
|
write(err)
|
|
while true do end
|
|
end
|
|
|
|
local ok, err = xpcall(function()
|
|
local apis = {}
|
|
|
|
local lua = {
|
|
coroutine = true,
|
|
debug = true,
|
|
_VERSION = true,
|
|
assert = true,
|
|
collectgarbage = true,
|
|
error = true,
|
|
gcinfo = true,
|
|
getmetatable = true,
|
|
ipairs = true,
|
|
__inext = true,
|
|
load = true,
|
|
math = true,
|
|
next = true,
|
|
pairs = true,
|
|
pcall = true,
|
|
rawequal = true,
|
|
rawget = true,
|
|
rawlen = true,
|
|
rawset = true,
|
|
select = true,
|
|
setmetatable = true,
|
|
string = true,
|
|
table = true,
|
|
tonumber = true,
|
|
tostring = true,
|
|
type = true,
|
|
xpcall = true,
|
|
_G = true
|
|
}
|
|
|
|
local debug = debug
|
|
for i, v in pairs(_G) do
|
|
if not lua[i] or lua[i] == nil then
|
|
apis[i] = v
|
|
_G[i] = nil
|
|
end
|
|
end
|
|
|
|
local function string_file(file)
|
|
local str = file:read()
|
|
local buf = {str or ""}
|
|
local pos = 1
|
|
local closed = false
|
|
|
|
local function content()
|
|
return table.concat(buf)
|
|
end
|
|
|
|
local function set_content(s)
|
|
buf = {s}
|
|
end
|
|
|
|
local function flush()
|
|
file.write(content())
|
|
end
|
|
|
|
local file = {}
|
|
|
|
function file.read(n)
|
|
assert(not closed, "file is closed")
|
|
|
|
local s = content()
|
|
local len = #s
|
|
|
|
if not n then
|
|
local out = s:sub(pos)
|
|
pos = len + 1
|
|
return out
|
|
end
|
|
|
|
local out = s:sub(pos, pos + n - 1)
|
|
pos = pos + #out
|
|
return out
|
|
end
|
|
|
|
function file.write(data)
|
|
assert(not closed, "file is closed")
|
|
|
|
local s = content()
|
|
local before = s:sub(1, pos - 1)
|
|
local after = s:sub(pos + #data)
|
|
|
|
set_content(before .. data .. after)
|
|
pos = pos + #data
|
|
|
|
return true
|
|
end
|
|
|
|
function file.seek(whence, offset)
|
|
assert(not closed, "file is closed")
|
|
|
|
local s = content()
|
|
local len = #s
|
|
|
|
whence = whence or "cur"
|
|
offset = offset or 0
|
|
|
|
if whence == "set" then
|
|
pos = offset + 1
|
|
elseif whence == "cur" then
|
|
pos = pos + offset
|
|
elseif whence == "end" then
|
|
pos = len + offset + 1
|
|
else
|
|
error("invalid whence")
|
|
end
|
|
|
|
if pos < 1 then pos = 1 end
|
|
if pos > len + 1 then pos = len + 1 end
|
|
|
|
return pos - 1
|
|
end
|
|
|
|
function file:close()
|
|
assert(not closed, "file is closed")
|
|
flush()
|
|
closed = true
|
|
end
|
|
|
|
function file:flush()
|
|
assert(not closed, "file is closed")
|
|
flush()
|
|
end
|
|
|
|
return file
|
|
end
|
|
|
|
local function getFile(path)
|
|
local file = bootdrive:open(path, "r")
|
|
if not file then
|
|
displaySuperBadError("Could not open file: " .. path)
|
|
end
|
|
local content = file:read()
|
|
return content
|
|
end
|
|
|
|
local Kernel = load(getFile("/boot/kernel.lua"),"@Kernel")
|
|
local initFs = load(getFile("/boot/ac/initdisks"),"@Init_disks")(apis)
|
|
local fs = load(getFile("/boot/initfs"), "@InitFs")()
|
|
|
|
if not Kernel then displaySuperBadError("Could not load kernel.") end
|
|
if not initFs then displaySuperBadError("Could not load initdisks.") end
|
|
if not fs then displaySuperBadError("Could not load initfs.") end
|
|
|
|
local computercomp=apis.components:getFirst("computer")
|
|
local uefi=apis.components:getFirst("uefi")
|
|
local computer = {
|
|
time = function() return apis.os.epoch("utc") end,
|
|
clock = function() return apis.os.clock() * 1000 end,
|
|
shutdown = apis.os.shutdown,
|
|
reboot = apis.os.reboot,
|
|
getMachineEvent = function()
|
|
return computercomp:getMachineEvent()
|
|
end,
|
|
getEEPROM = function() return uefi.data end,
|
|
setEEPROM = function(_, text)
|
|
uefi.data=text
|
|
end
|
|
}
|
|
|
|
local icolors = {
|
|
[0x1] = 1, -- #000000
|
|
[0x2] = 2, -- #FFFFFF
|
|
[0x4] = 3, -- #FF0000
|
|
[0x8] = 4, -- #00FF00
|
|
[0x10] = 5, -- #0000FF
|
|
[0x20] = 6, -- #00FFFF
|
|
[0x40] = 7, -- #FF00FF
|
|
[0x80] = 8, -- #FFFF00
|
|
[0x100] = 9, -- #FF6D00
|
|
[0x200] = 10, -- #6DFF55
|
|
[0x400] = 11, -- #24FFFF
|
|
[0x800] = 12, -- #924900
|
|
[0x1000] = 13, -- #6D6D55
|
|
[0x2000] = 14, -- #DBDBAA
|
|
[0x4000] = 15, -- #6D00FF
|
|
[0x8000] = 16 -- #B6FF00
|
|
}
|
|
|
|
local colors = {
|
|
0x0001, -- #000000
|
|
0x0002, -- #FFFFFF
|
|
0x0004, -- #FF0000
|
|
0x0008, -- #00FF00
|
|
0x0010, -- #0000FF
|
|
0x0020, -- #00FFFF
|
|
0x0040, -- #FF00FF
|
|
0x0080, -- #FFFF00
|
|
0x0100, -- #FF6D00
|
|
0x0200, -- #6DFF55
|
|
0x0400, -- #24FFFF
|
|
0x0800, -- #924900
|
|
0x1000, -- #6D6D55
|
|
0x2000, -- #DBDBAA
|
|
0x4000, -- #6D00FF
|
|
0x8000 -- #B6FF00
|
|
}
|
|
|
|
apis.term.setBackgroundColor(0x8000)
|
|
apis.term.setTextColor(0x1000)
|
|
apis.term.clear()
|
|
apis.term.setCursorPos(1, 1)
|
|
|
|
local kernelCoro = coroutine.create(function()
|
|
---@diagnostic disable-next-line: param-type-mismatch
|
|
local ok, err = xpcall(Kernel, debug.traceback, apis, initFs, "cct", "/sbin/init",
|
|
{
|
|
print = function(_, text) write(text .. "\n") end,
|
|
printInline = function(_, text) write(text) end,
|
|
clear = function()
|
|
apis.term.clear()
|
|
apis.term.setCursorPos(1, 1)
|
|
end,
|
|
setCursorPos = function(_, x, y)
|
|
apis.term.setCursorPos(x, y)
|
|
end,
|
|
getCursorPos = function() return apis.term.getCursorPos() end,
|
|
getSize = function() return apis.term.getSize() end,
|
|
setBackgroundColor = function(_, color)
|
|
apis.term.setBackgroundColor(colors[color])
|
|
end,
|
|
setTextColor = function(_, color)
|
|
apis.term.setTextColor(colors[color])
|
|
end,
|
|
getBackgroundColor = function()
|
|
return icolors[apis.term.getBackgroundColor()]
|
|
end,
|
|
getTextColor = function()
|
|
return icolors[apis.term.getTextColor()]
|
|
end
|
|
}, computer, fs, "$")
|
|
if not ok then displaySuperBadError(err) end
|
|
end)
|
|
|
|
function coroutine.resumeWithTimeout(co, timeout, ...)
|
|
local startTime = computer.time()
|
|
debug.sethook(co, function()
|
|
if computer.time() > startTime + timeout then
|
|
return coroutine.yield("timeout")
|
|
end
|
|
end, "", 1000)
|
|
local ret = {coroutine.resume(co, ...)}
|
|
if ret[1] and ret[2] == "timeout" then
|
|
return "timeout"
|
|
elseif ret[1] == false then
|
|
return "error", ret[2]
|
|
else
|
|
debug.sethook(co)
|
|
return "success", table.unpack(ret, 2)
|
|
end
|
|
end
|
|
|
|
write("Loaded in " .. tostring(apis.os.clock()) .. " seconds.\n")
|
|
|
|
while true do
|
|
local status, err = coroutine.resumeWithTimeout(kernelCoro, 50)
|
|
apis.os.queueEvent("NoSleep")
|
|
local exit = false
|
|
while not exit do
|
|
local event = {coroutine.yield()}
|
|
if event[1] == "key" then
|
|
queueEvent("keyPressed", 1, event[2])
|
|
if acekeys[event[2]] then
|
|
queueEvent("keyTyped", 1, acekeys[event[2]])
|
|
end
|
|
elseif event[1] == "char" then
|
|
queueEvent("keyTyped", 1, event[2])
|
|
elseif event[1] == "key_up" then
|
|
queueEvent("keyReleased", 1, event[2])
|
|
elseif event[1] == "disk" then
|
|
queueEvent("componentAdded", "disk")
|
|
elseif event[1] == "disk_eject" then
|
|
queueEvent("componentRemoved", "disk")
|
|
elseif event[1] == "modem_message" then
|
|
queueEvent("modem_message", table.unpack(event, 2))
|
|
elseif event[1] == "rednet_message" then
|
|
queueEvent("rednet_message", table.unpack(event, 2))
|
|
elseif event[1] == "http_success" then
|
|
queueEvent("http_success", table.unpack(event, 2))
|
|
elseif event[1] == "http_failure" then
|
|
queueEvent("http_failure", table.unpack(event, 2))
|
|
elseif event[1] == "NoSleep" then
|
|
exit = true
|
|
end
|
|
end
|
|
if status == "error" or coroutine.status(kernelCoro) == "dead" then
|
|
displaySuperBadError("Kernel error: " .. tostring(err))
|
|
coroutine.yield("key")
|
|
end
|
|
end
|
|
end, debug.traceback)
|
|
|
|
if not ok then displaySuperBadError("Fatal error during boot: " .. err) end
|
|
while true do coroutine.yield() end
|