Browse Source

Adds web based eeprom programmer and default openbios

master
Chris Mahoney 2 years ago
parent
commit
893d0b2f7f
  1. 191
      eeprom-server.lua
  2. 72
      eeprom-worker.lua
  3. 122
      openbios.lua
  4. 28
      webflash.lua

191
eeprom-server.lua

@ -0,0 +1,191 @@
local net = require("net")
local component = require("component")
local sides = require("sides")
local os = require("os")
-- location of eeprom in computer case
local EEPROM_SLOT = 10
local transposer = component.transposer
-- Waits for a SYN from a worker and responds with an ACK
-- Returns the workers address
local function meetWorker(port)
print("Waiting for worker")
local function syn(name, ...)
-- local addr, remote addr, port, distance, msg
local t = {...}
return t[5] == "SYN"
end
-- Wait for a SYN
local pkt, err = net.recv{port, filter = syn}
-- ACK the worker
net.send(pkt.raddr, port, "ACK")
print("Found worker", pkt.raddr)
return pkt.raddr
end
-- Checks if the top chest is filled
local function isFilled()
local i = 1
for k in transposer.getAllStacks(sides.top) do
if k.size == nil then break end
i = i + 1
end
return i >= 27
end
-- Moves the EEPROM from the worker into the top chest
-- Optionally include the slot
-- Returns the slot the eeprom was moved to
local function removeEEPROM(sink_slot)
print("REMOVING - ", sink_slot)
if sink_slot == nil then
local i = 1
for k in transposer.getAllStacks(sides.top) do
if k.size == nil then break end
i = i + 1
end
if i == 27 then
return nil, "Inventory filled"
end
sink_slot = i
end
-- Remove the OpenOS Bios and store it in the top chest
transposer.transferItem(sides.left, sides.top, 1, EEPROM_SLOT, sink_slot)
return sink_slot
end
-- Moves a blank EEPROM from storage into the worker
local function loadNewEEPROM()
print("LOADING")
-- Find largest inventory slot in the storage with an eeprom
local i = 1
local last = nil
for k in transposer.getAllStacks(sides.right) do
if k.size ~= nil then
last = i
end
i = i + 1
end
if last == nil then
return nil, "No EEPROMS"
end
-- Move the new EEPROM into computer
transposer.transferItem(sides.right, sides.left, 1, last, EEPROM_SLOT)
return true
end
local function flashEEPROM(worker, port, data, label)
print("Send", worker, port, "flash", label)
net.send(worker, port, "flash", data, label)
local function fromWorker(name, ...)
t = {...}
return t[2] == worker
end
local pkt, error = net.recv{port, filter=fromWorker}
if pkt.msg == "flash-good" then
return true
else
return nil, pkt.msg
end
end
local function respond(pkt, code, error)
print("SEND", pkt.raddr, pkt.port, code, error)
net.send(pkt.raddr, pkt.port, code, error)
computer.beep(200)
end
-- Waits to recv a message
local function waitForJob(port, worker)
local pkt, err = net.recv{port}
if pkt == nil and err ~= "interrupted" then
return pkt
end
-- "eeprom-flash file-contents"
if pkt.msg == "eeprom-flash" then
-- 4k is the largest an eeprom can hold
if #pkt.data[2] > 4096 then
respond(pkt, 400, "file too large")
return pkt
end
if isFilled() then respond(pkt, 500, "inventory filled") return end
-- Remove the OpenOS Bios and store it in the last slot of top chest
local res, err = removeEEPROM(27)
if res == nil then respond(pkt, 500, err) return end
computer.beep(100)
local res, err = loadNewEEPROM()
if res == nil then respond(pkt, 500, err) return end
computer.beep(100)
if pkt.data[3] == nil then
pkt.data[3] = "Flashed EEPROM"
end
local res, err = flashEEPROM(worker, port, pkt.data[2], pkt.data[3])
if res == nil then respond(pkt, 500, err) return end
-- Now the NBT data of the eeprom will update on the next auto save
-- To detect this we're going to check the item stack every few seconds until the labels match
local i = 0
while transposer.getStackInSlot(sides.left, EEPROM_SLOT).label ~= pkt.data[3] do
print("Checking for autosave...")
computer.beep(500)
os.sleep(2.5)
i = i + 1
end
print("Autosave detected! Took " .. tostring(2.5 * i) .. " seconds")
computer.beep(1000)
local location, err = removeEEPROM()
if location == nil then respond(pkt, 500, err) return end
computer.beep(100)
-- Load the old EERPOM
transposer.transferItem(sides.top, sides.left, 1, 27, EEPROM_SLOT)
computer.beep(100)
respond(pkt, 200, location)
computer.beep(1000)
end
end
local function startServer(port)
worker = meetWorker(port)
while true do
print(waitForJob(port, worker))
end
end
startServer(10)

72
eeprom-worker.lua

