diff --git a/Src/Hyperion-core/lib/colors b/Src/Hyperion-core/lib/colors new file mode 100644 index 0000000..da1ad9e --- /dev/null +++ b/Src/Hyperion-core/lib/colors @@ -0,0 +1,18 @@ +--:Minify:-- +return { + white=0xFFFFFF, + red=0xFF0000, + green=0x00FF00, + blue=0x0000FF, + cyan=0x00FFFF, + yellow=0xFFFF00, + purple=0xFF00FF, + black=0x000000, + gray=0x888888, + lightgrey=0xBBBBBB, + darkgrey=0x444444, + orange=0xFF8800, + mint=0x00FF88, + brown=0xa52a2a, + chocolate=0xd2691e +} \ No newline at end of file diff --git a/Src/Hyperion-firmware-ac/boot/ac/boot.lua b/Src/Hyperion-firmware-ac/boot/ac/boot.lua new file mode 100644 index 0000000..5b42647 --- /dev/null +++ b/Src/Hyperion-firmware-ac/boot/ac/boot.lua @@ -0,0 +1,344 @@ +--:Minify:-- +local args={...} +local bootdrive=args[1] +local gpu=components:getFirst("gpu") +local screenTextBuffer=nil +local cursorX,cursorY=0,0 +local screenSizeX,screenSizeY=128,25 + + +if gpu then + screenTextBuffer=gpu:newBuffer(screenSizeX,screenSizeY) + for t,v in components:list() do + if t == "screen" then + gpu:assignBuffer(screenTextBuffer, v) + end + end +end + +local function write(text) + cursorX, cursorY = screenTextBuffer:pasteText(cursorX, cursorY, "SCROLL_SPILL_CLEAR", text) + cursorY = cursorY + 1 + cursorX = 0 + if cursorY >= screenSizeY then + cursorY = screenSizeY-1 + screenTextBuffer:newline() + end +end + +local function displaySuperBadError(err) + gpu:freeAllBuffers() + screenTextBuffer=gpu:newBuffer(screenSizeX,screenSizeY) + for t,v in components:list() do + if t == "screen" then + gpu:assignBuffer(screenTextBuffer, v) + end + end + term.setBackgroundColor(0x1) + term.setTextColor(0x4) + term.clear() + term.setCursorPos(1, 1) + term.write("A critical error occurred while loading the system:") + term.setCursorPos(1, 3) + write(err) + while true do end +end + +local ok, err = xpcall(function() + local apis = {} + + local lua = { + coroutine = true, + debug = true, + _VERSION = true, + assert = true, + collectgarbage = true, + error = true, + gcinfo = true, + getmetatable = true, + ipairs = true, + __inext = true, + load = true, + math = true, + next = true, + pairs = true, + pcall = true, + rawequal = true, + rawget = true, + rawlen = true, + rawset = true, + select = true, + setmetatable = true, + string = true, + table = true, + tonumber = true, + tostring = true, + type = true, + xpcall = true, + _G = true + } + + local debug = debug + for i, v in pairs(_G) do + if not lua[i] or lua[i] == nil then + apis[i] = v + _G[i] = nil + end + end + + local function string_file(file) + local str = file:read() + local buf = {str or ""} + local pos = 1 + local closed = false + + local function content() + return table.concat(buf) + end + + local function set_content(s) + buf = {s} + end + + local function flush() + file.write(content()) + end + + local file = {} + + function file:read(n) + assert(not closed, "file is closed") + + local s = content() + local len = #s + + if not n then + local out = s:sub(pos) + pos = len + 1 + return out + end + + local out = s:sub(pos, pos + n - 1) + pos = pos + #out + return out + end + + function file:write(data) + assert(not closed, "file is closed") + + local s = content() + local before = s:sub(1, pos - 1) + local after = s:sub(pos + #data) + + set_content(before .. data .. after) + pos = pos + #data + + return true + end + + function file:seek(whence, offset) + assert(not closed, "file is closed") + + local s = content() + local len = #s + + whence = whence or "cur" + offset = offset or 0 + + if whence == "set" then + pos = offset + 1 + elseif whence == "cur" then + pos = pos + offset + elseif whence == "end" then + pos = len + offset + 1 + else + error("invalid whence") + end + + if pos < 1 then pos = 1 end + if pos > len + 1 then pos = len + 1 end + + return pos - 1 + end + + function file:close() + assert(not closed, "file is closed") + flush() + closed = true + end + + function file:flush() + assert(not closed, "file is closed") + flush() + end + + return file + end + + local function getFile(path) + local file = bootdrive:open(path, "r") + if not file then + displaySuperBadError("Could not open file: " .. path) + end + local content = file:read() + return content + end + + local Kernel = load(getFile("/boot/kernel.lua"),"@Kernel") + local initFs = load(getFile("/boot/ac/initdisks"),"@Init_disks")(apis) + local fs = load(getFile("/boot/initfs"), "@InitFs")() + + if not Kernel then displaySuperBadError("Could not load kernel.") end + if not initFs then displaySuperBadError("Could not load initdisks.") end + if not fs then displaySuperBadError("Could not load initfs.") end + + local computercomp=apis.components:getFirst("computer") + local uefi=apis.components:getFirst("uefi") + local computer = { + time = function() return apis.os.epoch("utc") end, + clock = function() return apis.os.clock() * 1000 end, + shutdown = apis.os.shutdown, + reboot = apis.os.reboot, + getMachineEvent = function() + return computercomp:getMachineEvent() + end, + getEEPROM = function() return uefi.data end, + setEEPROM = function(_, text) + uefi.data=text + end + } + + local icolors = { + [0x1] = 1, -- #000000 + [0x2] = 2, -- #FFFFFF + [0x4] = 3, -- #FF0000 + [0x8] = 4, -- #00FF00 + [0x10] = 5, -- #0000FF + [0x20] = 6, -- #00FFFF + [0x40] = 7, -- #FF00FF + [0x80] = 8, -- #FFFF00 + [0x100] = 9, -- #FF6D00 + [0x200] = 10, -- #6DFF55 + [0x400] = 11, -- #24FFFF + [0x800] = 12, -- #924900 + [0x1000] = 13, -- #6D6D55 + [0x2000] = 14, -- #DBDBAA + [0x4000] = 15, -- #6D00FF + [0x8000] = 16 -- #B6FF00 + } + + local colors = { + 0x0001, -- #000000 + 0x0002, -- #FFFFFF + 0x0004, -- #FF0000 + 0x0008, -- #00FF00 + 0x0010, -- #0000FF + 0x0020, -- #00FFFF + 0x0040, -- #FF00FF + 0x0080, -- #FFFF00 + 0x0100, -- #FF6D00 + 0x0200, -- #6DFF55 + 0x0400, -- #24FFFF + 0x0800, -- #924900 + 0x1000, -- #6D6D55 + 0x2000, -- #DBDBAA + 0x4000, -- #6D00FF + 0x8000 -- #B6FF00 + } + + apis.term.setBackgroundColor(0x8000) + apis.term.setTextColor(0x1000) + apis.term.clear() + apis.term.setCursorPos(1, 1) + + local kernelCoro = coroutine.create(function() + ---@diagnostic disable-next-line: param-type-mismatch + local ok, err = xpcall(Kernel, debug.traceback, apis, initFs, "cct", "/sbin/init", + { + print = function(_, text) write(text .. "\n") end, + printInline = function(_, text) write(text) end, + clear = function() + apis.term.clear() + apis.term.setCursorPos(1, 1) + end, + setCursorPos = function(_, x, y) + apis.term.setCursorPos(x, y) + end, + getCursorPos = function() return apis.term.getCursorPos() end, + getSize = function() return apis.term.getSize() end, + setBackgroundColor = function(_, color) + apis.term.setBackgroundColor(colors[color]) + end, + setTextColor = function(_, color) + apis.term.setTextColor(colors[color]) + end, + getBackgroundColor = function() + return icolors[apis.term.getBackgroundColor()] + end, + getTextColor = function() + return icolors[apis.term.getTextColor()] + end + }, computer, fs, "$") + if not ok then displaySuperBadError(err) end + end) + + function coroutine.resumeWithTimeout(co, timeout, ...) + local startTime = computer.time() + debug.sethook(co, function() + if computer.time() > startTime + timeout then + return coroutine.yield("timeout") + end + end, "", 1000) + local ret = {coroutine.resume(co, ...)} + if ret[1] and ret[2] == "timeout" then + return "timeout" + elseif ret[1] == false then + return "error", ret[2] + else + debug.sethook(co) + return "success", table.unpack(ret, 2) + end + end + + write("Loaded in " .. tostring(apis.os.clock()) .. " seconds.\n") + + while true do + local status, err = coroutine.resumeWithTimeout(kernelCoro, 50) + apis.os.queueEvent("NoSleep") + local exit = false + while not exit do + local event = {coroutine.yield()} + if event[1] == "key" then + queueEvent("keyPressed", 1, event[2]) + if acekeys[event[2]] then + queueEvent("keyTyped", 1, acekeys[event[2]]) + end + elseif event[1] == "char" then + queueEvent("keyTyped", 1, event[2]) + elseif event[1] == "key_up" then + queueEvent("keyReleased", 1, event[2]) + elseif event[1] == "disk" then + queueEvent("componentAdded", "disk") + elseif event[1] == "disk_eject" then + queueEvent("componentRemoved", "disk") + elseif event[1] == "modem_message" then + queueEvent("modem_message", table.unpack(event, 2)) + elseif event[1] == "rednet_message" then + queueEvent("rednet_message", table.unpack(event, 2)) + elseif event[1] == "http_success" then + queueEvent("http_success", table.unpack(event, 2)) + elseif event[1] == "http_failure" then + queueEvent("http_failure", table.unpack(event, 2)) + elseif event[1] == "NoSleep" then + exit = true + end + end + if status == "error" or coroutine.status(kernelCoro) == "dead" then + displaySuperBadError("Kernel error: " .. tostring(err)) + coroutine.yield("key") + end + end +end, debug.traceback) + +if not ok then displaySuperBadError("Fatal error during boot: " .. err) end +while true do coroutine.yield() end diff --git a/Src/Hyperion-firmware-ccpc/boot/cct/boot.lua b/Src/Hyperion-firmware-ccpc/boot/ccpc/boot.lua similarity index 100% rename from Src/Hyperion-firmware-ccpc/boot/cct/boot.lua rename to Src/Hyperion-firmware-ccpc/boot/ccpc/boot.lua diff --git a/Src/Hyperion-firmware-ccpc/boot/cct/eeprom b/Src/Hyperion-firmware-ccpc/boot/ccpc/eeprom similarity index 100% rename from Src/Hyperion-firmware-ccpc/boot/cct/eeprom rename to Src/Hyperion-firmware-ccpc/boot/ccpc/eeprom diff --git a/Src/Hyperion-firmware-ccpc/boot/cct/initdisks b/Src/Hyperion-firmware-ccpc/boot/ccpc/initdisks similarity index 100% rename from Src/Hyperion-firmware-ccpc/boot/cct/initdisks rename to Src/Hyperion-firmware-ccpc/boot/ccpc/initdisks diff --git a/Src/Hyperion-firmware-ccpc/lib/modules/ccpc/25_gfx.kmod b/Src/Hyperion-firmware-ccpc/lib/modules/ccpc/25_gfx.kmod index 8b586e1..94edf54 100644 --- a/Src/Hyperion-firmware-ccpc/lib/modules/ccpc/25_gfx.kmod +++ b/Src/Hyperion-firmware-ccpc/lib/modules/ccpc/25_gfx.kmod @@ -311,7 +311,7 @@ local fifo = kernel.newFifo() kernel.processes.cctmond = function() local timeout = false while true do - local event = {kernel.computer:getMachineEvent()} + local event = {kernel.EFI:getMachineEvent()} if event[1] then local eventType = event[1] diff --git a/Src/Hyperion-firmware-cct/boot/cct/boot.lua b/Src/Hyperion-firmware-cct/boot/cct/boot.lua index b902780..01bfcb8 100644 --- a/Src/Hyperion-firmware-cct/boot/cct/boot.lua +++ b/Src/Hyperion-firmware-cct/boot/cct/boot.lua @@ -1,4 +1,4 @@ --- :Minify:-- +--:Minify:-- local BOOT_DRIVE_PATH = ({...})[1] or "/$" ---@diagnostic disable-next-line: undefined-global local term = term @@ -152,17 +152,99 @@ local ok, err = xpcall(function() if not initFs then displaySuperBadError("Could not load initdisks.") end if not fs then displaySuperBadError("Could not load initfs.") end + if not apis.fs.exists("/nvram.dat") then + local file = apis.fs.open("/nvram.dat", "w") + file.write("Hello, World!") + file.close() + end + local eventQueue = {} local function queueEvent(event, ...) table.insert(eventQueue, {event, ...}) end - local computer = { - time = function() return apis.os.epoch("utc") end, - clock = function() return apis.os.clock() * 1000 end, - shutdown = apis.os.shutdown, - reboot = apis.os.reboot, + local colors = { + [0x000000]=0x0001, + [0xFFFFFF]=0x0002, + [0xFF0000]=0x0004, + [0x00FF00]=0x0008, + [0x0000FF]=0x0010, + [0x00FFFF]=0x0020, + [0xFF00FF]=0x0040, + [0xFFFF00]=0x0080, + [0xFF6D00]=0x0100, + [0x6DFF55]=0x0200, + [0x24FFFF]=0x0400, + [0x924900]=0x0800, + [0x6D6D55]=0x1000, + [0xDBDBAA]=0x2000, + [0x6D00FF]=0x4000, + [0xB6FF00]=0x8000 + } + + local fg,bg=0x6D6D55,0x000000 + local l1f,l1d,l2,ops={},{},{},0 + + local function findClosest(tbl, target) + local closest = nil + local smallestDiff = math.huge + + for k, _ in pairs(tbl) do + local diff = math.abs(k - target) + if diff < smallestDiff then + smallestDiff = diff + closest = k + end + end + + return closest + end + + local function aprox(c24) + ops = ops + 1 + + if ops % 1024 == 0 then + l1d = {} + l1f = {} + end + + if ops % 8192 == 0 then + l2 = {} + end + + if l2[c24] ~= nil then + return l2[c24] + end + + if l1d[c24] ~= nil then + l1f[c24] = l1f[c24] + 1 + + if l1f[c24] >= 16 then + l2[c24] = l1d[c24] + l1d[c24] = nil + l1f[c24] = nil + return l2[c24] + end + + return l1d[c24] + end + + local closestKey = findClosest(colors, c24) + if not closestKey then return nil end + + local value = colors[closestKey] + + l1d[c24] = value + l1f[c24] = 1 + + return value + end + + local EFI = { + getEpochMs = function() return apis.os.epoch("utc") end, + getUptime = function() return apis.os.clock() * 1000 end, + date = function() return apis.os.date("!%Y-%m-%dT%H:%M:%SZ", apis.os.epoch("utc") / 1000) end, getMachineEvent = function() if #eventQueue > 0 then return table.unpack(table.remove(eventQueue, 1)) @@ -175,56 +257,10 @@ local ok, err = xpcall(function() local h = apis.fs.open("/startup.lua", "w") h.write(text) h.close() - end - } - - local icolors = { - [0x1] = 1, -- #000000 - [0x2] = 2, -- #FFFFFF - [0x4] = 3, -- #FF0000 - [0x8] = 4, -- #00FF00 - [0x10] = 5, -- #0000FF - [0x20] = 6, -- #00FFFF - [0x40] = 7, -- #FF00FF - [0x80] = 8, -- #FFFF00 - [0x100] = 9, -- #FF6D00 - [0x200] = 10, -- #6DFF55 - [0x400] = 11, -- #24FFFF - [0x800] = 12, -- #924900 - [0x1000] = 13, -- #6D6D55 - [0x2000] = 14, -- #DBDBAA - [0x4000] = 15, -- #6D00FF - [0x8000] = 16 -- #B6FF00 - } - - local colors = { - 0x0001, -- #000000 - 0x0002, -- #FFFFFF - 0x0004, -- #FF0000 - 0x0008, -- #00FF00 - 0x0010, -- #0000FF - 0x0020, -- #00FFFF - 0x0040, -- #FF00FF - 0x0080, -- #FFFF00 - 0x0100, -- #FF6D00 - 0x0200, -- #6DFF55 - 0x0400, -- #24FFFF - 0x0800, -- #924900 - 0x1000, -- #6D6D55 - 0x2000, -- #DBDBAA - 0x4000, -- #6D00FF - 0x8000 -- #B6FF00 - } - - apis.term.setBackgroundColor(0x8000) - apis.term.setTextColor(0x1000) - apis.term.clear() - apis.term.setCursorPos(1, 1) - - local kernelCoro = coroutine.create(function() - ---@diagnostic disable-next-line: param-type-mismatch - local ok, err = xpcall(Kernel, debug.traceback, apis, initFs, "cct", "/sbin/init", - { + end, + initfs=fs, + disks=initFs, + screenCtl={ print = function(_, text) write(text .. "\n") end, printInline = function(_, text) write(text) end, clear = function() @@ -237,25 +273,51 @@ local ok, err = xpcall(function() getCursorPos = function() return apis.term.getCursorPos() end, getSize = function() return apis.term.getSize() end, setBackgroundColor = function(_, color) - apis.term.setBackgroundColor(colors[color]) + apis.term.setBackgroundColor(aprox(color)) end, setTextColor = function(_, color) - apis.term.setTextColor(colors[color]) + apis.term.setTextColor(aprox(color)) end, getBackgroundColor = function() - return icolors[apis.term.getBackgroundColor()] + return bg end, getTextColor = function() - return icolors[apis.term.getTextColor()] - end - }, computer, fs, "$") - if not ok then displaySuperBadError(err) end + return fg + end, + enable=function() end, + disable=function() end + }, + architecture="cct", + getNvram = function() return getFile("/nvram.dat") end, + setNvram = function(_, text) + local h = apis.fs.open("/nvram.dat", "w") + h.write(text) + h.close() + end, + firmware=apis, + reboot=false + } + + apis.term.setBackgroundColor(0x8000) + apis.term.setTextColor(0x1000) + apis.term.clear() + apis.term.setCursorPos(1, 1) + + local kernelCoro = coroutine.create(function() + ---@diagnostic disable-next-line: param-type-mismatch + local ok, err = xpcall(Kernel, debug.traceback, EFI) + if not ok and not EFI.reboot then displaySuperBadError(err) end + if err then + apis.os.reboot() + else + apis.os.shutdown() + end end) function coroutine.resumeWithTimeout(co, timeout, ...) - local startTime = computer.time() + local startTime = EFI.getEpochMs() debug.sethook(co, function() - if computer.time() > startTime + timeout then + if EFI.getEpochMs() > startTime + timeout then return coroutine.yield("timeout") end end, "", 1000) @@ -304,11 +366,15 @@ local ok, err = xpcall(function() end end if status == "error" or coroutine.status(kernelCoro) == "dead" then + if EFI.reboot then + apis.os.reboot() + end displaySuperBadError("Kernel error: " .. tostring(err)) coroutine.yield("key") end + initFs:refresh() end end, debug.traceback) if not ok then displaySuperBadError("Fatal error during boot: " .. err) end -while true do coroutine.yield() end +while true do coroutine.yield("key") end diff --git a/Src/Hyperion-firmware-cct/boot/cct/initdisks b/Src/Hyperion-firmware-cct/boot/cct/initdisks index 09997dd..1480a0b 100644 --- a/Src/Hyperion-firmware-cct/boot/cct/initdisks +++ b/Src/Hyperion-firmware-cct/boot/cct/initdisks @@ -1,6 +1,6 @@ --- :Minify:-- +--:Minify:-- local apis = ({...})[1] -local BOOT_DRIVE_PATH = apis.BOOT_DRIVE_PATH or "/$" +local BOOT_DRIVE_PATH = apis.BOOT_DRIVE_PATH local fs = apis.fs local native = apis.peripheral local peripheral = {} @@ -241,11 +241,17 @@ internal["$"] = createDisk("$", BOOT_DRIVE_PATH, false, { end }) -local function refresh() - for id, _ in pairs(disks) do - if not peripheral.getType(id) then disks[id] = nil end +internal["rom"] = createDisk("rom", "/rom", true, { + setLabel = function(label) + error("Device is read-only") + end, + getLabel = function() + return "cctrom" end +}) +local function refresh() + disks={} for _, disk in ipairs({peripheral.find("drive")}) do if disk.isDiskPresent() then disks[tostring(disk.getDiskID())]=createDisk("cctdisk"..tostring(disk.getDiskID()), disk.getMountPath(), false, fs) diff --git a/Src/Hyperion-firmware-cct/lib/modules/cc-tweaked/24_periph.kmod b/Src/Hyperion-firmware-cct/lib/modules/cc-tweaked/24_periph.kmod new file mode 100644 index 0000000..99953dc --- /dev/null +++ b/Src/Hyperion-firmware-cct/lib/modules/cc-tweaked/24_periph.kmod @@ -0,0 +1,152 @@ +--:Minify:-- +-- CCT driver peripheral helper +local kernel=... +kernel.cct={} +kernel.cct.peripheral={} +local peripheral=kernel.cct.peripheral +local apis = kernel.apis +local native = apis.peripheral +local sides = {"top", "bottom", "left", "right", "front", "back"} + +function peripheral.getNames() + local results = {} + for n = 1, #sides do + local side = sides[n] + if native.isPresent(side) then + table.insert(results, side) + if native.hasType(side, "peripheral_hub") then + local remote = native.call(side, "getNamesRemote") + for _, name in ipairs(remote) do + table.insert(results, name) + end + end + end + end + return results +end + +function peripheral.isPresent(name) + if native.isPresent(name) then + return true + end + + for n = 1, #sides do + local side = sides[n] + if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then + return true + end + end + return false +end + +function peripheral.getType(peripheral) + if type(peripheral) == "string" then + if native.isPresent(peripheral) then + return native.getType(peripheral) + end + for n = 1, #sides do + local side = sides[n] + if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then + return native.call(side, "getTypeRemote", peripheral) + end + end + return nil + else + local mt = getmetatable(peripheral) + if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then + error("bad argument #1 (table is not a peripheral)", 2) + end + return table.unpack(mt.types) + end +end + +function peripheral.hasType(peripheral, peripheral_type) + if type(peripheral) == "string" then + if native.isPresent(peripheral) then + return native.hasType(peripheral, peripheral_type) + end + for n = 1, #sides do + local side = sides[n] + if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then + return native.call(side, "hasTypeRemote", peripheral, peripheral_type) + end + end + return nil + else + local mt = getmetatable(peripheral) + if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then + error("bad argument #1 (table is not a peripheral)", 2) + end + return mt.types[peripheral_type] ~= nil + end +end + +function peripheral.getMethods(name) + if native.isPresent(name) then + return native.getMethods(name) + end + for n = 1, #sides do + local side = sides[n] + if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then + return native.call(side, "getMethodsRemote", name) + end + end + return nil +end + +function peripheral.getName(peripheral) + local mt = getmetatable(peripheral) + if not mt or mt.__name ~= "peripheral" or type(mt.name) ~= "string" then + error("bad argument #1 (table is not a peripheral)", 2) + end + return mt.name +end + +function peripheral.call(name, method, ...) + if native.isPresent(name) then + return native.call(name, method, ...) + end + + for n = 1, #sides do + local side = sides[n] + if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then + return native.call(side, "callRemote", name, method, ...) + end + end + return nil +end + +function peripheral.wrap(name) + local methods = peripheral.getMethods(name) + if not methods then + return nil + end + + local types = { peripheral.getType(name) } + for i = 1, #types do types[types[i]] = true end + local result = setmetatable({}, { + __name = "peripheral", + name = name, + type = types[1], + types = types, + }) + for _, method in ipairs(methods) do + result[method] = function(...) + return peripheral.call(name, method, ...) + end + end + return result +end + +function peripheral.find(ty, filter) + local results = {} + for _, name in ipairs(peripheral.getNames()) do + if peripheral.hasType(name, ty) then + local wrapped = peripheral.wrap(name) + if filter == nil or filter(name, wrapped) then + table.insert(results, wrapped) + end + end + end + return table.unpack(results) +end \ No newline at end of file diff --git a/Src/Hyperion-firmware-cct/lib/modules/cc-tweaked/25_tty.kmod b/Src/Hyperion-firmware-cct/lib/modules/cc-tweaked/25_tty.kmod index 0ded701..4cd738d 100644 --- a/Src/Hyperion-firmware-cct/lib/modules/cc-tweaked/25_tty.kmod +++ b/Src/Hyperion-firmware-cct/lib/modules/cc-tweaked/25_tty.kmod @@ -1,192 +1,85 @@ --:Minify:-- - local kernel = ... -local apis = kernel.apis -local native = apis.peripheral -local sides = {"top", "bottom", "left", "right", "front", "back"} -local peripheral={} - -function peripheral.getNames() - local results = {} - for n = 1, #sides do - local side = sides[n] - if native.isPresent(side) then - table.insert(results, side) - if native.hasType(side, "peripheral_hub") then - local remote = native.call(side, "getNamesRemote") - for _, name in ipairs(remote) do - table.insert(results, name) - end - end - end - end - return results -end - -function peripheral.isPresent(name) - if native.isPresent(name) then - return true - end - - for n = 1, #sides do - local side = sides[n] - if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then - return true - end - end - return false -end - -function peripheral.getType(peripheral) - if type(peripheral) == "string" then - if native.isPresent(peripheral) then - return native.getType(peripheral) - end - for n = 1, #sides do - local side = sides[n] - if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then - return native.call(side, "getTypeRemote", peripheral) - end - end - return nil - else - local mt = getmetatable(peripheral) - if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then - error("bad argument #1 (table is not a peripheral)", 2) - end - return table.unpack(mt.types) - end -end - -function peripheral.hasType(peripheral, peripheral_type) - if type(peripheral) == "string" then - if native.isPresent(peripheral) then - return native.hasType(peripheral, peripheral_type) - end - for n = 1, #sides do - local side = sides[n] - if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then - return native.call(side, "hasTypeRemote", peripheral, peripheral_type) - end - end - return nil - else - local mt = getmetatable(peripheral) - if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then - error("bad argument #1 (table is not a peripheral)", 2) - end - return mt.types[peripheral_type] ~= nil - end -end - -function peripheral.getMethods(name) - if native.isPresent(name) then - return native.getMethods(name) - end - for n = 1, #sides do - local side = sides[n] - if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then - return native.call(side, "getMethodsRemote", name) - end - end - return nil -end - -function peripheral.getName(peripheral) - local mt = getmetatable(peripheral) - if not mt or mt.__name ~= "peripheral" or type(mt.name) ~= "string" then - error("bad argument #1 (table is not a peripheral)", 2) - end - return mt.name -end - -function peripheral.call(name, method, ...) - if native.isPresent(name) then - return native.call(name, method, ...) - end - - for n = 1, #sides do - local side = sides[n] - if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then - return native.call(side, "callRemote", name, method, ...) - end - end - return nil -end - -function peripheral.wrap(name) - local methods = peripheral.getMethods(name) - if not methods then - return nil - end - - local types = { peripheral.getType(name) } - for i = 1, #types do types[types[i]] = true end - local result = setmetatable({}, { - __name = "peripheral", - name = name, - type = types[1], - types = types, - }) - for _, method in ipairs(methods) do - result[method] = function(...) - return peripheral.call(name, method, ...) - end - end - return result -end - -function peripheral.find(ty, filter) - local results = {} - for _, name in ipairs(peripheral.getNames()) do - if peripheral.hasType(name, ty) then - local wrapped = peripheral.wrap(name) - if filter == nil or filter(name, wrapped) then - table.insert(results, wrapped) - end - end - end - return table.unpack(results) -end - -local icolors = { - [0x1] = 1, -- #000000 - [0x2] = 2, -- #FFFFFF - [0x4] = 3, -- #FF0000 - [0x8] = 4, -- #00FF00 - [0x10] = 5, -- #0000FF - [0x20] = 6, -- #00FFFF - [0x40] = 7, -- #FF00FF - [0x80] = 8, -- #FFFF00 - [0x100] = 9, -- #FF6D00 - [0x200] = 10, -- #6DFF55 - [0x400] = 11, -- #24FFFF - [0x800] = 12, -- #924900 - [0x1000] = 13, -- #6D6D55 - [0x2000] = 14, -- #DBDBAA - [0x4000] = 15, -- #6D00FF - [0x8000] = 16 -- #B6FF00 -} +local peripheral=kernel.cct.peripheral +local keys=kernel.apis.keys local colors = { - 0x0001, -- #000000 - 0x0002, -- #FFFFFF - 0x0004, -- #FF0000 - 0x0008, -- #00FF00 - 0x0010, -- #0000FF - 0x0020, -- #00FFFF - 0x0040, -- #FF00FF - 0x0080, -- #FFFF00 - 0x0100, -- #FF6D00 - 0x0200, -- #6DFF55 - 0x0400, -- #24FFFF - 0x0800, -- #924900 - 0x1000, -- #6D6D55 - 0x2000, -- #DBDBAA - 0x4000, -- #6D00FF - 0x8000 -- #B6FF00 + [0xFFFFFF]=0x0001, + [0xFF0000]=0x0002, + [0x00FF00]=0x0004, + [0x0000FF]=0x0008, + [0x00FFFF]=0x0010, + [0xFF00FF]=0x0020, + [0xFFFF00]=0x0040, + [0xFF6D00]=0x0080, + [0x6DFF55]=0x0100, + [0x24FFFF]=0x0200, + [0x924900]=0x0400, + [0x6D6D55]=0x0800, + [0xDBDBAA]=0x1000, + [0x6D00FF]=0x2000, + [0xB6FF00]=0x4000, + [0x000000]=0x8000 } +local fg,bg=0x6D6D55,0x000000 +local l1f,l1d,l2,ops={},{},{},0 + +local function findClosest(tbl, target) + local closest = nil + local smallestDiff = math.huge + + for k, _ in pairs(tbl) do + local diff = math.abs(k - target) + if diff < smallestDiff then + smallestDiff = diff + closest = k + end + end + + return closest +end + +local function aprox(c24) + ops = ops + 1 + + if ops % 1024 == 0 then + l1d = {} + l1f = {} + end + + if ops % 8192 == 0 then + l2 = {} + end + + if l2[c24] ~= nil then + return l2[c24] + end + + if l1d[c24] ~= nil then + l1f[c24] = l1f[c24] + 1 + + if l1f[c24] >= 16 then + l2[c24] = l1d[c24] + l1d[c24] = nil + l1f[c24] = nil + return l2[c24] + end + + return l1d[c24] + end + + local closestKey = findClosest(colors, c24) + if not closestKey then return nil end + + local value = colors[closestKey] + + l1d[c24] = value + l1f[c24] = 1 + + return value +end + local function write(text, term) local x, y = term.getCursorPos() local w, h = term.getSize() @@ -244,18 +137,18 @@ local function serializeBool(bool) end local function newtty(obj, id, ev) - obj.setPaletteColor(0x1, 0xFFFFFF) -- #000000 - obj.setPaletteColor(0x2, 0xFF0000) -- #FFFFFF - obj.setPaletteColor(0x4, 0x00FF00) -- #FF0000 - obj.setPaletteColor(0x8, 0x0000FF) -- #00FF00 - obj.setPaletteColor(0x10, 0x00FFFF) -- #0000FF - obj.setPaletteColor(0x20, 0xFF00FF) -- #00FFFF - obj.setPaletteColor(0x40, 0xFFFF00) -- #FF00FF - obj.setPaletteColor(0x80, 0xFF6D00) -- #FFFF00 - obj.setPaletteColor(0x100, 0x6DFF55) -- #FF6D00 - obj.setPaletteColor(0x200, 0x24FFFF) -- #6DFF55 - obj.setPaletteColor(0x400, 0x924900) -- #24FFFF - obj.setPaletteColor(0x800, 0x6D6D55) -- #924900 + obj.setPaletteColor(0x1, 0xFFFFFF) -- #000000 + obj.setPaletteColor(0x2, 0xFF0000) -- #FFFFFF + obj.setPaletteColor(0x4, 0x00FF00) -- #FF0000 + obj.setPaletteColor(0x8, 0x0000FF) -- #00FF00 + obj.setPaletteColor(0x10, 0x00FFFF) -- #0000FF + obj.setPaletteColor(0x20, 0xFF00FF) -- #00FFFF + obj.setPaletteColor(0x40, 0xFFFF00) -- #FF00FF + obj.setPaletteColor(0x80, 0xFF6D00) -- #FFFF00 + obj.setPaletteColor(0x100, 0x6DFF55) -- #FF6D00 + obj.setPaletteColor(0x200, 0x24FFFF) -- #6DFF55 + obj.setPaletteColor(0x400, 0x924900) -- #24FFFF + obj.setPaletteColor(0x800, 0x6D6D55) -- #924900 obj.setPaletteColor(0x1000, 0xDBDBAA) -- #6D6D55 obj.setPaletteColor(0x2000, 0x6D00FF) -- #DBDBAA obj.setPaletteColor(0x4000, 0xB6FF00) -- #6D00FF @@ -295,16 +188,18 @@ local function newtty(obj, id, ev) return obj.setCursorPos(x,y) end, sfgc=function(c) - return obj.setTextColor(colors[c]) + fg=c + return obj.setTextColor(aprox(c)) end, sbgc=function(c) - return obj.setBackgroundColor(colors[c]) + bg=c + return obj.setBackgroundColor(aprox(c)) end, gfgc=function() - return icolors[obj.getTextColor()] + return fg end, gbgc=function() - return icolors[obj.getBackgroundColor()] + return bg end, gctrl=function() return serializeBool(ctrl)..";"..serializeBool(alt) @@ -328,28 +223,28 @@ local fifo = kernel.newFifo() kernel.processes.cctmond = function() local timeout = false while true do - local event = {kernel.computer:getMachineEvent()} + local event = {kernel.EFI:getMachineEvent()} if event[1] then local eventType = event[1] local charOrKey = event[3] local ctrlKeyMap = { - [apis.keys.a]=1, [apis.keys.b]=2, [apis.keys.c]=3, - [apis.keys.d]=4, [apis.keys.e]=5, [apis.keys.f]=6, - [apis.keys.g]=7, [apis.keys.h]=8, [apis.keys.i]=9, - [apis.keys.j]=10, [apis.keys.k]=11, [apis.keys.l]=12, - [apis.keys.m]=13, [apis.keys.n]=14, [apis.keys.o]=15, - [apis.keys.p]=16, [apis.keys.q]=17, [apis.keys.r]=18, - [apis.keys.s]=19, [apis.keys.t]=20, [apis.keys.u]=21, - [apis.keys.v]=22, [apis.keys.w]=23, [apis.keys.x]=24, - [apis.keys.y]=25, [apis.keys.z]=26, + [keys.a]=1, [keys.b]=2, [keys.c]=3, + [keys.d]=4, [keys.e]=5, [keys.f]=6, + [keys.g]=7, [keys.h]=8, [keys.i]=9, + [keys.j]=10, [keys.k]=11, [keys.l]=12, + [keys.m]=13, [keys.n]=14, [keys.o]=15, + [keys.p]=16, [keys.q]=17, [keys.r]=18, + [keys.s]=19, [keys.t]=20, [keys.u]=21, + [keys.v]=22, [keys.w]=23, [keys.x]=24, + [keys.y]=25, [keys.z]=26, } if eventType == "keyPressed" then - if charOrKey == apis.keys.leftCtrl or charOrKey == apis.keys.rightCtrl then + if charOrKey == keys.leftCtrl or charOrKey == keys.rightCtrl then ctrl = true - elseif charOrKey == apis.keys.leftAlt or charOrKey == apis.keys.rightAlt then + elseif charOrKey == keys.leftAlt or charOrKey == keys.rightAlt then alt = true end @@ -366,24 +261,24 @@ kernel.processes.cctmond = function() end else local specialKeyMap = { - [apis.keys.up] = "", - [apis.keys.down] = "", - [apis.keys.right] = "", - [apis.keys.left] = "", - [apis.keys.home] = "", - [apis.keys["end"]] = "", - [apis.keys.pageUp] = "[5~", - [apis.keys.pageDown] = "[6~", - [apis.keys.delete] = "[3~", + [keys.up] = "", + [keys.down] = "", + [keys.right] = "", + [keys.left] = "", + [keys.home] = "", + [keys["end"]] = "", + [keys.pageUp] = "[5~", + [keys.pageDown] = "[6~", + [keys.delete] = "[3~", } local special = specialKeyMap[charOrKey] if special then fifo.push(special) end end elseif eventType == "keyReleased" then - if charOrKey == apis.keys.leftCtrl or charOrKey == apis.keys.rightCtrl then + if charOrKey == keys.leftCtrl or charOrKey == keys.rightCtrl then ctrl = false - elseif charOrKey == apis.keys.leftAlt or charOrKey == apis.keys.rightAlt then + elseif charOrKey == keys.leftAlt or charOrKey == keys.rightAlt then alt = false end @@ -402,7 +297,7 @@ kernel.processes.cctmond = function() end end -newtty(apis.term, "1", fifo.pop) +newtty(kernel.apis.term, "1", fifo.pop) for i,v in ipairs({peripheral.find("monitor")}) do v.setTextScale(.5) diff --git a/Src/Hyperion-firmware-cct/lib/modules/cc-tweaked/40_redstone.kmod b/Src/Hyperion-firmware-cct/lib/modules/cc-tweaked/40_redstone.kmod deleted file mode 100644 index 8e06ca6..0000000 --- a/Src/Hyperion-firmware-cct/lib/modules/cc-tweaked/40_redstone.kmod +++ /dev/null @@ -1,26 +0,0 @@ -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/Src/Hyperion-firmware-cct/lib/modules/cc-tweaked/51_gpio.kmod b/Src/Hyperion-firmware-cct/lib/modules/cc-tweaked/51_gpio.kmod new file mode 100644 index 0000000..8263715 --- /dev/null +++ b/Src/Hyperion-firmware-cct/lib/modules/cc-tweaked/51_gpio.kmod @@ -0,0 +1,25 @@ +--:Minify:-- +local kernel=... +local rs=kernel.apis.rs +local sides = {top=1, bottom=2, left=3, right=4, front=5, back=6} +local function newGPIO(side) + return function(mode, data) + if mode=="w" then + if type(data)~="boolean" then error("data: expected bool") end + rs.setOutput(side, data) + elseif mode=="wa" then + if type(data)~="number" then error("data: expected bool") end + rs.setAnalogOutput(side, data) + elseif mode=="r" then + return rs.getInput(side) + elseif mode=="ra" then + return rs.getAnalogInput(side) + end + end +end + +for side, alt in pairs(sides) do + local func=newGPIO(side) + kernel.gpio[side]=func + kernel.gpio[alt]=func +end \ No newline at end of file diff --git a/Src/Hyperion-kernel/boot/kernel.lua b/Src/Hyperion-kernel/boot/kernel.lua index cf3a157..00370f0 100644 --- a/Src/Hyperion-kernel/boot/kernel.lua +++ b/Src/Hyperion-kernel/boot/kernel.lua @@ -1,11 +1,9 @@ --:Minify:-- -local args = {...} -local apis = args[1] -local disks = args[2] -local arch = args[3] -local screen = args[5] -local computer = args[6] -local ifs = args[7] +local EFI=... +local screen=EFI.screenCtl +local ifs=EFI.initfs +local disks=EFI.disks +local arch=EFI.architecture local kernel = {} kernel.LOG_Text="" kernel.version="HyperionOS V1.2.3" @@ -26,28 +24,31 @@ _G.sleep=nil local windowsExp = false function kernel.log(msg, level, c) - c=c or 12 - kernel.LOG_Text = kernel.LOG_Text..string.format("%X",c-1).." "..tostring(computer:time()).." "..kernel.users[kernel.uid].." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n" + c=c or 0x6D6D6D + kernel.LOG_Text = kernel.LOG_Text..tostring(EFI:date()).." "..kernel.users[kernel.uid].." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n" if kernel.status == "start" then screen:setTextColor(c) - screen:print(tostring(computer:time()).." "..kernel.users[kernel.uid].." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg) + screen:print(tostring(EFI:date()).." "..kernel.users[kernel.uid].." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg) elseif kernel.status == "term" then kernel.standbyTask=kernel.currentTask kernel.currentTask=kernel.kernelTask - kernel.vfs.devctl(1,"sfgc",c) - kernel.vfs.write(1,tostring(computer:time()).." "..kernel.users[kernel.uid].." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n") + local file=kernel.vfs.open("/dev/console", "w") + kernel.vfs.devctl(file,"sfgc",c) + kernel.vfs.write(file,tostring(EFI:date()).." "..kernel.users[kernel.uid].." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n") + kernel.vfs.close(file) kernel.currentTask=kernel.standbyTask end end function kernel.PANIC(msg) if kernel.status~="Panic" then - kernel.log("PANIC: "..msg, "PANIC") + kernel.log("PANIC: "..msg, "PANIC", 0xFF0000) pcall(kernel["saveLog"]) kernel.status="Panic" kernel.reason=msg - screen:setTextColor(2) - screen:setBackgroundColor(16) + screen:enable() + screen:setTextColor(0xFF0000) + screen:setBackgroundColor(0x000000) screen:clear() screen:setCursorPos(1,1) screen:print(kernel.LOG_Text) @@ -56,18 +57,19 @@ function kernel.PANIC(msg) kernel.exitMain = true end while true do - local event={computer:getMachineEvent()} + local event={EFI:getMachineEvent()} if event[1]=="keyPressed" then break end end - computer:reboot() + EFI.reboot=true + error("KERNEL PANIC") end kernel.panic=kernel.PANIC if windowsExp then - screen:setTextColor(1) - screen:setBackgroundColor(4) + screen:setTextColor(0xFFFFFF) + screen:setBackgroundColor(0x0000FF) screen:clear() local w,h = screen:getSize() screen:setCursorPos(3,5) @@ -113,7 +115,7 @@ local split = function(str, delim, maxResultCountOrNil) end if not ifs.isFile("/boot/boot.cfg") then - kernel.log("First boot detected writing boot.cfg", "INFO", 3) + kernel.log("First boot detected writing boot.cfg", "INFO", 0x00FF00) ifs.writeAllText("/boot/boot.cfg",ifs.readAllText("/boot/safeboot.cfg")) kernel.firstBoot=true end @@ -136,7 +138,7 @@ for i,v in ipairs(split(fstab,"\n")) do local id="" for i=3,#v do if v:sub(i,i)==";" then - if i==3 then kernel.log("Invalid fstab line... Skipping.","WARN") skip = true break end + if i==3 then kernel.log("Invalid fstab line... Skipping.","WARN", 0xFF8800) skip = true break end id=v:sub(3,i-1) end end @@ -151,7 +153,13 @@ end kernel.log("Disks initialized") function kernel.saveLog() - ifs.writeAllText("/var/log/syslog.log", kernel.LOG_Text) + if kernel.status=="running" then + local file = kernel.vfs.open("/var/log/syslog.log", "w") + kernel.vfs.write(file, kernel.LOG_Text) + kernel.vfs.close(file) + else + ifs.writeAllText("/var/log/syslog.log", kernel.LOG_Text) + end end function kernel.newFifo() @@ -191,7 +199,7 @@ kernel.log("Gathering modules") for _, i in ipairs(ifs.list("/lib/modules")) do local modlist = ifs.list("/lib/modules/"..i) if not modlist then - kernel.log("WARNING: could not list /lib/modules/"..i.." (skipping)", "WARN", 8) + kernel.log("WARNING: could not list /lib/modules/"..i.." (skipping)", "WARN", 0xFF8800) else for _,v in ipairs(modlist) do local prior=tonumber(v:sub(1,2)) @@ -203,8 +211,8 @@ for _, i in ipairs(ifs.list("/lib/modules")) do end kernel.ifs=ifs -kernel.apis=apis -kernel.computer=computer +kernel.apis=EFI.firmware +kernel.EFI=EFI kernel.arch=arch kernel.initdisks=disks kernel.screen=screen @@ -233,16 +241,19 @@ kernel.kernelTask = { kernel.currentTask = kernel.kernelTask function kernel.shutdown() - kernel.computer:shutdown() + kernel.exitMain=true + kernel.status="shutdown" end function kernel.reboot() - kernel.computer:reboot() + kernel.exitMain=true + kernel.status="reboot" end -kernel.syscalls["time"]=function() return kernel.computer:time() end +kernel.syscalls["time"]=function() return kernel.EFI:getEpochMs() end +kernel.syscalls["date"]=function() return kernel.EFI:date() end kernel.syscalls["log"]=kernel.log -kernel.syscalls["getUptime"]=function() return kernel.computer:clock() end +kernel.syscalls["getUptime"]=function() return kernel.EFI:getUptime() end kernel.syscalls["getUsername"]=function(uid) return kernel.users[uid or kernel.uid] end kernel.syscalls["getHostname"]=function() return kernel.hostname end kernel.syscalls["getHost"]=function() return kernel.apis._HOST end @@ -256,17 +267,13 @@ kernel.syscalls["sysdump"]=function() end return rv end -kernel.syscalls["reboot"]=function() - kernel.computer:reboot() -end -kernel.syscalls["shutdown"]=function() - kernel.computer:reboot() -end +kernel.syscalls["reboot"]=kernel.reboot +kernel.syscalls["shutdown"]=kernel.shutdown kernel.log("Running modules") for _,p in ipairs(modules) do for _,v in ipairs(p) do - if kernel.config.showModLoad then kernel.log("Loading module "..v, "DBUG", 5) end + if kernel.config.showModLoad then kernel.log("Loading module "..v, "DBUG", 0x00FFFF) end local code=ifs.readAllText(v) if not code then kernel.panic("Failed to read module "..v) @@ -275,15 +282,20 @@ for _,p in ipairs(modules) do if not func then kernel.panic("ModuLoadErr: "..tostring(err)) end local status, err = xpcall(func,debug.traceback, kernel) if not status then kernel.panic("ModuRunErr: "..tostring(err)) end - if kernel.config.showModLoad then kernel.log("Loaded module "..v, "DBUG", 5) end + if kernel.config.showModLoad then kernel.log("Loaded module "..v, "DBUG", 0x00FFFF) end end end kernel.log("Kernel initialized successfully.") kernel.saveLog() kernel.status="running" +screen:disable() kernel.main() +kernel.panic("Exited main???") if kernel.status=="panic" then - kernel.panic() + kernel.panic(kernel.reason) end -kernel.PANIC("Execution complete") \ No newline at end of file +if kernel.status=="reboot" then + EFI.reboot=true + return true +end \ No newline at end of file diff --git a/Src/Hyperion-kernel/boot/safeboot.cfg b/Src/Hyperion-kernel/boot/safeboot.cfg index 8005543..1c58e65 100644 --- a/Src/Hyperion-kernel/boot/safeboot.cfg +++ b/Src/Hyperion-kernel/boot/safeboot.cfg @@ -7,5 +7,6 @@ return { initPath = "/sbin/init", maxOpenFiles = 128, maxFilesPerTask = 16, - preempt=true + preempt=true, + logTaskExit=true } \ No newline at end of file diff --git a/Src/Hyperion-kernel/lib/modules/hyperion/12_devfs.kmod b/Src/Hyperion-kernel/lib/modules/hyperion/12_devfs.kmod index 6ca94fa..989e4ac 100644 --- a/Src/Hyperion-kernel/lib/modules/hyperion/12_devfs.kmod +++ b/Src/Hyperion-kernel/lib/modules/hyperion/12_devfs.kmod @@ -50,7 +50,7 @@ function proxy:type(path, mode) if type(step[steps[#steps]]) == "table" then return "directory" end - error("ENOENT") + error(type(step[steps[#steps]])) end function proxy:list(path) @@ -140,6 +140,68 @@ function data.zero(op, mode) end end +function data.eeprom(op, mode) + if op=="type" then + return "character device" + elseif op=="open" then + if mode=="r" then + local ptr,eeprom=1,kernel.EFI:getEEPROM() + return { + read=function(amount) + ptr=ptr+amount + return eeprom:sub(ptr-amount, ptr) + end + } + elseif mode=="w" then + if kernel.uid~=0 then error("EACCES") end + return { + write=function(data) + kernel.EFI:setEEPROM(data) + end + } + elseif mode=="a" then + if kernel.uid~=0 then error("EACCES") end + return { + write=function(data) + kernel.EFI:setEEPROM(kernel.EFI:getEEPROM()..data) + end + } + else error("EACCES") + end + end +end + +function data.nvram(op, mode) + if op=="type" then + return "character device" + elseif op=="open" then + if mode=="r" then + local ptr,nvram=1,kernel.EFI:getNvram() + return { + read=function(amount) + ptr=ptr+amount + return nvram:sub(ptr-amount, ptr) + end + } + elseif mode=="w" then + if kernel.uid~=0 then error("EACCES") end + return { + write=function(data) + kernel.EFI:setNvram(data) + end + } + elseif mode=="a" then + if kernel.uid~=0 then error("EACCES") end + return { + write=function(data) + kernel.EFI:setNvram(kernel.EFI:getNvram()..data) + end + } + else error("EACCES") + end + end +end + data["disk"]={} kernel.devfs={} kernel.devfs.data=data diff --git a/Src/Hyperion-kernel/lib/modules/hyperion/12_procfs.kmod b/Src/Hyperion-kernel/lib/modules/hyperion/12_procfs.kmod index 2688e75..8dc6790 100644 --- a/Src/Hyperion-kernel/lib/modules/hyperion/12_procfs.kmod +++ b/Src/Hyperion-kernel/lib/modules/hyperion/12_procfs.kmod @@ -258,7 +258,7 @@ function proxy:fileExists(path) return ok end -data.uptime=simpleFile(function()return tostring(kernel.computer:getUptime())end,function()error("EACCES")end) +data.uptime=simpleFile(function()return tostring(kernel.EFI:getUptime())end,function()error("EACCES")end) kernel.procfs={} kernel.procfs.data=data kernel.procfs.proxy=proxy diff --git a/Src/Hyperion-kernel/lib/modules/hyperion/19_fstab.kmod b/Src/Hyperion-kernel/lib/modules/hyperion/19_fstab.kmod index f43fa24..9034cea 100644 --- a/Src/Hyperion-kernel/lib/modules/hyperion/19_fstab.kmod +++ b/Src/Hyperion-kernel/lib/modules/hyperion/19_fstab.kmod @@ -21,7 +21,7 @@ for _, line in ipairs(string.split(kernel.fstab, "\n")) do end if not semicolon_pos or semicolon_pos == 3 then - kernel.log("Invalid fstab line: "..line.." ... Skipping.", "WARN", 8) + kernel.log("Invalid fstab line: "..line.." ... Skipping.", "WARN", 0xFF8800) else local id = line:sub(3, semicolon_pos - 1) local path = trim(line:sub(semicolon_pos + 1)) diff --git a/Src/Hyperion-kernel/lib/modules/hyperion/20_socket.kmod b/Src/Hyperion-kernel/lib/modules/hyperion/20_socket.kmod index f1a2380..6312404 100644 --- a/Src/Hyperion-kernel/lib/modules/hyperion/20_socket.kmod +++ b/Src/Hyperion-kernel/lib/modules/hyperion/20_socket.kmod @@ -2,10 +2,7 @@ -- Supports: -- AF_UNIX - local IPC via /var/run/*.sock paths -- AF_INET - network sockets with three backends: --- rednet://0.0.B.C or rednet+PROTO://0.0.B.C -> CC rednet (computer B*256+C) --- modem://0.0.B.C -> raw CC modem frames --- http://host/path or https://... -> HTTP via CC http API --- A.B.C.D (dotted quad, non-zero A) -> HTTP +-- Implemented by drivers but expect http:// and https:// -- -- Socket lifecycle: -- fd = syscall.socket(domain, socktype) -- "unix"/"inet", "stream"/"dgram" @@ -18,539 +15,9 @@ -- syscall.sockshutdown(fd) -- half-close send side -- -- normal vfs.close(fd) closes the socket -local kernel = ... +local kernel=... +local socket={} +kernel.socket=socket -local sockets = {} -local unixSocks = {} -local nextSockId = 1 - -local function allocSockId() - local id = nextSockId - nextSockId = nextSockId + 1 - return id -end - -local function parseAddress(addr) - if not addr then error("EINVAL") end - - if addr:sub(1,1) == "/" or addr:sub(1,5) == "unix:" then - local path = addr:sub(1,5) == "unix:" and addr:sub(6) or addr - return { backend="unix", path=path } - end - - local rproto, raddr = addr:match("^rednet%+?([^:/]*)://(.+)$") - if raddr then - local a,b,c,d = raddr:match("^(%d+)%.(%d+)%.(%d+)%.(%d+)$") - if not a then error("EINVAL: bad rednet address " .. raddr) end - local compId = tonumber(c)*256 + tonumber(d) - return { backend="rednet", compId=compId, - protocol=(rproto ~= "" and rproto or "hyperion") } - end - - local maddr = addr:match("^modem://(.+)$") - if maddr then - local a,b,c,d = maddr:match("^(%d+)%.(%d+)%.(%d+)%.(%d+)$") - if not a then error("EINVAL: bad modem address " .. maddr) end - local compId = tonumber(c)*256 + tonumber(d) - local port = tonumber(maddr:match(":(%d+)$")) or 0 - return { backend="modem", compId=compId, port=port } - end - - local scheme, rest = addr:match("^(https?)://(.+)$") - if scheme then - return { backend=scheme, url=addr } - end - - local a,b,c,d = addr:match("^(%d+)%.(%d+)%.(%d+)%.(%d+)") - if a and tonumber(a) ~= 0 then - return { backend="http", url="http://" .. addr } - end - - error("EINVAL: unrecognised address format: " .. tostring(addr)) -end - -local rednetOpen = false -local function ensureRednet() - if rednetOpen then return end - local rn = kernel.apis and kernel.apis.rednet - if not rn then error("ENODEV: no rednet API available") end - local peripheral = kernel.apis.peripheral - if peripheral then - for _, name in ipairs(peripheral.getNames and peripheral.getNames() or {}) do - if peripheral.getType(name) == "modem" then - pcall(rn.open, name) - end - end - end - rednetOpen = true -end - -local function getModem() - local peripheral = kernel.apis and kernel.apis.peripheral - if not peripheral then error("ENODEV") end - for _, name in ipairs(peripheral.getNames and peripheral.getNames() or {}) do - if peripheral.getType(name) == "modem" then - local m = peripheral.wrap(name) - if m then return m, name end - end - end - error("ENODEV: no modem peripheral found") -end - -local function pumpEvents() - local ev = kernel.computer:getMachineEvent() - while ev do - if ev == "rednet_message" then - for _, sock in pairs(sockets) do - if sock.backend == "rednet" and sock.bound then - if sock.address.protocol == tostring(select(4, table.unpack({ev}))) or - sock.address.protocol == "hyperion" then - end - end - end - end - ev = kernel.computer:getMachineEvent() - end -end - -local function pollEvent() - local results = table.pack(kernel.computer:getMachineEvent()) - if results.n == 0 or results[1] == nil then return nil end - return results -end - -local function dispatchEvent(ev) - if not ev then return end - local evtype = ev[1] - - if evtype == "rednet_message" then - local senderId = ev[2] - local message = ev[3] - local protocol = ev[4] or "hyperion" - for _, sock in pairs(sockets) do - if sock.backend == "rednet" and (sock.listening or sock.connected) then - if sock.address and sock.address.protocol == protocol then - table.insert(sock.rxbuf, { from=senderId, data=message }) - end - end - end - - elseif evtype == "modem_message" then - local channel = ev[3] - local msg = ev[5] - local fromCh = ev[4] - for _, sock in pairs(sockets) do - if sock.backend == "modem" and sock.modemChannel == channel then - table.insert(sock.rxbuf, { from=fromCh, data=msg }) - end - end - - elseif evtype == "http_success" then - local url = ev[2] - local handle = ev[3] - for _, sock in pairs(sockets) do - if sock.backend == "http" or sock.backend == "https" then - if sock.pendingUrl == url then - local body = handle.readAll and handle.readAll() or "" - handle.close() - table.insert(sock.rxbuf, { data=body, done=true }) - sock.pendingUrl = nil - sock.connected = true - end - end - end - - elseif evtype == "http_failure" then - local url = ev[2] - local err = ev[3] - for _, sock in pairs(sockets) do - if (sock.backend == "http" or sock.backend == "https") and - sock.pendingUrl == url then - sock.error = err - sock.pendingUrl = nil - end - end - end -end - -local function pumpAll() - local ev = pollEvent() - while ev do - dispatchEvent(ev) - ev = pollEvent() - end -end - -local function newSocket(domain, socktype) - local sock = { - id = allocSockId(), - domain = domain, -- "unix" | "inet" - socktype = socktype, -- "stream" | "dgram" - backend = nil, - state = "idle", -- idle | bound | listening | connected | closed - rxbuf = {}, - txbuf = {}, - backlog = {}, - address = nil, - peer = nil, - modemChannel = nil, - modem = nil, - pendingUrl = nil, - bound = false, - listening = false, - connected = false, - error = nil, - } - sockets[sock.id] = sock - return sock -end - -local sockSend, sockClose - -local function socketToFd(sock) - return { - isSocket = true, - sockId = sock.id, - mode = "rw", - meta = { etype=0, owner=0, group=0, perms=0x1FF, cmeta="" }, - type = "socket", - refcount = 1, - handle = { - read = function(count) - pumpAll() - if #sock.rxbuf == 0 then return "" end - local item = table.remove(sock.rxbuf, 1) - local data = type(item) == "table" and (item.data or "") or tostring(item) - if count and #data > count then - table.insert(sock.rxbuf, 1, { data=data:sub(count+1), from=item.from }) - data = data:sub(1, count) - end - return data - end, - write = function(data) - if sock.state == "closed" then error("EBADF") end - return sockSend(sock, data) - end, - close = function() - sockClose(sock) - end, - } - } -end - -sockSend = function(sock, data) - if sock.backend == "unix" then - local peer = sock.peer - if not peer then error("ENOTCONN") end - table.insert(peer.rxbuf, { data=data }) - return #data - - elseif sock.backend == "rednet" then - ensureRednet() - local rn = kernel.apis.rednet - rn.send(sock.address.compId, data, sock.address.protocol) - return #data - - elseif sock.backend == "modem" then - local modem = sock.modem - if not modem then error("ENOTCONN") end - modem.transmit(sock.address.port, sock.modemChannel or 0, data) - return #data - - elseif sock.backend == "http" or sock.backend == "https" then - local http = kernel.apis and kernel.apis.http - if not http then error("ENODEV: no http API") end - local url = sock.address.url - local ok, err = pcall(http.request, url, data, { - ["Content-Type"] = "application/octet-stream" - }) - if not ok then error("ENETDOWN: " .. tostring(err)) end - sock.pendingUrl = url - return #data - end - error("EPROTONOSUPPORT") -end - -sockClose = function(sock) - if sock.state == "closed" then return end - sock.state = "closed" - - if sock.backend == "unix" then - if sock.peer then - sock.peer.peer = nil - sock.peer.state = "closed" - end - if sock.bound and sock.address and sock.address.path then - unixSocks[sock.address.path] = nil - end - - elseif sock.backend == "modem" and sock.modem and sock.modemChannel then - pcall(sock.modem.close, sock.modemChannel) - - elseif sock.backend == "rednet" then - end - - sockets[sock.id] = nil -end - -kernel.syscalls["socket"] = function(domain, socktype) - domain = domain or "inet" - socktype = socktype or "stream" - if domain ~= "unix" and domain ~= "inet" then error("EAFNOSUPPORT") end - if socktype ~= "stream" and socktype ~= "dgram" then error("EPROTOTYPE") end - - local sock = newSocket(domain, socktype) - local fdobj = socketToFd(sock) - local fd = kernel.vfs.newfd(fdobj) - return fd -end - -kernel.syscalls["bind"] = function(fd, address) - local task = kernel.currentTask - local fdobj = task.fd[fd] - if not fdobj or not fdobj.isSocket then error("ENOTSOCK") end - local sock = sockets[fdobj.sockId] - if not sock then error("EBADF") end - if sock.bound then error("EINVAL") end - - local parsed = parseAddress(address) - - if parsed.backend == "unix" then - local existing = unixSocks[parsed.path] - if existing then - if existing.state == "closed" then - unixSocks[parsed.path] = nil - else - error("EADDRINUSE") - end - end - sock.backend = "unix" - sock.address = parsed - sock.bound = true - sock.state = "bound" - unixSocks[parsed.path] = sock - - elseif parsed.backend == "rednet" then - ensureRednet() - sock.backend = "rednet" - sock.address = parsed - sock.bound = true - sock.state = "bound" - - elseif parsed.backend == "modem" then - local modem, side = getModem() - sock.backend = "modem" - sock.address = parsed - sock.modem = modem - sock.modemChannel = parsed.port - sock.bound = true - sock.state = "bound" - modem.open(parsed.port) - - else - error("EOPNOTSUPP: cannot bind to " .. parsed.backend .. " address") - end -end - -kernel.syscalls["listen"] = function(fd, backlog) - local task = kernel.currentTask - local fdobj = task.fd[fd] - if not fdobj or not fdobj.isSocket then error("ENOTSOCK") end - local sock = sockets[fdobj.sockId] - if not sock then error("EBADF") end - if not sock.bound then error("EDESTADDRREQ") end - sock.listening = true - sock.state = "listening" - sock.maxBacklog = backlog or 5 -end - -kernel.syscalls["accept"] = function(fd) - local task = kernel.currentTask - local fdobj = task.fd[fd] - if not fdobj or not fdobj.isSocket then error("ENOTSOCK") end - local sock = sockets[fdobj.sockId] - if not sock then error("EBADF") end - if not sock.listening then error("EINVAL") end - - local deadline = kernel.computer:time() + 30000 - while #sock.backlog == 0 do - pumpAll() - if kernel.computer:time() > deadline then error("ETIMEDOUT") end - coroutine.yield() - end - - local clientSock = table.remove(sock.backlog, 1) - local cfdobj = socketToFd(clientSock) - local newfd = kernel.vfs.newfd(cfdobj) - return newfd -end - -kernel.syscalls["connect"] = function(fd, address) - local task = kernel.currentTask - local fdobj = task.fd[fd] - if not fdobj or not fdobj.isSocket then error("ENOTSOCK") end - local sock = sockets[fdobj.sockId] - if not sock then error("EBADF") end - if sock.connected then error("EISCONN") end - - local parsed = parseAddress(address) - sock.address = parsed - sock.backend = parsed.backend - - if parsed.backend == "unix" then - local server = unixSocks[parsed.path] - if not server then error("ECONNREFUSED") end - if not server.listening then error("ECONNREFUSED") end - if #server.backlog >= (server.maxBacklog or 5) then error("ECONNREFUSED") end - - local serverPeer = newSocket("unix", sock.socktype) - serverPeer.backend = "unix" - serverPeer.connected = true - serverPeer.state = "connected" - serverPeer.peer = sock - - sock.peer = serverPeer - sock.connected = true - sock.state = "connected" - - table.insert(server.backlog, serverPeer) - - elseif parsed.backend == "rednet" then - ensureRednet() - sock.connected = true - sock.state = "connected" - - elseif parsed.backend == "modem" then - local modem, side = getModem() - local replyChannel = math.random(1024, 65534) - sock.modem = modem - sock.modemChannel = replyChannel - sock.connected = true - sock.state = "connected" - modem.open(replyChannel) - - elseif parsed.backend == "http" or parsed.backend == "https" then - sock.connected = true - sock.state = "connected" - - else - error("EAFNOSUPPORT") - end -end - -kernel.syscalls["send"] = function(fd, data) - local task = kernel.currentTask - local fdobj = task.fd[fd] - if not fdobj or not fdobj.isSocket then error("ENOTSOCK") end - local sock = sockets[fdobj.sockId] - if not sock then error("EBADF") end - return sockSend(sock, data) -end - -kernel.syscalls["recv"] = function(fd, maxlen, timeout_ms) - local task = kernel.currentTask - local fdobj = task.fd[fd] - if not fdobj or not fdobj.isSocket then error("ENOTSOCK") end - local sock = sockets[fdobj.sockId] - if not sock then error("EBADF") end - - local deadline = kernel.computer:time() + (timeout_ms or 10000) - while #sock.rxbuf == 0 do - pumpAll() - if #sock.rxbuf > 0 then break end - if sock.state == "closed" or sock.error then - if sock.error then error("ECONNRESET: " .. tostring(sock.error)) end - return "" - end - if kernel.computer:time() > deadline then return "" end - coroutine.yield() - end - - local item = table.remove(sock.rxbuf, 1) - local data = type(item) == "table" and (item.data or "") or tostring(item) - if maxlen and #data > maxlen then - table.insert(sock.rxbuf, 1, { data=data:sub(maxlen+1), from=item and item.from }) - data = data:sub(1, maxlen) - end - return data -end - -kernel.syscalls["sockshutdown"] = function(fd) - local task = kernel.currentTask - local fdobj = task.fd[fd] - if not fdobj or not fdobj.isSocket then error("ENOTSOCK") end - local sock = sockets[fdobj.sockId] - if sock then sockClose(sock) end -end - -kernel.syscalls["getpeername"] = function(fd) - local task = kernel.currentTask - local fdobj = task.fd[fd] - if not fdobj or not fdobj.isSocket then error("ENOTSOCK") end - local sock = sockets[fdobj.sockId] - if not sock or not sock.connected then error("ENOTCONN") end - if sock.address then return sock.address end - return nil -end - -kernel.syscalls["getsockname"] = function(fd) - local task = kernel.currentTask - local fdobj = task.fd[fd] - if not fdobj or not fdobj.isSocket then error("ENOTSOCK") end - local sock = sockets[fdobj.sockId] - if not sock then error("EBADF") end - return sock.address -end - -kernel.syscalls["httpget"] = function(url, headers) - local http = kernel.apis and kernel.apis.http - if not http then error("ENODEV: no http API") end - - local ok, err = pcall(http.request, url, nil, headers) - if not ok then error("ENETDOWN: " .. tostring(err)) end - - local deadline = kernel.computer:time() + 15000 - while true do - local ev = pollEvent() - if ev then - if ev[1] == "http_success" and ev[2] == url then - local handle = ev[3] - local body = handle.readAll and handle.readAll() or "" - handle.close() - return body - elseif ev[1] == "http_failure" and ev[2] == url then - error("ECONNREFUSED: " .. tostring(ev[3])) - else - dispatchEvent(ev) - end - end - if kernel.computer:time() > deadline then error("ETIMEDOUT") end - coroutine.yield() - end -end - -kernel.syscalls["resolve"] = function(hostname) - if hostname:match("^%d+%.%d+%.%d+%.%d+$") then return hostname end - - local a,b,c,d = hostname:match("^(%d+)%.(%d+)%.(%d+)%.(%d+)$") - if a and tonumber(a) == 0 and tonumber(b) == 0 then - return hostname - end - - local http = kernel.apis and kernel.apis.http - if not http then error("ENODEV: no http API for DNS") end - - local url = "https://cloudflare-dns.com/dns-query?name=" .. hostname .. "&type=A" - local body = kernel.syscalls["httpget"](url, { - ["Accept"] = "application/dns-json" - }) - - local ip = body:match('"type":1[^}]*"data":"([%d%.]+)"') - if not ip then error("ENOENT: could not resolve " .. hostname) end - return ip -end - -kernel.sockets = sockets -kernel.unixSockets = unixSocks kernel.log("Loaded socket module") diff --git a/Src/Hyperion-kernel/lib/modules/hyperion/40_auth.kmod b/Src/Hyperion-kernel/lib/modules/hyperion/40_auth.kmod index 3c11560..05229f7 100644 --- a/Src/Hyperion-kernel/lib/modules/hyperion/40_auth.kmod +++ b/Src/Hyperion-kernel/lib/modules/hyperion/40_auth.kmod @@ -139,7 +139,7 @@ end if not blake2s then error("Failed to load blake2s") end if not kernel.vfs.exists("/etc/pam.d/secret") then - kernel.log("PAM SECRET REGENERATING PLEASE USE ROOT") + kernel.log("PAM SECRET REGENERATING PLEASE USE ROOT", "WARN", 0xFF8800) local key = "" for i = 1, 256 do key = key .. string.char(math.random(0, 255)) end local handle = kernel.vfs.open("/etc/pam.d/secret", "w") diff --git a/Src/Hyperion-kernel/lib/modules/hyperion/45_hypervisor.kmod b/Src/Hyperion-kernel/lib/modules/hyperion/45_hypervisor.kmod index 7f414e6..6317c8d 100644 --- a/Src/Hyperion-kernel/lib/modules/hyperion/45_hypervisor.kmod +++ b/Src/Hyperion-kernel/lib/modules/hyperion/45_hypervisor.kmod @@ -41,11 +41,11 @@ local function createTask(func, name, envars, args, tgid, real_uid, eff_uid) if kernel.config.logTaskExit then if not ok then - kernel.log("Task " .. tostring(id) .. " exited with err: " .. tostring(err), "ERROR", 2) + kernel.log("Task " .. tostring(id) .. " exited with err: " .. tostring(err), "ERROR", 0xFF0000) elseif err then - kernel.log("Task " .. tostring(id) .. " exited with code: " .. tostring(err), "INFO") + kernel.log("Task " .. tostring(id) .. " exited with code: " .. tostring(err), "DBUG", 0x00FFFF) else - kernel.log("Task " .. tostring(id) .. " exited without code", "INFO") + kernel.log("Task " .. tostring(id) .. " exited without code", "DBUG", 0x00FFFF) end end @@ -110,7 +110,7 @@ function sys.execspawn(path, name, envars, args, tgid) kernel.log( "execspawn: suid exec '" .. path .. "' caller_uid=" .. tostring(real_uid) .. - " -> euid=" .. tostring(euid), "INFO" + " -> euid=" .. tostring(euid) ) end @@ -136,9 +136,9 @@ function sys.exec(path, args, envars) local ok, err = xpcall(func, debug.traceback, table.unpack(task.args)) if kernel.config.logTaskExit then if not ok then - kernel.log("Task " .. tostring(task.pid) .. " exec '" .. path .. "' err: " .. tostring(err), "ERROR", 2) + kernel.log("Task " .. tostring(task.pid) .. " exec '" .. path .. "' err: " .. tostring(err), "ERROR", 0xFF0000) else - kernel.log("Task " .. tostring(task.pid) .. " exec '" .. path .. "' exited: " .. tostring(err), "INFO") + kernel.log("Task " .. tostring(task.pid) .. " exec '" .. path .. "' exited: " .. tostring(err), "DBUG", 0x00FFFF) end end if type(err) == "number" then tasks[tostring(task.pid)].exit = err end @@ -155,7 +155,7 @@ end function sys.sleep(s) kernel.currentTask.status = "S" - kernel.currentTask.sleep = kernel.computer:time() + s * 1000 + kernel.currentTask.sleep = kernel.EFI:getEpochMs() + s * 1000 coroutine.yield() end @@ -260,9 +260,9 @@ function sys.exit(code) local task = kernel.currentTask if kernel.config.logTaskExit then if code then - kernel.log("Task " .. tostring(task.pid) .. " exited with code: " .. tostring(code), "INFO") + kernel.log("Task " .. tostring(task.pid) .. " exited with code: " .. tostring(code), "DBUG", 0x00FFFF) else - kernel.log("Task " .. tostring(task.pid) .. " exited without code", "INFO") + kernel.log("Task " .. tostring(task.pid) .. " exited without code", "DBUG", 0x00FFFF) end end tasks[tostring(task.pid)].status = "Z" @@ -303,9 +303,9 @@ local function reapDeadTasks() task.syscallReturn = nil task.sleep = nil task.fd = nil - task.reapTime = kernel.computer:time() + 30000 + task.reapTime = kernel.EFI:getEpochMs() + 30000 - elseif task.reapTime and kernel.computer:time() > task.reapTime + elseif task.reapTime and kernel.EFI:getEpochMs() > task.reapTime and task.status == "Z" then for _, child in ipairs(task.children) do child.parent = tasks["1"] @@ -343,7 +343,7 @@ function kernel.main() local taskTimes = {} for pid, task in pairs(tasks) do - if task.status == "S" and kernel.computer:time() >= task.sleep then + if task.status == "S" and kernel.EFI:getEpochMs() >= task.sleep then task.status = "R" task.sleep = 0 end @@ -382,7 +382,7 @@ function kernel.main() end if task.status == "R" then - local startTime = kernel.computer:time() + local startTime = kernel.EFI:getEpochMs() local ret if kernel.config.preempt then @@ -391,7 +391,7 @@ function kernel.main() ret = { coroutine.resume(task.coro, table.unpack(task.syscallReturn)) } end - local elapsed = kernel.computer:time() - startTime + local elapsed = kernel.EFI:getEpochMs() - startTime task.lastTime = elapsed task.totalTime = (task.totalTime or 0) + elapsed task.numRuns = (task.numRuns or 0) + 1 @@ -403,7 +403,7 @@ function kernel.main() if elapsed >= Tmax then Tmax_hit = Tmax_hit + 1 end if ret[1] == "error" or ret[1] == false then - kernel.log("processHandlerException: " .. tostring(ret[2]), "ERROR", 2) + kernel.log("processHandlerException: " .. tostring(ret[2]), "ERROR", 0xFF0000) task.status = "Z" task.exit = "processHandlerException: " .. tostring(ret[2]) @@ -418,9 +418,9 @@ function kernel.main() local scname = ret[3] if kernel.syscalls[scname] then if kernel.config.debugSyscalls then - kernel.log("Task " .. task.pid .. " syscall: " .. scname, "DBUG", 5) + kernel.log("Task " .. task.pid .. " syscall: " .. scname, "DBUG", 0x00FFFF) for i = 4, #ret do - kernel.log(" inval[" .. (i-3) .. "] = " .. tostring(ret[i]), "DBUG", 5) + kernel.log(" inval[" .. (i-3) .. "] = " .. tostring(ret[i]), "DBUG", 0x00FFFF) end end @@ -428,12 +428,12 @@ function kernel.main() if kernel.config.debugSyscalls then if not sysret[1] then - kernel.log("Task " .. task.pid .. " syscall " .. scname .. " failed: " .. tostring(sysret[2]), "ERROR", 2) + kernel.log("Task " .. task.pid .. " syscall " .. scname .. " failed: " .. tostring(sysret[2]), "ERROR", 0xFF0000) else - kernel.log("Task " .. task.pid .. " syscall " .. scname .. " ok, " .. (#sysret-1) .. " retvals", "DBUG", 5) + kernel.log("Task " .. task.pid .. " syscall " .. scname .. " ok, " .. (#sysret-1) .. " retvals", "DBUG", 0x00FFFF) for i = 2, #sysret do local v = type(sysret[i]) == "table" and table.serialize(sysret[i]) or tostring(sysret[i]) - kernel.log(" retval[" .. (i-1) .. "] = " .. v, "DBUG", 5) + kernel.log(" retval[" .. (i-1) .. "] = " .. v, "DBUG", 0x00FFFF) end end end diff --git a/Src/Hyperion-kernel/lib/modules/hyperion/50_gpio.kmod b/Src/Hyperion-kernel/lib/modules/hyperion/50_gpio.kmod index 1e43f63..e022fef 100644 --- a/Src/Hyperion-kernel/lib/modules/hyperion/50_gpio.kmod +++ b/Src/Hyperion-kernel/lib/modules/hyperion/50_gpio.kmod @@ -9,8 +9,20 @@ sysc["gpio_write"]=function(pin, data) end end +sysc["gpio_writeAnalog"]=function(pin, data) + if kernel.gpio[pin] then + return kernel.gpio[pin]("wa", data) + end +end + sysc["gpio_read"]=function(pin) if kernel.gpio[pin] then return kernel.gpio[pin]("r") end +end + +sysc["gpio_readAnalog"]=function(pin) + if kernel.gpio[pin] then + return kernel.gpio[pin]("ra") + end end \ No newline at end of file diff --git a/Src/Hyperion-kernel/lib/modules/hyperion/90_init.kmod b/Src/Hyperion-kernel/lib/modules/hyperion/90_init.kmod index 0e94960..1727621 100644 --- a/Src/Hyperion-kernel/lib/modules/hyperion/90_init.kmod +++ b/Src/Hyperion-kernel/lib/modules/hyperion/90_init.kmod @@ -9,11 +9,13 @@ if not initOk then end local handle = kernel.vfs.open(kernel.config.initPath, "r") +if not handle then kernel.panic("Failed to open "..kernel.config.initPath) end local data = kernel.vfs.read(handle, 1024 * 1024 * 4) +if not handle then kernel.panic("Failed to read "..kernel.config.initPath) end kernel.vfs.close(handle) local initFunc, err = load(data, "@sysinit", "t", kernel._U) -if not initFunc then error("Failed to load init system: " .. err) end +if not initFunc then kernel.PANIC("Failed to load init system: " .. err) end kernel.tasks["1"] = { coro = coroutine.create(function() diff --git a/Src/Hyperion-kernel/lib/modules/hyperion/91_login.kmod b/Src/Hyperion-kernel/lib/modules/hyperion/91_login.kmod index 229b9b2..448da86 100644 --- a/Src/Hyperion-kernel/lib/modules/hyperion/91_login.kmod +++ b/Src/Hyperion-kernel/lib/modules/hyperion/91_login.kmod @@ -4,6 +4,6 @@ local kernel = ... kernel.processes.login = function() local ok, err = pcall(kernel.hpv.execspawn, "/bin/login", "login") if not ok then - kernel.log("Failed to exec /bin/login: " .. tostring(err), "ERROR", 2) + kernel.log("Failed to exec /bin/login: " .. tostring(err), "ERROR", 0xFF0000) end end diff --git a/Src/Hyperion-kernel/lib/modules/hyperion/92_setup.kmod b/Src/Hyperion-kernel/lib/modules/hyperion/92_setup.kmod index 5fcdc09..1f7504b 100644 --- a/Src/Hyperion-kernel/lib/modules/hyperion/92_setup.kmod +++ b/Src/Hyperion-kernel/lib/modules/hyperion/92_setup.kmod @@ -1,88 +1,88 @@ --:Minify:-- local kernel = ... -local P = kernel.vfs.P -local PERM = kernel.vfs.PERM - -local RW_R_R = P.OWNER_R + P.OWNER_W + P.GROUP_R + P.WORLD_R -local RWX_RX_RX = P.OWNER_R + P.OWNER_W + P.OWNER_X - + P.GROUP_R + P.GROUP_X - + P.WORLD_R + P.WORLD_X -local RW_R__ = P.OWNER_R + P.OWNER_W + P.GROUP_R -local RW____ = P.OWNER_R + P.OWNER_W -local RWXRWXRWX = PERM.RWXRWXRWX -local SUID_755 = PERM.SUID_755 - -local META_VERSION = 0x02 -local rootDisk = kernel.disks["$"] - -local function makeEntry(name, etype, owner, group, perms, cmeta) - cmeta = cmeta or "" - local plo = perms % 256 - local phi = math.floor(perms / 256) % 256 - local olo = (owner or 0) % 256 - local ohi = math.floor((owner or 0) / 256) % 256 - local glo = (group or 0) % 256 - local ghi = math.floor((group or 0) / 256) % 256 - return string.char(#name) .. name - .. string.char(etype, olo, ohi, glo, ghi, plo, phi) - .. string.char(#cmeta) .. cmeta -end - -local REG = 0x00 - -local function mergeMeta(dir, entries) - local diskDir = dir - if diskDir:sub(1,1) == "/" then diskDir = diskDir:sub(2) end - local metaPath = (diskDir == "" and ".meta" or diskDir .. "/.meta") - - local existing = {} - local rok, rf = pcall(function() return rootDisk:open(metaPath, "r") end) - if rok and rf then - local raw = rf.read(65535) - if rf.close then rf.close() end - existing = (kernel.vfs._parseMetafile and kernel.vfs._parseMetafile(raw)) or {} - end - - for _, e in ipairs(entries) do - local name = e[1] - local etype = e[2] or REG - local owner = e[3] or 0 - local group = e[4] or 0 - local perms = e[5] or RWX_RX_RX - local cmeta = e[6] or "" - existing[name] = { - etype = etype, - owner = owner, - group = group, - perms = perms, - cmeta = cmeta, - } - end - - local data = string.char(META_VERSION) - for name, m in pairs(existing) do - data = data .. makeEntry( - name, - m.etype or REG, - m.owner or 0, - m.group or 0, - m.perms or RWX_RX_RX, - m.cmeta or "" - ) - end - - local ok, err = pcall(function() - local f = rootDisk:open(metaPath, "w") - f.write(data) - f.close() - end) - if not ok then - kernel.log("permissions: failed to write " .. metaPath .. ": " .. tostring(err), "WARN", 8) - end -end - if kernel.firstBoot then + local P = kernel.vfs.P + local PERM = kernel.vfs.PERM + + local RW_R_R = P.OWNER_R + P.OWNER_W + P.GROUP_R + P.WORLD_R + local RWX_RX_RX = P.OWNER_R + P.OWNER_W + P.OWNER_X + + P.GROUP_R + P.GROUP_X + + P.WORLD_R + P.WORLD_X + local RW_R__ = P.OWNER_R + P.OWNER_W + P.GROUP_R + local RW____ = P.OWNER_R + P.OWNER_W + local RWXRWXRWX = PERM.RWXRWXRWX + local SUID_755 = PERM.SUID_755 + + local META_VERSION = 0x02 + local rootDisk = kernel.disks["$"] + + local function makeEntry(name, etype, owner, group, perms, cmeta) + cmeta = cmeta or "" + local plo = perms % 256 + local phi = math.floor(perms / 256) % 256 + local olo = (owner or 0) % 256 + local ohi = math.floor((owner or 0) / 256) % 256 + local glo = (group or 0) % 256 + local ghi = math.floor((group or 0) / 256) % 256 + return string.char(#name) .. name + .. string.char(etype, olo, ohi, glo, ghi, plo, phi) + .. string.char(#cmeta) .. cmeta + end + + local REG = 0x00 + + local function mergeMeta(dir, entries) + local diskDir = dir + if diskDir:sub(1,1) == "/" then diskDir = diskDir:sub(2) end + local metaPath = (diskDir == "" and ".meta" or diskDir .. "/.meta") + + local existing = {} + local rok, rf = pcall(function() return rootDisk:open(metaPath, "r") end) + if rok and rf then + local raw = rf.read(65535) + if rf.close then rf.close() end + existing = (kernel.vfs._parseMetafile and kernel.vfs._parseMetafile(raw)) or {} + end + + for _, e in ipairs(entries) do + local name = e[1] + local etype = e[2] or REG + local owner = e[3] or 0 + local group = e[4] or 0 + local perms = e[5] or RWX_RX_RX + local cmeta = e[6] or "" + existing[name] = { + etype = etype, + owner = owner, + group = group, + perms = perms, + cmeta = cmeta, + } + end + + local data = string.char(META_VERSION) + for name, m in pairs(existing) do + data = data .. makeEntry( + name, + m.etype or REG, + m.owner or 0, + m.group or 0, + m.perms or RWX_RX_RX, + m.cmeta or "" + ) + end + + local ok, err = pcall(function() + local f = rootDisk:open(metaPath, "w") + f.write(data) + f.close() + end) + if not ok then + kernel.log("permissions: failed to write " .. metaPath .. ": " .. tostring(err), "WARN", 0xFF8800) + end + end + kernel.log("Seeding filesystem permissions...") mergeMeta("/", { @@ -117,4 +117,4 @@ if kernel.firstBoot then }) kernel.log("Filesystem permissions seeded.") -end +end \ No newline at end of file diff --git a/Src/hysh/bin/help b/Src/hysh/bin/help index ccd0dfd..f8938aa 100644 --- a/Src/hysh/bin/help +++ b/Src/hysh/bin/help @@ -261,16 +261,16 @@ local function render() syscall.write(1, "\n") end end - syscall.devctl(1, "sfgc", 16) - syscall.devctl(1, "sbgc", 13) + syscall.devctl(1, "sfgc", 0x000000) + syscall.devctl(1, "sbgc", 0xDBDBDB) local pct = math.floor(math.min(100, (scroll + pageSize) / totalLines * 100)) local status = string.format(" help -- line %d/%d (%d%%) [up/down: scroll q: quit] ", scroll + 1, totalLines, pct) if #status > screenW then status = status:sub(1, screenW) end syscall.devctl(1, "spos", 1, screenH) syscall.write(1, status .. string.rep(" ", screenW - #status)) - syscall.devctl(1, "sfgc", 1) - syscall.devctl(1, "sbgc", 16) + syscall.devctl(1, "sfgc", 0xFFFFFF) + syscall.devctl(1, "sbgc", 0x000000) dirty = false end @@ -281,7 +281,7 @@ if totalLines <= pageSize then syscall.devctl(1, "sfgc", line[2]) syscall.write(1, line[1] .. "\n") end - syscall.devctl(1, "sfgc", 1) + syscall.devctl(1, "sfgc", 0xFFFFFF) return end @@ -305,5 +305,5 @@ end syscall.devctl(1, "clear") syscall.devctl(1, "spos", 1, 1) -syscall.devctl(1, "sfgc", 1) -syscall.devctl(1, "sbgc", 16) +syscall.devctl(1, "sfgc", 0xFFFFFF) +syscall.devctl(1, "sbgc", 0x000000) diff --git a/Src/hysh/bin/hfetch b/Src/hysh/bin/hfetch index a640241..9839dd5 100644 --- a/Src/hysh/bin/hfetch +++ b/Src/hysh/bin/hfetch @@ -3,11 +3,11 @@ -- 1=white, 2=red, 3=green, 4=blue, 5=cyan, 6=magenta, 7=yellow -- 8=orange, 9=lime, 10=lightcyan, 11=brown, 12=darkgrey, 13=lightgrey, 14=purple, 15=chartreuse, 16=black -local C_LOGO = 5 -- cyan -local C_WHITE = 1 -- white -local C_LABEL = 13 -- light grey (key names) -local C_SEP = 12 -- dark grey (---- separator) -local C_USER = 3 -- green (user@host) +local C_LOGO = 0x00FFFF -- cyan +local C_WHITE = 0xFFFFFF -- white +local C_LABEL = 0xDBDBDB -- light grey (key names) +local C_SEP = 0x6D6D6D -- dark grey (---- separator) +local C_USER = 0x00FF00 -- green (user@host) local function c(col) syscall.devctl(1, "sfgc", col) end diff --git a/Src/hysh/bin/hysh b/Src/hysh/bin/hysh index 23ce7a5..60dd209 100644 --- a/Src/hysh/bin/hysh +++ b/Src/hysh/bin/hysh @@ -8,7 +8,7 @@ local success, errorMsg = xpcall(function() local fs = require("fs") syscall.devctl(1,"clear") -syscall.devctl(1,"sfgc",1) +syscall.devctl(1,"sfgc",0xFFFFFF) syscall.devctl(1,"spos",1,1) print("HyperionOS hysh Shell") @@ -26,8 +26,27 @@ else end local oldWD = "" +local colors = { + 0xFFFFFF, + 0xFF0000, + 0x00FF00, + 0x0000FF, + 0x00FFFF, + 0xFF00FF, + 0xFFFF00, + 0xFF6D00, + 0x6DFF55, + 0x24FFFF, + 0x924900, + 0x6D6D55, + 0xDBDBAA, + 0x6D00FF, + 0xB6FF00, + 0x000000 +} + for i = 1, 16 do - syscall.devctl(1,"sbgc",i); printInline(" ") + syscall.devctl(1,"sbgc",colors[i]); printInline(" ") end print("\n") @@ -221,7 +240,7 @@ end builtinCmds.clear = function() syscall.devctl(1,"clear") - syscall.devctl(1,"sfgc",1) + syscall.devctl(1,"sfgc",0xFFFFFF) syscall.devctl(1,"spos",1,1) end @@ -429,7 +448,7 @@ builtinCmds.head = function(...) local multi = #files > 1 local function dohead(text, label) if multi then - syscall.devctl(1,"sfgc",4); print("==> "..label.." <=="); syscall.devctl(1,"sfgc",1) + syscall.devctl(1,"sfgc",0x0000FF); print("==> "..label.." <=="); syscall.devctl(1,"sfgc",0xFFFFFF) end local count = 0 for line in (text.."\n"):gmatch("([^\n]*)\n") do @@ -468,7 +487,7 @@ builtinCmds.tail = function(...) local multi = #files > 1 local function dotail(text, label) if multi then - syscall.devctl(1,"sfgc",4); print("==> "..label.." <=="); syscall.devctl(1,"sfgc",1) + syscall.devctl(1,"sfgc",0x0000FF); print("==> "..label.." <=="); syscall.devctl(1,"sfgc",0xFFFFFF) end local lines = splitlines(text) local start = math.max(1, #lines - n + 1) @@ -963,13 +982,13 @@ local function doTabComplete(input, cursorPos) end local function getUserInput() - syscall.devctl(1,"sfgc",3) + syscall.devctl(1,"sfgc",0x00FF00) syscall.write(1, userhost) - syscall.devctl(1,"sfgc",1) + syscall.devctl(1,"sfgc",0xFFFFFF) syscall.write(1, ":") - syscall.devctl(1,"sfgc",10) + syscall.devctl(1,"sfgc",0x24FFFF) syscall.write(1, syscall.getcwd()) - syscall.devctl(1,"sfgc",1) + syscall.devctl(1,"sfgc",0xFFFFFF) syscall.write(1, "$ ") local curOffsetStr = syscall.devctl(1, "gpos") local curOffsetX = tonumber(curOffsetStr:sub(1, curOffsetStr:find(";")-1)) @@ -1020,21 +1039,21 @@ local function getUserInput() syscall.devctl(1,"spos",curOffsetX,curOffsetY) syscall.write(1, string.sub(input, 1, cursorPos-1)) if blinkState then - syscall.devctl(1,"sfgc",16); syscall.devctl(1,"sbgc",1) + syscall.devctl(1,"sfgc",0x000000); syscall.devctl(1,"sbgc",0xFFFFFF) end if cursorPos > #input then syscall.write(1, " ") else syscall.write(1, string.sub(input, cursorPos, cursorPos)) end - syscall.devctl(1,"sfgc",1); syscall.devctl(1,"sbgc",16) + syscall.devctl(1,"sfgc",0xFFFFFF); syscall.devctl(1,"sbgc",0x000000) local after = string.sub(input, cursorPos+1) syscall.write(1, after) local ghost = getGhostSuffix() if #ghost > 0 then - syscall.devctl(1,"sfgc",14) + syscall.devctl(1,"sfgc",0x6D00FF) syscall.write(1, ghost) - syscall.devctl(1,"sfgc",1) + syscall.devctl(1,"sfgc",0xFFFFFF) syscall.write(1, " ") else syscall.write(1, " ") @@ -1082,10 +1101,10 @@ local function getUserInput() syscall.write(1, string.rep(" ", tw)) syscall.devctl(1,"spos",1,py) end - syscall.devctl(1,"sfgc",3); syscall.write(1, userhost) - syscall.devctl(1,"sfgc",1); syscall.write(1, ":") - syscall.devctl(1,"sfgc",10); syscall.write(1, syscall.getcwd()) - syscall.devctl(1,"sfgc",1); syscall.write(1, "$ ") + syscall.devctl(1,"sfgc",0x00FF00); syscall.write(1, userhost) + syscall.devctl(1,"sfgc",0xFFFFFF); syscall.write(1, ":") + syscall.devctl(1,"sfgc",0x00FFFF); syscall.write(1, syscall.getcwd()) + syscall.devctl(1,"sfgc",0xFFFFFF); syscall.write(1, "$ ") posStr = syscall.devctl(1, "gpos") sep = posStr:find(";") curOffsetX = tonumber(posStr:sub(1, sep-1)) @@ -1098,7 +1117,7 @@ local function getUserInput() cursorPos=cursorPos-1;dirty=true end elseif key=="\n" then - syscall.devctl(1,"sfgc",1);syscall.devctl(1,"sbgc",16) + syscall.devctl(1,"sfgc",0xFFFFFF);syscall.devctl(1,"sbgc",0x000000) syscall.devctl(1,"spos",curOffsetX,curOffsetY) syscall.write(1, input.." \n") return input @@ -1114,7 +1133,7 @@ local function getUserInput() end local function printError(progName, msg) - syscall.devctl(1,"sfgc",2) + syscall.devctl(1,"sfgc",0xFF0000) local s = tostring(msg) local line, rest = s:match("%]:(%d+): (.+)$") if not line then line, rest = s:match(":(%d+): (.+)$") end @@ -1123,7 +1142,7 @@ local function printError(progName, msg) else print(progName..": "..s) end - syscall.devctl(1,"sfgc",1) + syscall.devctl(1,"sfgc",0xFFFFFF) end local function runCommand(command) @@ -1171,7 +1190,7 @@ local function runCommand(command) local xok, xerr = pcall(syscall.access, cmdPath, "x") if not xok then - syscall.devctl(1,"sfgc",2); print(progName..": Permission denied"); syscall.devctl(1,"sfgc",1) + syscall.devctl(1,"sfgc",0xFF0000); print(progName..": Permission denied"); syscall.devctl(1,"sfgc",0xFFFFFF) return end @@ -1195,8 +1214,8 @@ local function runCommand(command) if terminate then local ok2 = syscall.kill(proc) if ok2 then - syscall.devctl(1,"sbgc",16); syscall.devctl(1,"sfgc",2) - print("\nProgram Terminated."); syscall.devctl(1,"sfgc",1) + syscall.devctl(1,"sbgc",16); syscall.devctl(1,"sfgc",0xFF0000) + print("\nProgram Terminated."); syscall.devctl(1,"sfgc",0xFFFFFF) end terminate = false; break end @@ -1218,8 +1237,8 @@ end, debug.traceback) if not success then syscall.log("Error running shell: "..errorMsg, "ERROR") - syscall.devctl(1,"sfgc",2) - syscall.devctl(1,"sbgc",16) + syscall.devctl(1,"sfgc",0xFF0000) + syscall.devctl(1,"sbgc",0x000000) print() print("Error running shell: ") print(errorMsg) diff --git a/Src/hysh/bin/login b/Src/hysh/bin/login index 80146d9..13659d7 100644 --- a/Src/hysh/bin/login +++ b/Src/hysh/bin/login @@ -37,9 +37,9 @@ local function firstBoot() syscall.devctl(1, "clear") syscall.devctl(1, "spos", 1, 1) - syscall.devctl(1, "sfgc", 3) + syscall.devctl(1, "sfgc", 0x00FF00) syscall.write(1, "HyperionOS First Boot Setup\n") - syscall.devctl(1, "sfgc", 1) + syscall.devctl(1, "sfgc", 0xFFFFFF) syscall.write(1, "No root password is set. Please create one now.\n\n") while true do @@ -49,25 +49,25 @@ local function firstBoot() local pw2 = readLine("*") if pw1 ~= pw2 then - syscall.devctl(1, "sfgc", 2) + syscall.devctl(1, "sfgc", 0xFF0000) syscall.write(1, "Passwords do not match. Try again.\n\n") - syscall.devctl(1, "sfgc", 1) + syscall.devctl(1, "sfgc", 0xFFFFFF) elseif #pw1 < 6 then - syscall.devctl(1, "sfgc", 2) + syscall.devctl(1, "sfgc", 0xFF0000) syscall.write(1, "Password too short (minimum 6 characters).\n\n") - syscall.devctl(1, "sfgc", 1) + syscall.devctl(1, "sfgc", 0xFFFFFF) else local ok, err = syscall.setpassword(0, pw1) if ok then - syscall.devctl(1, "sfgc", 3) + syscall.devctl(1, "sfgc", 0x00FF00) syscall.write(1, "Root password set.\n\n") - syscall.devctl(1, "sfgc", 1) + syscall.devctl(1, "sfgc", 0xFFFFFF) sleep(0.5) break else - syscall.devctl(1, "sfgc", 2) + syscall.devctl(1, "sfgc", 0xFF0000) syscall.write(1, "Error: " .. tostring(err) .. "\n") - syscall.devctl(1, "sfgc", 1) + syscall.devctl(1, "sfgc", 0xFFFFFF) end end end @@ -112,8 +112,8 @@ end local function doLogin() syscall.devctl(1, "clear") - syscall.devctl(1, "sfgc", 1) - syscall.devctl(1, "sbgc", 16) + syscall.devctl(1, "sfgc", 0xFFFFFF) + syscall.devctl(1, "sbgc", 0x000000) syscall.devctl(1, "spos", 1, 1) local hostname = syscall.getHostname() or "hyperion" @@ -122,7 +122,7 @@ local function doLogin() local attempts = 0 while attempts < MAX_ATTEMPTS do - syscall.devctl(1, "sfgc", 1) + syscall.devctl(1, "sfgc", 0xFFFFFF) syscall.write(1, "Username: ") local username = readLine(nil) @@ -140,9 +140,9 @@ local function doLogin() local shell = (pwent and pwent.shell) or "/bin/hysh" local homedir = (pwent and pwent.homedir) or "/" - syscall.devctl(1, "sfgc", 3) + syscall.devctl(1, "sfgc", 0x00FF00) syscall.write(1, "\nWelcome, " .. username .. "!\n") - syscall.devctl(1, "sfgc", 1) + syscall.devctl(1, "sfgc", 0xFFFFFF) sleep(0.3) spawnShell(username, uid, shell, homedir) @@ -150,16 +150,16 @@ local function doLogin() else attempts = attempts + 1 sleep(1) - syscall.devctl(1, "sfgc", 2) + syscall.devctl(1, "sfgc", 0xFF0000) syscall.write(1, "Login incorrect.\n\n") - syscall.devctl(1, "sfgc", 1) + syscall.devctl(1, "sfgc", 0xFFFFFF) end end end - syscall.devctl(1, "sfgc", 2) + syscall.devctl(1, "sfgc", 0xFF0000) syscall.write(1, "Maximum login attempts exceeded.\n") - syscall.devctl(1, "sfgc", 1) + syscall.devctl(1, "sfgc", 0xFFFFFF) sleep(5) end diff --git a/Src/hysh/bin/loimgcreate b/Src/hysh/bin/loimgcreate index 6fca0dc..710e6ac 100644 --- a/Src/hysh/bin/loimgcreate +++ b/Src/hysh/bin/loimgcreate @@ -110,9 +110,9 @@ if opts.x then pcall(syscall.umount, tmpMnt) pcall(syscall.lodetach, loopId) - syscall.devctl(1, "sfgc", 10) + syscall.devctl(1, "sfgc", 0x00FFFF) print(name..": extracted "..count.." file(s) to "..destPath) - syscall.devctl(1, "sfgc", 1) + syscall.devctl(1, "sfgc", 0xFFFFFF) return end @@ -150,8 +150,8 @@ local lineCount = 0 for _ in imgStr:gmatch("\n") do lineCount = lineCount + 1 end local byteCount = #imgStr -syscall.devctl(1, "sfgc", 10) +syscall.devctl(1, "sfgc", 0x00FFFF) print(name..": image written to "..imgPath) -syscall.devctl(1, "sfgc", 14) +syscall.devctl(1, "sfgc", 0x6D00FF) print(string.format(" %d records, %d bytes", lineCount - 1, byteCount)) -syscall.devctl(1, "sfgc", 1) +syscall.devctl(1, "sfgc", 0xFFFFFF) diff --git a/Src/hysh/bin/losetup b/Src/hysh/bin/losetup index bbba40d..ade3301 100644 --- a/Src/hysh/bin/losetup +++ b/Src/hysh/bin/losetup @@ -60,18 +60,18 @@ if opts.l then local info = devs[id] local mode = (type(info) == "table" and info.mode) or "bind" local path = (type(info) == "table" and info.path) or tostring(info) - local colour = mode == "image" and 5 or 4 - syscall.devctl(1, "sfgc", 3) + local colour = mode == "image" and 0x00FFFF or 0x0000FF + syscall.devctl(1, "sfgc", 0x00FF00) printInline(string.format("%-10s", id)) syscall.devctl(1, "sfgc", colour) printInline(string.format("%-7s", "["..mode.."]")) - syscall.devctl(1, "sfgc", 1) + syscall.devctl(1, "sfgc", 0xFFFFFF) print(" "..path) end if not any then - syscall.devctl(1, "sfgc", 14) + syscall.devctl(1, "sfgc", 0x6D00FF) print(name..": no loop devices attached") - syscall.devctl(1, "sfgc", 1) + syscall.devctl(1, "sfgc", 0xFFFFFF) end return end @@ -92,9 +92,9 @@ if opts.d then end print(name..": "..msg); syscall.exit(1); return end - syscall.devctl(1, "sfgc", 10) + syscall.devctl(1, "sfgc", 0x00FFFF) print(name..": detached "..id) - syscall.devctl(1, "sfgc", 1) + syscall.devctl(1, "sfgc", 0xFFFFFF) return end diff --git a/Src/hysh/bin/ls b/Src/hysh/bin/ls index cf54cc4..80e08ce 100644 --- a/Src/hysh/bin/ls +++ b/Src/hysh/bin/ls @@ -136,26 +136,26 @@ if cloptions.l then printInline(tostring(mtime) .. " ") if isSym then - syscall.devctl(1, "sfgc", 6) + syscall.devctl(1, "sfgc", 0xFF00FF) printInline(v) - syscall.devctl(1, "sfgc", 1) + syscall.devctl(1, "sfgc", 0xFFFFFF) local ok, target = pcall(syscall.readlink, fullPath) if ok then printInline(" -> ") local targetExists = pcall(syscall.stat, fullPath) - syscall.devctl(1, "sfgc", targetExists and 6 or 2) + syscall.devctl(1, "sfgc", targetExists and 0xFF00FF or 0xFF0000) printInline(target) - syscall.devctl(1, "sfgc", 1) + syscall.devctl(1, "sfgc", 0xFFFFFF) end elseif isDir then - syscall.devctl(1, "sfgc", 14) + syscall.devctl(1, "sfgc", 0x6D00FF) printInline(v) - syscall.devctl(1, "sfgc", 1) + syscall.devctl(1, "sfgc", 0xFFFFFF) else local isExec = stat and stat.perms and (math.floor(stat.perms / (2^9)) % 2 == 1) - syscall.devctl(1, "sfgc", isExec and 3 or 1) + syscall.devctl(1, "sfgc", isExec and 0x00FF00 or 0xFFFFFF) printInline(v) - syscall.devctl(1, "sfgc", 1) + syscall.devctl(1, "sfgc", 0xFFFFFF) end print("") end @@ -175,16 +175,16 @@ for i, v in ipairs(list) do local isSym = stat and stat.etype == 0x01 if isSym then - syscall.devctl(1, "sfgc", 6) + syscall.devctl(1, "sfgc", 0xFF00FF) elseif isDir then - syscall.devctl(1, "sfgc", 14) + syscall.devctl(1, "sfgc", 0x6D00FF) else local isExec = stat and stat.perms and (math.floor(stat.perms / (2^9)) % 2 == 1) - syscall.devctl(1, "sfgc", isExec and 3 or 1) + syscall.devctl(1, "sfgc", isExec and 0x00FF00 or 0xFFFFFF) end printInline(v) - syscall.devctl(1, "sfgc", 1) + syscall.devctl(1, "sfgc", 0xFFFFFF) printInline((" "):rep(colWidth - #v)) if i % numCols == 0 then print("") end diff --git a/Src/hysh/bin/lsusers b/Src/hysh/bin/lsusers index 29fc90b..c3b1f2d 100644 --- a/Src/hysh/bin/lsusers +++ b/Src/hysh/bin/lsusers @@ -5,15 +5,15 @@ if not users or #users == 0 then return end -syscall.devctl(1,"sfgc",13) +syscall.devctl(1,"sfgc",0xDBDBDB) print(string.format("%-6s %-6s %-16s %-20s %s", "UID", "GID", "Username", "Home", "Shell")) print(string.rep("-", 65)) -syscall.devctl(1,"sfgc",1) +syscall.devctl(1,"sfgc",0xFFFFFF) for _, u in ipairs(users) do local lock_marker = u.locked and " [locked]" or "" - if u.locked then syscall.devctl(1,"sfgc",2) end + if u.locked then syscall.devctl(1,"sfgc",0xFF0000) end print(string.format("%-6d %-6d %-16s %-20s %s%s", u.uid, u.gid, u.username, u.homedir, u.shell, lock_marker)) - if u.locked then syscall.devctl(1,"sfgc",1) end + if u.locked then syscall.devctl(1,"sfgc",0xFFFFFF) end end diff --git a/Src/hysh/bin/mount b/Src/hysh/bin/mount index ab580e2..08105de 100644 --- a/Src/hysh/bin/mount +++ b/Src/hysh/bin/mount @@ -69,17 +69,17 @@ if #args == 0 and not opts.o then end if next(loDevs) == nil then - syscall.devctl(1, "sfgc", 14) + syscall.devctl(1, "sfgc", 0xFF00FF) print("(no loop devices attached)") - syscall.devctl(1, "sfgc", 1) + syscall.devctl(1, "sfgc", 0xFFFFFF) return end for id, info in pairs(loDevs) do - local colour = info.mode == "image" and 5 or 4 + local colour = info.mode == "image" and 0x00FFFF or 0x0000FF syscall.devctl(1, "sfgc", colour) printInline(info.mode.." "..id) - syscall.devctl(1, "sfgc", 1) + syscall.devctl(1, "sfgc", 0xFFFFFF) print(" on "..info.path) end return @@ -119,9 +119,9 @@ if opts.o and opts.o:lower() == "loop" then print(name..": mount: "..msg); syscall.exit(1); return end - syscall.devctl(1, "sfgc", 10) + syscall.devctl(1, "sfgc", 0x00FFFF) print(name..": "..loopId.." mounted at "..dest) - syscall.devctl(1, "sfgc", 1) + syscall.devctl(1, "sfgc", 0xFFFFFF) return end @@ -141,9 +141,9 @@ if #args == 2 then print(name..": "..msg); syscall.exit(1); return end - syscall.devctl(1, "sfgc", 10) + syscall.devctl(1, "sfgc", 0x00FFFF) print(name..": "..loopId.." mounted at "..dest) - syscall.devctl(1, "sfgc", 1) + syscall.devctl(1, "sfgc", 0xFFFFFF) return end diff --git a/Src/hysh/bin/su b/Src/hysh/bin/su index 393c1ce..64d75af 100644 --- a/Src/hysh/bin/su +++ b/Src/hysh/bin/su @@ -1,6 +1,9 @@ --:Minify:-- local targetUser = ({ ... })[1] local currentUid = syscall.getuid() +if syscall.geteuid()~=0 then + syscall.exec("/bin/su", {...}) +end local targetUid if targetUser then targetUid = syscall.getuidbyname(targetUser) diff --git a/Src/hysh/bin/umount b/Src/hysh/bin/umount index d806892..59cf4ce 100644 --- a/Src/hysh/bin/umount +++ b/Src/hysh/bin/umount @@ -59,9 +59,9 @@ if opts.l then end print(name..": "..msg); syscall.exit(1); return end - syscall.devctl(1, "sfgc", 10) + syscall.devctl(1, "sfgc", 0x00FFFF) print(name..": detached "..id) - syscall.devctl(1, "sfgc", 1) + syscall.devctl(1, "sfgc", 0xFFFFFF) return end @@ -95,17 +95,17 @@ if not ok then print(name..": "..msg); syscall.exit(1); return end -syscall.devctl(1, "sfgc", 10) +syscall.devctl(1, "sfgc", 0x00FFFF) print(name..": unmounted "..mpt) -syscall.devctl(1, "sfgc", 1) +syscall.devctl(1, "sfgc", 0xFFFFFF) if loopIdToDetach then for _, id in ipairs(loopIdToDetach) do local dok = pcall(syscall.lodetach, id) if dok then - syscall.devctl(1, "sfgc", 14) + syscall.devctl(1, "sfgc", 0xFF00FF) print(name..": auto-detached "..id) - syscall.devctl(1, "sfgc", 1) + syscall.devctl(1, "sfgc", 0xFFFFFF) end end end diff --git a/Src/lua/bin/lua b/Src/lua/bin/lua index 856eaa4..894d07f 100644 --- a/Src/lua/bin/lua +++ b/Src/lua/bin/lua @@ -1,14 +1,14 @@ --:Minify:-- -local C_PROMPT = 7 -local C_CONT = 13 -local C_OUT = 5 -local C_ERR = 2 -local C_KEY = 3 -local C_STR = 9 -local C_NUM = 10 -local C_BOOL = 8 -local C_NIL = 12 -local C_TABLE = 13 +local C_PROMPT = 0xFFFF00 +local C_CONT = 0xDBDBDB +local C_OUT = 0x00FFFF +local C_ERR = 0xFF0000 +local C_KEY = 0x00FF00 +local C_STR = 0x00FF88 +local C_NUM = 0x24FFFF +local C_BOOL = 0xFF6D00 +local C_NIL = 0x6D6D6D +local C_TABLE = 0xDBDBDB local function c(col) syscall.devctl(1, "sfgc", col) end local function w(s) syscall.write(1, tostring(s)) end @@ -250,9 +250,9 @@ local function getUserInput(prompt, history) local function redraw() syscall.devctl(1, "spos", ox, oy) w(input:sub(1, cursor-1)) - if blink then syscall.devctl(1,"sfgc",16); syscall.devctl(1,"sbgc",1) end + if blink then syscall.devctl(1,"sfgc",0x000000); syscall.devctl(1,"sbgc",1) end w(cursor > #input and " " or input:sub(cursor, cursor)) - syscall.devctl(1,"sfgc",1); syscall.devctl(1,"sbgc",16) + syscall.devctl(1,"sfgc",0xFFFFFF); syscall.devctl(1,"sbgc",16) w(input:sub(cursor+1) .. " ") dirty = false end @@ -284,7 +284,7 @@ local function getUserInput(prompt, history) cursor = cursor - 1; dirty = true end elseif key == "\n" then - syscall.devctl(1,"sfgc",1); syscall.devctl(1,"sbgc",16) + syscall.devctl(1,"sfgc",0xFFFFFF); syscall.devctl(1,"sbgc",16) syscall.devctl(1,"spos",ox,oy) w(input .. " \n") return input diff --git a/Src/micro/bin/micro b/Src/micro/bin/micro index 63b49ff..db188e2 100644 --- a/Src/micro/bin/micro +++ b/Src/micro/bin/micro @@ -135,16 +135,16 @@ local function pad(s, w) end local function drawTop() - tpos(1,1); tbg(4); tfg(16) + tpos(1,1); tbg(0x0000FF); tfg(0x000000) local left = " edit" .. (fname and (" - "..fname) or "") if dirty then left = left .. " [+]" end local right = tostring(cy)..","..tostring(cx).." " twrite(pad(left..string.rep(" ", math.max(1, W-#left-#right))..right, W)) - tbg(16); tfg(1) + tbg(0x000000); tfg(0xFFFFFF) end local function drawBottom() - tpos(1, H); tbg(4); tfg(16) + tpos(1, H); tbg(0x0000FF); tfg(0x000000) if msg ~= "" then if msgErr then tbg(2) end twrite(pad(" "..msg, W)) @@ -152,7 +152,7 @@ local function drawBottom() else twrite(pad(" ^W Save ^X Quit+Save ^P Quit ^K Cut ^U Paste ^F Find ^G Go", W)) end - tbg(16); tfg(1) + tbg(0x000000); tfg(0xFFFFFF) end local function drawLines(map) @@ -177,29 +177,29 @@ local function drawLines(map) local curCh = ci > #seg and " " or seg:sub(ci, ci) local after = seg:sub(ci+1) - tfg(1); tbg(16); twrite(before) - if blinkState then tfg(16); tbg(1) else tfg(1); tbg(16) end + tfg(0xFFFFFF); tbg(0x000000); twrite(before) + if blinkState then tfg(0x000000); tbg(0xFFFFFF) else tfg(0xFFFFFF); tbg(0x000000) end twrite(curCh) - tfg(1); tbg(16); twrite(after) + tfg(0xFFFFFF); tbg(0x000000); twrite(after) local drawn = #before + 1 + #after if drawn < W then twrite(string.rep(" ", W - drawn)) end else if li == sLine and sPat ~= "" and entry[2] == 1 then local s, e = seg:find(sPat) if s then - tfg(1); tbg(16); twrite(seg:sub(1,s-1)) - tfg(16); tbg(3); twrite(seg:sub(s,e)) - tfg(1); tbg(16); twrite(seg:sub(e+1)) + tfg(0xFFFFFF); tbg(0x000000); twrite(seg:sub(1,s-1)) + tfg(0x000000); tbg(0x00FF00); twrite(seg:sub(s,e)) + tfg(0xFFFFFF); tbg(0x000000); twrite(seg:sub(e+1)) twrite(string.rep(" ", W - #seg)) else - tfg(1); tbg(16); twrite(pad(seg, W)) + tfg(0xFFFFFF); tbg(0x000000); twrite(pad(seg, W)) end else - tfg(1); tbg(16); twrite(pad(seg, W)) + tfg(0xFFFFFF); tbg(0x000000); twrite(pad(seg, W)) end end else - tfg(13); tbg(16); twrite(pad("~", W)); tfg(1) + tfg(0xDBDBDB); tbg(0x000000); twrite(pad("~", W)); tfg(0xFFFFFF) end end end @@ -212,15 +212,15 @@ local function redraw() drawLines(map) drawBottom() tpos(1, H) - tbg(16); tfg(1) + tbg(0x000000); tfg(0xFFFFFF) end local function prompt(label, default) local inp = default or "" while true do - tpos(1, H); tbg(3); tfg(16) + tpos(1, H); tbg(0x00FF00); tfg(0x000000) twrite(pad(" "..label..inp.." ", W)) - tbg(16); tfg(1) + tbg(0x000000); tfg(0xFFFFFF) local key = syscall.read(0) if not key or key == "" then sleep(0.02) elseif key == "" then return nil @@ -415,5 +415,5 @@ while running do end end -tclear(); tfg(1); tbg(16); tpos(1,1) +tclear(); tfg(0xFFFFFF); tbg(0x000000); tpos(1,1) print("edit: exited"..(fname and (" - "..fname) or "")) diff --git a/Src/sysinit/usr/lib/sysinit/sysinit b/Src/sysinit/usr/lib/sysinit/sysinit index 58be0c9..8e5859b 100644 --- a/Src/sysinit/usr/lib/sysinit/sysinit +++ b/Src/sysinit/usr/lib/sysinit/sysinit @@ -1,15 +1,16 @@ --:Minify:-- local kernel=... local fs=require("fs") +kernel.log("Sysinit started...") for i,v in pairs(kernel.processes) do kernel.log("Spawning kernel task "..i) syscall.spawn(function() local status, err = pcall(v) if not status then - kernel.log("Error executing kernel task '" .. i .. "': " .. err, "ERROR") + kernel.log("Error executing kernel task '" .. i .. "': " .. err, "ERROR", 0xFF0000) else - kernel.log("Successfully executed kernel task: " .. i, "INFO") + kernel.log("Successfully executed kernel task: " .. i) end end, i) end @@ -17,23 +18,24 @@ end if not fs.exists("/bin/startup") then fs.mkdir("/bin/startup") end + local files = fs.list("/bin/startup") if not files then error("Failed to list /bin/startup") end for i,v in ipairs(files) do if v:sub(-4) == ".lua" then local filepath = "/bin/startup/" .. v - kernel.log("Executing startup script: " .. filepath, "INFO") + kernel.log("Executing startup script: " .. filepath) local startupFunc, err = load(fs.readAllText(filepath), "@" .. filepath) if not startupFunc then - kernel.log("Error loading startup script '" .. filepath .. "': " .. err, "ERROR") + kernel.log("Error loading startup script '" .. filepath .. "': " .. err, "ERROR", 0xFF0000) else syscall.spawn(function() syscall.setuid(1) local status, err = pcall(startupFunc) if not status then - kernel.log("Error executing startup script '" .. filepath .. "': " .. err, "ERROR") + kernel.log("Error executing startup script '" .. filepath .. "': " .. err, "ERROR", 0xFF0000) else - kernel.log("Successfully executed startup script: " .. filepath, "INFO") + kernel.log("Successfully executed startup script: " .. filepath) end end, "startup:" .. v) end diff --git a/build.py b/build.py index d3b0765..1af46c4 100644 --- a/build.py +++ b/build.py @@ -74,7 +74,7 @@ def compress_lz4(data: bytes) -> bytes: return lz4.frame.compress(data) -def process_root(src_root: Path, out_root: Path, minify: bool, micro: bool): +def process_root(src_root: Path, out_root: Path, minify: bool, micro: bool, arch:Union[str, None]): print(f"Building from {src_root}") print(f"Output to {out_root}") print() @@ -82,6 +82,10 @@ def process_root(src_root: Path, out_root: Path, minify: bool, micro: bool): for pkg_dir in sorted(src_root.iterdir()): if not pkg_dir.is_dir(): continue + + if pkg_dir.name[:18] == "Hyperion-firmware-": + if pkg_dir.name != f"Hyperion-firmware-{arch}": + continue print(f"== Package: {pkg_dir.name} ==") @@ -134,7 +138,7 @@ def run_build(minify: bool, micro: bool, include_test: bool, arch: Union[str, No out_root = BUILD_ROOT / "$" if arch else BUILD_ROOT - process_root(SRC_ROOT, out_root, minify, micro) + process_root(SRC_ROOT, out_root, minify, micro, arch) if include_test: process_root(TEST_ROOT, out_root, minify, micro) diff --git a/manifest.lua b/manifest.lua index 14edcf0..b3e0434 100644 --- a/manifest.lua +++ b/manifest.lua @@ -144,9 +144,14 @@ syscall.dup=function(fd) end --- Read GPIO pin --- @param pin integer ---- @return number|nil +--- @return boolean|nil syscall.gpio_read=function(pin) end +--- Read GPIO pin analog +--- @param pin integer +--- @return number|nil +syscall.gpio_readAnalog=function(pin) end + --- Get SUID bit from fd --- @param fd integer --- @return boolean @@ -154,10 +159,14 @@ syscall.fget_suid=function(fd) end --- Write GPIO pin --- @param pin integer ---- @param data number ---- @return boolean +--- @param data boolean syscall.gpio_write=function(pin, data) end +--- Write GPIO pin analog +--- @param pin integer +--- @param data number +syscall.gpio_writeAnalog=function(pin, data) end + --- Set password for user --- @param uid integer --- @param newPassword string