working on require needs to be done before EOW
This commit is contained in:
18
LICENSE
Normal file
18
LICENSE
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2025 Astronand
|
||||||
|
|
||||||
|
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.
|
||||||
34
docs/api/drivers/fs.txt
Normal file
34
docs/api/drivers/fs.txt
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
readAllText(dir) Returns string:contents
|
||||||
|
reads all text from directory on disk
|
||||||
|
|
||||||
|
writeAllText(dir, content) Returns nil
|
||||||
|
writes all content to file
|
||||||
|
|
||||||
|
appendAllText(dir, content) Returns nil
|
||||||
|
appends all content to file
|
||||||
|
|
||||||
|
getAtributes(dir) Returns table:atributes
|
||||||
|
returns atributes of a file or directory
|
||||||
|
|
||||||
|
list(dir) Returns table:files
|
||||||
|
returns contents of directory
|
||||||
|
|
||||||
|
mkdir(dir) Returns nil
|
||||||
|
makes specified directory
|
||||||
|
|
||||||
|
mkfile(dir) Returns nil
|
||||||
|
makes specified file
|
||||||
|
|
||||||
|
-------------------------------------------------------
|
||||||
|
Atributes table
|
||||||
|
number:size
|
||||||
|
size of file in bytes
|
||||||
|
|
||||||
|
number:owner
|
||||||
|
owner UUID
|
||||||
|
|
||||||
|
number:group
|
||||||
|
group UUID
|
||||||
|
|
||||||
|
number:perms
|
||||||
|
file perms 0-21
|
||||||
16
docs/api/drivers/readme.md
Normal file
16
docs/api/drivers/readme.md
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# drivers
|
||||||
|
---
|
||||||
|
|
||||||
|
## driver types
|
||||||
|
---
|
||||||
|
|
||||||
|
```
|
||||||
|
http - internet
|
||||||
|
lan - local networks
|
||||||
|
fs - filesystems
|
||||||
|
disk - normal disks
|
||||||
|
udisk - byte array disks
|
||||||
|
terminal - screens that only support text
|
||||||
|
```
|
||||||
|
|
||||||
|
### Driver APIS
|
||||||
8
docs/api/drivers/terminal.txt
Normal file
8
docs/api/drivers/terminal.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
print(text) Returns nil
|
||||||
|
Prints text to the terminal with a trailing \n
|
||||||
|
|
||||||
|
printInline(text) Returns nil
|
||||||
|
Same as print without the trailing \n
|
||||||
|
|
||||||
|
clear() Returns nil
|
||||||
|
Clears screen
|
||||||
0
docs/api/kernel.txt
Normal file
0
docs/api/kernel.txt
Normal file
188
src/computers/0/bios.lua
Normal file
188
src/computers/0/bios.lua
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
local computer = component.getFirst("computer")
|
||||||
|
local screen=component.getFirst("screen")
|
||||||
|
if not screen then
|
||||||
|
local function e(...)end
|
||||||
|
screen = {
|
||||||
|
print=e,
|
||||||
|
printInline=e,
|
||||||
|
clear=e
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
local ok,err = xpcall(function()
|
||||||
|
-- Init components
|
||||||
|
_G._DEVELOPMENT=true
|
||||||
|
_G.component=component
|
||||||
|
|
||||||
|
local printed=""
|
||||||
|
local print=function(text)
|
||||||
|
printed=printed..text.."\n"
|
||||||
|
screen.print(text)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Get CFG
|
||||||
|
local biosCfg = {}
|
||||||
|
local i=1
|
||||||
|
while i<=256 do
|
||||||
|
biosCfg[i]=computer.getData(i) or ""
|
||||||
|
i=i+1
|
||||||
|
end
|
||||||
|
computer.beep(800,0.2)
|
||||||
|
|
||||||
|
local function deepcopy(orig, copies)
|
||||||
|
copies = copies or {}
|
||||||
|
|
||||||
|
if type(orig) ~= 'table' then
|
||||||
|
return orig
|
||||||
|
elseif copies[orig] then
|
||||||
|
return copies[orig]
|
||||||
|
end
|
||||||
|
|
||||||
|
local copy = {}
|
||||||
|
copies[orig] = copy
|
||||||
|
|
||||||
|
for k, v in next, orig, nil do
|
||||||
|
local copied_key = deepcopy(k, copies)
|
||||||
|
local copied_val = deepcopy(v, copies)
|
||||||
|
copy[copied_key] = copied_val
|
||||||
|
end
|
||||||
|
|
||||||
|
return copy
|
||||||
|
end
|
||||||
|
|
||||||
|
local function save(table)
|
||||||
|
while i<=256 do
|
||||||
|
computer.setData(i, table[i] or nil)
|
||||||
|
i=i+1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function hasKey(tabl, query)
|
||||||
|
for i,v in pairs(tabl) do
|
||||||
|
if i==query then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Start boot seq
|
||||||
|
local disks={}
|
||||||
|
for i,v in component.list() do
|
||||||
|
if i=="disk" then
|
||||||
|
disks[v.id]=v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local idx = 1
|
||||||
|
local bootOption=1
|
||||||
|
while true do
|
||||||
|
if biosCfg[idx]=="$EOF" then break end
|
||||||
|
print("Atempting boot option "..tostring(bootOption).." labled \""..biosCfg[idx].."\".")
|
||||||
|
bootOption=bootOption+1
|
||||||
|
local drive={}
|
||||||
|
idx=idx+1
|
||||||
|
if not hasKey(disks,biosCfg[idx]) then
|
||||||
|
print("└─ Drive not found.")
|
||||||
|
print(" ")
|
||||||
|
idx=idx+3
|
||||||
|
goto invalid_boot
|
||||||
|
else
|
||||||
|
drive=disks[biosCfg[idx]]
|
||||||
|
print("├─ Drive found with id of \""..drive.id.."\"")
|
||||||
|
end
|
||||||
|
idx=idx+1
|
||||||
|
local path
|
||||||
|
local code
|
||||||
|
if drive.type=="udd" then
|
||||||
|
print("├─ Drive is Unmanaged, looking for MBR...")
|
||||||
|
sleep(0.02)
|
||||||
|
print("├─ Reading MBR...")
|
||||||
|
local tmp = drive.readBytes(0,512)
|
||||||
|
print("├─ MBR found, compiling bootloader...")
|
||||||
|
code = table.concat(tmp)
|
||||||
|
else
|
||||||
|
if not drive:fileExists(biosCfg[idx]) then
|
||||||
|
print("└─ Path not found.")
|
||||||
|
print(" ")
|
||||||
|
idx=idx+2
|
||||||
|
goto invalid_boot
|
||||||
|
else
|
||||||
|
print("├─ Kernel exists at path \""..biosCfg[idx].."\"")
|
||||||
|
path=biosCfg[idx]
|
||||||
|
end
|
||||||
|
code = drive:open(path).read()
|
||||||
|
end
|
||||||
|
idx=idx+1
|
||||||
|
_VG=deepcopy(_G)
|
||||||
|
print("├─ Created virtual ENV.")
|
||||||
|
local _,func = pcall(load,code,drive.id.." | "..path,nil,_G)
|
||||||
|
if not func then
|
||||||
|
print("└─ Compilation failure.")
|
||||||
|
print(" ")
|
||||||
|
idx=idx+1
|
||||||
|
goto invalid_boot
|
||||||
|
else
|
||||||
|
print("├─ Executing.")
|
||||||
|
end
|
||||||
|
local cmd=biosCfg[idx] or ""
|
||||||
|
idx=idx+1
|
||||||
|
local biosData = {}
|
||||||
|
biosData.bootDrive=drive
|
||||||
|
biosData.term=screen
|
||||||
|
screen.clear()
|
||||||
|
local ok, err = xpcall(func, debug.traceback, biosData, cmd)
|
||||||
|
screen.clear()
|
||||||
|
screen.print(printed)
|
||||||
|
if not ok then
|
||||||
|
print("└─ OS exited with error: "..err)
|
||||||
|
print(" ")
|
||||||
|
else
|
||||||
|
print("└─ OS exited.")
|
||||||
|
print(" ")
|
||||||
|
end
|
||||||
|
screen.print("Press enter to continue...")
|
||||||
|
while true do
|
||||||
|
local event = {computer.getMachineEvent()}
|
||||||
|
if event[1] == "keyTyped" then
|
||||||
|
if event[3] == "\n" then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
sleep(0.02)
|
||||||
|
end
|
||||||
|
::invalid_boot::
|
||||||
|
end
|
||||||
|
computer.beep(400,0.4)
|
||||||
|
print("No boot options available")
|
||||||
|
screen.print("Press enter to continue...")
|
||||||
|
while true do
|
||||||
|
local event = {computer.getMachineEvent()}
|
||||||
|
if event[1] == "keyTyped" then
|
||||||
|
if event[3] == "\n" then
|
||||||
|
computer.shutdown()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
sleep(0.02)
|
||||||
|
end
|
||||||
|
end, debug.traceback)
|
||||||
|
if not ok then
|
||||||
|
screen.clear()
|
||||||
|
screen.print("BIOS PANIC: "..err)
|
||||||
|
computer.beep(800,0.2)
|
||||||
|
sleep(0.02)
|
||||||
|
computer.beep(800,0.2)
|
||||||
|
sleep(0.02)
|
||||||
|
computer.beep(800,0.2)
|
||||||
|
sleep(0.02)
|
||||||
|
screen.print("Press enter to continue...")
|
||||||
|
while true do
|
||||||
|
local event = {computer.getMachineEvent()}
|
||||||
|
if event[1] == "keyTyped" then
|
||||||
|
if event[3] == "\n" then
|
||||||
|
computer.shutdown()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
sleep(0.02)
|
||||||
|
end
|
||||||
|
end
|
||||||
3
src/computers/0/computer.json
Normal file
3
src/computers/0/computer.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"disks":[1,2,3,56]
|
||||||
|
}
|
||||||
254
src/computers/0/nvram.dat
Normal file
254
src/computers/0/nvram.dat
Normal file
@@ -0,0 +1,254 @@
|
|||||||
|
HyperionOS
|
||||||
|
disk_1
|
||||||
|
/boot/ac/boot.ac
|
||||||
|
|
||||||
|
HyperionOS Dev
|
||||||
|
disk_2
|
||||||
|
/boot/Hyprkrnl.sys
|
||||||
|
|
||||||
|
$EOF
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
58
src/computers/1/bios.lua
Normal file
58
src/computers/1/bios.lua
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
local computer = component.getFirst("computer")
|
||||||
|
local screen=component.getFirst("screen")
|
||||||
|
if not screen then
|
||||||
|
computer.beep(400,0.2)
|
||||||
|
sleep(0.2)
|
||||||
|
computer.beep(400,0.2)
|
||||||
|
while true do
|
||||||
|
computer.shutdown()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local idx = 1
|
||||||
|
local ok, err = xpcall(function()
|
||||||
|
for t, a in component.list() do
|
||||||
|
if t == "disk" then
|
||||||
|
if a:fileExists("boot.lua") then
|
||||||
|
screen.print("Bootable file found on "..a.id.." - reading...")
|
||||||
|
local code = a:open("boot.lua").read()
|
||||||
|
screen.print("Compiling boot.lua...")
|
||||||
|
local f = load(code)
|
||||||
|
if not f then error("bios boot compilation failed") end
|
||||||
|
screen.print("Booting...")
|
||||||
|
---@diagnostic disable-next-line: need-check-nil
|
||||||
|
local ok, err = xpcall(f, debug.traceback)
|
||||||
|
if not ok then screen.print(err); sleep(3) end
|
||||||
|
break
|
||||||
|
else
|
||||||
|
idx = idx+1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end, debug.traceback)
|
||||||
|
if not ok then
|
||||||
|
screen.print("BIOS error: "..err)
|
||||||
|
computer.beep(800,0.2)
|
||||||
|
osleep(0.02)
|
||||||
|
screen.print("Press enter to continue...")
|
||||||
|
while true do
|
||||||
|
local event = {computer.getMachineEvent()}
|
||||||
|
if event[1] == "keyTyped" then
|
||||||
|
if event[3] == "\n" then
|
||||||
|
computer.shutdown()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
sleep(0.02)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
computer.beep(400,0.4)
|
||||||
|
screen.print("No bootable filesystem found!")
|
||||||
|
screen.print("Press enter to continue...")
|
||||||
|
while true do
|
||||||
|
local event = {computer.getMachineEvent()}
|
||||||
|
if event[1] == "keyTyped" then
|
||||||
|
if event[3] == "\n" then
|
||||||
|
computer.shutdown()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
sleep(0.02)
|
||||||
|
end
|
||||||
3
src/computers/1/computer.json
Normal file
3
src/computers/1/computer.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"disks":[3,4,8]
|
||||||
|
}
|
||||||
249
src/computers/1/nvram.dat
Normal file
249
src/computers/1/nvram.dat
Normal file
@@ -0,0 +1,249 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
189
src/computers/2/bios.lua
Normal file
189
src/computers/2/bios.lua
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
local computer = component.getFirst("computer")
|
||||||
|
local screen=component.getFirst("screen")
|
||||||
|
if not screen then
|
||||||
|
local function e(...)end
|
||||||
|
screen = {
|
||||||
|
print=e,
|
||||||
|
printInline=e,
|
||||||
|
clear=e
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
local ok,err = xpcall(function()
|
||||||
|
-- Init components
|
||||||
|
_G._DEVELOPMENT=true
|
||||||
|
_G.component=component
|
||||||
|
|
||||||
|
local printed=""
|
||||||
|
local print=function(text)
|
||||||
|
printed=printed..text.."\n"
|
||||||
|
screen.print(text)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Get CFG
|
||||||
|
local biosCfg = {}
|
||||||
|
local i=1
|
||||||
|
while i<=256 do
|
||||||
|
biosCfg[i]=computer.getData(i) or ""
|
||||||
|
i=i+1
|
||||||
|
end
|
||||||
|
computer.beep(800,0.2)
|
||||||
|
-- Difine functions
|
||||||
|
local function copy(tabl)
|
||||||
|
local out = {}
|
||||||
|
for i,v in pairs(tabl) do
|
||||||
|
local t=type(v)
|
||||||
|
if t=="table" then
|
||||||
|
if i == "_G" then
|
||||||
|
out._G=out
|
||||||
|
else
|
||||||
|
out[i]=copy(v)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
out[i]=v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return out
|
||||||
|
end
|
||||||
|
|
||||||
|
local function save(table)
|
||||||
|
while i<=256 do
|
||||||
|
computer.setData(i, table[i] or nil)
|
||||||
|
i=i+1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function hasKey(tabl, query)
|
||||||
|
for i,v in pairs(tabl) do
|
||||||
|
if i==query then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Start boot seq
|
||||||
|
local disks={}
|
||||||
|
for i,v in component.list() do
|
||||||
|
if i=="disk" then
|
||||||
|
disks[v.id]=v
|
||||||
|
if v.type=="udd" then
|
||||||
|
v:writeBytes(0, "HDS") -- "HDS"
|
||||||
|
local tmp = v:readBytes(0,512) -- Just to make sure it writes the data
|
||||||
|
print(tmp)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local idx = 1
|
||||||
|
local bootOption=1
|
||||||
|
while true do
|
||||||
|
if biosCfg[idx]=="$EOF" then break end
|
||||||
|
print("Atempting boot option "..tostring(bootOption).." labled \""..biosCfg[idx].."\".")
|
||||||
|
bootOption=bootOption+1
|
||||||
|
local drive={}
|
||||||
|
idx=idx+1
|
||||||
|
if not hasKey(disks,biosCfg[idx]) then
|
||||||
|
print("└─ Drive not found.")
|
||||||
|
print(" ")
|
||||||
|
idx=idx+3
|
||||||
|
goto invalid_boot
|
||||||
|
else
|
||||||
|
drive=disks[biosCfg[idx]]
|
||||||
|
print("├─ Drive found with id of \""..drive.id.."\"")
|
||||||
|
end
|
||||||
|
idx=idx+1
|
||||||
|
local path
|
||||||
|
local code
|
||||||
|
if drive.type=="udd" then
|
||||||
|
print("├─ Drive is Unmanaged, looking for MBR...")
|
||||||
|
sleep(0.02)
|
||||||
|
print("├─ Reading MBR...")
|
||||||
|
local tmp = drive.readBytes(0,512)
|
||||||
|
print("├─ MBR found, compiling bootloader...")
|
||||||
|
code = table.concat(tmp)
|
||||||
|
else
|
||||||
|
if not drive:fileExists(biosCfg[idx]) then
|
||||||
|
print("└─ Path not found.")
|
||||||
|
print(" ")
|
||||||
|
idx=idx+2
|
||||||
|
goto invalid_boot
|
||||||
|
else
|
||||||
|
print("├─ Kernel exists at path \""..biosCfg[idx].."\"")
|
||||||
|
path=biosCfg[idx]
|
||||||
|
end
|
||||||
|
code = drive:open(path).read()
|
||||||
|
end
|
||||||
|
idx=idx+1
|
||||||
|
local _VG=copy(_G)
|
||||||
|
print("├─ Created virtual ENV.")
|
||||||
|
local _,func = pcall(load,code,drive.id.." | "..path,nil,_VG)
|
||||||
|
if not func then
|
||||||
|
print("└─ Compilation failure.")
|
||||||
|
print(" ")
|
||||||
|
idx=idx+1
|
||||||
|
goto invalid_boot
|
||||||
|
else
|
||||||
|
print("├─ Executing.")
|
||||||
|
end
|
||||||
|
local cmd=biosCfg[idx] or ""
|
||||||
|
idx=idx+1
|
||||||
|
local biosData = {}
|
||||||
|
biosData.bootDrive=drive
|
||||||
|
biosData.term=screen
|
||||||
|
screen.clear()
|
||||||
|
local ok, err = xpcall(func, debug.traceback, biosData, cmd)
|
||||||
|
screen.clear()
|
||||||
|
screen.print(printed)
|
||||||
|
if not ok then
|
||||||
|
print("└─ OS exited with error: "..err)
|
||||||
|
print(" ")
|
||||||
|
else
|
||||||
|
print("└─ OS exited.")
|
||||||
|
print(" ")
|
||||||
|
end
|
||||||
|
screen.print("Press enter to continue...")
|
||||||
|
while true do
|
||||||
|
local event = {computer.getMachineEvent()}
|
||||||
|
if event[1] == "keyTyped" then
|
||||||
|
if event[3] == "\n" then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
sleep(0.02)
|
||||||
|
end
|
||||||
|
::invalid_boot::
|
||||||
|
end
|
||||||
|
computer.beep(400,0.4)
|
||||||
|
print("No boot options available")
|
||||||
|
screen.print("Press enter to continue...")
|
||||||
|
while true do
|
||||||
|
local event = {computer.getMachineEvent()}
|
||||||
|
if event[1] == "keyTyped" then
|
||||||
|
if event[3] == "\n" then
|
||||||
|
computer.shutdown()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
sleep(0.02)
|
||||||
|
end
|
||||||
|
end, debug.traceback)
|
||||||
|
if not ok then
|
||||||
|
screen.clear()
|
||||||
|
screen.print("BIOS PANIC: "..err)
|
||||||
|
computer.beep(800,0.2)
|
||||||
|
sleep(0.02)
|
||||||
|
computer.beep(800,0.2)
|
||||||
|
sleep(0.02)
|
||||||
|
computer.beep(800,0.2)
|
||||||
|
sleep(0.02)
|
||||||
|
screen.print("Press enter to continue...")
|
||||||
|
while true do
|
||||||
|
local event = {computer.getMachineEvent()}
|
||||||
|
if event[1] == "keyTyped" then
|
||||||
|
if event[3] == "\n" then
|
||||||
|
computer.shutdown()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
sleep(0.02)
|
||||||
|
end
|
||||||
|
end
|
||||||
3
src/computers/2/computer.json
Normal file
3
src/computers/2/computer.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"disks":[1,2,3,4,8]
|
||||||
|
}
|
||||||
249
src/computers/2/nvram.dat
Normal file
249
src/computers/2/nvram.dat
Normal file
@@ -0,0 +1,249 @@
|
|||||||
|
HyperionOS
|
||||||
|
disk_3
|
||||||
|
/boot/ac/boot.ac
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
46
src/computers/6/bios.lua
Normal file
46
src/computers/6/bios.lua
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
local driverutil={}
|
||||||
|
function driverutil.getFirst(type)
|
||||||
|
if drivers[type] then
|
||||||
|
if drivers[type][1] then
|
||||||
|
return drivers[type][1]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function driverutil.list(type)
|
||||||
|
if not type then
|
||||||
|
local tmp={}
|
||||||
|
for i,v in ipairs(drivers.raw) do
|
||||||
|
tmp[#tmp+1] = {type=v.type, obj=v}
|
||||||
|
end
|
||||||
|
local i=0
|
||||||
|
return function()
|
||||||
|
i=i+1
|
||||||
|
if tmp[i]==nil then return end
|
||||||
|
return tmp[i].type, tmp[i].obj
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local tmp={}
|
||||||
|
for i,v in ipairs(drivers[type]) do
|
||||||
|
tmp[#tmp+1] = {type=v.type, obj=v}
|
||||||
|
end
|
||||||
|
local i=0
|
||||||
|
return function()
|
||||||
|
i=i+1
|
||||||
|
if tmp[i]==nil then return end
|
||||||
|
return tmp[i].type, tmp[i].obj
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function runAsKernel(path, ...)
|
||||||
|
local func, err = load("return {'e'}", path, "t", _G)
|
||||||
|
if not func then return false, "\t"..err end
|
||||||
|
local ret = {xpcall(func, debug.traceback, ...)}
|
||||||
|
if not ret[1] then
|
||||||
|
return false, ret[2]
|
||||||
|
end
|
||||||
|
return true, table.unpack(ret, 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
runAsKernel(e, driverutil)
|
||||||
3
src/computers/6/computer.json
Normal file
3
src/computers/6/computer.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"disks":[1,2,3,4,8]
|
||||||
|
}
|
||||||
249
src/computers/6/nvram.dat
Normal file
249
src/computers/6/nvram.dat
Normal file
@@ -0,0 +1,249 @@
|
|||||||
|
HyperionOS
|
||||||
|
disk_3
|
||||||
|
/boot/ac/boot.ac
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
1
src/disks/.ignore
Normal file
1
src/disks/.ignore
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
0
src/disks/1h/bin/BASIC
Normal file
0
src/disks/1h/bin/BASIC
Normal file
0
src/disks/1h/bin/hex.lua
Normal file
0
src/disks/1h/bin/hex.lua
Normal file
10
src/disks/1h/bin/lua.lua
Normal file
10
src/disks/1h/bin/lua.lua
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
local args={...}
|
||||||
|
if #args>0 then
|
||||||
|
load(args[1])(table.unpack(args, 2))
|
||||||
|
else
|
||||||
|
local sys = require("system")
|
||||||
|
local evhook = sys.addEventHook("keyTyped", function()
|
||||||
|
|
||||||
|
end)
|
||||||
|
local term = sys.getParentTermObject()
|
||||||
|
end
|
||||||
0
src/disks/1h/bin/shell.hex
Normal file
0
src/disks/1h/bin/shell.hex
Normal file
783
src/disks/1h/bin/shell.lua
Normal file
783
src/disks/1h/bin/shell.lua
Normal file
@@ -0,0 +1,783 @@
|
|||||||
|
-- SPDX-FileCopyrightText: 2017 Daniel Ratcliffe
|
||||||
|
--
|
||||||
|
-- SPDX-License-Identifier: LicenseRef-CCPL
|
||||||
|
|
||||||
|
--[[- The shell API provides access to CraftOS's command line interface.
|
||||||
|
It allows you to @{run|start programs}, @{setCompletionFunction|add completion
|
||||||
|
for a program}, and much more.
|
||||||
|
@{shell} is not a "true" API. Instead, it is a standard program, which injects
|
||||||
|
its API into the programs that it launches. This allows for multiple shells to
|
||||||
|
run at the same time, but means that the API is not available in the global
|
||||||
|
environment, and so is unavailable to other @{os.loadAPI|APIs}.
|
||||||
|
## Programs and the program path
|
||||||
|
When you run a command with the shell, either from the prompt or
|
||||||
|
@{shell.run|from Lua code}, the shell API performs several steps to work out
|
||||||
|
which program to run:
|
||||||
|
1. Firstly, the shell attempts to resolve @{shell.aliases|aliases}. This allows
|
||||||
|
us to use multiple names for a single command. For example, the `list`
|
||||||
|
program has two aliases: `ls` and `dir`. When you write `ls /rom`, that's
|
||||||
|
expanded to `list /rom`.
|
||||||
|
2. Next, the shell attempts to find where the program actually is. For this, it
|
||||||
|
uses the @{shell.path|program path}. This is a colon separated list of
|
||||||
|
directories, each of which is checked to see if it contains the program.
|
||||||
|
`list` or `list.lua` doesn't exist in `.` (the current directory), so she
|
||||||
|
shell now looks in `/rom/programs`, where `list.lua` can be found!
|
||||||
|
3. Finally, the shell reads the file and checks if the file starts with a
|
||||||
|
`#!`. This is a [hashbang][], which says that this file shouldn't be treated
|
||||||
|
as Lua, but instead passed to _another_ program, the name of which should
|
||||||
|
follow the `#!`.
|
||||||
|
[hashbang]: https://en.wikipedia.org/wiki/Shebang_(Unix)
|
||||||
|
@module[module] shell
|
||||||
|
]]
|
||||||
|
local make_package = dofile("rom/modules/main/cc/require.lua").make
|
||||||
|
|
||||||
|
local multishell = multishell
|
||||||
|
local parentShell = shell
|
||||||
|
local parentTerm = term.current()
|
||||||
|
|
||||||
|
if multishell then
|
||||||
|
multishell.setTitle(multishell.getCurrent(), "shell")
|
||||||
|
end
|
||||||
|
|
||||||
|
local bExit = false
|
||||||
|
local sDir = parentShell and parentShell.dir() or ""
|
||||||
|
local sPath = parentShell and parentShell.path() or ".:/rom/programs"
|
||||||
|
local tAliases = parentShell and parentShell.aliases() or {}
|
||||||
|
local tCompletionInfo = parentShell and parentShell.getCompletionInfo() or {}
|
||||||
|
local tProgramStack = {}
|
||||||
|
|
||||||
|
local shell = {} --- @export
|
||||||
|
local function createShellEnv(dir)
|
||||||
|
local env = { shell = shell, multishell = multishell }
|
||||||
|
env.require, env.package = make_package(env, dir)
|
||||||
|
return env
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set up a dummy require based on the current shell, for loading some of our internal dependencies.
|
||||||
|
local require
|
||||||
|
do
|
||||||
|
local env = setmetatable(createShellEnv("/rom/programs"), { __index = _ENV })
|
||||||
|
require = env.require
|
||||||
|
end
|
||||||
|
local expect = require("cc.expect").expect
|
||||||
|
local exception = require "cc.internal.exception"
|
||||||
|
|
||||||
|
-- Colours
|
||||||
|
local promptColour, textColour, bgColour
|
||||||
|
if term.isColour() then
|
||||||
|
promptColour = colours.yellow
|
||||||
|
textColour = colours.white
|
||||||
|
bgColour = colours.black
|
||||||
|
else
|
||||||
|
promptColour = colours.white
|
||||||
|
textColour = colours.white
|
||||||
|
bgColour = colours.black
|
||||||
|
end
|
||||||
|
|
||||||
|
local function tokenise(...)
|
||||||
|
local sLine = table.concat({ ... }, " ")
|
||||||
|
local tWords = {}
|
||||||
|
local bQuoted = false
|
||||||
|
for match in string.gmatch(sLine .. "\"", "(.-)\"") do
|
||||||
|
if bQuoted then
|
||||||
|
table.insert(tWords, match)
|
||||||
|
else
|
||||||
|
for m in string.gmatch(match, "[^ \t]+") do
|
||||||
|
table.insert(tWords, m)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
bQuoted = not bQuoted
|
||||||
|
end
|
||||||
|
return tWords
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Execute a program using os.run, unless a shebang is present.
|
||||||
|
-- In that case, execute the program using the interpreter specified in the hashbang.
|
||||||
|
-- This may occur recursively, up to the maximum number of times specified by remainingRecursion
|
||||||
|
-- Returns the same type as os.run, which is a boolean indicating whether the program exited successfully.
|
||||||
|
local function executeProgram(remainingRecursion, path, args)
|
||||||
|
local file, err = fs.open(path, "r")
|
||||||
|
if not file then
|
||||||
|
printError(err)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- First check if the file begins with a #!
|
||||||
|
local contents = file.readLine() or ""
|
||||||
|
|
||||||
|
if contents:sub(1, 2) == "#!" then
|
||||||
|
file.close()
|
||||||
|
|
||||||
|
remainingRecursion = remainingRecursion - 1
|
||||||
|
if remainingRecursion == 0 then
|
||||||
|
printError("Hashbang recursion depth limit reached when loading file: " .. path)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Load the specified hashbang program instead
|
||||||
|
local hashbangArgs = tokenise(contents:sub(3))
|
||||||
|
local originalHashbangPath = table.remove(hashbangArgs, 1)
|
||||||
|
local resolvedHashbangProgram = shell.resolveProgram(originalHashbangPath)
|
||||||
|
if not resolvedHashbangProgram then
|
||||||
|
printError("Hashbang program not found: " .. originalHashbangPath)
|
||||||
|
return false
|
||||||
|
elseif resolvedHashbangProgram == "rom/programs/shell.lua" and #hashbangArgs == 0 then
|
||||||
|
-- If we try to launch the shell then our shebang expands to "shell <program>", which just does a
|
||||||
|
-- shell.run("<program>") again, resulting in an infinite loop. This may still happen (if the user
|
||||||
|
-- has a custom shell), but this reduces the risk.
|
||||||
|
-- It's a little ugly special-casing this, but it's probably worth warning about.
|
||||||
|
printError("Cannot use the shell as a hashbang program")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Add the path and any arguments to the interpreter's arguments
|
||||||
|
table.insert(hashbangArgs, path)
|
||||||
|
for _, v in ipairs(args) do
|
||||||
|
table.insert(hashbangArgs, v)
|
||||||
|
end
|
||||||
|
|
||||||
|
hashbangArgs[0] = originalHashbangPath
|
||||||
|
return executeProgram(remainingRecursion, resolvedHashbangProgram, hashbangArgs)
|
||||||
|
end
|
||||||
|
|
||||||
|
contents = contents .. "\n" .. (file.readAll() or "")
|
||||||
|
file.close()
|
||||||
|
|
||||||
|
local dir = fs.getDir(path)
|
||||||
|
local env = setmetatable(createShellEnv(dir), { __index = _G })
|
||||||
|
env.arg = args
|
||||||
|
|
||||||
|
local func, err = load(contents, "@/" .. fs.combine(path), nil, env)
|
||||||
|
if not func then
|
||||||
|
-- We had a syntax error. Attempt to run it through our own parser if
|
||||||
|
-- the file is "small enough", otherwise report the original error.
|
||||||
|
if #contents < 1024 * 128 then
|
||||||
|
local parser = require "cc.internal.syntax"
|
||||||
|
if parser.parse_program(contents) then printError(err) end
|
||||||
|
else
|
||||||
|
printError(err)
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
if settings.get("bios.strict_globals", false) then
|
||||||
|
getmetatable(env).__newindex = function(_, name)
|
||||||
|
error("Attempt to create global " .. tostring(name), 2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local ok, err, co = exception.try(func, table.unpack(args, 1, args.n))
|
||||||
|
|
||||||
|
if ok then return true end
|
||||||
|
|
||||||
|
if err and err ~= "" then
|
||||||
|
printError(err)
|
||||||
|
exception.report(err, co)
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Run a program with the supplied arguments.
|
||||||
|
--
|
||||||
|
-- Unlike @{shell.run}, each argument is passed to the program verbatim. While
|
||||||
|
-- `shell.run("echo", "b c")` runs `echo` with `b` and `c`,
|
||||||
|
-- `shell.execute("echo", "b c")` runs `echo` with a single argument `b c`.
|
||||||
|
--
|
||||||
|
-- @tparam string command The program to execute.
|
||||||
|
-- @tparam string ... Arguments to this program.
|
||||||
|
-- @treturn boolean Whether the program exited successfully.
|
||||||
|
-- @since 1.88.0
|
||||||
|
-- @usage Run `paint my-image` from within your program:
|
||||||
|
--
|
||||||
|
-- shell.execute("paint", "my-image")
|
||||||
|
function shell.execute(command, ...)
|
||||||
|
expect(1, command, "string")
|
||||||
|
for i = 1, select('#', ...) do
|
||||||
|
expect(i + 1, select(i, ...), "string")
|
||||||
|
end
|
||||||
|
|
||||||
|
local sPath = shell.resolveProgram(command)
|
||||||
|
if sPath ~= nil then
|
||||||
|
tProgramStack[#tProgramStack + 1] = sPath
|
||||||
|
if multishell then
|
||||||
|
local sTitle = fs.getName(sPath)
|
||||||
|
if sTitle:sub(-4) == ".lua" then
|
||||||
|
sTitle = sTitle:sub(1, -5)
|
||||||
|
end
|
||||||
|
multishell.setTitle(multishell.getCurrent(), sTitle)
|
||||||
|
end
|
||||||
|
|
||||||
|
local result = executeProgram(100, sPath, { [0] = command, ... })
|
||||||
|
|
||||||
|
tProgramStack[#tProgramStack] = nil
|
||||||
|
if multishell then
|
||||||
|
if #tProgramStack > 0 then
|
||||||
|
local sTitle = fs.getName(tProgramStack[#tProgramStack])
|
||||||
|
if sTitle:sub(-4) == ".lua" then
|
||||||
|
sTitle = sTitle:sub(1, -5)
|
||||||
|
end
|
||||||
|
multishell.setTitle(multishell.getCurrent(), sTitle)
|
||||||
|
else
|
||||||
|
multishell.setTitle(multishell.getCurrent(), "shell")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
else
|
||||||
|
printError("No such program")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Install shell API
|
||||||
|
|
||||||
|
--- Run a program with the supplied arguments.
|
||||||
|
--
|
||||||
|
-- All arguments are concatenated together and then parsed as a command line. As
|
||||||
|
-- a result, `shell.run("program a b")` is the same as `shell.run("program",
|
||||||
|
-- "a", "b")`.
|
||||||
|
--
|
||||||
|
-- @tparam string ... The program to run and its arguments.
|
||||||
|
-- @treturn boolean Whether the program exited successfully.
|
||||||
|
-- @usage Run `paint my-image` from within your program:
|
||||||
|
--
|
||||||
|
-- shell.run("paint", "my-image")
|
||||||
|
-- @see shell.execute Run a program directly without parsing the arguments.
|
||||||
|
-- @changed 1.80pr1 Programs now get their own environment instead of sharing the same one.
|
||||||
|
-- @changed 1.83.0 `arg` is now added to the environment.
|
||||||
|
function shell.run(...)
|
||||||
|
local tWords = tokenise(...)
|
||||||
|
local sCommand = tWords[1]
|
||||||
|
if sCommand then
|
||||||
|
return shell.execute(sCommand, table.unpack(tWords, 2))
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Exit the current shell.
|
||||||
|
--
|
||||||
|
-- This does _not_ terminate your program, it simply makes the shell terminate
|
||||||
|
-- after your program has finished. If this is the toplevel shell, then the
|
||||||
|
-- computer will be shutdown.
|
||||||
|
function shell.exit()
|
||||||
|
bExit = true
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Return the current working directory. This is what is displayed before the
|
||||||
|
-- `> ` of the shell prompt, and is used by @{shell.resolve} to handle relative
|
||||||
|
-- paths.
|
||||||
|
--
|
||||||
|
-- @treturn string The current working directory.
|
||||||
|
-- @see setDir To change the working directory.
|
||||||
|
function shell.dir()
|
||||||
|
return sDir
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set the current working directory.
|
||||||
|
--
|
||||||
|
-- @tparam string dir The new working directory.
|
||||||
|
-- @throws If the path does not exist or is not a directory.
|
||||||
|
-- @usage Set the working directory to "rom"
|
||||||
|
--
|
||||||
|
-- shell.setDir("rom")
|
||||||
|
function shell.setDir(dir)
|
||||||
|
expect(1, dir, "string")
|
||||||
|
if not fs.isDir(dir) then
|
||||||
|
error("Not a directory", 2)
|
||||||
|
end
|
||||||
|
sDir = fs.combine(dir, "")
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set the path where programs are located.
|
||||||
|
--
|
||||||
|
-- The path is composed of a list of directory names in a string, each separated
|
||||||
|
-- by a colon (`:`). On normal turtles will look in the current directory (`.`),
|
||||||
|
-- `/rom/programs` and `/rom/programs/turtle` folder, making the path
|
||||||
|
-- `.:/rom/programs:/rom/programs/turtle`.
|
||||||
|
--
|
||||||
|
-- @treturn string The current shell's path.
|
||||||
|
-- @see setPath To change the current path.
|
||||||
|
function shell.path()
|
||||||
|
return sPath
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set the @{path|current program path}.
|
||||||
|
--
|
||||||
|
-- Be careful to prefix directories with a `/`. Otherwise they will be searched
|
||||||
|
-- for from the @{shell.dir|current directory}, rather than the computer's root.
|
||||||
|
--
|
||||||
|
-- @tparam string path The new program path.
|
||||||
|
-- @since 1.2
|
||||||
|
function shell.setPath(path)
|
||||||
|
expect(1, path, "string")
|
||||||
|
sPath = path
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Resolve a relative path to an absolute path.
|
||||||
|
--
|
||||||
|
-- The @{fs} and @{io} APIs work using absolute paths, and so we must convert
|
||||||
|
-- any paths relative to the @{dir|current directory} to absolute ones. This
|
||||||
|
-- does nothing when the path starts with `/`.
|
||||||
|
--
|
||||||
|
-- @tparam string path The path to resolve.
|
||||||
|
-- @usage Resolve `startup.lua` when in the `rom` folder.
|
||||||
|
--
|
||||||
|
-- shell.setDir("rom")
|
||||||
|
-- print(shell.resolve("startup.lua"))
|
||||||
|
-- -- => rom/startup.lua
|
||||||
|
function shell.resolve(path)
|
||||||
|
expect(1, path, "string")
|
||||||
|
local sStartChar = string.sub(path, 1, 1)
|
||||||
|
if sStartChar == "/" or sStartChar == "\\" then
|
||||||
|
return fs.combine("", path)
|
||||||
|
else
|
||||||
|
return fs.combine(sDir, path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function pathWithExtension(_sPath, _sExt)
|
||||||
|
local nLen = #sPath
|
||||||
|
local sEndChar = string.sub(_sPath, nLen, nLen)
|
||||||
|
-- Remove any trailing slashes so we can add an extension to the path safely
|
||||||
|
if sEndChar == "/" or sEndChar == "\\" then
|
||||||
|
_sPath = string.sub(_sPath, 1, nLen - 1)
|
||||||
|
end
|
||||||
|
return _sPath .. "." .. _sExt
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Resolve a program, using the @{path|program path} and list of @{aliases|aliases}.
|
||||||
|
--
|
||||||
|
-- @tparam string command The name of the program
|
||||||
|
-- @treturn string|nil The absolute path to the program, or @{nil} if it could
|
||||||
|
-- not be found.
|
||||||
|
-- @since 1.2
|
||||||
|
-- @usage Locate the `hello` program.
|
||||||
|
--
|
||||||
|
-- shell.resolveProgram("hello")
|
||||||
|
-- -- => rom/programs/fun/hello.lua
|
||||||
|
function shell.resolveProgram(command)
|
||||||
|
expect(1, command, "string")
|
||||||
|
-- Substitute aliases firsts
|
||||||
|
if tAliases[command] ~= nil then
|
||||||
|
command = tAliases[command]
|
||||||
|
end
|
||||||
|
|
||||||
|
-- If the path is a global path, use it directly
|
||||||
|
if command:find("/") or command:find("\\") then
|
||||||
|
local sPath = shell.resolve(command)
|
||||||
|
if fs.exists(sPath) and not fs.isDir(sPath) then
|
||||||
|
return sPath
|
||||||
|
else
|
||||||
|
local sPathLua = pathWithExtension(sPath, "lua")
|
||||||
|
if fs.exists(sPathLua) and not fs.isDir(sPathLua) then
|
||||||
|
return sPathLua
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Otherwise, look on the path variable
|
||||||
|
for sPath in string.gmatch(sPath, "[^:]+") do
|
||||||
|
sPath = fs.combine(shell.resolve(sPath), command)
|
||||||
|
if fs.exists(sPath) and not fs.isDir(sPath) then
|
||||||
|
return sPath
|
||||||
|
else
|
||||||
|
local sPathLua = pathWithExtension(sPath, "lua")
|
||||||
|
if fs.exists(sPathLua) and not fs.isDir(sPathLua) then
|
||||||
|
return sPathLua
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Not found
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Return a list of all programs on the @{shell.path|path}.
|
||||||
|
--
|
||||||
|
-- @tparam[opt] boolean include_hidden Include hidden files. Namely, any which
|
||||||
|
-- start with `.`.
|
||||||
|
-- @treturn { string } A list of available programs.
|
||||||
|
-- @usage textutils.tabulate(shell.programs())
|
||||||
|
-- @since 1.2
|
||||||
|
function shell.programs(include_hidden)
|
||||||
|
expect(1, include_hidden, "boolean", "nil")
|
||||||
|
|
||||||
|
local tItems = {}
|
||||||
|
|
||||||
|
-- Add programs from the path
|
||||||
|
for sPath in string.gmatch(sPath, "[^:]+") do
|
||||||
|
sPath = shell.resolve(sPath)
|
||||||
|
if fs.isDir(sPath) then
|
||||||
|
local tList = fs.list(sPath)
|
||||||
|
for n = 1, #tList do
|
||||||
|
local sFile = tList[n]
|
||||||
|
if not fs.isDir(fs.combine(sPath, sFile)) and
|
||||||
|
(include_hidden or string.sub(sFile, 1, 1) ~= ".") then
|
||||||
|
if #sFile > 4 and sFile:sub(-4) == ".lua" then
|
||||||
|
sFile = sFile:sub(1, -5)
|
||||||
|
end
|
||||||
|
tItems[sFile] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Sort and return
|
||||||
|
local tItemList = {}
|
||||||
|
for sItem in pairs(tItems) do
|
||||||
|
table.insert(tItemList, sItem)
|
||||||
|
end
|
||||||
|
table.sort(tItemList)
|
||||||
|
return tItemList
|
||||||
|
end
|
||||||
|
|
||||||
|
local function completeProgram(sLine)
|
||||||
|
local bIncludeHidden = settings.get("shell.autocomplete_hidden")
|
||||||
|
if #sLine > 0 and (sLine:find("/") or sLine:find("\\")) then
|
||||||
|
-- Add programs from the root
|
||||||
|
return fs.complete(sLine, sDir, {
|
||||||
|
include_files = true,
|
||||||
|
include_dirs = false,
|
||||||
|
include_hidden = bIncludeHidden,
|
||||||
|
})
|
||||||
|
|
||||||
|
else
|
||||||
|
local tResults = {}
|
||||||
|
local tSeen = {}
|
||||||
|
|
||||||
|
-- Add aliases
|
||||||
|
for sAlias in pairs(tAliases) do
|
||||||
|
if #sAlias > #sLine and string.sub(sAlias, 1, #sLine) == sLine then
|
||||||
|
local sResult = string.sub(sAlias, #sLine + 1)
|
||||||
|
if not tSeen[sResult] then
|
||||||
|
table.insert(tResults, sResult)
|
||||||
|
tSeen[sResult] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Add all subdirectories. We don't include files as they will be added in the block below
|
||||||
|
local tDirs = fs.complete(sLine, sDir, {
|
||||||
|
include_files = false,
|
||||||
|
include_dirs = false,
|
||||||
|
include_hidden = bIncludeHidden,
|
||||||
|
})
|
||||||
|
for i = 1, #tDirs do
|
||||||
|
local sResult = tDirs[i]
|
||||||
|
if not tSeen[sResult] then
|
||||||
|
table.insert (tResults, sResult)
|
||||||
|
tSeen [sResult] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Add programs from the path
|
||||||
|
local tPrograms = shell.programs()
|
||||||
|
for n = 1, #tPrograms do
|
||||||
|
local sProgram = tPrograms[n]
|
||||||
|
if #sProgram > #sLine and string.sub(sProgram, 1, #sLine) == sLine then
|
||||||
|
local sResult = string.sub(sProgram, #sLine + 1)
|
||||||
|
if not tSeen[sResult] then
|
||||||
|
table.insert(tResults, sResult)
|
||||||
|
tSeen[sResult] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Sort and return
|
||||||
|
table.sort(tResults)
|
||||||
|
return tResults
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function completeProgramArgument(sProgram, nArgument, sPart, tPreviousParts)
|
||||||
|
local tInfo = tCompletionInfo[sProgram]
|
||||||
|
if tInfo then
|
||||||
|
return tInfo.fnComplete(shell, nArgument, sPart, tPreviousParts)
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Complete a shell command line.
|
||||||
|
--
|
||||||
|
-- This accepts an incomplete command, and completes the program name or
|
||||||
|
-- arguments. For instance, `l` will be completed to `ls`, and `ls ro` will be
|
||||||
|
-- completed to `ls rom/`.
|
||||||
|
--
|
||||||
|
-- Completion handlers for your program may be registered with
|
||||||
|
-- @{shell.setCompletionFunction}.
|
||||||
|
--
|
||||||
|
-- @tparam string sLine The input to complete.
|
||||||
|
-- @treturn { string }|nil The list of possible completions.
|
||||||
|
-- @see _G.read For more information about completion.
|
||||||
|
-- @see shell.completeProgram
|
||||||
|
-- @see shell.setCompletionFunction
|
||||||
|
-- @see shell.getCompletionInfo
|
||||||
|
-- @since 1.74
|
||||||
|
function shell.complete(sLine)
|
||||||
|
expect(1, sLine, "string")
|
||||||
|
if #sLine > 0 then
|
||||||
|
local tWords = tokenise(sLine)
|
||||||
|
local nIndex = #tWords
|
||||||
|
if string.sub(sLine, #sLine, #sLine) == " " then
|
||||||
|
nIndex = nIndex + 1
|
||||||
|
end
|
||||||
|
if nIndex == 1 then
|
||||||
|
local sBit = tWords[1] or ""
|
||||||
|
local sPath = shell.resolveProgram(sBit)
|
||||||
|
if tCompletionInfo[sPath] then
|
||||||
|
return { " " }
|
||||||
|
else
|
||||||
|
local tResults = completeProgram(sBit)
|
||||||
|
for n = 1, #tResults do
|
||||||
|
local sResult = tResults[n]
|
||||||
|
local sPath = shell.resolveProgram(sBit .. sResult)
|
||||||
|
if tCompletionInfo[sPath] then
|
||||||
|
tResults[n] = sResult .. " "
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return tResults
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif nIndex > 1 then
|
||||||
|
local sPath = shell.resolveProgram(tWords[1])
|
||||||
|
local sPart = tWords[nIndex] or ""
|
||||||
|
local tPreviousParts = tWords
|
||||||
|
tPreviousParts[nIndex] = nil
|
||||||
|
return completeProgramArgument(sPath , nIndex - 1, sPart, tPreviousParts)
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Complete the name of a program.
|
||||||
|
--
|
||||||
|
-- @tparam string program The name of a program to complete.
|
||||||
|
-- @treturn { string } A list of possible completions.
|
||||||
|
-- @see cc.shell.completion.program
|
||||||
|
function shell.completeProgram(program)
|
||||||
|
expect(1, program, "string")
|
||||||
|
return completeProgram(program)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set the completion function for a program. When the program is entered on
|
||||||
|
-- the command line, this program will be called to provide auto-complete
|
||||||
|
-- information.
|
||||||
|
--
|
||||||
|
-- The completion function accepts four arguments:
|
||||||
|
--
|
||||||
|
-- 1. The current shell. As completion functions are inherited, this is not
|
||||||
|
-- guaranteed to be the shell you registered this function in.
|
||||||
|
-- 2. The index of the argument currently being completed.
|
||||||
|
-- 3. The current argument. This may be the empty string.
|
||||||
|
-- 4. A list of the previous arguments.
|
||||||
|
--
|
||||||
|
-- For instance, when completing `pastebin put rom/st` our pastebin completion
|
||||||
|
-- function will receive the shell API, an index of 2, `rom/st` as the current
|
||||||
|
-- argument, and a "previous" table of `{ "put" }`. This function may then wish
|
||||||
|
-- to return a table containing `artup.lua`, indicating the entire command
|
||||||
|
-- should be completed to `pastebin put rom/startup.lua`.
|
||||||
|
--
|
||||||
|
-- You completion entries may also be followed by a space, if you wish to
|
||||||
|
-- indicate another argument is expected.
|
||||||
|
--
|
||||||
|
-- @tparam string program The path to the program. This should be an absolute path
|
||||||
|
-- _without_ the leading `/`.
|
||||||
|
-- @tparam function(shell: table, index: number, argument: string, previous: { string }):({ string }|nil) complete
|
||||||
|
-- The completion function.
|
||||||
|
-- @see cc.shell.completion Various utilities to help with writing completion functions.
|
||||||
|
-- @see shell.complete
|
||||||
|
-- @see _G.read For more information about completion.
|
||||||
|
-- @since 1.74
|
||||||
|
function shell.setCompletionFunction(program, complete)
|
||||||
|
expect(1, program, "string")
|
||||||
|
expect(2, complete, "function")
|
||||||
|
tCompletionInfo[program] = {
|
||||||
|
fnComplete = complete,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get a table containing all completion functions.
|
||||||
|
--
|
||||||
|
-- This should only be needed when building custom shells. Use
|
||||||
|
-- @{setCompletionFunction} to add a completion function.
|
||||||
|
--
|
||||||
|
-- @treturn { [string] = { fnComplete = function } } A table mapping the
|
||||||
|
-- absolute path of programs, to their completion functions.
|
||||||
|
function shell.getCompletionInfo()
|
||||||
|
return tCompletionInfo
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Returns the path to the currently running program.
|
||||||
|
--
|
||||||
|
-- @treturn string The absolute path to the running program.
|
||||||
|
-- @since 1.3
|
||||||
|
function shell.getRunningProgram()
|
||||||
|
if #tProgramStack > 0 then
|
||||||
|
return tProgramStack[#tProgramStack]
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Add an alias for a program.
|
||||||
|
--
|
||||||
|
-- @tparam string command The name of the alias to add.
|
||||||
|
-- @tparam string program The name or path to the program.
|
||||||
|
-- @since 1.2
|
||||||
|
-- @usage Alias `vim` to the `edit` program
|
||||||
|
--
|
||||||
|
-- shell.setAlias("vim", "edit")
|
||||||
|
function shell.setAlias(command, program)
|
||||||
|
expect(1, command, "string")
|
||||||
|
expect(2, program, "string")
|
||||||
|
tAliases[command] = program
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Remove an alias.
|
||||||
|
--
|
||||||
|
-- @tparam string command The alias name to remove.
|
||||||
|
function shell.clearAlias(command)
|
||||||
|
expect(1, command, "string")
|
||||||
|
tAliases[command] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the current aliases for this shell.
|
||||||
|
--
|
||||||
|
-- Aliases are used to allow multiple commands to refer to a single program. For
|
||||||
|
-- instance, the `list` program is aliased to `dir` or `ls`. Running `ls`, `dir`
|
||||||
|
-- or `list` in the shell will all run the `list` program.
|
||||||
|
--
|
||||||
|
-- @treturn { [string] = string } A table, where the keys are the names of
|
||||||
|
-- aliases, and the values are the path to the program.
|
||||||
|
-- @see shell.setAlias
|
||||||
|
-- @see shell.resolveProgram This uses aliases when resolving a program name to
|
||||||
|
-- an absolute path.
|
||||||
|
function shell.aliases()
|
||||||
|
-- Copy aliases
|
||||||
|
local tCopy = {}
|
||||||
|
for sAlias, sCommand in pairs(tAliases) do
|
||||||
|
tCopy[sAlias] = sCommand
|
||||||
|
end
|
||||||
|
return tCopy
|
||||||
|
end
|
||||||
|
|
||||||
|
if multishell then
|
||||||
|
--- Open a new @{multishell} tab running a command.
|
||||||
|
--
|
||||||
|
-- This behaves similarly to @{shell.run}, but instead returns the process
|
||||||
|
-- index.
|
||||||
|
--
|
||||||
|
-- This function is only available if the @{multishell} API is.
|
||||||
|
--
|
||||||
|
-- @tparam string ... The command line to run.
|
||||||
|
-- @see shell.run
|
||||||
|
-- @see multishell.launch
|
||||||
|
-- @since 1.6
|
||||||
|
-- @usage Launch the Lua interpreter and switch to it.
|
||||||
|
--
|
||||||
|
-- local id = shell.openTab("lua")
|
||||||
|
-- shell.switchTab(id)
|
||||||
|
function shell.openTab(...)
|
||||||
|
local tWords = tokenise(...)
|
||||||
|
local sCommand = tWords[1]
|
||||||
|
if sCommand then
|
||||||
|
local sPath = shell.resolveProgram(sCommand)
|
||||||
|
if sPath == "rom/programs/shell.lua" then
|
||||||
|
return multishell.launch(createShellEnv("rom/programs"), sPath, table.unpack(tWords, 2))
|
||||||
|
elseif sPath ~= nil then
|
||||||
|
return multishell.launch(createShellEnv("rom/programs"), "rom/programs/shell.lua", sCommand, table.unpack(tWords, 2))
|
||||||
|
else
|
||||||
|
printError("No such program")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Switch to the @{multishell} tab with the given index.
|
||||||
|
--
|
||||||
|
-- @tparam number id The tab to switch to.
|
||||||
|
-- @see multishell.setFocus
|
||||||
|
-- @since 1.6
|
||||||
|
function shell.switchTab(id)
|
||||||
|
expect(1, id, "number")
|
||||||
|
multishell.setFocus(id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local tArgs = { ... }
|
||||||
|
if #tArgs > 0 then
|
||||||
|
-- "shell x y z"
|
||||||
|
-- Run the program specified on the commandline
|
||||||
|
shell.run(...)
|
||||||
|
|
||||||
|
else
|
||||||
|
local function show_prompt()
|
||||||
|
term.setBackgroundColor(bgColour)
|
||||||
|
term.setTextColour(promptColour)
|
||||||
|
write(shell.dir() .. "> ")
|
||||||
|
term.setTextColour(textColour)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- "shell"
|
||||||
|
-- Print the header
|
||||||
|
term.setBackgroundColor(bgColour)
|
||||||
|
term.setTextColour(promptColour)
|
||||||
|
print(os.version())
|
||||||
|
term.setTextColour(textColour)
|
||||||
|
|
||||||
|
-- Run the startup program
|
||||||
|
if parentShell == nil then
|
||||||
|
shell.run("/rom/startup.lua")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Read commands and execute them
|
||||||
|
local tCommandHistory = {}
|
||||||
|
while not bExit do
|
||||||
|
term.redirect(parentTerm)
|
||||||
|
if term.setGraphicsMode then term.setGraphicsMode(0) end
|
||||||
|
show_prompt()
|
||||||
|
|
||||||
|
|
||||||
|
local complete
|
||||||
|
if settings.get("shell.autocomplete") then complete = shell.complete end
|
||||||
|
|
||||||
|
local ok, result
|
||||||
|
local co = coroutine.create(read)
|
||||||
|
assert(coroutine.resume(co, nil, tCommandHistory, complete))
|
||||||
|
|
||||||
|
while coroutine.status(co) ~= "dead" do
|
||||||
|
local event = table.pack(os.pullEvent())
|
||||||
|
if event[1] == "file_transfer" then
|
||||||
|
-- Abandon the current prompt
|
||||||
|
local _, h = term.getSize()
|
||||||
|
local _, y = term.getCursorPos()
|
||||||
|
if y == h then
|
||||||
|
term.scroll(1)
|
||||||
|
term.setCursorPos(1, y)
|
||||||
|
else
|
||||||
|
term.setCursorPos(1, y + 1)
|
||||||
|
end
|
||||||
|
term.setCursorBlink(false)
|
||||||
|
|
||||||
|
-- Run the import script with the provided files
|
||||||
|
local ok, err = require("cc.internal.import")(event[2].getFiles())
|
||||||
|
if not ok and err then printError(err) end
|
||||||
|
|
||||||
|
-- And attempt to restore the prompt.
|
||||||
|
show_prompt()
|
||||||
|
term.setCursorBlink(true)
|
||||||
|
event = { "term_resize", n = 1 } -- Nasty hack to force read() to redraw.
|
||||||
|
end
|
||||||
|
|
||||||
|
if result == nil or event[1] == result or event[1] == "terminate" then
|
||||||
|
ok, result = coroutine.resume(co, table.unpack(event, 1, event.n))
|
||||||
|
if not ok then error(result, 0) end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if result:match("%S") and tCommandHistory[#tCommandHistory] ~= result then
|
||||||
|
table.insert(tCommandHistory, result)
|
||||||
|
end
|
||||||
|
shell.run(result)
|
||||||
|
end
|
||||||
|
end
|
||||||
228
src/disks/1h/boot/Hyprkrnl.sys
Normal file
228
src/disks/1h/boot/Hyprkrnl.sys
Normal file
@@ -0,0 +1,228 @@
|
|||||||
|
local bootLoader={...}
|
||||||
|
local MODE=bootLoader[1]
|
||||||
|
local apis=bootLoader[2]
|
||||||
|
local bootDisk=bootLoader[3]
|
||||||
|
local term=bootLoader[4]
|
||||||
|
local getFile=bootLoader[5]
|
||||||
|
local bootData
|
||||||
|
do
|
||||||
|
local tmp=load("return "..(getFile("/var/log/kernel/bootData").readAllText() or "{}"))
|
||||||
|
if not tmp then error("Bootdata failed to load") end
|
||||||
|
bootData=tmp()
|
||||||
|
end
|
||||||
|
local list=bootLoader[6]
|
||||||
|
local computer=bootLoader[7]
|
||||||
|
local startup=true
|
||||||
|
local osleep=sleep
|
||||||
|
_G._SYSDEBUG=bootData.debug
|
||||||
|
local drivers={}
|
||||||
|
local eventCache={}
|
||||||
|
|
||||||
|
while true do
|
||||||
|
local event={computer.getMachineEvent()}
|
||||||
|
if event[1]==nil then break end
|
||||||
|
eventCache[#eventCache+1] = event
|
||||||
|
end
|
||||||
|
|
||||||
|
term.clear()
|
||||||
|
term.print("Welcome to Hyperion OS")
|
||||||
|
term.print("Creating logger")
|
||||||
|
osleep(1)
|
||||||
|
local log=load(getFile("/sys/util/logger.lua").readAllText())(computer)
|
||||||
|
term.clear()
|
||||||
|
local logHook=log.setHook(term.print)
|
||||||
|
log.api.log("Created logger")
|
||||||
|
local function saveLog()
|
||||||
|
local logNum=bootData.logNum
|
||||||
|
getFile("/var/log/kernel/"..tostring(logNum)..".log").writeAllText(log.api.get())
|
||||||
|
getFile("/var/log/kernel/latest.log").writeAllText(log.api.get())
|
||||||
|
if bootData.logNum==10 then
|
||||||
|
bootData.logNum=0
|
||||||
|
else
|
||||||
|
bootData.logNum=bootData.logNum+1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if bootData.debug then _G.saveLog=saveLog end
|
||||||
|
|
||||||
|
local function t2t(table)
|
||||||
|
local output = "{"
|
||||||
|
for i,v in pairs(table) do
|
||||||
|
local coma=true
|
||||||
|
if type(i) == "string" then
|
||||||
|
output=output.."[\""..i.."\"]="
|
||||||
|
end
|
||||||
|
if type(v) == "table" then
|
||||||
|
if v == table then
|
||||||
|
output=string.sub(output,1,#output-(#i+1))
|
||||||
|
coma=false
|
||||||
|
else
|
||||||
|
output=output..t2t(v)
|
||||||
|
end
|
||||||
|
elseif type(v) == "string" then
|
||||||
|
output=output.."[=["..v.."]=]"
|
||||||
|
elseif type(v) == "number" then
|
||||||
|
output=output..tostring(v)
|
||||||
|
elseif type(v) == "boolean" then
|
||||||
|
if v == true then
|
||||||
|
output=output.."true"
|
||||||
|
else
|
||||||
|
output=output.."false"
|
||||||
|
end
|
||||||
|
elseif type(v) == "function" then
|
||||||
|
output=output.."function()"
|
||||||
|
else
|
||||||
|
error("serialization of type \""..type(v).."\" is not supported")
|
||||||
|
end
|
||||||
|
if coma then
|
||||||
|
output=output..","
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #table>0 or string.sub(output,#output,#output) == "," then
|
||||||
|
output=string.sub(output,1,#output-1)
|
||||||
|
end
|
||||||
|
output=output.."}"
|
||||||
|
return output
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Make PANIC
|
||||||
|
local function PANIC(err)
|
||||||
|
term.clear()
|
||||||
|
term.print(log.api.get())
|
||||||
|
saveLog()
|
||||||
|
if err==bootData.prevError then
|
||||||
|
bootData.errorCount=bootData.errorCount+1
|
||||||
|
else
|
||||||
|
bootData.prevError=err
|
||||||
|
bootData.errorCount=0
|
||||||
|
end
|
||||||
|
getFile("/var/log/kernel/bootData").writeAllText(t2t(bootData))
|
||||||
|
term.print("KERNEL PANIC: "..err)
|
||||||
|
term.print("Log saved to /var/log/kernel/"..tostring(bootData.logNum)..".log\n")
|
||||||
|
term.print("Press enter to continue...")
|
||||||
|
while true do
|
||||||
|
local event = {computer.getMachineEvent()}
|
||||||
|
if event[1]~=nil then
|
||||||
|
term.print(table.concat(event, " "))
|
||||||
|
end
|
||||||
|
if event[1] == "keyTyped" then
|
||||||
|
if event[3] == "\n" then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
computer.reboot()
|
||||||
|
end
|
||||||
|
|
||||||
|
local function runAsKernel(path, ...)
|
||||||
|
local func, err = load(getFile(path).readAllText(), path, "t", _G)
|
||||||
|
if not func then return false, "\t"..err end
|
||||||
|
local ret = {xpcall(func, debug.traceback, ...)}
|
||||||
|
if not ret[1] then
|
||||||
|
return false, ret[2]
|
||||||
|
end
|
||||||
|
return true, table.unpack(ret, 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
log.api.log("Loading globals...")
|
||||||
|
for i,v in ipairs(list("/sys/api/")) do
|
||||||
|
if bootData.debug then log.api.debug("Loading "..v) end
|
||||||
|
local ok, err = runAsKernel("/sys/api/"..v, getFile, log)
|
||||||
|
if not ok then log.api.warn(err) end
|
||||||
|
end
|
||||||
|
|
||||||
|
local driverutil={}
|
||||||
|
function driverutil.getFirst(type)
|
||||||
|
if drivers[type] then
|
||||||
|
if drivers[type][1] then
|
||||||
|
return drivers[type][1]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function driverutil.list(type)
|
||||||
|
if not type then
|
||||||
|
local tmp={}
|
||||||
|
for i,v in ipairs(drivers.raw) do
|
||||||
|
tmp[#tmp+1] = {type=v.type, obj=v}
|
||||||
|
end
|
||||||
|
local i=0
|
||||||
|
return function()
|
||||||
|
i=i+1
|
||||||
|
if tmp[i]==nil then return end
|
||||||
|
return tmp[i].type, tmp[i].obj
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local tmp={}
|
||||||
|
for i,v in ipairs(drivers[type]) do
|
||||||
|
tmp[#tmp+1] = {type=v.type, obj=v}
|
||||||
|
end
|
||||||
|
local i=0
|
||||||
|
return function()
|
||||||
|
i=i+1
|
||||||
|
if tmp[i]==nil then return end
|
||||||
|
return tmp[i].type, tmp[i].obj
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
log.api.log("Loading drivers...")
|
||||||
|
for i,v in ipairs(list("/sys/modules/")) do
|
||||||
|
if bootData.debug then log.api.debug("Loading module "..v) end
|
||||||
|
local ok, err = runAsKernel("/sys/modules/"..v, apis, drivers, log, driverutil)
|
||||||
|
if not ok then log.api.warn("["..v.."] exited with ERR:\n"..err) end
|
||||||
|
end
|
||||||
|
|
||||||
|
log.api.log("Unloading non \""..MODE.."\" specific drivers...")
|
||||||
|
do
|
||||||
|
local tmp={}
|
||||||
|
for i,v in ipairs(drivers) do
|
||||||
|
if type(v.arch)=="table" then
|
||||||
|
for i2,v2 in ipairs(v.arch) do
|
||||||
|
if v2==MODE or v2=="ANY" then
|
||||||
|
tmp[#tmp+1] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if v.arch==MODE or v.arch=="ANY" then
|
||||||
|
tmp[#tmp+1] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
drivers={}
|
||||||
|
drivers.raw=tmp
|
||||||
|
end
|
||||||
|
|
||||||
|
if bootData.debug then log.api.debug("Sorting drivers...") end
|
||||||
|
for i,v in ipairs(drivers.raw) do
|
||||||
|
if not drivers[v.type] then drivers[v.type]={} end
|
||||||
|
drivers[v.type][#drivers[v.type]+1] = v
|
||||||
|
end
|
||||||
|
|
||||||
|
if bootData.debug then log.api.debug("Initializing drivers...") end
|
||||||
|
for i,v in ipairs(drivers.raw) do
|
||||||
|
if v.init then
|
||||||
|
local ok, err = xpcall(v.init, debug.traceback)
|
||||||
|
if not ok then
|
||||||
|
log.api.warn("["..v.name.."]: Init function ERR:\n"..err)
|
||||||
|
if bootData.debug then log.api.debug("Removing driver ["..v.name.."]") end
|
||||||
|
table.remove(drivers.raw, i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
log.api.log("Loaded "..tostring(#drivers.raw).." drivers")
|
||||||
|
|
||||||
|
log.api.log("Loading filesystem...")
|
||||||
|
local ok, fs = runAsKernel("/sys/fs/init", drivers, log, bootDisk, driverutil)
|
||||||
|
if not ok then PANIC(fs) end
|
||||||
|
if not fs then PANIC("filesystem failed to load") end
|
||||||
|
fs.delete("/tmp")
|
||||||
|
fs.mkDir("/tmp")
|
||||||
|
|
||||||
|
log.api.log("Loading system...")
|
||||||
|
local ok, err = runAsKernel("/sys/Hyperion.sys", drivers, log)
|
||||||
|
if not ok then PANIC(err) end
|
||||||
|
local hyperion = err
|
||||||
|
if type(hyperion)~="function" then PANIC("Hyperion failed to load:\nHyperion was: "..tostring(hyperion)) end
|
||||||
|
hyperion(fs, log, drivers, PANIC, driverutil)
|
||||||
|
|
||||||
|
PANIC("OS EXITED MAIN()")
|
||||||
135
src/disks/1h/boot/ac/boot.ac
Normal file
135
src/disks/1h/boot/ac/boot.ac
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
local biosData = ({...})[1]
|
||||||
|
local apis = {}
|
||||||
|
|
||||||
|
local lua = {
|
||||||
|
coroutine = true,
|
||||||
|
debug = true,
|
||||||
|
_HOST = true,
|
||||||
|
_VERSION = true,
|
||||||
|
assert = true,
|
||||||
|
collectgarbage = true,
|
||||||
|
error = true,
|
||||||
|
gcinfo = true,
|
||||||
|
getfenv = true,
|
||||||
|
getmetatable = true,
|
||||||
|
ipairs = true,
|
||||||
|
__inext = true,
|
||||||
|
load = true,
|
||||||
|
math = true,
|
||||||
|
next = true,
|
||||||
|
pairs = true,
|
||||||
|
pcall = true,
|
||||||
|
rawequal = true,
|
||||||
|
rawget = true,
|
||||||
|
rawlen = true,
|
||||||
|
rawset = true,
|
||||||
|
select = true,
|
||||||
|
setfenv = true,
|
||||||
|
setmetatable = true,
|
||||||
|
string = true,
|
||||||
|
table = true,
|
||||||
|
tonumber = true,
|
||||||
|
tostring = true,
|
||||||
|
type = true,
|
||||||
|
xpcall = true,
|
||||||
|
_G = true
|
||||||
|
}
|
||||||
|
|
||||||
|
local print=component.getFirst("screen").print
|
||||||
|
local comp=component
|
||||||
|
-- Sandbox globals
|
||||||
|
local _REAL_G = _G
|
||||||
|
local _PAIRS = pairs
|
||||||
|
|
||||||
|
if type(_REAL_G) ~= "table" then
|
||||||
|
error("Global environment (_G) is not a table")
|
||||||
|
end
|
||||||
|
|
||||||
|
for i, v in _PAIRS(_REAL_G) do
|
||||||
|
if not lua[i] then
|
||||||
|
apis[i] = v
|
||||||
|
_REAL_G[i] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
apis.component=comp
|
||||||
|
|
||||||
|
-- File abstraction compatible with open() -> {read,write,append}
|
||||||
|
local function getFile(path)
|
||||||
|
return {
|
||||||
|
readAllText = function()
|
||||||
|
local handle = biosData.bootDrive:open(path)
|
||||||
|
if not handle or type(handle.read) ~= "function" then
|
||||||
|
error("Cannot open file for reading: " .. tostring(path))
|
||||||
|
end
|
||||||
|
return handle.read() or ""
|
||||||
|
end,
|
||||||
|
writeAllText = function(text)
|
||||||
|
if not biosData.bootDrive:fileExists(path) then
|
||||||
|
biosData.bootDrive:createFile(path)
|
||||||
|
end
|
||||||
|
local handle = biosData.bootDrive:open(path)
|
||||||
|
if not handle or type(handle.write) ~= "function" then
|
||||||
|
error("Cannot open file for writing: " .. tostring(path))
|
||||||
|
end
|
||||||
|
handle.write(text)
|
||||||
|
end,
|
||||||
|
appendText = function(text)
|
||||||
|
local handle = biosData.bootDrive:open(path)
|
||||||
|
if not handle or type(handle.append) ~= "function" then
|
||||||
|
error("Cannot open file for appending: " .. tostring(path))
|
||||||
|
end
|
||||||
|
handle.append(text)
|
||||||
|
end
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
local function list(path)
|
||||||
|
return biosData.bootDrive:list(path)
|
||||||
|
end
|
||||||
|
|
||||||
|
function coroutine.resumeWithTimeout(CORO, LINES, ...)
|
||||||
|
local ret = { coroutine.resume(CORO, ...) }
|
||||||
|
if math.random(0, 1) == 0 then
|
||||||
|
return false, table.unpack(ret)
|
||||||
|
else
|
||||||
|
return true, table.unpack(ret)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Safety: verify APIs exist
|
||||||
|
if not apis.component then
|
||||||
|
error("Component API missing in environment")
|
||||||
|
end
|
||||||
|
if not biosData.bootDrive then
|
||||||
|
error("bootDrive missing from biosData")
|
||||||
|
end
|
||||||
|
|
||||||
|
local computer = apis.component.getFirst("computer")
|
||||||
|
|
||||||
|
-- Read kernel file correctly
|
||||||
|
local kernelSource = getFile("/boot/Hyprkrnl.sys").readAllText()
|
||||||
|
if not kernelSource or kernelSource == "" then
|
||||||
|
error("Kernel file empty or unreadable")
|
||||||
|
end
|
||||||
|
|
||||||
|
local kernel, err = load(kernelSource, "@kernel", "t", _G)
|
||||||
|
if not kernel then
|
||||||
|
error("Failed to load kernel: " .. tostring(err))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Run kernel safely
|
||||||
|
local ok, perr = xpcall(function()
|
||||||
|
kernel(
|
||||||
|
"ac",
|
||||||
|
apis,
|
||||||
|
biosData.bootDrive.id,
|
||||||
|
apis.component.getFirst("screen"),
|
||||||
|
getFile,
|
||||||
|
list,
|
||||||
|
apis.component.getFirst("computer")
|
||||||
|
)
|
||||||
|
end, debug.traceback)
|
||||||
|
|
||||||
|
if not ok then
|
||||||
|
error("Kernel execution failed: " .. tostring(perr))
|
||||||
|
end
|
||||||
119
src/disks/1h/boot/cc/boot.cc
Normal file
119
src/disks/1h/boot/cc/boot.cc
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
-- UnBIOS by JackMacWindows
|
||||||
|
-- This will undo most of the changes/additions made in the BIOS, but some things may remain wrapped if `debug` is unavailable
|
||||||
|
-- To use, just place a `bios.lua` in the root of the drive, and run this program
|
||||||
|
-- Here's a list of things that are irreversibly changed:
|
||||||
|
-- * both `bit` and `bit32` are kept for compatibility
|
||||||
|
-- * string metatable blocking (on old versions of CC)
|
||||||
|
-- In addition, if `debug` is not available these things are also irreversibly changed:
|
||||||
|
-- * old Lua 5.1 `load` function (for loading from a function)
|
||||||
|
-- * `loadstring` prefixing (before CC:T 1.96.0)
|
||||||
|
-- * `http.request`
|
||||||
|
-- * `os.shutdown` and `os.reboot`
|
||||||
|
-- * `peripheral`
|
||||||
|
-- * `turtle.equip[Left|Right]`
|
||||||
|
-- Licensed under the MIT license
|
||||||
|
local args = {...}
|
||||||
|
if _HOST:find("UnBIOS") then return end
|
||||||
|
local keptAPIs = {keys=true, bit32 = true, bit = true, ccemux = true, config = true, coroutine = true, debug = true, fs = true, http = true, mounter = true, os = true, periphemu = true, peripheral = true, redstone = true, rs = true, term = true, utf8 = true, _HOST = true, _CC_DEFAULT_SETTINGS = true, _CC_DISABLE_LUA51_FEATURES = true, _VERSION = true, assert = true, collectgarbage = true, error = true, gcinfo = true, getfenv = true, getmetatable = true, ipairs = true, __inext = true,load = true, loadstring = true, math = true, newproxy = true, next = true, pairs = true, pcall = true, rawequal = true, rawget = true, rawlen = true, rawset = true, select = true, setfenv = true, setmetatable = true, string = true, table = true, tonumber = true, tostring = true, type = true, unpack = true, xpcall = true, turtle = true, pocket = true, commands = true, _G = true}
|
||||||
|
local t = {}
|
||||||
|
for k in pairs(_G) do if not keptAPIs[k] then table.insert(t, k) end end
|
||||||
|
for _,k in ipairs(t) do _G[k] = nil end
|
||||||
|
local native = _G.term.native()
|
||||||
|
for _, method in ipairs {"nativePaletteColor", "nativePaletteColour", "screenshot"} do native[method] = _G.term[method] end
|
||||||
|
_G.term = native
|
||||||
|
if _G.http then
|
||||||
|
_G.http.checkURL = _G.http.checkURLAsync
|
||||||
|
_G.http.websocket = _G.http.websocketAsync
|
||||||
|
end
|
||||||
|
if _G.commands then _G.commands = _G.commands.native end
|
||||||
|
if _G.turtle then _G.turtle.native, _G.turtle.craft = nil end
|
||||||
|
local delete = {os = {"version", "pullEventRaw", "pullEvent", "run", "loadAPI", "unloadAPI", "sleep"}, http = _G.http and {"get", "post", "put", "delete", "patch", "options", "head", "trace", "listen", "checkURLAsync", "websocketAsync"}, fs = {"complete", "isDriveRoot"}}
|
||||||
|
for k,v in pairs(delete) do for _,a in ipairs(v) do _G[k][a] = nil end end
|
||||||
|
_G._HOST = _G._HOST .. " (UnBIOS)"
|
||||||
|
-- Set up TLCO
|
||||||
|
-- This functions by crashing `rednet.run` by removing `os.pullEventRaw`. Normally
|
||||||
|
-- this would cause `parallel` to throw an error, but we replace `error` with an
|
||||||
|
-- empty placeholder to let it continue and return without throwing. This results
|
||||||
|
-- in the `pcall` returning successfully, preventing the error-displaying code
|
||||||
|
-- from running - essentially making it so that `os.shutdown` is called immediately
|
||||||
|
-- after the new BIOS exits.
|
||||||
|
--
|
||||||
|
-- From there, the setup code is placed in `term.native` since it's the first
|
||||||
|
-- thing called after `parallel` exits. This loads the new BIOS and prepares it
|
||||||
|
-- for execution. Finally, it overwrites `os.shutdown` with the new function to
|
||||||
|
-- allow it to be the last function called in the original BIOS, and returns.
|
||||||
|
-- From there execution continues, calling the `term.redirect` dummy, skipping
|
||||||
|
-- over the error-handling code (since `pcall` returned ok), and calling
|
||||||
|
-- `os.shutdown()`. The real `os.shutdown` is re-added, and the new BIOS is tail
|
||||||
|
-- called, which effectively makes it run as the main chunk.
|
||||||
|
local olderror = error
|
||||||
|
_G.error = function() end
|
||||||
|
_G.term.redirect = function() end
|
||||||
|
function _G.term.native()
|
||||||
|
_G.term.native = nil
|
||||||
|
_G.term.redirect = nil
|
||||||
|
_G.error = olderror
|
||||||
|
term.setBackgroundColor(32768)
|
||||||
|
term.setTextColor(1)
|
||||||
|
term.setCursorPos(1, 1)
|
||||||
|
term.setCursorBlink(true)
|
||||||
|
term.clear()
|
||||||
|
local file = fs.open("/disk/boot/cc/preboot.cc", "r")
|
||||||
|
if file == nil then
|
||||||
|
term.setCursorBlink(false)
|
||||||
|
term.setTextColor(16384)
|
||||||
|
term.write("Could not find /boot/cc/bootloader.cc. UnBIOS cannot continue.")
|
||||||
|
term.setCursorPos(1, 2)
|
||||||
|
term.write("Press any key to continue")
|
||||||
|
coroutine.yield("key")
|
||||||
|
os.shutdown()
|
||||||
|
end
|
||||||
|
local fn, err = loadstring(file.readAll(), "@preboot.cc")
|
||||||
|
file.close()
|
||||||
|
if fn == nil then
|
||||||
|
term.setCursorBlink(false)
|
||||||
|
term.setTextColor(16384)
|
||||||
|
term.write("Could not load /boot/cc/bootloader.cc. UnBIOS cannot continue.")
|
||||||
|
term.setCursorPos(1, 2)
|
||||||
|
term.write(err)
|
||||||
|
term.setCursorPos(1, 3)
|
||||||
|
term.write("Press any key to continue")
|
||||||
|
coroutine.yield("key")
|
||||||
|
os.shutdown()
|
||||||
|
end
|
||||||
|
setfenv(fn, _G)
|
||||||
|
local oldshutdown = os.shutdown
|
||||||
|
os.shutdown = function()
|
||||||
|
os.shutdown = oldshutdown
|
||||||
|
return fn(table.unpack(args))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if debug then
|
||||||
|
-- Restore functions that were overwritten in the BIOS
|
||||||
|
-- Apparently this has to be done *after* redefining term.native
|
||||||
|
local function restoreValue(tab, idx, name, hint)
|
||||||
|
local i, key, value = 1, debug.getupvalue(tab[idx], hint)
|
||||||
|
while key ~= name and key ~= nil do
|
||||||
|
key, value = debug.getupvalue(tab[idx], i)
|
||||||
|
i=i+1
|
||||||
|
end
|
||||||
|
tab[idx] = value or tab[idx]
|
||||||
|
end
|
||||||
|
restoreValue(_G, "loadstring", "nativeloadstring", 1)
|
||||||
|
restoreValue(_G, "load", "nativeload", 5)
|
||||||
|
if http then restoreValue(http, "request", "nativeHTTPRequest", 3) end
|
||||||
|
restoreValue(os, "shutdown", "nativeShutdown", 1)
|
||||||
|
restoreValue(os, "reboot", "nativeReboot", 1)
|
||||||
|
if turtle then
|
||||||
|
restoreValue(turtle, "equipLeft", "v", 1)
|
||||||
|
restoreValue(turtle, "equipRight", "v", 1)
|
||||||
|
end
|
||||||
|
do
|
||||||
|
local i, key, value = 1, debug.getupvalue(peripheral.isPresent, 2)
|
||||||
|
while key ~= "native" and key ~= nil do
|
||||||
|
key, value = debug.getupvalue(peripheral.isPresent, i)
|
||||||
|
i=i+1
|
||||||
|
end
|
||||||
|
_G.peripheral = value or peripheral
|
||||||
|
end
|
||||||
|
end
|
||||||
236
src/disks/1h/boot/cc/preboot.cc
Normal file
236
src/disks/1h/boot/cc/preboot.cc
Normal file
@@ -0,0 +1,236 @@
|
|||||||
|
local apis={}
|
||||||
|
|
||||||
|
local lua = {
|
||||||
|
coroutine = true,
|
||||||
|
debug = true,
|
||||||
|
_HOST = true,
|
||||||
|
_VERSION = true,
|
||||||
|
assert = true,
|
||||||
|
collectgarbage = true,
|
||||||
|
error = true,
|
||||||
|
gcinfo = true,
|
||||||
|
getfenv = true,
|
||||||
|
getmetatable = true,
|
||||||
|
ipairs = true,
|
||||||
|
__inext = true,
|
||||||
|
load = true,
|
||||||
|
math = true,
|
||||||
|
next = true,
|
||||||
|
pairs = true,
|
||||||
|
pcall = true,
|
||||||
|
rawequal = true,
|
||||||
|
rawget = true,
|
||||||
|
rawlen = true,
|
||||||
|
rawset = true,
|
||||||
|
select = true,
|
||||||
|
setfenv = true,
|
||||||
|
setmetatable = true,
|
||||||
|
string = true,
|
||||||
|
table = true,
|
||||||
|
tonumber = true,
|
||||||
|
tostring = true,
|
||||||
|
type = true,
|
||||||
|
xpcall = true,
|
||||||
|
_G=true
|
||||||
|
}
|
||||||
|
|
||||||
|
for i,v in pairs(_G) do
|
||||||
|
if not lua[i] or lua[i]==nil then
|
||||||
|
apis[i]=v
|
||||||
|
_G[i]=nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function sleep(time)
|
||||||
|
coroutine.yield("CC_TIMER", time)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function catErr(text)
|
||||||
|
apis.term.setCursorPos(1,1)
|
||||||
|
apis.term.write(text)
|
||||||
|
while true do
|
||||||
|
coroutine.yield()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getFile(path)
|
||||||
|
if path:sub(1,1) ~= "/" then
|
||||||
|
path="/"..path
|
||||||
|
end
|
||||||
|
path="/disk"..path
|
||||||
|
if not apis.fs.exists(path) then error("File does not exist") end
|
||||||
|
if apis.fs.isDir(path) then error("Cannot open a directory") end
|
||||||
|
return {
|
||||||
|
readAllText=function()
|
||||||
|
local file = apis.fs.open(path, "r")
|
||||||
|
local text = file.readAll()
|
||||||
|
file.close()
|
||||||
|
return text
|
||||||
|
end,
|
||||||
|
writeAllText=function(text)
|
||||||
|
local file = apis.fs.open(path, "w")
|
||||||
|
file.write(text)
|
||||||
|
file.close()
|
||||||
|
end
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Prints text handling \n, \t, and \b with scrolling (no wrapping)
|
||||||
|
local function write(text)
|
||||||
|
local x, y = apis.term.getCursorPos()
|
||||||
|
local w, h = apis.term.getSize()
|
||||||
|
|
||||||
|
for i = 1, #text do
|
||||||
|
local c = text:sub(i, i)
|
||||||
|
|
||||||
|
if c == "\n" then
|
||||||
|
y = y + 1
|
||||||
|
x = 1
|
||||||
|
elseif c == "\t" then
|
||||||
|
local tabSize = 4
|
||||||
|
local spaces = tabSize - ((x - 1) % tabSize)
|
||||||
|
apis.term.write(string.rep(" ", spaces))
|
||||||
|
x = x + spaces
|
||||||
|
elseif c == "\b" then
|
||||||
|
if x > 1 then
|
||||||
|
x = x - 1
|
||||||
|
apis.term.setCursorPos(x, y)
|
||||||
|
apis.term.write(" ")
|
||||||
|
apis.term.setCursorPos(x, y)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if x <= w and y <= h then
|
||||||
|
apis.term.setCursorPos(x, y)
|
||||||
|
apis.term.write(c)
|
||||||
|
x = x + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Handle scrolling if we go past bottom
|
||||||
|
if y > h then
|
||||||
|
apis.term.scroll(1)
|
||||||
|
y = h
|
||||||
|
apis.term.setCursorPos(x, y)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
apis.term.setCursorPos(x, y)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local event_queue = {}
|
||||||
|
local function addEventRaw(...)
|
||||||
|
event_queue[#event_queue+1] = {...}
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getEvent()
|
||||||
|
local event = event_queue[1]
|
||||||
|
event_queue = {table.unpack(event_queue, 2)}
|
||||||
|
return table.unpack(event or {})
|
||||||
|
end
|
||||||
|
|
||||||
|
local lkeys={}
|
||||||
|
lkeys[apis.keys.enter]="\n"
|
||||||
|
lkeys[apis.keys.backspace]="\b"
|
||||||
|
lkeys[apis.keys.tab]="\t"
|
||||||
|
|
||||||
|
local computer={}
|
||||||
|
computer.beep=function() end
|
||||||
|
computer.shutdown=apis.os.shutdown
|
||||||
|
computer.reboot=apis.os.reboot
|
||||||
|
computer.time=function()
|
||||||
|
return apis.os.epoch("utc")
|
||||||
|
end
|
||||||
|
computer.getMachineEvent=getEvent
|
||||||
|
computer.date=apis.os.date
|
||||||
|
|
||||||
|
local function list(path)
|
||||||
|
if path:sub(1,1) ~= "/" then
|
||||||
|
path="/"..path
|
||||||
|
end
|
||||||
|
path="/disk"..path
|
||||||
|
if not apis.fs.isDir(path) then return {} end
|
||||||
|
return apis.fs.list(path)
|
||||||
|
end
|
||||||
|
|
||||||
|
function coroutine.resumeWithTimeout(CORO, LINES, ...)
|
||||||
|
local yeildKey = {}
|
||||||
|
debug.sethook(CORO, function()
|
||||||
|
coroutine.yield(yeildKey)
|
||||||
|
end, "l", LINES)
|
||||||
|
local ret = {coroutine.resume(CORO, ...)}
|
||||||
|
debug.sethook(CORO)
|
||||||
|
if ret[2]==yeildKey then return false else return true, table.unpack(ret, 2) end
|
||||||
|
end
|
||||||
|
|
||||||
|
local kernel = load(getFile("/boot/Hyprkrnl.sys").readAllText(), "@kernel", "t", _G)
|
||||||
|
if not kernel then
|
||||||
|
catErr("KERNEL COMPILE ERR")
|
||||||
|
end
|
||||||
|
local kernel_coro = coroutine.create(function()
|
||||||
|
local ok,err = pcall(function()
|
||||||
|
local ok, err=xpcall(kernel, debug.traceback, "cc", apis, "disk", {
|
||||||
|
print=function(text)
|
||||||
|
write(text.."\n")
|
||||||
|
end,
|
||||||
|
printInline=function(text)
|
||||||
|
write(text)
|
||||||
|
end,
|
||||||
|
clear=function()
|
||||||
|
apis.term.clear()
|
||||||
|
apis.term.setCursorPos(1,1)
|
||||||
|
end,
|
||||||
|
getSize=function ()
|
||||||
|
return apis.term.getSize()
|
||||||
|
end
|
||||||
|
}, getFile, list, computer)
|
||||||
|
if not ok then
|
||||||
|
write(err)
|
||||||
|
while true do
|
||||||
|
coroutine.yield()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
if not ok then
|
||||||
|
catErr(err)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
apis.term.setCursorBlink(false)
|
||||||
|
while true do
|
||||||
|
local ret = {coroutine.resumeWithTimeout(kernel_coro, 200)}
|
||||||
|
if coroutine.status(kernel_coro) == "dead" then
|
||||||
|
catErr("KERNEL EXITED")
|
||||||
|
end
|
||||||
|
if ret[1] then
|
||||||
|
if ret[2]=="CC_TIMER" and ret[3]~=nil and type(ret[3])=="number" then
|
||||||
|
local timer = apis.os.startTimer(ret[3])
|
||||||
|
repeat
|
||||||
|
local _, param = coroutine.yield("timer")
|
||||||
|
until param == timer
|
||||||
|
end
|
||||||
|
end
|
||||||
|
apis.os.queueEvent("nosleep")
|
||||||
|
local exit = false
|
||||||
|
repeat
|
||||||
|
local event = {coroutine.yield()}
|
||||||
|
if event[1] == "nosleep" then
|
||||||
|
exit=true
|
||||||
|
elseif event[1]==nil then
|
||||||
|
elseif event[1]=="key" then
|
||||||
|
addEventRaw("keyPressed", 1, event[2])
|
||||||
|
if lkeys[event[2]] then
|
||||||
|
addEventRaw("keyTyped", 1, lkeys[event[2]])
|
||||||
|
end
|
||||||
|
elseif event[1]=="char" then
|
||||||
|
addEventRaw("keyTyped", 1, event[2])
|
||||||
|
elseif event[1]=="key_up" then
|
||||||
|
addEventRaw("keyReleased", 1, event[2])
|
||||||
|
elseif event[1]=="disk" then
|
||||||
|
addEventRaw("componentAdded", "disk")
|
||||||
|
elseif event[1]=="disk_eject" then
|
||||||
|
addEventRaw("componentRemoved", "disk")
|
||||||
|
end
|
||||||
|
until exit
|
||||||
|
end
|
||||||
|
apis.os.reboot()
|
||||||
3435
src/disks/1h/lib/LibDeflate
Normal file
3435
src/disks/1h/lib/LibDeflate
Normal file
File diff suppressed because it is too large
Load Diff
0
src/disks/1h/lib/array/2d
Normal file
0
src/disks/1h/lib/array/2d
Normal file
0
src/disks/1h/lib/array/math
Normal file
0
src/disks/1h/lib/array/math
Normal file
10
src/disks/1h/lib/array/x
Normal file
10
src/disks/1h/lib/array/x
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
local lib = {}
|
||||||
|
|
||||||
|
function lib.create()
|
||||||
|
local array = {}
|
||||||
|
return setmetatable(array,{
|
||||||
|
__add=function(t1, t2)
|
||||||
|
|
||||||
|
end
|
||||||
|
})
|
||||||
|
end
|
||||||
0
src/disks/1h/opt/astronand/ZDelta/init
Normal file
0
src/disks/1h/opt/astronand/ZDelta/init
Normal file
0
src/disks/1h/opt/astronand/dbg/init
Normal file
0
src/disks/1h/opt/astronand/dbg/init
Normal file
0
src/disks/1h/sbin/init
Normal file
0
src/disks/1h/sbin/init
Normal file
22
src/disks/1h/sys/Hyperion.sys
Normal file
22
src/disks/1h/sys/Hyperion.sys
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
local args={...}
|
||||||
|
local fs=args[1]
|
||||||
|
local log=args[2]
|
||||||
|
local drivers=args[3]
|
||||||
|
local PANIC=args[4]
|
||||||
|
local driverutil=args[5]
|
||||||
|
local sys={}
|
||||||
|
local task={}
|
||||||
|
|
||||||
|
sys._VERSION = "HyperionOS V1.0.4"
|
||||||
|
|
||||||
|
local function run(file, args)
|
||||||
|
local func, err=fs.loadAsFunc(file)
|
||||||
|
if not file then return 8, err end
|
||||||
|
local ret={xpcall(func, debug.traceback, table.unpack(args))}
|
||||||
|
if not ret[1] then return 1, ret[2] end
|
||||||
|
return 0, table.unpack(ret, 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
local exitcode, req=run("/sys/system/require", {sys})
|
||||||
|
if exitcode~=0 then PANIC(req) end
|
||||||
|
_G.require=req
|
||||||
57
src/disks/1h/sys/api/string.lua
Normal file
57
src/disks/1h/sys/api/string.lua
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
-- Copyright (C) 2025 ASTRONAND
|
||||||
|
function string.hasSuffix(str, suffix)
|
||||||
|
return string.sub(str, #suffix+1) == suffix
|
||||||
|
end
|
||||||
|
|
||||||
|
function string.hasPrefix(str, prefix)
|
||||||
|
return string.sub(str, 1, #prefix) == prefix
|
||||||
|
end
|
||||||
|
|
||||||
|
function string.getSuffix(str, prefix)
|
||||||
|
return string.sub(str, #prefix+1)
|
||||||
|
end
|
||||||
|
|
||||||
|
function string.getPrefix(str, suffix)
|
||||||
|
return string.sub(str, 1, #suffix)
|
||||||
|
end
|
||||||
|
|
||||||
|
function string.join(str, ...)
|
||||||
|
return table.concat(table.pack(str, ...))
|
||||||
|
end
|
||||||
|
|
||||||
|
function string.delim(str, ...)
|
||||||
|
return table.concat(table.pack(...), str)
|
||||||
|
end
|
||||||
|
|
||||||
|
function string.split(str, delim, maxResultCountOrNil)
|
||||||
|
assert(#delim == 1, "only delim len 1 supported for now")
|
||||||
|
maxResultCountOrNil = (maxResultCountOrNil or 0)-1
|
||||||
|
local rv = {}
|
||||||
|
local buf = ""
|
||||||
|
for i = 1, #str do
|
||||||
|
local c = string.sub(str,i,i)
|
||||||
|
if #rv ~= maxResultCountOrNil and c == delim then
|
||||||
|
table.insert(rv, buf)
|
||||||
|
buf = ""
|
||||||
|
else
|
||||||
|
buf = buf..c
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.insert(rv, buf)
|
||||||
|
return rv
|
||||||
|
end
|
||||||
|
|
||||||
|
function string.replace(str, search, replacement)
|
||||||
|
local rv = ""
|
||||||
|
local consumedLen = 1
|
||||||
|
local i = 1
|
||||||
|
while i<#str do
|
||||||
|
if string.sub(str, i, i+#search-1) == search then
|
||||||
|
rv = rv .. string.sub(str, consumedLen, i-1) .. replacement
|
||||||
|
i=i+#search
|
||||||
|
consumedLen = i
|
||||||
|
end
|
||||||
|
i=i+1
|
||||||
|
end
|
||||||
|
return rv .. string.sub(str, consumedLen)
|
||||||
|
end
|
||||||
81
src/disks/1h/sys/api/table.lua
Normal file
81
src/disks/1h/sys/api/table.lua
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
-- Copyright (C) 2025 ASTRONAND
|
||||||
|
function table.deepcopy(orig, copies)
|
||||||
|
copies = copies or {}
|
||||||
|
|
||||||
|
if type(orig) ~= 'table' then
|
||||||
|
return orig
|
||||||
|
elseif copies[orig] then
|
||||||
|
return copies[orig]
|
||||||
|
end
|
||||||
|
|
||||||
|
local copy = {}
|
||||||
|
copies[orig] = copy
|
||||||
|
|
||||||
|
for k, v in next, orig, nil do
|
||||||
|
local copied_key = table.deepcopy(k, copies)
|
||||||
|
local copied_val = table.deepcopy(v, copies)
|
||||||
|
copy[copied_key] = copied_val
|
||||||
|
end
|
||||||
|
|
||||||
|
return copy
|
||||||
|
end
|
||||||
|
|
||||||
|
function table.hasKey(tabl, query)
|
||||||
|
for i,v in pairs(tabl) do
|
||||||
|
if i==query then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function table.hasVal(tabl, query)
|
||||||
|
for i,v in pairs(tabl) do
|
||||||
|
if v==query then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local function serialize(table)
|
||||||
|
local output = "{"
|
||||||
|
for i,v in pairs(table) do
|
||||||
|
local coma=true
|
||||||
|
if type(i) == "string" then
|
||||||
|
output=output.."[\""..i.."\"]="
|
||||||
|
end
|
||||||
|
if type(v) == "table" then
|
||||||
|
if v == table then
|
||||||
|
output=string.sub(output,1,#output-(#i+1))
|
||||||
|
coma=false
|
||||||
|
else
|
||||||
|
output=output..serialize(v)
|
||||||
|
end
|
||||||
|
elseif type(v) == "string" then
|
||||||
|
output=output.."[=["..v.."]=]"
|
||||||
|
elseif type(v) == "number" then
|
||||||
|
output=output..tostring(v)
|
||||||
|
elseif type(v) == "boolean" then
|
||||||
|
if v == true then
|
||||||
|
output=output.."true"
|
||||||
|
else
|
||||||
|
output=output.."false"
|
||||||
|
end
|
||||||
|
elseif type(v) == "function" then
|
||||||
|
output=output.."function() end"
|
||||||
|
else
|
||||||
|
error("serialization of type \""..type(v).."\" is not supported")
|
||||||
|
end
|
||||||
|
if coma then
|
||||||
|
output=output..","
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #table>0 or string.sub(output,#output,#output) == "," then
|
||||||
|
output=string.sub(output,1,#output-1)
|
||||||
|
end
|
||||||
|
output=output.."}"
|
||||||
|
return output
|
||||||
|
end
|
||||||
|
|
||||||
|
table.serialize=serialize
|
||||||
124
src/disks/1h/sys/fs/init
Normal file
124
src/disks/1h/sys/fs/init
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
local args={...}
|
||||||
|
local drivers=args[1]
|
||||||
|
local log=args[2]
|
||||||
|
local bootDisk=args[3]
|
||||||
|
local driverutil=args[4]
|
||||||
|
local wd="/"
|
||||||
|
log.api.log("Bootdrive is "..bootDisk)
|
||||||
|
if not drivers.disk then
|
||||||
|
error("WTF") -- ???
|
||||||
|
end
|
||||||
|
|
||||||
|
local disks={}
|
||||||
|
local mounts={
|
||||||
|
["/"]=bootDisk
|
||||||
|
}
|
||||||
|
local meta={}
|
||||||
|
|
||||||
|
local function refreshDisks()
|
||||||
|
local diskstmp={}
|
||||||
|
local tmp={}
|
||||||
|
for i,v in driverutil.list("disk") do
|
||||||
|
tmp[#tmp+1] = v
|
||||||
|
end
|
||||||
|
for _,d in ipairs(tmp) do
|
||||||
|
for i,v in d.api.list() do
|
||||||
|
if diskstmp[i]==nil then
|
||||||
|
diskstmp[i]=v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
disks=diskstmp
|
||||||
|
end
|
||||||
|
refreshDisks()
|
||||||
|
--[[
|
||||||
|
meta=load("return "..(disks[bootDisk].readAllText("/sys/fs/meta.ltn") or "{}"), "meta")()
|
||||||
|
if not meta then error("Meta failed to load") end
|
||||||
|
]]
|
||||||
|
local function resolve(path)
|
||||||
|
if path:sub(1,1)~="/" then path=wd..path end
|
||||||
|
local currmatch="/"
|
||||||
|
for i,_ in pairs(mounts) do
|
||||||
|
if string.hasPrefix(path, i) then
|
||||||
|
if #i>#currmatch then
|
||||||
|
currmatch=i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local drive=disks[mounts[currmatch]]
|
||||||
|
local newPath=string.getSuffix(path, currmatch)
|
||||||
|
return drive, newPath
|
||||||
|
end
|
||||||
|
|
||||||
|
local fs={}
|
||||||
|
|
||||||
|
function fs.list(path)
|
||||||
|
local drive, newPath = resolve(path)
|
||||||
|
return drive.list(newPath)
|
||||||
|
end
|
||||||
|
|
||||||
|
function fs.readAllText(path)
|
||||||
|
local drive, newPath = resolve(path)
|
||||||
|
return drive.readAllText(newPath)
|
||||||
|
end
|
||||||
|
|
||||||
|
function fs.writeAllText(path, content)
|
||||||
|
local drive, newPath = resolve(path)
|
||||||
|
return drive.writeAllText(newPath, content)
|
||||||
|
end
|
||||||
|
|
||||||
|
function fs.delete(path)
|
||||||
|
local drive, newPath = resolve(path)
|
||||||
|
return drive.delete(newPath)
|
||||||
|
end
|
||||||
|
|
||||||
|
function fs.exists(path)
|
||||||
|
local drive, newPath = resolve(path)
|
||||||
|
return (drive.fileExists(newPath) or drive.directoryExists(newPath))
|
||||||
|
end
|
||||||
|
|
||||||
|
function fs.fileExists(path)
|
||||||
|
local drive, newPath = resolve(path)
|
||||||
|
return drive.fileExists(newPath)
|
||||||
|
end
|
||||||
|
|
||||||
|
function fs.directoryExists(path)
|
||||||
|
local drive, newPath = resolve(path)
|
||||||
|
return drive.directoryExists(newPath)
|
||||||
|
end
|
||||||
|
|
||||||
|
function fs.createFile(path)
|
||||||
|
local drive, newPath = resolve(path)
|
||||||
|
return drive.makeFile(newPath)
|
||||||
|
end
|
||||||
|
|
||||||
|
function fs.createDirectory(path)
|
||||||
|
local drive, newPath = resolve(path)
|
||||||
|
return drive.makeDirectory(newPath)
|
||||||
|
end
|
||||||
|
|
||||||
|
fs.mkDir=fs.createDirectory
|
||||||
|
fs.mkFile=fs.createFile
|
||||||
|
fs.isDir=fs.directoryExists
|
||||||
|
fs.isFile=fs.fileExists
|
||||||
|
|
||||||
|
function fs.getWorkingDir()
|
||||||
|
return wd
|
||||||
|
end
|
||||||
|
|
||||||
|
function fs.setWorkingDir(dir)
|
||||||
|
if type(dir)~="string" then error("Invailid path") end
|
||||||
|
if dir:sub(1,1)~="/" then dir=wd..dir end
|
||||||
|
if dir:sub(#dir,#dir)~="/" then dir=dir.."/" end
|
||||||
|
if not fs.isDir(dir) then error("Invailid path") end
|
||||||
|
end
|
||||||
|
|
||||||
|
function fs.loadAsFunc(path)
|
||||||
|
local file = fs.readAllText(path)
|
||||||
|
return load(file, path, "t", setmetatable({},{
|
||||||
|
__index=_G,
|
||||||
|
__metatable=false
|
||||||
|
}))
|
||||||
|
end
|
||||||
|
|
||||||
|
return fs
|
||||||
69
src/disks/1h/sys/fs/meta.ltn
Normal file
69
src/disks/1h/sys/fs/meta.ltn
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
{["/sys/util/logger.lua"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/bin/hex.lua"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/opt"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/var/log/kernel"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/sys/modules/cc.component.kd"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/opt/astronand/ZDelta/init"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/sys/api"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/var/log/kernel/10.log"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/var/log/kernel/7.log"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/var/log/kernel/1.log"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/bin/BASIC"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/boot/cc/preboot.cc"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/boot/ac"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/sys"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/sys/fs/init"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/lib"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/sys/api/table.lua"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/var/log/kernel/5.log"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/usr/share/doc"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/var/log/kernel/3.log"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/opt/astronand/ZDelta"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/sys/hypervisor/init.sys"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/usr/share"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/sys/modules"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/var/log/kernel/6.log"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/sys/hypervisor"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/var/log/kernel/4.log"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/lib/array/math"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/var"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/sys/util/conhost.lua"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/boot/Hyprkrnl.sys"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/bin"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/sys/modules/ac.disks.kd"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/lib/array/x"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/sys/modules/cc.disks.kd"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/opt/astronand/dbg"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/usr"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/usr/share/doc/kernel/drivers"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/sys/util"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/var/log/kernel/8.log"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/var/log/kernel/9.log"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/var/log/kernel/latest.log"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/lib/array"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/boot/cc/boot.cc"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/home"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/usr/share/doc/kernel/drivers/disk.md"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/lib/LibDeflate"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/sys/fs/meta.ltn"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/var/log/kernel/0.log"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/var/log/kernel/bootData"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/sys/api/string.lua"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/var/log"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/bin/shell.hex"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/opt/astronand/dbg/init"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/boot/bootloader.sys"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/lib/array/2d"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/boot/cc"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/boot/ac/boot.ac"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/var/log/kernel/2.log"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/sys/modules/ccpc.disk.kd"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/sys/api/require.lua"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/bin/lua.lua"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/usr/share/doc/kernel"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/boot"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/sys/fs"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/var/system"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/sys/modules/cc.terminal.kd"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
,["/opt/astronand"]={["p"]=21,["o"]=0,["g"]=0}
|
||||||
|
}
|
||||||
75
src/disks/1h/sys/modules/ac.disks.kd
Normal file
75
src/disks/1h/sys/modules/ac.disks.kd
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
local kernelArgs={...}
|
||||||
|
local apis=kernelArgs[1]
|
||||||
|
local drivers=kernelArgs[2]
|
||||||
|
local log=kernelArgs[3]
|
||||||
|
local driver={}
|
||||||
|
local disks = {}
|
||||||
|
|
||||||
|
driver.type = "disk"
|
||||||
|
driver.name = "AC:Disk"
|
||||||
|
driver.version = "1.0.0"
|
||||||
|
driver.apiVersion = 1
|
||||||
|
driver.description = "Driver for AC disks"
|
||||||
|
driver.arch = "ac"
|
||||||
|
driver.api = {}
|
||||||
|
|
||||||
|
local function refreshDisks()
|
||||||
|
local tmp={}
|
||||||
|
for i,v in apis.component.list() do
|
||||||
|
if i=="disk" then
|
||||||
|
tmp[v.id]={
|
||||||
|
readAllText=function(path)
|
||||||
|
return v:open(path).read()
|
||||||
|
end,
|
||||||
|
writeAllText=function(path, content)
|
||||||
|
return v:open(path).write(content)
|
||||||
|
end,
|
||||||
|
list=function(path)
|
||||||
|
return v:list(path)
|
||||||
|
end,
|
||||||
|
delete=function(path)
|
||||||
|
return v:delete(path)
|
||||||
|
end,
|
||||||
|
makeDirectory=function(path)
|
||||||
|
return v:makeDirectory(path)
|
||||||
|
end,
|
||||||
|
makeFile=function(path)
|
||||||
|
return v:makeFile(path)
|
||||||
|
end,
|
||||||
|
directoryExists=function(path)
|
||||||
|
return v:directoryExists(path)
|
||||||
|
end,
|
||||||
|
fileExists=function(path)
|
||||||
|
return v:fileExists(path)
|
||||||
|
end
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
disks=tmp
|
||||||
|
end
|
||||||
|
|
||||||
|
function driver.init()
|
||||||
|
refreshDisks()
|
||||||
|
end
|
||||||
|
|
||||||
|
function driver.api.list()
|
||||||
|
local tmp={}
|
||||||
|
for i,v in pairs(disks) do
|
||||||
|
tmp[#tmp+1]={id=i, obj=v}
|
||||||
|
end
|
||||||
|
local i=0
|
||||||
|
return function()
|
||||||
|
i=i+1
|
||||||
|
if tmp[i]==nil then return end
|
||||||
|
return tmp.id, tmp.obj
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function driver.main()
|
||||||
|
while true do
|
||||||
|
refreshDisks()
|
||||||
|
sleep(5)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
drivers[#drivers+1]=driver
|
||||||
100
src/disks/1h/sys/modules/cc.disks.kd
Normal file
100
src/disks/1h/sys/modules/cc.disks.kd
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
local kernelArgs={...}
|
||||||
|
local apis=kernelArgs[1]
|
||||||
|
local drivers=kernelArgs[2]
|
||||||
|
local log=kernelArgs[3]
|
||||||
|
local driver={}
|
||||||
|
local disks={}
|
||||||
|
local driverutil=kernelArgs[4]
|
||||||
|
|
||||||
|
driver.type = "disk"
|
||||||
|
driver.name = "CC:Disks"
|
||||||
|
driver.version = "1.0.0"
|
||||||
|
driver.apiVersion = 1
|
||||||
|
driver.description = "Driver for CC:Tweaked disks"
|
||||||
|
driver.arch = "cc"
|
||||||
|
driver.api = {}
|
||||||
|
|
||||||
|
local function abs(path)
|
||||||
|
if path:sub(1,1)~="/" then path="/"..path end
|
||||||
|
return path
|
||||||
|
end
|
||||||
|
|
||||||
|
local function newDisk(root)
|
||||||
|
root="/"..root
|
||||||
|
return {
|
||||||
|
readAllText=function(path)
|
||||||
|
local file=apis.fs.open(root..abs(path),"r")
|
||||||
|
local text=file.readAll()
|
||||||
|
file.close()
|
||||||
|
return text
|
||||||
|
end,
|
||||||
|
writeAllText=function(path, content)
|
||||||
|
local file=apis.fs.open(root..abs(path),"w")
|
||||||
|
file.write(content)
|
||||||
|
file.close()
|
||||||
|
end,
|
||||||
|
list=function(path)
|
||||||
|
return apis.fs.list(root..abs(path))
|
||||||
|
end,
|
||||||
|
delete=function(path)
|
||||||
|
return apis.fs.delete(root..abs(path))
|
||||||
|
end,
|
||||||
|
makeDirectory=function(path)
|
||||||
|
return apis.fs.makeDir(root..abs(path))
|
||||||
|
end,
|
||||||
|
makeFile=function(path)
|
||||||
|
local file=apis.fs.open(root..abs(path),"w")
|
||||||
|
file.close()
|
||||||
|
end,
|
||||||
|
directoryExists=function(path)
|
||||||
|
return apis.fs.exists(root..abs(path)) and apis.fs.isDir(root..abs(path))
|
||||||
|
end,
|
||||||
|
fileExists=function(path)
|
||||||
|
return apis.fs.exists(root..abs(path)) and not apis.fs.isDir(root..abs(path))
|
||||||
|
end
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
local function refreshDisks(peripheral)
|
||||||
|
local tmp2={}
|
||||||
|
tmp2["disk"]=newDisk("disk")
|
||||||
|
for i,v in ipairs(peripheral.api.getNames()) do
|
||||||
|
if peripheral.api.isType(v, "drive") then
|
||||||
|
local p=peripheral.api.wrap(v)
|
||||||
|
if p.isDiskPresent() then
|
||||||
|
if p.getMountPath()~="disk" then
|
||||||
|
tmp2["disk_"..p.getID()] = newDisk(p.getMountPath())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
disks=tmp2
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function driver.init()
|
||||||
|
local peripheral=driverutil.getFirst("component")
|
||||||
|
refreshDisks(peripheral)
|
||||||
|
end
|
||||||
|
|
||||||
|
function driver.api.list()
|
||||||
|
local tmp={}
|
||||||
|
for i,v in pairs(disks) do
|
||||||
|
tmp[#tmp+1]={id=i, obj=v}
|
||||||
|
end
|
||||||
|
local i=0
|
||||||
|
return function()
|
||||||
|
i=i+1
|
||||||
|
if tmp[i]==nil then return end
|
||||||
|
return tmp[i].id, tmp[i].obj
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function driver.main()
|
||||||
|
while true do
|
||||||
|
refreshDisks()
|
||||||
|
sleep(5)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
drivers[#drivers+1] = driver
|
||||||
129
src/disks/1h/sys/modules/cc.periph.kd
Normal file
129
src/disks/1h/sys/modules/cc.periph.kd
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
local kernelArgs={...}
|
||||||
|
local apis=kernelArgs[1]
|
||||||
|
local drivers=kernelArgs[2]
|
||||||
|
local log=kernelArgs[3]
|
||||||
|
local driver={}
|
||||||
|
|
||||||
|
driver.type = "component"
|
||||||
|
driver.name = "CC:Periph"
|
||||||
|
driver.version = "1.0.0"
|
||||||
|
driver.apiVersion = 1
|
||||||
|
driver.description = "Driver for CC:Tweaked peripherals"
|
||||||
|
driver.arch = "cc"
|
||||||
|
driver.api = {}
|
||||||
|
|
||||||
|
local native,sides
|
||||||
|
if apis.peripheral then
|
||||||
|
native = apis.peripheral
|
||||||
|
sides = apis.rs.getSides()
|
||||||
|
end
|
||||||
|
|
||||||
|
function driver.api.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 driver.api.getType(peripheral)
|
||||||
|
if type(peripheral) == "string" then -- Peripheral name passed
|
||||||
|
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 driver.api.isType(peripheral, peripheral_type)
|
||||||
|
if type(peripheral) == "string" then -- Peripheral name passed
|
||||||
|
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 driver.api.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 driver.api.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 driver.api.wrap(name)
|
||||||
|
local methods = driver.api.getMethods(name)
|
||||||
|
if not methods then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local types = { driver.api.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 driver.api.call(name, method, ...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
drivers[#drivers+1] = driver
|
||||||
74
src/disks/1h/sys/modules/cc.terminal.kd
Normal file
74
src/disks/1h/sys/modules/cc.terminal.kd
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
local kernelArgs={...}
|
||||||
|
local apis=kernelArgs[1]
|
||||||
|
local drivers=kernelArgs[2]
|
||||||
|
local log=kernelArgs[3]
|
||||||
|
local driver={}
|
||||||
|
|
||||||
|
driver.type = "terminal"
|
||||||
|
driver.name = "CC:Term"
|
||||||
|
driver.version = "1.0.0"
|
||||||
|
driver.apiVersion = 1
|
||||||
|
driver.description = "Driver for CC:Tweaked screens"
|
||||||
|
driver.arch = "cc"
|
||||||
|
driver.api = {}
|
||||||
|
|
||||||
|
-- Prints text handling \n, \t, and \b with scrolling (no wrapping)
|
||||||
|
local function write(text)
|
||||||
|
local x, y = apis.term.getCursorPos()
|
||||||
|
local w, h = apis.term.getSize()
|
||||||
|
|
||||||
|
for i = 1, #text do
|
||||||
|
local c = text:sub(i, i)
|
||||||
|
|
||||||
|
if c == "\n" then
|
||||||
|
y = y + 1
|
||||||
|
x = 1
|
||||||
|
elseif c == "\t" then
|
||||||
|
local tabSize = 4
|
||||||
|
local spaces = tabSize - ((x - 1) % tabSize)
|
||||||
|
apis.term.write(string.rep(" ", spaces))
|
||||||
|
x = x + spaces
|
||||||
|
elseif c == "\b" then
|
||||||
|
if x > 1 then
|
||||||
|
x = x - 1
|
||||||
|
apis.term.setCursorPos(x, y)
|
||||||
|
apis.term.write(" ")
|
||||||
|
apis.term.setCursorPos(x, y)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if x <= w and y <= h then
|
||||||
|
apis.term.setCursorPos(x, y)
|
||||||
|
apis.term.write(c)
|
||||||
|
x = x + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Handle scrolling if we go past bottom
|
||||||
|
if y > h then
|
||||||
|
apis.term.scroll(1)
|
||||||
|
y = h
|
||||||
|
apis.term.setCursorPos(x, y)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
apis.term.setCursorPos(x, y)
|
||||||
|
end
|
||||||
|
|
||||||
|
function driver.api.print(text)
|
||||||
|
write(text.."\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
function driver.api.printInline(text)
|
||||||
|
write(text)
|
||||||
|
end
|
||||||
|
|
||||||
|
function driver.api.clear()
|
||||||
|
apis.term.clear()
|
||||||
|
apis.term.setCursorPos(1,1)
|
||||||
|
end
|
||||||
|
|
||||||
|
function driver.api.getSize()
|
||||||
|
return apis.term.getSize()
|
||||||
|
end
|
||||||
|
|
||||||
|
drivers[#drivers+1] = driver
|
||||||
0
src/disks/1h/sys/modules/ccpc.disk.kd
Normal file
0
src/disks/1h/sys/modules/ccpc.disk.kd
Normal file
0
src/disks/1h/sys/system/hypervisor/init
Normal file
0
src/disks/1h/sys/system/hypervisor/init
Normal file
0
src/disks/1h/sys/system/require
Normal file
0
src/disks/1h/sys/system/require
Normal file
3
src/disks/1h/sys/util/conhost.lua
Normal file
3
src/disks/1h/sys/util/conhost.lua
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
-- <!ARCH>
|
||||||
|
-- @ICON$101003000000000000092492492490080000000010082000000010080400000010080080000010080400000010082002492010080000000010092492492490000000000000092492492490080000000010080000000010092492492490000000000000
|
||||||
70
src/disks/1h/sys/util/logger.lua
Normal file
70
src/disks/1h/sys/util/logger.lua
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
local args={...}
|
||||||
|
local computer=args[1]
|
||||||
|
local logs={["nil"]=""}
|
||||||
|
local hooks={["nil"]=function()end}
|
||||||
|
local log={api={}}
|
||||||
|
|
||||||
|
local function convert_epoch(epoch)
|
||||||
|
return computer.date("[%b %d %H:%M:%S]", epoch/1000)
|
||||||
|
end
|
||||||
|
|
||||||
|
function log.getProcess(func)
|
||||||
|
if type(func)=="function" then
|
||||||
|
log.getProcess=func
|
||||||
|
else
|
||||||
|
return "Hyprkrnl"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function log.api.log(text, logID)
|
||||||
|
local appendedText=convert_epoch(computer.time()).." "..log.getProcess()..":[IN] "..text
|
||||||
|
logs[tostring(logID)]=logs[tostring(logID)]..appendedText.."\n"
|
||||||
|
hooks[tostring(logID)](appendedText)
|
||||||
|
end
|
||||||
|
|
||||||
|
function log.api.warn(text, logID)
|
||||||
|
local appendedText=convert_epoch(computer.time()).." "..log.getProcess()..":[WN] "..text
|
||||||
|
logs[tostring(logID)]=logs[tostring(logID)]..appendedText.."\n"
|
||||||
|
hooks[tostring(logID)](appendedText)
|
||||||
|
end
|
||||||
|
|
||||||
|
function log.api.fail(text, logID)
|
||||||
|
local appendedText=convert_epoch(computer.time()).." "..log.getProcess()..":[FA] "..text
|
||||||
|
logs[tostring(logID)]=logs[tostring(logID)]..appendedText.."\n"
|
||||||
|
hooks[tostring(logID)](appendedText)
|
||||||
|
end
|
||||||
|
|
||||||
|
function log.api.debug(text, logID)
|
||||||
|
local appendedText=convert_epoch(computer.time()).." "..log.getProcess()..":[DE] "..text
|
||||||
|
logs[tostring(logID)]=logs[tostring(logID)]..appendedText.."\n"
|
||||||
|
hooks[tostring(logID)](appendedText)
|
||||||
|
end
|
||||||
|
|
||||||
|
function log.api.error(text, logID)
|
||||||
|
local appendedText=convert_epoch(computer.time()).." "..log.getProcess()..":[ER] "..text
|
||||||
|
logs[tostring(logID)]=logs[tostring(logID)]..appendedText.."\n"
|
||||||
|
hooks[tostring(logID)](appendedText)
|
||||||
|
end
|
||||||
|
|
||||||
|
function log.api.get(logID)
|
||||||
|
return logs[tostring(logID)]
|
||||||
|
end
|
||||||
|
|
||||||
|
function log.setHook(func, logID)
|
||||||
|
hooks[tostring(logID)]=func
|
||||||
|
return {
|
||||||
|
removeHook=function()
|
||||||
|
hooks[tostring(logID)]=function()end
|
||||||
|
end
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
local UUID = 0
|
||||||
|
function log.api.createLog(logID)
|
||||||
|
if logs[tostring(logID)]~=nil then error("cannot create duplicate log") end
|
||||||
|
if logID==nil then UUID=UUID+1; logID=UUID end
|
||||||
|
hooks[tostring(logID)]=function()end
|
||||||
|
logs[tostring(logID)]=""
|
||||||
|
end
|
||||||
|
|
||||||
|
return log
|
||||||
6
src/disks/1h/usr/share/doc/kernel/drivers/disk.md
Normal file
6
src/disks/1h/usr/share/doc/kernel/drivers/disk.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
### API:
|
||||||
|
---
|
||||||
|
```
|
||||||
|
getDisks():id, obj
|
||||||
|
|
||||||
|
```
|
||||||
17
src/disks/1h/var/log/kernel/0.log
Normal file
17
src/disks/1h/var/log/kernel/0.log
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
[Oct 31 18:33:08] Hyprkrnl:[IN] Created logger
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[IN] Loading globals...
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[DE] Loading string.lua
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[DE] Loading table.lua
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[IN] Loading drivers...
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[DE] Loading module ac.disks.kd
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[DE] Loading module cc.disks.kd
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[DE] Loading module cc.periph.kd
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[DE] Loading module cc.terminal.kd
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[DE] Loading module ccpc.disk.kd
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[DE] Sorting drivers...
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[DE] Initializing drivers...
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[IN] Loaded 3 drivers
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[IN] Loading filesystem...
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[IN] Bootdrive is disk
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[IN] Loading system...
|
||||||
19
src/disks/1h/var/log/kernel/1.log
Normal file
19
src/disks/1h/var/log/kernel/1.log
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
[Oct 24 14:20:21] Hyprkrnl:[IN] Created logger
|
||||||
|
[Oct 24 14:20:21] Hyprkrnl:[IN] Loading globals...
|
||||||
|
[Oct 24 14:20:21] Hyprkrnl:[DE] Loading require.lua
|
||||||
|
[Oct 24 14:20:21] Hyprkrnl:[DE] Loading string.lua
|
||||||
|
[Oct 24 14:20:21] Hyprkrnl:[DE] Loading table.lua
|
||||||
|
[Oct 24 14:20:21] Hyprkrnl:[IN] Loading drivers...
|
||||||
|
[Oct 24 14:20:21] Hyprkrnl:[DE] Loading module ac.disks.kd
|
||||||
|
[Oct 24 14:20:21] Hyprkrnl:[DE] Loading module cc.disks.kd
|
||||||
|
[Oct 24 14:20:21] Hyprkrnl:[DE] Loading module cc.periph.kd
|
||||||
|
[Oct 24 14:20:21] Hyprkrnl:[DE] Loading module cc.terminal.kd
|
||||||
|
[Oct 24 14:20:21] Hyprkrnl:[DE] Loading module ccpc.disk.kd
|
||||||
|
[Oct 24 14:20:21] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
|
||||||
|
[Oct 24 14:20:21] Hyprkrnl:[DE] Sorting drivers...
|
||||||
|
[Oct 24 14:20:21] Hyprkrnl:[DE] Initializing drivers...
|
||||||
|
[Oct 24 14:20:21] Hyprkrnl:[IN] Loaded 3 drivers
|
||||||
|
[Oct 24 14:20:21] Hyprkrnl:[IN] Loading filesystem...
|
||||||
|
[Oct 24 14:20:21] Hyprkrnl:[IN] Bootdrive is disk
|
||||||
|
[Oct 24 14:20:21] Hyprkrnl:[IN] [REQUIRE]: Initialized FS
|
||||||
|
[Oct 24 14:20:21] Hyprkrnl:[IN] Loading hypervisor...
|
||||||
17
src/disks/1h/var/log/kernel/10.log
Normal file
17
src/disks/1h/var/log/kernel/10.log
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
[Oct 30 18:13:15] Hyprkrnl:[IN] Created logger
|
||||||
|
[Oct 30 18:13:15] Hyprkrnl:[IN] Loading globals...
|
||||||
|
[Oct 30 18:13:15] Hyprkrnl:[DE] Loading string.lua
|
||||||
|
[Oct 30 18:13:15] Hyprkrnl:[DE] Loading table.lua
|
||||||
|
[Oct 30 18:13:15] Hyprkrnl:[IN] Loading drivers...
|
||||||
|
[Oct 30 18:13:15] Hyprkrnl:[DE] Loading module ac.disks.kd
|
||||||
|
[Oct 30 18:13:15] Hyprkrnl:[DE] Loading module cc.disks.kd
|
||||||
|
[Oct 30 18:13:15] Hyprkrnl:[DE] Loading module cc.periph.kd
|
||||||
|
[Oct 30 18:13:15] Hyprkrnl:[DE] Loading module cc.terminal.kd
|
||||||
|
[Oct 30 18:13:15] Hyprkrnl:[DE] Loading module ccpc.disk.kd
|
||||||
|
[Oct 30 18:13:15] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
|
||||||
|
[Oct 30 18:13:15] Hyprkrnl:[DE] Sorting drivers...
|
||||||
|
[Oct 30 18:13:15] Hyprkrnl:[DE] Initializing drivers...
|
||||||
|
[Oct 30 18:13:15] Hyprkrnl:[IN] Loaded 3 drivers
|
||||||
|
[Oct 30 18:13:15] Hyprkrnl:[IN] Loading filesystem...
|
||||||
|
[Oct 30 18:13:15] Hyprkrnl:[IN] Bootdrive is disk
|
||||||
|
[Oct 30 18:13:15] Hyprkrnl:[IN] Loading system...
|
||||||
19
src/disks/1h/var/log/kernel/2.log
Normal file
19
src/disks/1h/var/log/kernel/2.log
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
[Oct 29 21:46:16] Hyprkrnl:[IN] Created logger
|
||||||
|
[Oct 29 21:46:17] Hyprkrnl:[IN] Loading globals...
|
||||||
|
[Oct 29 21:46:17] Hyprkrnl:[DE] Loading require.lua
|
||||||
|
[Oct 29 21:46:17] Hyprkrnl:[DE] Loading string.lua
|
||||||
|
[Oct 29 21:46:17] Hyprkrnl:[DE] Loading table.lua
|
||||||
|
[Oct 29 21:46:17] Hyprkrnl:[IN] Loading drivers...
|
||||||
|
[Oct 29 21:46:17] Hyprkrnl:[DE] Loading module ac.disks.kd
|
||||||
|
[Oct 29 21:46:17] Hyprkrnl:[DE] Loading module cc.disks.kd
|
||||||
|
[Oct 29 21:46:17] Hyprkrnl:[DE] Loading module cc.periph.kd
|
||||||
|
[Oct 29 21:46:17] Hyprkrnl:[DE] Loading module cc.terminal.kd
|
||||||
|
[Oct 29 21:46:17] Hyprkrnl:[DE] Loading module ccpc.disk.kd
|
||||||
|
[Oct 29 21:46:17] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
|
||||||
|
[Oct 29 21:46:17] Hyprkrnl:[DE] Sorting drivers...
|
||||||
|
[Oct 29 21:46:17] Hyprkrnl:[DE] Initializing drivers...
|
||||||
|
[Oct 29 21:46:17] Hyprkrnl:[IN] Loaded 3 drivers
|
||||||
|
[Oct 29 21:46:17] Hyprkrnl:[IN] Loading filesystem...
|
||||||
|
[Oct 29 21:46:17] Hyprkrnl:[IN] Bootdrive is disk
|
||||||
|
[Oct 29 21:46:17] Hyprkrnl:[IN] [REQUIRE]: Initialized FS
|
||||||
|
[Oct 29 21:46:17] Hyprkrnl:[IN] Loading hypervisor...
|
||||||
19
src/disks/1h/var/log/kernel/3.log
Normal file
19
src/disks/1h/var/log/kernel/3.log
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
[Oct 29 21:46:38] Hyprkrnl:[IN] Created logger
|
||||||
|
[Oct 29 21:46:38] Hyprkrnl:[IN] Loading globals...
|
||||||
|
[Oct 29 21:46:38] Hyprkrnl:[DE] Loading require.lua
|
||||||
|
[Oct 29 21:46:38] Hyprkrnl:[DE] Loading string.lua
|
||||||
|
[Oct 29 21:46:38] Hyprkrnl:[DE] Loading table.lua
|
||||||
|
[Oct 29 21:46:38] Hyprkrnl:[IN] Loading drivers...
|
||||||
|
[Oct 29 21:46:38] Hyprkrnl:[DE] Loading module ac.disks.kd
|
||||||
|
[Oct 29 21:46:38] Hyprkrnl:[DE] Loading module cc.disks.kd
|
||||||
|
[Oct 29 21:46:38] Hyprkrnl:[DE] Loading module cc.periph.kd
|
||||||
|
[Oct 29 21:46:38] Hyprkrnl:[DE] Loading module cc.terminal.kd
|
||||||
|
[Oct 29 21:46:38] Hyprkrnl:[DE] Loading module ccpc.disk.kd
|
||||||
|
[Oct 29 21:46:38] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
|
||||||
|
[Oct 29 21:46:38] Hyprkrnl:[DE] Sorting drivers...
|
||||||
|
[Oct 29 21:46:38] Hyprkrnl:[DE] Initializing drivers...
|
||||||
|
[Oct 29 21:46:38] Hyprkrnl:[IN] Loaded 3 drivers
|
||||||
|
[Oct 29 21:46:38] Hyprkrnl:[IN] Loading filesystem...
|
||||||
|
[Oct 29 21:46:38] Hyprkrnl:[IN] Bootdrive is disk
|
||||||
|
[Oct 29 21:46:38] Hyprkrnl:[IN] [REQUIRE]: Initialized FS
|
||||||
|
[Oct 29 21:46:38] Hyprkrnl:[IN] Loading hypervisor...
|
||||||
19
src/disks/1h/var/log/kernel/4.log
Normal file
19
src/disks/1h/var/log/kernel/4.log
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
[Oct 30 17:41:54] Hyprkrnl:[IN] Created logger
|
||||||
|
[Oct 30 17:41:54] Hyprkrnl:[IN] Loading globals...
|
||||||
|
[Oct 30 17:41:54] Hyprkrnl:[DE] Loading require.lua
|
||||||
|
[Oct 30 17:41:54] Hyprkrnl:[DE] Loading string.lua
|
||||||
|
[Oct 30 17:41:54] Hyprkrnl:[DE] Loading table.lua
|
||||||
|
[Oct 30 17:41:54] Hyprkrnl:[IN] Loading drivers...
|
||||||
|
[Oct 30 17:41:54] Hyprkrnl:[DE] Loading module ac.disks.kd
|
||||||
|
[Oct 30 17:41:54] Hyprkrnl:[DE] Loading module cc.disks.kd
|
||||||
|
[Oct 30 17:41:54] Hyprkrnl:[DE] Loading module cc.periph.kd
|
||||||
|
[Oct 30 17:41:54] Hyprkrnl:[DE] Loading module cc.terminal.kd
|
||||||
|
[Oct 30 17:41:54] Hyprkrnl:[DE] Loading module ccpc.disk.kd
|
||||||
|
[Oct 30 17:41:54] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
|
||||||
|
[Oct 30 17:41:54] Hyprkrnl:[DE] Sorting drivers...
|
||||||
|
[Oct 30 17:41:54] Hyprkrnl:[DE] Initializing drivers...
|
||||||
|
[Oct 30 17:41:54] Hyprkrnl:[IN] Loaded 3 drivers
|
||||||
|
[Oct 30 17:41:54] Hyprkrnl:[IN] Loading filesystem...
|
||||||
|
[Oct 30 17:41:54] Hyprkrnl:[IN] Bootdrive is disk
|
||||||
|
[Oct 30 17:41:54] Hyprkrnl:[IN] [REQUIRE]: Initialized FS
|
||||||
|
[Oct 30 17:41:54] Hyprkrnl:[IN] Loading hypervisor...
|
||||||
19
src/disks/1h/var/log/kernel/5.log
Normal file
19
src/disks/1h/var/log/kernel/5.log
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
[Oct 30 17:43:09] Hyprkrnl:[IN] Created logger
|
||||||
|
[Oct 30 17:43:09] Hyprkrnl:[IN] Loading globals...
|
||||||
|
[Oct 30 17:43:09] Hyprkrnl:[DE] Loading require.lua
|
||||||
|
[Oct 30 17:43:09] Hyprkrnl:[DE] Loading string.lua
|
||||||
|
[Oct 30 17:43:09] Hyprkrnl:[DE] Loading table.lua
|
||||||
|
[Oct 30 17:43:09] Hyprkrnl:[IN] Loading drivers...
|
||||||
|
[Oct 30 17:43:09] Hyprkrnl:[DE] Loading module ac.disks.kd
|
||||||
|
[Oct 30 17:43:09] Hyprkrnl:[DE] Loading module cc.disks.kd
|
||||||
|
[Oct 30 17:43:09] Hyprkrnl:[DE] Loading module cc.periph.kd
|
||||||
|
[Oct 30 17:43:09] Hyprkrnl:[DE] Loading module cc.terminal.kd
|
||||||
|
[Oct 30 17:43:09] Hyprkrnl:[DE] Loading module ccpc.disk.kd
|
||||||
|
[Oct 30 17:43:09] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
|
||||||
|
[Oct 30 17:43:09] Hyprkrnl:[DE] Sorting drivers...
|
||||||
|
[Oct 30 17:43:09] Hyprkrnl:[DE] Initializing drivers...
|
||||||
|
[Oct 30 17:43:09] Hyprkrnl:[IN] Loaded 3 drivers
|
||||||
|
[Oct 30 17:43:09] Hyprkrnl:[IN] Loading filesystem...
|
||||||
|
[Oct 30 17:43:09] Hyprkrnl:[IN] Bootdrive is disk
|
||||||
|
[Oct 30 17:43:09] Hyprkrnl:[IN] [REQUIRE]: Initialized FS
|
||||||
|
[Oct 30 17:43:09] Hyprkrnl:[IN] Loading hypervisor...
|
||||||
19
src/disks/1h/var/log/kernel/6.log
Normal file
19
src/disks/1h/var/log/kernel/6.log
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
[Oct 30 17:44:55] Hyprkrnl:[IN] Created logger
|
||||||
|
[Oct 30 17:44:55] Hyprkrnl:[IN] Loading globals...
|
||||||
|
[Oct 30 17:44:55] Hyprkrnl:[DE] Loading require.lua
|
||||||
|
[Oct 30 17:44:55] Hyprkrnl:[DE] Loading string.lua
|
||||||
|
[Oct 30 17:44:55] Hyprkrnl:[DE] Loading table.lua
|
||||||
|
[Oct 30 17:44:55] Hyprkrnl:[IN] Loading drivers...
|
||||||
|
[Oct 30 17:44:55] Hyprkrnl:[DE] Loading module ac.disks.kd
|
||||||
|
[Oct 30 17:44:55] Hyprkrnl:[DE] Loading module cc.disks.kd
|
||||||
|
[Oct 30 17:44:55] Hyprkrnl:[DE] Loading module cc.periph.kd
|
||||||
|
[Oct 30 17:44:55] Hyprkrnl:[DE] Loading module cc.terminal.kd
|
||||||
|
[Oct 30 17:44:55] Hyprkrnl:[DE] Loading module ccpc.disk.kd
|
||||||
|
[Oct 30 17:44:55] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
|
||||||
|
[Oct 30 17:44:55] Hyprkrnl:[DE] Sorting drivers...
|
||||||
|
[Oct 30 17:44:55] Hyprkrnl:[DE] Initializing drivers...
|
||||||
|
[Oct 30 17:44:55] Hyprkrnl:[IN] Loaded 3 drivers
|
||||||
|
[Oct 30 17:44:55] Hyprkrnl:[IN] Loading filesystem...
|
||||||
|
[Oct 30 17:44:55] Hyprkrnl:[IN] Bootdrive is disk
|
||||||
|
[Oct 30 17:44:55] Hyprkrnl:[IN] [REQUIRE]: Initialized FS
|
||||||
|
[Oct 30 17:44:55] Hyprkrnl:[IN] Loading hypervisor...
|
||||||
19
src/disks/1h/var/log/kernel/7.log
Normal file
19
src/disks/1h/var/log/kernel/7.log
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
[Oct 30 17:45:15] Hyprkrnl:[IN] Created logger
|
||||||
|
[Oct 30 17:45:15] Hyprkrnl:[IN] Loading globals...
|
||||||
|
[Oct 30 17:45:15] Hyprkrnl:[DE] Loading require.lua
|
||||||
|
[Oct 30 17:45:15] Hyprkrnl:[DE] Loading string.lua
|
||||||
|
[Oct 30 17:45:15] Hyprkrnl:[DE] Loading table.lua
|
||||||
|
[Oct 30 17:45:15] Hyprkrnl:[IN] Loading drivers...
|
||||||
|
[Oct 30 17:45:15] Hyprkrnl:[DE] Loading module ac.disks.kd
|
||||||
|
[Oct 30 17:45:15] Hyprkrnl:[DE] Loading module cc.disks.kd
|
||||||
|
[Oct 30 17:45:15] Hyprkrnl:[DE] Loading module cc.periph.kd
|
||||||
|
[Oct 30 17:45:15] Hyprkrnl:[DE] Loading module cc.terminal.kd
|
||||||
|
[Oct 30 17:45:15] Hyprkrnl:[DE] Loading module ccpc.disk.kd
|
||||||
|
[Oct 30 17:45:15] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
|
||||||
|
[Oct 30 17:45:15] Hyprkrnl:[DE] Sorting drivers...
|
||||||
|
[Oct 30 17:45:15] Hyprkrnl:[DE] Initializing drivers...
|
||||||
|
[Oct 30 17:45:15] Hyprkrnl:[IN] Loaded 3 drivers
|
||||||
|
[Oct 30 17:45:15] Hyprkrnl:[IN] Loading filesystem...
|
||||||
|
[Oct 30 17:45:15] Hyprkrnl:[IN] Bootdrive is disk
|
||||||
|
[Oct 30 17:45:15] Hyprkrnl:[IN] [REQUIRE]: Initialized FS
|
||||||
|
[Oct 30 17:45:15] Hyprkrnl:[IN] Loading hypervisor...
|
||||||
19
src/disks/1h/var/log/kernel/8.log
Normal file
19
src/disks/1h/var/log/kernel/8.log
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
[Oct 30 18:02:54] Hyprkrnl:[IN] Created logger
|
||||||
|
[Oct 30 18:02:54] Hyprkrnl:[IN] Loading globals...
|
||||||
|
[Oct 30 18:02:54] Hyprkrnl:[DE] Loading require.lua
|
||||||
|
[Oct 30 18:02:54] Hyprkrnl:[DE] Loading string.lua
|
||||||
|
[Oct 30 18:02:54] Hyprkrnl:[DE] Loading table.lua
|
||||||
|
[Oct 30 18:02:54] Hyprkrnl:[IN] Loading drivers...
|
||||||
|
[Oct 30 18:02:54] Hyprkrnl:[DE] Loading module ac.disks.kd
|
||||||
|
[Oct 30 18:02:54] Hyprkrnl:[DE] Loading module cc.disks.kd
|
||||||
|
[Oct 30 18:02:54] Hyprkrnl:[DE] Loading module cc.periph.kd
|
||||||
|
[Oct 30 18:02:54] Hyprkrnl:[DE] Loading module cc.terminal.kd
|
||||||
|
[Oct 30 18:02:54] Hyprkrnl:[DE] Loading module ccpc.disk.kd
|
||||||
|
[Oct 30 18:02:54] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
|
||||||
|
[Oct 30 18:02:54] Hyprkrnl:[DE] Sorting drivers...
|
||||||
|
[Oct 30 18:02:54] Hyprkrnl:[DE] Initializing drivers...
|
||||||
|
[Oct 30 18:02:54] Hyprkrnl:[IN] Loaded 3 drivers
|
||||||
|
[Oct 30 18:02:54] Hyprkrnl:[IN] Loading filesystem...
|
||||||
|
[Oct 30 18:02:54] Hyprkrnl:[IN] Bootdrive is disk
|
||||||
|
[Oct 30 18:02:54] Hyprkrnl:[IN] [REQUIRE]: Initialized FS
|
||||||
|
[Oct 30 18:02:54] Hyprkrnl:[IN] Loading hypervisor...
|
||||||
19
src/disks/1h/var/log/kernel/9.log
Normal file
19
src/disks/1h/var/log/kernel/9.log
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
[Oct 30 18:03:46] Hyprkrnl:[IN] Created logger
|
||||||
|
[Oct 30 18:03:46] Hyprkrnl:[IN] Loading globals...
|
||||||
|
[Oct 30 18:03:46] Hyprkrnl:[DE] Loading require.lua
|
||||||
|
[Oct 30 18:03:46] Hyprkrnl:[DE] Loading string.lua
|
||||||
|
[Oct 30 18:03:46] Hyprkrnl:[DE] Loading table.lua
|
||||||
|
[Oct 30 18:03:46] Hyprkrnl:[IN] Loading drivers...
|
||||||
|
[Oct 30 18:03:46] Hyprkrnl:[DE] Loading module ac.disks.kd
|
||||||
|
[Oct 30 18:03:46] Hyprkrnl:[DE] Loading module cc.disks.kd
|
||||||
|
[Oct 30 18:03:46] Hyprkrnl:[DE] Loading module cc.periph.kd
|
||||||
|
[Oct 30 18:03:46] Hyprkrnl:[DE] Loading module cc.terminal.kd
|
||||||
|
[Oct 30 18:03:46] Hyprkrnl:[DE] Loading module ccpc.disk.kd
|
||||||
|
[Oct 30 18:03:46] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
|
||||||
|
[Oct 30 18:03:46] Hyprkrnl:[DE] Sorting drivers...
|
||||||
|
[Oct 30 18:03:46] Hyprkrnl:[DE] Initializing drivers...
|
||||||
|
[Oct 30 18:03:46] Hyprkrnl:[IN] Loaded 3 drivers
|
||||||
|
[Oct 30 18:03:46] Hyprkrnl:[IN] Loading filesystem...
|
||||||
|
[Oct 30 18:03:46] Hyprkrnl:[IN] Bootdrive is disk
|
||||||
|
[Oct 30 18:03:46] Hyprkrnl:[IN] [REQUIRE]: Initialized FS
|
||||||
|
[Oct 30 18:03:46] Hyprkrnl:[IN] Loading hypervisor...
|
||||||
2
src/disks/1h/var/log/kernel/bootData
Normal file
2
src/disks/1h/var/log/kernel/bootData
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
{["debug"]=true,["errorCount"]=1,["logNum"]=1,["prevError"]=[=[Hyperion failed to load:
|
||||||
|
Hyperion was: nil]=]}
|
||||||
17
src/disks/1h/var/log/kernel/latest.log
Normal file
17
src/disks/1h/var/log/kernel/latest.log
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
[Oct 31 18:33:08] Hyprkrnl:[IN] Created logger
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[IN] Loading globals...
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[DE] Loading string.lua
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[DE] Loading table.lua
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[IN] Loading drivers...
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[DE] Loading module ac.disks.kd
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[DE] Loading module cc.disks.kd
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[DE] Loading module cc.periph.kd
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[DE] Loading module cc.terminal.kd
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[DE] Loading module ccpc.disk.kd
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[IN] Unloading non "cc" specific drivers...
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[DE] Sorting drivers...
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[DE] Initializing drivers...
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[IN] Loaded 3 drivers
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[IN] Loading filesystem...
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[IN] Bootdrive is disk
|
||||||
|
[Oct 31 18:33:08] Hyprkrnl:[IN] Loading system...
|
||||||
14
src/disks/2f/burn.lua
Normal file
14
src/disks/2f/burn.lua
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
local biosData = ({...})[1]
|
||||||
|
local disks = {}
|
||||||
|
|
||||||
|
for i,v in component.list() do
|
||||||
|
if i == "disk" then
|
||||||
|
disks[v.id]=v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local bootDisk = disks[biosData.bootDrive.open("/config").read()]
|
||||||
|
|
||||||
|
if not bootDisk.type=="udd" then
|
||||||
|
error("invalid")
|
||||||
|
end
|
||||||
1
src/disks/2f/config
Normal file
1
src/disks/2f/config
Normal file
@@ -0,0 +1 @@
|
|||||||
|
disk_56
|
||||||
0
src/disks/3h/boot/Hyprkrnl.sys
Normal file
0
src/disks/3h/boot/Hyprkrnl.sys
Normal file
50
src/disks/3h/boot/ac/boot.ac
Normal file
50
src/disks/3h/boot/ac/boot.ac
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
local biosData = ({...})[1]
|
||||||
|
local apis={}
|
||||||
|
|
||||||
|
local lua = {
|
||||||
|
coroutine = true,
|
||||||
|
debug = true,
|
||||||
|
_HOST = true,
|
||||||
|
_VERSION = true,
|
||||||
|
assert = true,
|
||||||
|
collectgarbage = true,
|
||||||
|
error = true,
|
||||||
|
gcinfo = true,
|
||||||
|
getfenv = true,
|
||||||
|
getmetatable = true,
|
||||||
|
ipairs = true,
|
||||||
|
__inext = true,
|
||||||
|
load = true,
|
||||||
|
math = true,
|
||||||
|
next = true,
|
||||||
|
pairs = true,
|
||||||
|
pcall = true,
|
||||||
|
rawequal = true,
|
||||||
|
rawget = true,
|
||||||
|
rawlen = true,
|
||||||
|
rawset = true,
|
||||||
|
select = true,
|
||||||
|
setfenv = true,
|
||||||
|
setmetatable = true,
|
||||||
|
string = true,
|
||||||
|
table = true,
|
||||||
|
tonumber = true,
|
||||||
|
tostring = true,
|
||||||
|
type = true,
|
||||||
|
xpcall = true
|
||||||
|
}
|
||||||
|
|
||||||
|
for i,v in ipairs(_G) do
|
||||||
|
if not lua[i] then
|
||||||
|
apis[i]=v
|
||||||
|
_G[i]=nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getFile(path)
|
||||||
|
return biosData.bootDrive:open(path).read()
|
||||||
|
end
|
||||||
|
|
||||||
|
local computer = apis.component.getFirst("computer")
|
||||||
|
local kernel = load(getFile("/boot/Hyprkrnl.sys"), "@kernel", "t", _G)
|
||||||
|
kernel("ac", apis, biosData.bootDrive.id, apis.component.getFirst("screen"), computer.getMachineEvent)
|
||||||
119
src/disks/3h/boot/cc/boot.cc
Normal file
119
src/disks/3h/boot/cc/boot.cc
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
-- UnBIOS by JackMacWindows
|
||||||
|
-- This will undo most of the changes/additions made in the BIOS, but some things may remain wrapped if `debug` is unavailable
|
||||||
|
-- To use, just place a `bios.lua` in the root of the drive, and run this program
|
||||||
|
-- Here's a list of things that are irreversibly changed:
|
||||||
|
-- * both `bit` and `bit32` are kept for compatibility
|
||||||
|
-- * string metatable blocking (on old versions of CC)
|
||||||
|
-- In addition, if `debug` is not available these things are also irreversibly changed:
|
||||||
|
-- * old Lua 5.1 `load` function (for loading from a function)
|
||||||
|
-- * `loadstring` prefixing (before CC:T 1.96.0)
|
||||||
|
-- * `http.request`
|
||||||
|
-- * `os.shutdown` and `os.reboot`
|
||||||
|
-- * `peripheral`
|
||||||
|
-- * `turtle.equip[Left|Right]`
|
||||||
|
-- Licensed under the MIT license
|
||||||
|
if _HOST:find("UnBIOS") then return end
|
||||||
|
local keptAPIs = {keys=true, bit32 = true, bit = true, ccemux = true, config = true, coroutine = true, debug = true, fs = true, http = true, mounter = true, os = true, periphemu = true, peripheral = true, redstone = true, rs = true, term = true, utf8 = true, _HOST = true, _CC_DEFAULT_SETTINGS = true, _CC_DISABLE_LUA51_FEATURES = true, _VERSION = true, assert = true, collectgarbage = true, error = true, gcinfo = true, getfenv = true, getmetatable = true, ipairs = true, __inext = true,load = true, loadstring = true, math = true, newproxy = true, next = true, pairs = true, pcall = true, rawequal = true, rawget = true, rawlen = true, rawset = true, select = true, setfenv = true, setmetatable = true, string = true, table = true, tonumber = true, tostring = true, type = true, unpack = true, xpcall = true, turtle = true, pocket = true, commands = true, _G = true}
|
||||||
|
local t = {}
|
||||||
|
for k in pairs(_G) do if not keptAPIs[k] then table.insert(t, k) end end
|
||||||
|
for _,k in ipairs(t) do _G[k] = nil end
|
||||||
|
local native = _G.term.native()
|
||||||
|
for _, method in ipairs {"nativePaletteColor", "nativePaletteColour", "screenshot"} do native[method] = _G.term[method] end
|
||||||
|
_G.term = native
|
||||||
|
if _G.http then
|
||||||
|
_G.http.checkURL = _G.http.checkURLAsync
|
||||||
|
_G.http.websocket = _G.http.websocketAsync
|
||||||
|
end
|
||||||
|
if _G.commands then _G.commands = _G.commands.native end
|
||||||
|
if _G.turtle then _G.turtle.native, _G.turtle.craft = nil end
|
||||||
|
local delete = {os = {"version", "pullEventRaw", "pullEvent", "run", "loadAPI", "unloadAPI", "sleep"}, http = _G.http and {"get", "post", "put", "delete", "patch", "options", "head", "trace", "listen", "checkURLAsync", "websocketAsync"}, fs = {"complete", "isDriveRoot"}}
|
||||||
|
for k,v in pairs(delete) do for _,a in ipairs(v) do _G[k][a] = nil end end
|
||||||
|
_G._HOST = _G._HOST .. " (UnBIOS)"
|
||||||
|
-- Set up TLCO
|
||||||
|
-- This functions by crashing `rednet.run` by removing `os.pullEventRaw`. Normally
|
||||||
|
-- this would cause `parallel` to throw an error, but we replace `error` with an
|
||||||
|
-- empty placeholder to let it continue and return without throwing. This results
|
||||||
|
-- in the `pcall` returning successfully, preventing the error-displaying code
|
||||||
|
-- from running - essentially making it so that `os.shutdown` is called immediately
|
||||||
|
-- after the new BIOS exits.
|
||||||
|
--
|
||||||
|
-- From there, the setup code is placed in `term.native` since it's the first
|
||||||
|
-- thing called after `parallel` exits. This loads the new BIOS and prepares it
|
||||||
|
-- for execution. Finally, it overwrites `os.shutdown` with the new function to
|
||||||
|
-- allow it to be the last function called in the original BIOS, and returns.
|
||||||
|
-- From there execution continues, calling the `term.redirect` dummy, skipping
|
||||||
|
-- over the error-handling code (since `pcall` returned ok), and calling
|
||||||
|
-- `os.shutdown()`. The real `os.shutdown` is re-added, and the new BIOS is tail
|
||||||
|
-- called, which effectively makes it run as the main chunk.
|
||||||
|
local olderror = error
|
||||||
|
_G.error = function() end
|
||||||
|
_G.term.redirect = function() end
|
||||||
|
function _G.term.native()
|
||||||
|
_G.term.native = nil
|
||||||
|
_G.term.redirect = nil
|
||||||
|
_G.error = olderror
|
||||||
|
term.setBackgroundColor(32768)
|
||||||
|
term.setTextColor(1)
|
||||||
|
term.setCursorPos(1, 1)
|
||||||
|
term.setCursorBlink(true)
|
||||||
|
term.clear()
|
||||||
|
local file = fs.open("/boot/cc/bootloader.cc", "r")
|
||||||
|
if file == nil then
|
||||||
|
term.setCursorBlink(false)
|
||||||
|
term.setTextColor(16384)
|
||||||
|
term.write("Could not find /boot/cc/bootloader.cc. UnBIOS cannot continue.")
|
||||||
|
term.setCursorPos(1, 2)
|
||||||
|
term.write("Press any key to continue")
|
||||||
|
coroutine.yield("key")
|
||||||
|
os.shutdown()
|
||||||
|
end
|
||||||
|
local fn, err = loadstring(file.readAll(), "@bootloader.cc")
|
||||||
|
file.close()
|
||||||
|
if fn == nil then
|
||||||
|
term.setCursorBlink(false)
|
||||||
|
term.setTextColor(16384)
|
||||||
|
term.write("Could not load /boot/cc/bootloader.cc. UnBIOS cannot continue.")
|
||||||
|
term.setCursorPos(1, 2)
|
||||||
|
term.write(err)
|
||||||
|
term.setCursorPos(1, 3)
|
||||||
|
term.write("Press any key to continue")
|
||||||
|
coroutine.yield("key")
|
||||||
|
os.shutdown()
|
||||||
|
end
|
||||||
|
setfenv(fn, _G)
|
||||||
|
local oldshutdown = os.shutdown
|
||||||
|
os.shutdown = function()
|
||||||
|
os.shutdown = oldshutdown
|
||||||
|
return fn()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if debug then
|
||||||
|
-- Restore functions that were overwritten in the BIOS
|
||||||
|
-- Apparently this has to be done *after* redefining term.native
|
||||||
|
local function restoreValue(tab, idx, name, hint)
|
||||||
|
local i, key, value = 1, debug.getupvalue(tab[idx], hint)
|
||||||
|
while key ~= name and key ~= nil do
|
||||||
|
key, value = debug.getupvalue(tab[idx], i)
|
||||||
|
i=i+1
|
||||||
|
end
|
||||||
|
tab[idx] = value or tab[idx]
|
||||||
|
end
|
||||||
|
restoreValue(_G, "loadstring", "nativeloadstring", 1)
|
||||||
|
restoreValue(_G, "load", "nativeload", 5)
|
||||||
|
if http then restoreValue(http, "request", "nativeHTTPRequest", 3) end
|
||||||
|
restoreValue(os, "shutdown", "nativeShutdown", 1)
|
||||||
|
restoreValue(os, "reboot", "nativeReboot", 1)
|
||||||
|
if turtle then
|
||||||
|
restoreValue(turtle, "equipLeft", "v", 1)
|
||||||
|
restoreValue(turtle, "equipRight", "v", 1)
|
||||||
|
end
|
||||||
|
do
|
||||||
|
local i, key, value = 1, debug.getupvalue(peripheral.isPresent, 2)
|
||||||
|
while key ~= "native" and key ~= nil do
|
||||||
|
key, value = debug.getupvalue(peripheral.isPresent, i)
|
||||||
|
i=i+1
|
||||||
|
end
|
||||||
|
_G.peripheral = value or peripheral
|
||||||
|
end
|
||||||
|
end
|
||||||
|
os.shutdown()
|
||||||
115
src/disks/3h/boot/cc/bootloader.cc
Normal file
115
src/disks/3h/boot/cc/bootloader.cc
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
local apis={}
|
||||||
|
|
||||||
|
local lua = {
|
||||||
|
coroutine = true,
|
||||||
|
debug = true,
|
||||||
|
_HOST = true,
|
||||||
|
_VERSION = true,
|
||||||
|
assert = true,
|
||||||
|
collectgarbage = true,
|
||||||
|
error = true,
|
||||||
|
gcinfo = true,
|
||||||
|
getfenv = true,
|
||||||
|
getmetatable = true,
|
||||||
|
ipairs = true,
|
||||||
|
__inext = true,
|
||||||
|
load = true,
|
||||||
|
math = true,
|
||||||
|
next = true,
|
||||||
|
pairs = true,
|
||||||
|
pcall = true,
|
||||||
|
rawequal = true,
|
||||||
|
rawget = true,
|
||||||
|
rawlen = true,
|
||||||
|
rawset = true,
|
||||||
|
select = true,
|
||||||
|
setfenv = true,
|
||||||
|
setmetatable = true,
|
||||||
|
string = true,
|
||||||
|
table = true,
|
||||||
|
tonumber = true,
|
||||||
|
tostring = true,
|
||||||
|
type = true,
|
||||||
|
xpcall = true
|
||||||
|
}
|
||||||
|
|
||||||
|
for i,v in ipairs(_G) do
|
||||||
|
if not lua[i] then
|
||||||
|
apis[i]=v
|
||||||
|
_G[i]=nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getFile(path)
|
||||||
|
if path:sub(1,1) ~= "/" then
|
||||||
|
path="/"..path
|
||||||
|
end
|
||||||
|
local file = apis.fs.open("/root"..path)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function write(text)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
local event_queue = {}
|
||||||
|
local function addEventRaw(...)
|
||||||
|
event_queue[#event_queue+1] = {...}
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getEvent()
|
||||||
|
local event = event_queue[1]
|
||||||
|
event_queue = {table.unpack(event_queue, 2)}
|
||||||
|
return table.unpack(event)
|
||||||
|
end
|
||||||
|
|
||||||
|
local lkeys={}
|
||||||
|
lkeys[keys.enter]="\n"
|
||||||
|
lkeys[keys.backspace]="\b"
|
||||||
|
lkeys[keys.tab]="\t"
|
||||||
|
|
||||||
|
local kernel = load(getFile("/boot/Hyprkrnl.sys"), "@kernel", "t", _G)
|
||||||
|
local kernel_coro = coroutine.create(function()
|
||||||
|
kernel("cc", apis, "internal", {
|
||||||
|
print=function(text)
|
||||||
|
write(text)
|
||||||
|
write("\n")
|
||||||
|
end,
|
||||||
|
printInline=function(text)
|
||||||
|
write(text)
|
||||||
|
end,
|
||||||
|
clear=function()
|
||||||
|
apis.term.clear()
|
||||||
|
apis.term.setCursorPos(1,1)
|
||||||
|
end
|
||||||
|
}, getEvent)
|
||||||
|
end)
|
||||||
|
|
||||||
|
debug.sethook(kernel_coro, function() coroutine.yield("CC:TWEAKED", "CORO_TIMEOUT") end, "l", 3000)
|
||||||
|
while true do
|
||||||
|
local ret = {coroutine.resume(kernel_coro)}
|
||||||
|
if coroutine.status(kernel_coro) == "dead" then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
local timer = os.startTimer(0)
|
||||||
|
local exit = false
|
||||||
|
repeat
|
||||||
|
local event = {coroutine.yield()}
|
||||||
|
if event[1] == "timer" and event[2]==timer then
|
||||||
|
exit=true
|
||||||
|
elseif event[1]==nil then
|
||||||
|
elseif event[1]=="key" then
|
||||||
|
addEventRaw("keyPressed", 1, event[2])
|
||||||
|
if lkeys[event[2]] then
|
||||||
|
addEventRaw("keyTyped", 1, lkeys[event[2]])
|
||||||
|
end
|
||||||
|
elseif event[1]=="char" then
|
||||||
|
addEventRaw("keyTyped", 1, event[2])
|
||||||
|
elseif event[1]=="key_up" then
|
||||||
|
addEventRaw("keyReleased", 1, event[2])
|
||||||
|
elseif event[1]=="disk" then
|
||||||
|
addEventRaw("componentAdded", "disk", sandboxedFS.new(api.disk.getMountPath(event[2]), apis.disk.getID(event[2])))
|
||||||
|
elseif event[1]=="disk_eject" then
|
||||||
|
addEventRaw("componentRemoved", "disk")
|
||||||
|
end
|
||||||
|
until exit
|
||||||
|
end
|
||||||
0
src/disks/3h/boot/cc/sandboxedFS.cc
Normal file
0
src/disks/3h/boot/cc/sandboxedFS.cc
Normal file
2
src/disks/45h/bin_/beep
Normal file
2
src/disks/45h/bin_/beep
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
local computer=component.getFirst("computer")
|
||||||
|
computer.beep(800, 0.2, 1)
|
||||||
2
src/disks/45h/bin_/clear
Normal file
2
src/disks/45h/bin_/clear
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
local term=component.getFirst("screen")
|
||||||
|
term.clear()
|
||||||
17
src/disks/45h/bin_/debug
Normal file
17
src/disks/45h/bin_/debug
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
local args={...}
|
||||||
|
local term=component.getFirst("screen")
|
||||||
|
local hpv=require("hypervisor")
|
||||||
|
local fs=require("filesystem")
|
||||||
|
if not (fs.exists("/bin/"..args[1]) and (not fs.isDir("/bin/"..args[1]))) then error("not a file") end
|
||||||
|
local handle = hpv.createProcessFromFile("/bin/"..args[1], args[1], table.unpack(args, 2))
|
||||||
|
local pid=handle.getID()
|
||||||
|
local debugger=hpv.attachDebugger(handle)
|
||||||
|
debugger.addEvent("threadReturn", function(...)
|
||||||
|
term.print("threadReturn", ...)
|
||||||
|
end)
|
||||||
|
debugger.addEvent("threadError", function(...)
|
||||||
|
term.print("threadError", ...)
|
||||||
|
end)
|
||||||
|
while hpv.isrunning(pid) do
|
||||||
|
sleep(0.5)
|
||||||
|
end
|
||||||
0
src/disks/45h/bin_/ls
Normal file
0
src/disks/45h/bin_/ls
Normal file
24
src/disks/45h/bin_/neofetch
Normal file
24
src/disks/45h/bin_/neofetch
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
local term=component.getFirst("screen")
|
||||||
|
term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | root@hyperion ")
|
||||||
|
term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | ------------- ")
|
||||||
|
term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | OS: Hyperion AC ")
|
||||||
|
term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | Host: $Computer_id ")
|
||||||
|
term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | Kernel: Hyprkrnl 1.0.0 ")
|
||||||
|
term.print("⠀⢷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⡞⠀ | Uptime: 2:00 ")
|
||||||
|
term.print("⠀⠈⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⣿⣿⣿⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⠁⠀ | Packages: 204 ")
|
||||||
|
term.print("⠀⠀⠘⣿⣿⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣼⣿⣿⠃⠀⠀ | Shell: DoomieShell ")
|
||||||
|
term.print("⠀⠀⠀⢹⣿⣿⣿⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⣿⣿⡏⠀⠀⠀ | Resolution: $monitor_size ")
|
||||||
|
term.print("⠀⠀⠀⠀⢻⣿⣿⣿⣿⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⣿⣿⣿⡟⠀⠀⠀⠀ | DE: ComputeX ")
|
||||||
|
term.print("⠀⠀⠀⠀⠈⢿⣿⣿⣿⣿⣿⣦⡀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⣿⣿⣿⣿⡿⠁⠀⠀⠀⠀ | WM: HWMS ")
|
||||||
|
term.print("⠀⠀⠀⠀⠀⠈⠛⢿⣿⣿⣿⣿⣿⣦⡀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⢀⣴⣿⣿⣿⣿⣿⡿⠋⠁⠀⠀⠀⠀⠀ | WM Theme: Standard dark ")
|
||||||
|
term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⢿⣿⣿⣿⣿⣦⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⣠⣿⣿⣿⣿⡿⠛⠁⠀⠀⠀⠀⠀⠀⠀⠀ | Theme: Standard dark ")
|
||||||
|
term.print("⠀⠀⠀⠀⠀⠀⠀⢠⣀⠀⠀⠈⠛⢿⣿⣿⣷⣄⠀⠀⣿⣿⣿⣿⣿⣿⠀⠀⣠⣾⣿⣿⡿⠛⠁⠀⠀⣀⡄⠀⠀⠀⠀⠀⠀⠀ | Icons: Standard ")
|
||||||
|
term.print("⠀⠀⠀⠀⠀⠀⠀⠈⢿⣿⣶⣤⣀⠀⠈⠛⢿⣿⠀⠀⣿⣿⣿⣿⣿⣿⠀⠀⣿⡿⠛⠁⠀⣀⣤⣶⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀ | Terminal: Goterm ")
|
||||||
|
term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣿⣶⡄⢸⣿⠀⠀⠸⣿⣿⣿⣿⡏⠀⠀⣿⡇⢠⣶⣿⣿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀ | ")
|
||||||
|
term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⠿⠿⠿⠟⠛⠃⢸⣿⠀⠀⠀⠹⣿⣿⡟⠀⠀⠀⣿⡇⠘⠛⠻⠿⠿⠿⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀ | ")
|
||||||
|
term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣤⡄⢸⣿⡀⠀⠀⠀⢻⡿⠁⠀⠀⢀⣿⡇⢠⣤⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | ")
|
||||||
|
term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⣿⣿⣿⠇⠘⢿⣿⣦⡀⠀⠀⠁⠀⢀⣴⣿⡿⠃⠸⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | ")
|
||||||
|
term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⡿⠋⠀⠀⠀⠀⠙⣿⣿⣦⡀⢀⣴⣿⡿⠋⠀⠀⠀⠈⠙⠿⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | ")
|
||||||
|
term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣿⣿⣿⣿⠟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | ")
|
||||||
|
term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | ")
|
||||||
|
term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | ")
|
||||||
13
src/disks/45h/bin_/pge
Normal file
13
src/disks/45h/bin_/pge
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
local function func(tble,space)
|
||||||
|
space=space or ""
|
||||||
|
for i,v in pairs(tble) do
|
||||||
|
print(space..tostring(i).." | "..tostring(v))
|
||||||
|
if type(v) == "table" then
|
||||||
|
if i=="_G" then else
|
||||||
|
func(v,space.." ")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
func(_G)
|
||||||
2
src/disks/45h/bin_/reboot
Normal file
2
src/disks/45h/bin_/reboot
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
local computer=component.getFirst("computer")
|
||||||
|
computer.reboot()
|
||||||
52
src/disks/45h/bin_/shell
Normal file
52
src/disks/45h/bin_/shell
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
local stringBuffer=""
|
||||||
|
local hpv = require("hypervisor")
|
||||||
|
local fs = require("filesystem")
|
||||||
|
local term=component.getFirst("screen")
|
||||||
|
local captureInput=true
|
||||||
|
local exit=false
|
||||||
|
local function printPrefix()
|
||||||
|
term.printInline("root@testharness:/& ")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function tokenize(str)
|
||||||
|
return string.split(str, " ")
|
||||||
|
end
|
||||||
|
|
||||||
|
hpv.addEvent("keyTyped",function(...)
|
||||||
|
if not captureInput then return end
|
||||||
|
local char=({...})[1]
|
||||||
|
if char == "\n" then
|
||||||
|
captureInput=false
|
||||||
|
term.print("")
|
||||||
|
elseif char == "\b" then
|
||||||
|
if #stringBuffer > 0 then
|
||||||
|
stringBuffer=stringBuffer:sub(1,#stringBuffer-1)
|
||||||
|
term.printInline(char)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
stringBuffer=stringBuffer..char
|
||||||
|
term.printInline(char)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
printPrefix()
|
||||||
|
while not exit do
|
||||||
|
while captureInput do
|
||||||
|
sleep(1)
|
||||||
|
end
|
||||||
|
local token = tokenize(stringBuffer)
|
||||||
|
if token[1] == "exit" then
|
||||||
|
exit=true
|
||||||
|
elseif fs.exists("/bin/"..token[1]) and (not fs.isDir("/bin/"..token[1])) then
|
||||||
|
local handle = hpv.createProcessFromFile("/bin/"..token[1], token[1], table.unpack(token, 2))
|
||||||
|
local pid=handle.getID()
|
||||||
|
while hpv.isrunning(pid) do
|
||||||
|
sleep(0.5)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
term.print("Command not recognized")
|
||||||
|
end
|
||||||
|
stringBuffer=""
|
||||||
|
printPrefix()
|
||||||
|
captureInput=true
|
||||||
|
end
|
||||||
2
src/disks/45h/bin_/t
Normal file
2
src/disks/45h/bin_/t
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
local print=component.getFirst("screen").print
|
||||||
|
print("test")
|
||||||
23
src/disks/45h/bin_/top
Normal file
23
src/disks/45h/bin_/top
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
local hpv=require("hypervisor")
|
||||||
|
local term=component.getFirst("screen")
|
||||||
|
|
||||||
|
term.clear()
|
||||||
|
local function m(str, m)
|
||||||
|
if #str>m then
|
||||||
|
return str:sub(1,m-1).."- "
|
||||||
|
else
|
||||||
|
while #str~=m do
|
||||||
|
str=str.." "
|
||||||
|
end
|
||||||
|
return str.." "
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for i in hpv.listProc() do
|
||||||
|
term.print(m(i.name, 15)..m(i.status, 7)..m(i.pid, 4))
|
||||||
|
for _,v in ipairs(i.threads) do
|
||||||
|
if v.name~="main" then
|
||||||
|
term.print(" "..m(v.name, 12)..m(v.status, 7))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
19
src/disks/45h/bin_/unitest
Normal file
19
src/disks/45h/bin_/unitest
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
local errors={}
|
||||||
|
local function tables_equal(t1, t2)
|
||||||
|
if #t1 ~= #t2 then return false end
|
||||||
|
for i = 1, #t1 do
|
||||||
|
if t1[i] ~= t2[i] then return false end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function run_test(name, test_func)
|
||||||
|
local status, err = pcall(test_func)
|
||||||
|
if status then
|
||||||
|
print("[PASS] " .. name)
|
||||||
|
else
|
||||||
|
print("[FAIL] " .. name .. ": " .. err)
|
||||||
|
errors[name]=err
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
215
src/disks/45h/boot/Hyprkrnl.sys
Normal file
215
src/disks/45h/boot/Hyprkrnl.sys
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
local function rand()
|
||||||
|
if math.random(0,1)==0 then return true else return false end
|
||||||
|
end
|
||||||
|
function coroutine.resumeWithTimeout(CORO, TIME, ...)
|
||||||
|
return rand(), coroutine.resume(CORO, ...)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Copyright (C) 2025 ASTRONAND
|
||||||
|
-- Get boot arguments
|
||||||
|
local bootArgs=({...})[1]
|
||||||
|
local bootDrive=bootArgs.bootDrive
|
||||||
|
local LOG_TEXT=""
|
||||||
|
local log={}
|
||||||
|
local term
|
||||||
|
local bootData=load("return "..(bootDrive:open("var/log/kernel/bootData").read() or "{}"))()
|
||||||
|
local computer=component.getFirst("computer")
|
||||||
|
local startup=true
|
||||||
|
local osleep=sleep
|
||||||
|
local oldYield=coroutine.yield
|
||||||
|
|
||||||
|
function coroutine.yield(...)
|
||||||
|
if not startup then
|
||||||
|
if coroutine.isyieldable(coroutine.running()) then
|
||||||
|
oldYield(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Find terminal(s)
|
||||||
|
local terminals={}
|
||||||
|
for i,v in component.list() do
|
||||||
|
if i == "screen" then
|
||||||
|
terminals[#terminals+1] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
term={
|
||||||
|
print=function(...)
|
||||||
|
for _,v in ipairs(terminals) do
|
||||||
|
v.print(...)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
printInline=function(...)
|
||||||
|
for _,v in ipairs(terminals) do
|
||||||
|
v.printInline(...)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
clear=function(...)
|
||||||
|
for _,v in ipairs(terminals) do
|
||||||
|
v.clear(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
term.print("Welcome to Hyperion OS")
|
||||||
|
-- Difine logging lib
|
||||||
|
local function getPName(func)
|
||||||
|
if type(func) == "function" then
|
||||||
|
getPName=func
|
||||||
|
end
|
||||||
|
return "Hyprkrnl"
|
||||||
|
end
|
||||||
|
|
||||||
|
function log.log(text)
|
||||||
|
if startup then term.print("[ OK ] "..getPName()..": "..text) end
|
||||||
|
LOG_TEXT=LOG_TEXT.."[ OK ] "..getPName()..": "..text.."\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
function log.error(text)
|
||||||
|
if startup then term.print("[FAILED] "..getPName()..": "..text) end
|
||||||
|
LOG_TEXT=LOG_TEXT.."[FAILED] "..getPName()..": "..text.."\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
function log.warn(text)
|
||||||
|
if startup then term.print("[ WARN ] "..getPName()..": "..text) end
|
||||||
|
LOG_TEXT=LOG_TEXT.."[ WARN ] "..getPName()..": "..text.."\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
function log.raw(text)
|
||||||
|
if startup then term.print(" "..getPName()..": "..text) end
|
||||||
|
LOG_TEXT=LOG_TEXT.." "..getPName()..": "..text.."\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
function log.get()
|
||||||
|
return LOG_TEXT
|
||||||
|
end
|
||||||
|
|
||||||
|
local function t2t(table)
|
||||||
|
local output = "{"
|
||||||
|
for i,v in pairs(table) do
|
||||||
|
local coma=true
|
||||||
|
if type(i) == "string" then
|
||||||
|
output=output.."[\""..i.."\"]="
|
||||||
|
end
|
||||||
|
if type(v) == "table" then
|
||||||
|
if v == table then
|
||||||
|
output=string.sub(output,1,#output-(#i+1))
|
||||||
|
coma=false
|
||||||
|
else
|
||||||
|
output=output..t2t(v)
|
||||||
|
end
|
||||||
|
elseif type(v) == "string" then
|
||||||
|
output=output.."[=["..v.."]=]"
|
||||||
|
elseif type(v) == "number" then
|
||||||
|
output=output..tostring(v)
|
||||||
|
elseif type(v) == "function" then
|
||||||
|
output=string.sub(output,1,#output-(#i+1))
|
||||||
|
coma=false
|
||||||
|
end
|
||||||
|
if coma then
|
||||||
|
output=output..","
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #table>0 or string.sub(output,#output,#output) == "," then
|
||||||
|
output=string.sub(output,1,#output-1)
|
||||||
|
end
|
||||||
|
output=output.."}"
|
||||||
|
return output
|
||||||
|
end
|
||||||
|
|
||||||
|
-- My favorite function
|
||||||
|
local function PANIC(err,lvl)
|
||||||
|
term.clear()
|
||||||
|
term.print(LOG_TEXT)
|
||||||
|
term.printInline("KERNEL PANIC: "..err)
|
||||||
|
computer.beep(800,0.2)
|
||||||
|
osleep(0.02)
|
||||||
|
if err==bootData.prevError then
|
||||||
|
bootData.errorCount=bootData.errorCount+1
|
||||||
|
else
|
||||||
|
bootData.prevError=err
|
||||||
|
bootData.errorCount=0
|
||||||
|
end
|
||||||
|
bootDrive:open("var/log/kernel/bootData").write(t2t(bootData))
|
||||||
|
if bootData.errorCount < 4 then
|
||||||
|
term.print("")
|
||||||
|
term.print("Atempting reboot...")
|
||||||
|
osleep(0.5)
|
||||||
|
computer.reboot()
|
||||||
|
elseif bootData.errorCount > 3 then
|
||||||
|
term.print("")
|
||||||
|
term.print("boot determined to be unrecoverable...")
|
||||||
|
osleep(0.5)
|
||||||
|
computer.shutdown()
|
||||||
|
end
|
||||||
|
while true do
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function runAsKernel(path, args)
|
||||||
|
local ok,err,extra = pcall(load(bootDrive:open(path):read()), args)
|
||||||
|
if not ok then
|
||||||
|
PANIC(path.." failed to load/execute err:\n"..(err or ""))
|
||||||
|
end
|
||||||
|
return err,extra
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Add libray modifications+
|
||||||
|
for _,v in ipairs(bootDrive:list("/sys/kernel/glib")) do
|
||||||
|
log.raw("running "..v)
|
||||||
|
runAsKernel("/sys/kernel/glib/"..v)
|
||||||
|
log.log("Loaded "..v)
|
||||||
|
end
|
||||||
|
log.log("Finished loading global librarys")
|
||||||
|
local sudoMaster={}
|
||||||
|
local auth=runAsKernel("sys/kernel/userManager.sys",{masterKey=sudoMaster,bootDrive=bootDrive})
|
||||||
|
log.log("Created UE Manager")
|
||||||
|
local fs=runAsKernel("sys/kernel/filesystem.sys",{bootDrive=bootDrive,auth=auth})
|
||||||
|
log.log("Initailized filesystem")
|
||||||
|
local io=runAsKernel("sys/kernel/ioManager.sys",{masterKey=sudoMaster})
|
||||||
|
log.log("Started ioManager")
|
||||||
|
local packages={filesystem=fs, auth=auth, logging=log, term=term}
|
||||||
|
local req=runAsKernel("sys/modules/require",{filesystem=fs,logging=log, preload=packages})
|
||||||
|
log.log("Loaded require")
|
||||||
|
local setRequire
|
||||||
|
local requ=req.makeRequire("lib/?;lib/?/init;sys/modules/?;sys/modules/?/init",packages)
|
||||||
|
_G.require, setRequire = requ.require, requ.load
|
||||||
|
setRequire("require",req)
|
||||||
|
log.log("Initailized require")
|
||||||
|
|
||||||
|
local code=fs.open("sys/kernel/hypervisor.sys","xe", _G)
|
||||||
|
|
||||||
|
if not code then
|
||||||
|
PANIC("System failed to load")
|
||||||
|
end
|
||||||
|
local ok, system=pcall(code, {masterKey=sudoMaster, setRequire=setRequire, pname=getPName})
|
||||||
|
if not ok then
|
||||||
|
PANIC("Hypervisor failed to execute ERR:\n"..hypervisor)
|
||||||
|
end
|
||||||
|
log.log("Loaded hypervisor")
|
||||||
|
log.raw("Making kernel process")
|
||||||
|
|
||||||
|
hypervisor(function()
|
||||||
|
local hpv=require("hypervisor")
|
||||||
|
local thread=require("thread")
|
||||||
|
log.log("Created kernel process")
|
||||||
|
hpv.createProcessFromFile("sys/os/init.lua", "systemd")
|
||||||
|
thread.create(function()
|
||||||
|
while true do
|
||||||
|
local event = {computer.getMachineEvent()}
|
||||||
|
if event[1] == nil then
|
||||||
|
coroutine.yield()
|
||||||
|
else
|
||||||
|
hpv.triggerEvent("all", event[1], table.unpack(event,2))
|
||||||
|
coroutine.yield()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end, "eventHandler")
|
||||||
|
|
||||||
|
while true do
|
||||||
|
coroutine.yield()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
term.print("Goodbye :)")
|
||||||
1
src/disks/45h/boot/hyprboot.lua
Normal file
1
src/disks/45h/boot/hyprboot.lua
Normal file
@@ -0,0 +1 @@
|
|||||||
|
if
|
||||||
0
src/disks/45h/etc/ast-ip/config.ini
Normal file
0
src/disks/45h/etc/ast-ip/config.ini
Normal file
0
src/disks/45h/etc/fstab
Normal file
0
src/disks/45h/etc/fstab
Normal file
2
src/disks/45h/etc/group
Normal file
2
src/disks/45h/etc/group
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
root:0:root
|
||||||
|
sudo:1:root
|
||||||
1
src/disks/45h/etc/passwd
Normal file
1
src/disks/45h/etc/passwd
Normal file
@@ -0,0 +1 @@
|
|||||||
|
root:x:0:0::/root:/bin/pshell
|
||||||
1
src/disks/45h/etc/shadow
Normal file
1
src/disks/45h/etc/shadow
Normal file
@@ -0,0 +1 @@
|
|||||||
|
root:$5$9a7f8e2b4cd01ac18d7cbb4da74f5c1e$53326d6a24ef6a050b5ef88dbbe5906d4afbcf191725f9750e44a818ab22bd62:0
|
||||||
2
src/disks/45h/etc/spm/repos
Normal file
2
src/disks/45h/etc/spm/repos
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
https://git.astronand.dev/Hyperion-OS/packages/raw/branch/main/spm/
|
||||||
|
https://git.astronand.dev/Hyperion-OS/packages/raw/branch/main/ac/
|
||||||
1
src/disks/45h/etc/sudoers
Normal file
1
src/disks/45h/etc/sudoers
Normal file
@@ -0,0 +1 @@
|
|||||||
|
root
|
||||||
0
src/disks/45h/etc/sysinit/system/graphical.target
Normal file
0
src/disks/45h/etc/sysinit/system/graphical.target
Normal file
0
src/disks/45h/etc/sysinit/system/halt.target
Normal file
0
src/disks/45h/etc/sysinit/system/halt.target
Normal file
0
src/disks/45h/etc/sysinit/system/multi-user.target
Normal file
0
src/disks/45h/etc/sysinit/system/multi-user.target
Normal file
5
src/disks/45h/etc/sysinit/system/poweroff.target
Normal file
5
src/disks/45h/etc/sysinit/system/poweroff.target
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Shutdown of system
|
||||||
|
Conflicts=reboot.target halt.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
0
src/disks/45h/etc/sysinit/system/reboot.target
Normal file
0
src/disks/45h/etc/sysinit/system/reboot.target
Normal file
16
src/disks/45h/lib/color/init
Normal file
16
src/disks/45h/lib/color/init
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
function color.screen8(r, g, b)
|
||||||
|
-- Ensure input is within valid 0-255 range
|
||||||
|
r = math.max(0, math.min(255, r))
|
||||||
|
g = math.max(0, math.min(255, g))
|
||||||
|
b = math.max(0, math.min(255, b))
|
||||||
|
|
||||||
|
-- Convert 8-bit to reduced bit depth
|
||||||
|
local r3 = math.floor(r / 32) -- 8-bit to 3-bit
|
||||||
|
local g3 = math.floor(g / 32) -- 8-bit to 3-bit
|
||||||
|
local b2 = math.floor(b / 64) -- 8-bit to 2-bit
|
||||||
|
|
||||||
|
-- Pack into a single 8-bit value: RRR GGG BB
|
||||||
|
local rgb332 = (r3 << 5) | (g3 << 2) | b2
|
||||||
|
|
||||||
|
return rgb332
|
||||||
|
end
|
||||||
111
src/disks/45h/lib/config/ini
Normal file
111
src/disks/45h/lib/config/ini
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
-- Copyright (C) 2025 ASTRONAND
|
||||||
|
local ini = {}
|
||||||
|
local fs=require("filesystem")
|
||||||
|
|
||||||
|
local function trim(s)
|
||||||
|
local i, j = 1, #s
|
||||||
|
while i <= j and (s:sub(i,i) == " " or s:sub(i,i) == "\t") do
|
||||||
|
i = i + 1
|
||||||
|
end
|
||||||
|
while j >= i and (s:sub(j,j) == " " or s:sub(j,j) == "\t") do
|
||||||
|
j = j - 1
|
||||||
|
end
|
||||||
|
return s:sub(i, j)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function parse(list)
|
||||||
|
local lines=function ()
|
||||||
|
local i=0
|
||||||
|
return function()
|
||||||
|
i=i+1
|
||||||
|
return list[i]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local data = {}
|
||||||
|
local section = data
|
||||||
|
for line in lines() do
|
||||||
|
line = trim(line)
|
||||||
|
|
||||||
|
if line ~= "" and line:sub(1,1) ~= ";" and line:sub(1,1) ~= "#" then
|
||||||
|
if line:sub(1,1) == "[" and line:sub(-1) == "]" then
|
||||||
|
local secName = trim(line:sub(2, -2))
|
||||||
|
if secName ~= "" then
|
||||||
|
data[secName] = data[secName] or {}
|
||||||
|
section = data[secName]
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local eq
|
||||||
|
for i = 1, #line do
|
||||||
|
if line:sub(i,i) == "=" then
|
||||||
|
eq = i
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if eq then
|
||||||
|
local key = trim(line:sub(1, eq-1))
|
||||||
|
local value = trim(line:sub(eq+1))
|
||||||
|
|
||||||
|
local lower = value:lower()
|
||||||
|
if tonumber(value) then
|
||||||
|
value = tonumber(value)
|
||||||
|
elseif lower == "true" then
|
||||||
|
value = true
|
||||||
|
elseif lower == "false" then
|
||||||
|
value = false
|
||||||
|
end
|
||||||
|
section[key] = value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return data
|
||||||
|
end
|
||||||
|
|
||||||
|
function ini.read(path)
|
||||||
|
local file, err = fs.open(path, "r")
|
||||||
|
if not file then return nil, err end
|
||||||
|
local list={}
|
||||||
|
for i in file.lines() do
|
||||||
|
list[#list+1] = i
|
||||||
|
end
|
||||||
|
file.close()
|
||||||
|
return parse(list)
|
||||||
|
end
|
||||||
|
|
||||||
|
function ini.get(text)
|
||||||
|
return parse(string.split(text, "\n"))
|
||||||
|
end
|
||||||
|
|
||||||
|
local function write(data)
|
||||||
|
local text=""
|
||||||
|
for k,v in pairs(data) do
|
||||||
|
if type(v) ~= "table" then
|
||||||
|
text=text..k .. " = " .. tostring(v) .. "\n"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for sec, tbl in pairs(data) do
|
||||||
|
if type(tbl) == "table" then
|
||||||
|
text=text.."\n[" .. sec .. "]\n"
|
||||||
|
for k,v in pairs(tbl) do
|
||||||
|
text=text..k .. " = " .. tostring(v) .. "\n"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return text
|
||||||
|
end
|
||||||
|
|
||||||
|
function ini.write(path, data)
|
||||||
|
local file=fs.open(path, "w")
|
||||||
|
file.write(write(data))
|
||||||
|
file.close()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function ini.make(data)
|
||||||
|
return write(data)
|
||||||
|
end
|
||||||
|
|
||||||
|
return ini
|
||||||
14
src/disks/45h/lib/consumer
Normal file
14
src/disks/45h/lib/consumer
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
-- Copyright (C) 2025 ASTRONAND
|
||||||
|
local lib={}
|
||||||
|
|
||||||
|
function lib.create(def)
|
||||||
|
local function func(fun)
|
||||||
|
if type(fun)=="function" then
|
||||||
|
func=fun
|
||||||
|
end
|
||||||
|
return def
|
||||||
|
end
|
||||||
|
return func
|
||||||
|
end
|
||||||
|
|
||||||
|
return lib
|
||||||
193
src/disks/45h/lib/crypto/sha256
Normal file
193
src/disks/45h/lib/crypto/sha256
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
-- From http://pastebin.com/gsFrNjbt linked from http://www.computercraft.info/forums2/index.php?/topic/8169-sha-256-in-pure-lua/
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Adaptation of the Secure Hashing Algorithm (SHA-244/256)
|
||||||
|
-- Found Here: http://lua-users.org/wiki/SecureHashAlgorithm
|
||||||
|
--
|
||||||
|
-- Using an adapted version of the bit library
|
||||||
|
-- Found Here: https://bitbucket.org/Boolsheet/bslf/src/1ee664885805/bit.lua
|
||||||
|
--
|
||||||
|
|
||||||
|
local MOD = 2^32
|
||||||
|
local MODM = MOD-1
|
||||||
|
|
||||||
|
local function memoize(f)
|
||||||
|
local mt = {}
|
||||||
|
local t = setmetatable({}, mt)
|
||||||
|
function mt:__index(k)
|
||||||
|
local v = f(k)
|
||||||
|
t[k] = v
|
||||||
|
return v
|
||||||
|
end
|
||||||
|
return t
|
||||||
|
end
|
||||||
|
|
||||||
|
local function make_bitop_uncached(t, m)
|
||||||
|
local function bitop(a, b)
|
||||||
|
local res,p = 0,1
|
||||||
|
while a ~= 0 and b ~= 0 do
|
||||||
|
local am, bm = a % m, b % m
|
||||||
|
res = res + t[am][bm] * p
|
||||||
|
a = (a - am) / m
|
||||||
|
b = (b - bm) / m
|
||||||
|
p = p*m
|
||||||
|
end
|
||||||
|
res = res + (a + b) * p
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
return bitop
|
||||||
|
end
|
||||||
|
|
||||||
|
local function make_bitop(t)
|
||||||
|
local op1 = make_bitop_uncached(t,2^1)
|
||||||
|
local op2 = memoize(function(a) return memoize(function(b) return op1(a, b) end) end)
|
||||||
|
return make_bitop_uncached(op2, 2 ^ (t.n or 1))
|
||||||
|
end
|
||||||
|
|
||||||
|
local bxor1 = make_bitop({[0] = {[0] = 0,[1] = 1}, [1] = {[0] = 1, [1] = 0}, n = 4})
|
||||||
|
|
||||||
|
local function bxor(a, b, c, ...)
|
||||||
|
local z = nil
|
||||||
|
if b then
|
||||||
|
a = a % MOD
|
||||||
|
b = b % MOD
|
||||||
|
z = bxor1(a, b)
|
||||||
|
if c then z = bxor(z, c, ...) end
|
||||||
|
return z
|
||||||
|
elseif a then return a % MOD
|
||||||
|
else return 0 end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function band(a, b, c, ...)
|
||||||
|
local z
|
||||||
|
if b then
|
||||||
|
a = a % MOD
|
||||||
|
b = b % MOD
|
||||||
|
z = ((a + b) - bxor1(a,b)) / 2
|
||||||
|
if c then z = bit32_band(z, c, ...) end
|
||||||
|
return z
|
||||||
|
elseif a then return a % MOD
|
||||||
|
else return MODM end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function bnot(x) return (-1 - x) % MOD end
|
||||||
|
|
||||||
|
local function rshift1(a, disp)
|
||||||
|
if disp < 0 then return lshift(a,-disp) end
|
||||||
|
return math.floor(a % 2 ^ 32 / 2 ^ disp)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function rshift(x, disp)
|
||||||
|
if disp > 31 or disp < -31 then return 0 end
|
||||||
|
return rshift1(x % MOD, disp)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function lshift(a, disp)
|
||||||
|
if disp < 0 then return rshift(a,-disp) end
|
||||||
|
return (a * 2 ^ disp) % 2 ^ 32
|
||||||
|
end
|
||||||
|
|
||||||
|
local function rrotate(x, disp)
|
||||||
|
x = x % MOD
|
||||||
|
disp = disp % 32
|
||||||
|
local low = band(x, 2 ^ disp - 1)
|
||||||
|
return rshift(x, disp) + lshift(low, 32 - disp)
|
||||||
|
end
|
||||||
|
|
||||||
|
local k = {
|
||||||
|
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
||||||
|
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||||
|
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||||
|
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||||
|
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
||||||
|
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||||
|
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
||||||
|
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||||
|
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||||
|
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||||
|
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
||||||
|
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||||
|
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
||||||
|
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||||
|
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||||
|
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
|
||||||
|
}
|
||||||
|
|
||||||
|
local function str2hexa(s)
|
||||||
|
return (string.gsub(s, ".", function(c) return string.format("%02x", string.byte(c)) end))
|
||||||
|
end
|
||||||
|
|
||||||
|
local function num2s(l, n)
|
||||||
|
local s = ""
|
||||||
|
for i = 1, n do
|
||||||
|
local rem = l % 256
|
||||||
|
s = string.char(rem) .. s
|
||||||
|
l = (l - rem) / 256
|
||||||
|
end
|
||||||
|
return s
|
||||||
|
end
|
||||||
|
|
||||||
|
local function s232num(s, i)
|
||||||
|
local n = 0
|
||||||
|
for i = i, i + 3 do n = n*256 + string.byte(s, i) end
|
||||||
|
return n
|
||||||
|
end
|
||||||
|
|
||||||
|
local function preproc(msg, len)
|
||||||
|
local extra = 64 - ((len + 9) % 64)
|
||||||
|
len = num2s(8 * len, 8)
|
||||||
|
msg = msg .. "\128" .. string.rep("\0", extra) .. len
|
||||||
|
assert(#msg % 64 == 0)
|
||||||
|
return msg
|
||||||
|
end
|
||||||
|
|
||||||
|
local function initH256(H)
|
||||||
|
H[1] = 0x6a09e667
|
||||||
|
H[2] = 0xbb67ae85
|
||||||
|
H[3] = 0x3c6ef372
|
||||||
|
H[4] = 0xa54ff53a
|
||||||
|
H[5] = 0x510e527f
|
||||||
|
H[6] = 0x9b05688c
|
||||||
|
H[7] = 0x1f83d9ab
|
||||||
|
H[8] = 0x5be0cd19
|
||||||
|
return H
|
||||||
|
end
|
||||||
|
|
||||||
|
local function digestblock(msg, i, H)
|
||||||
|
local w = {}
|
||||||
|
for j = 1, 16 do w[j] = s232num(msg, i + (j - 1)*4) end
|
||||||
|
for j = 17, 64 do
|
||||||
|
local v = w[j - 15]
|
||||||
|
local s0 = bxor(rrotate(v, 7), rrotate(v, 18), rshift(v, 3))
|
||||||
|
v = w[j - 2]
|
||||||
|
w[j] = w[j - 16] + s0 + w[j - 7] + bxor(rrotate(v, 17), rrotate(v, 19), rshift(v, 10))
|
||||||
|
end
|
||||||
|
|
||||||
|
local a, b, c, d, e, f, g, h = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8]
|
||||||
|
for i = 1, 64 do
|
||||||
|
local s0 = bxor(rrotate(a, 2), rrotate(a, 13), rrotate(a, 22))
|
||||||
|
local maj = bxor(band(a, b), band(a, c), band(b, c))
|
||||||
|
local t2 = s0 + maj
|
||||||
|
local s1 = bxor(rrotate(e, 6), rrotate(e, 11), rrotate(e, 25))
|
||||||
|
local ch = bxor (band(e, f), band(bnot(e), g))
|
||||||
|
local t1 = h + s1 + ch + k[i] + w[i]
|
||||||
|
h, g, f, e, d, c, b, a = g, f, e, d + t1, c, b, a, t1 + t2
|
||||||
|
end
|
||||||
|
|
||||||
|
H[1] = band(H[1] + a)
|
||||||
|
H[2] = band(H[2] + b)
|
||||||
|
H[3] = band(H[3] + c)
|
||||||
|
H[4] = band(H[4] + d)
|
||||||
|
H[5] = band(H[5] + e)
|
||||||
|
H[6] = band(H[6] + f)
|
||||||
|
H[7] = band(H[7] + g)
|
||||||
|
H[8] = band(H[8] + h)
|
||||||
|
end
|
||||||
|
|
||||||
|
return function(msg)
|
||||||
|
msg = preproc(msg, #msg)
|
||||||
|
local H = initH256({})
|
||||||
|
for i = 1, #msg, 64 do digestblock(msg, i, H) end
|
||||||
|
return str2hexa(num2s(H[1], 4) .. num2s(H[2], 4) .. num2s(H[3], 4) .. num2s(H[4], 4) ..
|
||||||
|
num2s(H[5], 4) .. num2s(H[6], 4) .. num2s(H[7], 4) .. num2s(H[8], 4))
|
||||||
|
end
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user