Import
This commit is contained in:
BIN
Src/Hyperion-kernel/boot/.meta
Normal file
BIN
Src/Hyperion-kernel/boot/.meta
Normal file
Binary file not shown.
11
Src/Hyperion-kernel/boot/boot.cfg
Normal file
11
Src/Hyperion-kernel/boot/boot.cfg
Normal file
@@ -0,0 +1,11 @@
|
||||
-- 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.
|
||||
-- DEFAULT BOOT CONFIGURATION FILE
|
||||
return {
|
||||
initPath = "/sbin/init.lua",
|
||||
maxOpenFiles = 128,
|
||||
maxFilesPerTask = 16,
|
||||
preempt=true
|
||||
}
|
||||
309
Src/Hyperion-kernel/boot/cct/boot.lua
Normal file
309
Src/Hyperion-kernel/boot/cct/boot.lua
Normal file
@@ -0,0 +1,309 @@
|
||||
-- :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)
|
||||
|
||||
-- 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")
|
||||
|
||||
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] == "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-kernel/boot/cct/eeprom
Normal file
119
Src/Hyperion-kernel/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-kernel/boot/cct/initdisks
Normal file
155
Src/Hyperion-kernel/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}
|
||||
3
Src/Hyperion-kernel/boot/fstab
Normal file
3
Src/Hyperion-kernel/boot/fstab
Normal file
@@ -0,0 +1,3 @@
|
||||
U $;/
|
||||
U devfs0000;/dev/
|
||||
U tmpfs0000;/tmp/
|
||||
84
Src/Hyperion-kernel/boot/initfs
Normal file
84
Src/Hyperion-kernel/boot/initfs
Normal file
@@ -0,0 +1,84 @@
|
||||
-- :Minify:--
|
||||
local fs = {}
|
||||
local disks = {}
|
||||
local mounts = {}
|
||||
|
||||
local function resolve(path)
|
||||
local mountPoint = "/"
|
||||
for mount, disk in pairs(mounts) do
|
||||
if path:sub(1, #mount) == mount then
|
||||
if not mountPoint or #mount > #mountPoint then
|
||||
mountPoint = mount
|
||||
end
|
||||
end
|
||||
end
|
||||
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
|
||||
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")
|
||||
if not handle then return nil end
|
||||
local content = handle.readAll()
|
||||
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.mount(disk, mountPoint)
|
||||
if not disks[disk] then return end
|
||||
mounts[mountPoint] = disk
|
||||
end
|
||||
|
||||
return fs
|
||||
274
Src/Hyperion-kernel/boot/kernel.lua
Normal file
274
Src/Hyperion-kernel/boot/kernel.lua
Normal file
@@ -0,0 +1,274 @@
|
||||
--:Minify:--
|
||||
local args = {...}
|
||||
local apis = args[1]
|
||||
local disks = args[2]
|
||||
local arch = args[3]
|
||||
local screen = args[5]
|
||||
local computer = args[6]
|
||||
local ifs = args[7]
|
||||
local kernel = {}
|
||||
|
||||
kernel.LOG_Text=""
|
||||
kernel.version="HyperionOS V1.0.0"
|
||||
kernel.process = "Kernel"
|
||||
kernel.users={[0]="root",[1]="User"}
|
||||
kernel.hostname = "hyperion"
|
||||
kernel.groups = {}
|
||||
kernel.uid = 0
|
||||
kernel.gid = 0
|
||||
kernel.status = "start"
|
||||
kernel.key = {}
|
||||
kernel.cache = {}
|
||||
kernel.cache.preload = {}
|
||||
kernel._G=_G
|
||||
kernel.sleep=sleep
|
||||
|
||||
_G.sleep=nil
|
||||
local windowsExp = false
|
||||
|
||||
function kernel.log(msg, level, c)
|
||||
c=c or 12
|
||||
kernel.LOG_Text = kernel.LOG_Text..tostring(computer:time()).." "..kernel.users[kernel.uid].." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n"
|
||||
if kernel.status == "start" then
|
||||
screen:setTextColor(c)
|
||||
screen:print(string.format("%X",c-1).." "..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.vfs.devctl(1,"sfgc",c)
|
||||
kernel.vfs.write(1,string.format("%X",c-1).." "..tostring(computer:time()).." "..kernel.users[kernel.uid].." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n")
|
||||
kernel.currentTask=kernel.standbyTask
|
||||
end
|
||||
end
|
||||
|
||||
function kernel.PANIC(msg)
|
||||
if kernel.status~="Panic" then
|
||||
kernel.log("PANIC: "..msg, "PANIC")
|
||||
pcall(kernel["saveLog"])
|
||||
kernel.status="Panic"
|
||||
kernel.reason=msg
|
||||
screen:setTextColor(2)
|
||||
screen:setBackgroundColor(16)
|
||||
screen:clear()
|
||||
screen:setCursorPos(1,1)
|
||||
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
|
||||
local event={computer:getMachineEvent()}
|
||||
if event[1]=="keyPressed" then
|
||||
break
|
||||
end
|
||||
end
|
||||
computer:reboot()
|
||||
end
|
||||
kernel.panic=kernel.PANIC
|
||||
|
||||
if windowsExp then
|
||||
screen:setTextColor(1)
|
||||
screen:setBackgroundColor(4)
|
||||
screen:clear()
|
||||
local w,h = screen:getSize()
|
||||
screen:setCursorPos(3,5)
|
||||
screen:print(":(")
|
||||
screen:setCursorPos(3,7)
|
||||
screen:print("Your PC ran into a problem and needs to restart. We're just collecting some error")
|
||||
screen:setCursorPos(3,8)
|
||||
screen:print("info, and then we'll restart for you.\n")
|
||||
screen:setCursorPos(3,h-5)
|
||||
screen:print("Stop code: average windows experience")
|
||||
screen:setCursorPos(1,h)
|
||||
screen:print("Press any key to continue... jk reboot it yourself lazy")
|
||||
while true do end
|
||||
end
|
||||
|
||||
kernel.log("Kernel loaded.")
|
||||
kernel.log("Mounting init disks...")
|
||||
disks.refresh()
|
||||
ifs.update(disks)
|
||||
kernel.disks={}
|
||||
for _,v in disks.list() do
|
||||
kernel.disks[v.address] = v
|
||||
end
|
||||
ifs.mount("$", "/")
|
||||
|
||||
local fstab=ifs.readAllText("/boot/fstab")
|
||||
local split = function(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
|
||||
|
||||
if not ifs.isFile("/boot/boot.cfg") then
|
||||
kernel.log("boot.cfg missing or corrupted!, Attempting to write recovery boot.cfg", "ERROR", 2)
|
||||
ifs.writeAllText("/boot/boot.cfg",ifs.readAllText("/boot/safeboot.cfg"))
|
||||
end
|
||||
|
||||
local initCfgFunc, err = load(ifs.readAllText("/boot/boot.cfg"), "@boot.cfg")
|
||||
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))
|
||||
end
|
||||
kernel.config = config
|
||||
|
||||
for i,v in ipairs(split(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)
|
||||
ifs.mount(id,path)
|
||||
::endline::
|
||||
end
|
||||
end
|
||||
kernel.log("Disks initialized")
|
||||
|
||||
function kernel.saveLog()
|
||||
ifs.writeAllText("/var/log/syslog.log", kernel.LOG_Text)
|
||||
end
|
||||
|
||||
function kernel.newFifo()
|
||||
local fifo = {}
|
||||
fifo.push=function(data)
|
||||
table.insert(fifo, data)
|
||||
end
|
||||
fifo.pop=function()
|
||||
return table.remove(fifo,1)
|
||||
end
|
||||
return fifo
|
||||
end
|
||||
|
||||
function kernel.newUUID()
|
||||
local template = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"
|
||||
local uuid = ""
|
||||
for i = 1, #template do
|
||||
local c = template:sub(i,i)
|
||||
if c == "x" then
|
||||
uuid = uuid .. string.format("%x", math.random(0, 15))
|
||||
elseif c == "y" then
|
||||
uuid = uuid .. string.format("%x", math.random(8, 11))
|
||||
else
|
||||
uuid = uuid .. c
|
||||
end
|
||||
end
|
||||
return uuid
|
||||
end
|
||||
|
||||
kernel.syscalls={}
|
||||
local modules={[0]={}}
|
||||
for i=0, 100 do
|
||||
modules[i]={}
|
||||
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
|
||||
end
|
||||
end
|
||||
|
||||
kernel.ifs=ifs
|
||||
kernel.apis=apis
|
||||
kernel.computer=computer
|
||||
kernel.arch=arch
|
||||
kernel.initdisks=disks
|
||||
kernel.screen=screen
|
||||
kernel.processes={}
|
||||
kernel.fstab=fstab
|
||||
|
||||
kernel.kernelTask = {
|
||||
name="kernel",
|
||||
status="R",
|
||||
pid=0,
|
||||
tgid=0,
|
||||
uid=0,
|
||||
fd={},
|
||||
exit="",
|
||||
sleep=0,
|
||||
ivs=0,
|
||||
vs=0,
|
||||
children={},
|
||||
syscallReturn={},
|
||||
cwd="/",
|
||||
timeSlice=0,
|
||||
lastTime=0,
|
||||
totalTime=0,
|
||||
numRuns=0
|
||||
}
|
||||
kernel.currentTask = kernel.kernelTask
|
||||
|
||||
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["test"]=function() return true 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", 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.main()
|
||||
if kernel.status=="panic" then
|
||||
kernel.panic()
|
||||
end
|
||||
kernel.PANIC("Execution complete")
|
||||
41
Src/Hyperion-kernel/boot/oc/boot.lua
Normal file
41
Src/Hyperion-kernel/boot/oc/boot.lua
Normal file
@@ -0,0 +1,41 @@
|
||||
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
|
||||
}
|
||||
|
||||
local apis={}
|
||||
for i,v in pairs(_G) do
|
||||
if not lua[i] or lua[i]==nil then
|
||||
apis[i]=v
|
||||
_G[i]=nil
|
||||
end
|
||||
end
|
||||
18
Src/Hyperion-kernel/boot/oc/eeprom
Normal file
18
Src/Hyperion-kernel/boot/oc/eeprom
Normal file
@@ -0,0 +1,18 @@
|
||||
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
Src/Hyperion-kernel/boot/oc/initfs.lua
Normal file
1
Src/Hyperion-kernel/boot/oc/initfs.lua
Normal file
@@ -0,0 +1 @@
|
||||
local fs={}
|
||||
11
Src/Hyperion-kernel/boot/safeboot.cfg
Normal file
11
Src/Hyperion-kernel/boot/safeboot.cfg
Normal file
@@ -0,0 +1,11 @@
|
||||
-- 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.
|
||||
-- DEFAULT BOOT CONFIGURATION FILE
|
||||
return {
|
||||
initPath = "/sbin/init.lua",
|
||||
maxOpenFiles = 128,
|
||||
maxFilesPerTask = 16,
|
||||
preempt=true
|
||||
}
|
||||
Reference in New Issue
Block a user