stuff.mp4

This commit is contained in:
2025-12-17 11:53:54 -05:00
parent 6d9d02edf7
commit e63bb275a0
92 changed files with 1060 additions and 965 deletions

2
.vscode/tasks.json vendored Executable file → Normal file
View File

@@ -15,7 +15,7 @@
"if (Test-Path '${workspaceFolder}\\Build') { Remove-Item -LiteralPath '${workspaceFolder}\\Build' -Recurse -Force -ErrorAction SilentlyContinue }; New-Item -ItemType Directory -Path '${workspaceFolder}\\Build' | Out-Null; Get-ChildItem -Path '${workspaceFolder}\\Test' -Directory | ForEach-Object { $base = $_.FullName; Get-ChildItem -Path $base -File -Recurse | ForEach-Object { $rel = $_.FullName.Substring($base.Length).TrimStart(\"\\\"); $destPath = Join-Path '${workspaceFolder}\\Build' $rel; $destDir = Split-Path $destPath; if (-not (Test-Path $destDir)) { New-Item -ItemType Directory -Path $destDir | Out-Null }; Copy-Item -LiteralPath $_.FullName -Destination $destPath -Force } }"
]
},
"linux": {
"command": "bash",
"args": [

BIN
Build.tar

Binary file not shown.

20
Build/bin/bash Normal file
View File

@@ -0,0 +1,20 @@
local args={...}
local os=require("os")
local io=require("io")
local text=""
local blockKeyEvents=false
io.link(io.focas)
os.hookSignal("keyTyped", function(_, screen, key)
if blockKeyEvents then return end
if key == "\n" then
blockKeyEvents=true
elseif key == "\b" then
text=text:sub(1,#text-1)
io.stdout.printInline("\b")
else
text=text..key
io.stdout.printInline(key)
end
end)

0
Build/boot/cct/boot.lua Executable file → Normal file
View File

0
Build/boot/cct/eeprom Executable file → Normal file
View File

0
Build/boot/cct/initdisks Executable file → Normal file
View File

0
Build/boot/initfs Executable file → Normal file
View File

0
Build/boot/kernel.lua Executable file → Normal file
View File

0
Build/boot/oc/boot.lua Executable file → Normal file
View File

0
Build/boot/oc/eeprom Executable file → Normal file
View File

0
Build/boot/oc/initfs.lua Executable file → Normal file
View File

0
Build/etc/fstab Executable file → Normal file
View File

0
Build/lib/LibDeflate Executable file → Normal file
View File

0
Build/lib/deflate Executable file → Normal file
View File

0
Build/lib/modules/CC-Tweaked/modem.kmod Executable file → Normal file
View File

0
Build/lib/modules/CC-Tweaked/redstone.kmod Executable file → Normal file
View File

0
Build/lib/modules/CC-Tweaked/tty.kmod Executable file → Normal file
View File

33
Build/lib/modules/Hyperion/00_stdlib.kmod Executable file → Normal file
View File

@@ -192,5 +192,38 @@ local function serialize(table)
return output
end
local oldtype=type
local oldgetmetatable=getmetatable
function type(object)
if oldtype(object)~="table" then
return oldtype(object)
else
if oldtype(oldgetmetatable(object))=="table" then
local metatable = oldgetmetatable(object)
if metatable.__type then return metatable.__type end
else
return "table"
end
end
end
function getmetatable(object)
if oldtype(object)~="table" then return end
if oldtype(oldgetmetatable(object))=="table" then
if oldgetmetatable(object).__isuserdata then
if oldtype(oldgetmetatable(object).__usermeta)=="function" then
return oldgetmetatable(object).__usermeta()
else
return oldgetmetatable(object).__usermeta
end
else
return oldgetmetatable(object)
end
else
return oldgetmetatable(object)
end
end
table.serialize=serialize
kernel.log("Loaded stdlib")

0
Build/lib/modules/Hyperion/05_userspace.kmod Executable file → Normal file
View File

36
Build/lib/modules/Hyperion/10_vfs.kmod Executable file → Normal file
View File

@@ -8,6 +8,7 @@ local fs = {}
local disks = {} -- address → disk object
local mounts = {["/"] = "$"} -- mountpoint → disk address (root = boot disk)
local cwd = "/"
local SYMLINK_PREFIX = "#!@SYMLINK["
local SYMLINK_SUFFIX = "]"
@@ -27,10 +28,11 @@ end
local function normalizePath(path)
if not path or path == "" then return "/" end
-- ensure absolute
-- cwd
if path:sub(1,1) ~= "/" then
path = "/" .. path
path=cwd..path
end
local parts = splitPath(path)
local out = {}
@@ -300,7 +302,35 @@ function fs.getSize(path, ...)
return disk:getSize(p, ...)
end
-- =====================================================================
-- WD STUFF
-- =====================================================================
function fs.setCwd(path)
if not path or path == "" then return "/" end
-- ensure absolute
if path:sub(1,1) ~= "/" then
path = "/" .. path
end
local parts = splitPath(path)
local out = {}
for _,part in ipairs(parts) do
if part == ".." then
if #out > 0 then table.remove(out) end
elseif part ~= "." and part ~= "" then
out[#out+1] = part
end
end
cwd="/" .. table.concat(out, "/")
end
function fs.getCwd(path)
return cwd
end
-- =====================================================================
-- INIT
@@ -317,5 +347,5 @@ if not ok then kernel.panic(err) end
kernel.disks=disks
kernel.mounts=mounts
kernel.fs = fs
kernel.cache.preload.fs = table.proxy(kernel.fs)
kernel.cache.preload.fs = fs
kernel.cache.preload.filesystem = kernel.cache.preload.fs

0
Build/lib/modules/Hyperion/11_mkvirtfs.kmod Executable file → Normal file
View File

0
Build/lib/modules/Hyperion/11_require.kmod Executable file → Normal file
View File

0
Build/lib/modules/Hyperion/12_devfs.kmod Executable file → Normal file
View File

0
Build/lib/modules/Hyperion/12_sysfs.kmod Executable file → Normal file
View File

0
Build/lib/modules/Hyperion/13_procfs.kmod Executable file → Normal file
View File

0
Build/lib/modules/Hyperion/15_fstabInit.kmod Executable file → Normal file
View File

4
Build/lib/modules/Hyperion/20_keventd.kmod Executable file → Normal file
View File

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

View File

@@ -0,0 +1,15 @@
local args={...}
local kernel=args[1]
local io={}
local iolib={}
io.stdout={}
io.stdin={}
io.stderr={}
iolib.stdout=io.stdout
iolib.stdin =io.stdin
iolib.stderr=io.stderr
function io.register(ttyObj)

0
Build/lib/modules/Hyperion/31_thirdPartyInit.kmod Executable file → Normal file
View File

0
Build/lib/modules/Hyperion/50_mutiUserAuth.kmod Executable file → Normal file
View File

0
Build/lib/modules/Hyperion/98_dbgProtect.kmod Executable file → Normal file
View File

63
Build/lib/modules/Hyperion/99_init.kmod Executable file → Normal file
View File

@@ -8,7 +8,7 @@ local gid=2
local hookuuid=0
local sys={}
function sys.hookSig(sig, func)
function sys.hookSignal(sig, func)
if not currentTask.signal[sig] then
currentTask.signal[sig]={}
end
@@ -22,7 +22,7 @@ function sys.hookSig(sig, func)
}
end
function sys.clearSigHooks(typ)
function sys.clearSignalHooks(typ)
if not typ or typ == "all" then
signals[tostring(currentTask.pid)]={}
currentTask.signal=signals[tostring(currentTask.pid)]
@@ -33,9 +33,9 @@ function sys.clearSigHooks(typ)
end
end
function sys.sendSig(pid, signal, ...)
function sys.sendSignal(pid, signal, ...)
if pid=="all" then
for i,v in pairs(tasks) do+
for i,v in pairs(tasks) do
v.sigQ[#v.sigQ+1]={signal, ...}
end
return
@@ -57,7 +57,7 @@ function sys.flushSigs()
coroutine.resumeWithTimeout(coroutine.create(function()
local ok,err = xpcall(v,debug.traceback,table.unpack(sig))
if not ok and sig[1]~="callbackErr" then
sys.sendSig(currentTask.pid, "callbackErr", sig[1], k, err)
sys.sendSignal(currentTask.pid, "callbackErr", sig[1], k, err)
end
end),10)
end
@@ -66,7 +66,7 @@ function sys.flushSigs()
coroutine.resumeWithTimeout(coroutine.create(function()
local ok,err = xpcall(v,debug.traceback,table.unpack(sig))
if not ok and sig[1]~="callbackErr" then
sys.sendSig(currentTask.pid, "callbackErr", sig[1], k, err)
sys.sendSignal(currentTask.pid, "callbackErr", sig[1], k, err)
end
end),10)
end
@@ -74,7 +74,7 @@ function sys.flushSigs()
end
end
function sys.spawn(func, name, evars, args, stdin, stdout, stderr)
function sys.spawn(func, name, evars, args)
local id=tid
tid=tid+1
name=name or tostring(id)
@@ -84,14 +84,15 @@ function sys.spawn(func, name, evars, args, stdin, stdout, stderr)
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)
sys.sendSignal(currentTask.ppid, "ChildTaskError", id, err)
else
sys.sendSig(currentTask.ppid, "ChildTaskExit", id, table.unpack(ret, 2))
sys.sendSignal(currentTask.ppid, "ChildTaskExit", id, table.unpack(ret, 2))
end
currentTask.status="Z"
end),
name=name,
pid=id,
cwd=currentTask.cwd,
ppid=currentTask.pid,
tgid=currentTask.tgid,
user=kernel.user,
@@ -108,10 +109,46 @@ function sys.spawn(func, name, evars, args, stdin, stdout, stderr)
sibling=currentTask.children,
sigQ={}
}
return id
end
function sys.spawnFromFile(path, name, envars, args)
sys.spawn(kernel.fs.load(path), name, envars, args)
end
function sys.spawnAndWait(func, name, envars, args)
local id=sys.spawn(func, name, envars, args)
local exit = false
local errored = false
local rets = {}
local hext=sys.hookSignal("ChildTaskExit",function(pid, ...)
if pid==id then
rets={...}
exit=true
end
end)
local herr=sys.hookSignal("ChildTaskError",function(pid, ...)
if pid==id then
rets={...}
exit=true
errored=true
end
end)
while not exit do
coroutine.yield()
end
return not errored, table.unpack(rets)
end
function sys.spawnFromFileAndWait(path, name, envars, args)
return sys.spawnAndWait(kernel.fs.load(path), name, envars, args)
end
function sys.exit(...)
sys.sendSig(currentTask.ppid, "ChildTaskExit", currentTask.pid, ...)
sys.sendSignal(currentTask.ppid, "ChildTaskExit", currentTask.pid, ...)
currentTask.status="Z"
coroutine.yield()
end
@@ -157,6 +194,7 @@ tasks["1"]={
end),
name="SysInit",
pid=1,
cwd="",
ppid=0,
tgid=1,
user="root",
@@ -176,7 +214,7 @@ tasks["1"]={
tasks["1"].sibling={tasks["1"]}
kernel.log("Created pid 1")
kernel.cache.preload.sys=table.proxy(sys)
kernel.cache.preload.sys=sys
kernel.cache.preload.system=kernel.cache.preload.sys
kernel.cache.preload.os=kernel.cache.preload.sys
kernel.hpv=sys
@@ -189,10 +227,12 @@ kernel.status="running"
while kernel.status~="Panic" do
for k,v in pairs(tasks) do
currentTask=v
kernel.computer:print(currentTask.name)
kernel.currentTask=v
kernel.process=currentTask.name
kernel.user=currentTask.user
kernel.uid=currentTask.uid
kernel.fs.setCwd(currentTask.cwd)
sys.flushSigs()
local status = coroutine.resumeWithTimeout(currentTask.coro, 50)
if status then
@@ -200,6 +240,7 @@ while kernel.status~="Panic" do
else
currentTask.ivy=currentTask.ivy+1
end
currentTask.cwd=kernel.fs.getCwd()
end
collectZombieProc()
end

11
Build/lib/userdata Normal file
View File

@@ -0,0 +1,11 @@
local userdata={}
userdata.policy={}
userdata.policy.readOnly=1
userdata.policy.readWrite=2
userdata.policy.WriteOnly=3
userdata.policy.hidden=4
userdata.policy.custom=5
function userdata.create()
return setmetatable()
end

3
Build/sbin/init Executable file → Normal file
View File

@@ -1,3 +1,6 @@
local args={...}
local kernel=args[1]
for i,v in pairs(kernel.drivers.processes) do
os.spawn(v, i, {}, {})
end
kernel.fs.load("/bin/bash")()

0
LICENSE Executable file → Normal file
View File

0
README.md Executable file → Normal file
View File

0
Src/iso.lua Executable file → Normal file
View File

View File

@@ -0,0 +1,10 @@
{
"Name": "Hyperion bash",
"Version": "1.0.0",
"Publishers": ["HyperionOS Dev Team"],
"Description": "basic bash shell",
"Dependencies": [
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-core-v1.0.0.pkg"
],
"Tar": "https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-bash-v1.0.0.tar"
}

View File

@@ -0,0 +1,20 @@
local args={...}
local os=require("os")
local io=require("io")
local text=""
local blockKeyEvents=false
io.link(io.focas)
os.hookSignal("keyTyped", function(_, screen, key)
if blockKeyEvents then return end
if key == "\n" then
blockKeyEvents=true
elseif key == "\b" then
text=text:sub(1,#text-1)
io.stdout.printInline("\b")
else
text=text..key
io.stdout.printInline(key)
end
end)

View File

@@ -1,3 +0,0 @@
local args={...}
local kernel=args[1]
kernel.fs.load("/bin/bash")()

View File

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

View File

@@ -0,0 +1,138 @@
local fs={}
-- 1 : open
-- 2 : read
-- 3 : write
-- 4 : close
function fs.open(path, mode)
local fd=cororoutine.yield(1,path,mode)
local ret={
close=function()
-- close file
return coroutine.yield(4,fd)
end,
flush=function()
-- close and reopen file to flush buffers
coroutine.yield(4,fd)
fd=coroutine.yield(1,path,mode)
end
}
if mode=="r" then
ret.read=function(count)
return coroutine.yield(2,fd,count)
end
ret.readAll=function()
local chunks={} -- to store read chunks
while true do
local chunk=coroutine.yield(2,fd,math.huge)
if chunk==nil or #chunk==0 then break end
table.insert(chunks,chunk)
end
return table.concat(chunks)
end
ret.readLine = function()
local buffer = {} -- stores leftover data
local buffer_str = "" -- concatenated buffer
local chunk_size = 4096 -- adjust chunk size for performance
local eof = false
while true do
-- Try to find a newline in the current buffer
local line_end = buffer_str:find("\n")
if line_end then
local line = buffer_str:sub(1, line_end - 1)
buffer_str = buffer_str:sub(line_end + 1)
return line
end
-- If EOF was reached previously and buffer is empty, stop
if eof then
if buffer_str ~= "" then
local last_line = buffer_str
buffer_str = ""
return last_line
else
return nil
end
end
-- Read the next chunk
local chunk = coroutine.yield(2, fd, chunk_size)
if not chunk or chunk == "" then
eof = true
else
buffer_str = buffer_str .. chunk
end
end
end
elseif mode=="w" then
ret.write=function(data)
-- write data to file
return coroutine.yield(3,fd,data)
end
elseif mode=="a" then
ret.write=function(data)
-- append data to file
return coroutine.yield(3,fd,data)
end
else
error("Invalid mode '"..mode.."'",2)
end
return ret
end
function fs.readAllText(path)
local file=fs.open(path,"r")
if not file then return false end
local content=file.readAll()
file.close()
return content
end
function fs.writeAllText(path, data)
local file=fs.open(path,"w")
file.write(data)
file.close()
end
function fs.appendAllText(path, data)
local file=fs.open(path,"a")
if not file then return false end
file.write(data)
file.close()
end
function fs.mkdir(path)
coroutine.yield(8,path)
end
function fs.remove(path)
coroutine.yield(9,path)
end
function fs.list(path)
return coroutine.yield(5,path)
end
function fs.type(path)
return coroutine.yield(6,path)
end
function fs.attributes(path)
return coroutine.yield(7,path)
end
function fs.exists(path)
return coroutine.yield(10, path)
end
function fs.getcwd()
return coroutine.yield(11)
end
function fs.setcwd(path)
return coroutine.yield(12, path)
end
return fs

View File

@@ -0,0 +1,74 @@
local sys = {}
local fs = require("fs")
function sys.spawn(func, name, envars, args)
return coroutine.yield(0x10, func, name, envars, args)
end
function sys.spawnFromFile(path, name, envars, args)
local data = fs.readAllText(path)
if not data then
error("File not found: "..path,2)
end
local func, err = load(data, "@"..path)
if not func then
error("Error loading file "..path..": "..tostring(err),2)
end
return coroutine.yield(0x10, func, name, envars, args)
end
function sys.spawnAndWait(func, name, envars, args)
local pid = coroutine.yield(0x10, func, name, envars, args)
local oldsignal = sys.getSignalHandler(17)
local exit = false
sys.setSignalHandler(17, function()
local tasks = sys.getChildrenTasks(pid)
if not tasks[pid] then
exit = true
end
end)
while not exit do
coroutine.yield()
end
sys.setSignalHandler(17, oldsignal)
return pid
end
function sys.spawnFromFileAndWait(path, name, envars, args)
local data = fs.readAllText(path)
if not data then
error("File not found: "..path,2)
end
local func, err = load(data, "@"..path)
if not func then
error("Error loading file "..path..": "..tostring(err),2)
end
return sys.spawnAndWait(func, name, envars, args)
end
function sys.exit(code)
return coroutine.yield(0x14, code)
end
function sys.setSignalHandler(signal, func)
return coroutine.yield(0x11, signal, func)
end
function sys.sendSignal(pid, signal)
return coroutine.yield(0x12, pid, signal)
end
function sys.getSignalHandler(signal)
return coroutine.yield(0x13, signal)
end
function sys.getChildrenTasks(PID)
PID = PID or sys.getCurrentTaskID()
return coroutine.yield(0x15, PID)
end
function sys.getCurrentTaskID()
return coroutine.yield(0x16)
end
return sys

View File

@@ -0,0 +1,11 @@
local userdata={}
userdata.policy={}
userdata.policy.readOnly=1
userdata.policy.readWrite=2
userdata.policy.WriteOnly=3
userdata.policy.hidden=4
userdata.policy.custom=5
function userdata.create()
return setmetatable()
end

View File

@@ -0,0 +1,7 @@
local args={...}
local kernel=args[1]
local os=require("os")
for i,v in pairs(kernel.drivers.processes) do
os.spawn(v, i, {}, {})
end
kernel.fs.load("/bin/bash")()

View File

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

View File

@@ -107,6 +107,11 @@ local ok, err = xpcall(function()
end
end
function sleep(time)
local stoptime = apis.os.clock() + (time*1000)
while stoptime > apis.os.clock() do end
end
-- Set up terminal default colors
apis.term.setPaletteColor(0x1, 0x000000) -- #000000
apis.term.setPaletteColor(0x2, 0xFFFFFF) -- #FFFFFF
@@ -256,12 +261,12 @@ local ok, err = xpcall(function()
end, "", 1000)
local ret = {coroutine.resume(co, ...)}
if ret[1]=="timeout" then
return nil, "Coroutine timed out"
return true, "Coroutine timed out"
elseif ret[1]==false then
return false, ret[2]
else
debug.sethook(co)
return true, table.unpack(ret)
return computer.time()-startTime, table.unpack(ret)
end
end

View File

@@ -62,33 +62,6 @@ local function createDisk(id, basePath, readonly, periph)
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
@@ -105,6 +78,17 @@ local function createDisk(id, basePath, readonly, periph)
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)
@@ -125,9 +109,14 @@ local function createDisk(id, basePath, readonly, periph)
return periph.getLabel()
end
function disk:size(path)
function disk:attributes(path)
local p = fs.combine(basePath, path)
return fs.getSize(p)
return fs.attributes(p)
end
function disk:open(path, mode)
local p = fs.combine(basePath, path)
return fs.open(p, mode)
end
return disk

View File

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

View File

@@ -1,321 +0,0 @@
local args = {...}
local kernel = args[1]
local fs = {}
-- =====================================================================
-- INTERNAL STATE
-- =====================================================================
local disks = {} -- address → disk object
local mounts = {["/"] = "$"} -- mountpoint → disk address (root = boot disk)
local SYMLINK_PREFIX = "#!@SYMLINK["
local SYMLINK_SUFFIX = "]"
local SYMLINK_MAX_DEPTH = 64
-- =====================================================================
-- PATH NORMALIZATION
-- =====================================================================
local function splitPath(p)
local t = {}
for part in p:gmatch("[^/]+") do t[#t+1] = part end
return t
end
local function normalizePath(path)
if not path or path == "" then return "/" end
-- ensure absolute
if path:sub(1,1) ~= "/" then
path = "/" .. path
end
local parts = splitPath(path)
local out = {}
for _,part in ipairs(parts) do
if part == ".." then
if #out > 0 then table.remove(out) end
elseif part ~= "." and part ~= "" then
out[#out+1] = part
end
end
return "/" .. table.concat(out, "/")
end
-- =====================================================================
-- DISK & MOUNT RESOLUTION
-- =====================================================================
-- Finds which disk owns an absolute path
local function resolveMount(abs)
local best = "/"
for mount, addr in pairs(mounts) do
if abs:sub(1, #mount) == mount then
if #mount > #best then
best = mount
end
end
end
local disk = disks[mounts[best]]
if not disk then
error("No disk registered for mount: " .. best)
end
local sub = abs:sub(#best + 1)
if sub == "" then sub = "/" end
return disk, sub
end
-- =====================================================================
-- SYMLINK HANDLING
-- =====================================================================
local function isSymlinkRaw(disk, p)
if not disk:fileExists(p) then return false end
local text = disk:readAllText(p)
return text and text:sub(1, #SYMLINK_PREFIX) == SYMLINK_PREFIX
end
local function readSymlinkRaw(disk, p)
local text = disk:readAllText(p)
if not text then return nil end
if text:sub(1, #SYMLINK_PREFIX) ~= SYMLINK_PREFIX then return nil end
local t = text:sub(#SYMLINK_PREFIX + 1)
if t:sub(-1) == SYMLINK_SUFFIX then
t = t:sub(1, -2)
end
return t
end
-- =====================================================================
-- FULL PATH RESOLUTION (FOLLOWS SYMLINKS)
-- =====================================================================
local function resolveSymlink(path)
local abs = normalizePath(path)
local parts = splitPath(abs)
local out = {}
local depth = 0
local idx = 1
while idx <= #parts do
local comp = parts[idx]
if comp == "." then
-- nothing
elseif comp == ".." then
if #out > 0 then table.remove(out) end
else
local curAbs = "/" .. table.concat(out, "/")
if curAbs ~= "/" then curAbs = curAbs .. "/" end
curAbs = curAbs .. comp
local disk, dpath = resolveMount(curAbs)
if isSymlinkRaw(disk, dpath) then
depth = depth + 1
if depth > SYMLINK_MAX_DEPTH then
error("Too many symlink levels: " .. path)
end
local target = readSymlinkRaw(disk, dpath)
if target then
local newAbs
if target:sub(1,1) == "/" then
-- absolute target
newAbs = normalizePath(target)
else
-- relative to current out[]
local tmp = "/" .. table.concat(out, "/")
if tmp ~= "/" then tmp = tmp .. "/" end
tmp = tmp .. target
newAbs = normalizePath(tmp)
end
-- rebuild remaining parts
local remaining = {}
for j = idx + 1, #parts do
remaining[#remaining+1] = parts[j]
end
-- restart symlink resolution with new path
abs = newAbs
parts = splitPath(abs)
-- append remaining
for _,x in ipairs(remaining) do parts[#parts+1] = x end
out = {}
idx = 0
else
out[#out+1] = comp
end
else
out[#out+1] = comp
end
end
idx = idx + 1
end
local finalAbs = "/" .. table.concat(out, "/")
return resolveMount(finalAbs)
end
-- =====================================================================
-- PUBLIC API
-- =====================================================================
-- MOUNT OPERATIONS -----------------------------------------------------
function fs.virtDisk(diskObj)
if kernel.uid ~= 0 then error("Permission Denied") end
if disks[diskObj.address] then
error("Disk exists: " .. diskObj.address)
end
disks[diskObj.address] = diskObj
end
function fs.mount(disk, mountPoint)
if kernel.uid ~= 0 then error("Permission Denied") end
mountPoint = normalizePath(mountPoint)
local drive, path = resolveMount(normalizePath(mountPoint))
if not drive:directoryExists(path) then error("Must mount on folder") end
if mountPoint ~= "/" and mounts[mountPoint] then
error("Already mounted: " .. mountPoint)
end
mounts[mountPoint] = disk
end
function fs.unmount(mountPoint)
if kernel.uid ~= 0 then error("Permission Denied") end
mountPoint = normalizePath(mountPoint)
if mountPoint == "/" then error("Cannot unmount root") end
mounts[mountPoint] = nil
end
function fs.eject(addr)
if kernel.uid ~= 0 then error("Permission Denied") end
disks[addr] = nil
end
function fs.isMount(path)
if mounts[normalizePath(path)] then return true, mounts[normalizePath(path)] end
end
-- SYMLINK API ----------------------------------------------------------
function fs.symlink(target, linkPath)
kernel.log("WARNING: Symlinks are a untested feature if you find any bugs please report them to https://git.astronand.dev/Hyperion/HyperionOS","WARN")
local disk, p = resolveMount(normalizePath(linkPath))
return disk:writeAllText(p, SYMLINK_PREFIX .. target .. SYMLINK_SUFFIX)
end
function fs.isLink(path)
local disk, p = resolveMount(normalizePath(path))
return isSymlinkRaw(disk, p)
end
function fs.readLink(path)
local disk, p = resolveMount(normalizePath(path))
return readSymlinkRaw(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)
return disk:fileExists(p, ...)
end
function fs.isDir(path, ...)
local disk, p = resolveSymlink(path)
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
-- remove does NOT follow symlinks (UNIX semantics)
function fs.remove(path, ...)
if fs.isMount(path) then return "Cannot delete mounted folder" end
local abs = normalizePath(path)
local disk, p = resolveMount(abs)
return disk:remove(p, ...)
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.load(path, name, ...)
return load(fs.readAllText(path, ...), name or path, nil, kernel._U)
end
function fs.getSize(path, ...)
local disk, p = resolveSymlink(path)
return disk:getSize(p, ...)
end
-- =====================================================================
-- INIT
-- =====================================================================
kernel.log("Loading disks for vfs")
local ok,err = xpcall(function()
for _,v in kernel.initdisks.list() do
fs.virtDisk(v)
end
end, debug.traceback)
if not ok then kernel.panic(err) end
kernel.disks=disks
kernel.mounts=mounts
kernel.fs = fs
kernel.cache.preload.fs = table.proxy(kernel.fs)
kernel.cache.preload.filesystem = kernel.cache.preload.fs

View File

@@ -1,179 +0,0 @@
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
local ok, err = ensureWrite(); if not ok then return false, err end
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
local ok, err = ensureWrite(); if not ok then return false, err end
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 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 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 autoRegister then
kernel.fs.virtDisk(disk)
end
return backend, disk
end

View File

@@ -1,56 +0,0 @@
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]~=nil 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
kernel.log("Created require")

View File

@@ -1,57 +0,0 @@
local args = {...}
local kernel = args[1]
local data = kernel.fs.mkvirtfs("devfs0000", true, "devfs", true)
if not kernel.fs.isDir("/dev") then kernel.fs.makeDir("/dev") end
kernel.devfs={}
kernel.devfs.data=data
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
}
data["/"]["null"]={
__file=true,
read=function() end,
write=function() end
}
data["/"]["random"]={
__file=true,
read=function(amount)
local s = ""
for i = 1, amount do
s = s .. string.char(math.random(0, 255))
end
return s
end,
write=function() end
}
data["/"]["zero"]={
__file=true,
read=function(amount)
return ("\0"):rep(amount)
end,
write=function() end
}
data["/"]["rtc0"]={
__file=true,
read=function()
return kernel.computer:time()
end,
write=function() end
}
data["/"]["rtc"]={
__file=true,
read=function()
return kernel.computer:time()
end,
write=function() end
}
kernel.log("Created devfs")

View File

@@ -1,18 +0,0 @@
local args = {...}
local kernel = args[1]
local data = kernel.fs.mkvirtfs("sysfs0000", true, "sysfs", true)
if not kernel.fs.isDir("/sys") then kernel.fs.makeDir("/sys") end
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
}
kernel.log("Created sysfs")

View File

@@ -1,26 +0,0 @@
local args = {...}
local kernel = args[1]
local ifs=kernel.ifs
kernel.log("Mounting fstab")
local fstab=ifs.readAllText("/etc/fstab")
local entrys = string.split(fstab,"\n")
for i,v in ipairs(entrys) 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,#v)
if i~=#entrys then
path=path:sub(1,#path-1)
end
kernel.log("Mounted "..id.." to "..path)
kernel.fs.mount(id,path)
::endline::
end
end
kernel.log("Mounted all disks")

View File

@@ -1,13 +0,0 @@
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
kernel.log("Created keventd daemon")

View File

@@ -1,210 +0,0 @@
local args = {...}
local kernel = args[1]
local tasks={}
local currentTask={}
local signals={}
local tid=2
local gid=2
local hookuuid=0
local sys={}
function sys.hookSig(sig, func)
if not currentTask.signal[sig] then
currentTask.signal[sig]={}
end
hookuuid=hookuuid+1
currentTask.signal[sig][tostring(hookuuid)]=func
callbackid=tostring(hookuuid)
return {
remove=function()
currentTask.signal[sig][callbackid]=nil
end
}
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 sigs = {}
for i,v in ipairs(currentTask.sigQ) do
sigs[i]=v
end
for i=1, #sigs do
local sig = sigs[i]
if currentTask.signal[sig[1]] then
for k,v in pairs(currentTask.signal[sig[1]]) do
coroutine.resumeWithTimeout(coroutine.create(function()
local ok,err = xpcall(v,debug.traceback,table.unpack(sig))
if not ok and sig[1]~="callbackErr" then
sys.sendSig(currentTask.pid, "callbackErr", sig[1], k, err)
end
end),10)
end
else
for k,v in pairs(currentTask.signal["unhandledSignal"]) do
coroutine.resumeWithTimeout(coroutine.create(function()
local ok,err = xpcall(v,debug.traceback,table.unpack(sig))
if not ok and sig[1]~="callbackErr" then
sys.sendSig(currentTask.pid, "callbackErr", sig[1], k, err)
end
end),10)
end
end
end
end
function sys.spawn(func, name, evars, args, stdin, stdout, stderr)
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",
sleep=0,
signal=signals[tostring(id)],
parent=currentTask,
children={},
sibling=currentTask.children,
sigQ={}
}
end
function sys.exit(...)
sys.sendSig(currentTask.ppid, "ChildTaskExit", currentTask.pid, ...)
currentTask.status="Z"
coroutine.yield()
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
kernel.log("initPath is: " .. tostring(kernel.initPath))
signals["1"]={}
tasks["1"]={
coro=coroutine.create(function()
local ok, code_or_err = xpcall(function() return kernel.fs.readAllText(kernel.initPath) end, debug.traceback)
if not ok then currentTask.status="Z"; kernel.panic(code_or_err) end
local code = code_or_err
local func, err = load(code, "@SysInit", nil, kernel._U)
if not func then currentTask.status="Z"; kernel.panic(err) end
local ok, err = xpcall(func, debug.traceback, kernel)
if not ok then
currentTask.status="Z"
kernel.panic(err)
else
currentTask.status="Z"
kernel.panic("Attempted to kill init!")
end
end),
name="SysInit",
pid=1,
ppid=0,
tgid=1,
user="root",
uid=0,
evars={},
args={kernel},
vy=0,
ivy=0,
status="R",
sleep=0,
signal=signals["1"],
parent={name="Hyprkrnl",pid=0},
children={},
sibling={},
sigQ={}
}
tasks["1"].sibling={tasks["1"]}
kernel.log("Created pid 1")
kernel.cache.preload.sys=table.proxy(sys)
kernel.cache.preload.system=kernel.cache.preload.sys
kernel.cache.preload.os=kernel.cache.preload.sys
kernel.hpv=sys
kernel.tasks=tasks
kernel.signals=signals
kernel.currentTask=currentTask
kernel.saveLog()
kernel.status="running"
while kernel.status~="Panic" do
for k,v in pairs(tasks) do
currentTask=v
kernel.currentTask=v
kernel.process=currentTask.name
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.process="Kernel"
kernel.user="root"
kernel.uid=0
kernel.panic(kernel.reason or "Exited pid 0")

View File

@@ -4,5 +4,5 @@
"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"
"Tar": "https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-kernel-v1.0.0.tar"
}

View File

@@ -19,6 +19,8 @@ kernel.key = {}
kernel.cache = {}
kernel.cache.preload = {}
kernel._G=_G
kernel.sleep=sleep
_G.sleep=nil
local windowsExp = false
function kernel.log(msg, level)
@@ -118,16 +120,39 @@ end
ifs.remove("/tmp")
ifs.makeDir("/tmp")
local drivers={}
drivers.raw={}
drivers.processes={}
drivers.type={}
function kernel.newFifo()
local fifo = {}
fifo.push=function(data)
table.insert(data)
end
fifo.pop=function()
return table.remove(fifo,1)
end
return fifo
end
function drivers.register(object)
drivers.raw[#drivers.raw+1]=object
if object.main then drivers.processes[#drivers.processes+1]=object.main end
if drivers.type[object.type]==nil then drivers.type[object.type]={} end
drivers.type[object.type][#drivers.type[object.type]+1]=object
function kernel.generateUUID()
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={[0]=0}
for i=1, 100 do
kernel.syscalls[i]=0
end
function kernel.registerSyscall(name, func)
kernel.syscalls[name]=func
end
local modules={[0]={}}
@@ -141,7 +166,6 @@ for i,v in ipairs(ifs.list("/lib/modules/Hyperion/")) do
modules[prior+1][#modules[prior+1]+1]="/lib/modules/Hyperion/"..v
end
kernel.drivers=drivers
kernel.ifs=ifs
kernel.apis=apis
kernel.computer=computer
@@ -149,16 +173,19 @@ kernel.initPath=initPath
kernel.arch=arch
kernel.initdisks=disks
kernel.screen=screen
kernel.processes={}
kernel.log("Running modules")
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), "WARN") goto skip end
if not func then kernel.panic("ModuLoadErr: "..tostring(err), "WARN") goto skip end
local status, err = xpcall(func,debug.traceback, kernel)
if not status then kernel.log("ModuRunErr: "..tostring(err), "WARN") end
if not status then kernel.panic("ModuRunErr: "..tostring(err), "WARN") end
::skip::
end
end
kernel.log("Kernel initialized successfully.")
kernel.main()
kernel.PANIC("Execution complete")

View File

@@ -117,7 +117,7 @@ function table.proxy(tbl)
end
end,
__newindex = function()
error("Attempt to modify read-only table", 2)
error("Attempt to modify table proxy", 2)
end,
__pairs = function()
return function(_, k)
@@ -192,5 +192,47 @@ local function serialize(table)
return output
end
local oldtype=type
local oldgetmetatable=getmetatable
function type(object)
if oldtype(object)~="table" then
return oldtype(object)
else
if oldtype(oldgetmetatable(object))=="table" then
local metatable = oldgetmetatable(object)
if metatable.__type then return metatable.__type end
else
return "table"
end
end
end
function getmetatable(object)
if oldtype(object)~="table" then return end
if oldtype(oldgetmetatable(object))=="table" then
if oldgetmetatable(object).__isuserdata then
if oldtype(oldgetmetatable(object).__usermeta)=="function" then
return oldgetmetatable(object).__usermeta()
else
return oldgetmetatable(object).__usermeta
end
else
return oldgetmetatable(object)
end
else
return oldgetmetatable(object)
end
end
function isEqual(a, ...)
local args={...}
for i=0, #args do
if a==args[i] then
return true
end
end
return false
end
table.serialize=serialize
kernel.log("Loaded stdlib")

View File

@@ -0,0 +1,185 @@
local kernel = ...
local openFiles = {}
kernel.openFiles = openFiles
local vfs = {}
vfs.mounts = {}
local disks = kernel.disks
vfs.cwd = ""
local function resolvePath(path)
local mountPoint = "/"
local mountId = "$"
if path:sub(1,1)~="/" then path=vfs.cwd..path end
for k,v in pairs(vfs.mounts) do
if path:sub(1,#v) == v and #v > #mountPoint then
mountPoint = v
mountId = k
end
end
local diskPath = path:sub(#mountPoint+1)
return disks[mountId], diskPath
end
function vfs.mount(diskId, path)
if kernel.uid ~= 0 then error("Permission denied") end
if not disks[diskId] then
error("Attempted to mount unknown disk '"..diskId.."'")
return false
end
if vfs.mounts[diskId] then
error("Disk '"..diskId.."' is already mounted")
return false
end
if path:sub(#path,#path)~="/" then path=path.."/" end
for i,v in pairs(vfs.mounts) do
if v == path then
error("Mount point '"..path.."' is already in use")
return false
end
end
vfs.mounts[diskId] = path
end
function vfs.unmount(path)
if kernel.uid ~= 0 then error("Permission denied") end
for k,v in pairs(vfs.mounts) do
if v == path then
vfs.mounts[k] = nil
return true
end
end
return false
end
function vfs.open(path, mode)
local disk, diskPath = resolvePath(path)
if not disk then
error("No disk mounted for path '"..path.."'")
return nil
end
local uuid = kernel.newUUID()
openFiles[uuid] = {disk=disk.address, path=path, mode=mode, handle=disk:open(diskPath, mode)}
return uuid
end
function vfs.close(fileId)
local file = openFiles[fileId]
if not file then
error("Invalid file handle")
return false
end
local disk = disks[file.disk]
disk:close(file.handle)
openFiles[fileId] = nil
return true
end
function vfs.read(fileId, count)
local file = openFiles[fileId]
if not file then
error("Invalid file handle")
return nil
end
if not file.mode:find("r") then
error("File not opened in read mode")
return nil
end
local disk = disks[file.disk]
return disk:read(file.handle, count)
end
function vfs.write(fileId, data)
local file = openFiles[fileId]
if not file then
error("Invalid file handle")
return false
end
if not file.mode:find("w") then
error("File not opened in write mode")
return false
end
local disk = disks[file.disk]
return disk:write(file.handle, data)
end
function vfs.mkdir(path)
local disk, diskPath = resolvePath(path)
if not disk then
error("No disk mounted for path '"..path.."'")
return false
end
return disk:mkdir(diskPath)
end
function vfs.remove(path)
local disk, diskPath = resolvePath(path)
if not disk then
error("No disk mounted for path '"..path.."'")
return false
end
return disk:remove(diskPath)
end
function vfs.atributes(path)
local disk, diskPath = resolvePath(path)
if not disk then
error("No disk mounted for path '"..path.."'")
return nil
end
return disk:attributes(diskPath)
end
function vfs.list(path)
local disk, diskPath = resolvePath(path)
if not disk then
error("No disk mounted for path '"..path.."'")
return nil
end
return disk:list(diskPath)
end
function vfs.exists(path)
local disk, diskPath = resolvePath(path)
if not disk then
error("No disk mounted for path '"..path.."'")
return false
end
return disk:directoryExists(diskPath) or disk:fileExists(diskPath)
end
function vfs.type(path)
local disk, diskPath = resolvePath(path)
if not disk then
error("No disk mounted for path '"..path.."'")
return nil
end
return disk:type(diskPath)
end
function vfs.getcwd()
return vfs.cwd
end
function vfs.setcwd(path)
if path:sub(#path,#path)~="/" then path=path.."/" end
if path:sub(1,1)~="/" then path="/"..path end
vfs.cwd=path
end
kernel.vfs = vfs
kernel.registerSyscall(0x01, vfs.open)
kernel.registerSyscall(0x02, vfs.read)
kernel.registerSyscall(0x03, vfs.write)
kernel.registerSyscall(0x04, vfs.close)
kernel.registerSyscall(0x05, vfs.list)
kernel.registerSyscall(0x06, vfs.type)
kernel.registerSyscall(0x07, vfs.atributes)
kernel.registerSyscall(0x08, vfs.mkdir)
kernel.registerSyscall(0x09, vfs.remove)
kernel.registerSyscall(0x0a, vfs.exists)
kernel.registerSyscall(0x0b, vfs.mount)
kernel.registerSyscall(0x0c, vfs.unmount)
kernel.registerSyscall(0x0d, vfs.getcwd)
kernel.registerSyscall(0x0e, vfs.setcwd)
kernel.log("VFS module loaded")

View File

@@ -1,6 +1,6 @@
local args = {...}
local kernel = args[1]
kernel.log("initializing third party drivers")
kernel.log("Initializing third party drivers")
for _,v in ipairs(kernel.drivers.raw) do
if v.arch==kernel.arch then
if v.load then

View File

@@ -0,0 +1 @@
local kernel = ...

17
Test/HyperionOS.pkg → Test/Hyperion-v1.0.0.pkg Executable file → Normal file
View File

@@ -1,14 +1,15 @@
{
"Name": "HyperionOS",
"Version": "0.1.0",
"Version": "1.0.0",
"Publishers": ["HyperionOS Dev Team"],
"Description": "A sample package for HyperionOS project.",
"Description": "The install 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"
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-core-v1.0.0.pkg",
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-kernel-v1.0.0.pkg",
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-ui-v1.0.0.pkg",
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-network-v1.0.0.pkg",
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-security-v1.0.0.pkg",
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-filesystem-v1.0.0.pkg",
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-bash-v1.0.0.pkg"
]
}

BIN
Test/disk.img Normal file

Binary file not shown.

0
Test/palette_16.txt Executable file → Normal file
View File

0
Test/text.img Normal file
View File

View File

@@ -0,0 +1,261 @@
syscalls are essential to the OSes functionality, syscalls with trailing * need to be privlaged (root)
```
Syscall | arg1 | arg2 | arg3 | arg4 | arg5 | arg6 | id |
============================================================================================
yield | | | | | | | 00 |
open | path | | | | | | 01 |
read | FD | | | | | | 02 |
write | FD | text | | | | | 03 |
close | FD | | | | | | 04 |
list | path | | | | | | 05 |
type | path | | | | | | 06 |
attributes | path | | | | | | 07 |
mkdir | path | | | | | | 08 |
remove | path | | | | | | 09 |
exists | path | | | | | | 0a |
getcwd | | | | | | | 0b |
setcwd | path | | | | | | 0c |
| | | | | | | 0d |
| | | | | | | 0e |
| | | | | | | 0f |
spawn | func | name | envars | args | | | 10 |
hookSignalHook | SIGID | func | | | | | 11 |
sendSignal | PID | SIGID | | | | | 12 |
getSignalHook | SIGID | | | | | | 13 |
exit | code | | | | | | 14 |
getChildrenTasks | PID | | | | | | 15 |
getTaskID | | | | | | | 16 |
pause | | | | | | | 17 |
resume | | | | | | | 18 |
| | | | | | | 19 |
| | | | | | | 1a |
| | | | | | | 1b |
| | | | | | | 1c |
| | | | | | | 1d |
| | | | | | | 1e |
| | | | | | | 1f |
| | | | | | | 20 |
| | | | | | | 21 |
| | | | | | | 22 |
| | | | | | | 23 |
| | | | | | | 24 |
| | | | | | | 25 |
| | | | | | | 26 |
| | | | | | | 27 |
| | | | | | | 28 |
| | | | | | | 29 |
| | | | | | | 2a |
| | | | | | | 2b |
| | | | | | | 2c |
| | | | | | | 2d |
| | | | | | | 2e |
| | | | | | | 2f |
| | | | | | | 30 |
| | | | | | | 31 |
| | | | | | | 32 |
| | | | | | | 33 |
| | | | | | | 34 |
| | | | | | | 35 |
| | | | | | | 36 |
| | | | | | | 37 |
| | | | | | | 38 |
| | | | | | | 39 |
| | | | | | | 3a |
| | | | | | | 3b |
| | | | | | | 3c |
| | | | | | | 3d |
| | | | | | | 3e |
| | | | | | | 3f |
| | | | | | | 40 |
| | | | | | | 41 |
| | | | | | | 42 |
| | | | | | | 43 |
| | | | | | | 44 |
| | | | | | | 45 |
| | | | | | | 46 |
| | | | | | | 47 |
| | | | | | | 48 |
| | | | | | | 49 |
| | | | | | | 4a |
| | | | | | | 4b |
| | | | | | | 4c |
| | | | | | | 4d |
| | | | | | | 4e |
| | | | | | | 4f |
| | | | | | | 50 |
| | | | | | | 51 |
| | | | | | | 52 |
| | | | | | | 53 |
| | | | | | | 54 |
| | | | | | | 55 |
| | | | | | | 56 |
| | | | | | | 57 |
| | | | | | | 58 |
| | | | | | | 59 |
| | | | | | | 5a |
| | | | | | | 5b |
| | | | | | | 5c |
| | | | | | | 5d |
| | | | | | | 5e |
| | | | | | | 5f |
| | | | | | | 60 |
| | | | | | | 61 |
| | | | | | | 62 |
| | | | | | | 63 |
| | | | | | | 64 |
| | | | | | | 65 |
| | | | | | | 66 |
| | | | | | | 67 |
| | | | | | | 68 |
| | | | | | | 69 |
| | | | | | | 6a |
| | | | | | | 6b |
| | | | | | | 6c |
| | | | | | | 6d |
| | | | | | | 6e |
| | | | | | | 6f |
| | | | | | | 70 |
| | | | | | | 71 |
| | | | | | | 72 |
| | | | | | | 73 |
| | | | | | | 74 |
| | | | | | | 75 |
| | | | | | | 76 |
| | | | | | | 77 |
| | | | | | | 78 |
| | | | | | | 79 |
| | | | | | | 7a |
| | | | | | | 7b |
| | | | | | | 7c |
| | | | | | | 7d |
| | | | | | | 7e |
| | | | | | | 7f |
| | | | | | | 80 |
| | | | | | | 81 |
| | | | | | | 82 |
| | | | | | | 83 |
| | | | | | | 84 |
| | | | | | | 85 |
| | | | | | | 86 |
| | | | | | | 87 |
| | | | | | | 88 |
| | | | | | | 89 |
| | | | | | | 8a |
| | | | | | | 8b |
| | | | | | | 8c |
| | | | | | | 8d |
| | | | | | | 8e |
| | | | | | | 8f |
| | | | | | | 90 |
| | | | | | | 91 |
| | | | | | | 92 |
| | | | | | | 93 |
| | | | | | | 94 |
| | | | | | | 95 |
| | | | | | | 96 |
| | | | | | | 97 |
| | | | | | | 98 |
| | | | | | | 99 |
| | | | | | | 9a |
| | | | | | | 9b |
| | | | | | | 9c |
| | | | | | | 9d |
| | | | | | | 9e |
| | | | | | | 9f |
| | | | | | | a0 |
| | | | | | | a1 |
| | | | | | | a2 |
| | | | | | | a3 |
| | | | | | | a4 |
| | | | | | | a5 |
| | | | | | | a6 |
| | | | | | | a7 |
| | | | | | | a8 |
| | | | | | | a9 |
| | | | | | | aa |
| | | | | | | ab |
| | | | | | | ac |
| | | | | | | ad |
| | | | | | | ae |
| | | | | | | af |
| | | | | | | b0 |
| | | | | | | b1 |
| | | | | | | b2 |
| | | | | | | b3 |
| | | | | | | b4 |
| | | | | | | b5 |
| | | | | | | b6 |
| | | | | | | b7 |
| | | | | | | b8 |
| | | | | | | b9 |
| | | | | | | ba |
| | | | | | | bb |
| | | | | | | bc |
| | | | | | | bd |
| | | | | | | be |
| | | | | | | bf |
| | | | | | | c0 |
| | | | | | | c1 |
| | | | | | | c2 |
| | | | | | | c3 |
| | | | | | | c4 |
| | | | | | | c5 |
| | | | | | | c6 |
| | | | | | | c7 |
| | | | | | | c8 |
| | | | | | | c9 |
| | | | | | | ca |
| | | | | | | cb |
| | | | | | | cc |
| | | | | | | cd |
| | | | | | | ce |
| | | | | | | cf |
| | | | | | | d0 |
| | | | | | | d1 |
| | | | | | | d2 |
| | | | | | | d3 |
| | | | | | | d4 |
| | | | | | | d5 |
| | | | | | | d6 |
| | | | | | | d7 |
| | | | | | | d8 |
| | | | | | | d9 |
| | | | | | | da |
| | | | | | | db |
| | | | | | | dc |
| | | | | | | dd |
| | | | | | | de |
| | | | | | | df |
| | | | | | | e0 |
| | | | | | | e1 |
| | | | | | | e2 |
| | | | | | | e3 |
| | | | | | | e4 |
| | | | | | | e5 |
| | | | | | | e6 |
| | | | | | | e7 |
| | | | | | | e8 |
| | | | | | | e9 |
| | | | | | | ea |
| | | | | | | eb |
| | | | | | | ec |
| | | | | | | ed |
| | | | | | | ee |
| | | | | | | ef |
| | | | | | | f0 |
| | | | | | | f1 |
| | | | | | | f2 |
| | | | | | | f3 |
| | | | | | | f4 |
| | | | | | | f5 |
| | | | | | | f6 |
| | | | | | | f7 |
| | | | | | | f8 |
| | | | | | | f9 |
| | | | | | | fa |
| | | | | | | fb |
| | | | | | | fc |
| | | | | | | fd |
| | | | | | | fe |
| | | | | | | ff |
```

View File

@@ -0,0 +1,17 @@
--- Disk API Documentation ---
string address = "EXAMPLE_DISK_ADDRESS"
function disk:isReadOnly()
function disk:spaceUsed()
function disk:spaceTotal()
function disk:list(path)
function disk:fileExists(path)
function disk:directoryExists(path)
function disk:makeDirectory(path)
function disk:remove(path)
function disk:setLabel(label)
function disk:getLabel(label)
function disk:size(path)
function disk:open(path, mode)
function file:read(handle, count)
function file:write(handle, data)
function file:close(handle)

2
docs/kernel/drivers/api/README.md Executable file → Normal file
View File

@@ -20,9 +20,7 @@ Driver API
load - loading code
unload - unloading code
main - Ran as a process and has normal behavior (used for checking network like things)
api - api difined by type
arch - architecture difined in bootloader (EX: cct, oc, ac, cc, ccpc, or all)
description - discription
author - author of driver
prior - priority (low first)
```

2
docs/kernel/drivers/api/tty.md Executable file → Normal file
View File

@@ -5,6 +5,8 @@ tty (Teletypewriter) is a driver class made for basic text output (ASCII only) u
```
API Signature
String: address
Address unique to the screen
print(String: text):Nil
Prints text to the screen with a following \n

37
docs/kernel/signals Normal file
View File

@@ -0,0 +1,37 @@
01 SIGHUP Terminate Hang up controlling terminal or Yes
process
02 SIGINT Terminate Interrupt from keyboard, Control-C Yes
03 SIGQUIT Dump Quit from keyboard, Control-\ Yes
04 SIGILL Dump Illegal instruction Yes
05 SIGTRAP Dump Breakpoint for debugging No
06 SIGABRT Dump Abnormal termination Yes
06 SIGIOT Dump Equivalent to SIGABRT No
07 SIGBUS Dump Bus error No
08 SIGFPE Dump Floating-point exception Yes
09 SIGKILL Terminate Forced-process termination Yes
10 SIGUSR1 Terminate Available to processes Yes
11 SIGSEGV Dump Invalid memory reference Yes
12 SIGUSR2 Terminate Available to processes Yes
13 SIGPIPE Terminate Write to pipe with no readers Yes
14 SIGALRM Terminate Real-timer clock Yes
15 SIGTERM Terminate Process termination Yes
16 SIGSTKFLT Terminate Coprocessor stack error No
17 SIGCHLD Ignore Child process stopped or terminated Yes
or got a signal if traced
18 SIGCONT Continue Resume execution, if stopped Yes
19 SIGSTOP Stop Stop process execution, Ctrl-Z Yes
20 SIGTSTP Stop Stop process issued from tty Yes
21 SIGTTIN Stop Background process requires input Yes
22 SIGTTOU Stop Background process requires output Yes
23 SIGURG Ignore Urgent condition on socket No
24 SIGXCPU Dump CPU time limit exceeded No
25 SIGXFSZ Dump File size limit exceeded No
26 SIGVTALRM Terminate Virtual timer clock No
27 SIGPROF Terminate Profile timer clock No
28 SIGWINCH Ignore Window resizing No
29 SIGIO Terminate I/O now possible No
29 SIGPOLL Terminate Equivalent to SIGIO No
30 SIGPWR Terminate Power supply failure No
31 SIGSYS Dump Bad system call No
32 SIGUNUSED Dump Equivalent to SIGSYS No

0
tools/boot.lua Executable file → Normal file
View File

0
tools/listtar.lua Executable file → Normal file
View File

0
tools/unpack.lua Executable file → Normal file
View File

0
tools/update.lua Executable file → Normal file
View File