From d0f26a937fd03ee2dd54d35d4fe737881309898f Mon Sep 17 00:00:00 2001 From: Astronand Date: Thu, 19 Mar 2026 11:16:05 -0400 Subject: [PATCH] made installer --- Src/Hyperion-firmware-ccpc/boot/ccpc/boot.lua | 211 ++++++---- .../boot/ccpc/initdisks | 169 ++++++-- Src/Hyperion-firmware-cct/boot/cct/boot.lua | 11 +- .../lib/modules/cc-tweaked/25_tty.kmod | 24 +- Src/Hyperion-kernel/boot/kernel.lua | 3 +- .../lib/modules/hyperion/10_vfs.kmod | 11 +- .../lib/modules/hyperion/12_devfs.kmod | 122 +++--- .../lib/modules/hyperion/91_login.kmod | 1 + .../lib/modules/hyperion/92_setup.kmod | 1 + Src/iniparse/lib/iniparse | 1 + install/installcc.lua | 21 - installers/HyperionOS-install-cct.lua | 178 ++++++++ misc/cct/installcct.lua | 20 + .../cct/installdata/cct}/Build.tar | Bin misc/cct/installdata/cct/json | 388 ++++++++++++++++++ .../data => misc/cct/installdata/cct}/tarbad | 0 16 files changed, 982 insertions(+), 179 deletions(-) delete mode 100644 install/installcc.lua create mode 100644 installers/HyperionOS-install-cct.lua create mode 100644 misc/cct/installcct.lua rename {install/data => misc/cct/installdata/cct}/Build.tar (100%) create mode 100644 misc/cct/installdata/cct/json rename {install/data => misc/cct/installdata/cct}/tarbad (100%) diff --git a/Src/Hyperion-firmware-ccpc/boot/ccpc/boot.lua b/Src/Hyperion-firmware-ccpc/boot/ccpc/boot.lua index 7bdae02..fba14d5 100644 --- a/Src/Hyperion-firmware-ccpc/boot/ccpc/boot.lua +++ b/Src/Hyperion-firmware-ccpc/boot/ccpc/boot.lua @@ -1,4 +1,4 @@ --- :Minify:-- +--:Minify:-- local BOOT_DRIVE_PATH = ({...})[1] or "/$" ---@diagnostic disable-next-line: undefined-global local term = term @@ -71,7 +71,6 @@ local ok, err = xpcall(function() collectgarbage = true, error = true, gcinfo = true, - getfenv = true, getmetatable = true, ipairs = true, __inext = true, @@ -85,7 +84,6 @@ local ok, err = xpcall(function() rawlen = true, rawset = true, select = true, - setfenv = true, setmetatable = true, string = true, table = true, @@ -154,17 +152,106 @@ 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 eeprom + if apis.fs.exists("/startup.lua") then + eeprom="/startup.lua" + elseif apis.fs.exists("/eeprom") then + eeprom="/eeprom" + 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)) @@ -172,61 +259,15 @@ local ok, err = xpcall(function() return nil end end, - getEEPROM = function() return getFile("/startup.lua") end, + getEEPROM = function() return getFile(eeprom) end, setEEPROM = function(_, text) - local h = apis.fs.open("/startup.lua", "w") + local h = apis.fs.open(eeprom, "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() @@ -239,25 +280,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) @@ -306,11 +373,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-ccpc/boot/ccpc/initdisks b/Src/Hyperion-firmware-ccpc/boot/ccpc/initdisks index 3669757..1480a0b 100644 --- a/Src/Hyperion-firmware-ccpc/boot/ccpc/initdisks +++ b/Src/Hyperion-firmware-ccpc/boot/ccpc/initdisks @@ -1,36 +1,152 @@ --- :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 = {} local sides = {"top", "bottom", "left", "right", "front", "back"} -function peripheral.getType(name) - if native.isPresent(name) then return native.getType(name) end +function peripheral.getNames() + local results = {} for n = 1, #sides do local side = sides[n] - if native.hasType(side, "peripheral_hub") and - native.call(side, "isPresentRemote", name) then - return native.call(side, "getTypeRemote", name) + 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.getNames() - local names = {} +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.isPresent(side) then table.insert(names, side) end - if native.hasType(side, "peripheral_hub") then - local hubSides = native.call(side, "getConnectedSides") - for _, hubSide in ipairs(hubSides) do - table.insert(names, hubSide) + 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 names + return table.unpack(results) end local disks = {} @@ -125,19 +241,20 @@ 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 +}) - for _, name in ipairs(peripheral.getNames()) do - if peripheral.getType(name) == "disk" then - if not disks[name] then - local mount = disk.getMountPath(name) - if mount then - disks[name] = createDisk(name, mount, false, disk) - end - 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) end end end diff --git a/Src/Hyperion-firmware-cct/boot/cct/boot.lua b/Src/Hyperion-firmware-cct/boot/cct/boot.lua index 01bfcb8..fba14d5 100644 --- a/Src/Hyperion-firmware-cct/boot/cct/boot.lua +++ b/Src/Hyperion-firmware-cct/boot/cct/boot.lua @@ -158,6 +158,13 @@ local ok, err = xpcall(function() file.close() end + local eeprom + if apis.fs.exists("/startup.lua") then + eeprom="/startup.lua" + elseif apis.fs.exists("/eeprom") then + eeprom="/eeprom" + end + local eventQueue = {} local function queueEvent(event, ...) @@ -252,9 +259,9 @@ local ok, err = xpcall(function() return nil end end, - getEEPROM = function() return getFile("/startup.lua") end, + getEEPROM = function() return getFile(eeprom) end, setEEPROM = function(_, text) - local h = apis.fs.open("/startup.lua", "w") + local h = apis.fs.open(eeprom, "w") h.write(text) h.close() end, 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 4cd738d..779b1cb 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 @@ -22,6 +22,25 @@ local colors = { [0x000000]=0x8000 } +local plt = { + 0xFFFFFF, + 0xFF0000, + 0x00FF00, + 0x0000FF, + 0x00FFFF, + 0xFF00FF, + 0xFFFF00, + 0xFF6D00, + 0x6DFF55, + 0x24FFFF, + 0x924900, + 0x6D6D55, + 0xDBDBAA, + 0x6D00FF, + 0xB6FF00, + 0x000000 +} + local fg,bg=0x6D6D55,0x000000 local l1f,l1d,l2,ops={},{},{},0 @@ -155,7 +174,7 @@ local function newtty(obj, id, ev) obj.setPaletteColor(0x8000, 0x000000) -- #B6FF00 kernel.devfs.data["tty"][id] = function(op, mode) if op=="type" then - return "character device" + return "Terminal" elseif op=="open" then local h = { read=function(amount) @@ -203,6 +222,9 @@ local function newtty(obj, id, ev) end, gctrl=function() return serializeBool(ctrl)..";"..serializeBool(alt) + end, + gplt=function() + return plt end } if mode=="rw" then diff --git a/Src/Hyperion-kernel/boot/kernel.lua b/Src/Hyperion-kernel/boot/kernel.lua index 00370f0..38f56b2 100644 --- a/Src/Hyperion-kernel/boot/kernel.lua +++ b/Src/Hyperion-kernel/boot/kernel.lua @@ -6,7 +6,7 @@ local disks=EFI.disks local arch=EFI.architecture local kernel = {} kernel.LOG_Text="" -kernel.version="HyperionOS V1.2.3" +kernel.version="HyperionOS V1.2.4" kernel.process = "Kernel" kernel.users={[0]="root",[1]="User"} kernel.hostname = "hyperion" @@ -291,7 +291,6 @@ kernel.saveLog() kernel.status="running" screen:disable() kernel.main() -kernel.panic("Exited main???") if kernel.status=="panic" then kernel.panic(kernel.reason) end diff --git a/Src/Hyperion-kernel/lib/modules/hyperion/10_vfs.kmod b/Src/Hyperion-kernel/lib/modules/hyperion/10_vfs.kmod index 156cc71..ab49a8a 100644 --- a/Src/Hyperion-kernel/lib/modules/hyperion/10_vfs.kmod +++ b/Src/Hyperion-kernel/lib/modules/hyperion/10_vfs.kmod @@ -555,8 +555,9 @@ function vfs.mount(target, diskOrId) if _euid ~= 0 then error("EPERM") end if not target then error("EINVAL") end target = normalizeMountPoint(target) - if not vfs.exists(target) then vfs.mkdir(target) end - if vfs.type(target) ~= "directory" then error("EINVAL") end + local drive, path = resolvePath(target) + if not drive:directoryExists(path) then drive:makeDirectory(path) end + if drive:type(target) ~= "directory" then error("EINVAL") end local disk, id if type(diskOrId) == "string" then @@ -946,7 +947,11 @@ function vfs.exists(path) if meta.etype == 0x01 then return true end local ok, disk, diskPath = pcall(resolvePath, path) if not ok then return false end - return disk:fileExists(diskPath) + if disk:type(diskPath) then + return true + else + return false + end end function vfs.type(path) diff --git a/Src/Hyperion-kernel/lib/modules/hyperion/12_devfs.kmod b/Src/Hyperion-kernel/lib/modules/hyperion/12_devfs.kmod index 989e4ac..317b09e 100644 --- a/Src/Hyperion-kernel/lib/modules/hyperion/12_devfs.kmod +++ b/Src/Hyperion-kernel/lib/modules/hyperion/12_devfs.kmod @@ -140,64 +140,78 @@ 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") +if kernel.EFI:getEEPROM() then + 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 + local firstwrite=true + return { + write=function(data) + if firstwrite then + kernel.EFI:setEEPROM(data) + else + kernel.EFI:setEEPROM(kernel.EFI:getEEPROM()..data) + end + 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 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") +if kernel.EFI:getNvram() then + 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 + local firstwrite=true + return { + write=function(data) + if firstwrite then + kernel.EFI:setNvram(data) + else + kernel.EFI:setNvram(kernel.EFI:getNvram()..data) + end + 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 end diff --git a/Src/Hyperion-kernel/lib/modules/hyperion/91_login.kmod b/Src/Hyperion-kernel/lib/modules/hyperion/91_login.kmod index 448da86..f40d92a 100644 --- a/Src/Hyperion-kernel/lib/modules/hyperion/91_login.kmod +++ b/Src/Hyperion-kernel/lib/modules/hyperion/91_login.kmod @@ -1,5 +1,6 @@ --:Minify:-- local kernel = ... +if not kernel.vfs.exists("/root") then kernel.vfs.mkdir("/root") end kernel.processes.login = function() local ok, err = pcall(kernel.hpv.execspawn, "/bin/login", "login") diff --git a/Src/Hyperion-kernel/lib/modules/hyperion/92_setup.kmod b/Src/Hyperion-kernel/lib/modules/hyperion/92_setup.kmod index 1f7504b..051846e 100644 --- a/Src/Hyperion-kernel/lib/modules/hyperion/92_setup.kmod +++ b/Src/Hyperion-kernel/lib/modules/hyperion/92_setup.kmod @@ -92,6 +92,7 @@ if kernel.firstBoot then {"etc", REG, 0, 0, RWX_RX_RX}, {"home", REG, 0, 0, RWX_RX_RX}, {"lib", REG, 0, 0, RWX_RX_RX}, + {"proc", REG, 0, 0, RWXRWXRWX}, {"root", REG, 0, 0, RW____ }, {"sbin", REG, 0, 0, RWX_RX_RX}, {"tmp", REG, 0, 0, RWXRWXRWX}, diff --git a/Src/iniparse/lib/iniparse b/Src/iniparse/lib/iniparse index f6b0e4b..fa564aa 100644 --- a/Src/iniparse/lib/iniparse +++ b/Src/iniparse/lib/iniparse @@ -1,3 +1,4 @@ +--:Minify:-- local ini = {} function ini.parse(str) diff --git a/install/installcc.lua b/install/installcc.lua deleted file mode 100644 index 88e6c81..0000000 --- a/install/installcc.lua +++ /dev/null @@ -1,21 +0,0 @@ -print("Hello, World!") -sleep(1) -term.clear() -print("Do you want to install HyperionOS? [Y/n]") -local input=read() -if input=="y" or input=="Y" or input=="" then - print("Installing tar but bad...") - shell.run("wget https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/install/data/tarbad /tar.lua") - print("Installing HyperionOS...") - print("Installing precompiled tar") - shell.run("wget https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/install/data/Build.tar /Build.tar") - shell.run("tar Build.tar /") - print("Removing tar but bad...") - shell.run("rm /tar.lua") - shell.run("rm $") - shell.run("cp Build $") - shell.run("rm Build") - shell.run("rm Build.tar") - fs.copy("/$/boot/cct/eeprom","/startup.lua") - dofile("startup.lua") -end \ No newline at end of file diff --git a/installers/HyperionOS-install-cct.lua b/installers/HyperionOS-install-cct.lua new file mode 100644 index 0000000..1adecee --- /dev/null +++ b/installers/HyperionOS-install-cct.lua @@ -0,0 +1,178 @@ +term.clear() +term.setCursorPos(1,1) +print("HyperionOS CCT Installer //") +local w,h = term.getSize() +local install,releasename=function()end,"" +local exitall=false + +local function download(url) + shell.run("wget "..url.." /tmp/download") + local lib = require("tmp.download") + fs.delete("/tmp/download") + return lib +end + +print("Installing JSON...") +local json = download("https://git.astronand.dev/Hyperion/HyperionOS/raw/branch/main/misc/install/data/json") + +local function printTitle() + term.clear() + term.setCursorPos(1,1) + term.setTextColor(colors.white) + print("HyperionOS CCT Installer //") + print("Orange is prerelease...") + term.setCursorPos(1,h-1) + print("DESCLAIMER: This will wipe your system on install...") + term.write("Bspc: Back | Enter: execute | Tab: description") +end +printTitle() + +local function pc(text, y, c) + local x=(w/2)-#text/2 + term.setTextColor(c) + term.setCursorPos(x, y) + term.write(text) +end + +local function drawMenu(menu, sel) + local y=(h/2)-#menu/2 + for i,v in ipairs(menu) do + if i==sel then + pc("[ "..v.name.." ]", y+i, v.color) + else + pc(v.name, y+i, v.color) + end + end +end + +local function desc(description) + term.clear() + term.setTextColor(colors.white) + term.setCursorPos(1,1) + print("HyperionOS CCT Installer //\n") + print(description) + term.setCursorPos(1,h) + term.write("Press enter to continue...") + while not exitall do + local _,key = os.pullEvent("key") + if key==keys.enter then + break + end + end +end + +local function menu(m) + local exit,sel=false,1 + while not exit or not exitall do + printTitle() + drawMenu(m, sel) + local _,key = os.pullEvent("key") + if key==keys.down then + if sel<#m then + sel=sel+1 + end + elseif key==keys.up then + if sel>1 then + sel=sel-1 + end + elseif key==keys.enter then + m[sel].func() + elseif key==keys.tab then + desc(m[sel].desc) + elseif key==keys.backspace then + exit=true + end + end +end + +local releases,page={},1 +while true do + local raw=http.get("https://git.astronand.dev/api/v1/repos/Hyperion/HyperionOS/releases?page="..tostring(page).."&limit=1") + if raw=="[]" then + break + end + releases[#releases+1]=json.decode(raw)[1] +end + +local function makePage(start, num) + local m,nonext={},false + for i=start, num do + if not releases[i] then nonext=true; break end + local release=releases[i] + m[#m+1]={ + name=release.name, + desc=release.body, + color=release.prerelease and colors.orange or colors.white, + func=function() + local data, err=http.get("https://git.astronand.dev/Hyperion/HyperionOS/raw/tag/"..release.tag_name.."/misc/cct/installcc.lua") + releasename=release.tag_name + if not data then + term.clear() + term.setCursorPos(1,1) + print("Unable to install "..release.tag_name..":\n"..err) + sleep(3) + return + end + local func, err = load(data.readAll(), "@Installer") + if not func then + term.clear() + term.setCursorPos(1,1) + print("Unable to load Installer "..release.tag_name..":\n"..err) + sleep(3) + return + end + install=func + end + } + end + if not nonext then + m[#m+1]={ + name="Next", + desc="Next menu", + color=colors.cyan, + func=function() + local menudata=makePage(start+num, num) + menu(menudata) + end + } + end +end + +menu(makePage(1,5)) +term.clear() +term.setCursorPos(1,1) +term.setTextColor(colors.white) +term.write("Formating disk in ") +for i=5, 0, -1 do + term.write(tostring(i)) + sleep(.25) + for v=1, 3 do + term.write(".") + sleep(.25) + end +end + +local function printc(text, c) + term.setTextColor(c) + print(text) +end + +local function delDir(dir) + printc("ls "..dir, colors.green) + local list=fs.list(dir) + printc("rm -rf "..dir, colors.red) + for i=1, #list do + if fs.isDir(dir..list[i]) then + if dir..list[i] ~= "/rom" then + delDir(dir..list[i].."/") + fs.delete(dir..list[i]) + end + else + fs.delete(dir..list[i]) + printc("rm "..dir..list[i], colors.orange) + end + end +end + +delDir("/") +install(releasename) \ No newline at end of file diff --git a/misc/cct/installcct.lua b/misc/cct/installcct.lua new file mode 100644 index 0000000..9d33613 --- /dev/null +++ b/misc/cct/installcct.lua @@ -0,0 +1,20 @@ +local release=... +term.clear() +term.setCursorPos(1,1) +print("Hello, World!") +print("Installing tar but bad...") +shell.run("wget https://git.astronand.dev/Hyperion/HyperionOS/raw/tag/"..release.."/misc/cct/data/tarbad /tar.lua") +print("Installing HyperionOS...") +print("Installing precompiled tar") +shell.run("wget https://git.astronand.dev/Hyperion/HyperionOS/raw/tag/"..release.."/misc/cct/data/Build.tar /Build.tar") +shell.run("tar Build.tar /") +print("Removing tar but bad...") +shell.run("rm /tar.lua") +shell.run("rm $") +shell.run("cp Build $") +shell.run("rm Build") +shell.run("rm Build.tar") +fs.copy("/$/boot/cct/eeprom","/startup.lua") +print("Installing...") +sleep(1) +dofile("startup.lua") \ No newline at end of file diff --git a/install/data/Build.tar b/misc/cct/installdata/cct/Build.tar similarity index 100% rename from install/data/Build.tar rename to misc/cct/installdata/cct/Build.tar diff --git a/misc/cct/installdata/cct/json b/misc/cct/installdata/cct/json new file mode 100644 index 0000000..484c997 --- /dev/null +++ b/misc/cct/installdata/cct/json @@ -0,0 +1,388 @@ +--:Minify:-- +-- json.lua +-- +-- Copyright (c) 2020 rxi +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of +-- this software and associated documentation files (the "Software"), to deal in +-- the Software without restriction, including without limitation the rights to +-- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +-- of the Software, and to permit persons to whom the Software is furnished to do +-- so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all +-- copies or substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +-- SOFTWARE. +-- + +local json = { _version = "0.1.2" } + +------------------------------------------------------------------------------- +-- Encode +------------------------------------------------------------------------------- + +local encode + +local escape_char_map = { + [ "\\" ] = "\\", + [ "\"" ] = "\"", + [ "\b" ] = "b", + [ "\f" ] = "f", + [ "\n" ] = "n", + [ "\r" ] = "r", + [ "\t" ] = "t", +} + +local escape_char_map_inv = { [ "/" ] = "/" } +for k, v in pairs(escape_char_map) do + escape_char_map_inv[v] = k +end + + +local function escape_char(c) + return "\\" .. (escape_char_map[c] or string.format("u%04x", c:byte())) +end + + +local function encode_nil(val) + return "null" +end + + +local function encode_table(val, stack) + local res = {} + stack = stack or {} + + -- Circular reference? + if stack[val] then error("circular reference") end + + stack[val] = true + + if rawget(val, 1) ~= nil or next(val) == nil then + -- Treat as array -- check keys are valid and it is not sparse + local n = 0 + for k in pairs(val) do + if type(k) ~= "number" then + error("invalid table: mixed or invalid key types") + end + n = n + 1 + end + if n ~= #val then + error("invalid table: sparse array") + end + -- Encode + for i, v in ipairs(val) do + table.insert(res, encode(v, stack)) + end + stack[val] = nil + return "[" .. table.concat(res, ",") .. "]" + + else + -- Treat as an object + for k, v in pairs(val) do + if type(k) ~= "string" then + error("invalid table: mixed or invalid key types") + end + table.insert(res, encode(k, stack) .. ":" .. encode(v, stack)) + end + stack[val] = nil + return "{" .. table.concat(res, ",") .. "}" + end +end + + +local function encode_string(val) + return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"' +end + + +local function encode_number(val) + -- Check for NaN, -inf and inf + if val ~= val or val <= -math.huge or val >= math.huge then + error("unexpected number value '" .. tostring(val) .. "'") + end + return string.format("%.14g", val) +end + + +local type_func_map = { + [ "nil" ] = encode_nil, + [ "table" ] = encode_table, + [ "string" ] = encode_string, + [ "number" ] = encode_number, + [ "boolean" ] = tostring, +} + + +encode = function(val, stack) + local t = type(val) + local f = type_func_map[t] + if f then + return f(val, stack) + end + error("unexpected type '" .. t .. "'") +end + + +function json.encode(val) + return ( encode(val) ) +end + + +------------------------------------------------------------------------------- +-- Decode +------------------------------------------------------------------------------- + +local parse + +local function create_set(...) + local res = {} + for i = 1, select("#", ...) do + res[ select(i, ...) ] = true + end + return res +end + +local space_chars = create_set(" ", "\t", "\r", "\n") +local delim_chars = create_set(" ", "\t", "\r", "\n", "]", "}", ",") +local escape_chars = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u") +local literals = create_set("true", "false", "null") + +local literal_map = { + [ "true" ] = true, + [ "false" ] = false, + [ "null" ] = nil, +} + + +local function next_char(str, idx, set, negate) + for i = idx, #str do + if set[str:sub(i, i)] ~= negate then + return i + end + end + return #str + 1 +end + + +local function decode_error(str, idx, msg) + local line_count = 1 + local col_count = 1 + for i = 1, idx - 1 do + col_count = col_count + 1 + if str:sub(i, i) == "\n" then + line_count = line_count + 1 + col_count = 1 + end + end + error( string.format("%s at line %d col %d", msg, line_count, col_count) ) +end + + +local function codepoint_to_utf8(n) + -- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=iws-appendixa + local f = math.floor + if n <= 0x7f then + return string.char(n) + elseif n <= 0x7ff then + return string.char(f(n / 64) + 192, n % 64 + 128) + elseif n <= 0xffff then + return string.char(f(n / 4096) + 224, f(n % 4096 / 64) + 128, n % 64 + 128) + elseif n <= 0x10ffff then + return string.char(f(n / 262144) + 240, f(n % 262144 / 4096) + 128, + f(n % 4096 / 64) + 128, n % 64 + 128) + end + error( string.format("invalid unicode codepoint '%x'", n) ) +end + + +local function parse_unicode_escape(s) + local n1 = tonumber( s:sub(1, 4), 16 ) + local n2 = tonumber( s:sub(7, 10), 16 ) + -- Surrogate pair? + if n2 then + return codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000) + else + return codepoint_to_utf8(n1) + end +end + + +local function parse_string(str, i) + local res = "" + local j = i + 1 + local k = j + + while j <= #str do + local x = str:byte(j) + + if x < 32 then + decode_error(str, j, "control character in string") + + elseif x == 92 then -- `\`: Escape + res = res .. str:sub(k, j - 1) + j = j + 1 + local c = str:sub(j, j) + if c == "u" then + local hex = str:match("^[dD][89aAbB]%x%x\\u%x%x%x%x", j + 1) + or str:match("^%x%x%x%x", j + 1) + or decode_error(str, j - 1, "invalid unicode escape in string") + res = res .. parse_unicode_escape(hex) + j = j + #hex + else + if not escape_chars[c] then + decode_error(str, j - 1, "invalid escape char '" .. c .. "' in string") + end + res = res .. escape_char_map_inv[c] + end + k = j + 1 + + elseif x == 34 then -- `"`: End of string + res = res .. str:sub(k, j - 1) + return res, j + 1 + end + + j = j + 1 + end + + decode_error(str, i, "expected closing quote for string") +end + + +local function parse_number(str, i) + local x = next_char(str, i, delim_chars) + local s = str:sub(i, x - 1) + local n = tonumber(s) + if not n then + decode_error(str, i, "invalid number '" .. s .. "'") + end + return n, x +end + + +local function parse_literal(str, i) + local x = next_char(str, i, delim_chars) + local word = str:sub(i, x - 1) + if not literals[word] then + decode_error(str, i, "invalid literal '" .. word .. "'") + end + return literal_map[word], x +end + + +local function parse_array(str, i) + local res = {} + local n = 1 + i = i + 1 + while 1 do + local x + i = next_char(str, i, space_chars, true) + -- Empty / end of array? + if str:sub(i, i) == "]" then + i = i + 1 + break + end + -- Read token + x, i = parse(str, i) + res[n] = x + n = n + 1 + -- Next token + i = next_char(str, i, space_chars, true) + local chr = str:sub(i, i) + i = i + 1 + if chr == "]" then break end + if chr ~= "," then decode_error(str, i, "expected ']' or ','") end + end + return res, i +end + + +local function parse_object(str, i) + local res = {} + i = i + 1 + while 1 do + local key, val + i = next_char(str, i, space_chars, true) + -- Empty / end of object? + if str:sub(i, i) == "}" then + i = i + 1 + break + end + -- Read key + if str:sub(i, i) ~= '"' then + decode_error(str, i, "expected string for key") + end + key, i = parse(str, i) + -- Read ':' delimiter + i = next_char(str, i, space_chars, true) + if str:sub(i, i) ~= ":" then + decode_error(str, i, "expected ':' after key") + end + i = next_char(str, i + 1, space_chars, true) + -- Read value + val, i = parse(str, i) + -- Set + res[key] = val + -- Next token + i = next_char(str, i, space_chars, true) + local chr = str:sub(i, i) + i = i + 1 + if chr == "}" then break end + if chr ~= "," then decode_error(str, i, "expected '}' or ','") end + end + return res, i +end + + +local char_func_map = { + [ '"' ] = parse_string, + [ "0" ] = parse_number, + [ "1" ] = parse_number, + [ "2" ] = parse_number, + [ "3" ] = parse_number, + [ "4" ] = parse_number, + [ "5" ] = parse_number, + [ "6" ] = parse_number, + [ "7" ] = parse_number, + [ "8" ] = parse_number, + [ "9" ] = parse_number, + [ "-" ] = parse_number, + [ "t" ] = parse_literal, + [ "f" ] = parse_literal, + [ "n" ] = parse_literal, + [ "[" ] = parse_array, + [ "{" ] = parse_object, +} + + +parse = function(str, idx) + local chr = str:sub(idx, idx) + local f = char_func_map[chr] + if f then + return f(str, idx) + end + decode_error(str, idx, "unexpected character '" .. chr .. "'") +end + + +function json.decode(str) + if type(str) ~= "string" then + error("expected argument of type string, got " .. type(str)) + end + local res, idx = parse(str, next_char(str, 1, space_chars, true)) + idx = next_char(str, idx, space_chars, true) + if idx <= #str then + decode_error(str, idx, "trailing garbage") + end + return res +end + + +return json \ No newline at end of file diff --git a/install/data/tarbad b/misc/cct/installdata/cct/tarbad similarity index 100% rename from install/data/tarbad rename to misc/cct/installdata/cct/tarbad