This commit is contained in:
2025-12-08 21:42:20 -05:00
parent 67db52a25f
commit 7bc6d87322
70 changed files with 11403 additions and 58 deletions

10
Test/Hyperion-core-v0.1.0.pkg Executable file
View File

@@ -0,0 +1,10 @@
{
"Name": "Hyperion core",
"Version": "0.1.0",
"Publishers": ["HyperionOS Dev Team"],
"Description": "Core system files and librarys for HyperionOS",
"Dependencies": [
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-kernel-v0.1.0.pkg"
],
"Tar": "https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-core-v0.1.0.tar"
}

View File

@@ -0,0 +1,2 @@
U $;/
U devfs0000;/dev/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,9 @@
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

View File

View File

View File

@@ -0,0 +1,8 @@
local args={...}
local kernel=args[1]
kernel.panic("text")
for i,v in ipairs(kernel.fs.list("/dev")) do
kernl.log(v)
end

View File

@@ -0,0 +1,11 @@
{
"Name": "Hyperion CCT Firmware",
"Version": "0.1.0",
"Publishers": ["HyperionOS Dev Team"],
"Description": "The ComputerCraftTweaked firmware package for HyperionOS.",
"Dependencies": [
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-kernel-v0.1.0.pkg"
],
"Tar": "https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-firmware-cct-v0.1.0.tar",
"BuildCommand": "sudo cp boot/cct/eeprom /dev/eeprom"
}

View File

@@ -0,0 +1,303 @@
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
-- 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 nil, "Coroutine timed out"
elseif ret[1]==false then
return false, ret[2]
else
debug.sethook(co)
return true, 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

View File

@@ -0,0 +1,119 @@
-- 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 = {...}
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
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
_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
-- 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/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(table.unpack(args))
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

View File

@@ -0,0 +1,201 @@
local apis = ({...})[1]
local fs = apis.fs
local native = apis.peripheral
local peripheral = {}
local sides = {"top", "bottom", "left", "right", "front", "back"}
function peripheral.getType(name)
if native.isPresent(name) then
return native.getType(name)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
return native.call(side, "getTypeRemote", name)
end
end
return nil
end
function peripheral.getNames()
local names = {}
for n = 1, #sides do
local side = sides[n]
if native.isPresent(side) then
table.insert(names, side)
end
if native.hasType(side, "peripheral_hub") then
local hubSides = native.call(side, "getConnectedSides")
for _, hubSide in ipairs(hubSides) do
table.insert(names, hubSide)
end
end
end
return names
end
---------------------------------------------------------
-- STORAGE
---------------------------------------------------------
local disks = {} -- real disks
local internal = {} -- "$" disk
---------------------------------------------------------
-- HELPERS
---------------------------------------------------------
local function norm(path)
if not path or path == "" then return "/" end
return fs.combine("/", path)
end
--- Creates a disk object given a base path
local function createDisk(id, basePath, readonly, periph)
basePath = norm(basePath)
local disk = {address=id,isReadOnly=function() return readonly end}
function disk:spaceUsed()
return fs.getCapacity(basePath) - fs.getFreeSpace(basePath)
end
function disk:spaceTotal()
return fs.getCapacity(basePath)
end
function disk:readAllText(path)
local p = fs.combine(basePath, path)
if not fs.exists(p) then return nil, "file not found" end
local h = fs.open(p, "r")
local t = h.readAll()
h.close()
return t
end
function disk:writeAllText(path, text)
local p = fs.combine(basePath, path)
local h = fs.open(p, "w")
if not h then return nil, "cannot write" end
h.write(text)
h.close()
return true
end
function disk:appendAllText(path, text)
local p = fs.combine(basePath, path)
local h = fs.open(p, "a")
if not h then return nil, "cannot append" end
h.write(text)
h.close()
return true
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: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:size(path)
local p = fs.combine(basePath, path)
return fs.getSize(p)
end
return disk
end
---------------------------------------------------------
-- INTERNAL DISK "$" (mapped to "/")
---------------------------------------------------------
internal["$"] = createDisk("$", "/$", false, {
setLabel=function(label)
local h = fs.open("/.label", "w")
h.write(label)
h.close()
end,
getLabel=function()
local h = fs.open("/.label", "r")
local label = h.readAll()
h.close()
return label
end
})
---------------------------------------------------------
-- SCAN REAL DISK PERIPHERALS
---------------------------------------------------------
local function refresh()
-- remove disks that no longer exist
for id, _ in pairs(disks) do
if not peripheral.getType(id) then
disks[id] = nil
end
end
-- detect new disks
for _, name in ipairs(peripheral.getNames()) do
if peripheral.getType(name) == "disk" then
if not disks[name] then
local mount = disk.getMountPath(name)
if mount then
disks[name] = createDisk(name, mount, false, disk)
end
end
end
end
end
---------------------------------------------------------
-- ITERATOR
---------------------------------------------------------
local function iter()
refresh()
-- first internal
local combined = {}
for id, obj in pairs(internal) do
combined[id] = obj
end
for id, obj in pairs(disks) do
combined[id] = obj
end
return pairs(combined)
end
---------------------------------------------------------
-- MODULE RETURN
---------------------------------------------------------
return {
refresh = refresh,
list = iter
}

