|
|
|
local component, error, math, select = component, error, math, select
|
|
|
|
local cl, ci, ct = component.list, component.invoke, component.type
|
|
|
|
|
|
|
|
local function bail(msg, ...)
|
|
|
|
if select('#', ...) > 0 then
|
|
|
|
msg = msg:format(...)
|
|
|
|
end
|
|
|
|
return error(msg, 0)
|
|
|
|
end
|
|
|
|
local function unique(addr1, addr2, what)
|
|
|
|
if addr1 and addr2 then
|
|
|
|
return bail('multiple %s: %s, %s', what, addr1, addr2)
|
|
|
|
end
|
|
|
|
return addr1 or addr2 or bail('no %s', what)
|
|
|
|
end
|
|
|
|
|
|
|
|
local eeprom
|
|
|
|
for addr in cl('eeprom') do eeprom = unique(eeprom, addr, 'eeproms') end
|
|
|
|
eeprom = unique(eeprom, nil, 'eeprom')
|
|
|
|
|
|
|
|
local data = ci(eeprom, 'getData')
|
|
|
|
local bootfs, bootpath
|
|
|
|
if data == '' then
|
|
|
|
for fs in cl('filesystem') do
|
|
|
|
if ci(fs, 'exists', '/init.lua') then
|
|
|
|
bootfs = unique(bootfs, fs, 'bootable filesystems')
|
|
|
|
bootpath = '/init.lua'
|
|
|
|
end
|
|
|
|
end
|
|
|
|
bootfs = unique(bootfs, nil, 'bootable filesystem')
|
|
|
|
else
|
|
|
|
local split = data:find(':')
|
|
|
|
if split then
|
|
|
|
bootfs, bootpath = data:sub(1, split - 1), data:sub(split + 1)
|
|
|
|
else
|
|
|
|
bootfs, bootpath = data, '/init.lua'
|
|
|
|
end
|
|
|
|
local ty, err = ct(bootfs)
|
|
|
|
if not ty then bail('bootfs %s absent', bootfs) end
|
|
|
|
if ty ~= 'filesystem' then bail('bootfs %s is a %s', bootfs, ty) end
|
|
|
|
end
|
|
|
|
|
|
|
|
--polyfill {get,set}BootAddress like openloader does
|
|
|
|
--lua bios says these are for "backwards compatibility", but neither [lua bios, openloader] provide
|
|
|
|
--other ways to find the boot filesystem and both [openos, plan9k] call getBootAddress during boot
|
|
|
|
function computer.getBootAddress()
|
|
|
|
return bootfs
|
|
|
|
end
|
|
|
|
function computer.setBootAddress(addr)
|
|
|
|
return ci(eeprom, 'setData', addr)
|
|
|
|
end
|
|
|
|
|
|
|
|
local fd, err = ci(bootfs, 'open', bootpath)
|
|
|
|
if not fd then bail('open %s:%s failed: %s', bootfs:sub(1, 8), bootpath, err) end
|
|
|
|
local code = ''
|
|
|
|
local lots = math.maxinteger or math.huge --read as much as possible
|
|
|
|
repeat
|
|
|
|
local chunk, err = ci(bootfs, 'read', fd, lots)
|
|
|
|
if err then bail('read %s:%s failed: %s', bootfs:sub(1, 8), bootpath, err) end
|
|
|
|
code = code .. (chunk or '')
|
|
|
|
until not chunk
|
|
|
|
ci(bootfs, 'close', fd)
|
|
|
|
local fn = assert(load(code, '@' .. bootpath))
|
|
|
|
return fn(bootfs, bootpath)
|
|
|
|
|
|
|
|
-- vi: set ts=2:
|