@ -0,0 +1,72 @@
local net = require("net")
local component = require("component")
local sides = require("sides")
local os = require("os")
local function meet_server(port)
while true do
print("broadcast 10 SYN")
net.broadcast(port, "SYN")
computer.beep(200)
local function ack(name, ...)
-- local addr, remote addr, port, distance, msg
local t = {...}
return t[5] == "ACK"
end
print("recv 10 ack")
local pkt, err = net.recv{port, filter = ack, timeout = 5}
print(pkt)
if pkt ~= nil then
return pkt.raddr
end
end
end
local function respond(pkt, code, error)
print("SEND", pkt.raddr, pkt.port, code, error)
net.send(pkt.raddr, pkt.port, code, error)
computer.beep(200)
end
-- Waits to recv a function asking to flash the current EEPROM
local function wait_for_job(port, server)
local function filter(name, ...)
-- local addr, remote addr, port, distance, msg
local t = {...}
return t[5] == "flash"
end
local pkt, err = net.recv{port, filter=filter}
local eeprom = require("component").eeprom
print("Found eeprom", eeprom.getData())
print("Flashing EEPROM", #pkt.data[2], "bytes")
eeprom.set(pkt.data[2])
computer.beep(500)
if pkt.data[3] ~= nil then
eeprom.setLabel(pkt.data[3])
computer.beep(500)
end
print("Bytes written", #eeprom.get())
respond(pkt, "flash-good")
computer.beep(1000)
end
local function start_client(port)
server = meet_server(port)
while true do
wait_for_job(port, server)
os.sleep(5)
end
end
start_client(10)

122
openbios.lua

@ -0,0 +1,122 @@
-- this is the default boot loader
local component = component or require('component')
local computer = computer or require('computer')
local unicode = unicode or require('unicode')
local eeprom = component.list("eeprom")()
computer.getBootAddress = function()
return component.invoke(eeprom, "getData")
end
computer.setBootAddress = function(address)
return component.invoke(eeprom, "setData", address)
end
local gpu = component.list("gpu")()
local w, h
local screen = component.list('screen')()
for address in component.list('screen') do
if #component.invoke(address, 'getKeyboards') > 0 then
screen = address
end
end
local cls = function()end
if gpu and screen then
component.invoke(gpu, "bind", screen)
w, h = component.invoke(gpu, "getResolution")
component.invoke(gpu, "setResolution", w, h)
component.invoke(gpu, "setBackground", 0x000000)
component.invoke(gpu, "setForeground", 0xFFFFFF)
component.invoke(gpu, "fill", 1, 1, w, h, " ")
cls = function()component.invoke(gpu,"fill", 1, 1, w, h, " ")end
end
local y = 1
local function status(msg)
if gpu and screen then
component.invoke(gpu, "set", 1, y, msg)
if y == h then
component.invoke(gpu, "copy", 1, 2, w, h - 1, 0, -1)
component.invoke(gpu, "fill", 1, h, w, 1, " ")
else
y = y + 1
end
end
end
local function loadfile(fs, file)
--status("> " .. file)
local handle, reason = component.invoke(fs,"open",file)
if not handle then
error(reason)
end
local buffer = ""
repeat
local data, reason = component.invoke(fs,"read",handle,math.huge)
if not data and reason then
error(reason)
end
buffer = buffer .. (data or "")
until not data
component.invoke(fs,"close",handle)
return load(buffer, "=" .. file)
end
local function dofile(fs, file)
local program, reason = loadfile(fs, file)
if program then
local result = table.pack(pcall(program))
if result[1] then
return table.unpack(result, 2, result.n)
else
error(result[2])
end
else
error(reason)
end
end
local function boot(kernel)
status("BOOTING")
_G.computer.getBootAddress = function()return kernel.address end
cls()
dofile(kernel.address, kernel.fpx .. kernel.file)
end
status(_OSVERSION)
status("Select what to boot:")
local osList = {}
for fs in component.list("filesystem") do
if component.invoke(fs, "isDirectory", "boot/kernel/")then
for _,file in ipairs(component.invoke(fs, "list", "boot/kernel/")) do
osList[#osList+1] = {fpx = "boot/kernel/", file = file, address = fs}
status(tostring(#osList).."."..file.." from "..(fs:sub(1,3)))
end
end
if component.invoke(fs, "exists", "init.lua") then
local osName = "init.lua"
if component.invoke(fs, "exists", ".osprop") then
pcall(function()
local prop = dofile(fs, ".osprop")
osName = (prop and prop.name) or "init.lua"
end)
end
osList[#osList+1] = {fpx = "", file = "init.lua", address = fs}
status(tostring(#osList).."."..osName.." from "..(fs:sub(1,3)))
end
end
status("Select os: ")
if #osList == 1 then
boot(osList[1])
end
if #osList == 0 then
error("No OS found")
while true do computer.pullSignal() end
end
while true do
local sig = {computer.pullSignal()}
if sig[1] == "key_down" then
if sig[4] >= 2 and sig[4] <= 11 then
if osList[sig[4]-1] then
boot(osList[sig[4]-1])
else
status("Not found!")
end
end
end
end
error("System crashed")
while true do computer.pullSignal() end

28
webflash.lua

@ -0,0 +1,28 @@
-- This file takes as input a script and a label
-- it will ask the eeprom machine to flash it to an eeprom
local computer = require("computer")
local net = require("net")
local args = {...}
print("Reading " .. args[1])
f = io.open(args[1])
local bytes = f:read()
f:close()
computer.beep(100)
print("Broadcasting bios")
if args[2] == nil then
net.broadcast(10, "eeprom-flash", bytes)
else
net.broadcast(10, "eeprom-flash", bytes, args[2])
end
computer.beep(200)
print("Waiting for response...")
local pkt, err = net.recv{10}
print("Status: " .. tostring(pkt.data[1]) .. " Slot: " .. tostring(pkt.data[2]))
computer.beep(1000)
Loading…
Cancel
Save