View File

@@ -0,0 +1,109 @@
local args={...}
local apis=args[1]
local drivers=args[2]
local driver={}
driver.name="CCT TTO Module"
driver.version="0.1.0"
driver.description="CCT TTO Module Kernel Module"
driver.arch="cct"
driver.author="HyperionOS Dev Team"
driver.license="MIT"
driver.api={}
colors={
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
}
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
}
function driver.load()
end
function driver.unload()
-- Nothing to unload
end
function driver.reload()
-- Nothing to reload
end
function driver.main()
-- Nothing to run
end
function driver.api.print(text)
apis.term.write(text.."\n")
end
function driver.api.printInline(text)
apis.term.write(text)
end
function driver.api.clear()
apis.term.clear()
apis.term.setCursorPos(1,1)
end
function driver.api.getSize()
return apis.term.getSize()
end
function driver.api.setBackgroundColor(index)
apis.term.setBackgroundColor(colors[index] or 0)
end
function driver.api.setForegroundColor(index)
apis.term.setTextColor(colors[index] or 0)
end
function driver.api.setCursorPos(x, y)
apis.term.setCursorPos(x, y)
end
function driver.api.getCursorPos()
return apis.term.getCursorPos()
end
function driver.api.getBackgroundColor()
return icolors[apis.term.getBackgroundColor()]
end
function driver.api.getForegroundColor()
return icolors[apis.term.getTextColor()]
end
drivers.register(driver)

View File

@@ -0,0 +1,11 @@
{
"Name": "Hyperion OC Firmware",
"Version": "0.1.0",
"Publishers": ["HyperionOS Dev Team"],
"Description": "The OpenComputers firmware package for HyperionOS.",
"Dependencies": [
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-kernel-v0.1.0.pkg"
],
"Tar": "https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-firmware-oc-v0.1.0.tar",
"BuildCommand": "cp boot/oc/eeprom /dev/eeprom"
}

View File

@@ -0,0 +1,40 @@
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

View 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

View File

@@ -0,0 +1 @@
local fs={}

View File

@@ -0,0 +1,8 @@
{
"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-v0.1.0.tar"
}

View File

@@ -0,0 +1,69 @@
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)
return disk:readAllText(newPath)
end
function fs.writeAllText(path, text)
local disk, newPath = resolve(path)
return disk:writeAllText(newPath, text)
end
function fs.appendAllText(path, text)
local disk, newPath = resolve(path)
return disk:appendAllText(newPath, text)
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

View File

