update to start working on SysInit

This commit is contained in:
2025-12-10 22:14:52 -05:00
parent 7bc6d87322
commit 6d9d02edf7
163 changed files with 1422 additions and 10637 deletions

46
.vscode/tasks.json vendored Executable file
View File

@@ -0,0 +1,46 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Build",
"type": "shell",
"windows": {
"command": "powershell",
"args": [
"-NoProfile",
"-ExecutionPolicy",
"Bypass",
"-Command",
"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": [
"-c",
"[ -d \"${workspaceFolder}/Build\" ] && rm -rf \"${workspaceFolder}/Build\"; mkdir -p \"${workspaceFolder}/Build\"; for d in \"${workspaceFolder}/Test\"/*; do if [ -d \"$d\" ]; then find \"$d\" -type f | while read f; do rel=\"${f#$d/}\"; mkdir -p \"${workspaceFolder}/Build/$(dirname \"$rel\")\"; cp \"$f\" \"${workspaceFolder}/Build/$rel\"; done; fi; done"
]
},
"osx": {
"command": "bash",
"args": [
"-c",
"[ -d \"${workspaceFolder}/Build\" ] && rm -rf \"${workspaceFolder}/Build\"; mkdir -p \"${workspaceFolder}/Build\"; for d in \"${workspaceFolder}/Test\"/*; do if [ -d \"$d\" ]; then find \"$d\" -type f | while read f; do rel=\"${f#$d/}\"; mkdir -p \"${workspaceFolder}/Build/$(dirname \"$rel\")\"; cp \"$f\" \"${workspaceFolder}/Build/$rel\"; done; fi; done"
]
},
"presentation": {
"reveal": "always",
"panel": "shared"
},
"problemMatcher": [],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}

BIN
Build.tar Executable file

Binary file not shown.

View File

