diff --git a/Build.tar b/Build.tar new file mode 100755 index 0000000..5f902c9 Binary files /dev/null and b/Build.tar differ diff --git a/Build/boot/kernel.lua b/Build/boot/kernel.lua index c488614..e646db3 100755 --- a/Build/boot/kernel.lua +++ b/Build/boot/kernel.lua @@ -14,29 +14,34 @@ kernel.group = "root" kernel.groups = {0} kernel.uid = 0 kernel.gid = 0 -kernel.stage = "start" +kernel.status = "start" kernel.key = {} -kernel.chache = {} -kernel.chache.preload = {} +kernel.cache = {} +kernel.cache.preload = {} +kernel._G=_G local windowsExp = false function kernel.log(msg, level) LOG_Text = LOG_Text..tostring(computer.time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n" - if kernel.stage == "start" then + if kernel.status == "start" then screen:print(tostring(computer.time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg) end end function kernel.PANIC(msg) - kernel.log("PANIC: "..msg, "PANIC") - pcall(kernel["saveLog"]) - screen:setTextColor(2) - screen:setBackgroundColor(0) - screen:clear() - screen:setCursorPos(1,1) - screen:print(LOG_Text) - screen:print("KERNEL PANIC!\n"..msg.."\nSystem halted.") - screen:print("Press any key to continue...") + if kernel.status~="Panic" then + kernel.log("PANIC: "..msg, "PANIC") + pcall(kernel["saveLog"]) + kernel.status="Panic" + kernel.reason=msg + screen:setTextColor(2) + screen:setBackgroundColor(0) + screen:clear() + screen:setCursorPos(1,1) + screen:print(LOG_Text) + screen:print("KERNEL PANIC!\n"..msg.."\nSystem halted.") + screen:print("Press any key to continue...") + end while true do local event={computer:getMachineEvent()} if event[1]=="keyPressed" then @@ -65,16 +70,12 @@ if windowsExp then while true do end end -kernel.log("Kernel loaded.", "INFO") -kernel.log("Mounting disks...", "INFO") +kernel.log("Kernel loaded.") +kernel.log("Mounting init disks...") disks.refresh() ifs.update(disks) ifs.mount("$", "/") -function kernel.saveLog() - ifs.writeAllText("/var/log/syslog.log", LOG_Text) -end - local fstab=ifs.readAllText("/etc/fstab") local split = function(str, delim, maxResultCountOrNil) assert(#delim == 1, "only delim len 1 supported for now") @@ -104,11 +105,15 @@ for i,v in ipairs(split(fstab,"\n")) do end end local path=v:sub(#id+4) - kernel.log("Mounted "..id.." to "..path) ifs.mount(id,path) ::endline:: end end +kernel.log("Disks initialized") + +function kernel.saveLog() + ifs.writeAllText("/var/log/syslog.log", LOG_Text) +end ifs.remove("/tmp") ifs.makeDir("/tmp") @@ -116,29 +121,24 @@ ifs.makeDir("/tmp") local drivers={} drivers.raw={} drivers.processes={} -drivers.prior={} drivers.type={} -for i=0, 99 do - drivers.prior[i]={} -end -function drivers.register(prior,object) +function drivers.register(object) drivers.raw[#drivers.raw+1]=object if object.main then drivers.processes[#drivers.processes+1]=object.main end - if drivers.prior[prior]==nil then drivers.prior[prior]={} end - drivers.prior[prior][#drivers.prior[prior]+1]=object if drivers.type[object.type]==nil then drivers.type[object.type]={} end drivers.type[object.type][#drivers.type[object.type]+1]=object end -local modules={} -for i=0, 99 do +local modules={[0]={}} +for i=0, 100 do modules[i]={} end +kernel.log("Gathering modules") for i,v in ipairs(ifs.list("/lib/modules/Hyperion/")) do local prior=tonumber(v:sub(1,2)) - modules[prior][#modules[prior]+1]="/lib/modules/Hyperion/"..v + modules[prior+1][#modules[prior+1]+1]="/lib/modules/Hyperion/"..v end kernel.drivers=drivers @@ -147,19 +147,17 @@ kernel.apis=apis kernel.computer=computer kernel.initPath=initPath kernel.arch=arch -kernel.initdisks=initdisks +kernel.initdisks=disks kernel.screen=screen + +kernel.log("Running modules") for _,p in ipairs(modules) do for _,v in ipairs(p) do local code=ifs.readAllText(v) local func,err=load(code,"@"..v) - if not func then kernel.log("ModuLoadErr: "..tostring(err)) goto skip end - local status, err = xpcall(func,debug.traceback,kernel) - if not status then goto skip end - if not err then goto skip end - if not err.init then goto skip end - local ok, err = xpcall(status.main,debug.traceback) - if not ok then kernel.log("ModuInitErr: "..tostring(err)) end + if not func then kernel.log("ModuLoadErr: "..tostring(err), "WARN") goto skip end + local status, err = xpcall(func,debug.traceback, kernel) + if not status then kernel.log("ModuRunErr: "..tostring(err), "WARN") end ::skip:: end end diff --git a/Build/etc/fstab b/Build/etc/fstab index 785148b..3c9538d 100755 --- a/Build/etc/fstab +++ b/Build/etc/fstab @@ -1,2 +1,3 @@ U $;/ -U devfs0000;/dev/ \ No newline at end of file +U devfs0000;/dev/ +U sysfs0000;/sys/ \ No newline at end of file diff --git a/Build/lib/globals/string b/Build/lib/modules/CC-Tweaked/modem.kmod similarity index 100% rename from Build/lib/globals/string rename to Build/lib/modules/CC-Tweaked/modem.kmod diff --git a/Build/lib/modules/CC-Tweaked/redstone.kmod b/Build/lib/modules/CC-Tweaked/redstone.kmod new file mode 100755 index 0000000..8380f50 --- /dev/null +++ b/Build/lib/modules/CC-Tweaked/redstone.kmod @@ -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) \ No newline at end of file diff --git a/Build/lib/modules/CC-Tweaked/tty.kmod b/Build/lib/modules/CC-Tweaked/tty.kmod new file mode 100755 index 0000000..0dac680 --- /dev/null +++ b/Build/lib/modules/CC-Tweaked/tty.kmod @@ -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) \ No newline at end of file diff --git a/Build/lib/modules/Hyperion/00_stdlib.kmod b/Build/lib/modules/Hyperion/00_stdlib.kmod index 1ec4e59..5ac1fe7 100755 --- a/Build/lib/modules/Hyperion/00_stdlib.kmod +++ b/Build/lib/modules/Hyperion/00_stdlib.kmod @@ -1,3 +1,5 @@ +local args={...} +local kernel=args[1] function string.hasSuffix(str, suffix) return string.sub(str, #suffix+1) == suffix end @@ -94,6 +96,62 @@ function table.hasVal(tabl, query) return false 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 output = "{" for i,v in pairs(table) do @@ -119,7 +177,7 @@ local function serialize(table) output=output.."false" end elseif type(v) == "function" then - output=output.."function() end" + output=output..tostring(v) else error("serialization of type \""..type(v).."\" is not supported") end @@ -134,4 +192,5 @@ local function serialize(table) return output end -table.serialize=serialize \ No newline at end of file +table.serialize=serialize +kernel.log("Loaded stdlib") \ No newline at end of file diff --git a/Build/lib/modules/Hyperion/05_userspace.kmod b/Build/lib/modules/Hyperion/05_userspace.kmod new file mode 100755 index 0000000..6190be4 --- /dev/null +++ b/Build/lib/modules/Hyperion/05_userspace.kmod @@ -0,0 +1,3 @@ +local args={...} +local kernel=args[1] +kernel._U=table.proxy(_G) \ No newline at end of file diff --git a/Build/lib/modules/Hyperion/10_vfs.kmod b/Build/lib/modules/Hyperion/10_vfs.kmod index 5c89c25..3137b82 100755 --- a/Build/lib/modules/Hyperion/10_vfs.kmod +++ b/Build/lib/modules/Hyperion/10_vfs.kmod @@ -1,217 +1,321 @@ 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 +-- ===================================================================== +-- INTERNAL STATE +-- ===================================================================== --- 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 +local disks = {} -- address → disk object +local mounts = {["/"] = "$"} -- mountpoint → disk address (root = boot disk) --- 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 NORMALIZATION +-- ===================================================================== - --- Path resolution local function splitPath(p) - local parts = {} - for part in p:gmatch("[^/]+") do parts[#parts+1] = part end - return parts + local t = {} + for part in p:gmatch("[^/]+") do t[#t+1] = part end + return t end -local function resolveSymlink(path) - path = normalizePath(path) - local symlinkDepth = 0 - local parts = splitPath(path) - local resolved = {} - local i = 1 +local function normalizePath(path) + if not path or path == "" then return "/" end - 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 + -- 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 - i=i+1 end - local finalPath="/"..table.concat(resolved,"/") - local disk,diskPath=resolvePath(finalPath) - return disk,diskPath + 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 --- PUBLIC API: MOUNTING -function fs.mount(disk, mountPoint) - if kernel.uid ~= 0 then error("Permission Denied") end - mounts[mountPoint]=disk + + +-- ===================================================================== +-- 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 -function fs.unmount(mountPoint) - if kernel.uid ~= 0 then error("Permission Denied") end - mounts[mountPoint]=nil + +local function readSymlinkRaw(disk, p) + local text = disk:readAllText(p) + if not text then return nil end + if text:sub(1, #SYMLINK_PREFIX) ~= SYMLINK_PREFIX then return nil end + + local t = text:sub(#SYMLINK_PREFIX + 1) + if t:sub(-1) == SYMLINK_SUFFIX then + t = t:sub(1, -2) + end + return t end + + +-- ===================================================================== +-- FULL PATH RESOLUTION (FOLLOWS SYMLINKS) +-- ===================================================================== + +local function resolveSymlink(path) + local abs = normalizePath(path) + local parts = splitPath(abs) + local out = {} + + local depth = 0 + local idx = 1 + + while idx <= #parts do + local comp = parts[idx] + + if comp == "." then + -- nothing + elseif comp == ".." then + if #out > 0 then table.remove(out) end + else + local curAbs = "/" .. table.concat(out, "/") + if curAbs ~= "/" then curAbs = curAbs .. "/" end + curAbs = curAbs .. comp + + local disk, dpath = resolveMount(curAbs) + + if isSymlinkRaw(disk, dpath) then + depth = depth + 1 + if depth > SYMLINK_MAX_DEPTH then + error("Too many symlink levels: " .. path) + end + + local target = readSymlinkRaw(disk, dpath) + if target then + local newAbs + + if target:sub(1,1) == "/" then + -- absolute target + newAbs = normalizePath(target) + else + -- relative to current out[] + local tmp = "/" .. table.concat(out, "/") + if tmp ~= "/" then tmp = tmp .. "/" end + tmp = tmp .. target + newAbs = normalizePath(tmp) + end + + -- rebuild remaining parts + local remaining = {} + for j = idx + 1, #parts do + remaining[#remaining+1] = parts[j] + end + + -- restart symlink resolution with new path + abs = newAbs + parts = splitPath(abs) + + -- append remaining + for _,x in ipairs(remaining) do parts[#parts+1] = x end + + out = {} + idx = 0 + else + out[#out+1] = comp + end + else + out[#out+1] = comp + end + end + + idx = idx + 1 + end + + local finalAbs = "/" .. table.concat(out, "/") + return resolveMount(finalAbs) +end + + + +-- ===================================================================== +-- PUBLIC API +-- ===================================================================== + +-- MOUNT OPERATIONS ----------------------------------------------------- + function fs.virtDisk(diskObj) if kernel.uid ~= 0 then error("Permission Denied") end - if disks[diskObj.address] then error("Disk exists") end - disks[diskObj.address]=diskObj + if disks[diskObj.address] then + error("Disk exists: " .. diskObj.address) + end + disks[diskObj.address] = diskObj end + +function fs.mount(disk, mountPoint) + if kernel.uid ~= 0 then error("Permission Denied") end + mountPoint = normalizePath(mountPoint) + + local drive, path = resolveMount(normalizePath(mountPoint)) + if not drive:directoryExists(path) then error("Must mount on folder") end + + if mountPoint ~= "/" and mounts[mountPoint] then + error("Already mounted: " .. mountPoint) + end + + mounts[mountPoint] = disk +end + +function fs.unmount(mountPoint) + if kernel.uid ~= 0 then error("Permission Denied") end + mountPoint = normalizePath(mountPoint) + + if mountPoint == "/" then error("Cannot unmount root") end + mounts[mountPoint] = nil +end + function fs.eject(addr) if kernel.uid ~= 0 then error("Permission Denied") end - disks[addr]=nil + disks[addr] = nil 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) - local disk, p = resolvePath(linkPath) - return disk:writeAllText(p, SYMLINK_PREFIX..target..SYMLINK_SUFFIX) + kernel.log("WARNING: Symlinks are a untested feature if you find any bugs please report them to https://git.astronand.dev/Hyperion/HyperionOS","WARN") + local disk, p = resolveMount(normalizePath(linkPath)) + return disk:writeAllText(p, SYMLINK_PREFIX .. target .. SYMLINK_SUFFIX) end + function fs.isLink(path) - local disk, p = resolvePath(path) - return isSymlink(disk,p) + local disk, p = resolveMount(normalizePath(path)) + return isSymlinkRaw(disk, p) end + function fs.readLink(path) - local disk, p = resolvePath(path) - return readSymlink(disk,p) + local disk, p = resolveMount(normalizePath(path)) + return readSymlinkRaw(disk, p) end --- FILE OPERATIONS -function fs.exists(path) + +-- FILE OPERATIONS ------------------------------------------------------ + +function fs.exists(path, ...) local disk, p = resolveSymlink(path) - return disk:fileExists(p) or disk:directoryExists(p) + return disk:fileExists(p, ...) or disk:directoryExists(p, ...) end -function fs.isFile(path) +function fs.isFile(path, ...) local disk, p = resolveSymlink(path) - if isSymlink(disk, p) then return false end - return disk:fileExists(p) + return disk:fileExists(p, ...) end -function fs.isDir(path) +function fs.isDir(path, ...) local disk, p = resolveSymlink(path) - if isSymlink(disk, p) then return false end - return disk:directoryExists(p) + return disk:directoryExists(p, ...) end -function fs.list(path) +function fs.list(path, ...) local disk, p = resolveSymlink(path) - return disk:list(p) + return disk:list(p, ...) end -function fs.makeDir(path) +function fs.makeDir(path, ...) local disk, p = resolveSymlink(path) - return disk:makeDirectory(p) + 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) +-- remove does NOT follow symlinks (UNIX semantics) +function fs.remove(path, ...) + if fs.isMount(path) then return "Cannot delete mounted folder" end + local abs = normalizePath(path) + local disk, p = resolveMount(abs) + return disk:remove(p, ...) end -function fs.readAllText(path) +function fs.readAllText(path, ...) local disk, p = resolveSymlink(path) - return disk:readAllText(p) + return disk:readAllText(p, ...) end -function fs.writeAllText(path, text) +function fs.writeAllText(path, text, ...) local disk, p = resolveSymlink(path) - return disk:writeAllText(p, text) + return disk:writeAllText(p, text, ...) end -function fs.appendAllText(path, text) +function fs.appendAllText(path, text, ...) local disk, p = resolveSymlink(path) - return disk:appendAllText(p, text) + return disk:appendAllText(p, text, ...) 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) - return disk:getSize(p) + 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 \ No newline at end of file +-- ===================================================================== + +kernel.log("Loading disks for vfs") +local ok,err = xpcall(function() + for _,v in kernel.initdisks.list() do + fs.virtDisk(v) + end +end, debug.traceback) +if not ok then kernel.panic(err) end + +kernel.disks=disks +kernel.mounts=mounts +kernel.fs = fs +kernel.cache.preload.fs = table.proxy(kernel.fs) +kernel.cache.preload.filesystem = kernel.cache.preload.fs \ No newline at end of file diff --git a/Build/lib/modules/Hyperion/11_mkvirtfs.kmod b/Build/lib/modules/Hyperion/11_mkvirtfs.kmod index 0aa0340..3ee6341 100755 --- a/Build/lib/modules/Hyperion/11_mkvirtfs.kmod +++ b/Build/lib/modules/Hyperion/11_mkvirtfs.kmod @@ -1,6 +1,5 @@ -local args={...} -local kernel=args[1] - +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 = {} @@ -55,34 +54,36 @@ function kernel.fs.mkvirtfs(address, readOnly, label, autoRegister) -- File IO (supports string or file-object with read/write funcs) ----------------------------------------------------------------- - local function fileRead(node) + 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() + return node.read(...) end return nil end - local function fileWrite(parent, name, text) + local function fileWrite(parent, name, text, ...) local node = parent[name] if type(node) == "string" then + local ok, err = ensureWrite(); if not ok then return false, err end parent[name] = text return true elseif type(node) == "table" and node.__file and node.write then - return node.write(text) + return node.write(text, ...) end parent[name] = text return true end - local function fileAppend(parent, name, text) + local function fileAppend(parent, name, text, ...) local node = parent[name] if type(node) == "string" then + local ok, err = ensureWrite(); if not ok then return false, err end parent[name] = node .. text return true elseif type(node) == "table" and node.__file and node.write then - return node.write((node.read() or "") .. text) + return node.write((node.read() or "") .. text, ...) end parent[name] = text return true @@ -96,26 +97,22 @@ function kernel.fs.mkvirtfs(address, readOnly, label, autoRegister) function disk:spaceUsed() return 0 end function disk:spaceTotal() return 0 end - function disk:readAllText(path) + function disk:readAllText(path, ...) local node = getNode(path) if not node then return nil, "file not found" end - return fileRead(node) + return fileRead(node, ...) end - function disk:writeAllText(path, text) - local ok, err = ensureWrite(); if not ok then return false, err end - + function disk:writeAllText(path, text, ...) local parent, name = getParent(path) if not parent or not parent.__dir then return false, "invalid directory" end - return fileWrite(parent, name, tostring(text)) + return fileWrite(parent, name, tostring(text), ...) end - function disk:appendAllText(path, text) - local ok, err = ensureWrite(); if not ok then return false, err end - + function disk:appendAllText(path, text, ...) local parent, name = getParent(path) if not parent or not parent.__dir then return false, "invalid directory" end - return fileAppend(parent, name, tostring(text)) + return fileAppend(parent, name, tostring(text), ...) end function disk:list(path) @@ -161,11 +158,11 @@ function kernel.fs.mkvirtfs(address, readOnly, label, autoRegister) return label end - function disk:size(path) + 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() + local v = node.read(...) return v and #v or 0 end return 0 @@ -174,7 +171,7 @@ function kernel.fs.mkvirtfs(address, readOnly, label, autoRegister) ----------------------------------------------------------------- -- 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) end diff --git a/Build/lib/modules/Hyperion/11_require.kmod b/Build/lib/modules/Hyperion/11_require.kmod index c22cf4d..60eaaeb 100755 --- a/Build/lib/modules/Hyperion/11_require.kmod +++ b/Build/lib/modules/Hyperion/11_require.kmod @@ -1,6 +1,5 @@ local args = {...} local kernel = args[1] - -- List of search paths local paths = { "/lib/?", @@ -11,7 +10,7 @@ local paths = { -- Custom require implementation function require(module) -- 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] end @@ -53,4 +52,5 @@ function require(module) -- If nothing worked, raise an error with all reasons error("Unable to require module '" .. module .. "':\n" .. table.concat(err, "\n")) -end \ No newline at end of file +end +kernel.log("Created require") \ No newline at end of file diff --git a/Build/lib/modules/Hyperion/12_devfs.kmod b/Build/lib/modules/Hyperion/12_devfs.kmod index 87ac661..aea0a51 100755 --- a/Build/lib/modules/Hyperion/12_devfs.kmod +++ b/Build/lib/modules/Hyperion/12_devfs.kmod @@ -1,7 +1,9 @@ -local args={...} +local args = {...} local kernel = args[1] - -local data = kernel.fs.mkvirtfs("devfs0000", true, "devfs", false) +local data = kernel.fs.mkvirtfs("devfs0000", true, "devfs", true) +if not kernel.fs.isDir("/dev") then kernel.fs.makeDir("/dev") end +kernel.devfs={} +kernel.devfs.data=data data["/"]["OSVERSION"]="Hyperion 1.0.0" data["/"]["eeprom"]={ @@ -14,4 +16,42 @@ data["/"]["eeprom"]={ kernel.computer:setEEPROM(text) end } +data["/"]["null"]={ + __file=true, + read=function() end, + write=function() end +} +data["/"]["random"]={ + __file=true, + read=function(amount) + local s = "" + for i = 1, amount do + s = s .. string.char(math.random(0, 255)) + end + return s + end, + write=function() end +} +data["/"]["zero"]={ + __file=true, + read=function(amount) + return ("\0"):rep(amount) + end, + write=function() end +} +data["/"]["rtc0"]={ + __file=true, + read=function() + return kernel.computer:time() + end, + write=function() end +} +data["/"]["rtc"]={ + __file=true, + read=function() + return kernel.computer:time() + end, + write=function() end +} +kernel.log("Created devfs") \ No newline at end of file diff --git a/Build/lib/modules/Hyperion/12_sysfs.kmod b/Build/lib/modules/Hyperion/12_sysfs.kmod new file mode 100755 index 0000000..cbee3df --- /dev/null +++ b/Build/lib/modules/Hyperion/12_sysfs.kmod @@ -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") \ No newline at end of file diff --git a/Build/lib/globals/table b/Build/lib/modules/Hyperion/13_procfs.kmod similarity index 100% rename from Build/lib/globals/table rename to Build/lib/modules/Hyperion/13_procfs.kmod diff --git a/Build/lib/modules/Hyperion/11_fstabInit.kmod b/Build/lib/modules/Hyperion/15_fstabInit.kmod similarity index 58% rename from Build/lib/modules/Hyperion/11_fstabInit.kmod rename to Build/lib/modules/Hyperion/15_fstabInit.kmod index 64456fd..f8a5c85 100755 --- a/Build/lib/modules/Hyperion/11_fstabInit.kmod +++ b/Build/lib/modules/Hyperion/15_fstabInit.kmod @@ -1,11 +1,11 @@ -local args={...} -local kernel=args[1] +local args = {...} +local kernel = args[1] local ifs=kernel.ifs -local initdisks=kernel.initdisks +kernel.log("Mounting fstab") local fstab=ifs.readAllText("/etc/fstab") -kernel.fs.update(initdisks) -for i,v in ipairs(string.split(fstab,"\n")) do +local entrys = string.split(fstab,"\n") +for i,v in ipairs(entrys) do if v:sub(1,1)=="U" then local id="" for i=3,#v do @@ -14,9 +14,13 @@ for i,v in ipairs(string.split(fstab,"\n")) do id=v:sub(3,i-1) 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.fs.mount(id,path) ::endline:: end -end \ No newline at end of file +end +kernel.log("Mounted all disks") \ No newline at end of file diff --git a/Build/lib/modules/Hyperion/20_keventd.kmod b/Build/lib/modules/Hyperion/20_keventd.kmod index 9f47b9e..9c55cca 100755 --- a/Build/lib/modules/Hyperion/20_keventd.kmod +++ b/Build/lib/modules/Hyperion/20_keventd.kmod @@ -1,5 +1,5 @@ -local args={...} -local kernel=args[1] +local args = {...} +local kernel = args[1] kernel.drivers.processes[#kernel.drivers.processes+1]=function() while true do local event={kernel.computer:getMachineEvent()} @@ -9,4 +9,5 @@ kernel.drivers.processes[#kernel.drivers.processes+1]=function() end coroutine.yield() end -end \ No newline at end of file +end +kernel.log("Created keventd daemon") \ No newline at end of file diff --git a/Build/lib/modules/Hyperion/30_thirdParty.kmod b/Build/lib/modules/Hyperion/30_thirdParty.kmod index b0e6ff6..47b635f 100644 --- a/Build/lib/modules/Hyperion/30_thirdParty.kmod +++ b/Build/lib/modules/Hyperion/30_thirdParty.kmod @@ -1,17 +1,20 @@ -local args={...} -local kernel=args[2] - +local args = {...} +local kernel = args[1] +kernel.log("Loading third party drivers") 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") + if kernel.fs.isDir("/lib/modules/"..subf) then + if subf~="Hyperion" then + 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 func, err = load(code, "@"..driver) + if not func then + kernel.log("DriverCompileErr: "..tostring(err), "ERROR") + else + local ok, err = xpcall(func, debug.traceback, table.unpack(args)) + if not ok then + kernel.log("DriverExecErr: "..tostring(err), "ERROR") + end end end end diff --git a/Build/lib/modules/Hyperion/31_thirdPartyInit.kmod b/Build/lib/modules/Hyperion/31_thirdPartyInit.kmod index c98ec23..5143c77 100755 --- a/Build/lib/modules/Hyperion/31_thirdPartyInit.kmod +++ b/Build/lib/modules/Hyperion/31_thirdPartyInit.kmod @@ -1,11 +1,14 @@ -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 +local args = {...} +local kernel = args[1] +kernel.log("initializing third party drivers") +for _,v in ipairs(kernel.drivers.raw) do + if v.arch==kernel.arch then + if v.load then + kernel.log("Loading "..v.name) + local ok,err = xpcall(v.load, debug.traceback) + if not ok then + kernel.log("DriverLoadErr: "..tostring(err)) + end end end -end \ No newline at end of file +end diff --git a/Test/Hyperion-core-v0.1.0/lib/globals/string b/Build/lib/modules/Hyperion/50_mutiUserAuth.kmod similarity index 100% rename from Test/Hyperion-core-v0.1.0/lib/globals/string rename to Build/lib/modules/Hyperion/50_mutiUserAuth.kmod diff --git a/Build/lib/modules/Hyperion/99_init.kmod b/Build/lib/modules/Hyperion/99_init.kmod index 03361ef..b810db8 100755 --- a/Build/lib/modules/Hyperion/99_init.kmod +++ b/Build/lib/modules/Hyperion/99_init.kmod @@ -1,17 +1,25 @@ -local args={...} +local args = {...} local kernel = args[1] local tasks={} local currentTask={} local signals={} -local tid=1 -local gid=1 +local tid=2 +local gid=2 +local hookuuid=0 local sys={} function sys.hookSig(sig, func) - if not signals[tostring(currentTask.pid)][sig] then - signals[tostring(currentTask.pid)][sig]={} + if not currentTask.signal[sig] then + currentTask.signal[sig]={} 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 function sys.clearSigHooks(typ) @@ -27,7 +35,7 @@ end function sys.sendSig(pid, signal, ...) if pid=="all" then - for i,v in pairs(tasks) do + for i,v in pairs(tasks) do+ v.sigQ[#v.sigQ+1]={signal, ...} end return @@ -38,31 +46,35 @@ function sys.sendSig(pid, signal, ...) 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 + local sigs = {} + for i,v in ipairs(currentTask.sigQ) do + sigs[i]=v + end + for i=1, #sigs do + local sig = sigs[i] + if currentTask.signal[sig[1]] then + for k,v in pairs(currentTask.signal[sig[1]]) do coroutine.resumeWithTimeout(coroutine.create(function() - local ok, err = xpcall(v, debug.traceback, table.unpack(table.remove(currentTask.sigQ, 1))) - if not ok then - table.insert(ret, err) + local ok,err = xpcall(v,debug.traceback,table.unpack(sig)) + if not ok and sig[1]~="callbackErr" then + sys.sendSig(currentTask.pid, "callbackErr", sig[1], k, err) end - end), 10) + end),10) end else - for _,v in ipairs(currentTask.signal["unhandledEvent"]) do + for k,v in pairs(currentTask.signal["unhandledSignal"]) 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) + local ok,err = xpcall(v,debug.traceback,table.unpack(sig)) + if not ok and sig[1]~="callbackErr" then + sys.sendSig(currentTask.pid, "callbackErr", sig[1], k, err) end - end), 10) + end),10) end end end end -function sys.spawn(func, name, evars, args) +function sys.spawn(func, name, evars, args, stdin, stdout, stderr) local id=tid tid=tid+1 name=name or tostring(id) @@ -89,6 +101,7 @@ function sys.spawn(func, name, evars, args) vy=0, ivy=0, status="R", + sleep=0, signal=signals[tostring(id)], parent=currentTask, children={}, @@ -97,6 +110,12 @@ function sys.spawn(func, name, evars, args) } end +function sys.exit(...) + sys.sendSig(currentTask.ppid, "ChildTaskExit", currentTask.pid, ...) + currentTask.status="Z" + coroutine.yield() +end + local function collectZombieProc() local ret = {} for _,v in pairs(tasks) do @@ -116,13 +135,23 @@ local function collectZombieProc() return ret end +kernel.log("initPath is: " .. tostring(kernel.initPath)) signals["1"]={} tasks["1"]={ 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 + currentTask.status="Z" kernel.panic(err) else + currentTask.status="Z" kernel.panic("Attempted to kill init!") end end), @@ -130,27 +159,38 @@ tasks["1"]={ pid=1, ppid=0, tgid=1, - user=kernel.user, - uid=kernel.uid, + user="root", + uid=0, evars={}, args={kernel}, vy=0, ivy=0, status="R", + sleep=0, signal=signals["1"], parent={name="Hyprkrnl",pid=0}, children={}, sibling={}, sigQ={} } -kernel.chache.preload.sys=sys -kernel.chache.preload.system=sys +tasks["1"].sibling={tasks["1"]} + +kernel.log("Created pid 1") +kernel.cache.preload.sys=table.proxy(sys) +kernel.cache.preload.system=kernel.cache.preload.sys +kernel.cache.preload.os=kernel.cache.preload.sys kernel.hpv=sys +kernel.tasks=tasks +kernel.signals=signals +kernel.currentTask=currentTask kernel.saveLog() -while true do - for _,v in pairs(tasks) do +kernel.status="running" +while kernel.status~="Panic" do + for k,v in pairs(tasks) do currentTask=v + kernel.currentTask=v + kernel.process=currentTask.name kernel.user=currentTask.user kernel.uid=currentTask.uid sys.flushSigs() @@ -164,4 +204,7 @@ while true do collectZombieProc() end -kernel.panic("Exited pid 0") \ No newline at end of file +kernel.process="Kernel" +kernel.user="root" +kernel.uid=0 +kernel.panic(kernel.reason or "Exited pid 0") \ No newline at end of file diff --git a/Build/lib/modules/cct-tto.kmod b/Build/lib/modules/cct-tto.kmod deleted file mode 100755 index 2b0bcd8..0000000 --- a/Build/lib/modules/cct-tto.kmod +++ /dev/null @@ -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) \ No newline at end of file diff --git a/Build/sbin/init b/Build/sbin/init index 3954941..b5a6d33 100755 --- a/Build/sbin/init +++ b/Build/sbin/init @@ -1,8 +1,3 @@ local args={...} local kernel=args[1] - -kernel.panic("text") - -for i,v in ipairs(kernel.fs.list("/dev")) do - kernl.log(v) -end \ No newline at end of file +kernel.fs.load("/bin/bash")() \ No newline at end of file diff --git a/Test/Hyperion-core-v0.1.0/etc/fstab b/Test/Hyperion-core-v0.1.0/etc/fstab index 785148b..3c9538d 100755 --- a/Test/Hyperion-core-v0.1.0/etc/fstab +++ b/Test/Hyperion-core-v0.1.0/etc/fstab @@ -1,2 +1,3 @@ U $;/ -U devfs0000;/dev/ \ No newline at end of file +U devfs0000;/dev/ +U sysfs0000;/sys/ \ No newline at end of file diff --git a/Test/Hyperion-core-v0.1.0/sbin/init b/Test/Hyperion-core-v0.1.0/sbin/init index 3954941..b5a6d33 100755 --- a/Test/Hyperion-core-v0.1.0/sbin/init +++ b/Test/Hyperion-core-v0.1.0/sbin/init @@ -1,8 +1,3 @@ local args={...} local kernel=args[1] - -kernel.panic("text") - -for i,v in ipairs(kernel.fs.list("/dev")) do - kernl.log(v) -end \ No newline at end of file +kernel.fs.load("/bin/bash")() \ No newline at end of file diff --git a/Test/Hyperion-core-v0.1.0/lib/globals/table b/Test/Hyperion-firmware-cct-v0.1.0/lib/modules/CC-Tweaked/modem.kmod similarity index 100% rename from Test/Hyperion-core-v0.1.0/lib/globals/table rename to Test/Hyperion-firmware-cct-v0.1.0/lib/modules/CC-Tweaked/modem.kmod diff --git a/Test/Hyperion-firmware-cct-v0.1.0/lib/modules/CC-Tweaked/redstone.kmod b/Test/Hyperion-firmware-cct-v0.1.0/lib/modules/CC-Tweaked/redstone.kmod new file mode 100755 index 0000000..8380f50 --- /dev/null +++ b/Test/Hyperion-firmware-cct-v0.1.0/lib/modules/CC-Tweaked/redstone.kmod @@ -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) \ No newline at end of file diff --git a/Test/Hyperion-firmware-cct-v0.1.0/lib/modules/CC-Tweaked/tty.kmod b/Test/Hyperion-firmware-cct-v0.1.0/lib/modules/CC-Tweaked/tty.kmod new file mode 100755 index 0000000..0dac680 --- /dev/null +++ b/Test/Hyperion-firmware-cct-v0.1.0/lib/modules/CC-Tweaked/tty.kmod @@ -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) \ No newline at end of file diff --git a/Test/Hyperion-firmware-cct-v0.1.0/lib/modules/cct-tto.kmod b/Test/Hyperion-firmware-cct-v0.1.0/lib/modules/cct-tto.kmod deleted file mode 100755 index 2b0bcd8..0000000 --- a/Test/Hyperion-firmware-cct-v0.1.0/lib/modules/cct-tto.kmod +++ /dev/null @@ -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) \ No newline at end of file diff --git a/Test/Hyperion-kernel-v0.1.0/boot/kernel.lua b/Test/Hyperion-kernel-v0.1.0/boot/kernel.lua index c488614..e646db3 100755 --- a/Test/Hyperion-kernel-v0.1.0/boot/kernel.lua +++ b/Test/Hyperion-kernel-v0.1.0/boot/kernel.lua @@ -14,29 +14,34 @@ kernel.group = "root" kernel.groups = {0} kernel.uid = 0 kernel.gid = 0 -kernel.stage = "start" +kernel.status = "start" kernel.key = {} -kernel.chache = {} -kernel.chache.preload = {} +kernel.cache = {} +kernel.cache.preload = {} +kernel._G=_G local windowsExp = false function kernel.log(msg, level) LOG_Text = LOG_Text..tostring(computer.time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n" - if kernel.stage == "start" then + if kernel.status == "start" then screen:print(tostring(computer.time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg) end end function kernel.PANIC(msg) - kernel.log("PANIC: "..msg, "PANIC") - pcall(kernel["saveLog"]) - screen:setTextColor(2) - screen:setBackgroundColor(0) - screen:clear() - screen:setCursorPos(1,1) - screen:print(LOG_Text) - screen:print("KERNEL PANIC!\n"..msg.."\nSystem halted.") - screen:print("Press any key to continue...") + if kernel.status~="Panic" then + kernel.log("PANIC: "..msg, "PANIC") + pcall(kernel["saveLog"]) + kernel.status="Panic" + kernel.reason=msg + screen:setTextColor(2) + screen:setBackgroundColor(0) + screen:clear() + screen:setCursorPos(1,1) + screen:print(LOG_Text) + screen:print("KERNEL PANIC!\n"..msg.."\nSystem halted.") + screen:print("Press any key to continue...") + end while true do local event={computer:getMachineEvent()} if event[1]=="keyPressed" then @@ -65,16 +70,12 @@ if windowsExp then while true do end end -kernel.log("Kernel loaded.", "INFO") -kernel.log("Mounting disks...", "INFO") +kernel.log("Kernel loaded.") +kernel.log("Mounting init disks...") disks.refresh() ifs.update(disks) ifs.mount("$", "/") -function kernel.saveLog() - ifs.writeAllText("/var/log/syslog.log", LOG_Text) -end - local fstab=ifs.readAllText("/etc/fstab") local split = function(str, delim, maxResultCountOrNil) assert(#delim == 1, "only delim len 1 supported for now") @@ -104,11 +105,15 @@ for i,v in ipairs(split(fstab,"\n")) do end end local path=v:sub(#id+4) - kernel.log("Mounted "..id.." to "..path) ifs.mount(id,path) ::endline:: end end +kernel.log("Disks initialized") + +function kernel.saveLog() + ifs.writeAllText("/var/log/syslog.log", LOG_Text) +end ifs.remove("/tmp") ifs.makeDir("/tmp") @@ -116,29 +121,24 @@ ifs.makeDir("/tmp") local drivers={} drivers.raw={} drivers.processes={} -drivers.prior={} drivers.type={} -for i=0, 99 do - drivers.prior[i]={} -end -function drivers.register(prior,object) +function drivers.register(object) drivers.raw[#drivers.raw+1]=object if object.main then drivers.processes[#drivers.processes+1]=object.main end - if drivers.prior[prior]==nil then drivers.prior[prior]={} end - drivers.prior[prior][#drivers.prior[prior]+1]=object if drivers.type[object.type]==nil then drivers.type[object.type]={} end drivers.type[object.type][#drivers.type[object.type]+1]=object end -local modules={} -for i=0, 99 do +local modules={[0]={}} +for i=0, 100 do modules[i]={} end +kernel.log("Gathering modules") for i,v in ipairs(ifs.list("/lib/modules/Hyperion/")) do local prior=tonumber(v:sub(1,2)) - modules[prior][#modules[prior]+1]="/lib/modules/Hyperion/"..v + modules[prior+1][#modules[prior+1]+1]="/lib/modules/Hyperion/"..v end kernel.drivers=drivers @@ -147,19 +147,17 @@ kernel.apis=apis kernel.computer=computer kernel.initPath=initPath kernel.arch=arch -kernel.initdisks=initdisks +kernel.initdisks=disks kernel.screen=screen + +kernel.log("Running modules") for _,p in ipairs(modules) do for _,v in ipairs(p) do local code=ifs.readAllText(v) local func,err=load(code,"@"..v) - if not func then kernel.log("ModuLoadErr: "..tostring(err)) goto skip end - local status, err = xpcall(func,debug.traceback,kernel) - if not status then goto skip end - if not err then goto skip end - if not err.init then goto skip end - local ok, err = xpcall(status.main,debug.traceback) - if not ok then kernel.log("ModuInitErr: "..tostring(err)) end + if not func then kernel.log("ModuLoadErr: "..tostring(err), "WARN") goto skip end + local status, err = xpcall(func,debug.traceback, kernel) + if not status then kernel.log("ModuRunErr: "..tostring(err), "WARN") end ::skip:: end end diff --git a/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/00_stdlib.kmod b/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/00_stdlib.kmod index 1ec4e59..5ac1fe7 100755 --- a/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/00_stdlib.kmod +++ b/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/00_stdlib.kmod @@ -1,3 +1,5 @@ +local args={...} +local kernel=args[1] function string.hasSuffix(str, suffix) return string.sub(str, #suffix+1) == suffix end @@ -94,6 +96,62 @@ function table.hasVal(tabl, query) return false 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 output = "{" for i,v in pairs(table) do @@ -119,7 +177,7 @@ local function serialize(table) output=output.."false" end elseif type(v) == "function" then - output=output.."function() end" + output=output..tostring(v) else error("serialization of type \""..type(v).."\" is not supported") end @@ -134,4 +192,5 @@ local function serialize(table) return output end -table.serialize=serialize \ No newline at end of file +table.serialize=serialize +kernel.log("Loaded stdlib") \ No newline at end of file diff --git a/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/05_userspace.kmod b/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/05_userspace.kmod new file mode 100755 index 0000000..6190be4 --- /dev/null +++ b/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/05_userspace.kmod @@ -0,0 +1,3 @@ +local args={...} +local kernel=args[1] +kernel._U=table.proxy(_G) \ No newline at end of file diff --git a/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/10_vfs.kmod b/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/10_vfs.kmod index 5c89c25..3137b82 100755 --- a/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/10_vfs.kmod +++ b/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/10_vfs.kmod @@ -1,217 +1,321 @@ 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 +-- ===================================================================== +-- INTERNAL STATE +-- ===================================================================== --- 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 +local disks = {} -- address → disk object +local mounts = {["/"] = "$"} -- mountpoint → disk address (root = boot disk) --- 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 NORMALIZATION +-- ===================================================================== - --- Path resolution local function splitPath(p) - local parts = {} - for part in p:gmatch("[^/]+") do parts[#parts+1] = part end - return parts + local t = {} + for part in p:gmatch("[^/]+") do t[#t+1] = part end + return t end -local function resolveSymlink(path) - path = normalizePath(path) - local symlinkDepth = 0 - local parts = splitPath(path) - local resolved = {} - local i = 1 +local function normalizePath(path) + if not path or path == "" then return "/" end - 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 + -- 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 - i=i+1 end - local finalPath="/"..table.concat(resolved,"/") - local disk,diskPath=resolvePath(finalPath) - return disk,diskPath + 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 --- PUBLIC API: MOUNTING -function fs.mount(disk, mountPoint) - if kernel.uid ~= 0 then error("Permission Denied") end - mounts[mountPoint]=disk + + +-- ===================================================================== +-- 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 -function fs.unmount(mountPoint) - if kernel.uid ~= 0 then error("Permission Denied") end - mounts[mountPoint]=nil + +local function readSymlinkRaw(disk, p) + local text = disk:readAllText(p) + if not text then return nil end + if text:sub(1, #SYMLINK_PREFIX) ~= SYMLINK_PREFIX then return nil end + + local t = text:sub(#SYMLINK_PREFIX + 1) + if t:sub(-1) == SYMLINK_SUFFIX then + t = t:sub(1, -2) + end + return t end + + +-- ===================================================================== +-- FULL PATH RESOLUTION (FOLLOWS SYMLINKS) +-- ===================================================================== + +local function resolveSymlink(path) + local abs = normalizePath(path) + local parts = splitPath(abs) + local out = {} + + local depth = 0 + local idx = 1 + + while idx <= #parts do + local comp = parts[idx] + + if comp == "." then + -- nothing + elseif comp == ".." then + if #out > 0 then table.remove(out) end + else + local curAbs = "/" .. table.concat(out, "/") + if curAbs ~= "/" then curAbs = curAbs .. "/" end + curAbs = curAbs .. comp + + local disk, dpath = resolveMount(curAbs) + + if isSymlinkRaw(disk, dpath) then + depth = depth + 1 + if depth > SYMLINK_MAX_DEPTH then + error("Too many symlink levels: " .. path) + end + + local target = readSymlinkRaw(disk, dpath) + if target then + local newAbs + + if target:sub(1,1) == "/" then + -- absolute target + newAbs = normalizePath(target) + else + -- relative to current out[] + local tmp = "/" .. table.concat(out, "/") + if tmp ~= "/" then tmp = tmp .. "/" end + tmp = tmp .. target + newAbs = normalizePath(tmp) + end + + -- rebuild remaining parts + local remaining = {} + for j = idx + 1, #parts do + remaining[#remaining+1] = parts[j] + end + + -- restart symlink resolution with new path + abs = newAbs + parts = splitPath(abs) + + -- append remaining + for _,x in ipairs(remaining) do parts[#parts+1] = x end + + out = {} + idx = 0 + else + out[#out+1] = comp + end + else + out[#out+1] = comp + end + end + + idx = idx + 1 + end + + local finalAbs = "/" .. table.concat(out, "/") + return resolveMount(finalAbs) +end + + + +-- ===================================================================== +-- PUBLIC API +-- ===================================================================== + +-- MOUNT OPERATIONS ----------------------------------------------------- + function fs.virtDisk(diskObj) if kernel.uid ~= 0 then error("Permission Denied") end - if disks[diskObj.address] then error("Disk exists") end - disks[diskObj.address]=diskObj + if disks[diskObj.address] then + error("Disk exists: " .. diskObj.address) + end + disks[diskObj.address] = diskObj end + +function fs.mount(disk, mountPoint) + if kernel.uid ~= 0 then error("Permission Denied") end + mountPoint = normalizePath(mountPoint) + + local drive, path = resolveMount(normalizePath(mountPoint)) + if not drive:directoryExists(path) then error("Must mount on folder") end + + if mountPoint ~= "/" and mounts[mountPoint] then + error("Already mounted: " .. mountPoint) + end + + mounts[mountPoint] = disk +end + +function fs.unmount(mountPoint) + if kernel.uid ~= 0 then error("Permission Denied") end + mountPoint = normalizePath(mountPoint) + + if mountPoint == "/" then error("Cannot unmount root") end + mounts[mountPoint] = nil +end + function fs.eject(addr) if kernel.uid ~= 0 then error("Permission Denied") end - disks[addr]=nil + disks[addr] = nil 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) - local disk, p = resolvePath(linkPath) - return disk:writeAllText(p, SYMLINK_PREFIX..target..SYMLINK_SUFFIX) + kernel.log("WARNING: Symlinks are a untested feature if you find any bugs please report them to https://git.astronand.dev/Hyperion/HyperionOS","WARN") + local disk, p = resolveMount(normalizePath(linkPath)) + return disk:writeAllText(p, SYMLINK_PREFIX .. target .. SYMLINK_SUFFIX) end + function fs.isLink(path) - local disk, p = resolvePath(path) - return isSymlink(disk,p) + local disk, p = resolveMount(normalizePath(path)) + return isSymlinkRaw(disk, p) end + function fs.readLink(path) - local disk, p = resolvePath(path) - return readSymlink(disk,p) + local disk, p = resolveMount(normalizePath(path)) + return readSymlinkRaw(disk, p) end --- FILE OPERATIONS -function fs.exists(path) + +-- FILE OPERATIONS ------------------------------------------------------ + +function fs.exists(path, ...) local disk, p = resolveSymlink(path) - return disk:fileExists(p) or disk:directoryExists(p) + return disk:fileExists(p, ...) or disk:directoryExists(p, ...) end -function fs.isFile(path) +function fs.isFile(path, ...) local disk, p = resolveSymlink(path) - if isSymlink(disk, p) then return false end - return disk:fileExists(p) + return disk:fileExists(p, ...) end -function fs.isDir(path) +function fs.isDir(path, ...) local disk, p = resolveSymlink(path) - if isSymlink(disk, p) then return false end - return disk:directoryExists(p) + return disk:directoryExists(p, ...) end -function fs.list(path) +function fs.list(path, ...) local disk, p = resolveSymlink(path) - return disk:list(p) + return disk:list(p, ...) end -function fs.makeDir(path) +function fs.makeDir(path, ...) local disk, p = resolveSymlink(path) - return disk:makeDirectory(p) + 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) +-- remove does NOT follow symlinks (UNIX semantics) +function fs.remove(path, ...) + if fs.isMount(path) then return "Cannot delete mounted folder" end + local abs = normalizePath(path) + local disk, p = resolveMount(abs) + return disk:remove(p, ...) end -function fs.readAllText(path) +function fs.readAllText(path, ...) local disk, p = resolveSymlink(path) - return disk:readAllText(p) + return disk:readAllText(p, ...) end -function fs.writeAllText(path, text) +function fs.writeAllText(path, text, ...) local disk, p = resolveSymlink(path) - return disk:writeAllText(p, text) + return disk:writeAllText(p, text, ...) end -function fs.appendAllText(path, text) +function fs.appendAllText(path, text, ...) local disk, p = resolveSymlink(path) - return disk:appendAllText(p, text) + return disk:appendAllText(p, text, ...) 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) - return disk:getSize(p) + 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 \ No newline at end of file +-- ===================================================================== + +kernel.log("Loading disks for vfs") +local ok,err = xpcall(function() + for _,v in kernel.initdisks.list() do + fs.virtDisk(v) + end +end, debug.traceback) +if not ok then kernel.panic(err) end + +kernel.disks=disks +kernel.mounts=mounts +kernel.fs = fs +kernel.cache.preload.fs = table.proxy(kernel.fs) +kernel.cache.preload.filesystem = kernel.cache.preload.fs \ No newline at end of file diff --git a/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/11_mkvirtfs.kmod b/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/11_mkvirtfs.kmod index 0aa0340..3ee6341 100755 --- a/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/11_mkvirtfs.kmod +++ b/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/11_mkvirtfs.kmod @@ -1,6 +1,5 @@ -local args={...} -local kernel=args[1] - +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 = {} @@ -55,34 +54,36 @@ function kernel.fs.mkvirtfs(address, readOnly, label, autoRegister) -- File IO (supports string or file-object with read/write funcs) ----------------------------------------------------------------- - local function fileRead(node) + 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() + return node.read(...) end return nil end - local function fileWrite(parent, name, text) + local function fileWrite(parent, name, text, ...) local node = parent[name] if type(node) == "string" then + local ok, err = ensureWrite(); if not ok then return false, err end parent[name] = text return true elseif type(node) == "table" and node.__file and node.write then - return node.write(text) + return node.write(text, ...) end parent[name] = text return true end - local function fileAppend(parent, name, text) + local function fileAppend(parent, name, text, ...) local node = parent[name] if type(node) == "string" then + local ok, err = ensureWrite(); if not ok then return false, err end parent[name] = node .. text return true elseif type(node) == "table" and node.__file and node.write then - return node.write((node.read() or "") .. text) + return node.write((node.read() or "") .. text, ...) end parent[name] = text return true @@ -96,26 +97,22 @@ function kernel.fs.mkvirtfs(address, readOnly, label, autoRegister) function disk:spaceUsed() return 0 end function disk:spaceTotal() return 0 end - function disk:readAllText(path) + function disk:readAllText(path, ...) local node = getNode(path) if not node then return nil, "file not found" end - return fileRead(node) + return fileRead(node, ...) end - function disk:writeAllText(path, text) - local ok, err = ensureWrite(); if not ok then return false, err end - + function disk:writeAllText(path, text, ...) local parent, name = getParent(path) if not parent or not parent.__dir then return false, "invalid directory" end - return fileWrite(parent, name, tostring(text)) + return fileWrite(parent, name, tostring(text), ...) end - function disk:appendAllText(path, text) - local ok, err = ensureWrite(); if not ok then return false, err end - + function disk:appendAllText(path, text, ...) local parent, name = getParent(path) if not parent or not parent.__dir then return false, "invalid directory" end - return fileAppend(parent, name, tostring(text)) + return fileAppend(parent, name, tostring(text), ...) end function disk:list(path) @@ -161,11 +158,11 @@ function kernel.fs.mkvirtfs(address, readOnly, label, autoRegister) return label end - function disk:size(path) + 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() + local v = node.read(...) return v and #v or 0 end return 0 @@ -174,7 +171,7 @@ function kernel.fs.mkvirtfs(address, readOnly, label, autoRegister) ----------------------------------------------------------------- -- 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) end diff --git a/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/11_require.kmod b/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/11_require.kmod index c22cf4d..60eaaeb 100755 --- a/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/11_require.kmod +++ b/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/11_require.kmod @@ -1,6 +1,5 @@ local args = {...} local kernel = args[1] - -- List of search paths local paths = { "/lib/?", @@ -11,7 +10,7 @@ local paths = { -- Custom require implementation function require(module) -- 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] end @@ -53,4 +52,5 @@ function require(module) -- If nothing worked, raise an error with all reasons error("Unable to require module '" .. module .. "':\n" .. table.concat(err, "\n")) -end \ No newline at end of file +end +kernel.log("Created require") \ No newline at end of file diff --git a/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/12_devfs.kmod b/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/12_devfs.kmod index 87ac661..aea0a51 100755 --- a/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/12_devfs.kmod +++ b/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/12_devfs.kmod @@ -1,7 +1,9 @@ -local args={...} +local args = {...} local kernel = args[1] - -local data = kernel.fs.mkvirtfs("devfs0000", true, "devfs", false) +local data = kernel.fs.mkvirtfs("devfs0000", true, "devfs", true) +if not kernel.fs.isDir("/dev") then kernel.fs.makeDir("/dev") end +kernel.devfs={} +kernel.devfs.data=data data["/"]["OSVERSION"]="Hyperion 1.0.0" data["/"]["eeprom"]={ @@ -14,4 +16,42 @@ data["/"]["eeprom"]={ kernel.computer:setEEPROM(text) end } +data["/"]["null"]={ + __file=true, + read=function() end, + write=function() end +} +data["/"]["random"]={ + __file=true, + read=function(amount) + local s = "" + for i = 1, amount do + s = s .. string.char(math.random(0, 255)) + end + return s + end, + write=function() end +} +data["/"]["zero"]={ + __file=true, + read=function(amount) + return ("\0"):rep(amount) + end, + write=function() end +} +data["/"]["rtc0"]={ + __file=true, + read=function() + return kernel.computer:time() + end, + write=function() end +} +data["/"]["rtc"]={ + __file=true, + read=function() + return kernel.computer:time() + end, + write=function() end +} +kernel.log("Created devfs") \ No newline at end of file diff --git a/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/12_sysfs.kmod b/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/12_sysfs.kmod new file mode 100755 index 0000000..cbee3df --- /dev/null +++ b/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/12_sysfs.kmod @@ -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") \ No newline at end of file diff --git a/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/13_procfs.kmod b/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/13_procfs.kmod new file mode 100755 index 0000000..e69de29 diff --git a/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/11_fstabInit.kmod b/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/15_fstabInit.kmod similarity index 58% rename from Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/11_fstabInit.kmod rename to Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/15_fstabInit.kmod index 64456fd..f8a5c85 100755 --- a/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/11_fstabInit.kmod +++ b/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/15_fstabInit.kmod @@ -1,11 +1,11 @@ -local args={...} -local kernel=args[1] +local args = {...} +local kernel = args[1] local ifs=kernel.ifs -local initdisks=kernel.initdisks +kernel.log("Mounting fstab") local fstab=ifs.readAllText("/etc/fstab") -kernel.fs.update(initdisks) -for i,v in ipairs(string.split(fstab,"\n")) do +local entrys = string.split(fstab,"\n") +for i,v in ipairs(entrys) do if v:sub(1,1)=="U" then local id="" for i=3,#v do @@ -14,9 +14,13 @@ for i,v in ipairs(string.split(fstab,"\n")) do id=v:sub(3,i-1) 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.fs.mount(id,path) ::endline:: end -end \ No newline at end of file +end +kernel.log("Mounted all disks") \ No newline at end of file diff --git a/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/20_keventd.kmod b/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/20_keventd.kmod index 9f47b9e..9c55cca 100755 --- a/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/20_keventd.kmod +++ b/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/20_keventd.kmod @@ -1,5 +1,5 @@ -local args={...} -local kernel=args[1] +local args = {...} +local kernel = args[1] kernel.drivers.processes[#kernel.drivers.processes+1]=function() while true do local event={kernel.computer:getMachineEvent()} @@ -9,4 +9,5 @@ kernel.drivers.processes[#kernel.drivers.processes+1]=function() end coroutine.yield() end -end \ No newline at end of file +end +kernel.log("Created keventd daemon") \ No newline at end of file diff --git a/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/30_thirdParty.kmod b/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/30_thirdParty.kmod index b0e6ff6..47b635f 100644 --- a/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/30_thirdParty.kmod +++ b/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/30_thirdParty.kmod @@ -1,17 +1,20 @@ -local args={...} -local kernel=args[2] - +local args = {...} +local kernel = args[1] +kernel.log("Loading third party drivers") 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") + if kernel.fs.isDir("/lib/modules/"..subf) then + if subf~="Hyperion" then + 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 func, err = load(code, "@"..driver) + if not func then + kernel.log("DriverCompileErr: "..tostring(err), "ERROR") + else + local ok, err = xpcall(func, debug.traceback, table.unpack(args)) + if not ok then + kernel.log("DriverExecErr: "..tostring(err), "ERROR") + end end end end diff --git a/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/31_thirdPartyInit.kmod b/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/31_thirdPartyInit.kmod index c98ec23..5143c77 100755 --- a/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/31_thirdPartyInit.kmod +++ b/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/31_thirdPartyInit.kmod @@ -1,11 +1,14 @@ -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 +local args = {...} +local kernel = args[1] +kernel.log("initializing third party drivers") +for _,v in ipairs(kernel.drivers.raw) do + if v.arch==kernel.arch then + if v.load then + kernel.log("Loading "..v.name) + local ok,err = xpcall(v.load, debug.traceback) + if not ok then + kernel.log("DriverLoadErr: "..tostring(err)) + end end end -end \ No newline at end of file +end diff --git a/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/50_mutiUserAuth.kmod b/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/50_mutiUserAuth.kmod new file mode 100755 index 0000000..e69de29 diff --git a/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/99_init.kmod b/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/99_init.kmod index 03361ef..b810db8 100755 --- a/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/99_init.kmod +++ b/Test/Hyperion-kernel-v0.1.0/lib/modules/Hyperion/99_init.kmod @@ -1,17 +1,25 @@ -local args={...} +local args = {...} local kernel = args[1] local tasks={} local currentTask={} local signals={} -local tid=1 -local gid=1 +local tid=2 +local gid=2 +local hookuuid=0 local sys={} function sys.hookSig(sig, func) - if not signals[tostring(currentTask.pid)][sig] then - signals[tostring(currentTask.pid)][sig]={} + if not currentTask.signal[sig] then + currentTask.signal[sig]={} 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 function sys.clearSigHooks(typ) @@ -27,7 +35,7 @@ end function sys.sendSig(pid, signal, ...) if pid=="all" then - for i,v in pairs(tasks) do + for i,v in pairs(tasks) do+ v.sigQ[#v.sigQ+1]={signal, ...} end return @@ -38,31 +46,35 @@ function sys.sendSig(pid, signal, ...) 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 + local sigs = {} + for i,v in ipairs(currentTask.sigQ) do + sigs[i]=v + end + for i=1, #sigs do + local sig = sigs[i] + if currentTask.signal[sig[1]] then + for k,v in pairs(currentTask.signal[sig[1]]) do coroutine.resumeWithTimeout(coroutine.create(function() - local ok, err = xpcall(v, debug.traceback, table.unpack(table.remove(currentTask.sigQ, 1))) - if not ok then - table.insert(ret, err) + local ok,err = xpcall(v,debug.traceback,table.unpack(sig)) + if not ok and sig[1]~="callbackErr" then + sys.sendSig(currentTask.pid, "callbackErr", sig[1], k, err) end - end), 10) + end),10) end else - for _,v in ipairs(currentTask.signal["unhandledEvent"]) do + for k,v in pairs(currentTask.signal["unhandledSignal"]) 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) + local ok,err = xpcall(v,debug.traceback,table.unpack(sig)) + if not ok and sig[1]~="callbackErr" then + sys.sendSig(currentTask.pid, "callbackErr", sig[1], k, err) end - end), 10) + end),10) end end end end -function sys.spawn(func, name, evars, args) +function sys.spawn(func, name, evars, args, stdin, stdout, stderr) local id=tid tid=tid+1 name=name or tostring(id) @@ -89,6 +101,7 @@ function sys.spawn(func, name, evars, args) vy=0, ivy=0, status="R", + sleep=0, signal=signals[tostring(id)], parent=currentTask, children={}, @@ -97,6 +110,12 @@ function sys.spawn(func, name, evars, args) } end +function sys.exit(...) + sys.sendSig(currentTask.ppid, "ChildTaskExit", currentTask.pid, ...) + currentTask.status="Z" + coroutine.yield() +end + local function collectZombieProc() local ret = {} for _,v in pairs(tasks) do @@ -116,13 +135,23 @@ local function collectZombieProc() return ret end +kernel.log("initPath is: " .. tostring(kernel.initPath)) signals["1"]={} tasks["1"]={ 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 + currentTask.status="Z" kernel.panic(err) else + currentTask.status="Z" kernel.panic("Attempted to kill init!") end end), @@ -130,27 +159,38 @@ tasks["1"]={ pid=1, ppid=0, tgid=1, - user=kernel.user, - uid=kernel.uid, + user="root", + uid=0, evars={}, args={kernel}, vy=0, ivy=0, status="R", + sleep=0, signal=signals["1"], parent={name="Hyprkrnl",pid=0}, children={}, sibling={}, sigQ={} } -kernel.chache.preload.sys=sys -kernel.chache.preload.system=sys +tasks["1"].sibling={tasks["1"]} + +kernel.log("Created pid 1") +kernel.cache.preload.sys=table.proxy(sys) +kernel.cache.preload.system=kernel.cache.preload.sys +kernel.cache.preload.os=kernel.cache.preload.sys kernel.hpv=sys +kernel.tasks=tasks +kernel.signals=signals +kernel.currentTask=currentTask kernel.saveLog() -while true do - for _,v in pairs(tasks) do +kernel.status="running" +while kernel.status~="Panic" do + for k,v in pairs(tasks) do currentTask=v + kernel.currentTask=v + kernel.process=currentTask.name kernel.user=currentTask.user kernel.uid=currentTask.uid sys.flushSigs() @@ -164,4 +204,7 @@ while true do collectZombieProc() end -kernel.panic("Exited pid 0") \ No newline at end of file +kernel.process="Kernel" +kernel.user="root" +kernel.uid=0 +kernel.panic(kernel.reason or "Exited pid 0") \ No newline at end of file diff --git a/docs/kernel/drivers/api/README.md b/docs/kernel/drivers/api/README.md index d2b6639..3d3a9c9 100755 --- a/docs/kernel/drivers/api/README.md +++ b/docs/kernel/drivers/api/README.md @@ -4,22 +4,24 @@ Hyperion OS supports many driver types to allow it to run on any hardware ``` Driver types - tto - Supports basic text terminal output + tty - Supports basic teletype devices gpio - Supports things like redstone runner - Kernel level programs (no api) timer - Timers and time related periph - Basic peripheral info gfx - PixelScreens + modem - networking ``` Hyperion also has a base driver api ``` Driver API - name - Name of driver+ + name - Name 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) 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 author - author of driver prior - priority (low first) diff --git a/docs/kernel/drivers/api/tto.md b/docs/kernel/drivers/api/tty.md similarity index 100% rename from docs/kernel/drivers/api/tto.md rename to docs/kernel/drivers/api/tty.md