@@ -0,0 +1,166 @@
local args = {...}
local apis = args[1]
local disks = args[2]
local arch = args[3]
local initPath = args[4]
local screen = args[5]
local computer = args[6]
local ifs = args[7]
local LOG_Text = ""
local kernel = {}
kernel.process = "Kernel"
kernel.user = "root"
kernel.group = "root"
kernel.groups = {0}
kernel.uid = 0
kernel.gid = 0
kernel.stage = "start"
kernel.key = {}
kernel.chache = {}
kernel.chache.preload = {}
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"
if kernel.stage == "start" then
screen:print(tostring(computer.time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg)
end
end
function kernel.PANIC(msg)
kernel.log("PANIC: "..msg, "PANIC")
pcall(kernel["saveLog"])
screen:setTextColor(2)
screen:setBackgroundColor(0)
screen:clear()
screen:setCursorPos(1,1)
screen:print(LOG_Text)
screen:print("KERNEL PANIC!\n"..msg.."\nSystem halted.")
screen:print("Press any key to continue...")
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.", "INFO")
kernel.log("Mounting disks...", "INFO")
disks.refresh()
ifs.update(disks)
ifs.mount("$", "/")
function kernel.saveLog()
ifs.writeAllText("/var/log/syslog.log", LOG_Text)
end
local fstab=ifs.readAllText("/etc/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
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)
kernel.log("Mounted "..id.." to "..path)
ifs.mount(id,path)
::endline::
end
end
ifs.remove("/tmp")
ifs.makeDir("/tmp")
local drivers={}
drivers.raw={}
drivers.processes={}
drivers.prior={}
drivers.type={}
for i=0, 99 do
drivers.prior[i]={}
end
function drivers.register(prior,object)
drivers.raw[#drivers.raw+1]=object
if object.main then drivers.processes[#drivers.processes+1]=object.main end
if drivers.prior[prior]==nil then drivers.prior[prior]={} end
drivers.prior[prior][#drivers.prior[prior]+1]=object
if drivers.type[object.type]==nil then drivers.type[object.type]={} end
drivers.type[object.type][#drivers.type[object.type]+1]=object
end
local modules={}
for i=0, 99 do
modules[i]={}
end
for i,v in ipairs(ifs.list("/lib/modules/Hyperion/")) do
local prior=tonumber(v:sub(1,2))
modules[prior][#modules[prior]+1]="/lib/modules/Hyperion/"..v
end
kernel.drivers=drivers
kernel.ifs=ifs
kernel.apis=apis
kernel.computer=computer
kernel.initPath=initPath
kernel.arch=arch
kernel.initdisks=initdisks
kernel.screen=screen
for _,p in ipairs(modules) do
for _,v in ipairs(p) do
local code=ifs.readAllText(v)
local func,err=load(code,"@"..v)
if not func then kernel.log("ModuLoadErr: "..tostring(err)) goto skip end
local status, err = xpcall(func,debug.traceback,kernel)
if not status then goto skip end
if not err then goto skip end
if not err.init then goto skip end
local ok, err = xpcall(status.main,debug.traceback)
if not ok then kernel.log("ModuInitErr: "..tostring(err)) end
::skip::
end
end
kernel.PANIC("Execution complete")

View File

@@ -0,0 +1,137 @@
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
local function serialize(table)
local output = "{"
for i,v in pairs(table) do
local coma=true
if type(i) == "string" then
output=output.."[\""..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.."function() end"
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
table.serialize=serialize

View File

@@ -0,0 +1,217 @@
local args = {...}
local kernel = args[1]
local fs = {}
local disks = {}
local mounts = {["/"]="$"}
-- path normaliing
local function normalizePath(path)
if not path or path == "" then return "/" end
if path:sub(1,1) ~= "/" then path = "/" .. path end
local parts = {}
for part in path:gmatch("[^/]+") do
if part == ".." then
if #parts > 0 then table.remove(parts) end
elseif part ~= "." and part ~= "" then
parts[#parts+1] = part
end
end
return "/" .. table.concat(parts, "/")
end
-- disk resolution
local function resolvePath(path)
local abs = normalizePath(path)
local best = "/"
for mount, diskAddr in pairs(mounts) do
if abs:sub(1, #mount) == mount and #mount > #best then
best = mount
end
end
local newPath = abs:sub(#best + 1)
if newPath == "" then newPath = "/" end
return disks[mounts[best]], newPath
end
-- Symlinks
-- Format: #!@SYMLINK[target]
local SYMLINK_PREFIX = "#!@SYMLINK["
local SYMLINK_SUFFIX = "]"
local SYMLINK_MAX_DEPTH = 64
local function isSymlink(disk, path)
if not disk:fileExists(path) then return false end
local text = disk:readAllText(path)
if not text then return false end
return text:sub(1, #SYMLINK_PREFIX) == SYMLINK_PREFIX
end
local function readSymlink(disk, path)
local text = disk:readAllText(path)
if not text then return nil end
if text:sub(1, #SYMLINK_PREFIX) ~= SYMLINK_PREFIX then return nil end
local target = text:sub(#SYMLINK_PREFIX + 1)
if target:sub(-1) == SYMLINK_SUFFIX then
target = target:sub(1, -2)
end
return target
end
-- Path resolution
local function splitPath(p)
local parts = {}
for part in p:gmatch("[^/]+") do parts[#parts+1] = part end
return parts
end
local function resolveSymlink(path)
path = normalizePath(path)
local symlinkDepth = 0
local parts = splitPath(path)
local resolved = {}
local i = 1
while i <= #parts do
local comp = parts[i]
if comp == "." then
elseif comp == ".." then
if #resolved > 0 then table.remove(resolved) end
else
local currentPath = "/" .. table.concat(resolved, "/")
local disk, p = resolvePath(currentPath .. "/" .. comp)
if isSymlink(disk, p) then
symlinkDepth = symlinkDepth + 1
if symlinkDepth > SYMLINK_MAX_DEPTH then
error("Too many levels of symbolic links: " .. path)
end
local target = readSymlink(disk, p)
if not target then
resolved[#resolved+1] = comp
else
if target:sub(1,1) == "/" then
resolved = splitPath(normalizePath(target))
else
local base = resolved
resolved = {}
for _, seg in ipairs(base) do resolved[#resolved+1]=seg end
for seg in target:gmatch("[^/]+") do
if seg == ".." then
if #resolved>0 then table.remove(resolved) end
elseif seg ~= "." then
resolved[#resolved+1]=seg
end
end
end
local remaining = {}
for j=i+1,#parts do remaining[#remaining+1]=parts[j] end
parts = remaining
i = 0
end
else
resolved[#resolved+1]=comp
end
end
i=i+1
end
local finalPath="/"..table.concat(resolved,"/")
local disk,diskPath=resolvePath(finalPath)
return disk,diskPath
end
-- PUBLIC API: MOUNTING
function fs.mount(disk, mountPoint)
if kernel.uid ~= 0 then error("Permission Denied") end
mounts[mountPoint]=disk
end
function fs.unmount(mountPoint)
if kernel.uid ~= 0 then error("Permission Denied") end
mounts[mountPoint]=nil
end
function fs.virtDisk(diskObj)
if kernel.uid ~= 0 then error("Permission Denied") end
if disks[diskObj.address] then error("Disk exists") end
disks[diskObj.address]=diskObj
end
function fs.eject(addr)
if kernel.uid ~= 0 then error("Permission Denied") end
disks[addr]=nil
end
-- SYMLINK API
function fs.symlink(target, linkPath)
local disk, p = resolvePath(linkPath)
return disk:writeAllText(p, SYMLINK_PREFIX..target..SYMLINK_SUFFIX)
end
function fs.isLink(path)
local disk, p = resolvePath(path)
return isSymlink(disk,p)
end
function fs.readLink(path)
local disk, p = resolvePath(path)
return readSymlink(disk,p)
end
-- FILE OPERATIONS
function fs.exists(path)
local disk, p = resolveSymlink(path)
return disk:fileExists(p) or disk:directoryExists(p)
end
function fs.isFile(path)
local disk, p = resolveSymlink(path)
if isSymlink(disk, p) then return false end
return disk:fileExists(p)
end
function fs.isDir(path)
local disk, p = resolveSymlink(path)
if isSymlink(disk, p) then return false end
return disk:directoryExists(p)
end
function fs.list(path)
local disk, p = resolveSymlink(path)
return disk:list(p)
end
function fs.makeDir(path)
local disk, p = resolveSymlink(path)
return disk:makeDirectory(p)
end
function fs.remove(path)
local disk, p = resolvePath(path)
if isSymlink(disk, p) then
return disk:remove(p)
end
local d2, p2 = resolveSymlink(path)
return d2:remove(p2)
end
function fs.readAllText(path)
local disk, p = resolveSymlink(path)
return disk:readAllText(p)
end
function fs.writeAllText(path, text)
local disk, p = resolveSymlink(path)
return disk:writeAllText(p, text)
end
function fs.appendAllText(path, text)
local disk, p = resolveSymlink(path)
return disk:appendAllText(p, text)
end
function fs.getSize(path)
local disk, p = resolveSymlink(path)
return disk:getSize(p)
end
-- INIT
for _,v in kernel.initdisks.list() do fs.virtDisk(v) end
kernel.fs=fs
kernel.chache.preload.fs=fs
kernel.chache.preload.filesystem=fs

View File

@@ -0,0 +1,22 @@
local args={...}
local kernel=args[1]
local ifs=kernel.ifs
local initdisks=kernel.initdisks
local fstab=ifs.readAllText("/etc/fstab")
kernel.fs.update(initdisks)
for i,v in ipairs(string.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)
kernel.log("Mounted "..id.." to "..path)
kernel.fs.mount(id,path)
::endline::
end
end

View File

@@ -0,0 +1,182 @@
local args={...}
local kernel=args[1]
function kernel.fs.mkvirtfs(address, readOnly, label, autoRegister)
if kernel.uid ~= 0 then error("Permission Denied") end
local disk = {}
disk.address = address
local isRO = readOnly or false
local backend = {
["/"] = { __dir = true }
}
-----------------------------------------------------------------
-- Helpers
-----------------------------------------------------------------
local function norm(path)
if not path or path == "" then return "/" end
if path:sub(1,1) ~= "/" then path = "/" .. path end
path = path:gsub("/+", "/")
return path
end
local function split(path)
local parts = {}
for p in path:gmatch("[^/]+") do table.insert(parts, p) end
return parts
end
local function getNode(path)
path = norm(path)
if path == "/" then return backend["/"] end
local node = backend["/"]
for _, part in ipairs(split(path)) do
node = node[part]
if not node then return nil end
end
return node
end
local function getParent(path)
local parts = split(norm(path))
local name = table.remove(parts)
local parentPath = "/" .. table.concat(parts, "/")
return getNode(parentPath), name
end
local function ensureWrite()
if isRO then return false, "read-only" end
return true
end
-----------------------------------------------------------------
-- File IO (supports string or file-object with read/write funcs)
-----------------------------------------------------------------
local function fileRead(node)
if type(node) == "string" then
return node
elseif type(node) == "table" and node.__file and node.read then
return node.read()
end
return nil
end
local function fileWrite(parent, name, text)
local node = parent[name]
if type(node) == "string" then
parent[name] = text
return true
elseif type(node) == "table" and node.__file and node.write then
return node.write(text)
end
parent[name] = text
return true
end
local function fileAppend(parent, name, text)
local node = parent[name]
if type(node) == "string" then
parent[name] = node .. text
return true
elseif type(node) == "table" and node.__file and node.write then
return node.write((node.read() or "") .. text)
end
parent[name] = text
return true
end
-----------------------------------------------------------------
-- API
-----------------------------------------------------------------
function disk:isReadOnly() return isRO end
function disk:spaceUsed() return 0 end
function disk:spaceTotal() return 0 end
function disk:readAllText(path)
local node = getNode(path)
if not node then return nil, "file not found" end
return fileRead(node)
end
function disk:writeAllText(path, text)
local ok, err = ensureWrite(); if not ok then return false, err end
local parent, name = getParent(path)
if not parent or not parent.__dir then return false, "invalid directory" end
return fileWrite(parent, name, tostring(text))
end
function disk:appendAllText(path, text)
local ok, err = ensureWrite(); if not ok then return false, err end
local parent, name = getParent(path)
if not parent or not parent.__dir then return false, "invalid directory" end
return fileAppend(parent, name, tostring(text))
end
function disk:list(path)
local node = getNode(path)
if not node or not node.__dir then return nil, "not a directory" end
local out = {}
for k, _ in pairs(node) do if k ~= "__dir" then table.insert(out, k) end end
return out
end
function disk:fileExists(path)
local node = getNode(path)
return type(node) == "string" or (type(node) == "table" and node.__file)
end
function disk:directoryExists(path)
local node = getNode(path)
return node and type(node) == "table" and node.__dir or false
end
function disk:makeDirectory(path)
local ok, err = ensureWrite(); if not ok then return false, err end
local parent, name = getParent(path)
if not parent or not parent.__dir then return false, "invalid parent directory" end
parent[name] = { __dir = true }
return true
end
function disk:remove(path)
local ok, err = ensureWrite(); if not ok then return false, err end
local parent, name = getParent(path)
if not parent or not parent[name] then return false, "not found" end
parent[name] = nil
return true
end
function disk:setLabel(new)
local ok, err = ensureWrite(); if not ok then return false, err end
label = tostring(new)
end
function disk:getLabel()
return label
end
function disk:size(path)
local node = getNode(path)
if type(node) == "string" then return #node end
if type(node) == "table" and node.__file and node.read then
local v = node.read()
return v and #v or 0
end
return 0
end
-----------------------------------------------------------------
-- Auto-register with kernel and return backend
-----------------------------------------------------------------
if kernel and kernel.fs and kernel.fs.virtDisk and autoRegister then
kernel.fs.virtDisk(disk)
end
return backend, disk
end

View File

@@ -0,0 +1,56 @@
local args = {...}
local kernel = args[1]
-- List of search paths
local paths = {
"/lib/?",
"/usr/lib/?",
"/usr/local/lib/?"
}
-- Custom require implementation
function require(module)
-- Return cached module if it already exists
if kernel.cache.preload[module] then
return kernel.cache.preload[module]
end
local err = {}
for _, path in ipairs(paths) do
-- Replace "?" with module name
local filePath = string.replace(path, "?", module)
-- Try to open file
local file = kernel.fs.isFile(filePath)
if file then
local content = kernel.fs.readAllText(filePath)
-- Load the module as Lua code
local chunk, loadErr = load(content, filePath)
if not chunk then
table.insert(err, "Error loading: " .. filePath .. ": " .. loadErr)
else
-- Execute the module. If the module returns a value, cache it.
local ok, result = xpcall(chunk, debug.traceback)
if not ok then
table.insert(err, "Error executing: "..filePath..": "..tostring(result))
else
if result ~= nil then
kernel.cache.preload[module] = result
return result
end
-- If module doesn't return anything, cache `true` like Lua does
kernel.cache.preload[module] = true
return true
end
end
else
table.insert(err, "Module not found: " .. filePath)
end
end
-- If nothing worked, raise an error with all reasons
error("Unable to require module '" .. module .. "':\n" .. table.concat(err, "\n"))
end

View File

@@ -0,0 +1,17 @@
local args={...}
local kernel = args[1]
local data = kernel.fs.mkvirtfs("devfs0000", true, "devfs", false)
data["/"]["OSVERSION"]="Hyperion 1.0.0"
data["/"]["eeprom"]={
__file=true,
read=function()
return kernel.computer:getEEPROM()
end,
write=function(text)
if kernel.uid ~= 0 then error("Permission Denied") end
kernel.computer:setEEPROM(text)
end
}

View File

@@ -0,0 +1,12 @@
local args={...}
local kernel=args[1]
kernel.drivers.processes[#kernel.drivers.processes+1]=function()
while true do
local event={kernel.computer:getMachineEvent()}
while event[1]~=nil do
kernel.hpv.sendSig("all", table.unpack(event))
event={kernel.computer:getMachineEvent()}
end
coroutine.yield()
end
end

View File

@@ -0,0 +1,19 @@
local args={...}
local kernel=args[2]
for _,subf in ipairs(kernel.fs.list("/lib/modules/")) do
if subf~="Hyperion" then
for _,driver in ipairs(kernel.fs.list("/lib/modules/"..subf)) do
local code = kernel.fs.readAllText("/lib/modules/"..subf.."/"..driver)
local func, err = load(code, "@"..driver)
if not func then
kernel.log("DriverLoadErr: "..tostring(err), "ERROR")
else
local ok, err = xpcall(func, debug.traceback)
if not ok then
kernel.log("DriverLoadErr: "..tostring(err), "ERROR")
end
end
end
end
end

View File

@@ -0,0 +1,11 @@
local args={...}
local kernel=args[1]
for _,l in ipairs(kernel.drivers.prior) do
for _,d in ipairs(l) do
if d.init then
local ok,err = xpcall(d.init, debug.traceback)
if not ok then kernel.log("DriverInitErr: "..tostring(err)) end
end
end
end

View File

@@ -0,0 +1,167 @@
local args={...}
local kernel = args[1]
local tasks={}
local currentTask={}
local signals={}
local tid=1
local gid=1
local sys={}
function sys.hookSig(sig, func)
if not signals[tostring(currentTask.pid)][sig] then
signals[tostring(currentTask.pid)][sig]={}
end
signals[tostring(currentTask.pid)][sig][#signals[tostring(currentTask.pid)][sig]+1]=func
end
function sys.clearSigHooks(typ)
if not typ or typ == "all" then
signals[tostring(currentTask.pid)]={}
currentTask.signal=signals[tostring(currentTask.pid)]
else
if currentTask.signal[typ] then
currentTask.signal[typ]={}
end
end
end
function sys.sendSig(pid, signal, ...)
if pid=="all" then
for i,v in pairs(tasks) do
v.sigQ[#v.sigQ+1]={signal, ...}
end
return
end
if not tasks[tostring(pid)] then return false end
tasks[tostring(pid)].sigQ[#tasks[tostring(pid)].sigQ+1]={signal, ...}
return true
end
function sys.flushSigs()
local ret = {}
for i=1, #currentTask.sigQ do
if currentTask.signal[currentTask.sigQ[i][1]] then
for _,v in ipairs(currentTask.signal[currentTask.sigQ[1][1]]) do
coroutine.resumeWithTimeout(coroutine.create(function()
local ok, err = xpcall(v, debug.traceback, table.unpack(table.remove(currentTask.sigQ, 1)))
if not ok then
table.insert(ret, err)
end
end), 10)
end
else
for _,v in ipairs(currentTask.signal["unhandledEvent"]) do
coroutine.resumeWithTimeout(coroutine.create(function()
local ok, err = xpcall(v, debug.traceback, table.unpack(table.remove(currentTask.sigQ, 1)))
if not ok then
table.insert(ret, err)
end
end), 10)
end
end
end
end
function sys.spawn(func, name, evars, args)
local id=tid
tid=tid+1
name=name or tostring(id)
signals[tostring(id)]={}
tasks[tostring(id)]={
coro=coroutine.create(function()
local ret = {xpcall(func, debug.traceback, table.unpack(args))}
if not ret[1] then
sys.sendSig(currentTask.ppid, "ChildTaskError", id, err)
else
sys.sendSig(currentTask.ppid, "ChildTaskExit", id, table.unpack(ret, 2))
end
currentTask.status="Z"
end),
name=name,
pid=id,
ppid=currentTask.pid,
tgid=currentTask.tgid,
user=kernel.user,
uid=kernel.uid,
evars=evars,
args=args,
vy=0,
ivy=0,
status="R",
signal=signals[tostring(id)],
parent=currentTask,
children={},
sibling=currentTask.children,
sigQ={}
}
end
local function collectZombieProc()
local ret = {}
for _,v in pairs(tasks) do
if v.status=="Z" then
local pid = v.pid
for _,c in ipairs(v.children) do
c.parent=tasks["1"]
c.sibling=tasks["1"].children
c.ppid=1
c.tgid=1
end
signals[tostring(pid)]=nil
tasks[tostring(pid)]=nil
table.insert(ret, pid)
end
end
return ret
end
signals["1"]={}
tasks["1"]={
coro=coroutine.create(function()
local ret = {xpcall(kernel.fs.load(kernel.initPath), debug.traceback)}
if not ok then
kernel.panic(err)
else
kernel.panic("Attempted to kill init!")
end
end),
name="SysInit",
pid=1,
ppid=0,
tgid=1,
user=kernel.user,
uid=kernel.uid,
evars={},
args={kernel},
vy=0,
ivy=0,
status="R",
signal=signals["1"],
parent={name="Hyprkrnl",pid=0},
children={},
sibling={},
sigQ={}
}
kernel.chache.preload.sys=sys
kernel.chache.preload.system=sys
kernel.hpv=sys
kernel.saveLog()
while true do
for _,v in pairs(tasks) do
currentTask=v
kernel.user=currentTask.user
kernel.uid=currentTask.uid
sys.flushSigs()
local status = coroutine.resumeWithTimeout(currentTask.coro, 50)
if status then
currentTask.vy=currentTask.vy+1
else
currentTask.ivy=currentTask.ivy+1
end
end
collectZombieProc()
end
kernel.panic("Exited pid 0")

14
Test/HyperionOS.pkg Executable file
View File

@@ -0,0 +1,14 @@
{
"Name": "HyperionOS",
"Version": "0.1.0",
"Publishers": ["HyperionOS Dev Team"],
"Description": "A sample package for HyperionOS project.",
"Dependencies": [
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-core-v0.1.0.pkg",
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-kernel-v0.1.0.pkg",
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-ui-v0.1.0.pkg",
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-network-v0.1.0.pkg",
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-security-v0.1.0.pkg",
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-filesystem-v0.1.0.pkg"
]
}

16
Test/palette_16.txt Executable file
View File

@@ -0,0 +1,16 @@
0: #000000
1: #FFFFFF
2: #FF0000
3: #00FF00
4: #0000FF
5: #00FFFF
6: #FF00FF
7: #FFFF00
8: #FF6D00
9: #6DFF55
10: #24FFFF
11: #924900
12: #6D6D55
13: #DBDBAA
14: #6D00FF
15: #B6FF00