@@ -14,22 +14,26 @@ kernel.group = "root"
kernel.groups = {0} kernel.groups = {0}
kernel.uid = 0 kernel.uid = 0
kernel.gid = 0 kernel.gid = 0
kernel.stage = "start" kernel.status = "start"
kernel.key = {} kernel.key = {}
kernel.chache = {} kernel.cache = {}
kernel.chache.preload = {} kernel.cache.preload = {}
kernel._G=_G
local windowsExp = false local windowsExp = false
function kernel.log(msg, level) function kernel.log(msg, level)
LOG_Text = LOG_Text..tostring(computer.time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n" LOG_Text = LOG_Text..tostring(computer.time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n"
if kernel.stage == "start" then if kernel.status == "start" then
screen:print(tostring(computer.time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg) screen:print(tostring(computer.time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg)
end end
end end
function kernel.PANIC(msg) function kernel.PANIC(msg)
if kernel.status~="Panic" then
kernel.log("PANIC: "..msg, "PANIC") kernel.log("PANIC: "..msg, "PANIC")
pcall(kernel["saveLog"]) pcall(kernel["saveLog"])
kernel.status="Panic"
kernel.reason=msg
screen:setTextColor(2) screen:setTextColor(2)
screen:setBackgroundColor(0) screen:setBackgroundColor(0)
screen:clear() screen:clear()
@@ -37,6 +41,7 @@ function kernel.PANIC(msg)
screen:print(LOG_Text) screen:print(LOG_Text)
screen:print("KERNEL PANIC!\n"..msg.."\nSystem halted.") screen:print("KERNEL PANIC!\n"..msg.."\nSystem halted.")
screen:print("Press any key to continue...") screen:print("Press any key to continue...")
end
while true do while true do
local event={computer:getMachineEvent()} local event={computer:getMachineEvent()}
if event[1]=="keyPressed" then if event[1]=="keyPressed" then
@@ -65,16 +70,12 @@ if windowsExp then
while true do end while true do end
end end
kernel.log("Kernel loaded.", "INFO") kernel.log("Kernel loaded.")
kernel.log("Mounting disks...", "INFO") kernel.log("Mounting init disks...")
disks.refresh() disks.refresh()
ifs.update(disks) ifs.update(disks)
ifs.mount("$", "/") ifs.mount("$", "/")
function kernel.saveLog()
ifs.writeAllText("/var/log/syslog.log", LOG_Text)
end
local fstab=ifs.readAllText("/etc/fstab") local fstab=ifs.readAllText("/etc/fstab")
local split = function(str, delim, maxResultCountOrNil) local split = function(str, delim, maxResultCountOrNil)
assert(#delim == 1, "only delim len 1 supported for now") assert(#delim == 1, "only delim len 1 supported for now")
@@ -104,11 +105,15 @@ for i,v in ipairs(split(fstab,"\n")) do
end end
end end
local path=v:sub(#id+4) local path=v:sub(#id+4)
kernel.log("Mounted "..id.." to "..path)
ifs.mount(id,path) ifs.mount(id,path)
::endline:: ::endline::
end end
end end
kernel.log("Disks initialized")
function kernel.saveLog()
ifs.writeAllText("/var/log/syslog.log", LOG_Text)
end
ifs.remove("/tmp") ifs.remove("/tmp")
ifs.makeDir("/tmp") ifs.makeDir("/tmp")
@@ -116,29 +121,24 @@ ifs.makeDir("/tmp")
local drivers={} local drivers={}
drivers.raw={} drivers.raw={}
drivers.processes={} drivers.processes={}
drivers.prior={}
drivers.type={} drivers.type={}
for i=0, 99 do
drivers.prior[i]={}
end
function drivers.register(prior,object) function drivers.register(object)
drivers.raw[#drivers.raw+1]=object drivers.raw[#drivers.raw+1]=object
if object.main then drivers.processes[#drivers.processes+1]=object.main end 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 if drivers.type[object.type]==nil then drivers.type[object.type]={} end
drivers.type[object.type][#drivers.type[object.type]+1]=object drivers.type[object.type][#drivers.type[object.type]+1]=object
end end
local modules={} local modules={[0]={}}
for i=0, 99 do for i=0, 100 do
modules[i]={} modules[i]={}
end end
kernel.log("Gathering modules")
for i,v in ipairs(ifs.list("/lib/modules/Hyperion/")) do for i,v in ipairs(ifs.list("/lib/modules/Hyperion/")) do
local prior=tonumber(v:sub(1,2)) local prior=tonumber(v:sub(1,2))
modules[prior][#modules[prior]+1]="/lib/modules/Hyperion/"..v modules[prior+1][#modules[prior+1]+1]="/lib/modules/Hyperion/"..v
end end
kernel.drivers=drivers kernel.drivers=drivers
@@ -147,19 +147,17 @@ kernel.apis=apis
kernel.computer=computer kernel.computer=computer
kernel.initPath=initPath kernel.initPath=initPath
kernel.arch=arch kernel.arch=arch
kernel.initdisks=initdisks kernel.initdisks=disks
kernel.screen=screen kernel.screen=screen
kernel.log("Running modules")
for _,p in ipairs(modules) do for _,p in ipairs(modules) do
for _,v in ipairs(p) do for _,v in ipairs(p) do
local code=ifs.readAllText(v) local code=ifs.readAllText(v)
local func,err=load(code,"@"..v) local func,err=load(code,"@"..v)
if not func then kernel.log("ModuLoadErr: "..tostring(err)) goto skip end if not func then kernel.log("ModuLoadErr: "..tostring(err), "WARN") goto skip end
local status, err = xpcall(func,debug.traceback, kernel) local status, err = xpcall(func,debug.traceback, kernel)
if not status then goto skip end if not status then kernel.log("ModuRunErr: "..tostring(err), "WARN") 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:: ::skip::
end end
end end

View File

@@ -1,2 +1,3 @@
U $;/ U $;/
U devfs0000;/dev/ U devfs0000;/dev/
U sysfs0000;/sys/

View File

@@ -0,0 +1,26 @@
local args={...}
local kernel=args[1]
local driver={}
driver.name="CCT Term Module"
driver.version="0.1.0"
driver.type="gpio"
driver.description="CCT redstone Module Kernel Module"
driver.arch="cct"
driver.author="HyperionOS Dev Team"
driver.license="MIT"
driver.api={}
function driver.load()
-- will
end
function driver.unload()
-- Nothing to unload
end
function driver.main()
-- Nothing to run
end
kernel.drivers.register(driver)

View File

@@ -0,0 +1,105 @@
local args={...}
local kernel=args[1]
local apis=kernel.apis
local native=apis.peripheral
local driver={}
local sides = {"top", "bottom", "left", "right", "front", "back"}
local function 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
local function 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
driver.name="CCT TTY Module"
driver.version="0.1.0"
driver.type="tty"
driver.description="CCT TTY Module Kernel Module"
driver.arch="cct"
driver.author="HyperionOS Dev Team"
driver.license="MIT"
driver.api={}
local colors={
[0]=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
}
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 function getAllScreens()
end
local function wrapScreens()
end
function driver.load()
-- Nothing to load
end
function driver.unload()
-- Nothing to unload
end
function driver.main()
-- Nothing to run
end
kernel.drivers.register(driver)

View File

@@ -1,3 +1,5 @@
local args={...}
local kernel=args[1]
function string.hasSuffix(str, suffix) function string.hasSuffix(str, suffix)
return string.sub(str, #suffix+1) == suffix return string.sub(str, #suffix+1) == suffix
end end
@@ -94,6 +96,62 @@ function table.hasVal(tabl, query)
return false return false
end end
function table.proxy(tbl)
local proxies = setmetatable({}, {__mode = "k"}) -- Weak table to avoid cycles
local function createProxy(t)
if type(t) ~= "table" then return t end
if proxies[t] then return proxies[t] end -- reuse proxy for the same table (handle cycles)
local proxy = {}
proxies[t] = proxy
local mt
mt = {
__index = function(_, k)
local value = t[k]
if type(value) == "table" then
return createProxy(value) -- recursively proxy subtables
else
return value
end
end,
__newindex = function()
error("Attempt to modify read-only table", 2)
end,
__pairs = function()
return function(_, k)
local nextKey, nextValue = next(t, k)
if type(nextValue) == "table" then
nextValue = createProxy(nextValue)
end
return nextKey, nextValue
end, nil, nil
end,
__ipairs = function()
local i = 0
local n = #t
return function()
i = i + 1
if i <= n then
local v = t[i]
if type(v) == "table" then
v = createProxy(v)
end
return i, v
end
end
end,
__metatable = false
}
setmetatable(proxy, mt)
return proxy
end
return createProxy(tbl)
end
local function serialize(table) local function serialize(table)
local output = "{" local output = "{"
for i,v in pairs(table) do for i,v in pairs(table) do
@@ -119,7 +177,7 @@ local function serialize(table)
output=output.."false" output=output.."false"
end end
elseif type(v) == "function" then elseif type(v) == "function" then
output=output.."function() end" output=output..tostring(v)
else else
error("serialization of type \""..type(v).."\" is not supported") error("serialization of type \""..type(v).."\" is not supported")
end end
@@ -135,3 +193,4 @@ local function serialize(table)
end end
table.serialize=serialize table.serialize=serialize
kernel.log("Loaded stdlib")

View File

@@ -0,0 +1,3 @@
local args={...}
local kernel=args[1]
kernel._U=table.proxy(_G)

View File

@@ -1,217 +1,321 @@
local args = {...} local args = {...}
local kernel = args[1] local kernel = args[1]
local fs = {} local fs = {}
local disks = {}
local mounts = {["/"]="$"}
-- path normaliing -- =====================================================================
local function normalizePath(path) -- INTERNAL STATE
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 disks = {} -- address → disk object
local function resolvePath(path) local mounts = {["/"] = "$"} -- mountpoint → disk address (root = boot disk)
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_PREFIX = "#!@SYMLINK["
local SYMLINK_SUFFIX = "]" local SYMLINK_SUFFIX = "]"
local SYMLINK_MAX_DEPTH = 64 local SYMLINK_MAX_DEPTH = 64
local function isSymlink(disk, path)
if not disk:fileExists(path) then return false end -- =====================================================================
local text = disk:readAllText(path) -- PATH NORMALIZATION
if not text then return false end -- =====================================================================
return text:sub(1, #SYMLINK_PREFIX) == SYMLINK_PREFIX
local function splitPath(p)
local t = {}
for part in p:gmatch("[^/]+") do t[#t+1] = part end
return t
end end
local function readSymlink(disk, path) local function normalizePath(path)
local text = disk:readAllText(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 not text then return nil end
if text:sub(1, #SYMLINK_PREFIX) ~= SYMLINK_PREFIX 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 local t = text:sub(#SYMLINK_PREFIX + 1)
target = target:sub(1, -2) if t:sub(-1) == SYMLINK_SUFFIX then
t = t:sub(1, -2)
end end
return target return t
end end
-- Path resolution -- =====================================================================
local function splitPath(p) -- FULL PATH RESOLUTION (FOLLOWS SYMLINKS)
local parts = {} -- =====================================================================
for part in p:gmatch("[^/]+") do parts[#parts+1] = part end
return parts
end
local function resolveSymlink(path) local function resolveSymlink(path)
path = normalizePath(path) local abs = normalizePath(path)
local symlinkDepth = 0 local parts = splitPath(abs)
local parts = splitPath(path) local out = {}
local resolved = {}
local i = 1 local depth = 0
local idx = 1
while idx <= #parts do
local comp = parts[idx]
while i <= #parts do
local comp = parts[i]
if comp == "." then if comp == "." then
-- nothing
elseif comp == ".." then elseif comp == ".." then
if #resolved > 0 then table.remove(resolved) end if #out > 0 then table.remove(out) end
else else
local currentPath = "/" .. table.concat(resolved, "/") local curAbs = "/" .. table.concat(out, "/")
local disk, p = resolvePath(currentPath .. "/" .. comp) if curAbs ~= "/" then curAbs = curAbs .. "/" end
if isSymlink(disk, p) then curAbs = curAbs .. comp
symlinkDepth = symlinkDepth + 1
if symlinkDepth > SYMLINK_MAX_DEPTH then local disk, dpath = resolveMount(curAbs)
error("Too many levels of symbolic links: " .. path)
if isSymlinkRaw(disk, dpath) then
depth = depth + 1
if depth > SYMLINK_MAX_DEPTH then
error("Too many symlink levels: " .. path)
end end
local target = readSymlink(disk, p)
if not target then local target = readSymlinkRaw(disk, dpath)
resolved[#resolved+1] = comp if target then
else local newAbs
if target:sub(1,1) == "/" then if target:sub(1,1) == "/" then
resolved = splitPath(normalizePath(target)) -- absolute target
newAbs = normalizePath(target)
else else
local base = resolved -- relative to current out[]
resolved = {} local tmp = "/" .. table.concat(out, "/")
for _, seg in ipairs(base) do resolved[#resolved+1]=seg end if tmp ~= "/" then tmp = tmp .. "/" end
for seg in target:gmatch("[^/]+") do tmp = tmp .. target
if seg == ".." then newAbs = normalizePath(tmp)
if #resolved>0 then table.remove(resolved) end
elseif seg ~= "." then
resolved[#resolved+1]=seg
end
end
end end
-- rebuild remaining parts
local remaining = {} local remaining = {}
for j=i+1,#parts do remaining[#remaining+1]=parts[j] end for j = idx + 1, #parts do
parts = remaining remaining[#remaining+1] = parts[j]
i = 0 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 end
else else
resolved[#resolved+1]=comp out[#out+1] = comp
end end
end end
i=i+1
end
local finalPath="/"..table.concat(resolved,"/") idx = idx + 1
local disk,diskPath=resolvePath(finalPath)
return disk,diskPath
end end
-- PUBLIC API: MOUNTING local finalAbs = "/" .. table.concat(out, "/")
function fs.mount(disk, mountPoint) return resolveMount(finalAbs)
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 end
-- =====================================================================
-- PUBLIC API
-- =====================================================================
-- MOUNT OPERATIONS -----------------------------------------------------
function fs.virtDisk(diskObj) function fs.virtDisk(diskObj)
if kernel.uid ~= 0 then error("Permission Denied") end if kernel.uid ~= 0 then error("Permission Denied") end
if disks[diskObj.address] then error("Disk exists") end if disks[diskObj.address] then
error("Disk exists: " .. diskObj.address)
end
disks[diskObj.address] = diskObj disks[diskObj.address] = diskObj
end 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) function fs.eject(addr)
if kernel.uid ~= 0 then error("Permission Denied") end if kernel.uid ~= 0 then error("Permission Denied") end
disks[addr] = nil disks[addr] = nil
end end
-- SYMLINK API function fs.isMount(path)
if mounts[normalizePath(path)] then return true, mounts[normalizePath(path)] end
end
-- SYMLINK API ----------------------------------------------------------
function fs.symlink(target, linkPath) function fs.symlink(target, linkPath)
local disk, p = resolvePath(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) return disk:writeAllText(p, SYMLINK_PREFIX .. target .. SYMLINK_SUFFIX)
end end
function fs.isLink(path) function fs.isLink(path)
local disk, p = resolvePath(path) local disk, p = resolveMount(normalizePath(path))
return isSymlink(disk,p) return isSymlinkRaw(disk, p)
end end
function fs.readLink(path) function fs.readLink(path)
local disk, p = resolvePath(path) local disk, p = resolveMount(normalizePath(path))
return readSymlink(disk,p) return readSymlinkRaw(disk, p)
end end
-- FILE OPERATIONS
function fs.exists(path) -- FILE OPERATIONS ------------------------------------------------------
function fs.exists(path, ...)
local disk, p = resolveSymlink(path) local disk, p = resolveSymlink(path)
return disk:fileExists(p) or disk:directoryExists(p) return disk:fileExists(p, ...) or disk:directoryExists(p, ...)
end end
function fs.isFile(path) function fs.isFile(path, ...)
local disk, p = resolveSymlink(path) local disk, p = resolveSymlink(path)
if isSymlink(disk, p) then return false end return disk:fileExists(p, ...)
return disk:fileExists(p)
end end
function fs.isDir(path) function fs.isDir(path, ...)
local disk, p = resolveSymlink(path) local disk, p = resolveSymlink(path)
if isSymlink(disk, p) then return false end return disk:directoryExists(p, ...)
return disk:directoryExists(p)
end end
function fs.list(path) function fs.list(path, ...)
local disk, p = resolveSymlink(path) local disk, p = resolveSymlink(path)
return disk:list(p) return disk:list(p, ...)
end end
function fs.makeDir(path) function fs.makeDir(path, ...)
local disk, p = resolveSymlink(path) local disk, p = resolveSymlink(path)
return disk:makeDirectory(p) return disk:makeDirectory(p, ...)
end end
function fs.remove(path) -- remove does NOT follow symlinks (UNIX semantics)
local disk, p = resolvePath(path) function fs.remove(path, ...)
if isSymlink(disk, p) then if fs.isMount(path) then return "Cannot delete mounted folder" end
return disk:remove(p) local abs = normalizePath(path)
end local disk, p = resolveMount(abs)
local d2, p2 = resolveSymlink(path) return disk:remove(p, ...)
return d2:remove(p2)
end end
function fs.readAllText(path) function fs.readAllText(path, ...)
local disk, p = resolveSymlink(path) local disk, p = resolveSymlink(path)
return disk:readAllText(p) return disk:readAllText(p, ...)
end end
function fs.writeAllText(path, text) function fs.writeAllText(path, text, ...)
local disk, p = resolveSymlink(path) local disk, p = resolveSymlink(path)
return disk:writeAllText(p, text) return disk:writeAllText(p, text, ...)
end end
function fs.appendAllText(path, text) function fs.appendAllText(path, text, ...)
local disk, p = resolveSymlink(path) local disk, p = resolveSymlink(path)
return disk:appendAllText(p, text) return disk:appendAllText(p, text, ...)
end end
function fs.getSize(path) 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) local disk, p = resolveSymlink(path)
return disk:getSize(p) return disk:getSize(p, ...)
end end
-- =====================================================================
-- INIT -- INIT
for _,v in kernel.initdisks.list() do fs.virtDisk(v) end -- =====================================================================
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.fs = fs
kernel.chache.preload.fs=fs kernel.cache.preload.fs = table.proxy(kernel.fs)
kernel.chache.preload.filesystem=fs kernel.cache.preload.filesystem = kernel.cache.preload.fs

View File

@@ -1,6 +1,5 @@
local args = {...} local args = {...}
local kernel = args[1] local kernel = args[1]
function kernel.fs.mkvirtfs(address, readOnly, label, autoRegister) function kernel.fs.mkvirtfs(address, readOnly, label, autoRegister)
if kernel.uid ~= 0 then error("Permission Denied") end if kernel.uid ~= 0 then error("Permission Denied") end
local disk = {} local disk = {}
@@ -55,34 +54,36 @@ function kernel.fs.mkvirtfs(address, readOnly, label, autoRegister)
-- File IO (supports string or file-object with read/write funcs) -- File IO (supports string or file-object with read/write funcs)
----------------------------------------------------------------- -----------------------------------------------------------------
local function fileRead(node) local function fileRead(node, ...)
if type(node) == "string" then if type(node) == "string" then
return node return node
elseif type(node) == "table" and node.__file and node.read then elseif type(node) == "table" and node.__file and node.read then
return node.read() return node.read(...)
end end
return nil return nil
end end
local function fileWrite(parent, name, text) local function fileWrite(parent, name, text, ...)
local node = parent[name] local node = parent[name]
if type(node) == "string" then if type(node) == "string" then
local ok, err = ensureWrite(); if not ok then return false, err end
parent[name] = text parent[name] = text
return true return true
elseif type(node) == "table" and node.__file and node.write then elseif type(node) == "table" and node.__file and node.write then
return node.write(text) return node.write(text, ...)
end end
parent[name] = text parent[name] = text
return true return true
end end
local function fileAppend(parent, name, text) local function fileAppend(parent, name, text, ...)
local node = parent[name] local node = parent[name]
if type(node) == "string" then if type(node) == "string" then
local ok, err = ensureWrite(); if not ok then return false, err end
parent[name] = node .. text parent[name] = node .. text
return true return true
elseif type(node) == "table" and node.__file and node.write then elseif type(node) == "table" and node.__file and node.write then
return node.write((node.read() or "") .. text) return node.write((node.read() or "") .. text, ...)
end end
parent[name] = text parent[name] = text
return true return true
@@ -96,26 +97,22 @@ function kernel.fs.mkvirtfs(address, readOnly, label, autoRegister)
function disk:spaceUsed() return 0 end function disk:spaceUsed() return 0 end
function disk:spaceTotal() return 0 end function disk:spaceTotal() return 0 end
function disk:readAllText(path) function disk:readAllText(path, ...)
local node = getNode(path) local node = getNode(path)
if not node then return nil, "file not found" end if not node then return nil, "file not found" end
return fileRead(node) return fileRead(node, ...)
end end
function disk:writeAllText(path, text) function disk:writeAllText(path, text, ...)
local ok, err = ensureWrite(); if not ok then return false, err end
local parent, name = getParent(path) local parent, name = getParent(path)
if not parent or not parent.__dir then return false, "invalid directory" end if not parent or not parent.__dir then return false, "invalid directory" end
return fileWrite(parent, name, tostring(text)) return fileWrite(parent, name, tostring(text), ...)
end end
function disk:appendAllText(path, text) function disk:appendAllText(path, text, ...)
local ok, err = ensureWrite(); if not ok then return false, err end
local parent, name = getParent(path) local parent, name = getParent(path)
if not parent or not parent.__dir then return false, "invalid directory" end if not parent or not parent.__dir then return false, "invalid directory" end
return fileAppend(parent, name, tostring(text)) return fileAppend(parent, name, tostring(text), ...)
end end
function disk:list(path) function disk:list(path)
@@ -161,11 +158,11 @@ function kernel.fs.mkvirtfs(address, readOnly, label, autoRegister)
return label return label
end end
function disk:size(path) function disk:size(path, ...)
local node = getNode(path) local node = getNode(path)
if type(node) == "string" then return #node end if type(node) == "string" then return #node end
if type(node) == "table" and node.__file and node.read then if type(node) == "table" and node.__file and node.read then
local v = node.read() local v = node.read(...)
return v and #v or 0 return v and #v or 0
end end
return 0 return 0
@@ -174,7 +171,7 @@ function kernel.fs.mkvirtfs(address, readOnly, label, autoRegister)
----------------------------------------------------------------- -----------------------------------------------------------------
-- Auto-register with kernel and return backend -- Auto-register with kernel and return backend
----------------------------------------------------------------- -----------------------------------------------------------------
if kernel and kernel.fs and kernel.fs.virtDisk and autoRegister then if autoRegister then
kernel.fs.virtDisk(disk) kernel.fs.virtDisk(disk)
end end

View File

@@ -1,6 +1,5 @@
local args = {...} local args = {...}
local kernel = args[1] local kernel = args[1]
-- List of search paths -- List of search paths
local paths = { local paths = {
"/lib/?", "/lib/?",
@@ -11,7 +10,7 @@ local paths = {
-- Custom require implementation -- Custom require implementation
function require(module) function require(module)
-- Return cached module if it already exists -- Return cached module if it already exists
if kernel.cache.preload[module] then if kernel.cache.preload[module]~=nil then
return kernel.cache.preload[module] return kernel.cache.preload[module]
end end
@@ -54,3 +53,4 @@ function require(module)
-- If nothing worked, raise an error with all reasons -- If nothing worked, raise an error with all reasons
error("Unable to require module '" .. module .. "':\n" .. table.concat(err, "\n")) error("Unable to require module '" .. module .. "':\n" .. table.concat(err, "\n"))
end end
kernel.log("Created require")

View File

@@ -1,7 +1,9 @@
local args = {...} local args = {...}
local kernel = args[1] local kernel = args[1]
local data = kernel.fs.mkvirtfs("devfs0000", true, "devfs", true)
local data = kernel.fs.mkvirtfs("devfs0000", true, "devfs", false) 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["/"]["OSVERSION"]="Hyperion 1.0.0"
data["/"]["eeprom"]={ data["/"]["eeprom"]={
@@ -14,4 +16,42 @@ data["/"]["eeprom"]={
kernel.computer:setEEPROM(text) kernel.computer:setEEPROM(text)
end 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

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

View File

@@ -10,3 +10,4 @@ kernel.drivers.processes[#kernel.drivers.processes+1]=function()
coroutine.yield() coroutine.yield()
end end
end end
kernel.log("Created keventd daemon")

View File

@@ -1,17 +1,20 @@
local args = {...} local args = {...}
local kernel=args[2] local kernel = args[1]
kernel.log("Loading third party drivers")
for _,subf in ipairs(kernel.fs.list("/lib/modules/")) do for _,subf in ipairs(kernel.fs.list("/lib/modules/")) do
if kernel.fs.isDir("/lib/modules/"..subf) then
if subf~="Hyperion" then if subf~="Hyperion" then
for _,driver in ipairs(kernel.fs.list("/lib/modules/"..subf)) do for _,driver in ipairs(kernel.fs.list("/lib/modules/"..subf)) do
kernel.log("Compiling driver \""..subf..":"..driver.."\"")
local code = kernel.fs.readAllText("/lib/modules/"..subf.."/"..driver) local code = kernel.fs.readAllText("/lib/modules/"..subf.."/"..driver)
local func, err = load(code, "@"..driver) local func, err = load(code, "@"..driver)
if not func then if not func then
kernel.log("DriverLoadErr: "..tostring(err), "ERROR") kernel.log("DriverCompileErr: "..tostring(err), "ERROR")
else else
local ok, err = xpcall(func, debug.traceback) local ok, err = xpcall(func, debug.traceback, table.unpack(args))
if not ok then if not ok then
kernel.log("DriverLoadErr: "..tostring(err), "ERROR") kernel.log("DriverExecErr: "..tostring(err), "ERROR")
end
end end
end end
end end

View File

@@ -1,11 +1,14 @@
local args = {...} local args = {...}
local kernel = args[1] local kernel = args[1]
kernel.log("initializing third party drivers")
for _,l in ipairs(kernel.drivers.prior) do for _,v in ipairs(kernel.drivers.raw) do
for _,d in ipairs(l) do if v.arch==kernel.arch then
if d.init then if v.load then
local ok,err = xpcall(d.init, debug.traceback) kernel.log("Loading "..v.name)
if not ok then kernel.log("DriverInitErr: "..tostring(err)) end local ok,err = xpcall(v.load, debug.traceback)
if not ok then
kernel.log("DriverLoadErr: "..tostring(err))
end
end end
end end
end end

View File

@@ -3,15 +3,23 @@ local kernel = args[1]
local tasks={} local tasks={}
local currentTask={} local currentTask={}
local signals={} local signals={}
local tid=1 local tid=2
local gid=1 local gid=2
local hookuuid=0
local sys={} local sys={}
function sys.hookSig(sig, func) function sys.hookSig(sig, func)
if not signals[tostring(currentTask.pid)][sig] then if not currentTask.signal[sig] then
signals[tostring(currentTask.pid)][sig]={} currentTask.signal[sig]={}
end end
signals[tostring(currentTask.pid)][sig][#signals[tostring(currentTask.pid)][sig]+1]=func hookuuid=hookuuid+1
currentTask.signal[sig][tostring(hookuuid)]=func
callbackid=tostring(hookuuid)
return {
remove=function()
currentTask.signal[sig][callbackid]=nil
end
}
end end
function sys.clearSigHooks(typ) function sys.clearSigHooks(typ)
@@ -27,7 +35,7 @@ end
function sys.sendSig(pid, signal, ...) function sys.sendSig(pid, signal, ...)
if pid=="all" then if pid=="all" then
for i,v in pairs(tasks) do for i,v in pairs(tasks) do+
v.sigQ[#v.sigQ+1]={signal, ...} v.sigQ[#v.sigQ+1]={signal, ...}
end end
return return
@@ -38,23 +46,27 @@ function sys.sendSig(pid, signal, ...)
end end
function sys.flushSigs() function sys.flushSigs()
local ret = {} local sigs = {}
for i=1, #currentTask.sigQ do for i,v in ipairs(currentTask.sigQ) do
if currentTask.signal[currentTask.sigQ[i][1]] then sigs[i]=v
for _,v in ipairs(currentTask.signal[currentTask.sigQ[1][1]]) do 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() coroutine.resumeWithTimeout(coroutine.create(function()
local ok, err = xpcall(v, debug.traceback, table.unpack(table.remove(currentTask.sigQ, 1))) local ok,err = xpcall(v,debug.traceback,table.unpack(sig))
if not ok then if not ok and sig[1]~="callbackErr" then
table.insert(ret, err) sys.sendSig(currentTask.pid, "callbackErr", sig[1], k, err)
end end
end),10) end),10)
end end
else else
for _,v in ipairs(currentTask.signal["unhandledEvent"]) do for k,v in pairs(currentTask.signal["unhandledSignal"]) do
coroutine.resumeWithTimeout(coroutine.create(function() coroutine.resumeWithTimeout(coroutine.create(function()
local ok, err = xpcall(v, debug.traceback, table.unpack(table.remove(currentTask.sigQ, 1))) local ok,err = xpcall(v,debug.traceback,table.unpack(sig))
if not ok then if not ok and sig[1]~="callbackErr" then
table.insert(ret, err) sys.sendSig(currentTask.pid, "callbackErr", sig[1], k, err)
end end
end),10) end),10)
end end
@@ -62,7 +74,7 @@ function sys.flushSigs()
end end
end end
function sys.spawn(func, name, evars, args) function sys.spawn(func, name, evars, args, stdin, stdout, stderr)
local id=tid local id=tid
tid=tid+1 tid=tid+1
name=name or tostring(id) name=name or tostring(id)
@@ -89,6 +101,7 @@ function sys.spawn(func, name, evars, args)
vy=0, vy=0,
ivy=0, ivy=0,
status="R", status="R",
sleep=0,
signal=signals[tostring(id)], signal=signals[tostring(id)],
parent=currentTask, parent=currentTask,
children={}, children={},
@@ -97,6 +110,12 @@ function sys.spawn(func, name, evars, args)
} }
end end
function sys.exit(...)
sys.sendSig(currentTask.ppid, "ChildTaskExit", currentTask.pid, ...)
currentTask.status="Z"
coroutine.yield()
end
local function collectZombieProc() local function collectZombieProc()
local ret = {} local ret = {}
for _,v in pairs(tasks) do for _,v in pairs(tasks) do
@@ -116,13 +135,23 @@ local function collectZombieProc()
return ret return ret
end end
kernel.log("initPath is: " .. tostring(kernel.initPath))
signals["1"]={} signals["1"]={}
tasks["1"]={ tasks["1"]={
coro=coroutine.create(function() coro=coroutine.create(function()
local ret = {xpcall(kernel.fs.load(kernel.initPath), debug.traceback)} 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 if not ok then
currentTask.status="Z"
kernel.panic(err) kernel.panic(err)
else else
currentTask.status="Z"
kernel.panic("Attempted to kill init!") kernel.panic("Attempted to kill init!")
end end
end), end),
@@ -130,27 +159,38 @@ tasks["1"]={
pid=1, pid=1,
ppid=0, ppid=0,
tgid=1, tgid=1,
user=kernel.user, user="root",
uid=kernel.uid, uid=0,
evars={}, evars={},
args={kernel}, args={kernel},
vy=0, vy=0,
ivy=0, ivy=0,
status="R", status="R",
sleep=0,
signal=signals["1"], signal=signals["1"],
parent={name="Hyprkrnl",pid=0}, parent={name="Hyprkrnl",pid=0},
children={}, children={},
sibling={}, sibling={},
sigQ={} sigQ={}
} }
kernel.chache.preload.sys=sys tasks["1"].sibling={tasks["1"]}
kernel.chache.preload.system=sys
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.hpv=sys
kernel.tasks=tasks
kernel.signals=signals
kernel.currentTask=currentTask
kernel.saveLog() kernel.saveLog()
while true do kernel.status="running"
for _,v in pairs(tasks) do while kernel.status~="Panic" do
for k,v in pairs(tasks) do
currentTask=v currentTask=v
kernel.currentTask=v
kernel.process=currentTask.name
kernel.user=currentTask.user kernel.user=currentTask.user
kernel.uid=currentTask.uid kernel.uid=currentTask.uid
sys.flushSigs() sys.flushSigs()
@@ -164,4 +204,7 @@ while true do
collectZombieProc() collectZombieProc()
end end
kernel.panic("Exited pid 0") kernel.process="Kernel"
kernel.user="root"
kernel.uid=0
kernel.panic(kernel.reason or "Exited pid 0")

View File

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

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

View File

@@ -1,2 +1,3 @@
U $;/ U $;/
U devfs0000;/dev/ U devfs0000;/dev/
U sysfs0000;/sys/

View File

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

View File

@@ -0,0 +1,26 @@
local args={...}
local kernel=args[1]
local driver={}
driver.name="CCT Term Module"
driver.version="0.1.0"
driver.type="gpio"
driver.description="CCT redstone Module Kernel Module"
driver.arch="cct"
driver.author="HyperionOS Dev Team"
driver.license="MIT"
driver.api={}
function driver.load()
-- will
end
function driver.unload()
-- Nothing to unload
end
function driver.main()
-- Nothing to run
end
kernel.drivers.register(driver)

View File

@@ -0,0 +1,105 @@
local args={...}
local kernel=args[1]
local apis=kernel.apis
local native=apis.peripheral
local driver={}
local sides = {"top", "bottom", "left", "right", "front", "back"}
local function 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
local function 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
driver.name="CCT TTY Module"
driver.version="0.1.0"
driver.type="tty"
driver.description="CCT TTY Module Kernel Module"
driver.arch="cct"
driver.author="HyperionOS Dev Team"
driver.license="MIT"
driver.api={}
local colors={
[0]=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
}
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 function getAllScreens()
end
local function wrapScreens()
end
function driver.load()
-- Nothing to load
end
function driver.unload()
-- Nothing to unload
end
function driver.main()
-- Nothing to run
end
kernel.drivers.register(driver)

View File

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

@@ -14,22 +14,26 @@ kernel.group = "root"
kernel.groups = {0} kernel.groups = {0}
kernel.uid = 0 kernel.uid = 0
kernel.gid = 0 kernel.gid = 0
kernel.stage = "start" kernel.status = "start"
kernel.key = {} kernel.key = {}
kernel.chache = {} kernel.cache = {}
kernel.chache.preload = {} kernel.cache.preload = {}
kernel._G=_G
local windowsExp = false local windowsExp = false
function kernel.log(msg, level) function kernel.log(msg, level)
LOG_Text = LOG_Text..tostring(computer.time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n" LOG_Text = LOG_Text..tostring(computer.time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n"
if kernel.stage == "start" then if kernel.status == "start" then
screen:print(tostring(computer.time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg) screen:print(tostring(computer.time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg)
end end
end end
function kernel.PANIC(msg) function kernel.PANIC(msg)
if kernel.status~="Panic" then
kernel.log("PANIC: "..msg, "PANIC") kernel.log("PANIC: "..msg, "PANIC")
pcall(kernel["saveLog"]) pcall(kernel["saveLog"])
kernel.status="Panic"
kernel.reason=msg
screen:setTextColor(2) screen:setTextColor(2)
screen:setBackgroundColor(0) screen:setBackgroundColor(0)
screen:clear() screen:clear()
@@ -37,6 +41,7 @@ function kernel.PANIC(msg)
screen:print(LOG_Text) screen:print(LOG_Text)
screen:print("KERNEL PANIC!\n"..msg.."\nSystem halted.") screen:print("KERNEL PANIC!\n"..msg.."\nSystem halted.")
screen:print("Press any key to continue...") screen:print("Press any key to continue...")
end
while true do while true do
local event={computer:getMachineEvent()} local event={computer:getMachineEvent()}
if event[1]=="keyPressed" then if event[1]=="keyPressed" then
@@ -65,16 +70,12 @@ if windowsExp then
while true do end while true do end
end end
kernel.log("Kernel loaded.", "INFO") kernel.log("Kernel loaded.")
kernel.log("Mounting disks...", "INFO") kernel.log("Mounting init disks...")
disks.refresh() disks.refresh()
ifs.update(disks) ifs.update(disks)
ifs.mount("$", "/") ifs.mount("$", "/")
function kernel.saveLog()
ifs.writeAllText("/var/log/syslog.log", LOG_Text)
end
local fstab=ifs.readAllText("/etc/fstab") local fstab=ifs.readAllText("/etc/fstab")
local split = function(str, delim, maxResultCountOrNil) local split = function(str, delim, maxResultCountOrNil)
assert(#delim == 1, "only delim len 1 supported for now") assert(#delim == 1, "only delim len 1 supported for now")
@@ -104,11 +105,15 @@ for i,v in ipairs(split(fstab,"\n")) do
end end
end end
local path=v:sub(#id+4) local path=v:sub(#id+4)
kernel.log("Mounted "..id.." to "..path)
ifs.mount(id,path) ifs.mount(id,path)
::endline:: ::endline::
end end
end end
kernel.log("Disks initialized")
function kernel.saveLog()
ifs.writeAllText("/var/log/syslog.log", LOG_Text)
end
ifs.remove("/tmp") ifs.remove("/tmp")
ifs.makeDir("/tmp") ifs.makeDir("/tmp")
@@ -116,29 +121,24 @@ ifs.makeDir("/tmp")
local drivers={} local drivers={}
drivers.raw={} drivers.raw={}
drivers.processes={} drivers.processes={}
drivers.prior={}
drivers.type={} drivers.type={}
for i=0, 99 do
drivers.prior[i]={}
end
function drivers.register(prior,object) function drivers.register(object)
drivers.raw[#drivers.raw+1]=object drivers.raw[#drivers.raw+1]=object
if object.main then drivers.processes[#drivers.processes+1]=object.main end 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 if drivers.type[object.type]==nil then drivers.type[object.type]={} end
drivers.type[object.type][#drivers.type[object.type]+1]=object drivers.type[object.type][#drivers.type[object.type]+1]=object
end end
local modules={} local modules={[0]={}}
for i=0, 99 do for i=0, 100 do
modules[i]={} modules[i]={}
end end
kernel.log("Gathering modules")
for i,v in ipairs(ifs.list("/lib/modules/Hyperion/")) do for i,v in ipairs(ifs.list("/lib/modules/Hyperion/")) do
local prior=tonumber(v:sub(1,2)) local prior=tonumber(v:sub(1,2))
modules[prior][#modules[prior]+1]="/lib/modules/Hyperion/"..v modules[prior+1][#modules[prior+1]+1]="/lib/modules/Hyperion/"..v
end end
kernel.drivers=drivers kernel.drivers=drivers
@@ -147,19 +147,17 @@ kernel.apis=apis
kernel.computer=computer kernel.computer=computer
kernel.initPath=initPath kernel.initPath=initPath
kernel.arch=arch kernel.arch=arch
kernel.initdisks=initdisks kernel.initdisks=disks
kernel.screen=screen kernel.screen=screen
kernel.log("Running modules")
for _,p in ipairs(modules) do for _,p in ipairs(modules) do
for _,v in ipairs(p) do for _,v in ipairs(p) do
local code=ifs.readAllText(v) local code=ifs.readAllText(v)
local func,err=load(code,"@"..v) local func,err=load(code,"@"..v)
if not func then kernel.log("ModuLoadErr: "..tostring(err)) goto skip end if not func then kernel.log("ModuLoadErr: "..tostring(err), "WARN") goto skip end
local status, err = xpcall(func,debug.traceback, kernel) local status, err = xpcall(func,debug.traceback, kernel)
if not status then goto skip end if not status then kernel.log("ModuRunErr: "..tostring(err), "WARN") 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:: ::skip::
end end
end end

View File

@@ -1,3 +1,5 @@
local args={...}
local kernel=args[1]
function string.hasSuffix(str, suffix) function string.hasSuffix(str, suffix)
return string.sub(str, #suffix+1) == suffix return string.sub(str, #suffix+1) == suffix
end end
@@ -94,6 +96,62 @@ function table.hasVal(tabl, query)
return false return false
end end
function table.proxy(tbl)
local proxies = setmetatable({}, {__mode = "k"}) -- Weak table to avoid cycles
local function createProxy(t)
if type(t) ~= "table" then return t end
if proxies[t] then return proxies[t] end -- reuse proxy for the same table (handle cycles)
local proxy = {}
proxies[t] = proxy
local mt
mt = {
__index = function(_, k)
local value = t[k]
if type(value) == "table" then
return createProxy(value) -- recursively proxy subtables
else
return value
end
end,
__newindex = function()
error("Attempt to modify read-only table", 2)
end,
__pairs = function()
return function(_, k)
local nextKey, nextValue = next(t, k)
if type(nextValue) == "table" then
nextValue = createProxy(nextValue)
end
return nextKey, nextValue
end, nil, nil
end,
__ipairs = function()
local i = 0
local n = #t
return function()
i = i + 1
if i <= n then
local v = t[i]
if type(v) == "table" then
v = createProxy(v)
end
return i, v
end
end
end,
__metatable = false
}
setmetatable(proxy, mt)
return proxy
end
return createProxy(tbl)
end
local function serialize(table) local function serialize(table)
local output = "{" local output = "{"
for i,v in pairs(table) do for i,v in pairs(table) do
@@ -119,7 +177,7 @@ local function serialize(table)
output=output.."false" output=output.."false"
end end
elseif type(v) == "function" then elseif type(v) == "function" then
output=output.."function() end" output=output..tostring(v)
else else
error("serialization of type \""..type(v).."\" is not supported") error("serialization of type \""..type(v).."\" is not supported")
end end
@@ -135,3 +193,4 @@ local function serialize(table)
end end
table.serialize=serialize table.serialize=serialize
kernel.log("Loaded stdlib")

View File

@@ -0,0 +1,3 @@
local args={...}
local kernel=args[1]
kernel._U=table.proxy(_G)

View File

@@ -1,217 +1,321 @@
local args = {...} local args = {...}
local kernel = args[1] local kernel = args[1]
local fs = {} local fs = {}
local disks = {}
local mounts = {["/"]="$"}
-- path normaliing -- =====================================================================
local function normalizePath(path) -- INTERNAL STATE
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 disks = {} -- address → disk object
local function resolvePath(path) local mounts = {["/"] = "$"} -- mountpoint → disk address (root = boot disk)
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_PREFIX = "#!@SYMLINK["
local SYMLINK_SUFFIX = "]" local SYMLINK_SUFFIX = "]"
local SYMLINK_MAX_DEPTH = 64 local SYMLINK_MAX_DEPTH = 64
local function isSymlink(disk, path)
if not disk:fileExists(path) then return false end -- =====================================================================
local text = disk:readAllText(path) -- PATH NORMALIZATION
if not text then return false end -- =====================================================================
return text:sub(1, #SYMLINK_PREFIX) == SYMLINK_PREFIX
local function splitPath(p)
local t = {}
for part in p:gmatch("[^/]+") do t[#t+1] = part end
return t
end end
local function readSymlink(disk, path) local function normalizePath(path)
local text = disk:readAllText(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 not text then return nil end
if text:sub(1, #SYMLINK_PREFIX) ~= SYMLINK_PREFIX 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 local t = text:sub(#SYMLINK_PREFIX + 1)
target = target:sub(1, -2) if t:sub(-1) == SYMLINK_SUFFIX then
t = t:sub(1, -2)
end end
return target return t
end end
-- Path resolution -- =====================================================================
local function splitPath(p) -- FULL PATH RESOLUTION (FOLLOWS SYMLINKS)
local parts = {} -- =====================================================================
for part in p:gmatch("[^/]+") do parts[#parts+1] = part end
return parts
end
local function resolveSymlink(path) local function resolveSymlink(path)
path = normalizePath(path) local abs = normalizePath(path)
local symlinkDepth = 0 local parts = splitPath(abs)
local parts = splitPath(path) local out = {}
local resolved = {}
local i = 1 local depth = 0
local idx = 1
while idx <= #parts do
local comp = parts[idx]
while i <= #parts do
local comp = parts[i]
if comp == "." then if comp == "." then
-- nothing
elseif comp == ".." then elseif comp == ".." then
if #resolved > 0 then table.remove(resolved) end if #out > 0 then table.remove(out) end
else else
local currentPath = "/" .. table.concat(resolved, "/") local curAbs = "/" .. table.concat(out, "/")
local disk, p = resolvePath(currentPath .. "/" .. comp) if curAbs ~= "/" then curAbs = curAbs .. "/" end
if isSymlink(disk, p) then curAbs = curAbs .. comp
symlinkDepth = symlinkDepth + 1
if symlinkDepth > SYMLINK_MAX_DEPTH then local disk, dpath = resolveMount(curAbs)
error("Too many levels of symbolic links: " .. path)
if isSymlinkRaw(disk, dpath) then
depth = depth + 1
if depth > SYMLINK_MAX_DEPTH then
error("Too many symlink levels: " .. path)
end end
local target = readSymlink(disk, p)
if not target then local target = readSymlinkRaw(disk, dpath)
resolved[#resolved+1] = comp if target then
else local newAbs
if target:sub(1,1) == "/" then if target:sub(1,1) == "/" then
resolved = splitPath(normalizePath(target)) -- absolute target
newAbs = normalizePath(target)
else else
local base = resolved -- relative to current out[]
resolved = {} local tmp = "/" .. table.concat(out, "/")
for _, seg in ipairs(base) do resolved[#resolved+1]=seg end if tmp ~= "/" then tmp = tmp .. "/" end
for seg in target:gmatch("[^/]+") do tmp = tmp .. target
if seg == ".." then newAbs = normalizePath(tmp)
if #resolved>0 then table.remove(resolved) end
elseif seg ~= "." then
resolved[#resolved+1]=seg
end
end
end end
-- rebuild remaining parts
local remaining = {} local remaining = {}
for j=i+1,#parts do remaining[#remaining+1]=parts[j] end for j = idx + 1, #parts do
parts = remaining remaining[#remaining+1] = parts[j]
i = 0 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 end
else else
resolved[#resolved+1]=comp out[#out+1] = comp
end end
end end
i=i+1
end
local finalPath="/"..table.concat(resolved,"/") idx = idx + 1
local disk,diskPath=resolvePath(finalPath)
return disk,diskPath
end end
-- PUBLIC API: MOUNTING local finalAbs = "/" .. table.concat(out, "/")
function fs.mount(disk, mountPoint) return resolveMount(finalAbs)
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 end
-- =====================================================================
-- PUBLIC API
-- =====================================================================
-- MOUNT OPERATIONS -----------------------------------------------------
function fs.virtDisk(diskObj) function fs.virtDisk(diskObj)
if kernel.uid ~= 0 then error("Permission Denied") end if kernel.uid ~= 0 then error("Permission Denied") end
if disks[diskObj.address] then error("Disk exists") end if disks[diskObj.address] then
error("Disk exists: " .. diskObj.address)
end
disks[diskObj.address] = diskObj disks[diskObj.address] = diskObj
end 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) function fs.eject(addr)
if kernel.uid ~= 0 then error("Permission Denied") end if kernel.uid ~= 0 then error("Permission Denied") end
disks[addr] = nil disks[addr] = nil
end end
-- SYMLINK API function fs.isMount(path)
if mounts[normalizePath(path)] then return true, mounts[normalizePath(path)] end
end
-- SYMLINK API ----------------------------------------------------------
function fs.symlink(target, linkPath) function fs.symlink(target, linkPath)
local disk, p = resolvePath(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) return disk:writeAllText(p, SYMLINK_PREFIX .. target .. SYMLINK_SUFFIX)
end end
function fs.isLink(path) function fs.isLink(path)
local disk, p = resolvePath(path) local disk, p = resolveMount(normalizePath(path))
return isSymlink(disk,p) return isSymlinkRaw(disk, p)
end end
function fs.readLink(path) function fs.readLink(path)
local disk, p = resolvePath(path) local disk, p = resolveMount(normalizePath(path))
return readSymlink(disk,p) return readSymlinkRaw(disk, p)
end end
-- FILE OPERATIONS
function fs.exists(path) -- FILE OPERATIONS ------------------------------------------------------
function fs.exists(path, ...)
local disk, p = resolveSymlink(path) local disk, p = resolveSymlink(path)
return disk:fileExists(p) or disk:directoryExists(p) return disk:fileExists(p, ...) or disk:directoryExists(p, ...)
end end
function fs.isFile(path) function fs.isFile(path, ...)
local disk, p = resolveSymlink(path) local disk, p = resolveSymlink(path)
if isSymlink(disk, p) then return false end return disk:fileExists(p, ...)
return disk:fileExists(p)
end end
function fs.isDir(path) function fs.isDir(path, ...)
local disk, p = resolveSymlink(path) local disk, p = resolveSymlink(path)
if isSymlink(disk, p) then return false end return disk:directoryExists(p, ...)
return disk:directoryExists(p)
end end
function fs.list(path) function fs.list(path, ...)
local disk, p = resolveSymlink(path) local disk, p = resolveSymlink(path)
return disk:list(p) return disk:list(p, ...)
end end
function fs.makeDir(path) function fs.makeDir(path, ...)
local disk, p = resolveSymlink(path) local disk, p = resolveSymlink(path)
return disk:makeDirectory(p) return disk:makeDirectory(p, ...)
end end
function fs.remove(path) -- remove does NOT follow symlinks (UNIX semantics)
local disk, p = resolvePath(path) function fs.remove(path, ...)
if isSymlink(disk, p) then if fs.isMount(path) then return "Cannot delete mounted folder" end
return disk:remove(p) local abs = normalizePath(path)
end local disk, p = resolveMount(abs)
local d2, p2 = resolveSymlink(path) return disk:remove(p, ...)
return d2:remove(p2)
end end
function fs.readAllText(path) function fs.readAllText(path, ...)
local disk, p = resolveSymlink(path) local disk, p = resolveSymlink(path)
return disk:readAllText(p) return disk:readAllText(p, ...)
end end
function fs.writeAllText(path, text) function fs.writeAllText(path, text, ...)
local disk, p = resolveSymlink(path) local disk, p = resolveSymlink(path)
return disk:writeAllText(p, text) return disk:writeAllText(p, text, ...)
end end
function fs.appendAllText(path, text) function fs.appendAllText(path, text, ...)
local disk, p = resolveSymlink(path) local disk, p = resolveSymlink(path)
return disk:appendAllText(p, text) return disk:appendAllText(p, text, ...)
end end
function fs.getSize(path) 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) local disk, p = resolveSymlink(path)
return disk:getSize(p) return disk:getSize(p, ...)
end end
-- =====================================================================
-- INIT -- INIT
for _,v in kernel.initdisks.list() do fs.virtDisk(v) end -- =====================================================================
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.fs = fs
kernel.chache.preload.fs=fs kernel.cache.preload.fs = table.proxy(kernel.fs)
kernel.chache.preload.filesystem=fs kernel.cache.preload.filesystem = kernel.cache.preload.fs

View File

@@ -1,6 +1,5 @@
local args = {...} local args = {...}
local kernel = args[1] local kernel = args[1]
function kernel.fs.mkvirtfs(address, readOnly, label, autoRegister) function kernel.fs.mkvirtfs(address, readOnly, label, autoRegister)
if kernel.uid ~= 0 then error("Permission Denied") end if kernel.uid ~= 0 then error("Permission Denied") end
local disk = {} local disk = {}
@@ -55,34 +54,36 @@ function kernel.fs.mkvirtfs(address, readOnly, label, autoRegister)
-- File IO (supports string or file-object with read/write funcs) -- File IO (supports string or file-object with read/write funcs)
----------------------------------------------------------------- -----------------------------------------------------------------
local function fileRead(node) local function fileRead(node, ...)
if type(node) == "string" then if type(node) == "string" then
return node return node
elseif type(node) == "table" and node.__file and node.read then elseif type(node) == "table" and node.__file and node.read then
return node.read() return node.read(...)
end end
return nil return nil
end end
local function fileWrite(parent, name, text) local function fileWrite(parent, name, text, ...)
local node = parent[name] local node = parent[name]
if type(node) == "string" then if type(node) == "string" then
local ok, err = ensureWrite(); if not ok then return false, err end
parent[name] = text parent[name] = text
return true return true
elseif type(node) == "table" and node.__file and node.write then elseif type(node) == "table" and node.__file and node.write then
return node.write(text) return node.write(text, ...)
end end
parent[name] = text parent[name] = text
return true return true
end end
local function fileAppend(parent, name, text) local function fileAppend(parent, name, text, ...)
local node = parent[name] local node = parent[name]
if type(node) == "string" then if type(node) == "string" then
local ok, err = ensureWrite(); if not ok then return false, err end
parent[name] = node .. text parent[name] = node .. text
return true return true
elseif type(node) == "table" and node.__file and node.write then elseif type(node) == "table" and node.__file and node.write then
return node.write((node.read() or "") .. text) return node.write((node.read() or "") .. text, ...)
end end
parent[name] = text parent[name] = text
return true return true
@@ -96,26 +97,22 @@ function kernel.fs.mkvirtfs(address, readOnly, label, autoRegister)
function disk:spaceUsed() return 0 end function disk:spaceUsed() return 0 end
function disk:spaceTotal() return 0 end function disk:spaceTotal() return 0 end
function disk:readAllText(path) function disk:readAllText(path, ...)
local node = getNode(path) local node = getNode(path)
if not node then return nil, "file not found" end if not node then return nil, "file not found" end
return fileRead(node) return fileRead(node, ...)
end end
function disk:writeAllText(path, text) function disk:writeAllText(path, text, ...)
local ok, err = ensureWrite(); if not ok then return false, err end
local parent, name = getParent(path) local parent, name = getParent(path)
if not parent or not parent.__dir then return false, "invalid directory" end if not parent or not parent.__dir then return false, "invalid directory" end
return fileWrite(parent, name, tostring(text)) return fileWrite(parent, name, tostring(text), ...)
end end
function disk:appendAllText(path, text) function disk:appendAllText(path, text, ...)
local ok, err = ensureWrite(); if not ok then return false, err end
local parent, name = getParent(path) local parent, name = getParent(path)
if not parent or not parent.__dir then return false, "invalid directory" end if not parent or not parent.__dir then return false, "invalid directory" end
return fileAppend(parent, name, tostring(text)) return fileAppend(parent, name, tostring(text), ...)
end end
function disk:list(path) function disk:list(path)
@@ -161,11 +158,11 @@ function kernel.fs.mkvirtfs(address, readOnly, label, autoRegister)
return label return label
end end
function disk:size(path) function disk:size(path, ...)
local node = getNode(path) local node = getNode(path)
if type(node) == "string" then return #node end if type(node) == "string" then return #node end
if type(node) == "table" and node.__file and node.read then if type(node) == "table" and node.__file and node.read then
local v = node.read() local v = node.read(...)
return v and #v or 0 return v and #v or 0
end end
return 0 return 0
@@ -174,7 +171,7 @@ function kernel.fs.mkvirtfs(address, readOnly, label, autoRegister)
----------------------------------------------------------------- -----------------------------------------------------------------
-- Auto-register with kernel and return backend -- Auto-register with kernel and return backend
----------------------------------------------------------------- -----------------------------------------------------------------
if kernel and kernel.fs and kernel.fs.virtDisk and autoRegister then if autoRegister then
kernel.fs.virtDisk(disk) kernel.fs.virtDisk(disk)
end end

View File

@@ -1,6 +1,5 @@
local args = {...} local args = {...}
local kernel = args[1] local kernel = args[1]
-- List of search paths -- List of search paths
local paths = { local paths = {
"/lib/?", "/lib/?",
@@ -11,7 +10,7 @@ local paths = {
-- Custom require implementation -- Custom require implementation
function require(module) function require(module)
-- Return cached module if it already exists -- Return cached module if it already exists
if kernel.cache.preload[module] then if kernel.cache.preload[module]~=nil then
return kernel.cache.preload[module] return kernel.cache.preload[module]
end end
@@ -54,3 +53,4 @@ function require(module)
-- If nothing worked, raise an error with all reasons -- If nothing worked, raise an error with all reasons
error("Unable to require module '" .. module .. "':\n" .. table.concat(err, "\n")) error("Unable to require module '" .. module .. "':\n" .. table.concat(err, "\n"))
end end
kernel.log("Created require")

View File

@@ -1,7 +1,9 @@
local args = {...} local args = {...}
local kernel = args[1] local kernel = args[1]
local data = kernel.fs.mkvirtfs("devfs0000", true, "devfs", true)
local data = kernel.fs.mkvirtfs("devfs0000", true, "devfs", false) 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["/"]["OSVERSION"]="Hyperion 1.0.0"
data["/"]["eeprom"]={ data["/"]["eeprom"]={
@@ -14,4 +16,42 @@ data["/"]["eeprom"]={
kernel.computer:setEEPROM(text) kernel.computer:setEEPROM(text)
end 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

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

View File

@@ -10,3 +10,4 @@ kernel.drivers.processes[#kernel.drivers.processes+1]=function()
coroutine.yield() coroutine.yield()
end end
end end
kernel.log("Created keventd daemon")

View File

@@ -1,17 +1,20 @@
local args = {...} local args = {...}
local kernel=args[2] local kernel = args[1]
kernel.log("Loading third party drivers")
for _,subf in ipairs(kernel.fs.list("/lib/modules/")) do for _,subf in ipairs(kernel.fs.list("/lib/modules/")) do
if kernel.fs.isDir("/lib/modules/"..subf) then
if subf~="Hyperion" then if subf~="Hyperion" then
for _,driver in ipairs(kernel.fs.list("/lib/modules/"..subf)) do for _,driver in ipairs(kernel.fs.list("/lib/modules/"..subf)) do
kernel.log("Compiling driver \""..subf..":"..driver.."\"")
local code = kernel.fs.readAllText("/lib/modules/"..subf.."/"..driver) local code = kernel.fs.readAllText("/lib/modules/"..subf.."/"..driver)
local func, err = load(code, "@"..driver) local func, err = load(code, "@"..driver)
if not func then if not func then
kernel.log("DriverLoadErr: "..tostring(err), "ERROR") kernel.log("DriverCompileErr: "..tostring(err), "ERROR")
else else
local ok, err = xpcall(func, debug.traceback) local ok, err = xpcall(func, debug.traceback, table.unpack(args))
if not ok then if not ok then
kernel.log("DriverLoadErr: "..tostring(err), "ERROR") kernel.log("DriverExecErr: "..tostring(err), "ERROR")
end
end end
end end
end end

View File

@@ -1,11 +1,14 @@
local args = {...} local args = {...}
local kernel = args[1] local kernel = args[1]
kernel.log("initializing third party drivers")
for _,l in ipairs(kernel.drivers.prior) do for _,v in ipairs(kernel.drivers.raw) do
for _,d in ipairs(l) do if v.arch==kernel.arch then
if d.init then if v.load then
local ok,err = xpcall(d.init, debug.traceback) kernel.log("Loading "..v.name)
if not ok then kernel.log("DriverInitErr: "..tostring(err)) end local ok,err = xpcall(v.load, debug.traceback)
if not ok then
kernel.log("DriverLoadErr: "..tostring(err))
end
end end
end end
end end

View File

@@ -3,15 +3,23 @@ local kernel = args[1]
local tasks={} local tasks={}
local currentTask={} local currentTask={}
local signals={} local signals={}
local tid=1 local tid=2
local gid=1 local gid=2
local hookuuid=0
local sys={} local sys={}
function sys.hookSig(sig, func) function sys.hookSig(sig, func)
if not signals[tostring(currentTask.pid)][sig] then if not currentTask.signal[sig] then
signals[tostring(currentTask.pid)][sig]={} currentTask.signal[sig]={}
end end
signals[tostring(currentTask.pid)][sig][#signals[tostring(currentTask.pid)][sig]+1]=func hookuuid=hookuuid+1
currentTask.signal[sig][tostring(hookuuid)]=func
callbackid=tostring(hookuuid)
return {
remove=function()
currentTask.signal[sig][callbackid]=nil
end
}
end end
function sys.clearSigHooks(typ) function sys.clearSigHooks(typ)
@@ -27,7 +35,7 @@ end
function sys.sendSig(pid, signal, ...) function sys.sendSig(pid, signal, ...)
if pid=="all" then if pid=="all" then
for i,v in pairs(tasks) do for i,v in pairs(tasks) do+
v.sigQ[#v.sigQ+1]={signal, ...} v.sigQ[#v.sigQ+1]={signal, ...}
end end
return return
@@ -38,23 +46,27 @@ function sys.sendSig(pid, signal, ...)
end end
function sys.flushSigs() function sys.flushSigs()
local ret = {} local sigs = {}
for i=1, #currentTask.sigQ do for i,v in ipairs(currentTask.sigQ) do
if currentTask.signal[currentTask.sigQ[i][1]] then sigs[i]=v
for _,v in ipairs(currentTask.signal[currentTask.sigQ[1][1]]) do 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() coroutine.resumeWithTimeout(coroutine.create(function()
local ok, err = xpcall(v, debug.traceback, table.unpack(table.remove(currentTask.sigQ, 1))) local ok,err = xpcall(v,debug.traceback,table.unpack(sig))
if not ok then if not ok and sig[1]~="callbackErr" then
table.insert(ret, err) sys.sendSig(currentTask.pid, "callbackErr", sig[1], k, err)
end end
end),10) end),10)
end end
else else
for _,v in ipairs(currentTask.signal["unhandledEvent"]) do for k,v in pairs(currentTask.signal["unhandledSignal"]) do
coroutine.resumeWithTimeout(coroutine.create(function() coroutine.resumeWithTimeout(coroutine.create(function()
local ok, err = xpcall(v, debug.traceback, table.unpack(table.remove(currentTask.sigQ, 1))) local ok,err = xpcall(v,debug.traceback,table.unpack(sig))
if not ok then if not ok and sig[1]~="callbackErr" then
table.insert(ret, err) sys.sendSig(currentTask.pid, "callbackErr", sig[1], k, err)
end end
end),10) end),10)
end end
@@ -62,7 +74,7 @@ function sys.flushSigs()
end end
end end
function sys.spawn(func, name, evars, args) function sys.spawn(func, name, evars, args, stdin, stdout, stderr)
local id=tid local id=tid
tid=tid+1 tid=tid+1
name=name or tostring(id) name=name or tostring(id)
@@ -89,6 +101,7 @@ function sys.spawn(func, name, evars, args)
vy=0, vy=0,
ivy=0, ivy=0,
status="R", status="R",
sleep=0,
signal=signals[tostring(id)], signal=signals[tostring(id)],
parent=currentTask, parent=currentTask,
children={}, children={},
@@ -97,6 +110,12 @@ function sys.spawn(func, name, evars, args)
} }
end end
function sys.exit(...)
sys.sendSig(currentTask.ppid, "ChildTaskExit", currentTask.pid, ...)
currentTask.status="Z"
coroutine.yield()
end
local function collectZombieProc() local function collectZombieProc()
local ret = {} local ret = {}
for _,v in pairs(tasks) do for _,v in pairs(tasks) do
@@ -116,13 +135,23 @@ local function collectZombieProc()
return ret return ret
end end
kernel.log("initPath is: " .. tostring(kernel.initPath))
signals["1"]={} signals["1"]={}
tasks["1"]={ tasks["1"]={
coro=coroutine.create(function() coro=coroutine.create(function()
local ret = {xpcall(kernel.fs.load(kernel.initPath), debug.traceback)} 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 if not ok then
currentTask.status="Z"
kernel.panic(err) kernel.panic(err)
else else
currentTask.status="Z"
kernel.panic("Attempted to kill init!") kernel.panic("Attempted to kill init!")
end end
end), end),
@@ -130,27 +159,38 @@ tasks["1"]={
pid=1, pid=1,
ppid=0, ppid=0,
tgid=1, tgid=1,
user=kernel.user, user="root",
uid=kernel.uid, uid=0,
evars={}, evars={},
args={kernel}, args={kernel},
vy=0, vy=0,
ivy=0, ivy=0,
status="R", status="R",
sleep=0,
signal=signals["1"], signal=signals["1"],
parent={name="Hyprkrnl",pid=0}, parent={name="Hyprkrnl",pid=0},
children={}, children={},
sibling={}, sibling={},
sigQ={} sigQ={}
} }
kernel.chache.preload.sys=sys tasks["1"].sibling={tasks["1"]}
kernel.chache.preload.system=sys
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.hpv=sys
kernel.tasks=tasks
kernel.signals=signals
kernel.currentTask=currentTask
kernel.saveLog() kernel.saveLog()
while true do kernel.status="running"
for _,v in pairs(tasks) do while kernel.status~="Panic" do
for k,v in pairs(tasks) do
currentTask=v currentTask=v
kernel.currentTask=v
kernel.process=currentTask.name
kernel.user=currentTask.user kernel.user=currentTask.user
kernel.uid=currentTask.uid kernel.uid=currentTask.uid
sys.flushSigs() sys.flushSigs()
@@ -164,4 +204,7 @@ while true do
collectZombieProc() collectZombieProc()
end end
kernel.panic("Exited pid 0") kernel.process="Kernel"
kernel.user="root"
kernel.uid=0
kernel.panic(kernel.reason or "Exited pid 0")

View File

@@ -4,22 +4,24 @@
Hyperion OS supports many driver types to allow it to run on any hardware Hyperion OS supports many driver types to allow it to run on any hardware
``` ```
Driver types Driver types
tto - Supports basic text terminal output tty - Supports basic teletype devices
gpio - Supports things like redstone gpio - Supports things like redstone
runner - Kernel level programs (no api) runner - Kernel level programs (no api)
timer - Timers and time related timer - Timers and time related
periph - Basic peripheral info periph - Basic peripheral info
gfx - PixelScreens gfx - PixelScreens
modem - networking
``` ```
Hyperion also has a base driver api Hyperion also has a base driver api
``` ```
Driver API Driver API
name - Name of driver+ name - Name of driver
type - Type of driver type - Type of driver
init - Ran before init load - loading code
unload - unloading code
main - Ran as a process and has normal behavior (used for checking network like things) main - Ran as a process and has normal behavior (used for checking network like things)
api - api difined by type api - api difined by type
arch - architecture difined in bootloader (EX: cct, oc, ac, cc, ccpc) arch - architecture difined in bootloader (EX: cct, oc, ac, cc, ccpc, or all)
description - discription description - discription
author - author of driver author - author of driver
prior - priority (low first) prior - priority (low first)

View File

@@ -1,188 +0,0 @@
local computer = component.getFirst("computer")
local screen=component.getFirst("screen")
if not screen then
local function e(...)end
screen = {
print=e,
printInline=e,
clear=e
}
end
local ok,err = xpcall(function()
-- Init components
_G._DEVELOPMENT=true
_G.component=component
local printed=""
local print=function(text)
printed=printed..text.."\n"
screen.print(text)
end
-- Get CFG
local biosCfg = {}
local i=1
while i<=256 do
biosCfg[i]=computer.getData(i) or ""
i=i+1
end
computer.beep(800,0.2)
local function 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 = deepcopy(k, copies)
local copied_val = deepcopy(v, copies)
copy[copied_key] = copied_val
end
return copy
end
local function save(table)
while i<=256 do
computer.setData(i, table[i] or nil)
i=i+1
end
end
local function hasKey(tabl, query)
for i,v in pairs(tabl) do
if i==query then
return true
end
end
return false
end
-- Start boot seq
local disks={}
for i,v in component.list() do
if i=="disk" then
disks[v.id]=v
end
end
local idx = 1
local bootOption=1
while true do
if biosCfg[idx]=="$EOF" then break end
print("Atempting boot option "..tostring(bootOption).." labled \""..biosCfg[idx].."\".")
bootOption=bootOption+1
local drive={}
idx=idx+1
if not hasKey(disks,biosCfg[idx]) then
print("└─ Drive not found.")
print(" ")
idx=idx+3
goto invalid_boot
else
drive=disks[biosCfg[idx]]
print("├─ Drive found with id of \""..drive.id.."\"")
end
idx=idx+1
local path
local code
if drive.type=="udd" then
print("├─ Drive is Unmanaged, looking for MBR...")
sleep(0.02)
print("├─ Reading MBR...")
local tmp = drive.readBytes(0,512)
print("├─ MBR found, compiling bootloader...")
code = table.concat(tmp)
else
if not drive:fileExists(biosCfg[idx]) then
print("└─ Path not found.")
print(" ")
idx=idx+2
goto invalid_boot
else
print("├─ Kernel exists at path \""..biosCfg[idx].."\"")
path=biosCfg[idx]
end
code = drive:open(path).read()
end
idx=idx+1
_VG=deepcopy(_G)
print("├─ Created virtual ENV.")
local _,func = pcall(load,code,drive.id.." | "..path,nil,_G)
if not func then
print("└─ Compilation failure.")
print(" ")
idx=idx+1
goto invalid_boot
else
print("├─ Executing.")
end
local cmd=biosCfg[idx] or ""
idx=idx+1
local biosData = {}
biosData.bootDrive=drive
biosData.term=screen
screen.clear()
local ok, err = xpcall(func, debug.traceback, biosData, cmd)
screen.clear()
screen.print(printed)
if not ok then
print("└─ OS exited with error: "..err)
print(" ")
else
print("└─ OS exited.")
print(" ")
end
screen.print("Press enter to continue...")
while true do
local event = {computer.getMachineEvent()}
if event[1] == "keyTyped" then
if event[3] == "\n" then
break
end
end
sleep(0.02)
end
::invalid_boot::
end
computer.beep(400,0.4)
print("No boot options available")
screen.print("Press enter to continue...")
while true do
local event = {computer.getMachineEvent()}
if event[1] == "keyTyped" then
if event[3] == "\n" then
computer.shutdown()
end
end
sleep(0.02)
end
end, debug.traceback)
if not ok then
screen.clear()
screen.print("BIOS PANIC: "..err)
computer.beep(800,0.2)
sleep(0.02)
computer.beep(800,0.2)
sleep(0.02)
computer.beep(800,0.2)
sleep(0.02)
screen.print("Press enter to continue...")
while true do
local event = {computer.getMachineEvent()}
if event[1] == "keyTyped" then
if event[3] == "\n" then
computer.shutdown()
end
end
sleep(0.02)
end
end

View File

@@ -1,3 +0,0 @@
{
"disks":[1,2,3,56]
}

View File

@@ -1,254 +0,0 @@
HyperionOS
disk_1
/boot/ac/boot.ac
HyperionOS Dev
disk_2
/boot/Hyprkrnl.sys
$EOF

View File

@@ -1,58 +0,0 @@
local computer = component.getFirst("computer")
local screen=component.getFirst("screen")
if not screen then
computer.beep(400,0.2)
sleep(0.2)
computer.beep(400,0.2)
while true do
computer.shutdown()
end
end
local idx = 1
local ok, err = xpcall(function()
for t, a in component.list() do
if t == "disk" then
if a:fileExists("boot.lua") then
screen.print("Bootable file found on "..a.id.." - reading...")
local code = a:open("boot.lua").read()
screen.print("Compiling boot.lua...")
local f = load(code)
if not f then error("bios boot compilation failed") end
screen.print("Booting...")
---@diagnostic disable-next-line: need-check-nil
local ok, err = xpcall(f, debug.traceback)
if not ok then screen.print(err); sleep(3) end
break
else
idx = idx+1
end
end
end
end, debug.traceback)
if not ok then
screen.print("BIOS error: "..err)
computer.beep(800,0.2)
osleep(0.02)
screen.print("Press enter to continue...")
while true do
local event = {computer.getMachineEvent()}
if event[1] == "keyTyped" then
if event[3] == "\n" then
computer.shutdown()
end
end
sleep(0.02)
end
end
computer.beep(400,0.4)
screen.print("No bootable filesystem found!")
screen.print("Press enter to continue...")
while true do
local event = {computer.getMachineEvent()}
if event[1] == "keyTyped" then
if event[3] == "\n" then
computer.shutdown()
end
end
sleep(0.02)
end

View File

@@ -1,3 +0,0 @@
{
"disks":[3,4,8]
}

View File

@@ -1,249 +0,0 @@

View File

@@ -1,189 +0,0 @@
local computer = component.getFirst("computer")
local screen=component.getFirst("screen")
if not screen then
local function e(...)end
screen = {
print=e,
printInline=e,
clear=e
}
end
local ok,err = xpcall(function()
-- Init components
_G._DEVELOPMENT=true
_G.component=component
local printed=""
local print=function(text)
printed=printed..text.."\n"
screen.print(text)
end
-- Get CFG
local biosCfg = {}
local i=1
while i<=256 do
biosCfg[i]=computer.getData(i) or ""
i=i+1
end
computer.beep(800,0.2)
-- Difine functions
local function copy(tabl)
local out = {}
for i,v in pairs(tabl) do
local t=type(v)
if t=="table" then
if i == "_G" then
out._G=out
else
out[i]=copy(v)
end
else
out[i]=v
end
end
return out
end
local function save(table)
while i<=256 do
computer.setData(i, table[i] or nil)
i=i+1
end
end
local function hasKey(tabl, query)
for i,v in pairs(tabl) do
if i==query then
return true
end
end
return false
end
-- Start boot seq
local disks={}
for i,v in component.list() do
if i=="disk" then
disks[v.id]=v
if v.type=="udd" then
v:writeBytes(0, "HDS") -- "HDS"
local tmp = v:readBytes(0,512) -- Just to make sure it writes the data
print(tmp)
end
end
end
local idx = 1
local bootOption=1
while true do
if biosCfg[idx]=="$EOF" then break end
print("Atempting boot option "..tostring(bootOption).." labled \""..biosCfg[idx].."\".")
bootOption=bootOption+1
local drive={}
idx=idx+1
if not hasKey(disks,biosCfg[idx]) then
print("└─ Drive not found.")
print(" ")
idx=idx+3
goto invalid_boot
else
drive=disks[biosCfg[idx]]
print("├─ Drive found with id of \""..drive.id.."\"")
end
idx=idx+1
local path
local code
if drive.type=="udd" then
print("├─ Drive is Unmanaged, looking for MBR...")
sleep(0.02)
print("├─ Reading MBR...")
local tmp = drive.readBytes(0,512)
print("├─ MBR found, compiling bootloader...")
code = table.concat(tmp)
else
if not drive:fileExists(biosCfg[idx]) then
print("└─ Path not found.")
print(" ")
idx=idx+2
goto invalid_boot
else
print("├─ Kernel exists at path \""..biosCfg[idx].."\"")
path=biosCfg[idx]
end
code = drive:open(path).read()
end
idx=idx+1
local _VG=copy(_G)
print("├─ Created virtual ENV.")
local _,func = pcall(load,code,drive.id.." | "..path,nil,_VG)
if not func then
print("└─ Compilation failure.")
print(" ")
idx=idx+1
goto invalid_boot
else
print("├─ Executing.")
end
local cmd=biosCfg[idx] or ""
idx=idx+1
local biosData = {}
biosData.bootDrive=drive
biosData.term=screen
screen.clear()
local ok, err = xpcall(func, debug.traceback, biosData, cmd)
screen.clear()
screen.print(printed)
if not ok then
print("└─ OS exited with error: "..err)
print(" ")
else
print("└─ OS exited.")
print(" ")
end
screen.print("Press enter to continue...")
while true do
local event = {computer.getMachineEvent()}
if event[1] == "keyTyped" then
if event[3] == "\n" then
break
end
end
sleep(0.02)
end
::invalid_boot::
end
computer.beep(400,0.4)
print("No boot options available")
screen.print("Press enter to continue...")
while true do
local event = {computer.getMachineEvent()}
if event[1] == "keyTyped" then
if event[3] == "\n" then
computer.shutdown()
end
end
sleep(0.02)
end
end, debug.traceback)
if not ok then
screen.clear()
screen.print("BIOS PANIC: "..err)
computer.beep(800,0.2)
sleep(0.02)
computer.beep(800,0.2)
sleep(0.02)
computer.beep(800,0.2)
sleep(0.02)
screen.print("Press enter to continue...")
while true do
local event = {computer.getMachineEvent()}
if event[1] == "keyTyped" then
if event[3] == "\n" then
computer.shutdown()
end
end
sleep(0.02)
end
end

View File

@@ -1,3 +0,0 @@
{
"disks":[1,2,3,4,8]
}

View File

@@ -1,249 +0,0 @@
HyperionOS
disk_3
/boot/ac/boot.ac

View File

@@ -1,46 +0,0 @@
local driverutil={}
function driverutil.getFirst(type)
if drivers[type] then
if drivers[type][1] then
return drivers[type][1]
end
end
end
function driverutil.list(type)
if not type then
local tmp={}
for i,v in ipairs(drivers.raw) do
tmp[#tmp+1] = {type=v.type, obj=v}
end
local i=0
return function()
i=i+1
if tmp[i]==nil then return end
return tmp[i].type, tmp[i].obj
end
else
local tmp={}
for i,v in ipairs(drivers[type]) do
tmp[#tmp+1] = {type=v.type, obj=v}
end
local i=0
return function()
i=i+1
if tmp[i]==nil then return end
return tmp[i].type, tmp[i].obj
end
end
end
local function runAsKernel(path, ...)
local func, err = load("return {'e'}", path, "t", _G)
if not func then return false, "\t"..err end
local ret = {xpcall(func, debug.traceback, ...)}
if not ret[1] then
return false, ret[2]
end
return true, table.unpack(ret, 2)
end
runAsKernel(e, driverutil)

View File

@@ -1,3 +0,0 @@
{
"disks":[1,2,3,4,8]
}

View File

@@ -1,249 +0,0 @@
HyperionOS
disk_3
/boot/ac/boot.ac

View File

@@ -1 +0,0 @@

View File

@@ -1,10 +0,0 @@
local args={...}
if #args>0 then
load(args[1])(table.unpack(args, 2))
else
local sys = require("system")
local evhook = sys.addEventHook("keyTyped", function()
end)
local term = sys.getParentTermObject()
end

View File

@@ -1,783 +0,0 @@
-- SPDX-FileCopyrightText: 2017 Daniel Ratcliffe
--
-- SPDX-License-Identifier: LicenseRef-CCPL
--[[- The shell API provides access to CraftOS's command line interface.
It allows you to @{run|start programs}, @{setCompletionFunction|add completion
for a program}, and much more.
@{shell} is not a "true" API. Instead, it is a standard program, which injects
its API into the programs that it launches. This allows for multiple shells to
run at the same time, but means that the API is not available in the global
environment, and so is unavailable to other @{os.loadAPI|APIs}.
## Programs and the program path
When you run a command with the shell, either from the prompt or
@{shell.run|from Lua code}, the shell API performs several steps to work out
which program to run:
1. Firstly, the shell attempts to resolve @{shell.aliases|aliases}. This allows
us to use multiple names for a single command. For example, the `list`
program has two aliases: `ls` and `dir`. When you write `ls /rom`, that's
expanded to `list /rom`.
2. Next, the shell attempts to find where the program actually is. For this, it
uses the @{shell.path|program path}. This is a colon separated list of
directories, each of which is checked to see if it contains the program.
`list` or `list.lua` doesn't exist in `.` (the current directory), so she
shell now looks in `/rom/programs`, where `list.lua` can be found!
3. Finally, the shell reads the file and checks if the file starts with a
`#!`. This is a [hashbang][], which says that this file shouldn't be treated
as Lua, but instead passed to _another_ program, the name of which should
follow the `#!`.
[hashbang]: https://en.wikipedia.org/wiki/Shebang_(Unix)
@module[module] shell
]]
local make_package = dofile("rom/modules/main/cc/require.lua").make
local multishell = multishell
local parentShell = shell
local parentTerm = term.current()
if multishell then
multishell.setTitle(multishell.getCurrent(), "shell")
end
local bExit = false
local sDir = parentShell and parentShell.dir() or ""
local sPath = parentShell and parentShell.path() or ".:/rom/programs"
local tAliases = parentShell and parentShell.aliases() or {}
local tCompletionInfo = parentShell and parentShell.getCompletionInfo() or {}
local tProgramStack = {}
local shell = {} --- @export
local function createShellEnv(dir)
local env = { shell = shell, multishell = multishell }
env.require, env.package = make_package(env, dir)
return env
end
-- Set up a dummy require based on the current shell, for loading some of our internal dependencies.
local require
do
local env = setmetatable(createShellEnv("/rom/programs"), { __index = _ENV })
require = env.require
end
local expect = require("cc.expect").expect
local exception = require "cc.internal.exception"
-- Colours
local promptColour, textColour, bgColour
if term.isColour() then
promptColour = colours.yellow
textColour = colours.white
bgColour = colours.black
else
promptColour = colours.white
textColour = colours.white
bgColour = colours.black
end
local function tokenise(...)
local sLine = table.concat({ ... }, " ")
local tWords = {}
local bQuoted = false
for match in string.gmatch(sLine .. "\"", "(.-)\"") do
if bQuoted then
table.insert(tWords, match)
else
for m in string.gmatch(match, "[^ \t]+") do
table.insert(tWords, m)
end
end
bQuoted = not bQuoted
end
return tWords
end
-- Execute a program using os.run, unless a shebang is present.
-- In that case, execute the program using the interpreter specified in the hashbang.
-- This may occur recursively, up to the maximum number of times specified by remainingRecursion
-- Returns the same type as os.run, which is a boolean indicating whether the program exited successfully.
local function executeProgram(remainingRecursion, path, args)
local file, err = fs.open(path, "r")
if not file then
printError(err)
return false
end
-- First check if the file begins with a #!
local contents = file.readLine() or ""
if contents:sub(1, 2) == "#!" then
file.close()
remainingRecursion = remainingRecursion - 1
if remainingRecursion == 0 then
printError("Hashbang recursion depth limit reached when loading file: " .. path)
return false
end
-- Load the specified hashbang program instead
local hashbangArgs = tokenise(contents:sub(3))
local originalHashbangPath = table.remove(hashbangArgs, 1)
local resolvedHashbangProgram = shell.resolveProgram(originalHashbangPath)
if not resolvedHashbangProgram then
printError("Hashbang program not found: " .. originalHashbangPath)
return false
elseif resolvedHashbangProgram == "rom/programs/shell.lua" and #hashbangArgs == 0 then
-- If we try to launch the shell then our shebang expands to "shell <program>", which just does a
-- shell.run("<program>") again, resulting in an infinite loop. This may still happen (if the user
-- has a custom shell), but this reduces the risk.
-- It's a little ugly special-casing this, but it's probably worth warning about.
printError("Cannot use the shell as a hashbang program")
return false
end
-- Add the path and any arguments to the interpreter's arguments
table.insert(hashbangArgs, path)
for _, v in ipairs(args) do
table.insert(hashbangArgs, v)
end
hashbangArgs[0] = originalHashbangPath
return executeProgram(remainingRecursion, resolvedHashbangProgram, hashbangArgs)
end
contents = contents .. "\n" .. (file.readAll() or "")
file.close()
local dir = fs.getDir(path)
local env = setmetatable(createShellEnv(dir), { __index = _G })
env.arg = args
local func, err = load(contents, "@/" .. fs.combine(path), nil, env)
if not func then
-- We had a syntax error. Attempt to run it through our own parser if
-- the file is "small enough", otherwise report the original error.
if #contents < 1024 * 128 then
local parser = require "cc.internal.syntax"
if parser.parse_program(contents) then printError(err) end
else
printError(err)
end
return false
end
if settings.get("bios.strict_globals", false) then
getmetatable(env).__newindex = function(_, name)
error("Attempt to create global " .. tostring(name), 2)
end
end
local ok, err, co = exception.try(func, table.unpack(args, 1, args.n))
if ok then return true end
if err and err ~= "" then
printError(err)
exception.report(err, co)
end
return false
end
--- Run a program with the supplied arguments.
--
-- Unlike @{shell.run}, each argument is passed to the program verbatim. While
-- `shell.run("echo", "b c")` runs `echo` with `b` and `c`,
-- `shell.execute("echo", "b c")` runs `echo` with a single argument `b c`.
--
-- @tparam string command The program to execute.
-- @tparam string ... Arguments to this program.
-- @treturn boolean Whether the program exited successfully.
-- @since 1.88.0
-- @usage Run `paint my-image` from within your program:
--
-- shell.execute("paint", "my-image")
function shell.execute(command, ...)
expect(1, command, "string")
for i = 1, select('#', ...) do
expect(i + 1, select(i, ...), "string")
end
local sPath = shell.resolveProgram(command)
if sPath ~= nil then
tProgramStack[#tProgramStack + 1] = sPath
if multishell then
local sTitle = fs.getName(sPath)
if sTitle:sub(-4) == ".lua" then
sTitle = sTitle:sub(1, -5)
end
multishell.setTitle(multishell.getCurrent(), sTitle)
end
local result = executeProgram(100, sPath, { [0] = command, ... })
tProgramStack[#tProgramStack] = nil
if multishell then
if #tProgramStack > 0 then
local sTitle = fs.getName(tProgramStack[#tProgramStack])
if sTitle:sub(-4) == ".lua" then
sTitle = sTitle:sub(1, -5)
end
multishell.setTitle(multishell.getCurrent(), sTitle)
else
multishell.setTitle(multishell.getCurrent(), "shell")
end
end
return result
else
printError("No such program")
return false
end
end
-- Install shell API
--- Run a program with the supplied arguments.
--
-- All arguments are concatenated together and then parsed as a command line. As
-- a result, `shell.run("program a b")` is the same as `shell.run("program",
-- "a", "b")`.
--
-- @tparam string ... The program to run and its arguments.
-- @treturn boolean Whether the program exited successfully.
-- @usage Run `paint my-image` from within your program:
--
-- shell.run("paint", "my-image")
-- @see shell.execute Run a program directly without parsing the arguments.
-- @changed 1.80pr1 Programs now get their own environment instead of sharing the same one.
-- @changed 1.83.0 `arg` is now added to the environment.
function shell.run(...)
local tWords = tokenise(...)
local sCommand = tWords[1]
if sCommand then
return shell.execute(sCommand, table.unpack(tWords, 2))
end
return false
end
--- Exit the current shell.
--
-- This does _not_ terminate your program, it simply makes the shell terminate
-- after your program has finished. If this is the toplevel shell, then the
-- computer will be shutdown.
function shell.exit()
bExit = true
end
--- Return the current working directory. This is what is displayed before the
-- `> ` of the shell prompt, and is used by @{shell.resolve} to handle relative
-- paths.
--
-- @treturn string The current working directory.
-- @see setDir To change the working directory.
function shell.dir()
return sDir
end
--- Set the current working directory.
--
-- @tparam string dir The new working directory.
-- @throws If the path does not exist or is not a directory.
-- @usage Set the working directory to "rom"
--
-- shell.setDir("rom")
function shell.setDir(dir)
expect(1, dir, "string")
if not fs.isDir(dir) then
error("Not a directory", 2)
end
sDir = fs.combine(dir, "")
end
--- Set the path where programs are located.
--
-- The path is composed of a list of directory names in a string, each separated
-- by a colon (`:`). On normal turtles will look in the current directory (`.`),
-- `/rom/programs` and `/rom/programs/turtle` folder, making the path
-- `.:/rom/programs:/rom/programs/turtle`.
--
-- @treturn string The current shell's path.
-- @see setPath To change the current path.
function shell.path()
return sPath
end
--- Set the @{path|current program path}.
--
-- Be careful to prefix directories with a `/`. Otherwise they will be searched
-- for from the @{shell.dir|current directory}, rather than the computer's root.
--
-- @tparam string path The new program path.
-- @since 1.2
function shell.setPath(path)
expect(1, path, "string")
sPath = path
end
--- Resolve a relative path to an absolute path.
--
-- The @{fs} and @{io} APIs work using absolute paths, and so we must convert
-- any paths relative to the @{dir|current directory} to absolute ones. This
-- does nothing when the path starts with `/`.
--
-- @tparam string path The path to resolve.
-- @usage Resolve `startup.lua` when in the `rom` folder.
--
-- shell.setDir("rom")
-- print(shell.resolve("startup.lua"))
-- -- => rom/startup.lua
function shell.resolve(path)
expect(1, path, "string")
local sStartChar = string.sub(path, 1, 1)
if sStartChar == "/" or sStartChar == "\\" then
return fs.combine("", path)
else
return fs.combine(sDir, path)
end
end
local function pathWithExtension(_sPath, _sExt)
local nLen = #sPath
local sEndChar = string.sub(_sPath, nLen, nLen)
-- Remove any trailing slashes so we can add an extension to the path safely
if sEndChar == "/" or sEndChar == "\\" then
_sPath = string.sub(_sPath, 1, nLen - 1)
end
return _sPath .. "." .. _sExt
end
--- Resolve a program, using the @{path|program path} and list of @{aliases|aliases}.
--
-- @tparam string command The name of the program
-- @treturn string|nil The absolute path to the program, or @{nil} if it could
-- not be found.
-- @since 1.2
-- @usage Locate the `hello` program.
--
-- shell.resolveProgram("hello")
-- -- => rom/programs/fun/hello.lua
function shell.resolveProgram(command)
expect(1, command, "string")
-- Substitute aliases firsts
if tAliases[command] ~= nil then
command = tAliases[command]
end
-- If the path is a global path, use it directly
if command:find("/") or command:find("\\") then
local sPath = shell.resolve(command)
if fs.exists(sPath) and not fs.isDir(sPath) then
return sPath
else
local sPathLua = pathWithExtension(sPath, "lua")
if fs.exists(sPathLua) and not fs.isDir(sPathLua) then
return sPathLua
end
end
return nil
end
-- Otherwise, look on the path variable
for sPath in string.gmatch(sPath, "[^:]+") do
sPath = fs.combine(shell.resolve(sPath), command)
if fs.exists(sPath) and not fs.isDir(sPath) then
return sPath
else
local sPathLua = pathWithExtension(sPath, "lua")
if fs.exists(sPathLua) and not fs.isDir(sPathLua) then
return sPathLua
end
end
end
-- Not found
return nil
end
--- Return a list of all programs on the @{shell.path|path}.
--
-- @tparam[opt] boolean include_hidden Include hidden files. Namely, any which
-- start with `.`.
-- @treturn { string } A list of available programs.
-- @usage textutils.tabulate(shell.programs())
-- @since 1.2
function shell.programs(include_hidden)
expect(1, include_hidden, "boolean", "nil")
local tItems = {}
-- Add programs from the path
for sPath in string.gmatch(sPath, "[^:]+") do
sPath = shell.resolve(sPath)
if fs.isDir(sPath) then
local tList = fs.list(sPath)
for n = 1, #tList do
local sFile = tList[n]
if not fs.isDir(fs.combine(sPath, sFile)) and
(include_hidden or string.sub(sFile, 1, 1) ~= ".") then
if #sFile > 4 and sFile:sub(-4) == ".lua" then
sFile = sFile:sub(1, -5)
end
tItems[sFile] = true
end
end
end
end
-- Sort and return
local tItemList = {}
for sItem in pairs(tItems) do
table.insert(tItemList, sItem)
end
table.sort(tItemList)
return tItemList
end
local function completeProgram(sLine)
local bIncludeHidden = settings.get("shell.autocomplete_hidden")
if #sLine > 0 and (sLine:find("/") or sLine:find("\\")) then
-- Add programs from the root
return fs.complete(sLine, sDir, {
include_files = true,
include_dirs = false,
include_hidden = bIncludeHidden,
})
else
local tResults = {}
local tSeen = {}
-- Add aliases
for sAlias in pairs(tAliases) do
if #sAlias > #sLine and string.sub(sAlias, 1, #sLine) == sLine then
local sResult = string.sub(sAlias, #sLine + 1)
if not tSeen[sResult] then
table.insert(tResults, sResult)
tSeen[sResult] = true
end
end
end
-- Add all subdirectories. We don't include files as they will be added in the block below
local tDirs = fs.complete(sLine, sDir, {
include_files = false,
include_dirs = false,
include_hidden = bIncludeHidden,
})
for i = 1, #tDirs do
local sResult = tDirs[i]
if not tSeen[sResult] then
table.insert (tResults, sResult)
tSeen [sResult] = true
end
end
-- Add programs from the path
local tPrograms = shell.programs()
for n = 1, #tPrograms do
local sProgram = tPrograms[n]
if #sProgram > #sLine and string.sub(sProgram, 1, #sLine) == sLine then
local sResult = string.sub(sProgram, #sLine + 1)
if not tSeen[sResult] then
table.insert(tResults, sResult)
tSeen[sResult] = true
end
end
end
-- Sort and return
table.sort(tResults)
return tResults
end
end
local function completeProgramArgument(sProgram, nArgument, sPart, tPreviousParts)
local tInfo = tCompletionInfo[sProgram]
if tInfo then
return tInfo.fnComplete(shell, nArgument, sPart, tPreviousParts)
end
return nil
end
--- Complete a shell command line.
--
-- This accepts an incomplete command, and completes the program name or
-- arguments. For instance, `l` will be completed to `ls`, and `ls ro` will be
-- completed to `ls rom/`.
--
-- Completion handlers for your program may be registered with
-- @{shell.setCompletionFunction}.
--
-- @tparam string sLine The input to complete.
-- @treturn { string }|nil The list of possible completions.
-- @see _G.read For more information about completion.
-- @see shell.completeProgram
-- @see shell.setCompletionFunction
-- @see shell.getCompletionInfo
-- @since 1.74
function shell.complete(sLine)
expect(1, sLine, "string")
if #sLine > 0 then
local tWords = tokenise(sLine)
local nIndex = #tWords
if string.sub(sLine, #sLine, #sLine) == " " then
nIndex = nIndex + 1
end
if nIndex == 1 then
local sBit = tWords[1] or ""
local sPath = shell.resolveProgram(sBit)
if tCompletionInfo[sPath] then
return { " " }
else
local tResults = completeProgram(sBit)
for n = 1, #tResults do
local sResult = tResults[n]
local sPath = shell.resolveProgram(sBit .. sResult)
if tCompletionInfo[sPath] then
tResults[n] = sResult .. " "
end
end
return tResults
end
elseif nIndex > 1 then
local sPath = shell.resolveProgram(tWords[1])
local sPart = tWords[nIndex] or ""
local tPreviousParts = tWords
tPreviousParts[nIndex] = nil
return completeProgramArgument(sPath , nIndex - 1, sPart, tPreviousParts)
end
end
return nil
end
--- Complete the name of a program.
--
-- @tparam string program The name of a program to complete.
-- @treturn { string } A list of possible completions.
-- @see cc.shell.completion.program
function shell.completeProgram(program)
expect(1, program, "string")
return completeProgram(program)
end
--- Set the completion function for a program. When the program is entered on
-- the command line, this program will be called to provide auto-complete
-- information.
--
-- The completion function accepts four arguments:
--
-- 1. The current shell. As completion functions are inherited, this is not
-- guaranteed to be the shell you registered this function in.
-- 2. The index of the argument currently being completed.
-- 3. The current argument. This may be the empty string.
-- 4. A list of the previous arguments.
--
-- For instance, when completing `pastebin put rom/st` our pastebin completion
-- function will receive the shell API, an index of 2, `rom/st` as the current
-- argument, and a "previous" table of `{ "put" }`. This function may then wish
-- to return a table containing `artup.lua`, indicating the entire command
-- should be completed to `pastebin put rom/startup.lua`.
--
-- You completion entries may also be followed by a space, if you wish to
-- indicate another argument is expected.
--
-- @tparam string program The path to the program. This should be an absolute path
-- _without_ the leading `/`.
-- @tparam function(shell: table, index: number, argument: string, previous: { string }):({ string }|nil) complete
-- The completion function.
-- @see cc.shell.completion Various utilities to help with writing completion functions.
-- @see shell.complete
-- @see _G.read For more information about completion.
-- @since 1.74
function shell.setCompletionFunction(program, complete)
expect(1, program, "string")
expect(2, complete, "function")
tCompletionInfo[program] = {
fnComplete = complete,
}
end
--- Get a table containing all completion functions.
--
-- This should only be needed when building custom shells. Use
-- @{setCompletionFunction} to add a completion function.
--
-- @treturn { [string] = { fnComplete = function } } A table mapping the
-- absolute path of programs, to their completion functions.
function shell.getCompletionInfo()
return tCompletionInfo
end
--- Returns the path to the currently running program.
--
-- @treturn string The absolute path to the running program.
-- @since 1.3
function shell.getRunningProgram()
if #tProgramStack > 0 then
return tProgramStack[#tProgramStack]
end
return nil
end
--- Add an alias for a program.
--
-- @tparam string command The name of the alias to add.
-- @tparam string program The name or path to the program.
-- @since 1.2
-- @usage Alias `vim` to the `edit` program
--
-- shell.setAlias("vim", "edit")
function shell.setAlias(command, program)
expect(1, command, "string")
expect(2, program, "string")
tAliases[command] = program
end
--- Remove an alias.
--
-- @tparam string command The alias name to remove.
function shell.clearAlias(command)
expect(1, command, "string")
tAliases[command] = nil
end
--- Get the current aliases for this shell.
--
-- Aliases are used to allow multiple commands to refer to a single program. For
-- instance, the `list` program is aliased to `dir` or `ls`. Running `ls`, `dir`
-- or `list` in the shell will all run the `list` program.
--
-- @treturn { [string] = string } A table, where the keys are the names of
-- aliases, and the values are the path to the program.
-- @see shell.setAlias
-- @see shell.resolveProgram This uses aliases when resolving a program name to
-- an absolute path.
function shell.aliases()
-- Copy aliases
local tCopy = {}
for sAlias, sCommand in pairs(tAliases) do
tCopy[sAlias] = sCommand
end
return tCopy
end
if multishell then
--- Open a new @{multishell} tab running a command.
--
-- This behaves similarly to @{shell.run}, but instead returns the process
-- index.
--
-- This function is only available if the @{multishell} API is.
--
-- @tparam string ... The command line to run.
-- @see shell.run
-- @see multishell.launch
-- @since 1.6
-- @usage Launch the Lua interpreter and switch to it.
--
-- local id = shell.openTab("lua")
-- shell.switchTab(id)
function shell.openTab(...)
local tWords = tokenise(...)
local sCommand = tWords[1]
if sCommand then
local sPath = shell.resolveProgram(sCommand)
if sPath == "rom/programs/shell.lua" then
return multishell.launch(createShellEnv("rom/programs"), sPath, table.unpack(tWords, 2))
elseif sPath ~= nil then
return multishell.launch(createShellEnv("rom/programs"), "rom/programs/shell.lua", sCommand, table.unpack(tWords, 2))
else
printError("No such program")
end
end
end
--- Switch to the @{multishell} tab with the given index.
--
-- @tparam number id The tab to switch to.
-- @see multishell.setFocus
-- @since 1.6
function shell.switchTab(id)
expect(1, id, "number")
multishell.setFocus(id)
end
end
local tArgs = { ... }
if #tArgs > 0 then
-- "shell x y z"
-- Run the program specified on the commandline
shell.run(...)
else
local function show_prompt()
term.setBackgroundColor(bgColour)
term.setTextColour(promptColour)
write(shell.dir() .. "> ")
term.setTextColour(textColour)
end
-- "shell"
-- Print the header
term.setBackgroundColor(bgColour)
term.setTextColour(promptColour)
print(os.version())
term.setTextColour(textColour)
-- Run the startup program
if parentShell == nil then
shell.run("/rom/startup.lua")
end
-- Read commands and execute them
local tCommandHistory = {}
while not bExit do
term.redirect(parentTerm)
if term.setGraphicsMode then term.setGraphicsMode(0) end
show_prompt()
local complete
if settings.get("shell.autocomplete") then complete = shell.complete end
local ok, result
local co = coroutine.create(read)
assert(coroutine.resume(co, nil, tCommandHistory, complete))
while coroutine.status(co) ~= "dead" do
local event = table.pack(os.pullEvent())
if event[1] == "file_transfer" then
-- Abandon the current prompt
local _, h = term.getSize()
local _, y = term.getCursorPos()
if y == h then
term.scroll(1)
term.setCursorPos(1, y)
else
term.setCursorPos(1, y + 1)
end
term.setCursorBlink(false)
-- Run the import script with the provided files
local ok, err = require("cc.internal.import")(event[2].getFiles())
if not ok and err then printError(err) end
-- And attempt to restore the prompt.
show_prompt()
term.setCursorBlink(true)
event = { "term_resize", n = 1 } -- Nasty hack to force read() to redraw.
end
if result == nil or event[1] == result or event[1] == "terminate" then
ok, result = coroutine.resume(co, table.unpack(event, 1, event.n))
if not ok then error(result, 0) end
end
end
if result:match("%S") and tCommandHistory[#tCommandHistory] ~= result then
table.insert(tCommandHistory, result)
end
shell.run(result)
end
end

View File

@@ -1,98 +0,0 @@
local args = {...}
local apis = args[2]
local term = args[4]
local getfile = args[5]
local computer = args[7]
local timeout = computer.time() + 5000
term.print("HBoot V1.0.0 //\n")
local w, h = term.getSize()
local kernel = load(getfile("/boot/Hyprkrnl.sys").readAllText())
local recovery = load(getfile("/boot/util/shell").readAllText())
-- Predeclare dbg so entries can reference it
local dbg = {}
local entries = {
{"HyperionOS", function() kernel(args, nil, "/sbin/init") end},
{"HyperionOS (Debug options)", dbg}
}
dbg[1] = {"Back", "BACK"}
dbg[2] = {"Boot HyperionOS in debug mode", function() kernel(args, true) end}
dbg[3] = {"Boot as shell", function() kernel(args, true, "/bin/bash") end}
dbg[4] = {"Boot in recovery", function() recovery(args) end}
local function render(tbl, selected)
term.clear()
term.print("HBoot V1.0.0 //\n\n")
for i, v in ipairs(tbl) do
if selected == i then
term.print("> " .. v[1] .. "\n")
else
term.print(" " .. v[1] .. "\n")
end
end
end
-- Initial render
render(entries, 1)
-- Wait for keypress or timeout
local exit = false
while not exit do
local ret = {computer.getMachineEvent()}
if ret[1] == "keyPressed" then
timeout = math.huge
break
end
if timeout <= computer.time() then
exit = true
break
end
end
-- Menu handling
if not exit then
local menuStack = {}
local currentMenu = entries
local selected = 1
render(currentMenu, selected)
while true do
local ret = {computer.getMachineEvent()}
if ret[1] == "keyTyped" then
if ret[3] == "\n" then
local entry = currentMenu[selected]
if entry then
if type(entry[2]) == "function" then
entry[2]()
elseif type(entry[2]) == "table" then
table.insert(menuStack, {currentMenu, selected})
currentMenu = entry[2]
selected = 1
render(currentMenu, selected)
elseif entry[2] == "BACK" then
if #menuStack > 0 then
local prev = table.remove(menuStack)
currentMenu, selected = prev[1], prev[2]
render(currentMenu, selected)
end
end
end
elseif ret[3] == "\x1b[A" then -- Up arrow
if selected > 1 then
selected = selected - 1
render(currentMenu, selected)
end
elseif ret[3] == "\x1b[B" then -- Down arrow
if selected < #currentMenu then
selected = selected + 1
render(currentMenu, selected)
end
end
end
end
else
kernel(args)
end

View File

@@ -1,230 +0,0 @@
local args={...}
local bootLoader=args[1]
local MODE=bootLoader[1]
local apis=bootLoader[2]
local bootDisk=bootLoader[3]
local term=bootLoader[4]
local getFile=bootLoader[5]
local bootData
do
local tmp=load("return "..(getFile("/var/log/kernel/bootData").readAllText() or "{}"))
if not tmp then error("Bootdata failed to load") end
bootData=tmp()
end
local list=bootLoader[6]
local computer=bootLoader[7]
local startup=true
local osleep=sleep
_G._SYSDEBUG=args[2]
bootData.debug=args[2]
local drivers={}
local eventCache={}
while true do
local event={computer.getMachineEvent()}
if event[1]==nil then break end
eventCache[#eventCache+1] = event
end
term.clear()
term.print("Welcome to Hyperion OS")
term.print("Creating logger")
osleep(1)
local log=load(getFile("/sys/util/logger.lua").readAllText())(computer)
term.clear()
local logHook=log.setHook(term.print)
log.api.log("Created logger")
local function saveLog()
local logNum=bootData.logNum
getFile("/var/log/kernel/"..tostring(logNum)..".log").writeAllText(log.api.get())
getFile("/var/log/kernel/latest.log").writeAllText(log.api.get())
if bootData.logNum==10 then
bootData.logNum=0
else
bootData.logNum=bootData.logNum+1
end
end
if bootData.debug then _G.saveLog=saveLog end
local function t2t(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..t2t(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()"
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
-- Make PANIC
local function PANIC(err)
term.clear()
term.print(log.api.get())
saveLog()
if err==bootData.prevError then
bootData.errorCount=bootData.errorCount+1
else
bootData.prevError=err
bootData.errorCount=0
end
getFile("/var/log/kernel/bootData").writeAllText(t2t(bootData))
term.print("KERNEL PANIC: "..err)
term.print("Log saved to /var/log/kernel/"..tostring(bootData.logNum)..".log\n")
term.print("Press enter to continue...")
while true do
local event = {computer.getMachineEvent()}
if event[1]~=nil then
term.print(table.concat(event, " "))
end
if event[1] == "keyTyped" then
if event[3] == "\n" then
break
end
end
end
computer.reboot()
end
local function runAsKernel(path, ...)
local func, err = load(getFile(path).readAllText(), path, "t", _G)
if not func then return false, "\t"..err end
local ret = {xpcall(func, debug.traceback, ...)}
if not ret[1] then
return false, ret[2]
end
return true, table.unpack(ret, 2)
end
log.api.log("Loading globals...")
for i,v in ipairs(list("/sys/api/")) do
if bootData.debug then log.api.debug("Loading "..v) end
local ok, err = runAsKernel("/sys/api/"..v, getFile, log)
if not ok then log.api.warn(err) end
end
local driverutil={}
function driverutil.getFirst(type)
if drivers[type] then
if drivers[type][1] then
return drivers[type][1]
end
end
end
function driverutil.list(type)
if not type then
local tmp={}
for i,v in ipairs(drivers.raw) do
tmp[#tmp+1] = {type=v.type, obj=v}
end
local i=0
return function()
i=i+1
if tmp[i]==nil then return end
return tmp[i].type, tmp[i].obj
end
else
local tmp={}
for i,v in ipairs(drivers[type]) do
tmp[#tmp+1] = {type=v.type, obj=v}
end
local i=0
return function()
i=i+1
if tmp[i]==nil then return end
return tmp[i].type, tmp[i].obj
end
end
end
log.api.log("Loading drivers...")
for i,v in ipairs(list("/sys/modules/")) do
if bootData.debug then log.api.debug("Loading module "..v) end
local ok, err = runAsKernel("/sys/modules/"..v, apis, drivers, log, driverutil)
if not ok then log.api.warn("["..v.."] exited with ERR:\n"..err) end
end
log.api.log("Unloading non \""..MODE.."\" specific drivers...")
do
local tmp={}
for i,v in ipairs(drivers) do
if type(v.arch)=="table" then
for i2,v2 in ipairs(v.arch) do
if v2==MODE or v2=="ANY" then
tmp[#tmp+1] = v
end
end
else
if v.arch==MODE or v.arch=="ANY" then
tmp[#tmp+1] = v
end
end
end
drivers={}
drivers.raw=tmp
end
if bootData.debug then log.api.debug("Sorting drivers...") end
for i,v in ipairs(drivers.raw) do
if not drivers[v.type] then drivers[v.type]={} end
drivers[v.type][#drivers[v.type]+1] = v
end
if bootData.debug then log.api.debug("Initializing drivers...") end
for i,v in ipairs(drivers.raw) do
if v.init then
local ok, err = xpcall(v.init, debug.traceback)
if not ok then
log.api.warn("["..v.name.."]: Init function ERR:\n"..err)
if bootData.debug then log.api.debug("Removing driver ["..v.name.."]") end
table.remove(drivers.raw, i)
end
end
end
log.api.log("Loaded "..tostring(#drivers.raw).." drivers")
log.api.log("Loading filesystem...")
local ok, fs = runAsKernel("/sys/fs/init", drivers, log, bootDisk, driverutil)
if not ok then PANIC(fs) end
if not fs then PANIC("filesystem failed to load") end
fs.delete("/tmp")
fs.mkDir("/tmp")
log.api.log("Loading system...")
local ok, err = runAsKernel("/sys/Hyperion.sys", drivers, log)
if not ok then PANIC(err) end
local hyperion = err
if type(hyperion)~="function" then PANIC("Hyperion failed to load:\nHyperion was: "..tostring(hyperion)) end
hyperion(fs, log, drivers, PANIC, driverutil)
PANIC("OS EXITED MAIN()")

View File

@@ -1,135 +0,0 @@
local biosData = ({...})[1]
local apis = {}
local lua = {
coroutine = true,
debug = true,
_HOST = true,
_VERSION = true,
assert = true,
collectgarbage = true,
error = true,
gcinfo = true,
getfenv = true,
getmetatable = true,
ipairs = true,
__inext = true,
load = true,
math = true,
next = true,
pairs = true,
pcall = true,
rawequal = true,
rawget = true,
rawlen = true,
rawset = true,
select = true,
setfenv = true,
setmetatable = true,
string = true,
table = true,
tonumber = true,
tostring = true,
type = true,
xpcall = true,
_G = true
}
local print=component.getFirst("screen").print
local comp=component
-- Sandbox globals
local _REAL_G = _G
local _PAIRS = pairs
if type(_REAL_G) ~= "table" then
error("Global environment (_G) is not a table")
end
for i, v in _PAIRS(_REAL_G) do
if not lua[i] then
apis[i] = v
_REAL_G[i] = nil
end
end
apis.component=comp
-- File abstraction compatible with open() -> {read,write,append}
local function getFile(path)
return {
readAllText = function()
local handle = biosData.bootDrive:open(path)
if not handle or type(handle.read) ~= "function" then
error("Cannot open file for reading: " .. tostring(path))
end
return handle.read() or ""
end,
writeAllText = function(text)
if not biosData.bootDrive:fileExists(path) then
biosData.bootDrive:createFile(path)
end
local handle = biosData.bootDrive:open(path)
if not handle or type(handle.write) ~= "function" then
error("Cannot open file for writing: " .. tostring(path))
end
handle.write(text)
end,
appendText = function(text)
local handle = biosData.bootDrive:open(path)
if not handle or type(handle.append) ~= "function" then
error("Cannot open file for appending: " .. tostring(path))
end
handle.append(text)
end
}
end
local function list(path)
return biosData.bootDrive:list(path)
end
function coroutine.resumeWithTimeout(CORO, LINES, ...)
local ret = { coroutine.resume(CORO, ...) }
if math.random(0, 1) == 0 then
return false, table.unpack(ret)
else
return true, table.unpack(ret)
end
end
-- Safety: verify APIs exist
if not apis.component then
error("Component API missing in environment")
end
if not biosData.bootDrive then
error("bootDrive missing from biosData")
end
local computer = apis.component.getFirst("computer")
-- Read kernel file correctly
local kernelSource = getFile("/boot/Hyprkrnl.sys").readAllText()
if not kernelSource or kernelSource == "" then
error("Kernel file empty or unreadable")
end
local kernel, err = load(kernelSource, "@kernel", "t", _G)
if not kernel then
error("Failed to load kernel: " .. tostring(err))
end
-- Run kernel safely
local ok, perr = xpcall(function()
kernel(
"ac",
apis,
biosData.bootDrive.id,
apis.component.getFirst("screen"),
getFile,
list,
apis.component.getFirst("computer")
)
end, debug.traceback)
if not ok then
error("Kernel execution failed: " .. tostring(perr))
end

View File

@@ -1,119 +0,0 @@
-- 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("/disk/boot/cc/preboot.cc", "r")
if file == nil then
term.setCursorBlink(false)
term.setTextColor(16384)
term.write("Could not find /boot/cc/bootloader.cc. 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(), "@preboot.cc")
file.close()
if fn == nil then
term.setCursorBlink(false)
term.setTextColor(16384)
term.write("Could not load /boot/cc/bootloader.cc. 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

@@ -1,240 +0,0 @@
local apis={}
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
function sleep(time)
coroutine.yield("CC_TIMER", time)
end
local function catErr(text)
apis.term.setCursorPos(1,1)
apis.term.write(text)
while true do
coroutine.yield()
end
end
local function getFile(path)
if path:sub(1,1) ~= "/" then
path="/"..path
end
path="/disk"..path
if not apis.fs.exists(path) then error("File does not exist") end
if apis.fs.isDir(path) then error("Cannot open a directory") end
return {
readAllText=function()
local file = apis.fs.open(path, "r")
local text = file.readAll()
file.close()
return text
end,
writeAllText=function(text)
local file = apis.fs.open(path, "w")
file.write(text)
file.close()
end
}
end
-- Prints text handling \n, \t, and \b with scrolling (no wrapping)
local function write(text)
local x, y = apis.term.getCursorPos()
local w, h = apis.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)
apis.term.write(string.rep(" ", spaces))
x = x + spaces
elseif c == "\b" then
if x > 1 then
x = x - 1
apis.term.setCursorPos(x, y)
apis.term.write(" ")
apis.term.setCursorPos(x, y)
end
else
if x <= w and y <= h then
apis.term.setCursorPos(x, y)
apis.term.write(c)
x = x + 1
end
end
-- Handle scrolling if we go past bottom
if y > h then
apis.term.scroll(1)
y = h
apis.term.setCursorPos(x, y)
end
end
apis.term.setCursorPos(x, y)
end
local event_queue = {}
local function addEventRaw(...)
event_queue[#event_queue+1] = {...}
end
local function getEvent()
local event = event_queue[1]
event_queue = {table.unpack(event_queue, 2)}
return table.unpack(event or {})
end
local lkeys={}
lkeys[apis.keys.enter]="\n"
lkeys[apis.keys.backspace]="\b"
lkeys[apis.keys.tab]="\t"
lkeys[apis.keys.up]="\x1b[A"
lkeys[apis.keys.down]="\x1b[B"
lkeys[apis.keys.right]="\x1b[C"
lkeys[apis.keys.left]="\x1b[D"
local computer={}
computer.beep=function() end
computer.shutdown=apis.os.shutdown
computer.reboot=apis.os.reboot
computer.time=function()
return apis.os.epoch("utc")
end
computer.getMachineEvent=getEvent
computer.date=apis.os.date
local function list(path)
if path:sub(1,1) ~= "/" then
path="/"..path
end
path="/disk"..path
if not apis.fs.isDir(path) then return {} end
return apis.fs.list(path)
end
function coroutine.resumeWithTimeout(CORO, LINES, ...)
local yeildKey = {}
debug.sethook(CORO, function()
coroutine.yield(yeildKey)
end, "l", LINES)
local ret = {coroutine.resume(CORO, ...)}
debug.sethook(CORO)
if ret[2]==yeildKey then return false else return true, table.unpack(ret, 2) end
end
local kernel = load(getFile("/boot/HBoot.sys").readAllText(), "@kernel", "t", _G)
if not kernel then
catErr("BOOT COMPILE ERR")
end
local kernel_coro = coroutine.create(function()
local ok,err = pcall(function()
local ok, err=xpcall(kernel, debug.traceback, "cc", apis, "disk", {
print=function(text)
write(text.."\n")
end,
printInline=function(text)
write(text)
end,
clear=function()
apis.term.clear()
apis.term.setCursorPos(1,1)
end,
getSize=function ()
return apis.term.getSize()
end
}, getFile, list, computer)
if not ok then
write(err)
while true do
coroutine.yield()
end
end
end)
if not ok then
catErr(err)
end
end)
apis.term.setCursorBlink(false)
while true do
local ret = {coroutine.resumeWithTimeout(kernel_coro, 200)}
if coroutine.status(kernel_coro) == "dead" then
catErr("KERNEL EXITED")
end
if ret[1] then
if ret[2]=="CC_TIMER" and ret[3]~=nil and type(ret[3])=="number" then
local timer = apis.os.startTimer(ret[3])
repeat
local _, param = coroutine.yield("timer")
until param == timer
end
end
apis.os.queueEvent("nosleep")
local exit = false
repeat
local event = {coroutine.yield()}
if event[1] == "nosleep" then
exit=true
elseif event[1]==nil then
elseif event[1]=="key" then
addEventRaw("keyPressed", 1, event[2])
if lkeys[event[2]] then
addEventRaw("keyTyped", 1, lkeys[event[2]])
end
elseif event[1]=="char" then
addEventRaw("keyTyped", 1, event[2])
elseif event[1]=="key_up" then
addEventRaw("keyReleased", 1, event[2])
elseif event[1]=="disk" then
addEventRaw("componentAdded", "disk")
elseif event[1]=="disk_eject" then
addEventRaw("componentRemoved", "disk")
end
until exit
end
apis.os.reboot()

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +0,0 @@
local lib = {}
function lib.create()
local array = {}
return setmetatable(array,{
__add=function(t1, t2)
end
})
end

View File

View File

@@ -1,27 +0,0 @@
local args={...}
local fs=args[1]
local log=args[2]
local drivers=args[3]
local PANIC=args[4]
local driverutil=args[5]
local sys={}
local task={}
sys._VERSION = "HyperionOS V1.0.4"
local function run(file, args)
local func, err=fs.loadAsFunc(file)
if not file then return 8, err end
local ret={xpcall(func, debug.traceback, table.unpack(args))}
if not ret[1] then return 1, ret[2] end
return 0, table.unpack(ret, 2)
end
local exitcode, req=run("/sys/system/require", {sys})
if exitcode~=0 then PANIC(req) end
_G.require=req
local exitcode, hypervisor=run("/sys/system/hypervisor/init", {sys})
if exitcode~=0 then PANIC(hypervisor) end
_G.require=hypervisor

View File

@@ -1,57 +0,0 @@
-- Copyright (C) 2025 ASTRONAND
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

View File

@@ -1,81 +0,0 @@
-- Copyright (C) 2025 ASTRONAND
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

@@ -1,124 +0,0 @@
local args={...}
local drivers=args[1]
local log=args[2]
local bootDisk=args[3]
local driverutil=args[4]
local wd="/"
log.api.log("Bootdrive is "..bootDisk)
if not drivers.disk then
error("WTF") -- ???
end
local disks={}
local mounts={
["/"]=bootDisk
}
local meta={}
local function refreshDisks()
local diskstmp={}
local tmp={}
for i,v in driverutil.list("disk") do
tmp[#tmp+1] = v
end
for _,d in ipairs(tmp) do
for i,v in d.api.list() do
if diskstmp[i]==nil then
diskstmp[i]=v
end
end
end
disks=diskstmp
end
refreshDisks()
--[[
meta=load("return "..(disks[bootDisk].readAllText("/sys/fs/meta.ltn") or "{}"), "meta")()
if not meta then error("Meta failed to load") end
]]
local function resolve(path)
if path:sub(1,1)~="/" then path=wd..path end
local currmatch="/"
for i,_ in pairs(mounts) do
if string.hasPrefix(path, i) then
if #i>#currmatch then
currmatch=i
end
end
end
local drive=disks[mounts[currmatch]]
local newPath=string.getSuffix(path, currmatch)
return drive, newPath
end
local fs={}
function fs.list(path)
local drive, newPath = resolve(path)
return drive.list(newPath)
end
function fs.readAllText(path)
local drive, newPath = resolve(path)
return drive.readAllText(newPath)
end
function fs.writeAllText(path, content)
local drive, newPath = resolve(path)
return drive.writeAllText(newPath, content)
end
function fs.delete(path)
local drive, newPath = resolve(path)
return drive.delete(newPath)
end
function fs.exists(path)
local drive, newPath = resolve(path)
return (drive.fileExists(newPath) or drive.directoryExists(newPath))
end
function fs.fileExists(path)
local drive, newPath = resolve(path)
return drive.fileExists(newPath)
end
function fs.directoryExists(path)
local drive, newPath = resolve(path)
return drive.directoryExists(newPath)
end
function fs.createFile(path)
local drive, newPath = resolve(path)
return drive.makeFile(newPath)
end
function fs.createDirectory(path)
local drive, newPath = resolve(path)
return drive.makeDirectory(newPath)
end
fs.mkDir=fs.createDirectory
fs.mkFile=fs.createFile
fs.isDir=fs.directoryExists
fs.isFile=fs.fileExists
function fs.getWorkingDir()
return wd
end
function fs.setWorkingDir(dir)
if type(dir)~="string" then error("Invailid path") end
if dir:sub(1,1)~="/" then dir=wd..dir end
if dir:sub(#dir,#dir)~="/" then dir=dir.."/" end
if not fs.isDir(dir) then error("Invailid path") end
end
function fs.loadAsFunc(path)
local file = fs.readAllText(path)
return load(file, path, "t", setmetatable({},{
__index=_G,
__metatable=false
}))
end
return fs

View File

@@ -1,69 +0,0 @@
{["/sys/util/logger.lua"]={["p"]=21,["o"]=0,["g"]=0}
,["/bin/hex.lua"]={["p"]=21,["o"]=0,["g"]=0}
,["/opt"]={["p"]=21,["o"]=0,["g"]=0}
,["/var/log/kernel"]={["p"]=21,["o"]=0,["g"]=0}
,["/sys/modules/cc.component.kd"]={["p"]=21,["o"]=0,["g"]=0}
,["/opt/astronand/ZDelta/init"]={["p"]=21,["o"]=0,["g"]=0}
,["/sys/api"]={["p"]=21,["o"]=0,["g"]=0}
,["/var/log/kernel/10.log"]={["p"]=21,["o"]=0,["g"]=0}
,["/var/log/kernel/7.log"]={["p"]=21,["o"]=0,["g"]=0}
,["/var/log/kernel/1.log"]={["p"]=21,["o"]=0,["g"]=0}
,["/bin/BASIC"]={["p"]=21,["o"]=0,["g"]=0}
,["/boot/cc/preboot.cc"]={["p"]=21,["o"]=0,["g"]=0}
,["/boot/ac"]={["p"]=21,["o"]=0,["g"]=0}
,["/sys"]={["p"]=21,["o"]=0,["g"]=0}
,["/sys/fs/init"]={["p"]=21,["o"]=0,["g"]=0}
,["/lib"]={["p"]=21,["o"]=0,["g"]=0}
,["/sys/api/table.lua"]={["p"]=21,["o"]=0,["g"]=0}
,["/var/log/kernel/5.log"]={["p"]=21,["o"]=0,["g"]=0}
,["/usr/share/doc"]={["p"]=21,["o"]=0,["g"]=0}
,["/var/log/kernel/3.log"]={["p"]=21,["o"]=0,["g"]=0}
,["/opt/astronand/ZDelta"]={["p"]=21,["o"]=0,["g"]=0}
,["/sys/hypervisor/init.sys"]={["p"]=21,["o"]=0,["g"]=0}
,["/usr/share"]={["p"]=21,["o"]=0,["g"]=0}
,["/sys/modules"]={["p"]=21,["o"]=0,["g"]=0}
,["/var/log/kernel/6.log"]={["p"]=21,["o"]=0,["g"]=0}
,["/sys/hypervisor"]={["p"]=21,["o"]=0,["g"]=0}
,["/var/log/kernel/4.log"]={["p"]=21,["o"]=0,["g"]=0}
,["/lib/array/math"]={["p"]=21,["o"]=0,["g"]=0}
,["/var"]={["p"]=21,["o"]=0,["g"]=0}
,["/sys/util/conhost.lua"]={["p"]=21,["o"]=0,["g"]=0}
,["/boot/Hyprkrnl.sys"]={["p"]=21,["o"]=0,["g"]=0}
,["/bin"]={["p"]=21,["o"]=0,["g"]=0}
,["/sys/modules/ac.disks.kd"]={["p"]=21,["o"]=0,["g"]=0}
,["/lib/array/x"]={["p"]=21,["o"]=0,["g"]=0}
,["/sys/modules/cc.disks.kd"]={["p"]=21,["o"]=0,["g"]=0}
,["/opt/astronand/dbg"]={["p"]=21,["o"]=0,["g"]=0}
,["/usr"]={["p"]=21,["o"]=0,["g"]=0}
,["/usr/share/doc/kernel/drivers"]={["p"]=21,["o"]=0,["g"]=0}
,["/sys/util"]={["p"]=21,["o"]=0,["g"]=0}
,["/var/log/kernel/8.log"]={["p"]=21,["o"]=0,["g"]=0}
,["/var/log/kernel/9.log"]={["p"]=21,["o"]=0,["g"]=0}
,["/var/log/kernel/latest.log"]={["p"]=21,["o"]=0,["g"]=0}
,["/lib/array"]={["p"]=21,["o"]=0,["g"]=0}
,["/boot/cc/boot.cc"]={["p"]=21,["o"]=0,["g"]=0}
,["/home"]={["p"]=21,["o"]=0,["g"]=0}
,["/usr/share/doc/kernel/drivers/disk.md"]={["p"]=21,["o"]=0,["g"]=0}
,["/lib/LibDeflate"]={["p"]=21,["o"]=0,["g"]=0}
,["/sys/fs/meta.ltn"]={["p"]=21,["o"]=0,["g"]=0}
,["/var/log/kernel/0.log"]={["p"]=21,["o"]=0,["g"]=0}
,["/var/log/kernel/bootData"]={["p"]=21,["o"]=0,["g"]=0}
,["/sys/api/string.lua"]={["p"]=21,["o"]=0,["g"]=0}
,["/var/log"]={["p"]=21,["o"]=0,["g"]=0}
,["/bin/shell.hex"]={["p"]=21,["o"]=0,["g"]=0}
,["/opt/astronand/dbg/init"]={["p"]=21,["o"]=0,["g"]=0}
,["/boot/bootloader.sys"]={["p"]=21,["o"]=0,["g"]=0}
,["/lib/array/2d"]={["p"]=21,["o"]=0,["g"]=0}
,["/boot/cc"]={["p"]=21,["o"]=0,["g"]=0}
,["/boot/ac/boot.ac"]={["p"]=21,["o"]=0,["g"]=0}
,["/var/log/kernel/2.log"]={["p"]=21,["o"]=0,["g"]=0}
,["/sys/modules/ccpc.disk.kd"]={["p"]=21,["o"]=0,["g"]=0}
,["/sys/api/require.lua"]={["p"]=21,["o"]=0,["g"]=0}
,["/bin/lua.lua"]={["p"]=21,["o"]=0,["g"]=0}
,["/usr/share/doc/kernel"]={["p"]=21,["o"]=0,["g"]=0}
,["/boot"]={["p"]=21,["o"]=0,["g"]=0}
,["/sys/fs"]={["p"]=21,["o"]=0,["g"]=0}
,["/var/system"]={["p"]=21,["o"]=0,["g"]=0}
,["/sys/modules/cc.terminal.kd"]={["p"]=21,["o"]=0,["g"]=0}
,["/opt/astronand"]={["p"]=21,["o"]=0,["g"]=0}
}

View File

@@ -1,75 +0,0 @@
local kernelArgs={...}
local apis=kernelArgs[1]
local drivers=kernelArgs[2]
local log=kernelArgs[3]
local driver={}
local disks = {}
driver.type = "disk"
driver.name = "AC:Disk"
driver.version = "1.0.0"
driver.apiVersion = 1
driver.description = "Driver for AC disks"
driver.arch = "ac"
driver.api = {}
local function refreshDisks()
local tmp={}
for i,v in apis.component.list() do
if i=="disk" then
tmp[v.id]={
readAllText=function(path)
return v:open(path).read()
end,
writeAllText=function(path, content)
return v:open(path).write(content)
end,
list=function(path)
return v:list(path)
end,
delete=function(path)
return v:delete(path)
end,
makeDirectory=function(path)
return v:makeDirectory(path)
end,
makeFile=function(path)
return v:makeFile(path)
end,
directoryExists=function(path)
return v:directoryExists(path)
end,
fileExists=function(path)
return v:fileExists(path)
end
}
end
end
disks=tmp
end
function driver.init()
refreshDisks()
end
function driver.api.list()
local tmp={}
for i,v in pairs(disks) do
tmp[#tmp+1]={id=i, obj=v}
end
local i=0
return function()
i=i+1
if tmp[i]==nil then return end
return tmp.id, tmp.obj
end
end
function driver.main()
while true do
refreshDisks()
sleep(5)
end
end
drivers[#drivers+1]=driver

View File

@@ -1,100 +0,0 @@
local kernelArgs={...}
local apis=kernelArgs[1]
local drivers=kernelArgs[2]
local log=kernelArgs[3]
local driver={}
local disks={}
local driverutil=kernelArgs[4]
driver.type = "disk"
driver.name = "CC:Disks"
driver.version = "1.0.0"
driver.apiVersion = 1
driver.description = "Driver for CC:Tweaked disks"
driver.arch = "cc"
driver.api = {}
local function abs(path)
if path:sub(1,1)~="/" then path="/"..path end
return path
end
local function newDisk(root)
root="/"..root
return {
readAllText=function(path)
local file=apis.fs.open(root..abs(path),"r")
local text=file.readAll()
file.close()
return text
end,
writeAllText=function(path, content)
local file=apis.fs.open(root..abs(path),"w")
file.write(content)
file.close()
end,
list=function(path)
return apis.fs.list(root..abs(path))
end,
delete=function(path)
return apis.fs.delete(root..abs(path))
end,
makeDirectory=function(path)
return apis.fs.makeDir(root..abs(path))
end,
makeFile=function(path)
local file=apis.fs.open(root..abs(path),"w")
file.close()
end,
directoryExists=function(path)
return apis.fs.exists(root..abs(path)) and apis.fs.isDir(root..abs(path))
end,
fileExists=function(path)
return apis.fs.exists(root..abs(path)) and not apis.fs.isDir(root..abs(path))
end
}
end
local function refreshDisks(peripheral)
local tmp2={}
tmp2["disk"]=newDisk("disk")
for i,v in ipairs(peripheral.api.getNames()) do
if peripheral.api.isType(v, "drive") then
local p=peripheral.api.wrap(v)
if p.isDiskPresent() then
if p.getMountPath()~="disk" then
tmp2["disk_"..p.getID()] = newDisk(p.getMountPath())
end
end
end
end
disks=tmp2
return true
end
function driver.init()
local peripheral=driverutil.getFirst("component")
refreshDisks(peripheral)
end
function driver.api.list()
local tmp={}
for i,v in pairs(disks) do
tmp[#tmp+1]={id=i, obj=v}
end
local i=0
return function()
i=i+1
if tmp[i]==nil then return end
return tmp[i].id, tmp[i].obj
end
end
function driver.main()
while true do
refreshDisks()
sleep(5)
end
end
drivers[#drivers+1] = driver

View File

@@ -1,129 +0,0 @@
local kernelArgs={...}
local apis=kernelArgs[1]
local drivers=kernelArgs[2]
local log=kernelArgs[3]
local driver={}
driver.type = "component"
driver.name = "CC:Periph"
driver.version = "1.0.0"
driver.apiVersion = 1
driver.description = "Driver for CC:Tweaked peripherals"
driver.arch = "cc"
driver.api = {}
local native,sides
if apis.peripheral then
native = apis.peripheral
sides = apis.rs.getSides()
end
function driver.api.getNames()
local results = {}
for n = 1, #sides do
local side = sides[n]
if native.isPresent(side) then
table.insert(results, side)
if native.hasType(side, "peripheral_hub") then
local remote = native.call(side, "getNamesRemote")
for _, name in ipairs(remote) do
table.insert(results, name)
end
end
end
end
return results
end
function driver.api.getType(peripheral)
if type(peripheral) == "string" then -- Peripheral name passed
if native.isPresent(peripheral) then
return native.getType(peripheral)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then
return native.call(side, "getTypeRemote", peripheral)
end
end
return nil
else
local mt = getmetatable(peripheral)
if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then
error("bad argument #1 (table is not a peripheral)", 2)
end
return table.unpack(mt.types)
end
end
function driver.api.isType(peripheral, peripheral_type)
if type(peripheral) == "string" then -- Peripheral name passed
if native.isPresent(peripheral) then
return native.hasType(peripheral, peripheral_type)
end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then
return native.call(side, "hasTypeRemote", peripheral, peripheral_type)
end
end
return nil
else
local mt = getmetatable(peripheral)
if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then
error("bad argument #1 (table is not a peripheral)", 2)
end
return mt.types[peripheral_type] ~= nil
end
end
function driver.api.getMethods(name)
if native.isPresent(name) then
return native.getMethods(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, "getMethodsRemote", name)
end
end
return nil
end
function driver.api.call(name, method, ...)
if native.isPresent(name) then
return native.call(name, method, ...)
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, "callRemote", name, method, ...)
end
end
return nil
end
function driver.api.wrap(name)
local methods = driver.api.getMethods(name)
if not methods then
return nil
end
local types = { driver.api.getType(name) }
for i = 1, #types do types[types[i]] = true end
local result = setmetatable({}, {
__name = "peripheral",
name = name,
type = types[1],
types = types,
})
for _, method in ipairs(methods) do
result[method] = function(...)
return driver.api.call(name, method, ...)
end
end
return result
end
drivers[#drivers+1] = driver

View File

@@ -1,74 +0,0 @@
local kernelArgs={...}
local apis=kernelArgs[1]
local drivers=kernelArgs[2]
local log=kernelArgs[3]
local driver={}
driver.type = "terminal"
driver.name = "CC:Term"
driver.version = "1.0.0"
driver.apiVersion = 1
driver.description = "Driver for CC:Tweaked screens"
driver.arch = "cc"
driver.api = {}
-- Prints text handling \n, \t, and \b with scrolling (no wrapping)
local function write(text)
local x, y = apis.term.getCursorPos()
local w, h = apis.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)
apis.term.write(string.rep(" ", spaces))
x = x + spaces
elseif c == "\b" then
if x > 1 then
x = x - 1
apis.term.setCursorPos(x, y)
apis.term.write(" ")
apis.term.setCursorPos(x, y)
end
else
if x <= w and y <= h then
apis.term.setCursorPos(x, y)
apis.term.write(c)
x = x + 1
end
end
-- Handle scrolling if we go past bottom
if y > h then
apis.term.scroll(1)
y = h
apis.term.setCursorPos(x, y)
end
end
apis.term.setCursorPos(x, y)
end
function driver.api.print(text)
write(text.."\n")
end
function driver.api.printInline(text)
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
drivers[#drivers+1] = driver

View File

@@ -1,3 +0,0 @@
-- <!ARCH>
-- @ICON$101003000000000000092492492490080000000010082000000010080400000010080080000010080400000010082002492010080000000010092492492490000000000000092492492490080000000010080000000010092492492490000000000000

View File

@@ -1,70 +0,0 @@
local args={...}
local computer=args[1]
local logs={["nil"]=""}
local hooks={["nil"]=function()end}
local log={api={}}
local function convert_epoch(epoch)
return computer.date("[%b %d %H:%M:%S]", epoch/1000)
end
function log.getProcess(func)
if type(func)=="function" then
log.getProcess=func
else
return "Hyprkrnl"
end
end
function log.api.log(text, logID)
local appendedText=convert_epoch(computer.time()).." "..log.getProcess()..":[IN] "..text
logs[tostring(logID)]=logs[tostring(logID)]..appendedText.."\n"
hooks[tostring(logID)](appendedText)
end
function log.api.warn(text, logID)
local appendedText=convert_epoch(computer.time()).." "..log.getProcess()..":[WN] "..text
logs[tostring(logID)]=logs[tostring(logID)]..appendedText.."\n"
hooks[tostring(logID)](appendedText)
end
function log.api.fail(text, logID)
local appendedText=convert_epoch(computer.time()).." "..log.getProcess()..":[FA] "..text
logs[tostring(logID)]=logs[tostring(logID)]..appendedText.."\n"
hooks[tostring(logID)](appendedText)
end
function log.api.debug(text, logID)
local appendedText=convert_epoch(computer.time()).." "..log.getProcess()..":[DE] "..text
logs[tostring(logID)]=logs[tostring(logID)]..appendedText.."\n"
hooks[tostring(logID)](appendedText)
end
function log.api.error(text, logID)
local appendedText=convert_epoch(computer.time()).." "..log.getProcess()..":[ER] "..text
logs[tostring(logID)]=logs[tostring(logID)]..appendedText.."\n"
hooks[tostring(logID)](appendedText)
end
function log.api.get(logID)
return logs[tostring(logID)]
end
function log.setHook(func, logID)
hooks[tostring(logID)]=func
return {
removeHook=function()
hooks[tostring(logID)]=function()end
end
}
end
local UUID = 0
function log.api.createLog(logID)
if logs[tostring(logID)]~=nil then error("cannot create duplicate log") end
if logID==nil then UUID=UUID+1; logID=UUID end
hooks[tostring(logID)]=function()end
logs[tostring(logID)]=""
end
return log

View File

@@ -1,6 +0,0 @@
### API:
---
```
getDisks():id, obj
```

View File

@@ -1,17 +0,0 @@
[Oct 31 18:33:08] Hyprkrnl:[IN] Created logger
[Oct 31 18:33:08] Hyprkrnl:[IN] Loading globals...
[Oct 31 18:33:08] Hyprkrnl:[DE] Loading string.lua
[Oct 31 18:33:08] Hyprkrnl:[DE] Loading table.lua
[Oct 31 18:33:08] Hyprkrnl:[IN] Loading drivers...
[Oct 31 18:33:08] Hyprkrnl:[DE] Loading module ac.disks.kd
[Oct 31 18:33:08] Hyprkrnl:[DE] Loading module cc.disks.kd
[Oct 31 18:33:08] Hyprkrnl:[DE] Loading module cc.periph.kd
[Oct 31 18:33:08] Hyprkrnl:[DE] Loading module cc.terminal.kd
[Oct 31 18:33:08] Hyprkrnl:[DE] Loading module ccpc.disk.kd
[Oct 31 18:33:08] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
[Oct 31 18:33:08] Hyprkrnl:[DE] Sorting drivers...
[Oct 31 18:33:08] Hyprkrnl:[DE] Initializing drivers...
[Oct 31 18:33:08] Hyprkrnl:[IN] Loaded 3 drivers
[Oct 31 18:33:08] Hyprkrnl:[IN] Loading filesystem...
[Oct 31 18:33:08] Hyprkrnl:[IN] Bootdrive is disk
[Oct 31 18:33:08] Hyprkrnl:[IN] Loading system...

View File

@@ -1,8 +0,0 @@
[Nov 12 22:17:07] Hyprkrnl:[IN] Created logger
[Nov 12 22:17:07] Hyprkrnl:[IN] Loading globals...
[Nov 12 22:17:07] Hyprkrnl:[IN] Loading drivers...
[Nov 12 22:17:07] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
[Nov 12 22:17:07] Hyprkrnl:[IN] Loaded 3 drivers
[Nov 12 22:17:07] Hyprkrnl:[IN] Loading filesystem...
[Nov 12 22:17:07] Hyprkrnl:[IN] Bootdrive is disk
[Nov 12 22:17:07] Hyprkrnl:[IN] Loading system...

View File

@@ -1,17 +0,0 @@
[Oct 30 18:13:15] Hyprkrnl:[IN] Created logger
[Oct 30 18:13:15] Hyprkrnl:[IN] Loading globals...
[Oct 30 18:13:15] Hyprkrnl:[DE] Loading string.lua
[Oct 30 18:13:15] Hyprkrnl:[DE] Loading table.lua
[Oct 30 18:13:15] Hyprkrnl:[IN] Loading drivers...
[Oct 30 18:13:15] Hyprkrnl:[DE] Loading module ac.disks.kd
[Oct 30 18:13:15] Hyprkrnl:[DE] Loading module cc.disks.kd
[Oct 30 18:13:15] Hyprkrnl:[DE] Loading module cc.periph.kd
[Oct 30 18:13:15] Hyprkrnl:[DE] Loading module cc.terminal.kd
[Oct 30 18:13:15] Hyprkrnl:[DE] Loading module ccpc.disk.kd
[Oct 30 18:13:15] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
[Oct 30 18:13:15] Hyprkrnl:[DE] Sorting drivers...
[Oct 30 18:13:15] Hyprkrnl:[DE] Initializing drivers...
[Oct 30 18:13:15] Hyprkrnl:[IN] Loaded 3 drivers
[Oct 30 18:13:15] Hyprkrnl:[IN] Loading filesystem...
[Oct 30 18:13:15] Hyprkrnl:[IN] Bootdrive is disk
[Oct 30 18:13:15] Hyprkrnl:[IN] Loading system...

View File

@@ -1,8 +0,0 @@
[Nov 13 20:06:54] Hyprkrnl:[IN] Created logger
[Nov 13 20:06:54] Hyprkrnl:[IN] Loading globals...
[Nov 13 20:06:54] Hyprkrnl:[IN] Loading drivers...
[Nov 13 20:06:54] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
[Nov 13 20:06:54] Hyprkrnl:[IN] Loaded 3 drivers
[Nov 13 20:06:54] Hyprkrnl:[IN] Loading filesystem...
[Nov 13 20:06:54] Hyprkrnl:[IN] Bootdrive is disk
[Nov 13 20:06:54] Hyprkrnl:[IN] Loading system...

View File

@@ -1,17 +0,0 @@
[Nov 13 20:07:50] Hyprkrnl:[IN] Created logger
[Nov 13 20:07:50] Hyprkrnl:[IN] Loading globals...
[Nov 13 20:07:50] Hyprkrnl:[DE] Loading string.lua
[Nov 13 20:07:50] Hyprkrnl:[DE] Loading table.lua
[Nov 13 20:07:50] Hyprkrnl:[IN] Loading drivers...
[Nov 13 20:07:50] Hyprkrnl:[DE] Loading module ac.disks.kd
[Nov 13 20:07:50] Hyprkrnl:[DE] Loading module cc.disks.kd
[Nov 13 20:07:50] Hyprkrnl:[DE] Loading module cc.periph.kd
[Nov 13 20:07:50] Hyprkrnl:[DE] Loading module cc.terminal.kd
[Nov 13 20:07:50] Hyprkrnl:[DE] Loading module ccpc.disk.kd
[Nov 13 20:07:50] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
[Nov 13 20:07:50] Hyprkrnl:[DE] Sorting drivers...
[Nov 13 20:07:50] Hyprkrnl:[DE] Initializing drivers...
[Nov 13 20:07:50] Hyprkrnl:[IN] Loaded 3 drivers
[Nov 13 20:07:50] Hyprkrnl:[IN] Loading filesystem...
[Nov 13 20:07:50] Hyprkrnl:[IN] Bootdrive is disk
[Nov 13 20:07:50] Hyprkrnl:[IN] Loading system...

View File

@@ -1,19 +0,0 @@
[Oct 30 17:41:54] Hyprkrnl:[IN] Created logger
[Oct 30 17:41:54] Hyprkrnl:[IN] Loading globals...
[Oct 30 17:41:54] Hyprkrnl:[DE] Loading require.lua
[Oct 30 17:41:54] Hyprkrnl:[DE] Loading string.lua
[Oct 30 17:41:54] Hyprkrnl:[DE] Loading table.lua
[Oct 30 17:41:54] Hyprkrnl:[IN] Loading drivers...
[Oct 30 17:41:54] Hyprkrnl:[DE] Loading module ac.disks.kd
[Oct 30 17:41:54] Hyprkrnl:[DE] Loading module cc.disks.kd
[Oct 30 17:41:54] Hyprkrnl:[DE] Loading module cc.periph.kd
[Oct 30 17:41:54] Hyprkrnl:[DE] Loading module cc.terminal.kd
[Oct 30 17:41:54] Hyprkrnl:[DE] Loading module ccpc.disk.kd
[Oct 30 17:41:54] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
[Oct 30 17:41:54] Hyprkrnl:[DE] Sorting drivers...
[Oct 30 17:41:54] Hyprkrnl:[DE] Initializing drivers...
[Oct 30 17:41:54] Hyprkrnl:[IN] Loaded 3 drivers
[Oct 30 17:41:54] Hyprkrnl:[IN] Loading filesystem...
[Oct 30 17:41:54] Hyprkrnl:[IN] Bootdrive is disk
[Oct 30 17:41:54] Hyprkrnl:[IN] [REQUIRE]: Initialized FS
[Oct 30 17:41:54] Hyprkrnl:[IN] Loading hypervisor...

View File

@@ -1,19 +0,0 @@
[Oct 30 17:43:09] Hyprkrnl:[IN] Created logger
[Oct 30 17:43:09] Hyprkrnl:[IN] Loading globals...
[Oct 30 17:43:09] Hyprkrnl:[DE] Loading require.lua
[Oct 30 17:43:09] Hyprkrnl:[DE] Loading string.lua
[Oct 30 17:43:09] Hyprkrnl:[DE] Loading table.lua
[Oct 30 17:43:09] Hyprkrnl:[IN] Loading drivers...
[Oct 30 17:43:09] Hyprkrnl:[DE] Loading module ac.disks.kd
[Oct 30 17:43:09] Hyprkrnl:[DE] Loading module cc.disks.kd
[Oct 30 17:43:09] Hyprkrnl:[DE] Loading module cc.periph.kd
[Oct 30 17:43:09] Hyprkrnl:[DE] Loading module cc.terminal.kd
[Oct 30 17:43:09] Hyprkrnl:[DE] Loading module ccpc.disk.kd
[Oct 30 17:43:09] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
[Oct 30 17:43:09] Hyprkrnl:[DE] Sorting drivers...
[Oct 30 17:43:09] Hyprkrnl:[DE] Initializing drivers...
[Oct 30 17:43:09] Hyprkrnl:[IN] Loaded 3 drivers
[Oct 30 17:43:09] Hyprkrnl:[IN] Loading filesystem...
[Oct 30 17:43:09] Hyprkrnl:[IN] Bootdrive is disk
[Oct 30 17:43:09] Hyprkrnl:[IN] [REQUIRE]: Initialized FS
[Oct 30 17:43:09] Hyprkrnl:[IN] Loading hypervisor...

View File

@@ -1,19 +0,0 @@
[Oct 30 17:44:55] Hyprkrnl:[IN] Created logger
[Oct 30 17:44:55] Hyprkrnl:[IN] Loading globals...
[Oct 30 17:44:55] Hyprkrnl:[DE] Loading require.lua
[Oct 30 17:44:55] Hyprkrnl:[DE] Loading string.lua
[Oct 30 17:44:55] Hyprkrnl:[DE] Loading table.lua
[Oct 30 17:44:55] Hyprkrnl:[IN] Loading drivers...
[Oct 30 17:44:55] Hyprkrnl:[DE] Loading module ac.disks.kd
[Oct 30 17:44:55] Hyprkrnl:[DE] Loading module cc.disks.kd
[Oct 30 17:44:55] Hyprkrnl:[DE] Loading module cc.periph.kd
[Oct 30 17:44:55] Hyprkrnl:[DE] Loading module cc.terminal.kd
[Oct 30 17:44:55] Hyprkrnl:[DE] Loading module ccpc.disk.kd
[Oct 30 17:44:55] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
[Oct 30 17:44:55] Hyprkrnl:[DE] Sorting drivers...
[Oct 30 17:44:55] Hyprkrnl:[DE] Initializing drivers...
[Oct 30 17:44:55] Hyprkrnl:[IN] Loaded 3 drivers
[Oct 30 17:44:55] Hyprkrnl:[IN] Loading filesystem...
[Oct 30 17:44:55] Hyprkrnl:[IN] Bootdrive is disk
[Oct 30 17:44:55] Hyprkrnl:[IN] [REQUIRE]: Initialized FS
[Oct 30 17:44:55] Hyprkrnl:[IN] Loading hypervisor...

View File

@@ -1,19 +0,0 @@
[Oct 30 17:45:15] Hyprkrnl:[IN] Created logger
[Oct 30 17:45:15] Hyprkrnl:[IN] Loading globals...
[Oct 30 17:45:15] Hyprkrnl:[DE] Loading require.lua
[Oct 30 17:45:15] Hyprkrnl:[DE] Loading string.lua
[Oct 30 17:45:15] Hyprkrnl:[DE] Loading table.lua
[Oct 30 17:45:15] Hyprkrnl:[IN] Loading drivers...
[Oct 30 17:45:15] Hyprkrnl:[DE] Loading module ac.disks.kd
[Oct 30 17:45:15] Hyprkrnl:[DE] Loading module cc.disks.kd
[Oct 30 17:45:15] Hyprkrnl:[DE] Loading module cc.periph.kd
[Oct 30 17:45:15] Hyprkrnl:[DE] Loading module cc.terminal.kd
[Oct 30 17:45:15] Hyprkrnl:[DE] Loading module ccpc.disk.kd
[Oct 30 17:45:15] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
[Oct 30 17:45:15] Hyprkrnl:[DE] Sorting drivers...
[Oct 30 17:45:15] Hyprkrnl:[DE] Initializing drivers...
[Oct 30 17:45:15] Hyprkrnl:[IN] Loaded 3 drivers
[Oct 30 17:45:15] Hyprkrnl:[IN] Loading filesystem...
[Oct 30 17:45:15] Hyprkrnl:[IN] Bootdrive is disk
[Oct 30 17:45:15] Hyprkrnl:[IN] [REQUIRE]: Initialized FS
[Oct 30 17:45:15] Hyprkrnl:[IN] Loading hypervisor...

View File

@@ -1,19 +0,0 @@
[Oct 30 18:02:54] Hyprkrnl:[IN] Created logger
[Oct 30 18:02:54] Hyprkrnl:[IN] Loading globals...
[Oct 30 18:02:54] Hyprkrnl:[DE] Loading require.lua
[Oct 30 18:02:54] Hyprkrnl:[DE] Loading string.lua
[Oct 30 18:02:54] Hyprkrnl:[DE] Loading table.lua
[Oct 30 18:02:54] Hyprkrnl:[IN] Loading drivers...
[Oct 30 18:02:54] Hyprkrnl:[DE] Loading module ac.disks.kd
[Oct 30 18:02:54] Hyprkrnl:[DE] Loading module cc.disks.kd
[Oct 30 18:02:54] Hyprkrnl:[DE] Loading module cc.periph.kd
[Oct 30 18:02:54] Hyprkrnl:[DE] Loading module cc.terminal.kd
[Oct 30 18:02:54] Hyprkrnl:[DE] Loading module ccpc.disk.kd
[Oct 30 18:02:54] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
[Oct 30 18:02:54] Hyprkrnl:[DE] Sorting drivers...
[Oct 30 18:02:54] Hyprkrnl:[DE] Initializing drivers...
[Oct 30 18:02:54] Hyprkrnl:[IN] Loaded 3 drivers
[Oct 30 18:02:54] Hyprkrnl:[IN] Loading filesystem...
[Oct 30 18:02:54] Hyprkrnl:[IN] Bootdrive is disk
[Oct 30 18:02:54] Hyprkrnl:[IN] [REQUIRE]: Initialized FS
[Oct 30 18:02:54] Hyprkrnl:[IN] Loading hypervisor...

Some files were not shown because too many files have changed in this diff Show More