Compare commits
2 Commits
1.2.4-dev_
...
099638c735
| Author | SHA1 | Date | |
|---|---|---|---|
| 099638c735 | |||
| 5172da1b5b |
@@ -1,18 +0,0 @@
|
|||||||
--:Minify:--
|
|
||||||
return {
|
|
||||||
white=0xFFFFFF,
|
|
||||||
red=0xFF0000,
|
|
||||||
green=0x00FF00,
|
|
||||||
blue=0x0000FF,
|
|
||||||
cyan=0x00FFFF,
|
|
||||||
yellow=0xFFFF00,
|
|
||||||
purple=0xFF00FF,
|
|
||||||
black=0x000000,
|
|
||||||
gray=0x888888,
|
|
||||||
lightgrey=0xBBBBBB,
|
|
||||||
darkgrey=0x444444,
|
|
||||||
orange=0xFF8800,
|
|
||||||
mint=0x00FF88,
|
|
||||||
brown=0xa52a2a,
|
|
||||||
chocolate=0xd2691e
|
|
||||||
}
|
|
||||||
@@ -1,344 +0,0 @@
|
|||||||
--:Minify:--
|
|
||||||
local args={...}
|
|
||||||
local bootdrive=args[1]
|
|
||||||
local gpu=components:getFirst("gpu")
|
|
||||||
local screenTextBuffer=nil
|
|
||||||
local cursorX,cursorY=0,0
|
|
||||||
local screenSizeX,screenSizeY=128,25
|
|
||||||
|
|
||||||
|
|
||||||
if gpu then
|
|
||||||
screenTextBuffer=gpu:newBuffer(screenSizeX,screenSizeY)
|
|
||||||
for t,v in components:list() do
|
|
||||||
if t == "screen" then
|
|
||||||
gpu:assignBuffer(screenTextBuffer, v)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function write(text)
|
|
||||||
cursorX, cursorY = screenTextBuffer:pasteText(cursorX, cursorY, "SCROLL_SPILL_CLEAR", text)
|
|
||||||
cursorY = cursorY + 1
|
|
||||||
cursorX = 0
|
|
||||||
if cursorY >= screenSizeY then
|
|
||||||
cursorY = screenSizeY-1
|
|
||||||
screenTextBuffer:newline()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function displaySuperBadError(err)
|
|
||||||
gpu:freeAllBuffers()
|
|
||||||
screenTextBuffer=gpu:newBuffer(screenSizeX,screenSizeY)
|
|
||||||
for t,v in components:list() do
|
|
||||||
if t == "screen" then
|
|
||||||
gpu:assignBuffer(screenTextBuffer, v)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
term.setBackgroundColor(0x1)
|
|
||||||
term.setTextColor(0x4)
|
|
||||||
term.clear()
|
|
||||||
term.setCursorPos(1, 1)
|
|
||||||
term.write("A critical error occurred while loading the system:")
|
|
||||||
term.setCursorPos(1, 3)
|
|
||||||
write(err)
|
|
||||||
while true do end
|
|
||||||
end
|
|
||||||
|
|
||||||
local ok, err = xpcall(function()
|
|
||||||
local apis = {}
|
|
||||||
|
|
||||||
local lua = {
|
|
||||||
coroutine = true,
|
|
||||||
debug = true,
|
|
||||||
_VERSION = true,
|
|
||||||
assert = true,
|
|
||||||
collectgarbage = true,
|
|
||||||
error = true,
|
|
||||||
gcinfo = true,
|
|
||||||
getmetatable = true,
|
|
||||||
ipairs = true,
|
|
||||||
__inext = true,
|
|
||||||
load = true,
|
|
||||||
math = true,
|
|
||||||
next = true,
|
|
||||||
pairs = true,
|
|
||||||
pcall = true,
|
|
||||||
rawequal = true,
|
|
||||||
rawget = true,
|
|
||||||
rawlen = true,
|
|
||||||
rawset = true,
|
|
||||||
select = true,
|
|
||||||
setmetatable = true,
|
|
||||||
string = true,
|
|
||||||
table = true,
|
|
||||||
tonumber = true,
|
|
||||||
tostring = true,
|
|
||||||
type = true,
|
|
||||||
xpcall = true,
|
|
||||||
_G = true
|
|
||||||
}
|
|
||||||
|
|
||||||
local debug = debug
|
|
||||||
for i, v in pairs(_G) do
|
|
||||||
if not lua[i] or lua[i] == nil then
|
|
||||||
apis[i] = v
|
|
||||||
_G[i] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function string_file(file)
|
|
||||||
local str = file:read()
|
|
||||||
local buf = {str or ""}
|
|
||||||
local pos = 1
|
|
||||||
local closed = false
|
|
||||||
|
|
||||||
local function content()
|
|
||||||
return table.concat(buf)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function set_content(s)
|
|
||||||
buf = {s}
|
|
||||||
end
|
|
||||||
|
|
||||||
local function flush()
|
|
||||||
file.write(content())
|
|
||||||
end
|
|
||||||
|
|
||||||
local file = {}
|
|
||||||
|
|
||||||
function file:read(n)
|
|
||||||
assert(not closed, "file is closed")
|
|
||||||
|
|
||||||
local s = content()
|
|
||||||
local len = #s
|
|
||||||
|
|
||||||
if not n then
|
|
||||||
local out = s:sub(pos)
|
|
||||||
pos = len + 1
|
|
||||||
return out
|
|
||||||
end
|
|
||||||
|
|
||||||
local out = s:sub(pos, pos + n - 1)
|
|
||||||
pos = pos + #out
|
|
||||||
return out
|
|
||||||
end
|
|
||||||
|
|
||||||
function file:write(data)
|
|
||||||
assert(not closed, "file is closed")
|
|
||||||
|
|
||||||
local s = content()
|
|
||||||
local before = s:sub(1, pos - 1)
|
|
||||||
local after = s:sub(pos + #data)
|
|
||||||
|
|
||||||
set_content(before .. data .. after)
|
|
||||||
pos = pos + #data
|
|
||||||
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
function file:seek(whence, offset)
|
|
||||||
assert(not closed, "file is closed")
|
|
||||||
|
|
||||||
local s = content()
|
|
||||||
local len = #s
|
|
||||||
|
|
||||||
whence = whence or "cur"
|
|
||||||
offset = offset or 0
|
|
||||||
|
|
||||||
if whence == "set" then
|
|
||||||
pos = offset + 1
|
|
||||||
elseif whence == "cur" then
|
|
||||||
pos = pos + offset
|
|
||||||
elseif whence == "end" then
|
|
||||||
pos = len + offset + 1
|
|
||||||
else
|
|
||||||
error("invalid whence")
|
|
||||||
end
|
|
||||||
|
|
||||||
if pos < 1 then pos = 1 end
|
|
||||||
if pos > len + 1 then pos = len + 1 end
|
|
||||||
|
|
||||||
return pos - 1
|
|
||||||
end
|
|
||||||
|
|
||||||
function file:close()
|
|
||||||
assert(not closed, "file is closed")
|
|
||||||
flush()
|
|
||||||
closed = true
|
|
||||||
end
|
|
||||||
|
|
||||||
function file:flush()
|
|
||||||
assert(not closed, "file is closed")
|
|
||||||
flush()
|
|
||||||
end
|
|
||||||
|
|
||||||
return file
|
|
||||||
end
|
|
||||||
|
|
||||||
local function getFile(path)
|
|
||||||
local file = bootdrive:open(path, "r")
|
|
||||||
if not file then
|
|
||||||
displaySuperBadError("Could not open file: " .. path)
|
|
||||||
end
|
|
||||||
local content = file:read()
|
|
||||||
return content
|
|
||||||
end
|
|
||||||
|
|
||||||
local Kernel = load(getFile("/boot/kernel.lua"),"@Kernel")
|
|
||||||
local initFs = load(getFile("/boot/ac/initdisks"),"@Init_disks")(apis)
|
|
||||||
local fs = load(getFile("/boot/initfs"), "@InitFs")()
|
|
||||||
|
|
||||||
if not Kernel then displaySuperBadError("Could not load kernel.") end
|
|
||||||
if not initFs then displaySuperBadError("Could not load initdisks.") end
|
|
||||||
if not fs then displaySuperBadError("Could not load initfs.") end
|
|
||||||
|
|
||||||
local computercomp=apis.components:getFirst("computer")
|
|
||||||
local uefi=apis.components:getFirst("uefi")
|
|
||||||
local computer = {
|
|
||||||
time = function() return apis.os.epoch("utc") end,
|
|
||||||
clock = function() return apis.os.clock() * 1000 end,
|
|
||||||
shutdown = apis.os.shutdown,
|
|
||||||
reboot = apis.os.reboot,
|
|
||||||
getMachineEvent = function()
|
|
||||||
return computercomp:getMachineEvent()
|
|
||||||
end,
|
|
||||||
getEEPROM = function() return uefi.data end,
|
|
||||||
setEEPROM = function(_, text)
|
|
||||||
uefi.data=text
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
local icolors = {
|
|
||||||
[0x1] = 1, -- #000000
|
|
||||||
[0x2] = 2, -- #FFFFFF
|
|
||||||
[0x4] = 3, -- #FF0000
|
|
||||||
[0x8] = 4, -- #00FF00
|
|
||||||
[0x10] = 5, -- #0000FF
|
|
||||||
[0x20] = 6, -- #00FFFF
|
|
||||||
[0x40] = 7, -- #FF00FF
|
|
||||||
[0x80] = 8, -- #FFFF00
|
|
||||||
[0x100] = 9, -- #FF6D00
|
|
||||||
[0x200] = 10, -- #6DFF55
|
|
||||||
[0x400] = 11, -- #24FFFF
|
|
||||||
[0x800] = 12, -- #924900
|
|
||||||
[0x1000] = 13, -- #6D6D55
|
|
||||||
[0x2000] = 14, -- #DBDBAA
|
|
||||||
[0x4000] = 15, -- #6D00FF
|
|
||||||
[0x8000] = 16 -- #B6FF00
|
|
||||||
}
|
|
||||||
|
|
||||||
local colors = {
|
|
||||||
0x0001, -- #000000
|
|
||||||
0x0002, -- #FFFFFF
|
|
||||||
0x0004, -- #FF0000
|
|
||||||
0x0008, -- #00FF00
|
|
||||||
0x0010, -- #0000FF
|
|
||||||
0x0020, -- #00FFFF
|
|
||||||
0x0040, -- #FF00FF
|
|
||||||
0x0080, -- #FFFF00
|
|
||||||
0x0100, -- #FF6D00
|
|
||||||
0x0200, -- #6DFF55
|
|
||||||
0x0400, -- #24FFFF
|
|
||||||
0x0800, -- #924900
|
|
||||||
0x1000, -- #6D6D55
|
|
||||||
0x2000, -- #DBDBAA
|
|
||||||
0x4000, -- #6D00FF
|
|
||||||
0x8000 -- #B6FF00
|
|
||||||
}
|
|
||||||
|
|
||||||
apis.term.setBackgroundColor(0x8000)
|
|
||||||
apis.term.setTextColor(0x1000)
|
|
||||||
apis.term.clear()
|
|
||||||
apis.term.setCursorPos(1, 1)
|
|
||||||
|
|
||||||
local kernelCoro = coroutine.create(function()
|
|
||||||
---@diagnostic disable-next-line: param-type-mismatch
|
|
||||||
local ok, err = xpcall(Kernel, debug.traceback, apis, initFs, "cct", "/sbin/init",
|
|
||||||
{
|
|
||||||
print = function(_, text) write(text .. "\n") end,
|
|
||||||
printInline = function(_, text) write(text) end,
|
|
||||||
clear = function()
|
|
||||||
apis.term.clear()
|
|
||||||
apis.term.setCursorPos(1, 1)
|
|
||||||
end,
|
|
||||||
setCursorPos = function(_, x, y)
|
|
||||||
apis.term.setCursorPos(x, y)
|
|
||||||
end,
|
|
||||||
getCursorPos = function() return apis.term.getCursorPos() end,
|
|
||||||
getSize = function() return apis.term.getSize() end,
|
|
||||||
setBackgroundColor = function(_, color)
|
|
||||||
apis.term.setBackgroundColor(colors[color])
|
|
||||||
end,
|
|
||||||
setTextColor = function(_, color)
|
|
||||||
apis.term.setTextColor(colors[color])
|
|
||||||
end,
|
|
||||||
getBackgroundColor = function()
|
|
||||||
return icolors[apis.term.getBackgroundColor()]
|
|
||||||
end,
|
|
||||||
getTextColor = function()
|
|
||||||
return icolors[apis.term.getTextColor()]
|
|
||||||
end
|
|
||||||
}, computer, fs, "$")
|
|
||||||
if not ok then displaySuperBadError(err) end
|
|
||||||
end)
|
|
||||||
|
|
||||||
function coroutine.resumeWithTimeout(co, timeout, ...)
|
|
||||||
local startTime = computer.time()
|
|
||||||
debug.sethook(co, function()
|
|
||||||
if computer.time() > startTime + timeout then
|
|
||||||
return coroutine.yield("timeout")
|
|
||||||
end
|
|
||||||
end, "", 1000)
|
|
||||||
local ret = {coroutine.resume(co, ...)}
|
|
||||||
if ret[1] and ret[2] == "timeout" then
|
|
||||||
return "timeout"
|
|
||||||
elseif ret[1] == false then
|
|
||||||
return "error", ret[2]
|
|
||||||
else
|
|
||||||
debug.sethook(co)
|
|
||||||
return "success", table.unpack(ret, 2)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
write("Loaded in " .. tostring(apis.os.clock()) .. " seconds.\n")
|
|
||||||
|
|
||||||
while true do
|
|
||||||
local status, err = coroutine.resumeWithTimeout(kernelCoro, 50)
|
|
||||||
apis.os.queueEvent("NoSleep")
|
|
||||||
local exit = false
|
|
||||||
while not exit do
|
|
||||||
local event = {coroutine.yield()}
|
|
||||||
if event[1] == "key" then
|
|
||||||
queueEvent("keyPressed", 1, event[2])
|
|
||||||
if acekeys[event[2]] then
|
|
||||||
queueEvent("keyTyped", 1, acekeys[event[2]])
|
|
||||||
end
|
|
||||||
elseif event[1] == "char" then
|
|
||||||
queueEvent("keyTyped", 1, event[2])
|
|
||||||
elseif event[1] == "key_up" then
|
|
||||||
queueEvent("keyReleased", 1, event[2])
|
|
||||||
elseif event[1] == "disk" then
|
|
||||||
queueEvent("componentAdded", "disk")
|
|
||||||
elseif event[1] == "disk_eject" then
|
|
||||||
queueEvent("componentRemoved", "disk")
|
|
||||||
elseif event[1] == "modem_message" then
|
|
||||||
queueEvent("modem_message", table.unpack(event, 2))
|
|
||||||
elseif event[1] == "rednet_message" then
|
|
||||||
queueEvent("rednet_message", table.unpack(event, 2))
|
|
||||||
elseif event[1] == "http_success" then
|
|
||||||
queueEvent("http_success", table.unpack(event, 2))
|
|
||||||
elseif event[1] == "http_failure" then
|
|
||||||
queueEvent("http_failure", table.unpack(event, 2))
|
|
||||||
elseif event[1] == "NoSleep" then
|
|
||||||
exit = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if status == "error" or coroutine.status(kernelCoro) == "dead" then
|
|
||||||
displaySuperBadError("Kernel error: " .. tostring(err))
|
|
||||||
coroutine.yield("key")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end, debug.traceback)
|
|
||||||
|
|
||||||
if not ok then displaySuperBadError("Fatal error during boot: " .. err) end
|
|
||||||
while true do coroutine.yield() end
|
|
||||||
@@ -1,272 +0,0 @@
|
|||||||
--:Minify:--
|
|
||||||
local apis = ({...})[1]
|
|
||||||
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.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 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
|
|
||||||
})
|
|
||||||
|
|
||||||
internal["rom"] = createDisk("rom", "/rom", true, {
|
|
||||||
setLabel = function(label)
|
|
||||||
error("Device is read-only")
|
|
||||||
end,
|
|
||||||
getLabel = function()
|
|
||||||
return "cctrom"
|
|
||||||
end
|
|
||||||
})
|
|
||||||
|
|
||||||
local function refresh()
|
|
||||||
disks={}
|
|
||||||
for _, disk in ipairs({peripheral.find("drive")}) do
|
|
||||||
if disk.isDiskPresent() then
|
|
||||||
disks[tostring(disk.getDiskID())]=createDisk("cctdisk"..tostring(disk.getDiskID()), disk.getMountPath(), false, fs)
|
|
||||||
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}
|
|
||||||
@@ -71,6 +71,7 @@ local ok, err = xpcall(function()
|
|||||||
collectgarbage = true,
|
collectgarbage = true,
|
||||||
error = true,
|
error = true,
|
||||||
gcinfo = true,
|
gcinfo = true,
|
||||||
|
getfenv = true,
|
||||||
getmetatable = true,
|
getmetatable = true,
|
||||||
ipairs = true,
|
ipairs = true,
|
||||||
__inext = true,
|
__inext = true,
|
||||||
@@ -84,6 +85,7 @@ local ok, err = xpcall(function()
|
|||||||
rawlen = true,
|
rawlen = true,
|
||||||
rawset = true,
|
rawset = true,
|
||||||
select = true,
|
select = true,
|
||||||
|
setfenv = true,
|
||||||
setmetatable = true,
|
setmetatable = true,
|
||||||
string = true,
|
string = true,
|
||||||
table = true,
|
table = true,
|
||||||
@@ -152,106 +154,17 @@ local ok, err = xpcall(function()
|
|||||||
if not initFs then displaySuperBadError("Could not load initdisks.") end
|
if not initFs then displaySuperBadError("Could not load initdisks.") end
|
||||||
if not fs then displaySuperBadError("Could not load initfs.") 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 eventQueue = {}
|
||||||
|
|
||||||
local function queueEvent(event, ...)
|
local function queueEvent(event, ...)
|
||||||
table.insert(eventQueue, {event, ...})
|
table.insert(eventQueue, {event, ...})
|
||||||
end
|
end
|
||||||
|
|
||||||
local colors = {
|
local computer = {
|
||||||
[0x000000]=0x0001,
|
time = function() return apis.os.epoch("utc") end,
|
||||||
[0xFFFFFF]=0x0002,
|
clock = function() return apis.os.clock() * 1000 end,
|
||||||
[0xFF0000]=0x0004,
|
shutdown = apis.os.shutdown,
|
||||||
[0x00FF00]=0x0008,
|
reboot = apis.os.reboot,
|
||||||
[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()
|
getMachineEvent = function()
|
||||||
if #eventQueue > 0 then
|
if #eventQueue > 0 then
|
||||||
return table.unpack(table.remove(eventQueue, 1))
|
return table.unpack(table.remove(eventQueue, 1))
|
||||||
@@ -259,15 +172,61 @@ local ok, err = xpcall(function()
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
getEEPROM = function() return getFile(eeprom) end,
|
getEEPROM = function() return getFile("/startup.lua") end,
|
||||||
setEEPROM = function(_, text)
|
setEEPROM = function(_, text)
|
||||||
local h = apis.fs.open(eeprom, "w")
|
local h = apis.fs.open("/startup.lua", "w")
|
||||||
h.write(text)
|
h.write(text)
|
||||||
h.close()
|
h.close()
|
||||||
end,
|
end
|
||||||
initfs=fs,
|
}
|
||||||
disks=initFs,
|
|
||||||
screenCtl={
|
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,
|
print = function(_, text) write(text .. "\n") end,
|
||||||
printInline = function(_, text) write(text) end,
|
printInline = function(_, text) write(text) end,
|
||||||
clear = function()
|
clear = function()
|
||||||
@@ -280,51 +239,25 @@ local ok, err = xpcall(function()
|
|||||||
getCursorPos = function() return apis.term.getCursorPos() end,
|
getCursorPos = function() return apis.term.getCursorPos() end,
|
||||||
getSize = function() return apis.term.getSize() end,
|
getSize = function() return apis.term.getSize() end,
|
||||||
setBackgroundColor = function(_, color)
|
setBackgroundColor = function(_, color)
|
||||||
apis.term.setBackgroundColor(aprox(color))
|
apis.term.setBackgroundColor(colors[color])
|
||||||
end,
|
end,
|
||||||
setTextColor = function(_, color)
|
setTextColor = function(_, color)
|
||||||
apis.term.setTextColor(aprox(color))
|
apis.term.setTextColor(colors[color])
|
||||||
end,
|
end,
|
||||||
getBackgroundColor = function()
|
getBackgroundColor = function()
|
||||||
return bg
|
return icolors[apis.term.getBackgroundColor()]
|
||||||
end,
|
end,
|
||||||
getTextColor = function()
|
getTextColor = function()
|
||||||
return fg
|
return icolors[apis.term.getTextColor()]
|
||||||
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
|
||||||
|
}, computer, fs, "$")
|
||||||
|
if not ok then displaySuperBadError(err) end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
function coroutine.resumeWithTimeout(co, timeout, ...)
|
function coroutine.resumeWithTimeout(co, timeout, ...)
|
||||||
local startTime = EFI.getEpochMs()
|
local startTime = computer.time()
|
||||||
debug.sethook(co, function()
|
debug.sethook(co, function()
|
||||||
if EFI.getEpochMs() > startTime + timeout then
|
if computer.time() > startTime + timeout then
|
||||||
return coroutine.yield("timeout")
|
return coroutine.yield("timeout")
|
||||||
end
|
end
|
||||||
end, "", 1000)
|
end, "", 1000)
|
||||||
@@ -373,15 +306,11 @@ local ok, err = xpcall(function()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
if status == "error" or coroutine.status(kernelCoro) == "dead" then
|
if status == "error" or coroutine.status(kernelCoro) == "dead" then
|
||||||
if EFI.reboot then
|
|
||||||
apis.os.reboot()
|
|
||||||
end
|
|
||||||
displaySuperBadError("Kernel error: " .. tostring(err))
|
displaySuperBadError("Kernel error: " .. tostring(err))
|
||||||
coroutine.yield("key")
|
coroutine.yield("key")
|
||||||
end
|
end
|
||||||
initFs:refresh()
|
|
||||||
end
|
end
|
||||||
end, debug.traceback)
|
end, debug.traceback)
|
||||||
|
|
||||||
if not ok then displaySuperBadError("Fatal error during boot: " .. err) end
|
if not ok then displaySuperBadError("Fatal error during boot: " .. err) end
|
||||||
while true do coroutine.yield("key") end
|
while true do coroutine.yield() 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}
|
||||||
@@ -311,7 +311,7 @@ local fifo = kernel.newFifo()
|
|||||||
kernel.processes.cctmond = function()
|
kernel.processes.cctmond = function()
|
||||||
local timeout = false
|
local timeout = false
|
||||||
while true do
|
while true do
|
||||||
local event = {kernel.EFI:getMachineEvent()}
|
local event = {kernel.computer:getMachineEvent()}
|
||||||
|
|
||||||
if event[1] then
|
if event[1] then
|
||||||
local eventType = event[1]
|
local eventType = event[1]
|
||||||
|
|||||||
@@ -152,106 +152,17 @@ local ok, err = xpcall(function()
|
|||||||
if not initFs then displaySuperBadError("Could not load initdisks.") end
|
if not initFs then displaySuperBadError("Could not load initdisks.") end
|
||||||
if not fs then displaySuperBadError("Could not load initfs.") 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 eventQueue = {}
|
||||||
|
|
||||||
local function queueEvent(event, ...)
|
local function queueEvent(event, ...)
|
||||||
table.insert(eventQueue, {event, ...})
|
table.insert(eventQueue, {event, ...})
|
||||||
end
|
end
|
||||||
|
|
||||||
local colors = {
|
local computer = {
|
||||||
[0x000000]=0x0001,
|
time = function() return apis.os.epoch("utc") end,
|
||||||
[0xFFFFFF]=0x0002,
|
clock = function() return apis.os.clock() * 1000 end,
|
||||||
[0xFF0000]=0x0004,
|
shutdown = apis.os.shutdown,
|
||||||
[0x00FF00]=0x0008,
|
reboot = apis.os.reboot,
|
||||||
[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()
|
getMachineEvent = function()
|
||||||
if #eventQueue > 0 then
|
if #eventQueue > 0 then
|
||||||
return table.unpack(table.remove(eventQueue, 1))
|
return table.unpack(table.remove(eventQueue, 1))
|
||||||
@@ -259,15 +170,61 @@ local ok, err = xpcall(function()
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
getEEPROM = function() return getFile(eeprom) end,
|
getEEPROM = function() return getFile("/startup.lua") end,
|
||||||
setEEPROM = function(_, text)
|
setEEPROM = function(_, text)
|
||||||
local h = apis.fs.open(eeprom, "w")
|
local h = apis.fs.open("/startup.lua", "w")
|
||||||
h.write(text)
|
h.write(text)
|
||||||
h.close()
|
h.close()
|
||||||
end,
|
end
|
||||||
initfs=fs,
|
}
|
||||||
disks=initFs,
|
|
||||||
screenCtl={
|
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,
|
print = function(_, text) write(text .. "\n") end,
|
||||||
printInline = function(_, text) write(text) end,
|
printInline = function(_, text) write(text) end,
|
||||||
clear = function()
|
clear = function()
|
||||||
@@ -280,51 +237,25 @@ local ok, err = xpcall(function()
|
|||||||
getCursorPos = function() return apis.term.getCursorPos() end,
|
getCursorPos = function() return apis.term.getCursorPos() end,
|
||||||
getSize = function() return apis.term.getSize() end,
|
getSize = function() return apis.term.getSize() end,
|
||||||
setBackgroundColor = function(_, color)
|
setBackgroundColor = function(_, color)
|
||||||
apis.term.setBackgroundColor(aprox(color))
|
apis.term.setBackgroundColor(colors[color])
|
||||||
end,
|
end,
|
||||||
setTextColor = function(_, color)
|
setTextColor = function(_, color)
|
||||||
apis.term.setTextColor(aprox(color))
|
apis.term.setTextColor(colors[color])
|
||||||
end,
|
end,
|
||||||
getBackgroundColor = function()
|
getBackgroundColor = function()
|
||||||
return bg
|
return icolors[apis.term.getBackgroundColor()]
|
||||||
end,
|
end,
|
||||||
getTextColor = function()
|
getTextColor = function()
|
||||||
return fg
|
return icolors[apis.term.getTextColor()]
|
||||||
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
|
||||||
|
}, computer, fs, "$")
|
||||||
|
if not ok then displaySuperBadError(err) end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
function coroutine.resumeWithTimeout(co, timeout, ...)
|
function coroutine.resumeWithTimeout(co, timeout, ...)
|
||||||
local startTime = EFI.getEpochMs()
|
local startTime = computer.time()
|
||||||
debug.sethook(co, function()
|
debug.sethook(co, function()
|
||||||
if EFI.getEpochMs() > startTime + timeout then
|
if computer.time() > startTime + timeout then
|
||||||
return coroutine.yield("timeout")
|
return coroutine.yield("timeout")
|
||||||
end
|
end
|
||||||
end, "", 1000)
|
end, "", 1000)
|
||||||
@@ -373,15 +304,11 @@ local ok, err = xpcall(function()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
if status == "error" or coroutine.status(kernelCoro) == "dead" then
|
if status == "error" or coroutine.status(kernelCoro) == "dead" then
|
||||||
if EFI.reboot then
|
|
||||||
apis.os.reboot()
|
|
||||||
end
|
|
||||||
displaySuperBadError("Kernel error: " .. tostring(err))
|
displaySuperBadError("Kernel error: " .. tostring(err))
|
||||||
coroutine.yield("key")
|
coroutine.yield("key")
|
||||||
end
|
end
|
||||||
initFs:refresh()
|
|
||||||
end
|
end
|
||||||
end, debug.traceback)
|
end, debug.traceback)
|
||||||
|
|
||||||
if not ok then displaySuperBadError("Fatal error during boot: " .. err) end
|
if not ok then displaySuperBadError("Fatal error during boot: " .. err) end
|
||||||
while true do coroutine.yield("key") end
|
while true do coroutine.yield() end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
-- :Minify:--
|
-- :Minify:--
|
||||||
local apis = ({...})[1]
|
local apis = ({...})[1]
|
||||||
local BOOT_DRIVE_PATH = apis.BOOT_DRIVE_PATH
|
local BOOT_DRIVE_PATH = apis.BOOT_DRIVE_PATH or "/$"
|
||||||
local fs = apis.fs
|
local fs = apis.fs
|
||||||
local native = apis.peripheral
|
local native = apis.peripheral
|
||||||
local peripheral = {}
|
local peripheral = {}
|
||||||
@@ -241,17 +241,11 @@ internal["$"] = createDisk("$", BOOT_DRIVE_PATH, false, {
|
|||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
internal["rom"] = createDisk("rom", "/rom", true, {
|
|
||||||
setLabel = function(label)
|
|
||||||
error("Device is read-only")
|
|
||||||
end,
|
|
||||||
getLabel = function()
|
|
||||||
return "cctrom"
|
|
||||||
end
|
|
||||||
})
|
|
||||||
|
|
||||||
local function refresh()
|
local function refresh()
|
||||||
disks={}
|
for id, _ in pairs(disks) do
|
||||||
|
if not peripheral.getType(id) then disks[id] = nil end
|
||||||
|
end
|
||||||
|
|
||||||
for _, disk in ipairs({peripheral.find("drive")}) do
|
for _, disk in ipairs({peripheral.find("drive")}) do
|
||||||
if disk.isDiskPresent() then
|
if disk.isDiskPresent() then
|
||||||
disks[tostring(disk.getDiskID())]=createDisk("cctdisk"..tostring(disk.getDiskID()), disk.getMountPath(), false, fs)
|
disks[tostring(disk.getDiskID())]=createDisk("cctdisk"..tostring(disk.getDiskID()), disk.getMountPath(), false, fs)
|
||||||
|
|||||||
@@ -1,152 +0,0 @@
|
|||||||
--:Minify:--
|
|
||||||
-- CCT driver peripheral helper
|
|
||||||
local kernel=...
|
|
||||||
kernel.cct={}
|
|
||||||
kernel.cct.peripheral={}
|
|
||||||
local peripheral=kernel.cct.peripheral
|
|
||||||
local apis = kernel.apis
|
|
||||||
local native = apis.peripheral
|
|
||||||
local sides = {"top", "bottom", "left", "right", "front", "back"}
|
|
||||||
|
|
||||||
function peripheral.getNames()
|
|
||||||
local results = {}
|
|
||||||
for n = 1, #sides do
|
|
||||||
local side = sides[n]
|
|
||||||
if native.isPresent(side) then
|
|
||||||
table.insert(results, side)
|
|
||||||
if native.hasType(side, "peripheral_hub") then
|
|
||||||
local remote = native.call(side, "getNamesRemote")
|
|
||||||
for _, name in ipairs(remote) do
|
|
||||||
table.insert(results, name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return results
|
|
||||||
end
|
|
||||||
|
|
||||||
function peripheral.isPresent(name)
|
|
||||||
if native.isPresent(name) then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
for n = 1, #sides do
|
|
||||||
local side = sides[n]
|
|
||||||
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
function peripheral.getType(peripheral)
|
|
||||||
if type(peripheral) == "string" then
|
|
||||||
if native.isPresent(peripheral) then
|
|
||||||
return native.getType(peripheral)
|
|
||||||
end
|
|
||||||
for n = 1, #sides do
|
|
||||||
local side = sides[n]
|
|
||||||
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then
|
|
||||||
return native.call(side, "getTypeRemote", peripheral)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
else
|
|
||||||
local mt = getmetatable(peripheral)
|
|
||||||
if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then
|
|
||||||
error("bad argument #1 (table is not a peripheral)", 2)
|
|
||||||
end
|
|
||||||
return table.unpack(mt.types)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function peripheral.hasType(peripheral, peripheral_type)
|
|
||||||
if type(peripheral) == "string" then
|
|
||||||
if native.isPresent(peripheral) then
|
|
||||||
return native.hasType(peripheral, peripheral_type)
|
|
||||||
end
|
|
||||||
for n = 1, #sides do
|
|
||||||
local side = sides[n]
|
|
||||||
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then
|
|
||||||
return native.call(side, "hasTypeRemote", peripheral, peripheral_type)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
else
|
|
||||||
local mt = getmetatable(peripheral)
|
|
||||||
if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then
|
|
||||||
error("bad argument #1 (table is not a peripheral)", 2)
|
|
||||||
end
|
|
||||||
return mt.types[peripheral_type] ~= nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function peripheral.getMethods(name)
|
|
||||||
if native.isPresent(name) then
|
|
||||||
return native.getMethods(name)
|
|
||||||
end
|
|
||||||
for n = 1, #sides do
|
|
||||||
local side = sides[n]
|
|
||||||
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
|
|
||||||
return native.call(side, "getMethodsRemote", name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function peripheral.getName(peripheral)
|
|
||||||
local mt = getmetatable(peripheral)
|
|
||||||
if not mt or mt.__name ~= "peripheral" or type(mt.name) ~= "string" then
|
|
||||||
error("bad argument #1 (table is not a peripheral)", 2)
|
|
||||||
end
|
|
||||||
return mt.name
|
|
||||||
end
|
|
||||||
|
|
||||||
function peripheral.call(name, method, ...)
|
|
||||||
if native.isPresent(name) then
|
|
||||||
return native.call(name, method, ...)
|
|
||||||
end
|
|
||||||
|
|
||||||
for n = 1, #sides do
|
|
||||||
local side = sides[n]
|
|
||||||
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
|
|
||||||
return native.call(side, "callRemote", name, method, ...)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function peripheral.wrap(name)
|
|
||||||
local methods = peripheral.getMethods(name)
|
|
||||||
if not methods then
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
local types = { peripheral.getType(name) }
|
|
||||||
for i = 1, #types do types[types[i]] = true end
|
|
||||||
local result = setmetatable({}, {
|
|
||||||
__name = "peripheral",
|
|
||||||
name = name,
|
|
||||||
type = types[1],
|
|
||||||
types = types,
|
|
||||||
})
|
|
||||||
for _, method in ipairs(methods) do
|
|
||||||
result[method] = function(...)
|
|
||||||
return peripheral.call(name, method, ...)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
|
|
||||||
function peripheral.find(ty, filter)
|
|
||||||
local results = {}
|
|
||||||
for _, name in ipairs(peripheral.getNames()) do
|
|
||||||
if peripheral.hasType(name, ty) then
|
|
||||||
local wrapped = peripheral.wrap(name)
|
|
||||||
if filter == nil or filter(name, wrapped) then
|
|
||||||
table.insert(results, wrapped)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return table.unpack(results)
|
|
||||||
end
|
|
||||||
@@ -1,104 +1,192 @@
|
|||||||
--:Minify:--
|
--:Minify:--
|
||||||
|
|
||||||
local kernel = ...
|
local kernel = ...
|
||||||
local peripheral=kernel.cct.peripheral
|
local apis = kernel.apis
|
||||||
local keys=kernel.apis.keys
|
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 = {
|
local colors = {
|
||||||
[0xFFFFFF]=0x0001,
|
0x0001, -- #000000
|
||||||
[0xFF0000]=0x0002,
|
0x0002, -- #FFFFFF
|
||||||
[0x00FF00]=0x0004,
|
0x0004, -- #FF0000
|
||||||
[0x0000FF]=0x0008,
|
0x0008, -- #00FF00
|
||||||
[0x00FFFF]=0x0010,
|
0x0010, -- #0000FF
|
||||||
[0xFF00FF]=0x0020,
|
0x0020, -- #00FFFF
|
||||||
[0xFFFF00]=0x0040,
|
0x0040, -- #FF00FF
|
||||||
[0xFF6D00]=0x0080,
|
0x0080, -- #FFFF00
|
||||||
[0x6DFF55]=0x0100,
|
0x0100, -- #FF6D00
|
||||||
[0x24FFFF]=0x0200,
|
0x0200, -- #6DFF55
|
||||||
[0x924900]=0x0400,
|
0x0400, -- #24FFFF
|
||||||
[0x6D6D55]=0x0800,
|
0x0800, -- #924900
|
||||||
[0xDBDBAA]=0x1000,
|
0x1000, -- #6D6D55
|
||||||
[0x6D00FF]=0x2000,
|
0x2000, -- #DBDBAA
|
||||||
[0xB6FF00]=0x4000,
|
0x4000, -- #6D00FF
|
||||||
[0x000000]=0x8000
|
0x8000 -- #B6FF00
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
local function findClosest(tbl, target)
|
|
||||||
local closest = nil
|
|
||||||
local smallestDiff = math.huge
|
|
||||||
|
|
||||||
for k, _ in pairs(tbl) do
|
|
||||||
local diff = math.abs(k - target)
|
|
||||||
if diff < smallestDiff then
|
|
||||||
smallestDiff = diff
|
|
||||||
closest = k
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return closest
|
|
||||||
end
|
|
||||||
|
|
||||||
local function aprox(c24)
|
|
||||||
ops = ops + 1
|
|
||||||
|
|
||||||
if ops % 1024 == 0 then
|
|
||||||
l1d = {}
|
|
||||||
l1f = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
if ops % 8192 == 0 then
|
|
||||||
l2 = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
if l2[c24] ~= nil then
|
|
||||||
return l2[c24]
|
|
||||||
end
|
|
||||||
|
|
||||||
if l1d[c24] ~= nil then
|
|
||||||
l1f[c24] = l1f[c24] + 1
|
|
||||||
|
|
||||||
if l1f[c24] >= 16 then
|
|
||||||
l2[c24] = l1d[c24]
|
|
||||||
l1d[c24] = nil
|
|
||||||
l1f[c24] = nil
|
|
||||||
return l2[c24]
|
|
||||||
end
|
|
||||||
|
|
||||||
return l1d[c24]
|
|
||||||
end
|
|
||||||
|
|
||||||
local closestKey = findClosest(colors, c24)
|
|
||||||
if not closestKey then return nil end
|
|
||||||
|
|
||||||
local value = colors[closestKey]
|
|
||||||
|
|
||||||
l1d[c24] = value
|
|
||||||
l1f[c24] = 1
|
|
||||||
|
|
||||||
return value
|
|
||||||
end
|
|
||||||
|
|
||||||
local function write(text, term)
|
local function write(text, term)
|
||||||
local x, y = term.getCursorPos()
|
local x, y = term.getCursorPos()
|
||||||
local w, h = term.getSize()
|
local w, h = term.getSize()
|
||||||
@@ -174,7 +262,7 @@ local function newtty(obj, id, ev)
|
|||||||
obj.setPaletteColor(0x8000, 0x000000) -- #B6FF00
|
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 "Terminal"
|
return "character device"
|
||||||
elseif op=="open" then
|
elseif op=="open" then
|
||||||
local h = {
|
local h = {
|
||||||
read=function(amount)
|
read=function(amount)
|
||||||
@@ -207,24 +295,19 @@ local function newtty(obj, id, ev)
|
|||||||
return obj.setCursorPos(x,y)
|
return obj.setCursorPos(x,y)
|
||||||
end,
|
end,
|
||||||
sfgc=function(c)
|
sfgc=function(c)
|
||||||
fg=c
|
return obj.setTextColor(colors[c])
|
||||||
return obj.setTextColor(aprox(c))
|
|
||||||
end,
|
end,
|
||||||
sbgc=function(c)
|
sbgc=function(c)
|
||||||
bg=c
|
return obj.setBackgroundColor(colors[c])
|
||||||
return obj.setBackgroundColor(aprox(c))
|
|
||||||
end,
|
end,
|
||||||
gfgc=function()
|
gfgc=function()
|
||||||
return fg
|
return icolors[obj.getTextColor()]
|
||||||
end,
|
end,
|
||||||
gbgc=function()
|
gbgc=function()
|
||||||
return bg
|
return icolors[obj.getBackgroundColor()]
|
||||||
end,
|
end,
|
||||||
gctrl=function()
|
gctrl=function()
|
||||||
return serializeBool(ctrl)..";"..serializeBool(alt)
|
return serializeBool(ctrl)..";"..serializeBool(alt)
|
||||||
end,
|
|
||||||
gplt=function()
|
|
||||||
return plt
|
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
if mode=="rw" then
|
if mode=="rw" then
|
||||||
@@ -245,28 +328,28 @@ local fifo = kernel.newFifo()
|
|||||||
kernel.processes.cctmond = function()
|
kernel.processes.cctmond = function()
|
||||||
local timeout = false
|
local timeout = false
|
||||||
while true do
|
while true do
|
||||||
local event = {kernel.EFI:getMachineEvent()}
|
local event = {kernel.computer:getMachineEvent()}
|
||||||
|
|
||||||
if event[1] then
|
if event[1] then
|
||||||
local eventType = event[1]
|
local eventType = event[1]
|
||||||
local charOrKey = event[3]
|
local charOrKey = event[3]
|
||||||
|
|
||||||
local ctrlKeyMap = {
|
local ctrlKeyMap = {
|
||||||
[keys.a]=1, [keys.b]=2, [keys.c]=3,
|
[apis.keys.a]=1, [apis.keys.b]=2, [apis.keys.c]=3,
|
||||||
[keys.d]=4, [keys.e]=5, [keys.f]=6,
|
[apis.keys.d]=4, [apis.keys.e]=5, [apis.keys.f]=6,
|
||||||
[keys.g]=7, [keys.h]=8, [keys.i]=9,
|
[apis.keys.g]=7, [apis.keys.h]=8, [apis.keys.i]=9,
|
||||||
[keys.j]=10, [keys.k]=11, [keys.l]=12,
|
[apis.keys.j]=10, [apis.keys.k]=11, [apis.keys.l]=12,
|
||||||
[keys.m]=13, [keys.n]=14, [keys.o]=15,
|
[apis.keys.m]=13, [apis.keys.n]=14, [apis.keys.o]=15,
|
||||||
[keys.p]=16, [keys.q]=17, [keys.r]=18,
|
[apis.keys.p]=16, [apis.keys.q]=17, [apis.keys.r]=18,
|
||||||
[keys.s]=19, [keys.t]=20, [keys.u]=21,
|
[apis.keys.s]=19, [apis.keys.t]=20, [apis.keys.u]=21,
|
||||||
[keys.v]=22, [keys.w]=23, [keys.x]=24,
|
[apis.keys.v]=22, [apis.keys.w]=23, [apis.keys.x]=24,
|
||||||
[keys.y]=25, [keys.z]=26,
|
[apis.keys.y]=25, [apis.keys.z]=26,
|
||||||
}
|
}
|
||||||
|
|
||||||
if eventType == "keyPressed" then
|
if eventType == "keyPressed" then
|
||||||
if charOrKey == keys.leftCtrl or charOrKey == keys.rightCtrl then
|
if charOrKey == apis.keys.leftCtrl or charOrKey == apis.keys.rightCtrl then
|
||||||
ctrl = true
|
ctrl = true
|
||||||
elseif charOrKey == keys.leftAlt or charOrKey == keys.rightAlt then
|
elseif charOrKey == apis.keys.leftAlt or charOrKey == apis.keys.rightAlt then
|
||||||
alt = true
|
alt = true
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -283,24 +366,24 @@ kernel.processes.cctmond = function()
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
local specialKeyMap = {
|
local specialKeyMap = {
|
||||||
[keys.up] = "[A",
|
[apis.keys.up] = "[A",
|
||||||
[keys.down] = "[B",
|
[apis.keys.down] = "[B",
|
||||||
[keys.right] = "[C",
|
[apis.keys.right] = "[C",
|
||||||
[keys.left] = "[D",
|
[apis.keys.left] = "[D",
|
||||||
[keys.home] = "[H",
|
[apis.keys.home] = "[H",
|
||||||
[keys["end"]] = "[F",
|
[apis.keys["end"]] = "[F",
|
||||||
[keys.pageUp] = "[5~",
|
[apis.keys.pageUp] = "[5~",
|
||||||
[keys.pageDown] = "[6~",
|
[apis.keys.pageDown] = "[6~",
|
||||||
[keys.delete] = "[3~",
|
[apis.keys.delete] = "[3~",
|
||||||
}
|
}
|
||||||
local special = specialKeyMap[charOrKey]
|
local special = specialKeyMap[charOrKey]
|
||||||
if special then fifo.push(special) end
|
if special then fifo.push(special) end
|
||||||
end
|
end
|
||||||
|
|
||||||
elseif eventType == "keyReleased" then
|
elseif eventType == "keyReleased" then
|
||||||
if charOrKey == keys.leftCtrl or charOrKey == keys.rightCtrl then
|
if charOrKey == apis.keys.leftCtrl or charOrKey == apis.keys.rightCtrl then
|
||||||
ctrl = false
|
ctrl = false
|
||||||
elseif charOrKey == keys.leftAlt or charOrKey == keys.rightAlt then
|
elseif charOrKey == apis.keys.leftAlt or charOrKey == apis.keys.rightAlt then
|
||||||
alt = false
|
alt = false
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -319,7 +402,7 @@ kernel.processes.cctmond = function()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
newtty(kernel.apis.term, "1", fifo.pop)
|
newtty(apis.term, "1", fifo.pop)
|
||||||
|
|
||||||
for i,v in ipairs({peripheral.find("monitor")}) do
|
for i,v in ipairs({peripheral.find("monitor")}) do
|
||||||
v.setTextScale(.5)
|
v.setTextScale(.5)
|
||||||
|
|||||||
@@ -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)
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
--:Minify:--
|
|
||||||
local kernel=...
|
|
||||||
local rs=kernel.apis.rs
|
|
||||||
local sides = {top=1, bottom=2, left=3, right=4, front=5, back=6}
|
|
||||||
local function newGPIO(side)
|
|
||||||
return function(mode, data)
|
|
||||||
if mode=="w" then
|
|
||||||
if type(data)~="boolean" then error("data: expected bool") end
|
|
||||||
rs.setOutput(side, data)
|
|
||||||
elseif mode=="wa" then
|
|
||||||
if type(data)~="number" then error("data: expected bool") end
|
|
||||||
rs.setAnalogOutput(side, data)
|
|
||||||
elseif mode=="r" then
|
|
||||||
return rs.getInput(side)
|
|
||||||
elseif mode=="ra" then
|
|
||||||
return rs.getAnalogInput(side)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
for side, alt in pairs(sides) do
|
|
||||||
local func=newGPIO(side)
|
|
||||||
kernel.gpio[side]=func
|
|
||||||
kernel.gpio[alt]=func
|
|
||||||
end
|
|
||||||
@@ -1,12 +1,14 @@
|
|||||||
--:Minify:--
|
--:Minify:--
|
||||||
local EFI=...
|
local args = {...}
|
||||||
local screen=EFI.screenCtl
|
local apis = args[1]
|
||||||
local ifs=EFI.initfs
|
local disks = args[2]
|
||||||
local disks=EFI.disks
|
local arch = args[3]
|
||||||
local arch=EFI.architecture
|
local screen = args[5]
|
||||||
|
local computer = args[6]
|
||||||
|
local ifs = args[7]
|
||||||
local kernel = {}
|
local kernel = {}
|
||||||
kernel.LOG_Text=""
|
kernel.LOG_Text=""
|
||||||
kernel.version="HyperionOS V1.2.4"
|
kernel.version="HyperionOS V1.2.3"
|
||||||
kernel.process = "Kernel"
|
kernel.process = "Kernel"
|
||||||
kernel.users={[0]="root",[1]="User"}
|
kernel.users={[0]="root",[1]="User"}
|
||||||
kernel.hostname = "hyperion"
|
kernel.hostname = "hyperion"
|
||||||
@@ -24,31 +26,28 @@ _G.sleep=nil
|
|||||||
local windowsExp = false
|
local windowsExp = false
|
||||||
|
|
||||||
function kernel.log(msg, level, c)
|
function kernel.log(msg, level, c)
|
||||||
c=c or 0x6D6D6D
|
c=c or 12
|
||||||
kernel.LOG_Text = kernel.LOG_Text..tostring(EFI:date()).." "..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(tostring(EFI:date()).." "..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
|
||||||
local file=kernel.vfs.open("/dev/console", "w")
|
kernel.vfs.devctl(1,"sfgc",c)
|
||||||
kernel.vfs.devctl(file,"sfgc",c)
|
kernel.vfs.write(1,tostring(computer:time()).." "..kernel.users[kernel.uid].." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n")
|
||||||
kernel.vfs.write(file,tostring(EFI:date()).." "..kernel.users[kernel.uid].." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n")
|
|
||||||
kernel.vfs.close(file)
|
|
||||||
kernel.currentTask=kernel.standbyTask
|
kernel.currentTask=kernel.standbyTask
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function kernel.PANIC(msg)
|
function kernel.PANIC(msg)
|
||||||
if kernel.status~="Panic" then
|
if kernel.status~="Panic" then
|
||||||
kernel.log("PANIC: "..msg, "PANIC", 0xFF0000)
|
kernel.log("PANIC: "..msg, "PANIC")
|
||||||
pcall(kernel["saveLog"])
|
pcall(kernel["saveLog"])
|
||||||
kernel.status="Panic"
|
kernel.status="Panic"
|
||||||
kernel.reason=msg
|
kernel.reason=msg
|
||||||
screen:enable()
|
screen:setTextColor(2)
|
||||||
screen:setTextColor(0xFF0000)
|
screen:setBackgroundColor(16)
|
||||||
screen:setBackgroundColor(0x000000)
|
|
||||||
screen:clear()
|
screen:clear()
|
||||||
screen:setCursorPos(1,1)
|
screen:setCursorPos(1,1)
|
||||||
screen:print(kernel.LOG_Text)
|
screen:print(kernel.LOG_Text)
|
||||||
@@ -57,19 +56,18 @@ function kernel.PANIC(msg)
|
|||||||
kernel.exitMain = true
|
kernel.exitMain = true
|
||||||
end
|
end
|
||||||
while true do
|
while true do
|
||||||
local event={EFI:getMachineEvent()}
|
local event={computer:getMachineEvent()}
|
||||||
if event[1]=="keyPressed" then
|
if event[1]=="keyPressed" then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
EFI.reboot=true
|
computer:reboot()
|
||||||
error("KERNEL PANIC")
|
|
||||||
end
|
end
|
||||||
kernel.panic=kernel.PANIC
|
kernel.panic=kernel.PANIC
|
||||||
|
|
||||||
if windowsExp then
|
if windowsExp then
|
||||||
screen:setTextColor(0xFFFFFF)
|
screen:setTextColor(1)
|
||||||
screen:setBackgroundColor(0x0000FF)
|
screen:setBackgroundColor(4)
|
||||||
screen:clear()
|
screen:clear()
|
||||||
local w,h = screen:getSize()
|
local w,h = screen:getSize()
|
||||||
screen:setCursorPos(3,5)
|
screen:setCursorPos(3,5)
|
||||||
@@ -115,7 +113,7 @@ local split = function(str, delim, maxResultCountOrNil)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if not ifs.isFile("/boot/boot.cfg") then
|
if not ifs.isFile("/boot/boot.cfg") then
|
||||||
kernel.log("First boot detected writing boot.cfg", "INFO", 0x00FF00)
|
kernel.log("First boot detected writing boot.cfg", "INFO", 3)
|
||||||
ifs.writeAllText("/boot/boot.cfg",ifs.readAllText("/boot/safeboot.cfg"))
|
ifs.writeAllText("/boot/boot.cfg",ifs.readAllText("/boot/safeboot.cfg"))
|
||||||
kernel.firstBoot=true
|
kernel.firstBoot=true
|
||||||
end
|
end
|
||||||
@@ -138,7 +136,7 @@ for i,v in ipairs(split(fstab,"\n")) do
|
|||||||
local id=""
|
local id=""
|
||||||
for i=3,#v do
|
for i=3,#v do
|
||||||
if v:sub(i,i)==";" then
|
if v:sub(i,i)==";" then
|
||||||
if i==3 then kernel.log("Invalid fstab line... Skipping.","WARN", 0xFF8800) skip = true break end
|
if i==3 then kernel.log("Invalid fstab line... Skipping.","WARN") skip = true break end
|
||||||
id=v:sub(3,i-1)
|
id=v:sub(3,i-1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -153,14 +151,8 @@ end
|
|||||||
kernel.log("Disks initialized")
|
kernel.log("Disks initialized")
|
||||||
|
|
||||||
function kernel.saveLog()
|
function kernel.saveLog()
|
||||||
if kernel.status=="running" then
|
|
||||||
local file = kernel.vfs.open("/var/log/syslog.log", "w")
|
|
||||||
kernel.vfs.write(file, kernel.LOG_Text)
|
|
||||||
kernel.vfs.close(file)
|
|
||||||
else
|
|
||||||
ifs.writeAllText("/var/log/syslog.log", kernel.LOG_Text)
|
ifs.writeAllText("/var/log/syslog.log", kernel.LOG_Text)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.newFifo()
|
function kernel.newFifo()
|
||||||
local fifo = {}
|
local fifo = {}
|
||||||
@@ -199,7 +191,7 @@ kernel.log("Gathering modules")
|
|||||||
for _, i in ipairs(ifs.list("/lib/modules")) do
|
for _, i in ipairs(ifs.list("/lib/modules")) do
|
||||||
local modlist = ifs.list("/lib/modules/"..i)
|
local modlist = ifs.list("/lib/modules/"..i)
|
||||||
if not modlist then
|
if not modlist then
|
||||||
kernel.log("WARNING: could not list /lib/modules/"..i.." (skipping)", "WARN", 0xFF8800)
|
kernel.log("WARNING: could not list /lib/modules/"..i.." (skipping)", "WARN", 8)
|
||||||
else
|
else
|
||||||
for _,v in ipairs(modlist) do
|
for _,v in ipairs(modlist) do
|
||||||
local prior=tonumber(v:sub(1,2))
|
local prior=tonumber(v:sub(1,2))
|
||||||
@@ -211,8 +203,8 @@ for _, i in ipairs(ifs.list("/lib/modules")) do
|
|||||||
end
|
end
|
||||||
|
|
||||||
kernel.ifs=ifs
|
kernel.ifs=ifs
|
||||||
kernel.apis=EFI.firmware
|
kernel.apis=apis
|
||||||
kernel.EFI=EFI
|
kernel.computer=computer
|
||||||
kernel.arch=arch
|
kernel.arch=arch
|
||||||
kernel.initdisks=disks
|
kernel.initdisks=disks
|
||||||
kernel.screen=screen
|
kernel.screen=screen
|
||||||
@@ -241,19 +233,16 @@ kernel.kernelTask = {
|
|||||||
kernel.currentTask = kernel.kernelTask
|
kernel.currentTask = kernel.kernelTask
|
||||||
|
|
||||||
function kernel.shutdown()
|
function kernel.shutdown()
|
||||||
kernel.exitMain=true
|
kernel.computer:shutdown()
|
||||||
kernel.status="shutdown"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function kernel.reboot()
|
function kernel.reboot()
|
||||||
kernel.exitMain=true
|
kernel.computer:reboot()
|
||||||
kernel.status="reboot"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
kernel.syscalls["time"]=function() return kernel.EFI:getEpochMs() end
|
kernel.syscalls["time"]=function() return kernel.computer:time() end
|
||||||
kernel.syscalls["date"]=function() return kernel.EFI:date() end
|
|
||||||
kernel.syscalls["log"]=kernel.log
|
kernel.syscalls["log"]=kernel.log
|
||||||
kernel.syscalls["getUptime"]=function() return kernel.EFI:getUptime() end
|
kernel.syscalls["getUptime"]=function() return kernel.computer:clock() end
|
||||||
kernel.syscalls["getUsername"]=function(uid) return kernel.users[uid or kernel.uid] end
|
kernel.syscalls["getUsername"]=function(uid) return kernel.users[uid or kernel.uid] end
|
||||||
kernel.syscalls["getHostname"]=function() return kernel.hostname end
|
kernel.syscalls["getHostname"]=function() return kernel.hostname end
|
||||||
kernel.syscalls["getHost"]=function() return kernel.apis._HOST end
|
kernel.syscalls["getHost"]=function() return kernel.apis._HOST end
|
||||||
@@ -267,13 +256,17 @@ kernel.syscalls["sysdump"]=function()
|
|||||||
end
|
end
|
||||||
return rv
|
return rv
|
||||||
end
|
end
|
||||||
kernel.syscalls["reboot"]=kernel.reboot
|
kernel.syscalls["reboot"]=function()
|
||||||
kernel.syscalls["shutdown"]=kernel.shutdown
|
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
|
||||||
for _,v in ipairs(p) do
|
for _,v in ipairs(p) do
|
||||||
if kernel.config.showModLoad then kernel.log("Loading module "..v, "DBUG", 0x00FFFF) end
|
if kernel.config.showModLoad then kernel.log("Loading module "..v, "DBUG", 5) end
|
||||||
local code=ifs.readAllText(v)
|
local code=ifs.readAllText(v)
|
||||||
if not code then
|
if not code then
|
||||||
kernel.panic("Failed to read module "..v)
|
kernel.panic("Failed to read module "..v)
|
||||||
@@ -282,19 +275,15 @@ for _,p in ipairs(modules) do
|
|||||||
if not func then kernel.panic("ModuLoadErr: "..tostring(err)) end
|
if not func then kernel.panic("ModuLoadErr: "..tostring(err)) end
|
||||||
local status, err = xpcall(func,debug.traceback, kernel)
|
local status, err = xpcall(func,debug.traceback, kernel)
|
||||||
if not status then kernel.panic("ModuRunErr: "..tostring(err)) end
|
if not status then kernel.panic("ModuRunErr: "..tostring(err)) end
|
||||||
if kernel.config.showModLoad then kernel.log("Loaded module "..v, "DBUG", 0x00FFFF) end
|
if kernel.config.showModLoad then kernel.log("Loaded module "..v, "DBUG", 5) end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
kernel.log("Kernel initialized successfully.")
|
kernel.log("Kernel initialized successfully.")
|
||||||
kernel.saveLog()
|
kernel.saveLog()
|
||||||
kernel.status="running"
|
kernel.status="running"
|
||||||
screen:disable()
|
|
||||||
kernel.main()
|
kernel.main()
|
||||||
if kernel.status=="panic" then
|
if kernel.status=="panic" then
|
||||||
kernel.panic(kernel.reason)
|
kernel.panic()
|
||||||
end
|
|
||||||
if kernel.status=="reboot" then
|
|
||||||
EFI.reboot=true
|
|
||||||
return true
|
|
||||||
end
|
end
|
||||||
|
kernel.PANIC("Execution complete")
|
||||||
@@ -7,6 +7,5 @@ return {
|
|||||||
initPath = "/sbin/init",
|
initPath = "/sbin/init",
|
||||||
maxOpenFiles = 128,
|
maxOpenFiles = 128,
|
||||||
maxFilesPerTask = 16,
|
maxFilesPerTask = 16,
|
||||||
preempt=true,
|
preempt=true
|
||||||
logTaskExit=true
|
|
||||||
}
|
}
|
||||||
@@ -555,9 +555,8 @@ function vfs.mount(target, diskOrId)
|
|||||||
if _euid ~= 0 then error("EPERM") end
|
if _euid ~= 0 then error("EPERM") end
|
||||||
if not target then error("EINVAL") end
|
if not target then error("EINVAL") end
|
||||||
target = normalizeMountPoint(target)
|
target = normalizeMountPoint(target)
|
||||||
local drive, path = resolvePath(target)
|
if not vfs.exists(target) then vfs.mkdir(target) end
|
||||||
if not drive:directoryExists(path) then drive:makeDirectory(path) end
|
if vfs.type(target) ~= "directory" then error("EINVAL") end
|
||||||
if drive:type(target) ~= "directory" then error("EINVAL") end
|
|
||||||
|
|
||||||
local disk, id
|
local disk, id
|
||||||
if type(diskOrId) == "string" then
|
if type(diskOrId) == "string" then
|
||||||
@@ -947,11 +946,7 @@ function vfs.exists(path)
|
|||||||
if meta.etype == 0x01 then return true end
|
if meta.etype == 0x01 then return true end
|
||||||
local ok, disk, diskPath = pcall(resolvePath, path)
|
local ok, disk, diskPath = pcall(resolvePath, path)
|
||||||
if not ok then return false end
|
if not ok then return false end
|
||||||
if disk:type(diskPath) then
|
return disk:fileExists(diskPath)
|
||||||
return true
|
|
||||||
else
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function vfs.type(path)
|
function vfs.type(path)
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ function proxy:type(path, mode)
|
|||||||
if type(step[steps[#steps]]) == "table" then
|
if type(step[steps[#steps]]) == "table" then
|
||||||
return "directory"
|
return "directory"
|
||||||
end
|
end
|
||||||
error(type(step[steps[#steps]]))
|
error("ENOENT")
|
||||||
end
|
end
|
||||||
|
|
||||||
function proxy:list(path)
|
function proxy:list(path)
|
||||||
@@ -140,82 +140,6 @@ function data.zero(op, mode)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
data["disk"]={}
|
data["disk"]={}
|
||||||
kernel.devfs={}
|
kernel.devfs={}
|
||||||
kernel.devfs.data=data
|
kernel.devfs.data=data
|
||||||
|
|||||||
@@ -258,7 +258,7 @@ function proxy:fileExists(path)
|
|||||||
return ok
|
return ok
|
||||||
end
|
end
|
||||||
|
|
||||||
data.uptime=simpleFile(function()return tostring(kernel.EFI:getUptime())end,function()error("EACCES")end)
|
data.uptime=simpleFile(function()return tostring(kernel.computer:getUptime())end,function()error("EACCES")end)
|
||||||
kernel.procfs={}
|
kernel.procfs={}
|
||||||
kernel.procfs.data=data
|
kernel.procfs.data=data
|
||||||
kernel.procfs.proxy=proxy
|
kernel.procfs.proxy=proxy
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ for _, line in ipairs(string.split(kernel.fstab, "\n")) do
|
|||||||
end
|
end
|
||||||
|
|
||||||
if not semicolon_pos or semicolon_pos == 3 then
|
if not semicolon_pos or semicolon_pos == 3 then
|
||||||
kernel.log("Invalid fstab line: "..line.." ... Skipping.", "WARN", 0xFF8800)
|
kernel.log("Invalid fstab line: "..line.." ... Skipping.", "WARN", 8)
|
||||||
else
|
else
|
||||||
local id = line:sub(3, semicolon_pos - 1)
|
local id = line:sub(3, semicolon_pos - 1)
|
||||||
local path = trim(line:sub(semicolon_pos + 1))
|
local path = trim(line:sub(semicolon_pos + 1))
|
||||||
|
|||||||
@@ -2,7 +2,10 @@
|
|||||||
-- Supports:
|
-- Supports:
|
||||||
-- AF_UNIX - local IPC via /var/run/*.sock paths
|
-- AF_UNIX - local IPC via /var/run/*.sock paths
|
||||||
-- AF_INET - network sockets with three backends:
|
-- AF_INET - network sockets with three backends:
|
||||||
-- Implemented by drivers but expect http:// and https://
|
-- rednet://0.0.B.C or rednet+PROTO://0.0.B.C -> CC rednet (computer B*256+C)
|
||||||
|
-- modem://0.0.B.C -> raw CC modem frames
|
||||||
|
-- http://host/path or https://... -> HTTP via CC http API
|
||||||
|
-- A.B.C.D (dotted quad, non-zero A) -> HTTP
|
||||||
--
|
--
|
||||||
-- Socket lifecycle:
|
-- Socket lifecycle:
|
||||||
-- fd = syscall.socket(domain, socktype) -- "unix"/"inet", "stream"/"dgram"
|
-- fd = syscall.socket(domain, socktype) -- "unix"/"inet", "stream"/"dgram"
|
||||||
@@ -16,8 +19,538 @@
|
|||||||
-- -- normal vfs.close(fd) closes the socket
|
-- -- normal vfs.close(fd) closes the socket
|
||||||
|
|
||||||
local kernel = ...
|
local kernel = ...
|
||||||
local socket={}
|
|
||||||
kernel.socket=socket
|
|
||||||
|
|
||||||
|
local sockets = {}
|
||||||
|
local unixSocks = {}
|
||||||
|
local nextSockId = 1
|
||||||
|
|
||||||
|
local function allocSockId()
|
||||||
|
local id = nextSockId
|
||||||
|
nextSockId = nextSockId + 1
|
||||||
|
return id
|
||||||
|
end
|
||||||
|
|
||||||
|
local function parseAddress(addr)
|
||||||
|
if not addr then error("EINVAL") end
|
||||||
|
|
||||||
|
if addr:sub(1,1) == "/" or addr:sub(1,5) == "unix:" then
|
||||||
|
local path = addr:sub(1,5) == "unix:" and addr:sub(6) or addr
|
||||||
|
return { backend="unix", path=path }
|
||||||
|
end
|
||||||
|
|
||||||
|
local rproto, raddr = addr:match("^rednet%+?([^:/]*)://(.+)$")
|
||||||
|
if raddr then
|
||||||
|
local a,b,c,d = raddr:match("^(%d+)%.(%d+)%.(%d+)%.(%d+)$")
|
||||||
|
if not a then error("EINVAL: bad rednet address " .. raddr) end
|
||||||
|
local compId = tonumber(c)*256 + tonumber(d)
|
||||||
|
return { backend="rednet", compId=compId,
|
||||||
|
protocol=(rproto ~= "" and rproto or "hyperion") }
|
||||||
|
end
|
||||||
|
|
||||||
|
local maddr = addr:match("^modem://(.+)$")
|
||||||
|
if maddr then
|
||||||
|
local a,b,c,d = maddr:match("^(%d+)%.(%d+)%.(%d+)%.(%d+)$")
|
||||||
|
if not a then error("EINVAL: bad modem address " .. maddr) end
|
||||||
|
local compId = tonumber(c)*256 + tonumber(d)
|
||||||
|
local port = tonumber(maddr:match(":(%d+)$")) or 0
|
||||||
|
return { backend="modem", compId=compId, port=port }
|
||||||
|
end
|
||||||
|
|
||||||
|
local scheme, rest = addr:match("^(https?)://(.+)$")
|
||||||
|
if scheme then
|
||||||
|
return { backend=scheme, url=addr }
|
||||||
|
end
|
||||||
|
|
||||||
|
local a,b,c,d = addr:match("^(%d+)%.(%d+)%.(%d+)%.(%d+)")
|
||||||
|
if a and tonumber(a) ~= 0 then
|
||||||
|
return { backend="http", url="http://" .. addr }
|
||||||
|
end
|
||||||
|
|
||||||
|
error("EINVAL: unrecognised address format: " .. tostring(addr))
|
||||||
|
end
|
||||||
|
|
||||||
|
local rednetOpen = false
|
||||||
|
local function ensureRednet()
|
||||||
|
if rednetOpen then return end
|
||||||
|
local rn = kernel.apis and kernel.apis.rednet
|
||||||
|
if not rn then error("ENODEV: no rednet API available") end
|
||||||
|
local peripheral = kernel.apis.peripheral
|
||||||
|
if peripheral then
|
||||||
|
for _, name in ipairs(peripheral.getNames and peripheral.getNames() or {}) do
|
||||||
|
if peripheral.getType(name) == "modem" then
|
||||||
|
pcall(rn.open, name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
rednetOpen = true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getModem()
|
||||||
|
local peripheral = kernel.apis and kernel.apis.peripheral
|
||||||
|
if not peripheral then error("ENODEV") end
|
||||||
|
for _, name in ipairs(peripheral.getNames and peripheral.getNames() or {}) do
|
||||||
|
if peripheral.getType(name) == "modem" then
|
||||||
|
local m = peripheral.wrap(name)
|
||||||
|
if m then return m, name end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
error("ENODEV: no modem peripheral found")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function pumpEvents()
|
||||||
|
local ev = kernel.computer:getMachineEvent()
|
||||||
|
while ev do
|
||||||
|
if ev == "rednet_message" then
|
||||||
|
for _, sock in pairs(sockets) do
|
||||||
|
if sock.backend == "rednet" and sock.bound then
|
||||||
|
if sock.address.protocol == tostring(select(4, table.unpack({ev}))) or
|
||||||
|
sock.address.protocol == "hyperion" then
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
ev = kernel.computer:getMachineEvent()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function pollEvent()
|
||||||
|
local results = table.pack(kernel.computer:getMachineEvent())
|
||||||
|
if results.n == 0 or results[1] == nil then return nil end
|
||||||
|
return results
|
||||||
|
end
|
||||||
|
|
||||||
|
local function dispatchEvent(ev)
|
||||||
|
if not ev then return end
|
||||||
|
local evtype = ev[1]
|
||||||
|
|
||||||
|
if evtype == "rednet_message" then
|
||||||
|
local senderId = ev[2]
|
||||||
|
local message = ev[3]
|
||||||
|
local protocol = ev[4] or "hyperion"
|
||||||
|
for _, sock in pairs(sockets) do
|
||||||
|
if sock.backend == "rednet" and (sock.listening or sock.connected) then
|
||||||
|
if sock.address and sock.address.protocol == protocol then
|
||||||
|
table.insert(sock.rxbuf, { from=senderId, data=message })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif evtype == "modem_message" then
|
||||||
|
local channel = ev[3]
|
||||||
|
local msg = ev[5]
|
||||||
|
local fromCh = ev[4]
|
||||||
|
for _, sock in pairs(sockets) do
|
||||||
|
if sock.backend == "modem" and sock.modemChannel == channel then
|
||||||
|
table.insert(sock.rxbuf, { from=fromCh, data=msg })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif evtype == "http_success" then
|
||||||
|
local url = ev[2]
|
||||||
|
local handle = ev[3]
|
||||||
|
for _, sock in pairs(sockets) do
|
||||||
|
if sock.backend == "http" or sock.backend == "https" then
|
||||||
|
if sock.pendingUrl == url then
|
||||||
|
local body = handle.readAll and handle.readAll() or ""
|
||||||
|
handle.close()
|
||||||
|
table.insert(sock.rxbuf, { data=body, done=true })
|
||||||
|
sock.pendingUrl = nil
|
||||||
|
sock.connected = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif evtype == "http_failure" then
|
||||||
|
local url = ev[2]
|
||||||
|
local err = ev[3]
|
||||||
|
for _, sock in pairs(sockets) do
|
||||||
|
if (sock.backend == "http" or sock.backend == "https") and
|
||||||
|
sock.pendingUrl == url then
|
||||||
|
sock.error = err
|
||||||
|
sock.pendingUrl = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function pumpAll()
|
||||||
|
local ev = pollEvent()
|
||||||
|
while ev do
|
||||||
|
dispatchEvent(ev)
|
||||||
|
ev = pollEvent()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function newSocket(domain, socktype)
|
||||||
|
local sock = {
|
||||||
|
id = allocSockId(),
|
||||||
|
domain = domain, -- "unix" | "inet"
|
||||||
|
socktype = socktype, -- "stream" | "dgram"
|
||||||
|
backend = nil,
|
||||||
|
state = "idle", -- idle | bound | listening | connected | closed
|
||||||
|
rxbuf = {},
|
||||||
|
txbuf = {},
|
||||||
|
backlog = {},
|
||||||
|
address = nil,
|
||||||
|
peer = nil,
|
||||||
|
modemChannel = nil,
|
||||||
|
modem = nil,
|
||||||
|
pendingUrl = nil,
|
||||||
|
bound = false,
|
||||||
|
listening = false,
|
||||||
|
connected = false,
|
||||||
|
error = nil,
|
||||||
|
}
|
||||||
|
sockets[sock.id] = sock
|
||||||
|
return sock
|
||||||
|
end
|
||||||
|
|
||||||
|
local sockSend, sockClose
|
||||||
|
|
||||||
|
local function socketToFd(sock)
|
||||||
|
return {
|
||||||
|
isSocket = true,
|
||||||
|
sockId = sock.id,
|
||||||
|
mode = "rw",
|
||||||
|
meta = { etype=0, owner=0, group=0, perms=0x1FF, cmeta="" },
|
||||||
|
type = "socket",
|
||||||
|
refcount = 1,
|
||||||
|
handle = {
|
||||||
|
read = function(count)
|
||||||
|
pumpAll()
|
||||||
|
if #sock.rxbuf == 0 then return "" end
|
||||||
|
local item = table.remove(sock.rxbuf, 1)
|
||||||
|
local data = type(item) == "table" and (item.data or "") or tostring(item)
|
||||||
|
if count and #data > count then
|
||||||
|
table.insert(sock.rxbuf, 1, { data=data:sub(count+1), from=item.from })
|
||||||
|
data = data:sub(1, count)
|
||||||
|
end
|
||||||
|
return data
|
||||||
|
end,
|
||||||
|
write = function(data)
|
||||||
|
if sock.state == "closed" then error("EBADF") end
|
||||||
|
return sockSend(sock, data)
|
||||||
|
end,
|
||||||
|
close = function()
|
||||||
|
sockClose(sock)
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
sockSend = function(sock, data)
|
||||||
|
if sock.backend == "unix" then
|
||||||
|
local peer = sock.peer
|
||||||
|
if not peer then error("ENOTCONN") end
|
||||||
|
table.insert(peer.rxbuf, { data=data })
|
||||||
|
return #data
|
||||||
|
|
||||||
|
elseif sock.backend == "rednet" then
|
||||||
|
ensureRednet()
|
||||||
|
local rn = kernel.apis.rednet
|
||||||
|
rn.send(sock.address.compId, data, sock.address.protocol)
|
||||||
|
return #data
|
||||||
|
|
||||||
|
elseif sock.backend == "modem" then
|
||||||
|
local modem = sock.modem
|
||||||
|
if not modem then error("ENOTCONN") end
|
||||||
|
modem.transmit(sock.address.port, sock.modemChannel or 0, data)
|
||||||
|
return #data
|
||||||
|
|
||||||
|
elseif sock.backend == "http" or sock.backend == "https" then
|
||||||
|
local http = kernel.apis and kernel.apis.http
|
||||||
|
if not http then error("ENODEV: no http API") end
|
||||||
|
local url = sock.address.url
|
||||||
|
local ok, err = pcall(http.request, url, data, {
|
||||||
|
["Content-Type"] = "application/octet-stream"
|
||||||
|
})
|
||||||
|
if not ok then error("ENETDOWN: " .. tostring(err)) end
|
||||||
|
sock.pendingUrl = url
|
||||||
|
return #data
|
||||||
|
end
|
||||||
|
error("EPROTONOSUPPORT")
|
||||||
|
end
|
||||||
|
|
||||||
|
sockClose = function(sock)
|
||||||
|
if sock.state == "closed" then return end
|
||||||
|
sock.state = "closed"
|
||||||
|
|
||||||
|
if sock.backend == "unix" then
|
||||||
|
if sock.peer then
|
||||||
|
sock.peer.peer = nil
|
||||||
|
sock.peer.state = "closed"
|
||||||
|
end
|
||||||
|
if sock.bound and sock.address and sock.address.path then
|
||||||
|
unixSocks[sock.address.path] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif sock.backend == "modem" and sock.modem and sock.modemChannel then
|
||||||
|
pcall(sock.modem.close, sock.modemChannel)
|
||||||
|
|
||||||
|
elseif sock.backend == "rednet" then
|
||||||
|
end
|
||||||
|
|
||||||
|
sockets[sock.id] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
kernel.syscalls["socket"] = function(domain, socktype)
|
||||||
|
domain = domain or "inet"
|
||||||
|
socktype = socktype or "stream"
|
||||||
|
if domain ~= "unix" and domain ~= "inet" then error("EAFNOSUPPORT") end
|
||||||
|
if socktype ~= "stream" and socktype ~= "dgram" then error("EPROTOTYPE") end
|
||||||
|
|
||||||
|
local sock = newSocket(domain, socktype)
|
||||||
|
local fdobj = socketToFd(sock)
|
||||||
|
local fd = kernel.vfs.newfd(fdobj)
|
||||||
|
return fd
|
||||||
|
end
|
||||||
|
|
||||||
|
kernel.syscalls["bind"] = function(fd, address)
|
||||||
|
local task = kernel.currentTask
|
||||||
|
local fdobj = task.fd[fd]
|
||||||
|
if not fdobj or not fdobj.isSocket then error("ENOTSOCK") end
|
||||||
|
local sock = sockets[fdobj.sockId]
|
||||||
|
if not sock then error("EBADF") end
|
||||||
|
if sock.bound then error("EINVAL") end
|
||||||
|
|
||||||
|
local parsed = parseAddress(address)
|
||||||
|
|
||||||
|
if parsed.backend == "unix" then
|
||||||
|
local existing = unixSocks[parsed.path]
|
||||||
|
if existing then
|
||||||
|
if existing.state == "closed" then
|
||||||
|
unixSocks[parsed.path] = nil
|
||||||
|
else
|
||||||
|
error("EADDRINUSE")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
sock.backend = "unix"
|
||||||
|
sock.address = parsed
|
||||||
|
sock.bound = true
|
||||||
|
sock.state = "bound"
|
||||||
|
unixSocks[parsed.path] = sock
|
||||||
|
|
||||||
|
elseif parsed.backend == "rednet" then
|
||||||
|
ensureRednet()
|
||||||
|
sock.backend = "rednet"
|
||||||
|
sock.address = parsed
|
||||||
|
sock.bound = true
|
||||||
|
sock.state = "bound"
|
||||||
|
|
||||||
|
elseif parsed.backend == "modem" then
|
||||||
|
local modem, side = getModem()
|
||||||
|
sock.backend = "modem"
|
||||||
|
sock.address = parsed
|
||||||
|
sock.modem = modem
|
||||||
|
sock.modemChannel = parsed.port
|
||||||
|
sock.bound = true
|
||||||
|
sock.state = "bound"
|
||||||
|
modem.open(parsed.port)
|
||||||
|
|
||||||
|
else
|
||||||
|
error("EOPNOTSUPP: cannot bind to " .. parsed.backend .. " address")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
kernel.syscalls["listen"] = function(fd, backlog)
|
||||||
|
local task = kernel.currentTask
|
||||||
|
local fdobj = task.fd[fd]
|
||||||
|
if not fdobj or not fdobj.isSocket then error("ENOTSOCK") end
|
||||||
|
local sock = sockets[fdobj.sockId]
|
||||||
|
if not sock then error("EBADF") end
|
||||||
|
if not sock.bound then error("EDESTADDRREQ") end
|
||||||
|
sock.listening = true
|
||||||
|
sock.state = "listening"
|
||||||
|
sock.maxBacklog = backlog or 5
|
||||||
|
end
|
||||||
|
|
||||||
|
kernel.syscalls["accept"] = function(fd)
|
||||||
|
local task = kernel.currentTask
|
||||||
|
local fdobj = task.fd[fd]
|
||||||
|
if not fdobj or not fdobj.isSocket then error("ENOTSOCK") end
|
||||||
|
local sock = sockets[fdobj.sockId]
|
||||||
|
if not sock then error("EBADF") end
|
||||||
|
if not sock.listening then error("EINVAL") end
|
||||||
|
|
||||||
|
local deadline = kernel.computer:time() + 30000
|
||||||
|
while #sock.backlog == 0 do
|
||||||
|
pumpAll()
|
||||||
|
if kernel.computer:time() > deadline then error("ETIMEDOUT") end
|
||||||
|
coroutine.yield()
|
||||||
|
end
|
||||||
|
|
||||||
|
local clientSock = table.remove(sock.backlog, 1)
|
||||||
|
local cfdobj = socketToFd(clientSock)
|
||||||
|
local newfd = kernel.vfs.newfd(cfdobj)
|
||||||
|
return newfd
|
||||||
|
end
|
||||||
|
|
||||||
|
kernel.syscalls["connect"] = function(fd, address)
|
||||||
|
local task = kernel.currentTask
|
||||||
|
local fdobj = task.fd[fd]
|
||||||
|
if not fdobj or not fdobj.isSocket then error("ENOTSOCK") end
|
||||||
|
local sock = sockets[fdobj.sockId]
|
||||||
|
if not sock then error("EBADF") end
|
||||||
|
if sock.connected then error("EISCONN") end
|
||||||
|
|
||||||
|
local parsed = parseAddress(address)
|
||||||
|
sock.address = parsed
|
||||||
|
sock.backend = parsed.backend
|
||||||
|
|
||||||
|
if parsed.backend == "unix" then
|
||||||
|
local server = unixSocks[parsed.path]
|
||||||
|
if not server then error("ECONNREFUSED") end
|
||||||
|
if not server.listening then error("ECONNREFUSED") end
|
||||||
|
if #server.backlog >= (server.maxBacklog or 5) then error("ECONNREFUSED") end
|
||||||
|
|
||||||
|
local serverPeer = newSocket("unix", sock.socktype)
|
||||||
|
serverPeer.backend = "unix"
|
||||||
|
serverPeer.connected = true
|
||||||
|
serverPeer.state = "connected"
|
||||||
|
serverPeer.peer = sock
|
||||||
|
|
||||||
|
sock.peer = serverPeer
|
||||||
|
sock.connected = true
|
||||||
|
sock.state = "connected"
|
||||||
|
|
||||||
|
table.insert(server.backlog, serverPeer)
|
||||||
|
|
||||||
|
elseif parsed.backend == "rednet" then
|
||||||
|
ensureRednet()
|
||||||
|
sock.connected = true
|
||||||
|
sock.state = "connected"
|
||||||
|
|
||||||
|
elseif parsed.backend == "modem" then
|
||||||
|
local modem, side = getModem()
|
||||||
|
local replyChannel = math.random(1024, 65534)
|
||||||
|
sock.modem = modem
|
||||||
|
sock.modemChannel = replyChannel
|
||||||
|
sock.connected = true
|
||||||
|
sock.state = "connected"
|
||||||
|
modem.open(replyChannel)
|
||||||
|
|
||||||
|
elseif parsed.backend == "http" or parsed.backend == "https" then
|
||||||
|
sock.connected = true
|
||||||
|
sock.state = "connected"
|
||||||
|
|
||||||
|
else
|
||||||
|
error("EAFNOSUPPORT")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
kernel.syscalls["send"] = function(fd, data)
|
||||||
|
local task = kernel.currentTask
|
||||||
|
local fdobj = task.fd[fd]
|
||||||
|
if not fdobj or not fdobj.isSocket then error("ENOTSOCK") end
|
||||||
|
local sock = sockets[fdobj.sockId]
|
||||||
|
if not sock then error("EBADF") end
|
||||||
|
return sockSend(sock, data)
|
||||||
|
end
|
||||||
|
|
||||||
|
kernel.syscalls["recv"] = function(fd, maxlen, timeout_ms)
|
||||||
|
local task = kernel.currentTask
|
||||||
|
local fdobj = task.fd[fd]
|
||||||
|
if not fdobj or not fdobj.isSocket then error("ENOTSOCK") end
|
||||||
|
local sock = sockets[fdobj.sockId]
|
||||||
|
if not sock then error("EBADF") end
|
||||||
|
|
||||||
|
local deadline = kernel.computer:time() + (timeout_ms or 10000)
|
||||||
|
while #sock.rxbuf == 0 do
|
||||||
|
pumpAll()
|
||||||
|
if #sock.rxbuf > 0 then break end
|
||||||
|
if sock.state == "closed" or sock.error then
|
||||||
|
if sock.error then error("ECONNRESET: " .. tostring(sock.error)) end
|
||||||
|
return ""
|
||||||
|
end
|
||||||
|
if kernel.computer:time() > deadline then return "" end
|
||||||
|
coroutine.yield()
|
||||||
|
end
|
||||||
|
|
||||||
|
local item = table.remove(sock.rxbuf, 1)
|
||||||
|
local data = type(item) == "table" and (item.data or "") or tostring(item)
|
||||||
|
if maxlen and #data > maxlen then
|
||||||
|
table.insert(sock.rxbuf, 1, { data=data:sub(maxlen+1), from=item and item.from })
|
||||||
|
data = data:sub(1, maxlen)
|
||||||
|
end
|
||||||
|
return data
|
||||||
|
end
|
||||||
|
|
||||||
|
kernel.syscalls["sockshutdown"] = function(fd)
|
||||||
|
local task = kernel.currentTask
|
||||||
|
local fdobj = task.fd[fd]
|
||||||
|
if not fdobj or not fdobj.isSocket then error("ENOTSOCK") end
|
||||||
|
local sock = sockets[fdobj.sockId]
|
||||||
|
if sock then sockClose(sock) end
|
||||||
|
end
|
||||||
|
|
||||||
|
kernel.syscalls["getpeername"] = function(fd)
|
||||||
|
local task = kernel.currentTask
|
||||||
|
local fdobj = task.fd[fd]
|
||||||
|
if not fdobj or not fdobj.isSocket then error("ENOTSOCK") end
|
||||||
|
local sock = sockets[fdobj.sockId]
|
||||||
|
if not sock or not sock.connected then error("ENOTCONN") end
|
||||||
|
if sock.address then return sock.address end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
kernel.syscalls["getsockname"] = function(fd)
|
||||||
|
local task = kernel.currentTask
|
||||||
|
local fdobj = task.fd[fd]
|
||||||
|
if not fdobj or not fdobj.isSocket then error("ENOTSOCK") end
|
||||||
|
local sock = sockets[fdobj.sockId]
|
||||||
|
if not sock then error("EBADF") end
|
||||||
|
return sock.address
|
||||||
|
end
|
||||||
|
|
||||||
|
kernel.syscalls["httpget"] = function(url, headers)
|
||||||
|
local http = kernel.apis and kernel.apis.http
|
||||||
|
if not http then error("ENODEV: no http API") end
|
||||||
|
|
||||||
|
local ok, err = pcall(http.request, url, nil, headers)
|
||||||
|
if not ok then error("ENETDOWN: " .. tostring(err)) end
|
||||||
|
|
||||||
|
local deadline = kernel.computer:time() + 15000
|
||||||
|
while true do
|
||||||
|
local ev = pollEvent()
|
||||||
|
if ev then
|
||||||
|
if ev[1] == "http_success" and ev[2] == url then
|
||||||
|
local handle = ev[3]
|
||||||
|
local body = handle.readAll and handle.readAll() or ""
|
||||||
|
handle.close()
|
||||||
|
return body
|
||||||
|
elseif ev[1] == "http_failure" and ev[2] == url then
|
||||||
|
error("ECONNREFUSED: " .. tostring(ev[3]))
|
||||||
|
else
|
||||||
|
dispatchEvent(ev)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if kernel.computer:time() > deadline then error("ETIMEDOUT") end
|
||||||
|
coroutine.yield()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
kernel.syscalls["resolve"] = function(hostname)
|
||||||
|
if hostname:match("^%d+%.%d+%.%d+%.%d+$") then return hostname end
|
||||||
|
|
||||||
|
local a,b,c,d = hostname:match("^(%d+)%.(%d+)%.(%d+)%.(%d+)$")
|
||||||
|
if a and tonumber(a) == 0 and tonumber(b) == 0 then
|
||||||
|
return hostname
|
||||||
|
end
|
||||||
|
|
||||||
|
local http = kernel.apis and kernel.apis.http
|
||||||
|
if not http then error("ENODEV: no http API for DNS") end
|
||||||
|
|
||||||
|
local url = "https://cloudflare-dns.com/dns-query?name=" .. hostname .. "&type=A"
|
||||||
|
local body = kernel.syscalls["httpget"](url, {
|
||||||
|
["Accept"] = "application/dns-json"
|
||||||
|
})
|
||||||
|
|
||||||
|
local ip = body:match('"type":1[^}]*"data":"([%d%.]+)"')
|
||||||
|
if not ip then error("ENOENT: could not resolve " .. hostname) end
|
||||||
|
return ip
|
||||||
|
end
|
||||||
|
|
||||||
|
kernel.sockets = sockets
|
||||||
|
kernel.unixSockets = unixSocks
|
||||||
|
|
||||||
kernel.log("Loaded socket module")
|
kernel.log("Loaded socket module")
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ end
|
|||||||
if not blake2s then error("Failed to load blake2s") end
|
if not blake2s then error("Failed to load blake2s") end
|
||||||
|
|
||||||
if not kernel.vfs.exists("/etc/pam.d/secret") then
|
if not kernel.vfs.exists("/etc/pam.d/secret") then
|
||||||
kernel.log("PAM SECRET REGENERATING PLEASE USE ROOT", "WARN", 0xFF8800)
|
kernel.log("PAM SECRET REGENERATING PLEASE USE ROOT")
|
||||||
local key = ""
|
local key = ""
|
||||||
for i = 1, 256 do key = key .. string.char(math.random(0, 255)) end
|
for i = 1, 256 do key = key .. string.char(math.random(0, 255)) end
|
||||||
local handle = kernel.vfs.open("/etc/pam.d/secret", "w")
|
local handle = kernel.vfs.open("/etc/pam.d/secret", "w")
|
||||||
|
|||||||
@@ -41,11 +41,11 @@ local function createTask(func, name, envars, args, tgid, real_uid, eff_uid)
|
|||||||
|
|
||||||
if kernel.config.logTaskExit then
|
if kernel.config.logTaskExit then
|
||||||
if not ok then
|
if not ok then
|
||||||
kernel.log("Task " .. tostring(id) .. " exited with err: " .. tostring(err), "ERROR", 0xFF0000)
|
kernel.log("Task " .. tostring(id) .. " exited with err: " .. tostring(err), "ERROR", 2)
|
||||||
elseif err then
|
elseif err then
|
||||||
kernel.log("Task " .. tostring(id) .. " exited with code: " .. tostring(err), "DBUG", 0x00FFFF)
|
kernel.log("Task " .. tostring(id) .. " exited with code: " .. tostring(err), "INFO")
|
||||||
else
|
else
|
||||||
kernel.log("Task " .. tostring(id) .. " exited without code", "DBUG", 0x00FFFF)
|
kernel.log("Task " .. tostring(id) .. " exited without code", "INFO")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -110,7 +110,7 @@ function sys.execspawn(path, name, envars, args, tgid)
|
|||||||
kernel.log(
|
kernel.log(
|
||||||
"execspawn: suid exec '" .. path ..
|
"execspawn: suid exec '" .. path ..
|
||||||
"' caller_uid=" .. tostring(real_uid) ..
|
"' caller_uid=" .. tostring(real_uid) ..
|
||||||
" -> euid=" .. tostring(euid)
|
" -> euid=" .. tostring(euid), "INFO"
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -136,9 +136,9 @@ function sys.exec(path, args, envars)
|
|||||||
local ok, err = xpcall(func, debug.traceback, table.unpack(task.args))
|
local ok, err = xpcall(func, debug.traceback, table.unpack(task.args))
|
||||||
if kernel.config.logTaskExit then
|
if kernel.config.logTaskExit then
|
||||||
if not ok then
|
if not ok then
|
||||||
kernel.log("Task " .. tostring(task.pid) .. " exec '" .. path .. "' err: " .. tostring(err), "ERROR", 0xFF0000)
|
kernel.log("Task " .. tostring(task.pid) .. " exec '" .. path .. "' err: " .. tostring(err), "ERROR", 2)
|
||||||
else
|
else
|
||||||
kernel.log("Task " .. tostring(task.pid) .. " exec '" .. path .. "' exited: " .. tostring(err), "DBUG", 0x00FFFF)
|
kernel.log("Task " .. tostring(task.pid) .. " exec '" .. path .. "' exited: " .. tostring(err), "INFO")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if type(err) == "number" then tasks[tostring(task.pid)].exit = err end
|
if type(err) == "number" then tasks[tostring(task.pid)].exit = err end
|
||||||
@@ -155,7 +155,7 @@ end
|
|||||||
|
|
||||||
function sys.sleep(s)
|
function sys.sleep(s)
|
||||||
kernel.currentTask.status = "S"
|
kernel.currentTask.status = "S"
|
||||||
kernel.currentTask.sleep = kernel.EFI:getEpochMs() + s * 1000
|
kernel.currentTask.sleep = kernel.computer:time() + s * 1000
|
||||||
coroutine.yield()
|
coroutine.yield()
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -260,9 +260,9 @@ function sys.exit(code)
|
|||||||
local task = kernel.currentTask
|
local task = kernel.currentTask
|
||||||
if kernel.config.logTaskExit then
|
if kernel.config.logTaskExit then
|
||||||
if code then
|
if code then
|
||||||
kernel.log("Task " .. tostring(task.pid) .. " exited with code: " .. tostring(code), "DBUG", 0x00FFFF)
|
kernel.log("Task " .. tostring(task.pid) .. " exited with code: " .. tostring(code), "INFO")
|
||||||
else
|
else
|
||||||
kernel.log("Task " .. tostring(task.pid) .. " exited without code", "DBUG", 0x00FFFF)
|
kernel.log("Task " .. tostring(task.pid) .. " exited without code", "INFO")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
tasks[tostring(task.pid)].status = "Z"
|
tasks[tostring(task.pid)].status = "Z"
|
||||||
@@ -303,9 +303,9 @@ local function reapDeadTasks()
|
|||||||
task.syscallReturn = nil
|
task.syscallReturn = nil
|
||||||
task.sleep = nil
|
task.sleep = nil
|
||||||
task.fd = nil
|
task.fd = nil
|
||||||
task.reapTime = kernel.EFI:getEpochMs() + 30000
|
task.reapTime = kernel.computer:time() + 30000
|
||||||
|
|
||||||
elseif task.reapTime and kernel.EFI:getEpochMs() > task.reapTime
|
elseif task.reapTime and kernel.computer:time() > task.reapTime
|
||||||
and task.status == "Z" then
|
and task.status == "Z" then
|
||||||
for _, child in ipairs(task.children) do
|
for _, child in ipairs(task.children) do
|
||||||
child.parent = tasks["1"]
|
child.parent = tasks["1"]
|
||||||
@@ -343,7 +343,7 @@ function kernel.main()
|
|||||||
local taskTimes = {}
|
local taskTimes = {}
|
||||||
|
|
||||||
for pid, task in pairs(tasks) do
|
for pid, task in pairs(tasks) do
|
||||||
if task.status == "S" and kernel.EFI:getEpochMs() >= task.sleep then
|
if task.status == "S" and kernel.computer:time() >= task.sleep then
|
||||||
task.status = "R"
|
task.status = "R"
|
||||||
task.sleep = 0
|
task.sleep = 0
|
||||||
end
|
end
|
||||||
@@ -382,7 +382,7 @@ function kernel.main()
|
|||||||
end
|
end
|
||||||
|
|
||||||
if task.status == "R" then
|
if task.status == "R" then
|
||||||
local startTime = kernel.EFI:getEpochMs()
|
local startTime = kernel.computer:time()
|
||||||
local ret
|
local ret
|
||||||
|
|
||||||
if kernel.config.preempt then
|
if kernel.config.preempt then
|
||||||
@@ -391,7 +391,7 @@ function kernel.main()
|
|||||||
ret = { coroutine.resume(task.coro, table.unpack(task.syscallReturn)) }
|
ret = { coroutine.resume(task.coro, table.unpack(task.syscallReturn)) }
|
||||||
end
|
end
|
||||||
|
|
||||||
local elapsed = kernel.EFI:getEpochMs() - startTime
|
local elapsed = kernel.computer:time() - startTime
|
||||||
task.lastTime = elapsed
|
task.lastTime = elapsed
|
||||||
task.totalTime = (task.totalTime or 0) + elapsed
|
task.totalTime = (task.totalTime or 0) + elapsed
|
||||||
task.numRuns = (task.numRuns or 0) + 1
|
task.numRuns = (task.numRuns or 0) + 1
|
||||||
@@ -403,7 +403,7 @@ function kernel.main()
|
|||||||
if elapsed >= Tmax then Tmax_hit = Tmax_hit + 1 end
|
if elapsed >= Tmax then Tmax_hit = Tmax_hit + 1 end
|
||||||
|
|
||||||
if ret[1] == "error" or ret[1] == false then
|
if ret[1] == "error" or ret[1] == false then
|
||||||
kernel.log("processHandlerException: " .. tostring(ret[2]), "ERROR", 0xFF0000)
|
kernel.log("processHandlerException: " .. tostring(ret[2]), "ERROR", 2)
|
||||||
task.status = "Z"
|
task.status = "Z"
|
||||||
task.exit = "processHandlerException: " .. tostring(ret[2])
|
task.exit = "processHandlerException: " .. tostring(ret[2])
|
||||||
|
|
||||||
@@ -418,9 +418,9 @@ function kernel.main()
|
|||||||
local scname = ret[3]
|
local scname = ret[3]
|
||||||
if kernel.syscalls[scname] then
|
if kernel.syscalls[scname] then
|
||||||
if kernel.config.debugSyscalls then
|
if kernel.config.debugSyscalls then
|
||||||
kernel.log("Task " .. task.pid .. " syscall: " .. scname, "DBUG", 0x00FFFF)
|
kernel.log("Task " .. task.pid .. " syscall: " .. scname, "DBUG", 5)
|
||||||
for i = 4, #ret do
|
for i = 4, #ret do
|
||||||
kernel.log(" inval[" .. (i-3) .. "] = " .. tostring(ret[i]), "DBUG", 0x00FFFF)
|
kernel.log(" inval[" .. (i-3) .. "] = " .. tostring(ret[i]), "DBUG", 5)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -428,12 +428,12 @@ function kernel.main()
|
|||||||
|
|
||||||
if kernel.config.debugSyscalls then
|
if kernel.config.debugSyscalls then
|
||||||
if not sysret[1] then
|
if not sysret[1] then
|
||||||
kernel.log("Task " .. task.pid .. " syscall " .. scname .. " failed: " .. tostring(sysret[2]), "ERROR", 0xFF0000)
|
kernel.log("Task " .. task.pid .. " syscall " .. scname .. " failed: " .. tostring(sysret[2]), "ERROR", 2)
|
||||||
else
|
else
|
||||||
kernel.log("Task " .. task.pid .. " syscall " .. scname .. " ok, " .. (#sysret-1) .. " retvals", "DBUG", 0x00FFFF)
|
kernel.log("Task " .. task.pid .. " syscall " .. scname .. " ok, " .. (#sysret-1) .. " retvals", "DBUG", 5)
|
||||||
for i = 2, #sysret do
|
for i = 2, #sysret do
|
||||||
local v = type(sysret[i]) == "table" and table.serialize(sysret[i]) or tostring(sysret[i])
|
local v = type(sysret[i]) == "table" and table.serialize(sysret[i]) or tostring(sysret[i])
|
||||||
kernel.log(" retval[" .. (i-1) .. "] = " .. v, "DBUG", 0x00FFFF)
|
kernel.log(" retval[" .. (i-1) .. "] = " .. v, "DBUG", 5)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -9,20 +9,8 @@ sysc["gpio_write"]=function(pin, data)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
sysc["gpio_writeAnalog"]=function(pin, data)
|
|
||||||
if kernel.gpio[pin] then
|
|
||||||
return kernel.gpio[pin]("wa", data)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
sysc["gpio_read"]=function(pin)
|
sysc["gpio_read"]=function(pin)
|
||||||
if kernel.gpio[pin] then
|
if kernel.gpio[pin] then
|
||||||
return kernel.gpio[pin]("r")
|
return kernel.gpio[pin]("r")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
sysc["gpio_readAnalog"]=function(pin)
|
|
||||||
if kernel.gpio[pin] then
|
|
||||||
return kernel.gpio[pin]("ra")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -9,13 +9,11 @@ if not initOk then
|
|||||||
end
|
end
|
||||||
|
|
||||||
local handle = kernel.vfs.open(kernel.config.initPath, "r")
|
local handle = kernel.vfs.open(kernel.config.initPath, "r")
|
||||||
if not handle then kernel.panic("Failed to open "..kernel.config.initPath) end
|
|
||||||
local data = kernel.vfs.read(handle, 1024 * 1024 * 4)
|
local data = kernel.vfs.read(handle, 1024 * 1024 * 4)
|
||||||
if not handle then kernel.panic("Failed to read "..kernel.config.initPath) end
|
|
||||||
kernel.vfs.close(handle)
|
kernel.vfs.close(handle)
|
||||||
|
|
||||||
local initFunc, err = load(data, "@sysinit", "t", kernel._U)
|
local initFunc, err = load(data, "@sysinit", "t", kernel._U)
|
||||||
if not initFunc then kernel.PANIC("Failed to load init system: " .. err) end
|
if not initFunc then error("Failed to load init system: " .. err) end
|
||||||
|
|
||||||
kernel.tasks["1"] = {
|
kernel.tasks["1"] = {
|
||||||
coro = coroutine.create(function()
|
coro = coroutine.create(function()
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
--:Minify:--
|
--:Minify:--
|
||||||
local kernel = ...
|
local kernel = ...
|
||||||
if not kernel.vfs.exists("/root") then kernel.vfs.mkdir("/root") end
|
|
||||||
|
|
||||||
kernel.processes.login = function()
|
kernel.processes.login = function()
|
||||||
local ok, err = pcall(kernel.hpv.execspawn, "/bin/login", "login")
|
local ok, err = pcall(kernel.hpv.execspawn, "/bin/login", "login")
|
||||||
if not ok then
|
if not ok then
|
||||||
kernel.log("Failed to exec /bin/login: " .. tostring(err), "ERROR", 0xFF0000)
|
kernel.log("Failed to exec /bin/login: " .. tostring(err), "ERROR", 2)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
--:Minify:--
|
--:Minify:--
|
||||||
local kernel = ...
|
local kernel = ...
|
||||||
|
|
||||||
if kernel.firstBoot then
|
|
||||||
local P = kernel.vfs.P
|
local P = kernel.vfs.P
|
||||||
local PERM = kernel.vfs.PERM
|
local PERM = kernel.vfs.PERM
|
||||||
|
|
||||||
@@ -79,10 +78,11 @@ if kernel.firstBoot then
|
|||||||
f.close()
|
f.close()
|
||||||
end)
|
end)
|
||||||
if not ok then
|
if not ok then
|
||||||
kernel.log("permissions: failed to write " .. metaPath .. ": " .. tostring(err), "WARN", 0xFF8800)
|
kernel.log("permissions: failed to write " .. metaPath .. ": " .. tostring(err), "WARN", 8)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if kernel.firstBoot then
|
||||||
kernel.log("Seeding filesystem permissions...")
|
kernel.log("Seeding filesystem permissions...")
|
||||||
|
|
||||||
mergeMeta("/", {
|
mergeMeta("/", {
|
||||||
@@ -92,7 +92,6 @@ if kernel.firstBoot then
|
|||||||
{"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},
|
||||||
{"proc", REG, 0, 0, RWXRWXRWX},
|
|
||||||
{"root", REG, 0, 0, RW____ },
|
{"root", REG, 0, 0, RW____ },
|
||||||
{"sbin", REG, 0, 0, RWX_RX_RX},
|
{"sbin", REG, 0, 0, RWX_RX_RX},
|
||||||
{"tmp", REG, 0, 0, RWXRWXRWX},
|
{"tmp", REG, 0, 0, RWXRWXRWX},
|
||||||
|
|||||||
@@ -261,16 +261,16 @@ local function render()
|
|||||||
syscall.write(1, "\n")
|
syscall.write(1, "\n")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
syscall.devctl(1, "sfgc", 0x000000)
|
syscall.devctl(1, "sfgc", 16)
|
||||||
syscall.devctl(1, "sbgc", 0xDBDBDB)
|
syscall.devctl(1, "sbgc", 13)
|
||||||
local pct = math.floor(math.min(100, (scroll + pageSize) / totalLines * 100))
|
local pct = math.floor(math.min(100, (scroll + pageSize) / totalLines * 100))
|
||||||
local status = string.format(" help -- line %d/%d (%d%%) [up/down: scroll q: quit] ",
|
local status = string.format(" help -- line %d/%d (%d%%) [up/down: scroll q: quit] ",
|
||||||
scroll + 1, totalLines, pct)
|
scroll + 1, totalLines, pct)
|
||||||
if #status > screenW then status = status:sub(1, screenW) end
|
if #status > screenW then status = status:sub(1, screenW) end
|
||||||
syscall.devctl(1, "spos", 1, screenH)
|
syscall.devctl(1, "spos", 1, screenH)
|
||||||
syscall.write(1, status .. string.rep(" ", screenW - #status))
|
syscall.write(1, status .. string.rep(" ", screenW - #status))
|
||||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
syscall.devctl(1, "sfgc", 1)
|
||||||
syscall.devctl(1, "sbgc", 0x000000)
|
syscall.devctl(1, "sbgc", 16)
|
||||||
dirty = false
|
dirty = false
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -281,7 +281,7 @@ if totalLines <= pageSize then
|
|||||||
syscall.devctl(1, "sfgc", line[2])
|
syscall.devctl(1, "sfgc", line[2])
|
||||||
syscall.write(1, line[1] .. "\n")
|
syscall.write(1, line[1] .. "\n")
|
||||||
end
|
end
|
||||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
syscall.devctl(1, "sfgc", 1)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -305,5 +305,5 @@ end
|
|||||||
|
|
||||||
syscall.devctl(1, "clear")
|
syscall.devctl(1, "clear")
|
||||||
syscall.devctl(1, "spos", 1, 1)
|
syscall.devctl(1, "spos", 1, 1)
|
||||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
syscall.devctl(1, "sfgc", 1)
|
||||||
syscall.devctl(1, "sbgc", 0x000000)
|
syscall.devctl(1, "sbgc", 16)
|
||||||
|
|||||||
@@ -3,11 +3,11 @@
|
|||||||
-- 1=white, 2=red, 3=green, 4=blue, 5=cyan, 6=magenta, 7=yellow
|
-- 1=white, 2=red, 3=green, 4=blue, 5=cyan, 6=magenta, 7=yellow
|
||||||
-- 8=orange, 9=lime, 10=lightcyan, 11=brown, 12=darkgrey, 13=lightgrey, 14=purple, 15=chartreuse, 16=black
|
-- 8=orange, 9=lime, 10=lightcyan, 11=brown, 12=darkgrey, 13=lightgrey, 14=purple, 15=chartreuse, 16=black
|
||||||
|
|
||||||
local C_LOGO = 0x00FFFF -- cyan
|
local C_LOGO = 5 -- cyan
|
||||||
local C_WHITE = 0xFFFFFF -- white
|
local C_WHITE = 1 -- white
|
||||||
local C_LABEL = 0xDBDBDB -- light grey (key names)
|
local C_LABEL = 13 -- light grey (key names)
|
||||||
local C_SEP = 0x6D6D6D -- dark grey (---- separator)
|
local C_SEP = 12 -- dark grey (---- separator)
|
||||||
local C_USER = 0x00FF00 -- green (user@host)
|
local C_USER = 3 -- green (user@host)
|
||||||
|
|
||||||
local function c(col) syscall.devctl(1, "sfgc", col) end
|
local function c(col) syscall.devctl(1, "sfgc", col) end
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ local success, errorMsg = xpcall(function()
|
|||||||
local fs = require("fs")
|
local fs = require("fs")
|
||||||
|
|
||||||
syscall.devctl(1,"clear")
|
syscall.devctl(1,"clear")
|
||||||
syscall.devctl(1,"sfgc",0xFFFFFF)
|
syscall.devctl(1,"sfgc",1)
|
||||||
syscall.devctl(1,"spos",1,1)
|
syscall.devctl(1,"spos",1,1)
|
||||||
print("HyperionOS hysh Shell")
|
print("HyperionOS hysh Shell")
|
||||||
|
|
||||||
@@ -26,27 +26,8 @@ else
|
|||||||
end
|
end
|
||||||
local oldWD = ""
|
local oldWD = ""
|
||||||
|
|
||||||
local colors = {
|
|
||||||
0xFFFFFF,
|
|
||||||
0xFF0000,
|
|
||||||
0x00FF00,
|
|
||||||
0x0000FF,
|
|
||||||
0x00FFFF,
|
|
||||||
0xFF00FF,
|
|
||||||
0xFFFF00,
|
|
||||||
0xFF6D00,
|
|
||||||
0x6DFF55,
|
|
||||||
0x24FFFF,
|
|
||||||
0x924900,
|
|
||||||
0x6D6D55,
|
|
||||||
0xDBDBAA,
|
|
||||||
0x6D00FF,
|
|
||||||
0xB6FF00,
|
|
||||||
0x000000
|
|
||||||
}
|
|
||||||
|
|
||||||
for i = 1, 16 do
|
for i = 1, 16 do
|
||||||
syscall.devctl(1,"sbgc",colors[i]); printInline(" ")
|
syscall.devctl(1,"sbgc",i); printInline(" ")
|
||||||
end
|
end
|
||||||
print("\n")
|
print("\n")
|
||||||
|
|
||||||
@@ -240,7 +221,7 @@ end
|
|||||||
|
|
||||||
builtinCmds.clear = function()
|
builtinCmds.clear = function()
|
||||||
syscall.devctl(1,"clear")
|
syscall.devctl(1,"clear")
|
||||||
syscall.devctl(1,"sfgc",0xFFFFFF)
|
syscall.devctl(1,"sfgc",1)
|
||||||
syscall.devctl(1,"spos",1,1)
|
syscall.devctl(1,"spos",1,1)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -448,7 +429,7 @@ builtinCmds.head = function(...)
|
|||||||
local multi = #files > 1
|
local multi = #files > 1
|
||||||
local function dohead(text, label)
|
local function dohead(text, label)
|
||||||
if multi then
|
if multi then
|
||||||
syscall.devctl(1,"sfgc",0x0000FF); print("==> "..label.." <=="); syscall.devctl(1,"sfgc",0xFFFFFF)
|
syscall.devctl(1,"sfgc",4); print("==> "..label.." <=="); syscall.devctl(1,"sfgc",1)
|
||||||
end
|
end
|
||||||
local count = 0
|
local count = 0
|
||||||
for line in (text.."\n"):gmatch("([^\n]*)\n") do
|
for line in (text.."\n"):gmatch("([^\n]*)\n") do
|
||||||
@@ -487,7 +468,7 @@ builtinCmds.tail = function(...)
|
|||||||
local multi = #files > 1
|
local multi = #files > 1
|
||||||
local function dotail(text, label)
|
local function dotail(text, label)
|
||||||
if multi then
|
if multi then
|
||||||
syscall.devctl(1,"sfgc",0x0000FF); print("==> "..label.." <=="); syscall.devctl(1,"sfgc",0xFFFFFF)
|
syscall.devctl(1,"sfgc",4); print("==> "..label.." <=="); syscall.devctl(1,"sfgc",1)
|
||||||
end
|
end
|
||||||
local lines = splitlines(text)
|
local lines = splitlines(text)
|
||||||
local start = math.max(1, #lines - n + 1)
|
local start = math.max(1, #lines - n + 1)
|
||||||
@@ -982,13 +963,13 @@ local function doTabComplete(input, cursorPos)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function getUserInput()
|
local function getUserInput()
|
||||||
syscall.devctl(1,"sfgc",0x00FF00)
|
syscall.devctl(1,"sfgc",3)
|
||||||
syscall.write(1, userhost)
|
syscall.write(1, userhost)
|
||||||
syscall.devctl(1,"sfgc",0xFFFFFF)
|
syscall.devctl(1,"sfgc",1)
|
||||||
syscall.write(1, ":")
|
syscall.write(1, ":")
|
||||||
syscall.devctl(1,"sfgc",0x24FFFF)
|
syscall.devctl(1,"sfgc",10)
|
||||||
syscall.write(1, syscall.getcwd())
|
syscall.write(1, syscall.getcwd())
|
||||||
syscall.devctl(1,"sfgc",0xFFFFFF)
|
syscall.devctl(1,"sfgc",1)
|
||||||
syscall.write(1, "$ ")
|
syscall.write(1, "$ ")
|
||||||
local curOffsetStr = syscall.devctl(1, "gpos")
|
local curOffsetStr = syscall.devctl(1, "gpos")
|
||||||
local curOffsetX = tonumber(curOffsetStr:sub(1, curOffsetStr:find(";")-1))
|
local curOffsetX = tonumber(curOffsetStr:sub(1, curOffsetStr:find(";")-1))
|
||||||
@@ -1039,21 +1020,21 @@ local function getUserInput()
|
|||||||
syscall.devctl(1,"spos",curOffsetX,curOffsetY)
|
syscall.devctl(1,"spos",curOffsetX,curOffsetY)
|
||||||
syscall.write(1, string.sub(input, 1, cursorPos-1))
|
syscall.write(1, string.sub(input, 1, cursorPos-1))
|
||||||
if blinkState then
|
if blinkState then
|
||||||
syscall.devctl(1,"sfgc",0x000000); syscall.devctl(1,"sbgc",0xFFFFFF)
|
syscall.devctl(1,"sfgc",16); syscall.devctl(1,"sbgc",1)
|
||||||
end
|
end
|
||||||
if cursorPos > #input then
|
if cursorPos > #input then
|
||||||
syscall.write(1, " ")
|
syscall.write(1, " ")
|
||||||
else
|
else
|
||||||
syscall.write(1, string.sub(input, cursorPos, cursorPos))
|
syscall.write(1, string.sub(input, cursorPos, cursorPos))
|
||||||
end
|
end
|
||||||
syscall.devctl(1,"sfgc",0xFFFFFF); syscall.devctl(1,"sbgc",0x000000)
|
syscall.devctl(1,"sfgc",1); syscall.devctl(1,"sbgc",16)
|
||||||
local after = string.sub(input, cursorPos+1)
|
local after = string.sub(input, cursorPos+1)
|
||||||
syscall.write(1, after)
|
syscall.write(1, after)
|
||||||
local ghost = getGhostSuffix()
|
local ghost = getGhostSuffix()
|
||||||
if #ghost > 0 then
|
if #ghost > 0 then
|
||||||
syscall.devctl(1,"sfgc",0x6D00FF)
|
syscall.devctl(1,"sfgc",14)
|
||||||
syscall.write(1, ghost)
|
syscall.write(1, ghost)
|
||||||
syscall.devctl(1,"sfgc",0xFFFFFF)
|
syscall.devctl(1,"sfgc",1)
|
||||||
syscall.write(1, " ")
|
syscall.write(1, " ")
|
||||||
else
|
else
|
||||||
syscall.write(1, " ")
|
syscall.write(1, " ")
|
||||||
@@ -1101,10 +1082,10 @@ local function getUserInput()
|
|||||||
syscall.write(1, string.rep(" ", tw))
|
syscall.write(1, string.rep(" ", tw))
|
||||||
syscall.devctl(1,"spos",1,py)
|
syscall.devctl(1,"spos",1,py)
|
||||||
end
|
end
|
||||||
syscall.devctl(1,"sfgc",0x00FF00); syscall.write(1, userhost)
|
syscall.devctl(1,"sfgc",3); syscall.write(1, userhost)
|
||||||
syscall.devctl(1,"sfgc",0xFFFFFF); syscall.write(1, ":")
|
syscall.devctl(1,"sfgc",1); syscall.write(1, ":")
|
||||||
syscall.devctl(1,"sfgc",0x00FFFF); syscall.write(1, syscall.getcwd())
|
syscall.devctl(1,"sfgc",10); syscall.write(1, syscall.getcwd())
|
||||||
syscall.devctl(1,"sfgc",0xFFFFFF); syscall.write(1, "$ ")
|
syscall.devctl(1,"sfgc",1); syscall.write(1, "$ ")
|
||||||
posStr = syscall.devctl(1, "gpos")
|
posStr = syscall.devctl(1, "gpos")
|
||||||
sep = posStr:find(";")
|
sep = posStr:find(";")
|
||||||
curOffsetX = tonumber(posStr:sub(1, sep-1))
|
curOffsetX = tonumber(posStr:sub(1, sep-1))
|
||||||
@@ -1117,7 +1098,7 @@ local function getUserInput()
|
|||||||
cursorPos=cursorPos-1;dirty=true
|
cursorPos=cursorPos-1;dirty=true
|
||||||
end
|
end
|
||||||
elseif key=="\n" then
|
elseif key=="\n" then
|
||||||
syscall.devctl(1,"sfgc",0xFFFFFF);syscall.devctl(1,"sbgc",0x000000)
|
syscall.devctl(1,"sfgc",1);syscall.devctl(1,"sbgc",16)
|
||||||
syscall.devctl(1,"spos",curOffsetX,curOffsetY)
|
syscall.devctl(1,"spos",curOffsetX,curOffsetY)
|
||||||
syscall.write(1, input.." \n")
|
syscall.write(1, input.." \n")
|
||||||
return input
|
return input
|
||||||
@@ -1133,7 +1114,7 @@ local function getUserInput()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function printError(progName, msg)
|
local function printError(progName, msg)
|
||||||
syscall.devctl(1,"sfgc",0xFF0000)
|
syscall.devctl(1,"sfgc",2)
|
||||||
local s = tostring(msg)
|
local s = tostring(msg)
|
||||||
local line, rest = s:match("%]:(%d+): (.+)$")
|
local line, rest = s:match("%]:(%d+): (.+)$")
|
||||||
if not line then line, rest = s:match(":(%d+): (.+)$") end
|
if not line then line, rest = s:match(":(%d+): (.+)$") end
|
||||||
@@ -1142,7 +1123,7 @@ local function printError(progName, msg)
|
|||||||
else
|
else
|
||||||
print(progName..": "..s)
|
print(progName..": "..s)
|
||||||
end
|
end
|
||||||
syscall.devctl(1,"sfgc",0xFFFFFF)
|
syscall.devctl(1,"sfgc",1)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function runCommand(command)
|
local function runCommand(command)
|
||||||
@@ -1190,7 +1171,7 @@ local function runCommand(command)
|
|||||||
|
|
||||||
local xok, xerr = pcall(syscall.access, cmdPath, "x")
|
local xok, xerr = pcall(syscall.access, cmdPath, "x")
|
||||||
if not xok then
|
if not xok then
|
||||||
syscall.devctl(1,"sfgc",0xFF0000); print(progName..": Permission denied"); syscall.devctl(1,"sfgc",0xFFFFFF)
|
syscall.devctl(1,"sfgc",2); print(progName..": Permission denied"); syscall.devctl(1,"sfgc",1)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1214,8 +1195,8 @@ local function runCommand(command)
|
|||||||
if terminate then
|
if terminate then
|
||||||
local ok2 = syscall.kill(proc)
|
local ok2 = syscall.kill(proc)
|
||||||
if ok2 then
|
if ok2 then
|
||||||
syscall.devctl(1,"sbgc",16); syscall.devctl(1,"sfgc",0xFF0000)
|
syscall.devctl(1,"sbgc",16); syscall.devctl(1,"sfgc",2)
|
||||||
print("\nProgram Terminated."); syscall.devctl(1,"sfgc",0xFFFFFF)
|
print("\nProgram Terminated."); syscall.devctl(1,"sfgc",1)
|
||||||
end
|
end
|
||||||
terminate = false; break
|
terminate = false; break
|
||||||
end
|
end
|
||||||
@@ -1237,8 +1218,8 @@ end, debug.traceback)
|
|||||||
|
|
||||||
if not success then
|
if not success then
|
||||||
syscall.log("Error running shell: "..errorMsg, "ERROR")
|
syscall.log("Error running shell: "..errorMsg, "ERROR")
|
||||||
syscall.devctl(1,"sfgc",0xFF0000)
|
syscall.devctl(1,"sfgc",2)
|
||||||
syscall.devctl(1,"sbgc",0x000000)
|
syscall.devctl(1,"sbgc",16)
|
||||||
print()
|
print()
|
||||||
print("Error running shell: ")
|
print("Error running shell: ")
|
||||||
print(errorMsg)
|
print(errorMsg)
|
||||||
|
|||||||
@@ -37,9 +37,9 @@ local function firstBoot()
|
|||||||
|
|
||||||
syscall.devctl(1, "clear")
|
syscall.devctl(1, "clear")
|
||||||
syscall.devctl(1, "spos", 1, 1)
|
syscall.devctl(1, "spos", 1, 1)
|
||||||
syscall.devctl(1, "sfgc", 0x00FF00)
|
syscall.devctl(1, "sfgc", 3)
|
||||||
syscall.write(1, "HyperionOS First Boot Setup\n")
|
syscall.write(1, "HyperionOS First Boot Setup\n")
|
||||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
syscall.devctl(1, "sfgc", 1)
|
||||||
syscall.write(1, "No root password is set. Please create one now.\n\n")
|
syscall.write(1, "No root password is set. Please create one now.\n\n")
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
@@ -49,25 +49,25 @@ local function firstBoot()
|
|||||||
local pw2 = readLine("*")
|
local pw2 = readLine("*")
|
||||||
|
|
||||||
if pw1 ~= pw2 then
|
if pw1 ~= pw2 then
|
||||||
syscall.devctl(1, "sfgc", 0xFF0000)
|
syscall.devctl(1, "sfgc", 2)
|
||||||
syscall.write(1, "Passwords do not match. Try again.\n\n")
|
syscall.write(1, "Passwords do not match. Try again.\n\n")
|
||||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
syscall.devctl(1, "sfgc", 1)
|
||||||
elseif #pw1 < 6 then
|
elseif #pw1 < 6 then
|
||||||
syscall.devctl(1, "sfgc", 0xFF0000)
|
syscall.devctl(1, "sfgc", 2)
|
||||||
syscall.write(1, "Password too short (minimum 6 characters).\n\n")
|
syscall.write(1, "Password too short (minimum 6 characters).\n\n")
|
||||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
syscall.devctl(1, "sfgc", 1)
|
||||||
else
|
else
|
||||||
local ok, err = syscall.setpassword(0, pw1)
|
local ok, err = syscall.setpassword(0, pw1)
|
||||||
if ok then
|
if ok then
|
||||||
syscall.devctl(1, "sfgc", 0x00FF00)
|
syscall.devctl(1, "sfgc", 3)
|
||||||
syscall.write(1, "Root password set.\n\n")
|
syscall.write(1, "Root password set.\n\n")
|
||||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
syscall.devctl(1, "sfgc", 1)
|
||||||
sleep(0.5)
|
sleep(0.5)
|
||||||
break
|
break
|
||||||
else
|
else
|
||||||
syscall.devctl(1, "sfgc", 0xFF0000)
|
syscall.devctl(1, "sfgc", 2)
|
||||||
syscall.write(1, "Error: " .. tostring(err) .. "\n")
|
syscall.write(1, "Error: " .. tostring(err) .. "\n")
|
||||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
syscall.devctl(1, "sfgc", 1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -112,8 +112,8 @@ end
|
|||||||
|
|
||||||
local function doLogin()
|
local function doLogin()
|
||||||
syscall.devctl(1, "clear")
|
syscall.devctl(1, "clear")
|
||||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
syscall.devctl(1, "sfgc", 1)
|
||||||
syscall.devctl(1, "sbgc", 0x000000)
|
syscall.devctl(1, "sbgc", 16)
|
||||||
syscall.devctl(1, "spos", 1, 1)
|
syscall.devctl(1, "spos", 1, 1)
|
||||||
|
|
||||||
local hostname = syscall.getHostname() or "hyperion"
|
local hostname = syscall.getHostname() or "hyperion"
|
||||||
@@ -122,7 +122,7 @@ local function doLogin()
|
|||||||
|
|
||||||
local attempts = 0
|
local attempts = 0
|
||||||
while attempts < MAX_ATTEMPTS do
|
while attempts < MAX_ATTEMPTS do
|
||||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
syscall.devctl(1, "sfgc", 1)
|
||||||
syscall.write(1, "Username: ")
|
syscall.write(1, "Username: ")
|
||||||
local username = readLine(nil)
|
local username = readLine(nil)
|
||||||
|
|
||||||
@@ -140,9 +140,9 @@ local function doLogin()
|
|||||||
local shell = (pwent and pwent.shell) or "/bin/hysh"
|
local shell = (pwent and pwent.shell) or "/bin/hysh"
|
||||||
local homedir = (pwent and pwent.homedir) or "/"
|
local homedir = (pwent and pwent.homedir) or "/"
|
||||||
|
|
||||||
syscall.devctl(1, "sfgc", 0x00FF00)
|
syscall.devctl(1, "sfgc", 3)
|
||||||
syscall.write(1, "\nWelcome, " .. username .. "!\n")
|
syscall.write(1, "\nWelcome, " .. username .. "!\n")
|
||||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
syscall.devctl(1, "sfgc", 1)
|
||||||
sleep(0.3)
|
sleep(0.3)
|
||||||
|
|
||||||
spawnShell(username, uid, shell, homedir)
|
spawnShell(username, uid, shell, homedir)
|
||||||
@@ -150,16 +150,16 @@ local function doLogin()
|
|||||||
else
|
else
|
||||||
attempts = attempts + 1
|
attempts = attempts + 1
|
||||||
sleep(1)
|
sleep(1)
|
||||||
syscall.devctl(1, "sfgc", 0xFF0000)
|
syscall.devctl(1, "sfgc", 2)
|
||||||
syscall.write(1, "Login incorrect.\n\n")
|
syscall.write(1, "Login incorrect.\n\n")
|
||||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
syscall.devctl(1, "sfgc", 1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
syscall.devctl(1, "sfgc", 0xFF0000)
|
syscall.devctl(1, "sfgc", 2)
|
||||||
syscall.write(1, "Maximum login attempts exceeded.\n")
|
syscall.write(1, "Maximum login attempts exceeded.\n")
|
||||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
syscall.devctl(1, "sfgc", 1)
|
||||||
sleep(5)
|
sleep(5)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -110,9 +110,9 @@ if opts.x then
|
|||||||
pcall(syscall.umount, tmpMnt)
|
pcall(syscall.umount, tmpMnt)
|
||||||
pcall(syscall.lodetach, loopId)
|
pcall(syscall.lodetach, loopId)
|
||||||
|
|
||||||
syscall.devctl(1, "sfgc", 0x00FFFF)
|
syscall.devctl(1, "sfgc", 10)
|
||||||
print(name..": extracted "..count.." file(s) to "..destPath)
|
print(name..": extracted "..count.." file(s) to "..destPath)
|
||||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
syscall.devctl(1, "sfgc", 1)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -150,8 +150,8 @@ local lineCount = 0
|
|||||||
for _ in imgStr:gmatch("\n") do lineCount = lineCount + 1 end
|
for _ in imgStr:gmatch("\n") do lineCount = lineCount + 1 end
|
||||||
local byteCount = #imgStr
|
local byteCount = #imgStr
|
||||||
|
|
||||||
syscall.devctl(1, "sfgc", 0x00FFFF)
|
syscall.devctl(1, "sfgc", 10)
|
||||||
print(name..": image written to "..imgPath)
|
print(name..": image written to "..imgPath)
|
||||||
syscall.devctl(1, "sfgc", 0x6D00FF)
|
syscall.devctl(1, "sfgc", 14)
|
||||||
print(string.format(" %d records, %d bytes", lineCount - 1, byteCount))
|
print(string.format(" %d records, %d bytes", lineCount - 1, byteCount))
|
||||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
syscall.devctl(1, "sfgc", 1)
|
||||||
|
|||||||
@@ -60,18 +60,18 @@ if opts.l then
|
|||||||
local info = devs[id]
|
local info = devs[id]
|
||||||
local mode = (type(info) == "table" and info.mode) or "bind"
|
local mode = (type(info) == "table" and info.mode) or "bind"
|
||||||
local path = (type(info) == "table" and info.path) or tostring(info)
|
local path = (type(info) == "table" and info.path) or tostring(info)
|
||||||
local colour = mode == "image" and 0x00FFFF or 0x0000FF
|
local colour = mode == "image" and 5 or 4
|
||||||
syscall.devctl(1, "sfgc", 0x00FF00)
|
syscall.devctl(1, "sfgc", 3)
|
||||||
printInline(string.format("%-10s", id))
|
printInline(string.format("%-10s", id))
|
||||||
syscall.devctl(1, "sfgc", colour)
|
syscall.devctl(1, "sfgc", colour)
|
||||||
printInline(string.format("%-7s", "["..mode.."]"))
|
printInline(string.format("%-7s", "["..mode.."]"))
|
||||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
syscall.devctl(1, "sfgc", 1)
|
||||||
print(" "..path)
|
print(" "..path)
|
||||||
end
|
end
|
||||||
if not any then
|
if not any then
|
||||||
syscall.devctl(1, "sfgc", 0x6D00FF)
|
syscall.devctl(1, "sfgc", 14)
|
||||||
print(name..": no loop devices attached")
|
print(name..": no loop devices attached")
|
||||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
syscall.devctl(1, "sfgc", 1)
|
||||||
end
|
end
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -92,9 +92,9 @@ if opts.d then
|
|||||||
end
|
end
|
||||||
print(name..": "..msg); syscall.exit(1); return
|
print(name..": "..msg); syscall.exit(1); return
|
||||||
end
|
end
|
||||||
syscall.devctl(1, "sfgc", 0x00FFFF)
|
syscall.devctl(1, "sfgc", 10)
|
||||||
print(name..": detached "..id)
|
print(name..": detached "..id)
|
||||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
syscall.devctl(1, "sfgc", 1)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -136,26 +136,26 @@ if cloptions.l then
|
|||||||
printInline(tostring(mtime) .. " ")
|
printInline(tostring(mtime) .. " ")
|
||||||
|
|
||||||
if isSym then
|
if isSym then
|
||||||
syscall.devctl(1, "sfgc", 0xFF00FF)
|
syscall.devctl(1, "sfgc", 6)
|
||||||
printInline(v)
|
printInline(v)
|
||||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
syscall.devctl(1, "sfgc", 1)
|
||||||
local ok, target = pcall(syscall.readlink, fullPath)
|
local ok, target = pcall(syscall.readlink, fullPath)
|
||||||
if ok then
|
if ok then
|
||||||
printInline(" -> ")
|
printInline(" -> ")
|
||||||
local targetExists = pcall(syscall.stat, fullPath)
|
local targetExists = pcall(syscall.stat, fullPath)
|
||||||
syscall.devctl(1, "sfgc", targetExists and 0xFF00FF or 0xFF0000)
|
syscall.devctl(1, "sfgc", targetExists and 6 or 2)
|
||||||
printInline(target)
|
printInline(target)
|
||||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
syscall.devctl(1, "sfgc", 1)
|
||||||
end
|
end
|
||||||
elseif isDir then
|
elseif isDir then
|
||||||
syscall.devctl(1, "sfgc", 0x6D00FF)
|
syscall.devctl(1, "sfgc", 14)
|
||||||
printInline(v)
|
printInline(v)
|
||||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
syscall.devctl(1, "sfgc", 1)
|
||||||
else
|
else
|
||||||
local isExec = stat and stat.perms and (math.floor(stat.perms / (2^9)) % 2 == 1)
|
local isExec = stat and stat.perms and (math.floor(stat.perms / (2^9)) % 2 == 1)
|
||||||
syscall.devctl(1, "sfgc", isExec and 0x00FF00 or 0xFFFFFF)
|
syscall.devctl(1, "sfgc", isExec and 3 or 1)
|
||||||
printInline(v)
|
printInline(v)
|
||||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
syscall.devctl(1, "sfgc", 1)
|
||||||
end
|
end
|
||||||
print("")
|
print("")
|
||||||
end
|
end
|
||||||
@@ -175,16 +175,16 @@ for i, v in ipairs(list) do
|
|||||||
local isSym = stat and stat.etype == 0x01
|
local isSym = stat and stat.etype == 0x01
|
||||||
|
|
||||||
if isSym then
|
if isSym then
|
||||||
syscall.devctl(1, "sfgc", 0xFF00FF)
|
syscall.devctl(1, "sfgc", 6)
|
||||||
elseif isDir then
|
elseif isDir then
|
||||||
syscall.devctl(1, "sfgc", 0x6D00FF)
|
syscall.devctl(1, "sfgc", 14)
|
||||||
else
|
else
|
||||||
local isExec = stat and stat.perms and (math.floor(stat.perms / (2^9)) % 2 == 1)
|
local isExec = stat and stat.perms and (math.floor(stat.perms / (2^9)) % 2 == 1)
|
||||||
syscall.devctl(1, "sfgc", isExec and 0x00FF00 or 0xFFFFFF)
|
syscall.devctl(1, "sfgc", isExec and 3 or 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
printInline(v)
|
printInline(v)
|
||||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
syscall.devctl(1, "sfgc", 1)
|
||||||
printInline((" "):rep(colWidth - #v))
|
printInline((" "):rep(colWidth - #v))
|
||||||
|
|
||||||
if i % numCols == 0 then print("") end
|
if i % numCols == 0 then print("") end
|
||||||
|
|||||||
@@ -5,15 +5,15 @@ if not users or #users == 0 then
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
syscall.devctl(1,"sfgc",0xDBDBDB)
|
syscall.devctl(1,"sfgc",13)
|
||||||
print(string.format("%-6s %-6s %-16s %-20s %s", "UID", "GID", "Username", "Home", "Shell"))
|
print(string.format("%-6s %-6s %-16s %-20s %s", "UID", "GID", "Username", "Home", "Shell"))
|
||||||
print(string.rep("-", 65))
|
print(string.rep("-", 65))
|
||||||
syscall.devctl(1,"sfgc",0xFFFFFF)
|
syscall.devctl(1,"sfgc",1)
|
||||||
|
|
||||||
for _, u in ipairs(users) do
|
for _, u in ipairs(users) do
|
||||||
local lock_marker = u.locked and " [locked]" or ""
|
local lock_marker = u.locked and " [locked]" or ""
|
||||||
if u.locked then syscall.devctl(1,"sfgc",0xFF0000) end
|
if u.locked then syscall.devctl(1,"sfgc",2) end
|
||||||
print(string.format("%-6d %-6d %-16s %-20s %s%s",
|
print(string.format("%-6d %-6d %-16s %-20s %s%s",
|
||||||
u.uid, u.gid, u.username, u.homedir, u.shell, lock_marker))
|
u.uid, u.gid, u.username, u.homedir, u.shell, lock_marker))
|
||||||
if u.locked then syscall.devctl(1,"sfgc",0xFFFFFF) end
|
if u.locked then syscall.devctl(1,"sfgc",1) end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -69,17 +69,17 @@ if #args == 0 and not opts.o then
|
|||||||
end
|
end
|
||||||
|
|
||||||
if next(loDevs) == nil then
|
if next(loDevs) == nil then
|
||||||
syscall.devctl(1, "sfgc", 0xFF00FF)
|
syscall.devctl(1, "sfgc", 14)
|
||||||
print("(no loop devices attached)")
|
print("(no loop devices attached)")
|
||||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
syscall.devctl(1, "sfgc", 1)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
for id, info in pairs(loDevs) do
|
for id, info in pairs(loDevs) do
|
||||||
local colour = info.mode == "image" and 0x00FFFF or 0x0000FF
|
local colour = info.mode == "image" and 5 or 4
|
||||||
syscall.devctl(1, "sfgc", colour)
|
syscall.devctl(1, "sfgc", colour)
|
||||||
printInline(info.mode.." "..id)
|
printInline(info.mode.." "..id)
|
||||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
syscall.devctl(1, "sfgc", 1)
|
||||||
print(" on "..info.path)
|
print(" on "..info.path)
|
||||||
end
|
end
|
||||||
return
|
return
|
||||||
@@ -119,9 +119,9 @@ if opts.o and opts.o:lower() == "loop" then
|
|||||||
print(name..": mount: "..msg); syscall.exit(1); return
|
print(name..": mount: "..msg); syscall.exit(1); return
|
||||||
end
|
end
|
||||||
|
|
||||||
syscall.devctl(1, "sfgc", 0x00FFFF)
|
syscall.devctl(1, "sfgc", 10)
|
||||||
print(name..": "..loopId.." mounted at "..dest)
|
print(name..": "..loopId.." mounted at "..dest)
|
||||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
syscall.devctl(1, "sfgc", 1)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -141,9 +141,9 @@ if #args == 2 then
|
|||||||
print(name..": "..msg); syscall.exit(1); return
|
print(name..": "..msg); syscall.exit(1); return
|
||||||
end
|
end
|
||||||
|
|
||||||
syscall.devctl(1, "sfgc", 0x00FFFF)
|
syscall.devctl(1, "sfgc", 10)
|
||||||
print(name..": "..loopId.." mounted at "..dest)
|
print(name..": "..loopId.." mounted at "..dest)
|
||||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
syscall.devctl(1, "sfgc", 1)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
--:Minify:--
|
--:Minify:--
|
||||||
local targetUser = ({ ... })[1]
|
local targetUser = ({ ... })[1]
|
||||||
local currentUid = syscall.getuid()
|
local currentUid = syscall.getuid()
|
||||||
if syscall.geteuid()~=0 then
|
|
||||||
syscall.exec("/bin/su", {...})
|
|
||||||
end
|
|
||||||
local targetUid
|
local targetUid
|
||||||
if targetUser then
|
if targetUser then
|
||||||
targetUid = syscall.getuidbyname(targetUser)
|
targetUid = syscall.getuidbyname(targetUser)
|
||||||
|
|||||||
@@ -59,9 +59,9 @@ if opts.l then
|
|||||||
end
|
end
|
||||||
print(name..": "..msg); syscall.exit(1); return
|
print(name..": "..msg); syscall.exit(1); return
|
||||||
end
|
end
|
||||||
syscall.devctl(1, "sfgc", 0x00FFFF)
|
syscall.devctl(1, "sfgc", 10)
|
||||||
print(name..": detached "..id)
|
print(name..": detached "..id)
|
||||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
syscall.devctl(1, "sfgc", 1)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -95,17 +95,17 @@ if not ok then
|
|||||||
print(name..": "..msg); syscall.exit(1); return
|
print(name..": "..msg); syscall.exit(1); return
|
||||||
end
|
end
|
||||||
|
|
||||||
syscall.devctl(1, "sfgc", 0x00FFFF)
|
syscall.devctl(1, "sfgc", 10)
|
||||||
print(name..": unmounted "..mpt)
|
print(name..": unmounted "..mpt)
|
||||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
syscall.devctl(1, "sfgc", 1)
|
||||||
|
|
||||||
if loopIdToDetach then
|
if loopIdToDetach then
|
||||||
for _, id in ipairs(loopIdToDetach) do
|
for _, id in ipairs(loopIdToDetach) do
|
||||||
local dok = pcall(syscall.lodetach, id)
|
local dok = pcall(syscall.lodetach, id)
|
||||||
if dok then
|
if dok then
|
||||||
syscall.devctl(1, "sfgc", 0xFF00FF)
|
syscall.devctl(1, "sfgc", 14)
|
||||||
print(name..": auto-detached "..id)
|
print(name..": auto-detached "..id)
|
||||||
syscall.devctl(1, "sfgc", 0xFFFFFF)
|
syscall.devctl(1, "sfgc", 1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
--:Minify:--
|
|
||||||
local ini = {}
|
local ini = {}
|
||||||
|
|
||||||
function ini.parse(str)
|
function ini.parse(str)
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
--:Minify:--
|
--:Minify:--
|
||||||
local C_PROMPT = 0xFFFF00
|
local C_PROMPT = 7
|
||||||
local C_CONT = 0xDBDBDB
|
local C_CONT = 13
|
||||||
local C_OUT = 0x00FFFF
|
local C_OUT = 5
|
||||||
local C_ERR = 0xFF0000
|
local C_ERR = 2
|
||||||
local C_KEY = 0x00FF00
|
local C_KEY = 3
|
||||||
local C_STR = 0x00FF88
|
local C_STR = 9
|
||||||
local C_NUM = 0x24FFFF
|
local C_NUM = 10
|
||||||
local C_BOOL = 0xFF6D00
|
local C_BOOL = 8
|
||||||
local C_NIL = 0x6D6D6D
|
local C_NIL = 12
|
||||||
local C_TABLE = 0xDBDBDB
|
local C_TABLE = 13
|
||||||
|
|
||||||
local function c(col) syscall.devctl(1, "sfgc", col) end
|
local function c(col) syscall.devctl(1, "sfgc", col) end
|
||||||
local function w(s) syscall.write(1, tostring(s)) end
|
local function w(s) syscall.write(1, tostring(s)) end
|
||||||
@@ -250,9 +250,9 @@ local function getUserInput(prompt, history)
|
|||||||
local function redraw()
|
local function redraw()
|
||||||
syscall.devctl(1, "spos", ox, oy)
|
syscall.devctl(1, "spos", ox, oy)
|
||||||
w(input:sub(1, cursor-1))
|
w(input:sub(1, cursor-1))
|
||||||
if blink then syscall.devctl(1,"sfgc",0x000000); syscall.devctl(1,"sbgc",1) end
|
if blink then syscall.devctl(1,"sfgc",16); syscall.devctl(1,"sbgc",1) end
|
||||||
w(cursor > #input and " " or input:sub(cursor, cursor))
|
w(cursor > #input and " " or input:sub(cursor, cursor))
|
||||||
syscall.devctl(1,"sfgc",0xFFFFFF); syscall.devctl(1,"sbgc",16)
|
syscall.devctl(1,"sfgc",1); syscall.devctl(1,"sbgc",16)
|
||||||
w(input:sub(cursor+1) .. " ")
|
w(input:sub(cursor+1) .. " ")
|
||||||
dirty = false
|
dirty = false
|
||||||
end
|
end
|
||||||
@@ -284,7 +284,7 @@ local function getUserInput(prompt, history)
|
|||||||
cursor = cursor - 1; dirty = true
|
cursor = cursor - 1; dirty = true
|
||||||
end
|
end
|
||||||
elseif key == "\n" then
|
elseif key == "\n" then
|
||||||
syscall.devctl(1,"sfgc",0xFFFFFF); syscall.devctl(1,"sbgc",16)
|
syscall.devctl(1,"sfgc",1); syscall.devctl(1,"sbgc",16)
|
||||||
syscall.devctl(1,"spos",ox,oy)
|
syscall.devctl(1,"spos",ox,oy)
|
||||||
w(input .. " \n")
|
w(input .. " \n")
|
||||||
return input
|
return input
|
||||||
|
|||||||
@@ -135,16 +135,16 @@ local function pad(s, w)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function drawTop()
|
local function drawTop()
|
||||||
tpos(1,1); tbg(0x0000FF); tfg(0x000000)
|
tpos(1,1); tbg(4); tfg(16)
|
||||||
local left = " edit" .. (fname and (" - "..fname) or "")
|
local left = " edit" .. (fname and (" - "..fname) or "")
|
||||||
if dirty then left = left .. " [+]" end
|
if dirty then left = left .. " [+]" end
|
||||||
local right = tostring(cy)..","..tostring(cx).." "
|
local right = tostring(cy)..","..tostring(cx).." "
|
||||||
twrite(pad(left..string.rep(" ", math.max(1, W-#left-#right))..right, W))
|
twrite(pad(left..string.rep(" ", math.max(1, W-#left-#right))..right, W))
|
||||||
tbg(0x000000); tfg(0xFFFFFF)
|
tbg(16); tfg(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function drawBottom()
|
local function drawBottom()
|
||||||
tpos(1, H); tbg(0x0000FF); tfg(0x000000)
|
tpos(1, H); tbg(4); tfg(16)
|
||||||
if msg ~= "" then
|
if msg ~= "" then
|
||||||
if msgErr then tbg(2) end
|
if msgErr then tbg(2) end
|
||||||
twrite(pad(" "..msg, W))
|
twrite(pad(" "..msg, W))
|
||||||
@@ -152,7 +152,7 @@ local function drawBottom()
|
|||||||
else
|
else
|
||||||
twrite(pad(" ^W Save ^X Quit+Save ^P Quit ^K Cut ^U Paste ^F Find ^G Go", W))
|
twrite(pad(" ^W Save ^X Quit+Save ^P Quit ^K Cut ^U Paste ^F Find ^G Go", W))
|
||||||
end
|
end
|
||||||
tbg(0x000000); tfg(0xFFFFFF)
|
tbg(16); tfg(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function drawLines(map)
|
local function drawLines(map)
|
||||||
@@ -177,29 +177,29 @@ local function drawLines(map)
|
|||||||
local curCh = ci > #seg and " " or seg:sub(ci, ci)
|
local curCh = ci > #seg and " " or seg:sub(ci, ci)
|
||||||
local after = seg:sub(ci+1)
|
local after = seg:sub(ci+1)
|
||||||
|
|
||||||
tfg(0xFFFFFF); tbg(0x000000); twrite(before)
|
tfg(1); tbg(16); twrite(before)
|
||||||
if blinkState then tfg(0x000000); tbg(0xFFFFFF) else tfg(0xFFFFFF); tbg(0x000000) end
|
if blinkState then tfg(16); tbg(1) else tfg(1); tbg(16) end
|
||||||
twrite(curCh)
|
twrite(curCh)
|
||||||
tfg(0xFFFFFF); tbg(0x000000); twrite(after)
|
tfg(1); tbg(16); twrite(after)
|
||||||
local drawn = #before + 1 + #after
|
local drawn = #before + 1 + #after
|
||||||
if drawn < W then twrite(string.rep(" ", W - drawn)) end
|
if drawn < W then twrite(string.rep(" ", W - drawn)) end
|
||||||
else
|
else
|
||||||
if li == sLine and sPat ~= "" and entry[2] == 1 then
|
if li == sLine and sPat ~= "" and entry[2] == 1 then
|
||||||
local s, e = seg:find(sPat)
|
local s, e = seg:find(sPat)
|
||||||
if s then
|
if s then
|
||||||
tfg(0xFFFFFF); tbg(0x000000); twrite(seg:sub(1,s-1))
|
tfg(1); tbg(16); twrite(seg:sub(1,s-1))
|
||||||
tfg(0x000000); tbg(0x00FF00); twrite(seg:sub(s,e))
|
tfg(16); tbg(3); twrite(seg:sub(s,e))
|
||||||
tfg(0xFFFFFF); tbg(0x000000); twrite(seg:sub(e+1))
|
tfg(1); tbg(16); twrite(seg:sub(e+1))
|
||||||
twrite(string.rep(" ", W - #seg))
|
twrite(string.rep(" ", W - #seg))
|
||||||
else
|
else
|
||||||
tfg(0xFFFFFF); tbg(0x000000); twrite(pad(seg, W))
|
tfg(1); tbg(16); twrite(pad(seg, W))
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
tfg(0xFFFFFF); tbg(0x000000); twrite(pad(seg, W))
|
tfg(1); tbg(16); twrite(pad(seg, W))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
tfg(0xDBDBDB); tbg(0x000000); twrite(pad("~", W)); tfg(0xFFFFFF)
|
tfg(13); tbg(16); twrite(pad("~", W)); tfg(1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -212,15 +212,15 @@ local function redraw()
|
|||||||
drawLines(map)
|
drawLines(map)
|
||||||
drawBottom()
|
drawBottom()
|
||||||
tpos(1, H)
|
tpos(1, H)
|
||||||
tbg(0x000000); tfg(0xFFFFFF)
|
tbg(16); tfg(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function prompt(label, default)
|
local function prompt(label, default)
|
||||||
local inp = default or ""
|
local inp = default or ""
|
||||||
while true do
|
while true do
|
||||||
tpos(1, H); tbg(0x00FF00); tfg(0x000000)
|
tpos(1, H); tbg(3); tfg(16)
|
||||||
twrite(pad(" "..label..inp.." ", W))
|
twrite(pad(" "..label..inp.." ", W))
|
||||||
tbg(0x000000); tfg(0xFFFFFF)
|
tbg(16); tfg(1)
|
||||||
local key = syscall.read(0)
|
local key = syscall.read(0)
|
||||||
if not key or key == "" then sleep(0.02)
|
if not key or key == "" then sleep(0.02)
|
||||||
elseif key == "" then return nil
|
elseif key == "" then return nil
|
||||||
@@ -415,5 +415,5 @@ while running do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
tclear(); tfg(0xFFFFFF); tbg(0x000000); tpos(1,1)
|
tclear(); tfg(1); tbg(16); tpos(1,1)
|
||||||
print("edit: exited"..(fname and (" - "..fname) or ""))
|
print("edit: exited"..(fname and (" - "..fname) or ""))
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
--:Minify:--
|
--:Minify:--
|
||||||
local kernel=...
|
local kernel=...
|
||||||
local fs=require("fs")
|
local fs=require("fs")
|
||||||
kernel.log("Sysinit started...")
|
|
||||||
|
|
||||||
for i,v in pairs(kernel.processes) do
|
for i,v in pairs(kernel.processes) do
|
||||||
kernel.log("Spawning kernel task "..i)
|
kernel.log("Spawning kernel task "..i)
|
||||||
syscall.spawn(function()
|
syscall.spawn(function()
|
||||||
local status, err = pcall(v)
|
local status, err = pcall(v)
|
||||||
if not status then
|
if not status then
|
||||||
kernel.log("Error executing kernel task '" .. i .. "': " .. err, "ERROR", 0xFF0000)
|
kernel.log("Error executing kernel task '" .. i .. "': " .. err, "ERROR")
|
||||||
else
|
else
|
||||||
kernel.log("Successfully executed kernel task: " .. i)
|
kernel.log("Successfully executed kernel task: " .. i, "INFO")
|
||||||
end
|
end
|
||||||
end, i)
|
end, i)
|
||||||
end
|
end
|
||||||
@@ -18,24 +17,23 @@ end
|
|||||||
if not fs.exists("/bin/startup") then
|
if not fs.exists("/bin/startup") then
|
||||||
fs.mkdir("/bin/startup")
|
fs.mkdir("/bin/startup")
|
||||||
end
|
end
|
||||||
|
|
||||||
local files = fs.list("/bin/startup")
|
local files = fs.list("/bin/startup")
|
||||||
if not files then error("Failed to list /bin/startup") end
|
if not files then error("Failed to list /bin/startup") end
|
||||||
for i,v in ipairs(files) do
|
for i,v in ipairs(files) do
|
||||||
if v:sub(-4) == ".lua" then
|
if v:sub(-4) == ".lua" then
|
||||||
local filepath = "/bin/startup/" .. v
|
local filepath = "/bin/startup/" .. v
|
||||||
kernel.log("Executing startup script: " .. filepath)
|
kernel.log("Executing startup script: " .. filepath, "INFO")
|
||||||
local startupFunc, err = load(fs.readAllText(filepath), "@" .. filepath)
|
local startupFunc, err = load(fs.readAllText(filepath), "@" .. filepath)
|
||||||
if not startupFunc then
|
if not startupFunc then
|
||||||
kernel.log("Error loading startup script '" .. filepath .. "': " .. err, "ERROR", 0xFF0000)
|
kernel.log("Error loading startup script '" .. filepath .. "': " .. err, "ERROR")
|
||||||
else
|
else
|
||||||
syscall.spawn(function()
|
syscall.spawn(function()
|
||||||
syscall.setuid(1)
|
syscall.setuid(1)
|
||||||
local status, err = pcall(startupFunc)
|
local status, err = pcall(startupFunc)
|
||||||
if not status then
|
if not status then
|
||||||
kernel.log("Error executing startup script '" .. filepath .. "': " .. err, "ERROR", 0xFF0000)
|
kernel.log("Error executing startup script '" .. filepath .. "': " .. err, "ERROR")
|
||||||
else
|
else
|
||||||
kernel.log("Successfully executed startup script: " .. filepath)
|
kernel.log("Successfully executed startup script: " .. filepath, "INFO")
|
||||||
end
|
end
|
||||||
end, "startup:" .. v)
|
end, "startup:" .. v)
|
||||||
end
|
end
|
||||||
|
|||||||
8
build.py
8
build.py
@@ -74,7 +74,7 @@ def compress_lz4(data: bytes) -> bytes:
|
|||||||
return lz4.frame.compress(data)
|
return lz4.frame.compress(data)
|
||||||
|
|
||||||
|
|
||||||
def process_root(src_root: Path, out_root: Path, minify: bool, micro: bool, arch:Union[str, None]):
|
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()
|
||||||
@@ -83,10 +83,6 @@ def process_root(src_root: Path, out_root: Path, minify: bool, micro: bool, arch
|
|||||||
if not pkg_dir.is_dir():
|
if not pkg_dir.is_dir():
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if pkg_dir.name[:18] == "Hyperion-firmware-":
|
|
||||||
if pkg_dir.name != f"Hyperion-firmware-{arch}":
|
|
||||||
continue
|
|
||||||
|
|
||||||
print(f"== Package: {pkg_dir.name} ==")
|
print(f"== Package: {pkg_dir.name} ==")
|
||||||
|
|
||||||
for src in sorted(pkg_dir.rglob("*")):
|
for src in sorted(pkg_dir.rglob("*")):
|
||||||
@@ -138,7 +134,7 @@ def run_build(minify: bool, micro: bool, include_test: bool, arch: Union[str, No
|
|||||||
|
|
||||||
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, micro, arch)
|
process_root(SRC_ROOT, out_root, minify, micro)
|
||||||
if include_test:
|
if include_test:
|
||||||
process_root(TEST_ROOT, out_root, minify, micro)
|
process_root(TEST_ROOT, out_root, minify, micro)
|
||||||
|
|
||||||
|
|||||||
BIN
install/data/Build.tar
Normal file
BIN
install/data/Build.tar
Normal file
Binary file not shown.
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
local function octal_to_number(str)
|
local function octal_to_number(str)
|
||||||
str = str:gsub("%z", ""):match("^%s*(.-)%s*$")
|
str = str:gsub("%z", ""):match("^%s*(.-)%s*$")
|
||||||
return tonumber(str, 8) or 0
|
return tonumber(str, 8) or 0
|
||||||
@@ -98,16 +97,16 @@ local function unpack_tar(tarstr)
|
|||||||
local pad = (512 - (size % 512)) % 512
|
local pad = (512 - (size % 512)) % 512
|
||||||
i = i + size + pad
|
i = i + size + pad
|
||||||
|
|
||||||
if name == "" then goto continue end
|
if name ~= "" then
|
||||||
|
|
||||||
local is_dir = typeflag == "5" or name:sub(-1) == "/"
|
local is_dir = typeflag == "5" or name:sub(-1) == "/"
|
||||||
|
|
||||||
local clean_name = name:gsub("/$", "")
|
local clean_name = name:gsub("/$", "")
|
||||||
if clean_name == "" then goto continue end
|
|
||||||
|
if clean_name ~= "" then
|
||||||
|
|
||||||
local parent_path = clean_name:match("(.+)/")
|
local parent_path = clean_name:match("(.+)/")
|
||||||
local fname = clean_name:match("([^/]+)$")
|
local fname = clean_name:match("([^/]+)$")
|
||||||
if not fname then goto continue end
|
if not fname then
|
||||||
|
|
||||||
local parent = root
|
local parent = root
|
||||||
if parent_path then
|
if parent_path then
|
||||||
@@ -119,8 +118,9 @@ local function unpack_tar(tarstr)
|
|||||||
else
|
else
|
||||||
parent[fname] = { __type = "file", __contents = contents }
|
parent[fname] = { __type = "file", __contents = contents }
|
||||||
end
|
end
|
||||||
|
end
|
||||||
::continue::
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return flatten(root)
|
return flatten(root)
|
||||||
21
install/installcc.lua
Normal file
21
install/installcc.lua
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
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
|
||||||
@@ -1,189 +0,0 @@
|
|||||||
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/cct/installdata/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 and 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 handle=http.get("https://git.astronand.dev/api/v1/repos/Hyperion/HyperionOS/releases?page="..tostring(page).."&limit=1")
|
|
||||||
local raw=handle.readAll()
|
|
||||||
handle.close()
|
|
||||||
if raw=="[]\n" then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
releases[page]=json.decode(raw)[1]
|
|
||||||
page=page+1
|
|
||||||
end
|
|
||||||
|
|
||||||
local function makePage(start, num)
|
|
||||||
local m={}
|
|
||||||
for i=start, num do
|
|
||||||
if not releases[i] then 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/installcct.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","t",_ENV)
|
|
||||||
data.close()
|
|
||||||
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
|
|
||||||
exitall=true
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
|
||||||
if #releases>start+num then
|
|
||||||
m[#m+1]={
|
|
||||||
name="Next",
|
|
||||||
desc="Next menu",
|
|
||||||
color=colors.cyan,
|
|
||||||
func=function()
|
|
||||||
local menudata=makePage(start+num, num)
|
|
||||||
menu(menudata)
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
|
||||||
return m
|
|
||||||
end
|
|
||||||
|
|
||||||
menu(makePage(1,5))
|
|
||||||
term.clear()
|
|
||||||
term.setCursorPos(1,1)
|
|
||||||
term.setTextColor(colors.white)
|
|
||||||
term.write("Formating disk in ")
|
|
||||||
for i=5, 1, -1 do
|
|
||||||
term.write(tostring(i))
|
|
||||||
sleep(.25)
|
|
||||||
for v=1, 3 do
|
|
||||||
term.write(".")
|
|
||||||
sleep(.25)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
print("")
|
|
||||||
|
|
||||||
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
|
|
||||||
sleep(.01)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
delDir("/")
|
|
||||||
term.clear()
|
|
||||||
term.setCursorPos(1,1)
|
|
||||||
term.setTextColor(colors.white)
|
|
||||||
install(releasename)
|
|
||||||
15
manifest.lua
15
manifest.lua
@@ -144,13 +144,8 @@ syscall.dup=function(fd) end
|
|||||||
|
|
||||||
--- Read GPIO pin
|
--- Read GPIO pin
|
||||||
--- @param pin integer
|
--- @param pin integer
|
||||||
--- @return boolean|nil
|
|
||||||
syscall.gpio_read=function(pin) end
|
|
||||||
|
|
||||||
--- Read GPIO pin analog
|
|
||||||
--- @param pin integer
|
|
||||||
--- @return number|nil
|
--- @return number|nil
|
||||||
syscall.gpio_readAnalog=function(pin) end
|
syscall.gpio_read=function(pin) end
|
||||||
|
|
||||||
--- Get SUID bit from fd
|
--- Get SUID bit from fd
|
||||||
--- @param fd integer
|
--- @param fd integer
|
||||||
@@ -159,13 +154,9 @@ syscall.fget_suid=function(fd) end
|
|||||||
|
|
||||||
--- Write GPIO pin
|
--- Write GPIO pin
|
||||||
--- @param pin integer
|
--- @param pin integer
|
||||||
--- @param data boolean
|
|
||||||
syscall.gpio_write=function(pin, data) end
|
|
||||||
|
|
||||||
--- Write GPIO pin analog
|
|
||||||
--- @param pin integer
|
|
||||||
--- @param data number
|
--- @param data number
|
||||||
syscall.gpio_writeAnalog=function(pin, data) end
|
--- @return boolean
|
||||||
|
syscall.gpio_write=function(pin, data) end
|
||||||
|
|
||||||
--- Set password for user
|
--- Set password for user
|
||||||
--- @param uid integer
|
--- @param uid integer
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
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/installdata/tarbad /tar.lua")
|
|
||||||
print("Installing HyperionOS...")
|
|
||||||
print("Installing precompiled tar")
|
|
||||||
shell.run("wget https://git.astronand.dev/Hyperion/HyperionOS/raw/tag/"..release.."/misc/cct/installdata/Build.tar /Build.tar")
|
|
||||||
shell.run("tar Build.tar /")
|
|
||||||
sleep(1)
|
|
||||||
print("Removing tar but bad...")
|
|
||||||
shell.run("rm /tar.lua")
|
|
||||||
shell.run("rm $")
|
|
||||||
shell.run("rm Build.tar")
|
|
||||||
shell.run("cp Build $")
|
|
||||||
shell.run("rm Build")
|
|
||||||
fs.copy("/$/boot/cct/eeprom","/startup.lua")
|
|
||||||
print("Installing...")
|
|
||||||
sleep(1)
|
|
||||||
dofile("startup.lua")
|
|
||||||
Binary file not shown.
@@ -1,388 +0,0 @@
|
|||||||
--: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
|
|
||||||
Reference in New Issue
Block a user