forked from Hyperion/HyperionOS
rewrite
This commit is contained in:
137
Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/00_stdlib.kmod
Executable file
137
Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/00_stdlib.kmod
Executable file
@@ -0,0 +1,137 @@
|
||||
function string.hasSuffix(str, suffix)
|
||||
return string.sub(str, #suffix+1) == suffix
|
||||
end
|
||||
|
||||
function string.hasPrefix(str, prefix)
|
||||
return string.sub(str, 1, #prefix) == prefix
|
||||
end
|
||||
|
||||
function string.getSuffix(str, prefix)
|
||||
return string.sub(str, #prefix+1)
|
||||
end
|
||||
|
||||
function string.getPrefix(str, suffix)
|
||||
return string.sub(str, 1, #suffix)
|
||||
end
|
||||
|
||||
function string.join(str, ...)
|
||||
return table.concat(table.pack(str, ...))
|
||||
end
|
||||
|
||||
function string.delim(str, ...)
|
||||
return table.concat(table.pack(...), str)
|
||||
end
|
||||
|
||||
function string.split(str, delim, maxResultCountOrNil)
|
||||
assert(#delim == 1, "only delim len 1 supported for now")
|
||||
maxResultCountOrNil = (maxResultCountOrNil or 0)-1
|
||||
local rv = {}
|
||||
local buf = ""
|
||||
for i = 1, #str do
|
||||
local c = string.sub(str,i,i)
|
||||
if #rv ~= maxResultCountOrNil and c == delim then
|
||||
table.insert(rv, buf)
|
||||
buf = ""
|
||||
else
|
||||
buf = buf..c
|
||||
end
|
||||
end
|
||||
table.insert(rv, buf)
|
||||
return rv
|
||||
end
|
||||
|
||||
function string.replace(str, search, replacement)
|
||||
local rv = ""
|
||||
local consumedLen = 1
|
||||
local i = 1
|
||||
while i<#str do
|
||||
if string.sub(str, i, i+#search-1) == search then
|
||||
rv = rv .. string.sub(str, consumedLen, i-1) .. replacement
|
||||
i=i+#search
|
||||
consumedLen = i
|
||||
end
|
||||
i=i+1
|
||||
end
|
||||
return rv .. string.sub(str, consumedLen)
|
||||
end
|
||||
|
||||
function table.deepcopy(orig, copies)
|
||||
copies = copies or {}
|
||||
|
||||
if type(orig) ~= 'table' then
|
||||
return orig
|
||||
elseif copies[orig] then
|
||||
return copies[orig]
|
||||
end
|
||||
|
||||
local copy = {}
|
||||
copies[orig] = copy
|
||||
|
||||
for k, v in next, orig, nil do
|
||||
local copied_key = table.deepcopy(k, copies)
|
||||
local copied_val = table.deepcopy(v, copies)
|
||||
copy[copied_key] = copied_val
|
||||
end
|
||||
|
||||
return copy
|
||||
end
|
||||
|
||||
function table.hasKey(tabl, query)
|
||||
for i,v in pairs(tabl) do
|
||||
if i==query then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function table.hasVal(tabl, query)
|
||||
for i,v in pairs(tabl) do
|
||||
if v==query then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function serialize(table)
|
||||
local output = "{"
|
||||
for i,v in pairs(table) do
|
||||
local coma=true
|
||||
if type(i) == "string" then
|
||||
output=output.."[\""..i.."\"]="
|
||||
end
|
||||
if type(v) == "table" then
|
||||
if v == table then
|
||||
output=string.sub(output,1,#output-(#i+1))
|
||||
coma=false
|
||||
else
|
||||
output=output..serialize(v)
|
||||
end
|
||||
elseif type(v) == "string" then
|
||||
output=output.."[=["..v.."]=]"
|
||||
elseif type(v) == "number" then
|
||||
output=output..tostring(v)
|
||||
elseif type(v) == "boolean" then
|
||||
if v == true then
|
||||
output=output.."true"
|
||||
else
|
||||
output=output.."false"
|
||||
end
|
||||
elseif type(v) == "function" then
|
||||
output=output.."function() end"
|
||||
else
|
||||
error("serialization of type \""..type(v).."\" is not supported")
|
||||
end
|
||||
if coma then
|
||||
output=output..","
|
||||
end
|
||||
end
|
||||
if #table>0 or string.sub(output,#output,#output) == "," then
|
||||
output=string.sub(output,1,#output-1)
|
||||
end
|
||||
output=output.."}"
|
||||
return output
|
||||
end
|
||||
|
||||
table.serialize=serialize
|
||||
217
Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/10_vfs.kmod
Executable file
217
Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/10_vfs.kmod
Executable file
@@ -0,0 +1,217 @@
|
||||
local args = {...}
|
||||
local kernel = args[1]
|
||||
local fs = {}
|
||||
local disks = {}
|
||||
local mounts = {["/"]="$"}
|
||||
|
||||
-- path normaliing
|
||||
local function normalizePath(path)
|
||||
if not path or path == "" then return "/" end
|
||||
if path:sub(1,1) ~= "/" then path = "/" .. path end
|
||||
local parts = {}
|
||||
for part in path:gmatch("[^/]+") do
|
||||
if part == ".." then
|
||||
if #parts > 0 then table.remove(parts) end
|
||||
elseif part ~= "." and part ~= "" then
|
||||
parts[#parts+1] = part
|
||||
end
|
||||
end
|
||||
return "/" .. table.concat(parts, "/")
|
||||
end
|
||||
|
||||
-- disk resolution
|
||||
local function resolvePath(path)
|
||||
local abs = normalizePath(path)
|
||||
local best = "/"
|
||||
for mount, diskAddr in pairs(mounts) do
|
||||
if abs:sub(1, #mount) == mount and #mount > #best then
|
||||
best = mount
|
||||
end
|
||||
end
|
||||
local newPath = abs:sub(#best + 1)
|
||||
if newPath == "" then newPath = "/" end
|
||||
return disks[mounts[best]], newPath
|
||||
end
|
||||
|
||||
-- Symlinks
|
||||
-- Format: #!@SYMLINK[target]
|
||||
local SYMLINK_PREFIX = "#!@SYMLINK["
|
||||
local SYMLINK_SUFFIX = "]"
|
||||
local SYMLINK_MAX_DEPTH = 64
|
||||
|
||||
local function isSymlink(disk, path)
|
||||
if not disk:fileExists(path) then return false end
|
||||
local text = disk:readAllText(path)
|
||||
if not text then return false end
|
||||
return text:sub(1, #SYMLINK_PREFIX) == SYMLINK_PREFIX
|
||||
end
|
||||
|
||||
local function readSymlink(disk, path)
|
||||
local text = disk:readAllText(path)
|
||||
if not text then return nil end
|
||||
if text:sub(1, #SYMLINK_PREFIX) ~= SYMLINK_PREFIX then return nil end
|
||||
local target = text:sub(#SYMLINK_PREFIX + 1)
|
||||
if target:sub(-1) == SYMLINK_SUFFIX then
|
||||
target = target:sub(1, -2)
|
||||
end
|
||||
return target
|
||||
end
|
||||
|
||||
|
||||
-- Path resolution
|
||||
local function splitPath(p)
|
||||
local parts = {}
|
||||
for part in p:gmatch("[^/]+") do parts[#parts+1] = part end
|
||||
return parts
|
||||
end
|
||||
|
||||
local function resolveSymlink(path)
|
||||
path = normalizePath(path)
|
||||
local symlinkDepth = 0
|
||||
local parts = splitPath(path)
|
||||
local resolved = {}
|
||||
local i = 1
|
||||
|
||||
while i <= #parts do
|
||||
local comp = parts[i]
|
||||
if comp == "." then
|
||||
elseif comp == ".." then
|
||||
if #resolved > 0 then table.remove(resolved) end
|
||||
else
|
||||
local currentPath = "/" .. table.concat(resolved, "/")
|
||||
local disk, p = resolvePath(currentPath .. "/" .. comp)
|
||||
if isSymlink(disk, p) then
|
||||
symlinkDepth = symlinkDepth + 1
|
||||
if symlinkDepth > SYMLINK_MAX_DEPTH then
|
||||
error("Too many levels of symbolic links: " .. path)
|
||||
end
|
||||
local target = readSymlink(disk, p)
|
||||
if not target then
|
||||
resolved[#resolved+1] = comp
|
||||
else
|
||||
if target:sub(1,1) == "/" then
|
||||
resolved = splitPath(normalizePath(target))
|
||||
else
|
||||
local base = resolved
|
||||
resolved = {}
|
||||
for _, seg in ipairs(base) do resolved[#resolved+1]=seg end
|
||||
for seg in target:gmatch("[^/]+") do
|
||||
if seg == ".." then
|
||||
if #resolved>0 then table.remove(resolved) end
|
||||
elseif seg ~= "." then
|
||||
resolved[#resolved+1]=seg
|
||||
end
|
||||
end
|
||||
end
|
||||
local remaining = {}
|
||||
for j=i+1,#parts do remaining[#remaining+1]=parts[j] end
|
||||
parts = remaining
|
||||
i = 0
|
||||
end
|
||||
else
|
||||
resolved[#resolved+1]=comp
|
||||
end
|
||||
end
|
||||
i=i+1
|
||||
end
|
||||
|
||||
local finalPath="/"..table.concat(resolved,"/")
|
||||
local disk,diskPath=resolvePath(finalPath)
|
||||
return disk,diskPath
|
||||
end
|
||||
|
||||
-- PUBLIC API: MOUNTING
|
||||
function fs.mount(disk, mountPoint)
|
||||
if kernel.uid ~= 0 then error("Permission Denied") end
|
||||
mounts[mountPoint]=disk
|
||||
end
|
||||
function fs.unmount(mountPoint)
|
||||
if kernel.uid ~= 0 then error("Permission Denied") end
|
||||
mounts[mountPoint]=nil
|
||||
end
|
||||
function fs.virtDisk(diskObj)
|
||||
if kernel.uid ~= 0 then error("Permission Denied") end
|
||||
if disks[diskObj.address] then error("Disk exists") end
|
||||
disks[diskObj.address]=diskObj
|
||||
end
|
||||
function fs.eject(addr)
|
||||
if kernel.uid ~= 0 then error("Permission Denied") end
|
||||
disks[addr]=nil
|
||||
end
|
||||
|
||||
-- SYMLINK API
|
||||
function fs.symlink(target, linkPath)
|
||||
local disk, p = resolvePath(linkPath)
|
||||
return disk:writeAllText(p, SYMLINK_PREFIX..target..SYMLINK_SUFFIX)
|
||||
end
|
||||
function fs.isLink(path)
|
||||
local disk, p = resolvePath(path)
|
||||
return isSymlink(disk,p)
|
||||
end
|
||||
function fs.readLink(path)
|
||||
local disk, p = resolvePath(path)
|
||||
return readSymlink(disk,p)
|
||||
end
|
||||
|
||||
-- FILE OPERATIONS
|
||||
function fs.exists(path)
|
||||
local disk, p = resolveSymlink(path)
|
||||
return disk:fileExists(p) or disk:directoryExists(p)
|
||||
end
|
||||
|
||||
function fs.isFile(path)
|
||||
local disk, p = resolveSymlink(path)
|
||||
if isSymlink(disk, p) then return false end
|
||||
return disk:fileExists(p)
|
||||
end
|
||||
|
||||
function fs.isDir(path)
|
||||
local disk, p = resolveSymlink(path)
|
||||
if isSymlink(disk, p) then return false end
|
||||
return disk:directoryExists(p)
|
||||
end
|
||||
|
||||
function fs.list(path)
|
||||
local disk, p = resolveSymlink(path)
|
||||
return disk:list(p)
|
||||
end
|
||||
|
||||
function fs.makeDir(path)
|
||||
local disk, p = resolveSymlink(path)
|
||||
return disk:makeDirectory(p)
|
||||
end
|
||||
|
||||
function fs.remove(path)
|
||||
local disk, p = resolvePath(path)
|
||||
if isSymlink(disk, p) then
|
||||
return disk:remove(p)
|
||||
end
|
||||
local d2, p2 = resolveSymlink(path)
|
||||
return d2:remove(p2)
|
||||
end
|
||||
|
||||
function fs.readAllText(path)
|
||||
local disk, p = resolveSymlink(path)
|
||||
return disk:readAllText(p)
|
||||
end
|
||||
|
||||
function fs.writeAllText(path, text)
|
||||
local disk, p = resolveSymlink(path)
|
||||
return disk:writeAllText(p, text)
|
||||
end
|
||||
|
||||
function fs.appendAllText(path, text)
|
||||
local disk, p = resolveSymlink(path)
|
||||
return disk:appendAllText(p, text)
|
||||
end
|
||||
|
||||
function fs.getSize(path)
|
||||
local disk, p = resolveSymlink(path)
|
||||
return disk:getSize(p)
|
||||
end
|
||||
|
||||
-- INIT
|
||||
for _,v in kernel.initdisks.list() do fs.virtDisk(v) end
|
||||
kernel.fs=fs
|
||||
kernel.chache.preload.fs=fs
|
||||
kernel.chache.preload.filesystem=fs
|
||||
22
Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/11_fstabInit.kmod
Executable file
22
Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/11_fstabInit.kmod
Executable file
@@ -0,0 +1,22 @@
|
||||
local args={...}
|
||||
local kernel=args[1]
|
||||
local ifs=kernel.ifs
|
||||
local initdisks=kernel.initdisks
|
||||
|
||||
local fstab=ifs.readAllText("/etc/fstab")
|
||||
kernel.fs.update(initdisks)
|
||||
for i,v in ipairs(string.split(fstab,"\n")) do
|
||||
if v:sub(1,1)=="U" then
|
||||
local id=""
|
||||
for i=3,#v do
|
||||
if v:sub(i,i)==";" then
|
||||
if i==3 then kernel.log("Invalid fstab line... Skipping.","WARN") goto endline end
|
||||
id=v:sub(3,i-1)
|
||||
end
|
||||
end
|
||||
local path=v:sub(#id+4)
|
||||
kernel.log("Mounted "..id.." to "..path)
|
||||
kernel.fs.mount(id,path)
|
||||
::endline::
|
||||
end
|
||||
end
|
||||
182
Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/11_mkvirtfs.kmod
Executable file
182
Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/11_mkvirtfs.kmod
Executable file
@@ -0,0 +1,182 @@
|
||||
local args={...}
|
||||
local kernel=args[1]
|
||||
|
||||
function kernel.fs.mkvirtfs(address, readOnly, label, autoRegister)
|
||||
if kernel.uid ~= 0 then error("Permission Denied") end
|
||||
local disk = {}
|
||||
disk.address = address
|
||||
local isRO = readOnly or false
|
||||
|
||||
local backend = {
|
||||
["/"] = { __dir = true }
|
||||
}
|
||||
|
||||
-----------------------------------------------------------------
|
||||
-- Helpers
|
||||
-----------------------------------------------------------------
|
||||
|
||||
local function norm(path)
|
||||
if not path or path == "" then return "/" end
|
||||
if path:sub(1,1) ~= "/" then path = "/" .. path end
|
||||
path = path:gsub("/+", "/")
|
||||
return path
|
||||
end
|
||||
|
||||
local function split(path)
|
||||
local parts = {}
|
||||
for p in path:gmatch("[^/]+") do table.insert(parts, p) end
|
||||
return parts
|
||||
end
|
||||
|
||||
local function getNode(path)
|
||||
path = norm(path)
|
||||
if path == "/" then return backend["/"] end
|
||||
local node = backend["/"]
|
||||
for _, part in ipairs(split(path)) do
|
||||
node = node[part]
|
||||
if not node then return nil end
|
||||
end
|
||||
return node
|
||||
end
|
||||
|
||||
local function getParent(path)
|
||||
local parts = split(norm(path))
|
||||
local name = table.remove(parts)
|
||||
local parentPath = "/" .. table.concat(parts, "/")
|
||||
return getNode(parentPath), name
|
||||
end
|
||||
|
||||
local function ensureWrite()
|
||||
if isRO then return false, "read-only" end
|
||||
return true
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------
|
||||
-- File IO (supports string or file-object with read/write funcs)
|
||||
-----------------------------------------------------------------
|
||||
|
||||
local function fileRead(node)
|
||||
if type(node) == "string" then
|
||||
return node
|
||||
elseif type(node) == "table" and node.__file and node.read then
|
||||
return node.read()
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function fileWrite(parent, name, text)
|
||||
local node = parent[name]
|
||||
if type(node) == "string" then
|
||||
parent[name] = text
|
||||
return true
|
||||
elseif type(node) == "table" and node.__file and node.write then
|
||||
return node.write(text)
|
||||
end
|
||||
parent[name] = text
|
||||
return true
|
||||
end
|
||||
|
||||
local function fileAppend(parent, name, text)
|
||||
local node = parent[name]
|
||||
if type(node) == "string" then
|
||||
parent[name] = node .. text
|
||||
return true
|
||||
elseif type(node) == "table" and node.__file and node.write then
|
||||
return node.write((node.read() or "") .. text)
|
||||
end
|
||||
parent[name] = text
|
||||
return true
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------
|
||||
-- API
|
||||
-----------------------------------------------------------------
|
||||
|
||||
function disk:isReadOnly() return isRO end
|
||||
function disk:spaceUsed() return 0 end
|
||||
function disk:spaceTotal() return 0 end
|
||||
|
||||
function disk:readAllText(path)
|
||||
local node = getNode(path)
|
||||
if not node then return nil, "file not found" end
|
||||
return fileRead(node)
|
||||
end
|
||||
|
||||
function disk:writeAllText(path, text)
|
||||
local ok, err = ensureWrite(); if not ok then return false, err end
|
||||
|
||||
local parent, name = getParent(path)
|
||||
if not parent or not parent.__dir then return false, "invalid directory" end
|
||||
return fileWrite(parent, name, tostring(text))
|
||||
end
|
||||
|
||||
function disk:appendAllText(path, text)
|
||||
local ok, err = ensureWrite(); if not ok then return false, err end
|
||||
|
||||
local parent, name = getParent(path)
|
||||
if not parent or not parent.__dir then return false, "invalid directory" end
|
||||
return fileAppend(parent, name, tostring(text))
|
||||
end
|
||||
|
||||
function disk:list(path)
|
||||
local node = getNode(path)
|
||||
if not node or not node.__dir then return nil, "not a directory" end
|
||||
local out = {}
|
||||
for k, _ in pairs(node) do if k ~= "__dir" then table.insert(out, k) end end
|
||||
return out
|
||||
end
|
||||
|
||||
function disk:fileExists(path)
|
||||
local node = getNode(path)
|
||||
return type(node) == "string" or (type(node) == "table" and node.__file)
|
||||
end
|
||||
|
||||
function disk:directoryExists(path)
|
||||
local node = getNode(path)
|
||||
return node and type(node) == "table" and node.__dir or false
|
||||
end
|
||||
|
||||
function disk:makeDirectory(path)
|
||||
local ok, err = ensureWrite(); if not ok then return false, err end
|
||||
local parent, name = getParent(path)
|
||||
if not parent or not parent.__dir then return false, "invalid parent directory" end
|
||||
parent[name] = { __dir = true }
|
||||
return true
|
||||
end
|
||||
|
||||
function disk:remove(path)
|
||||
local ok, err = ensureWrite(); if not ok then return false, err end
|
||||
local parent, name = getParent(path)
|
||||
if not parent or not parent[name] then return false, "not found" end
|
||||
parent[name] = nil
|
||||
return true
|
||||
end
|
||||
|
||||
function disk:setLabel(new)
|
||||
local ok, err = ensureWrite(); if not ok then return false, err end
|
||||
label = tostring(new)
|
||||
end
|
||||
|
||||
function disk:getLabel()
|
||||
return label
|
||||
end
|
||||
|
||||
function disk:size(path)
|
||||
local node = getNode(path)
|
||||
if type(node) == "string" then return #node end
|
||||
if type(node) == "table" and node.__file and node.read then
|
||||
local v = node.read()
|
||||
return v and #v or 0
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------
|
||||
-- Auto-register with kernel and return backend
|
||||
-----------------------------------------------------------------
|
||||
if kernel and kernel.fs and kernel.fs.virtDisk and autoRegister then
|
||||
kernel.fs.virtDisk(disk)
|
||||
end
|
||||
|
||||
return backend, disk
|
||||
end
|
||||
56
Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/11_require.kmod
Executable file
56
Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/11_require.kmod
Executable file
@@ -0,0 +1,56 @@
|
||||
local args = {...}
|
||||
local kernel = args[1]
|
||||
|
||||
-- List of search paths
|
||||
local paths = {
|
||||
"/lib/?",
|
||||
"/usr/lib/?",
|
||||
"/usr/local/lib/?"
|
||||
}
|
||||
|
||||
-- Custom require implementation
|
||||
function require(module)
|
||||
-- Return cached module if it already exists
|
||||
if kernel.cache.preload[module] then
|
||||
return kernel.cache.preload[module]
|
||||
end
|
||||
|
||||
local err = {}
|
||||
|
||||
for _, path in ipairs(paths) do
|
||||
-- Replace "?" with module name
|
||||
local filePath = string.replace(path, "?", module)
|
||||
|
||||
-- Try to open file
|
||||
local file = kernel.fs.isFile(filePath)
|
||||
if file then
|
||||
local content = kernel.fs.readAllText(filePath)
|
||||
|
||||
-- Load the module as Lua code
|
||||
local chunk, loadErr = load(content, filePath)
|
||||
if not chunk then
|
||||
table.insert(err, "Error loading: " .. filePath .. ": " .. loadErr)
|
||||
else
|
||||
-- Execute the module. If the module returns a value, cache it.
|
||||
local ok, result = xpcall(chunk, debug.traceback)
|
||||
if not ok then
|
||||
table.insert(err, "Error executing: "..filePath..": "..tostring(result))
|
||||
else
|
||||
if result ~= nil then
|
||||
kernel.cache.preload[module] = result
|
||||
return result
|
||||
end
|
||||
|
||||
-- If module doesn't return anything, cache `true` like Lua does
|
||||
kernel.cache.preload[module] = true
|
||||
return true
|
||||
end
|
||||
end
|
||||
else
|
||||
table.insert(err, "Module not found: " .. filePath)
|
||||
end
|
||||
end
|
||||
|
||||
-- If nothing worked, raise an error with all reasons
|
||||
error("Unable to require module '" .. module .. "':\n" .. table.concat(err, "\n"))
|
||||
end
|
||||
17
Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/12_devfs.kmod
Executable file
17
Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/12_devfs.kmod
Executable file
@@ -0,0 +1,17 @@
|
||||
local args={...}
|
||||
local kernel = args[1]
|
||||
|
||||
local data = kernel.fs.mkvirtfs("devfs0000", true, "devfs", false)
|
||||
|
||||
data["/"]["OSVERSION"]="Hyperion 1.0.0"
|
||||
data["/"]["eeprom"]={
|
||||
__file=true,
|
||||
read=function()
|
||||
return kernel.computer:getEEPROM()
|
||||
end,
|
||||
write=function(text)
|
||||
if kernel.uid ~= 0 then error("Permission Denied") end
|
||||
kernel.computer:setEEPROM(text)
|
||||
end
|
||||
}
|
||||
|
||||
12
Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/20_keventd.kmod
Executable file
12
Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/20_keventd.kmod
Executable file
@@ -0,0 +1,12 @@
|
||||
local args={...}
|
||||
local kernel=args[1]
|
||||
kernel.drivers.processes[#kernel.drivers.processes+1]=function()
|
||||
while true do
|
||||
local event={kernel.computer:getMachineEvent()}
|
||||
while event[1]~=nil do
|
||||
kernel.hpv.sendSig("all", table.unpack(event))
|
||||
event={kernel.computer:getMachineEvent()}
|
||||
end
|
||||
coroutine.yield()
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,19 @@
|
||||
local args={...}
|
||||
local kernel=args[2]
|
||||
|
||||
for _,subf in ipairs(kernel.fs.list("/lib/modules/")) do
|
||||
if subf~="Hyperion" then
|
||||
for _,driver in ipairs(kernel.fs.list("/lib/modules/"..subf)) do
|
||||
local code = kernel.fs.readAllText("/lib/modules/"..subf.."/"..driver)
|
||||
local func, err = load(code, "@"..driver)
|
||||
if not func then
|
||||
kernel.log("DriverLoadErr: "..tostring(err), "ERROR")
|
||||
else
|
||||
local ok, err = xpcall(func, debug.traceback)
|
||||
if not ok then
|
||||
kernel.log("DriverLoadErr: "..tostring(err), "ERROR")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
11
Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/31_thirdPartyInit.kmod
Executable file
11
Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/31_thirdPartyInit.kmod
Executable file
@@ -0,0 +1,11 @@
|
||||
local args={...}
|
||||
local kernel=args[1]
|
||||
|
||||
for _,l in ipairs(kernel.drivers.prior) do
|
||||
for _,d in ipairs(l) do
|
||||
if d.init then
|
||||
local ok,err = xpcall(d.init, debug.traceback)
|
||||
if not ok then kernel.log("DriverInitErr: "..tostring(err)) end
|
||||
end
|
||||
end
|
||||
end
|
||||
0
Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/98_dbgProtect.kmod
Executable file
0
Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/98_dbgProtect.kmod
Executable file
167
Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/99_init.kmod
Executable file
167
Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/99_init.kmod
Executable file
@@ -0,0 +1,167 @@
|
||||
local args={...}
|
||||
local kernel = args[1]
|
||||
local tasks={}
|
||||
local currentTask={}
|
||||
local signals={}
|
||||
local tid=1
|
||||
local gid=1
|
||||
local sys={}
|
||||
|
||||
function sys.hookSig(sig, func)
|
||||
if not signals[tostring(currentTask.pid)][sig] then
|
||||
signals[tostring(currentTask.pid)][sig]={}
|
||||
end
|
||||
signals[tostring(currentTask.pid)][sig][#signals[tostring(currentTask.pid)][sig]+1]=func
|
||||
end
|
||||
|
||||
function sys.clearSigHooks(typ)
|
||||
if not typ or typ == "all" then
|
||||
signals[tostring(currentTask.pid)]={}
|
||||
currentTask.signal=signals[tostring(currentTask.pid)]
|
||||
else
|
||||
if currentTask.signal[typ] then
|
||||
currentTask.signal[typ]={}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function sys.sendSig(pid, signal, ...)
|
||||
if pid=="all" then
|
||||
for i,v in pairs(tasks) do
|
||||
v.sigQ[#v.sigQ+1]={signal, ...}
|
||||
end
|
||||
return
|
||||
end
|
||||
if not tasks[tostring(pid)] then return false end
|
||||
tasks[tostring(pid)].sigQ[#tasks[tostring(pid)].sigQ+1]={signal, ...}
|
||||
return true
|
||||
end
|
||||
|
||||
function sys.flushSigs()
|
||||
local ret = {}
|
||||
for i=1, #currentTask.sigQ do
|
||||
if currentTask.signal[currentTask.sigQ[i][1]] then
|
||||
for _,v in ipairs(currentTask.signal[currentTask.sigQ[1][1]]) do
|
||||
coroutine.resumeWithTimeout(coroutine.create(function()
|
||||
local ok, err = xpcall(v, debug.traceback, table.unpack(table.remove(currentTask.sigQ, 1)))
|
||||
if not ok then
|
||||
table.insert(ret, err)
|
||||
end
|
||||
end), 10)
|
||||
end
|
||||
else
|
||||
for _,v in ipairs(currentTask.signal["unhandledEvent"]) do
|
||||
coroutine.resumeWithTimeout(coroutine.create(function()
|
||||
local ok, err = xpcall(v, debug.traceback, table.unpack(table.remove(currentTask.sigQ, 1)))
|
||||
if not ok then
|
||||
table.insert(ret, err)
|
||||
end
|
||||
end), 10)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function sys.spawn(func, name, evars, args)
|
||||
local id=tid
|
||||
tid=tid+1
|
||||
name=name or tostring(id)
|
||||
|
||||
signals[tostring(id)]={}
|
||||
tasks[tostring(id)]={
|
||||
coro=coroutine.create(function()
|
||||
local ret = {xpcall(func, debug.traceback, table.unpack(args))}
|
||||
if not ret[1] then
|
||||
sys.sendSig(currentTask.ppid, "ChildTaskError", id, err)
|
||||
else
|
||||
sys.sendSig(currentTask.ppid, "ChildTaskExit", id, table.unpack(ret, 2))
|
||||
end
|
||||
currentTask.status="Z"
|
||||
end),
|
||||
name=name,
|
||||
pid=id,
|
||||
ppid=currentTask.pid,
|
||||
tgid=currentTask.tgid,
|
||||
user=kernel.user,
|
||||
uid=kernel.uid,
|
||||
evars=evars,
|
||||
args=args,
|
||||
vy=0,
|
||||
ivy=0,
|
||||
status="R",
|
||||
signal=signals[tostring(id)],
|
||||
parent=currentTask,
|
||||
children={},
|
||||
sibling=currentTask.children,
|
||||
sigQ={}
|
||||
}
|
||||
end
|
||||
|
||||
local function collectZombieProc()
|
||||
local ret = {}
|
||||
for _,v in pairs(tasks) do
|
||||
if v.status=="Z" then
|
||||
local pid = v.pid
|
||||
for _,c in ipairs(v.children) do
|
||||
c.parent=tasks["1"]
|
||||
c.sibling=tasks["1"].children
|
||||
c.ppid=1
|
||||
c.tgid=1
|
||||
end
|
||||
signals[tostring(pid)]=nil
|
||||
tasks[tostring(pid)]=nil
|
||||
table.insert(ret, pid)
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
signals["1"]={}
|
||||
tasks["1"]={
|
||||
coro=coroutine.create(function()
|
||||
local ret = {xpcall(kernel.fs.load(kernel.initPath), debug.traceback)}
|
||||
if not ok then
|
||||
kernel.panic(err)
|
||||
else
|
||||
kernel.panic("Attempted to kill init!")
|
||||
end
|
||||
end),
|
||||
name="SysInit",
|
||||
pid=1,
|
||||
ppid=0,
|
||||
tgid=1,
|
||||
user=kernel.user,
|
||||
uid=kernel.uid,
|
||||
evars={},
|
||||
args={kernel},
|
||||
vy=0,
|
||||
ivy=0,
|
||||
status="R",
|
||||
signal=signals["1"],
|
||||
parent={name="Hyprkrnl",pid=0},
|
||||
children={},
|
||||
sibling={},
|
||||
sigQ={}
|
||||
}
|
||||
kernel.chache.preload.sys=sys
|
||||
kernel.chache.preload.system=sys
|
||||
kernel.hpv=sys
|
||||
|
||||
kernel.saveLog()
|
||||
while true do
|
||||
for _,v in pairs(tasks) do
|
||||
currentTask=v
|
||||
kernel.user=currentTask.user
|
||||
kernel.uid=currentTask.uid
|
||||
sys.flushSigs()
|
||||
local status = coroutine.resumeWithTimeout(currentTask.coro, 50)
|
||||
if status then
|
||||
currentTask.vy=currentTask.vy+1
|
||||
else
|
||||
currentTask.ivy=currentTask.ivy+1
|
||||
end
|
||||
end
|
||||
collectZombieProc()
|
||||
end
|
||||
|
||||
kernel.panic("Exited pid 0")
|
||||
Reference in New Issue
Block a user