forked from Hyperion/HyperionOS
fixed ls links, modules writeable
This commit is contained in:
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -5,6 +5,7 @@
|
|||||||
"syscall",
|
"syscall",
|
||||||
"printf",
|
"printf",
|
||||||
"printInline",
|
"printInline",
|
||||||
"toHex"
|
"toHex",
|
||||||
|
"loadcstr"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
316
Src/Hyperion-firmware-ccpc/boot/cct/boot.lua
Normal file
316
Src/Hyperion-firmware-ccpc/boot/cct/boot.lua
Normal file
@@ -0,0 +1,316 @@
|
|||||||
|
-- :Minify:--
|
||||||
|
local BOOT_DRIVE_PATH = ({...})[1] or "/$"
|
||||||
|
---@diagnostic disable-next-line: undefined-global
|
||||||
|
local term = term
|
||||||
|
local os = os
|
||||||
|
local function write(text)
|
||||||
|
local x, y = term.getCursorPos()
|
||||||
|
local w, h = term.getSize()
|
||||||
|
|
||||||
|
for i = 1, #text do
|
||||||
|
local c = text:sub(i, i)
|
||||||
|
|
||||||
|
if c == "\n" then
|
||||||
|
y = y + 1
|
||||||
|
x = 1
|
||||||
|
elseif c == "\t" then
|
||||||
|
local tabSize = 4
|
||||||
|
local spaces = tabSize - ((x - 1) % tabSize)
|
||||||
|
term.write(string.rep(" ", spaces))
|
||||||
|
x = x + spaces
|
||||||
|
elseif c == "\b" then
|
||||||
|
if x > 1 then
|
||||||
|
x = x - 1
|
||||||
|
term.setCursorPos(x, y)
|
||||||
|
term.write(" ")
|
||||||
|
term.setCursorPos(x, y)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if x <= w and y <= h then
|
||||||
|
term.setCursorPos(x, y)
|
||||||
|
term.write(c)
|
||||||
|
x = x + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if x > w then
|
||||||
|
x = 1
|
||||||
|
y = y + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
if y - 1 >= h then
|
||||||
|
term.scroll(1)
|
||||||
|
y = h
|
||||||
|
term.setCursorPos(x, y)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
term.setCursorPos(x, y)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function displaySuperBadError(err)
|
||||||
|
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
|
||||||
|
|
||||||
|
term.setCursorBlink(false)
|
||||||
|
local ok, err = xpcall(function()
|
||||||
|
local apis = {BOOT_DRIVE_PATH = BOOT_DRIVE_PATH}
|
||||||
|
|
||||||
|
local lua = {
|
||||||
|
coroutine = true,
|
||||||
|
debug = true,
|
||||||
|
_VERSION = true,
|
||||||
|
assert = true,
|
||||||
|
collectgarbage = true,
|
||||||
|
error = true,
|
||||||
|
gcinfo = true,
|
||||||
|
getfenv = true,
|
||||||
|
getmetatable = true,
|
||||||
|
ipairs = true,
|
||||||
|
__inext = true,
|
||||||
|
load = true,
|
||||||
|
math = true,
|
||||||
|
next = true,
|
||||||
|
pairs = true,
|
||||||
|
pcall = true,
|
||||||
|
rawequal = true,
|
||||||
|
rawget = true,
|
||||||
|
rawlen = true,
|
||||||
|
rawset = true,
|
||||||
|
select = true,
|
||||||
|
setfenv = true,
|
||||||
|
setmetatable = true,
|
||||||
|
string = true,
|
||||||
|
table = true,
|
||||||
|
tonumber = true,
|
||||||
|
tostring = true,
|
||||||
|
type = true,
|
||||||
|
xpcall = true,
|
||||||
|
_G = true
|
||||||
|
}
|
||||||
|
|
||||||
|
local 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 acekeys={
|
||||||
|
[apis.keys.enter]="\n",
|
||||||
|
[apis.keys.tab]="\t",
|
||||||
|
[apis.keys.backspace]="\b",
|
||||||
|
[apis.keys.up]="\17",
|
||||||
|
[apis.keys.down]="\18",
|
||||||
|
[apis.keys.left]="\19",
|
||||||
|
[apis.keys.right]="\20",
|
||||||
|
}
|
||||||
|
|
||||||
|
function sleep(time)
|
||||||
|
local stoptime = apis.os.clock() + (time)
|
||||||
|
while stoptime > apis.os.clock() do end
|
||||||
|
end
|
||||||
|
|
||||||
|
apis.term.setPaletteColor(0x1, 0xFFFFFF) -- #000000
|
||||||
|
apis.term.setPaletteColor(0x2, 0xFF0000) -- #FFFFFF
|
||||||
|
apis.term.setPaletteColor(0x4, 0x00FF00) -- #FF0000
|
||||||
|
apis.term.setPaletteColor(0x8, 0x0000FF) -- #00FF00
|
||||||
|
apis.term.setPaletteColor(0x10, 0x00FFFF) -- #0000FF
|
||||||
|
apis.term.setPaletteColor(0x20, 0xFF00FF) -- #00FFFF
|
||||||
|
apis.term.setPaletteColor(0x40, 0xFFFF00) -- #FF00FF
|
||||||
|
apis.term.setPaletteColor(0x80, 0xFF6D00) -- #FFFF00
|
||||||
|
apis.term.setPaletteColor(0x100, 0x6DFF55) -- #FF6D00
|
||||||
|
apis.term.setPaletteColor(0x200, 0x24FFFF) -- #6DFF55
|
||||||
|
apis.term.setPaletteColor(0x400, 0x924900) -- #24FFFF
|
||||||
|
apis.term.setPaletteColor(0x800, 0x6D6D55) -- #924900
|
||||||
|
apis.term.setPaletteColor(0x1000, 0xDBDBAA) -- #6D6D55
|
||||||
|
apis.term.setPaletteColor(0x2000, 0x6D00FF) -- #DBDBAA
|
||||||
|
apis.term.setPaletteColor(0x4000, 0xB6FF00) -- #6D00FF
|
||||||
|
apis.term.setPaletteColor(0x8000, 0x000000) -- #B6FF00
|
||||||
|
|
||||||
|
local function getFile(path)
|
||||||
|
local file = apis.fs.open(path, "r")
|
||||||
|
if not file then
|
||||||
|
displaySuperBadError("Could not open file: " .. path)
|
||||||
|
end
|
||||||
|
local content = file.readAll()
|
||||||
|
file.close()
|
||||||
|
return content
|
||||||
|
end
|
||||||
|
|
||||||
|
local Kernel = load(getFile(BOOT_DRIVE_PATH .. "/boot/kernel.lua"),"@Kernel")
|
||||||
|
local initFs = load(getFile(BOOT_DRIVE_PATH .. "/boot/cct/initdisks"),"@Init_disks")(apis)
|
||||||
|
local fs = load(getFile(BOOT_DRIVE_PATH .. "/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 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,
|
||||||
|
getMachineEvent = function()
|
||||||
|
if #eventQueue > 0 then
|
||||||
|
return table.unpack(table.remove(eventQueue, 1))
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
getEEPROM = function() return getFile("/startup.lua") end,
|
||||||
|
setEEPROM = function(_, text)
|
||||||
|
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",
|
||||||
|
{
|
||||||
|
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
|
||||||
119
Src/Hyperion-firmware-ccpc/boot/cct/eeprom
Normal file
119
Src/Hyperion-firmware-ccpc/boot/cct/eeprom
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
--:Minify:--
|
||||||
|
local BOOT_DRIVE_PATH=({...})[1] or "/$"
|
||||||
|
-- UnBIOS by JackMacWindows
|
||||||
|
-- This will undo most of the changes/additions made in the BIOS, but some things may remain wrapped if `debug` is unavailable
|
||||||
|
-- To use, just place a `bios.lua` in the root of the drive, and run this program
|
||||||
|
-- Here's a list of things that are irreversibly changed:
|
||||||
|
-- * both `bit` and `bit32` are kept for compatibility
|
||||||
|
-- * string metatable blocking (on old versions of CC)
|
||||||
|
-- In addition, if `debug` is not available these things are also irreversibly changed:
|
||||||
|
-- * old Lua 5.1 `load` function (for loading from a function)
|
||||||
|
-- * `loadstring` prefixing (before CC:T 1.96.0)
|
||||||
|
-- * `http.request`
|
||||||
|
-- * `os.shutdown` and `os.reboot`
|
||||||
|
-- * `peripheral`
|
||||||
|
-- * `turtle.equip[Left|Right]`
|
||||||
|
-- Licensed under the MIT license
|
||||||
|
local args = {...}
|
||||||
|
local keptAPIs = {keys=true, bit32 = true, bit = true, ccemux = true, config = true, coroutine = true, debug = true, fs = true, http = true, mounter = true, os = true, periphemu = true, peripheral = true, redstone = true, rs = true, term = true, utf8 = true, _HOST = true, _CC_DEFAULT_SETTINGS = true, _CC_DISABLE_LUA51_FEATURES = true, _VERSION = true, assert = true, collectgarbage = true, error = true, gcinfo = true, getfenv = true, getmetatable = true, ipairs = true, __inext = true,load = true, loadstring = true, math = true, newproxy = true, next = true, pairs = true, pcall = true, rawequal = true, rawget = true, rawlen = true, rawset = true, select = true, setfenv = true, setmetatable = true, string = true, table = true, tonumber = true, tostring = true, type = true, unpack = true, xpcall = true, turtle = true, pocket = true, commands = true, _G = true}
|
||||||
|
local t = {}
|
||||||
|
for k in pairs(_G) do if not keptAPIs[k] then table.insert(t, k) end end
|
||||||
|
for _,k in ipairs(t) do _G[k] = nil end
|
||||||
|
local native = _G.term.native()
|
||||||
|
for _, method in ipairs {"nativePaletteColor", "nativePaletteColour", "screenshot"} do native[method] = _G.term[method] end
|
||||||
|
_G.term = native
|
||||||
|
if _G.http then
|
||||||
|
_G.http.checkURL = _G.http.checkURLAsync
|
||||||
|
_G.http.websocket = _G.http.websocketAsync
|
||||||
|
end
|
||||||
|
if _G.commands then _G.commands = _G.commands.native end
|
||||||
|
if _G.turtle then _G.turtle.native, _G.turtle.craft = nil end
|
||||||
|
local delete = {os = {"version", "pullEventRaw", "pullEvent", "run", "loadAPI", "unloadAPI", "sleep"}, http = _G.http and {"get", "post", "put", "delete", "patch", "options", "head", "trace", "listen", "checkURLAsync", "websocketAsync"}, fs = {"complete", "isDriveRoot"}}
|
||||||
|
for k,v in pairs(delete) do for _,a in ipairs(v) do _G[k][a] = nil end end
|
||||||
|
-- Set up TLCO
|
||||||
|
-- This functions by crashing `rednet.run` by removing `os.pullEventRaw`. Normally
|
||||||
|
-- this would cause `parallel` to throw an error, but we replace `error` with an
|
||||||
|
-- empty placeholder to let it continue and return without throwing. This results
|
||||||
|
-- in the `pcall` returning successfully, preventing the error-displaying code
|
||||||
|
-- from running - essentially making it so that `os.shutdown` is called immediately
|
||||||
|
-- after the new BIOS exits.
|
||||||
|
--
|
||||||
|
-- From there, the setup code is placed in `term.native` since it's the first
|
||||||
|
-- thing called after `parallel` exits. This loads the new BIOS and prepares it
|
||||||
|
-- for execution. Finally, it overwrites `os.shutdown` with the new function to
|
||||||
|
-- allow it to be the last function called in the original BIOS, and returns.
|
||||||
|
-- From there execution continues, calling the `term.redirect` dummy, skipping
|
||||||
|
-- over the error-handling code (since `pcall` returned ok), and calling
|
||||||
|
-- `os.shutdown()`. The real `os.shutdown` is re-added, and the new BIOS is tail
|
||||||
|
-- called, which effectively makes it run as the main chunk.
|
||||||
|
local olderror = error
|
||||||
|
_G.error = function() end
|
||||||
|
_G.term.redirect = function() end
|
||||||
|
function _G.term.native()
|
||||||
|
_G.term.native = nil
|
||||||
|
_G.term.redirect = nil
|
||||||
|
_G.error = olderror
|
||||||
|
term.setBackgroundColor(32768)
|
||||||
|
term.setTextColor(1)
|
||||||
|
term.setCursorPos(1, 1)
|
||||||
|
term.setCursorBlink(true)
|
||||||
|
term.clear()
|
||||||
|
local file = fs.open(BOOT_DRIVE_PATH.."/boot/cct/boot.lua", "r")
|
||||||
|
if file == nil then
|
||||||
|
term.setCursorBlink(false)
|
||||||
|
term.setTextColor(16384)
|
||||||
|
term.write("Could not find /boot/cct/boot.lua. UnBIOS cannot continue.")
|
||||||
|
term.setCursorPos(1, 2)
|
||||||
|
term.write("Press any key to continue")
|
||||||
|
coroutine.yield("key")
|
||||||
|
os.shutdown()
|
||||||
|
end
|
||||||
|
local fn, err = loadstring(file.readAll(), "@bootloader")
|
||||||
|
file.close()
|
||||||
|
if fn == nil then
|
||||||
|
term.setCursorBlink(false)
|
||||||
|
term.setTextColor(16384)
|
||||||
|
term.write("Could not load /boot/cc/boot.lua. UnBIOS cannot continue.")
|
||||||
|
term.setCursorPos(1, 2)
|
||||||
|
term.write(err)
|
||||||
|
term.setCursorPos(1, 3)
|
||||||
|
term.write("Press any key to continue")
|
||||||
|
coroutine.yield("key")
|
||||||
|
os.shutdown()
|
||||||
|
end
|
||||||
|
setfenv(fn, _G)
|
||||||
|
local oldshutdown = os.shutdown
|
||||||
|
os.shutdown = function()
|
||||||
|
os.shutdown = oldshutdown
|
||||||
|
return fn(BOOT_DRIVE_PATH)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if debug then
|
||||||
|
-- Restore functions that were overwritten in the BIOS
|
||||||
|
-- Apparently this has to be done *after* redefining term.native
|
||||||
|
local function restoreValue(tab, idx, name, hint)
|
||||||
|
local i, key, value = 1, debug.getupvalue(tab[idx], hint)
|
||||||
|
while key ~= name and key ~= nil do
|
||||||
|
key, value = debug.getupvalue(tab[idx], i)
|
||||||
|
i=i+1
|
||||||
|
end
|
||||||
|
tab[idx] = value or tab[idx]
|
||||||
|
end
|
||||||
|
restoreValue(_G, "loadstring", "nativeloadstring", 1)
|
||||||
|
restoreValue(_G, "load", "nativeload", 5)
|
||||||
|
if http then restoreValue(http, "request", "nativeHTTPRequest", 3) end
|
||||||
|
restoreValue(os, "shutdown", "nativeShutdown", 1)
|
||||||
|
restoreValue(os, "reboot", "nativeReboot", 1)
|
||||||
|
if turtle then
|
||||||
|
restoreValue(turtle, "equipLeft", "v", 1)
|
||||||
|
restoreValue(turtle, "equipRight", "v", 1)
|
||||||
|
end
|
||||||
|
do
|
||||||
|
local i, key, value = 1, debug.getupvalue(peripheral.isPresent, 2)
|
||||||
|
while key ~= "native" and key ~= nil do
|
||||||
|
key, value = debug.getupvalue(peripheral.isPresent, i)
|
||||||
|
i=i+1
|
||||||
|
end
|
||||||
|
_G.peripheral = value or peripheral
|
||||||
|
end
|
||||||
|
end
|
||||||
155
Src/Hyperion-firmware-ccpc/boot/cct/initdisks
Normal file
155
Src/Hyperion-firmware-ccpc/boot/cct/initdisks
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
-- :Minify:--
|
||||||
|
local apis = ({...})[1]
|
||||||
|
local BOOT_DRIVE_PATH = apis.BOOT_DRIVE_PATH or "/$"
|
||||||
|
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
|
||||||
|
for n = 1, #sides do
|
||||||
|
local side = sides[n]
|
||||||
|
if native.hasType(side, "peripheral_hub") and
|
||||||
|
native.call(side, "isPresentRemote", name) then
|
||||||
|
return native.call(side, "getTypeRemote", name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function peripheral.getNames()
|
||||||
|
local names = {}
|
||||||
|
for n = 1, #sides do
|
||||||
|
local side = sides[n]
|
||||||
|
if native.isPresent(side) then table.insert(names, side) end
|
||||||
|
if native.hasType(side, "peripheral_hub") then
|
||||||
|
local hubSides = native.call(side, "getConnectedSides")
|
||||||
|
for _, hubSide in ipairs(hubSides) do
|
||||||
|
table.insert(names, hubSide)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return names
|
||||||
|
end
|
||||||
|
|
||||||
|
local disks = {}
|
||||||
|
local internal = {}
|
||||||
|
|
||||||
|
local function norm(path)
|
||||||
|
if not path or path == "" then return "/" end
|
||||||
|
return fs.combine("/", path)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function createDisk(id, basePath, readonly, periph)
|
||||||
|
basePath = norm(basePath)
|
||||||
|
|
||||||
|
local disk = {address = id, isReadOnly = function() return readonly end}
|
||||||
|
|
||||||
|
function disk:spaceUsed()
|
||||||
|
return fs.getCapacity(basePath) - fs.getFreeSpace(basePath)
|
||||||
|
end
|
||||||
|
|
||||||
|
function disk:spaceTotal() return fs.getCapacity(basePath) end
|
||||||
|
|
||||||
|
function disk:list(path)
|
||||||
|
local p = fs.combine(basePath, path)
|
||||||
|
if not fs.exists(p) or not fs.isDir(p) then
|
||||||
|
return nil, "not directory"
|
||||||
|
end
|
||||||
|
return fs.list(p)
|
||||||
|
end
|
||||||
|
|
||||||
|
function disk:fileExists(path)
|
||||||
|
local p = fs.combine(basePath, path)
|
||||||
|
return fs.exists(p) and not fs.isDir(p)
|
||||||
|
end
|
||||||
|
|
||||||
|
function disk:directoryExists(path)
|
||||||
|
local p = fs.combine(basePath, path)
|
||||||
|
return fs.exists(p) and fs.isDir(p)
|
||||||
|
end
|
||||||
|
|
||||||
|
function disk:type(path)
|
||||||
|
local p = fs.combine(basePath, path)
|
||||||
|
if not fs.exists(p) then
|
||||||
|
return nil
|
||||||
|
elseif fs.isDir(p) then
|
||||||
|
return "directory"
|
||||||
|
else
|
||||||
|
return "file"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function disk:makeDirectory(path)
|
||||||
|
local p = fs.combine(basePath, path)
|
||||||
|
fs.makeDir(p)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function disk:remove(path)
|
||||||
|
local p = fs.combine(basePath, path)
|
||||||
|
if fs.exists(p) then fs.delete(p) end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function disk:setLabel(label) periph.setLabel(label) end
|
||||||
|
|
||||||
|
function disk:getLabel(label) return periph.getLabel() end
|
||||||
|
|
||||||
|
function disk:attributes(path)
|
||||||
|
local p = fs.combine(basePath, path)
|
||||||
|
return fs.attributes(p)
|
||||||
|
end
|
||||||
|
|
||||||
|
function disk:open(path, mode)
|
||||||
|
local p = fs.combine(basePath, path)
|
||||||
|
return fs.open(p, mode)
|
||||||
|
end
|
||||||
|
|
||||||
|
return disk
|
||||||
|
end
|
||||||
|
|
||||||
|
internal["$"] = createDisk("$", BOOT_DRIVE_PATH, false, {
|
||||||
|
setLabel = function(label)
|
||||||
|
local h = fs.open("/.label", "w")
|
||||||
|
h.write(label)
|
||||||
|
h.close()
|
||||||
|
end,
|
||||||
|
getLabel = function()
|
||||||
|
local h = fs.open("/.label", "r")
|
||||||
|
if not h then return "$" end
|
||||||
|
local label = h.readAll()
|
||||||
|
h.close()
|
||||||
|
return label
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
local function refresh()
|
||||||
|
for id, _ in pairs(disks) do
|
||||||
|
if not peripheral.getType(id) then disks[id] = nil end
|
||||||
|
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
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function iter()
|
||||||
|
refresh()
|
||||||
|
local combined = {}
|
||||||
|
|
||||||
|
for id, obj in pairs(internal) do combined[id] = obj end
|
||||||
|
for id, obj in pairs(disks) do combined[id] = obj end
|
||||||
|
|
||||||
|
return pairs(combined)
|
||||||
|
end
|
||||||
|
|
||||||
|
return {refresh = refresh, list = iter}
|
||||||
394
Src/Hyperion-firmware-ccpc/lib/modules/CC-Tweaked/25_tty.kmod
Normal file
394
Src/Hyperion-firmware-ccpc/lib/modules/CC-Tweaked/25_tty.kmod
Normal file
@@ -0,0 +1,394 @@
|
|||||||
|
--: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 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
|
||||||
|
}
|
||||||
|
|
||||||
|
local function write(text, term)
|
||||||
|
local x, y = term.getCursorPos()
|
||||||
|
local w, h = term.getSize()
|
||||||
|
|
||||||
|
for i = 1, #text do
|
||||||
|
local c = text:sub(i, i)
|
||||||
|
|
||||||
|
if c == "\n" then
|
||||||
|
y = y + 1
|
||||||
|
x = 1
|
||||||
|
elseif c == "\t" then
|
||||||
|
local tabSize = 4
|
||||||
|
local spaces = tabSize - ((x - 1) % tabSize)
|
||||||
|
term.write(string.rep(" ", spaces))
|
||||||
|
x = x + spaces
|
||||||
|
elseif c == "\b" then
|
||||||
|
if x > 1 then
|
||||||
|
x = x - 1
|
||||||
|
term.setCursorPos(x, y)
|
||||||
|
term.write(" ")
|
||||||
|
term.setCursorPos(x, y)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if x <= w and y <= h then
|
||||||
|
term.setCursorPos(x, y)
|
||||||
|
term.write(c)
|
||||||
|
x = x + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if x > w then
|
||||||
|
x = 1
|
||||||
|
y = y + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
if y - 1 >= h then
|
||||||
|
term.scroll(1)
|
||||||
|
y = h
|
||||||
|
term.setCursorPos(x, y)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
term.setCursorPos(x, y)
|
||||||
|
end
|
||||||
|
|
||||||
|
kernel.devfs.data.tty={}
|
||||||
|
local ctrl,alt = false, false
|
||||||
|
|
||||||
|
local function serializeBool(bool)
|
||||||
|
if bool then
|
||||||
|
return "T"
|
||||||
|
else
|
||||||
|
return "F"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function newtty(obj, id, ev)
|
||||||
|
kernel.devfs.data["tty"][id] = function(op, mode)
|
||||||
|
if op=="type" then
|
||||||
|
return "character device"
|
||||||
|
elseif op=="open" then
|
||||||
|
local h = {
|
||||||
|
read=function(amount)
|
||||||
|
local rv=""
|
||||||
|
for i=1, amount or 1 do
|
||||||
|
local event = {ev()}
|
||||||
|
if event[1] then
|
||||||
|
rv=rv..event[1]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if rv=="" then rv=nil end
|
||||||
|
return rv
|
||||||
|
end,
|
||||||
|
write=function(content)
|
||||||
|
write(content, obj)
|
||||||
|
end,
|
||||||
|
size=function()
|
||||||
|
local s={obj.getSize()}
|
||||||
|
return table.concat(s,";")
|
||||||
|
end,
|
||||||
|
clear=function()
|
||||||
|
obj.clear()
|
||||||
|
obj.setCursorPos(1,1)
|
||||||
|
end,
|
||||||
|
gpos=function()
|
||||||
|
local s={obj.getCursorPos()}
|
||||||
|
return table.concat(s,";")
|
||||||
|
end,
|
||||||
|
spos=function(x,y)
|
||||||
|
return obj.setCursorPos(x,y)
|
||||||
|
end,
|
||||||
|
sfgc=function(c)
|
||||||
|
return obj.setTextColor(colors[c])
|
||||||
|
end,
|
||||||
|
sbgc=function(c)
|
||||||
|
return obj.setBackgroundColor(colors[c])
|
||||||
|
end,
|
||||||
|
gfgc=function()
|
||||||
|
return icolors[obj.getTextColor()]
|
||||||
|
end,
|
||||||
|
gbgc=function()
|
||||||
|
return icolors[obj.getBackgroundColor()]
|
||||||
|
end,
|
||||||
|
gctrl=function()
|
||||||
|
return serializeBool(ctrl)..";"..serializeBool(alt)
|
||||||
|
end
|
||||||
|
}
|
||||||
|
if mode=="rw" then
|
||||||
|
return h
|
||||||
|
elseif mode=="r" then
|
||||||
|
h["write"]=nil
|
||||||
|
return h
|
||||||
|
elseif mode=="w" then
|
||||||
|
h["read"]=nil
|
||||||
|
return h
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local fifo = kernel.newFifo()
|
||||||
|
|
||||||
|
kernel.processes.cctmond = function()
|
||||||
|
local timeout = false
|
||||||
|
while true do
|
||||||
|
local event = {kernel.computer: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,
|
||||||
|
}
|
||||||
|
|
||||||
|
if eventType == "keyPressed" then
|
||||||
|
if charOrKey == apis.keys.leftCtrl or charOrKey == apis.keys.rightCtrl then
|
||||||
|
ctrl = true
|
||||||
|
elseif charOrKey == apis.keys.leftAlt or charOrKey == apis.keys.rightAlt then
|
||||||
|
alt = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if ctrl then
|
||||||
|
local ctrlByte = ctrlKeyMap[charOrKey]
|
||||||
|
if ctrlByte then
|
||||||
|
if ctrlByte == 3 then
|
||||||
|
for _, task in ipairs(syscall.getTasks()) do
|
||||||
|
syscall.sigsend(task, 1)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
fifo.push(string.char(ctrlByte))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local specialKeyMap = {
|
||||||
|
[apis.keys.up] = "[A",
|
||||||
|
[apis.keys.down] = "[B",
|
||||||
|
[apis.keys.right] = "[C",
|
||||||
|
[apis.keys.left] = "[D",
|
||||||
|
[apis.keys.home] = "[H",
|
||||||
|
[apis.keys["end"]] = "[F",
|
||||||
|
[apis.keys.pageUp] = "[5~",
|
||||||
|
[apis.keys.pageDown] = "[6~",
|
||||||
|
[apis.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
|
||||||
|
ctrl = false
|
||||||
|
elseif charOrKey == apis.keys.leftAlt or charOrKey == apis.keys.rightAlt then
|
||||||
|
alt = false
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif eventType == "keyTyped" then
|
||||||
|
if charOrKey then fifo.push(charOrKey) end
|
||||||
|
end
|
||||||
|
|
||||||
|
timeout = false
|
||||||
|
else
|
||||||
|
timeout = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if timeout then
|
||||||
|
sleep(0.05)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
newtty(apis.term, "1", fifo.pop)
|
||||||
|
|
||||||
|
for i,v in ipairs({peripheral.find("monitor")}) do
|
||||||
|
v.setTextScale(.5)
|
||||||
|
v.write("Initializing...")
|
||||||
|
newtty(v,tostring(i+1),function () end)
|
||||||
|
end
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
local args={...}
|
||||||
|
local kernel=args[1]
|
||||||
|
local driver={}
|
||||||
|
|
||||||
|
driver.name="CCT Term Module"
|
||||||
|
driver.version="0.1.0"
|
||||||
|
driver.type="gpio"
|
||||||
|
driver.description="CCT redstone Module Kernel Module"
|
||||||
|
driver.arch="cct"
|
||||||
|
driver.author="HyperionOS Dev Team"
|
||||||
|
driver.license="MIT"
|
||||||
|
driver.api={}
|
||||||
|
|
||||||
|
function driver.load()
|
||||||
|
-- will
|
||||||
|
end
|
||||||
|
|
||||||
|
function driver.unload()
|
||||||
|
-- Nothing to unload
|
||||||
|
end
|
||||||
|
|
||||||
|
function driver.main()
|
||||||
|
-- Nothing to run
|
||||||
|
end
|
||||||
|
|
||||||
|
-- kernel.drivers.register(driver)
|
||||||
@@ -243,6 +243,22 @@ local function serializeBool(bool)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function newtty(obj, id, ev)
|
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(0x1000, 0xDBDBAA) -- #6D6D55
|
||||||
|
obj.setPaletteColor(0x2000, 0x6D00FF) -- #DBDBAA
|
||||||
|
obj.setPaletteColor(0x4000, 0xB6FF00) -- #6D00FF
|
||||||
|
obj.setPaletteColor(0x8000, 0x000000) -- #B6FF00
|
||||||
kernel.devfs.data["tty"][id] = function(op, mode)
|
kernel.devfs.data["tty"][id] = function(op, mode)
|
||||||
if op=="type" then
|
if op=="type" then
|
||||||
return "character device"
|
return "character device"
|
||||||
|
|||||||
@@ -27,15 +27,15 @@ local windowsExp = false
|
|||||||
|
|
||||||
function kernel.log(msg, level, c)
|
function kernel.log(msg, level, c)
|
||||||
c=c or 12
|
c=c or 12
|
||||||
kernel.LOG_Text = kernel.LOG_Text..tostring(computer:time()).." "..kernel.users[kernel.uid].." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n"
|
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"
|
||||||
if kernel.status == "start" then
|
if kernel.status == "start" then
|
||||||
screen:setTextColor(c)
|
screen:setTextColor(c)
|
||||||
screen:print(string.format("%X",c-1).." "..tostring(computer:time()).." "..kernel.users[kernel.uid].." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg)
|
screen:print(tostring(computer:time()).." "..kernel.users[kernel.uid].." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg)
|
||||||
elseif kernel.status == "term" then
|
elseif kernel.status == "term" then
|
||||||
kernel.standbyTask=kernel.currentTask
|
kernel.standbyTask=kernel.currentTask
|
||||||
kernel.currentTask=kernel.kernelTask
|
kernel.currentTask=kernel.kernelTask
|
||||||
kernel.vfs.devctl(1,"sfgc",c)
|
kernel.vfs.devctl(1,"sfgc",c)
|
||||||
kernel.vfs.write(1,string.format("%X",c-1).." "..tostring(computer:time()).." "..kernel.users[kernel.uid].." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n")
|
kernel.vfs.write(1,tostring(computer:time()).." "..kernel.users[kernel.uid].." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n")
|
||||||
kernel.currentTask=kernel.standbyTask
|
kernel.currentTask=kernel.standbyTask
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -149,6 +149,10 @@ function kernel.saveLog()
|
|||||||
ifs.writeAllText("/var/log/syslog.log", kernel.LOG_Text)
|
ifs.writeAllText("/var/log/syslog.log", kernel.LOG_Text)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function loadcstr(string)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
function kernel.newFifo()
|
function kernel.newFifo()
|
||||||
local fifo = {}
|
local fifo = {}
|
||||||
fifo.push=function(data)
|
fifo.push=function(data)
|
||||||
@@ -251,7 +255,12 @@ kernel.syscalls["sysdump"]=function()
|
|||||||
end
|
end
|
||||||
return rv
|
return rv
|
||||||
end
|
end
|
||||||
kernel.syscalls["test"]=function() return true end
|
kernel.syscalls["reboot"]=function()
|
||||||
|
kernel.computer:reboot()
|
||||||
|
end
|
||||||
|
kernel.syscalls["shutdown"]=function()
|
||||||
|
kernel.computer:reboot()
|
||||||
|
end
|
||||||
|
|
||||||
kernel.log("Running modules")
|
kernel.log("Running modules")
|
||||||
for _,p in ipairs(modules) do
|
for _,p in ipairs(modules) do
|
||||||
@@ -272,6 +281,7 @@ for _,p in ipairs(modules) do
|
|||||||
end
|
end
|
||||||
|
|
||||||
kernel.log("Kernel initialized successfully.")
|
kernel.log("Kernel initialized successfully.")
|
||||||
|
kernel.saveLog()
|
||||||
kernel.status="running"
|
kernel.status="running"
|
||||||
kernel.main()
|
kernel.main()
|
||||||
if kernel.status=="panic" then
|
if kernel.status=="panic" then
|
||||||
|
|||||||
@@ -401,12 +401,27 @@ local function getFileMeta(path, noFollow)
|
|||||||
return { etype = 0x00, owner = 0, group = 0, perms = 63, cmeta = "" }
|
return { etype = 0x00, owner = 0, group = 0, perms = 63, cmeta = "" }
|
||||||
end
|
end
|
||||||
|
|
||||||
local parent, name = real:match("^(.*)/([^/]+)$")
|
local cur = real
|
||||||
if not parent or parent == "" then parent = "/" end
|
|
||||||
|
-- FML i hated implementing this - Astronand
|
||||||
|
while true do
|
||||||
|
local parent, name = cur:match("^(.*)/([^/]+)$")
|
||||||
|
if not parent or parent == "" then parent = "/" end
|
||||||
|
|
||||||
|
local disk, parentDiskPath = resolveMount(parent)
|
||||||
|
local entry = readMetaEntry(disk, parentDiskPath, name)
|
||||||
|
|
||||||
|
if entry then
|
||||||
|
return entry
|
||||||
|
end
|
||||||
|
|
||||||
|
if parent == "/" or cur == "/" then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
cur = parent
|
||||||
|
end
|
||||||
|
|
||||||
local disk, parentDiskPath = resolveMount(parent)
|
|
||||||
local entry = readMetaEntry(disk, parentDiskPath, name)
|
|
||||||
if entry then return entry end
|
|
||||||
return { etype = 0x00, owner = 0, group = 0, perms = 63, cmeta = "" }
|
return { etype = 0x00, owner = 0, group = 0, perms = 63, cmeta = "" }
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -610,6 +625,7 @@ function vfs.open(path, mode)
|
|||||||
if mode == "r" and bit_is_set(meta.perms, 6) then
|
if mode == "r" and bit_is_set(meta.perms, 6) then
|
||||||
fobj.suid_owner = meta.owner
|
fobj.suid_owner = meta.owner
|
||||||
end
|
end
|
||||||
|
if disk.isvirt then fobj.isvirt=true end
|
||||||
task.fd[fd] = fobj
|
task.fd[fd] = fobj
|
||||||
if not disk.isvirt then total = total + 1 end
|
if not disk.isvirt then total = total + 1 end
|
||||||
return fd
|
return fd
|
||||||
@@ -658,8 +674,10 @@ function vfs.close(fd)
|
|||||||
local task = kernel.currentTask
|
local task = kernel.currentTask
|
||||||
local file = task.fd[fd]
|
local file = task.fd[fd]
|
||||||
if not file then error("EBADF") end
|
if not file then error("EBADF") end
|
||||||
|
if not task.fd[fd].isvirt then
|
||||||
|
total = total - 1
|
||||||
|
end
|
||||||
task.fd[fd] = nil
|
task.fd[fd] = nil
|
||||||
total = total - 1
|
|
||||||
file.refcount = file.refcount - 1
|
file.refcount = file.refcount - 1
|
||||||
if file.refcount <= 0 and file.handle and file.handle.close then
|
if file.refcount <= 0 and file.handle and file.handle.close then
|
||||||
file.handle.close()
|
file.handle.close()
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ proxy.getLabel = function() return "devfs" end
|
|||||||
proxy.attributes = function(path) return {
|
proxy.attributes = function(path) return {
|
||||||
size = 0,
|
size = 0,
|
||||||
modified = 0,
|
modified = 0,
|
||||||
created = 0,
|
created = 0
|
||||||
} end
|
} end
|
||||||
|
|
||||||
function proxy:open(path, mode)
|
function proxy:open(path, mode)
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ kernel.log("Seeding filesystem permissions...", "INFO")
|
|||||||
mergeMeta("/", {
|
mergeMeta("/", {
|
||||||
{"bin", REG, 0, 0, RWX_RX_RX},
|
{"bin", REG, 0, 0, RWX_RX_RX},
|
||||||
{"boot", REG, 0, 0, RWX_RX_RX},
|
{"boot", REG, 0, 0, RWX_RX_RX},
|
||||||
{"dev", REG, 0, 0, RWX_RX_RX},
|
{"dev", REG, 0, 0, RWXRWXRWX},
|
||||||
{"etc", REG, 0, 0, RWX_RX_RX},
|
{"etc", REG, 0, 0, RWX_RX_RX},
|
||||||
{"home", REG, 0, 0, RWX_RX_RX},
|
{"home", REG, 0, 0, RWX_RX_RX},
|
||||||
{"lib", REG, 0, 0, RWX_RX_RX},
|
{"lib", REG, 0, 0, RWX_RX_RX},
|
||||||
@@ -98,126 +98,10 @@ mergeMeta("/", {
|
|||||||
{"var", REG, 0, 0, RWX_RX_RX},
|
{"var", REG, 0, 0, RWX_RX_RX},
|
||||||
})
|
})
|
||||||
|
|
||||||
mergeMeta("/boot", {
|
|
||||||
{"kernel.lua", REG, 0, 0, RW_R_R },
|
|
||||||
{"boot.cfg", REG, 0, 0, RW_R_R },
|
|
||||||
{"safeboot.cfg", REG, 0, 0, RW_R_R },
|
|
||||||
{"fstab", REG, 0, 0, RW_R_R },
|
|
||||||
{"initfs", REG, 0, 0, RW_R_R },
|
|
||||||
{"cct", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"oc", REG, 0, 0, RWX_RX_RX},
|
|
||||||
})
|
|
||||||
|
|
||||||
mergeMeta("/boot/cct", {
|
|
||||||
{"boot.lua", REG, 0, 0, RW_R_R},
|
|
||||||
{"initdisks", REG, 0, 0, RW_R_R},
|
|
||||||
{"eeprom", REG, 0, 0, RW_R_R},
|
|
||||||
})
|
|
||||||
|
|
||||||
mergeMeta("/boot/oc", {
|
|
||||||
{"boot.lua", REG, 0, 0, RW_R_R},
|
|
||||||
{"initfs.lua",REG, 0, 0, RW_R_R},
|
|
||||||
{"eeprom", REG, 0, 0, RW_R_R},
|
|
||||||
})
|
|
||||||
|
|
||||||
mergeMeta("/sbin", {
|
|
||||||
{"init.lua", REG, 0, 0, RWX_RX_RX},
|
|
||||||
})
|
|
||||||
|
|
||||||
mergeMeta("/bin", {
|
mergeMeta("/bin", {
|
||||||
{"cat", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"chattr", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"chgrp", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"chmod", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"chown", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"chroot", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"clear", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"echo", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"hfetch", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"help", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"hysh", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"hyshex", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"id", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"install", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"ln", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"login", REG, 0, 0, SUID_755 },
|
{"login", REG, 0, 0, SUID_755 },
|
||||||
{"loimgcreate", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"looptest", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"losetup", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"ls", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"lsusers", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"lua", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"luaold", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"micro", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"mkdir", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"mount", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"passwd", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"ps", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"pwd", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"readlink", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"sed", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"socktest", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"spm", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"startup", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"su", REG, 0, 0, SUID_755 },
|
{"su", REG, 0, 0, SUID_755 },
|
||||||
{"sudo", REG, 0, 0, SUID_755 },
|
{"sudo", REG, 0, 0, SUID_755 },
|
||||||
{"sysdump", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"umount", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"useradd", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"userdel", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"usermod", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"whoami", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"yes", REG, 0, 0, RWX_RX_RX},
|
|
||||||
})
|
|
||||||
|
|
||||||
mergeMeta("/bin/startup", {
|
|
||||||
{"test.lua", REG, 0, 0, RWX_RX_RX},
|
|
||||||
})
|
|
||||||
|
|
||||||
mergeMeta("/lib", {
|
|
||||||
{"sys", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"modules", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"crypto", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"store", REG, 0, 0, RWX_RX_RX},
|
|
||||||
{"snip", REG, 0, 0, RW_R_R },
|
|
||||||
{"io", REG, 0, 0, RW_R_R },
|
|
||||||
{"bit32", REG, 0, 0, RW_R_R },
|
|
||||||
})
|
|
||||||
|
|
||||||
mergeMeta("/lib/sys", {
|
|
||||||
{"fs", REG, 0, 0, RW_R_R},
|
|
||||||
{"hpv", REG, 0, 0, RW_R_R},
|
|
||||||
{"ipc", REG, 0, 0, RW_R_R},
|
|
||||||
{"term", REG, 0, 0, RW_R_R},
|
|
||||||
{"init", REG, 0, 0, RW_R_R},
|
|
||||||
})
|
|
||||||
|
|
||||||
mergeMeta("/lib/modules", {
|
|
||||||
{"hyperion", REG, 0, 0, RWX_RX_RX},
|
|
||||||
})
|
|
||||||
|
|
||||||
mergeMeta("/lib/modules/hyperion", {
|
|
||||||
{"01_stdlib.kmod", REG, 0, 0, RW_R_R},
|
|
||||||
{"10_vfs.kmod", REG, 0, 0, RW_R_R},
|
|
||||||
{"11_require.kmod", REG, 0, 0, RW_R_R},
|
|
||||||
{"12_devfs.kmod", REG, 0, 0, RW_R_R},
|
|
||||||
{"12_tmpfs.kmod", REG, 0, 0, RW_R_R},
|
|
||||||
{"13_loopdev.kmod", REG, 0, 0, RW_R_R},
|
|
||||||
{"14_keventd.kmod", REG, 0, 0, RW_R_R},
|
|
||||||
{"19_fstab.kmod", REG, 0, 0, RW_R_R},
|
|
||||||
{"20_signals.kmod", REG, 0, 0, RW_R_R},
|
|
||||||
{"20_socket.kmod", REG, 0, 0, RW_R_R},
|
|
||||||
{"26_tty.kmod", REG, 0, 0, RW_R_R},
|
|
||||||
{"30_userspace.kmod", REG, 0, 0, RW_R_R},
|
|
||||||
{"40_auth.kmod", REG, 0, 0, RW_R_R},
|
|
||||||
{"45_hypervisor.kmod", REG, 0, 0, RW_R_R},
|
|
||||||
{"47_dbg.kmod", REG, 0, 0, RW_R_R},
|
|
||||||
{"50_gpio.kmod", REG, 0, 0, RW_R_R},
|
|
||||||
{"70_stdlibadv.kmod", REG, 0, 0, RW_R_R},
|
|
||||||
{"90_init.kmod", REG, 0, 0, RW_R_R},
|
|
||||||
{"91_login.kmod", REG, 0, 0, RW_R_R},
|
|
||||||
{"92_permissions.kmod", REG, 0, 0, RW_R_R},
|
|
||||||
{"99_final.kmod", REG, 0, 0, RW_R_R},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
mergeMeta("/etc", {
|
mergeMeta("/etc", {
|
||||||
|
|||||||
158
build.py
158
build.py
@@ -6,8 +6,10 @@ Usage:
|
|||||||
Targets:
|
Targets:
|
||||||
build
|
build
|
||||||
build-mini
|
build-mini
|
||||||
|
build-micro
|
||||||
build-test
|
build-test
|
||||||
build-mini-test
|
build-mini-test
|
||||||
|
build-micro-test
|
||||||
clean
|
clean
|
||||||
|
|
||||||
Arch flags:
|
Arch flags:
|
||||||
@@ -23,11 +25,9 @@ import sys
|
|||||||
import shutil
|
import shutil
|
||||||
import argparse
|
import argparse
|
||||||
import subprocess
|
import subprocess
|
||||||
import hashlib
|
|
||||||
import random
|
|
||||||
import string
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
import lz4.frame
|
||||||
|
|
||||||
PROJECT_ROOT = Path(__file__).resolve().parent
|
PROJECT_ROOT = Path(__file__).resolve().parent
|
||||||
SRC_ROOT = PROJECT_ROOT / "Src"
|
SRC_ROOT = PROJECT_ROOT / "Src"
|
||||||
@@ -48,7 +48,34 @@ def clean():
|
|||||||
print("Nothing to clean.")
|
print("Nothing to clean.")
|
||||||
|
|
||||||
|
|
||||||
def process_root(src_root: Path, out_root: Path, minify: bool):
|
def has_minify_header(path: Path) -> bool:
|
||||||
|
try:
|
||||||
|
with path.open("r", encoding="utf-8", errors="ignore") as f:
|
||||||
|
for _ in range(3):
|
||||||
|
if "--:Minify:--" in f.readline():
|
||||||
|
return True
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def minify_file(src: Path) -> str:
|
||||||
|
result = subprocess.run(
|
||||||
|
["luamin.cmd", "-f", str(src)],
|
||||||
|
capture_output=True,
|
||||||
|
text=True
|
||||||
|
)
|
||||||
|
if result.returncode != 0:
|
||||||
|
print(f" ! luamin failed: {result.stderr.strip()}", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
return result.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def compress_lz4(data: bytes) -> bytes:
|
||||||
|
return lz4.frame.compress(data)
|
||||||
|
|
||||||
|
|
||||||
|
def process_root(src_root: Path, out_root: Path, minify: bool, micro: bool):
|
||||||
print(f"Building from {src_root}")
|
print(f"Building from {src_root}")
|
||||||
print(f"Output to {out_root}")
|
print(f"Output to {out_root}")
|
||||||
print()
|
print()
|
||||||
@@ -69,16 +96,20 @@ def process_root(src_root: Path, out_root: Path, minify: bool):
|
|||||||
|
|
||||||
print(f" Processing: {src.relative_to(src_root)}")
|
print(f" Processing: {src.relative_to(src_root)}")
|
||||||
|
|
||||||
if minify and has_minify_header(src):
|
if has_minify_header(src):
|
||||||
print(" > Minifying")
|
print(" > Minifying")
|
||||||
result = subprocess.run(
|
content = minify_file(src)
|
||||||
["luamin.cmd", "-f", str(src)],
|
if micro:
|
||||||
capture_output=True, text=True
|
print(" > LZ4 compressing")
|
||||||
)
|
compressed = compress_lz4(content.encode("utf-8"))
|
||||||
if result.returncode != 0:
|
# wrap in kernel.unpack if in hyperion-kernel
|
||||||
print(f" ! luamin failed: {result.stderr.strip()}", file=sys.stderr)
|
if pkg_dir.name == "hyperion-kernel" and dst.suffix == ".lua":
|
||||||
sys.exit(1)
|
content_str = f"kernel.unpack([=[{compressed.hex()}]=])"
|
||||||
dst.write_text(result.stdout, encoding="utf-8")
|
dst.write_text(content_str, encoding="utf-8")
|
||||||
|
else:
|
||||||
|
dst.write_bytes(compressed)
|
||||||
|
else:
|
||||||
|
dst.write_text(content, encoding="utf-8")
|
||||||
else:
|
else:
|
||||||
print(" > Copying")
|
print(" > Copying")
|
||||||
shutil.copy2(src, dst)
|
shutil.copy2(src, dst)
|
||||||
@@ -95,26 +126,15 @@ def install_bootloader(arch: str, release: bool):
|
|||||||
shutil.copy2(eeprom, BUILD_ROOT / eeprom_dst_name)
|
shutil.copy2(eeprom, BUILD_ROOT / eeprom_dst_name)
|
||||||
|
|
||||||
|
|
||||||
def has_minify_header(path: Path) -> bool:
|
def run_build(minify: bool, micro: bool, include_test: bool, arch: Union[str, None], release: bool):
|
||||||
try:
|
|
||||||
with path.open("r", encoding="utf-8", errors="ignore") as f:
|
|
||||||
for _ in range(3):
|
|
||||||
if "--:Minify:--" in f.readline():
|
|
||||||
return True
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def run_build(minify: bool, include_test: bool, arch: Union[str, None], release: bool):
|
|
||||||
clean()
|
clean()
|
||||||
BUILD_ROOT.mkdir()
|
BUILD_ROOT.mkdir()
|
||||||
|
|
||||||
out_root = BUILD_ROOT / "$" if arch else BUILD_ROOT
|
out_root = BUILD_ROOT / "$" if arch else BUILD_ROOT
|
||||||
|
|
||||||
process_root(SRC_ROOT, out_root, minify)
|
process_root(SRC_ROOT, out_root, minify, micro)
|
||||||
if include_test:
|
if include_test:
|
||||||
process_root(TEST_ROOT, out_root, minify)
|
process_root(TEST_ROOT, out_root, minify, micro)
|
||||||
|
|
||||||
if arch:
|
if arch:
|
||||||
print("Installing bootloader files ...")
|
print("Installing bootloader files ...")
|
||||||
@@ -122,46 +142,6 @@ def run_build(minify: bool, include_test: bool, arch: Union[str, None], release:
|
|||||||
print()
|
print()
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
parser = argparse.ArgumentParser(description="HyperionOS build script")
|
|
||||||
parser.add_argument("target", choices=["build", "build-mini", "build-test", "build-mini-test", "clean"])
|
|
||||||
parser.add_argument("--arch", choices=["cct", "oc"], default=None,
|
|
||||||
help="Target architecture (cct or oc)")
|
|
||||||
parser.add_argument("--release", dest="release", action="store_true", default=True,
|
|
||||||
help="Release build: eeprom placed as startup.lua (default)")
|
|
||||||
parser.add_argument("--dev", dest="release", action="store_false",
|
|
||||||
help="Dev build: boot.lua and eeprom copied unchanged")
|
|
||||||
parser.add_argument(
|
|
||||||
"--makeuser", metavar=("USERNAME", "PASSWORD"), nargs=2, action="append",
|
|
||||||
default=[],
|
|
||||||
help=(
|
|
||||||
"Pre-create a user on first boot (dev builds only). "
|
|
||||||
"May be specified multiple times. "
|
|
||||||
"Example: --makeuser root secretpass --makeuser alice alicepass"
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
if args.makeuser and args.release:
|
|
||||||
parser.error("--makeuser is only allowed with --dev builds")
|
|
||||||
|
|
||||||
if args.target == "clean":
|
|
||||||
clean()
|
|
||||||
return
|
|
||||||
|
|
||||||
minify = "mini" in args.target
|
|
||||||
include_test = "test" in args.target
|
|
||||||
|
|
||||||
run_build(minify=minify, include_test=include_test, arch=args.arch, release=args.release)
|
|
||||||
|
|
||||||
if args.makeuser:
|
|
||||||
print("Injecting first-boot user setup ...")
|
|
||||||
inject_makeusers(args.makeuser, args.arch)
|
|
||||||
print()
|
|
||||||
|
|
||||||
print("Build complete.")
|
|
||||||
|
|
||||||
def _make_firstboot_kmod(users):
|
def _make_firstboot_kmod(users):
|
||||||
lines = []
|
lines = []
|
||||||
lines.append("local kernel = ...")
|
lines.append("local kernel = ...")
|
||||||
@@ -212,5 +192,47 @@ def inject_makeusers(users, arch):
|
|||||||
print(" Wrote first-boot user setup -> " + str(kmod_path.relative_to(BUILD_ROOT)))
|
print(" Wrote first-boot user setup -> " + str(kmod_path.relative_to(BUILD_ROOT)))
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description="HyperionOS build script")
|
||||||
|
parser.add_argument("target", choices=["build", "build-mini", "build-micro", "build-test", "build-mini-test", "build-micro-test", "clean"])
|
||||||
|
parser.add_argument("--arch", choices=["cct", "oc"], default=None,
|
||||||
|
help="Target architecture (cct or oc)")
|
||||||
|
parser.add_argument("--release", dest="release", action="store_true", default=True,
|
||||||
|
help="Release build: eeprom placed as startup.lua (default)")
|
||||||
|
parser.add_argument("--dev", dest="release", action="store_false",
|
||||||
|
help="Dev build: boot.lua and eeprom copied unchanged")
|
||||||
|
parser.add_argument(
|
||||||
|
"--makeuser", metavar=("USERNAME", "PASSWORD"), nargs=2, action="append",
|
||||||
|
default=[],
|
||||||
|
help=(
|
||||||
|
"Pre-create a user on first boot (dev builds only). "
|
||||||
|
"May be specified multiple times. "
|
||||||
|
"Example: --makeuser root secretpass --makeuser alice alicepass"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.makeuser and args.release:
|
||||||
|
parser.error("--makeuser is only allowed with --dev builds")
|
||||||
|
|
||||||
|
if args.target == "clean":
|
||||||
|
clean()
|
||||||
|
return
|
||||||
|
|
||||||
|
minify = "mini" in args.target or "micro" in args.target
|
||||||
|
micro = "micro" in args.target
|
||||||
|
include_test = "test" in args.target
|
||||||
|
|
||||||
|
run_build(minify=minify, micro=micro, include_test=include_test, arch=args.arch, release=args.release)
|
||||||
|
|
||||||
|
if args.makeuser:
|
||||||
|
print("Injecting first-boot user setup ...")
|
||||||
|
inject_makeusers(args.makeuser, args.arch)
|
||||||
|
print()
|
||||||
|
|
||||||
|
print("Build complete.")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
73
building.md
73
building.md
@@ -8,24 +8,23 @@ Run:
|
|||||||
make build
|
make build
|
||||||
```
|
```
|
||||||
|
|
||||||
Optional variables:
|
**Optional variables:**
|
||||||
|
|
||||||
* **`ARCH=`**
|
* **`ARCH=`** – Select bootloader type:
|
||||||
|
|
||||||
* `cct` Build using the cct bootloader
|
* `cct` – Build using the CCT bootloader
|
||||||
* `oc` Build using the oc bootloader
|
* `oc` – Build using the OC bootloader
|
||||||
|
|
||||||
* **`DEV=1`**
|
* **`DEV=1`** – Enable development mode:
|
||||||
|
|
||||||
* Builds in development mode
|
* Bootloader does **not** start automatically on system startup
|
||||||
* Bootloader does not start automatically on system startup
|
|
||||||
|
|
||||||
If `DEV` is not specified:
|
**Default behavior (if `DEV` is not specified):**
|
||||||
|
|
||||||
* Default is release mode
|
* Builds in **release mode**
|
||||||
* Bootloader starts automatically on system startup
|
* Bootloader starts automatically on system startup
|
||||||
|
|
||||||
**Examples**
|
**Examples:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make build ARCH=cct
|
make build ARCH=cct
|
||||||
@@ -42,38 +41,46 @@ Run:
|
|||||||
python build.py build
|
python build.py build
|
||||||
```
|
```
|
||||||
|
|
||||||
Optional arguments:
|
**Optional arguments:**
|
||||||
|
|
||||||
* **`--arch {cct|oc}`**
|
* **`--arch {cct|oc}`** – Select bootloader:
|
||||||
Select bootloader
|
|
||||||
|
|
||||||
* `cct` Use the cct bootloader
|
* `cct` – Use the CCT bootloader
|
||||||
* `oc` Use the oc bootloader
|
* `oc` – Use the OC bootloader
|
||||||
|
|
||||||
* **`--dev`**
|
* **`--dev`** – Development mode:
|
||||||
|
|
||||||
* Development mode
|
* Bootloader does **not** start automatically
|
||||||
* Bootloader does not start automatically. You must run `eeprom` in CraftOS to start Hyperion.
|
* You must run `eeprom` in CraftOS to start Hyperion
|
||||||
|
|
||||||
* **`--release`** (default)
|
* **`--release`** (default) – Release mode:
|
||||||
|
|
||||||
* Release mode
|
|
||||||
* Bootloader starts automatically
|
* Bootloader starts automatically
|
||||||
|
|
||||||
* **`--makeuser username password`**
|
|
||||||
Makes a username upon startup. Only works for `--dev` builds.
|
|
||||||
|
|
||||||
* `--makeuser root rootpass`
|
|
||||||
|
|
||||||
Makes the root account already exist on first boot with rootpass as password
|
|
||||||
|
|
||||||
* `--makeuser root rootpass --makeuser alice alicepass`
|
|
||||||
|
|
||||||
Makes the root account and alice account already exist on first boot with defined passwords
|
|
||||||
|
|
||||||
**Examples**
|
* **`--makeuser username password`** – Pre-create user accounts (only works with `--dev` builds):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
--makeuser root rootpass
|
||||||
|
--makeuser root rootpass --makeuser alice alicepass
|
||||||
|
```
|
||||||
|
|
||||||
|
* Example: The first command creates the `root` account with the given password on first boot
|
||||||
|
* Example: The second command creates both `root` and `alice` accounts with defined passwords on first boot
|
||||||
|
|
||||||
|
**Examples:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python build.py build --arch cct
|
python build.py build --arch cct
|
||||||
python build.py build --arch oc --dev
|
python build.py build --arch oc --dev
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Build Requirements
|
||||||
|
|
||||||
|
* **`build`** – No additional requirements
|
||||||
|
* **`build-mini`** – Requires [`luamin`](https://www.npmjs.com/package/luamin)
|
||||||
|
* **`build-micro`** – Requires:
|
||||||
|
|
||||||
|
* [`luamin`](https://www.npmjs.com/package/luamin)
|
||||||
|
* [`LZ4 binaries`](https://github.com/lz4/lz4/releases)
|
||||||
Reference in New Issue
Block a user