-- Minimum viable BIOS, effectively a blend between LuaBIOS and AdvancedLoader local component, computer = component, computer local gpu = component.list("gpu")() local screen = component.list("screen")() local eeprom = component.list("eeprom")() computer.getBootAddress = function() return component.invoke(eeprom, "getData") end computer.setBootAddress = function(addr) return component.invoke(eeprom, "setData", addr) end if gpu and screen then component.invoke(gpu, "bind", screen) local w, h = component.invoke(gpu, "maxResolution") component.invoke(gpu, "setResolution", w, h) component.invoke(gpu, "setForeground", 0xFFFFFF) component.invoke(gpu, "setBackground", 0x000000) component.invoke(gpu, "fill", 1, 1, w, h, " ") end local function romRead(addr, path) local fs = component.proxy(addr) local fd = fs.open(path) if not fd then return end local data = "" while true do local chunk, err = fs.read(fd, math.huge) if err then fs.close(fd) return nil end if not chunk then break end data = data .. chunk end fs.close(fd) return data end local function getBootCode(addr) local drive = component.proxy(addr) local sectorSize = drive.getSectorSize() local firstSector = drive.readSector(1) -- Generic MBR bootcode if firstSector:sub(-2, -1) == "\x55\xAA" then local codeEnd = sectorSize - 66 local codeSec = string.sub(firstSector, 1, codeEnd) local term = string.find(codeSec, "\0", nil, true) return load(string.sub(codeSec, 1, term and (term - 1) or -1)) end -- TODO: whatever else NC might be testing -- Read first 32K, which is a standard convention local sectorsIn32K = math.ceil(32768 / sectorSize) local bootCode = {firstSector} -- since its null terminated, this is an optimization if not firstSector:find("\0") then for i=2,sectorsIn32K do local sec = drive.readSector(i) table.insert(bootCode, sec) if sec:find("\0") then break end end end local rawCode = table.concat(bootCode) local term = string.find(rawCode, "\0") rawCode = string.sub(rawCode, 1, term and (term - 1) or -1) if rawCode == "" then return end return load(rawCode) end local paths = { "init.lua", "OS.lua", "boot/pipes/kernel", } local bootables = {} for addr in component.list("filesystem", true) do for _, path in ipairs(paths) do local code = romRead(addr, path) if code then table.insert(bootables, {addr = addr, code = load(code)}) end end end for addr in component.list("drive", true) do local f = getBootCode(addr) if f then table.insert(bootables, {code = f, addr = addr}) end end local function boot(bootable) local w, h = component.invoke(gpu, "maxResolution") component.invoke(gpu, "setResolution", w, h) component.invoke(gpu, "setForeground", 0xFFFFFF) component.invoke(gpu, "setBackground", 0x000000) component.invoke(gpu, "fill", 1, 1, w, h, " ") computer.setBootAddress(bootable.addr) bootable.code(bootable.addr) error("halted") end if #bootables == 1 then boot(bootables[1]) elseif #bootables > 1 then local sel = 1 local function showBootable(bootable, i) local w = component.invoke(gpu, "getResolution") component.invoke(gpu, "fill", 1, i, w, 1, " ") local text = component.invoke(bootable.addr, "getLabel") or bootable.addr component.invoke(gpu, "set", 1, i, text) end for i=1,#bootables do if i == 1 then component.invoke(gpu, "setForeground", 0x000000) component.invoke(gpu, "setBackground", 0xFFFFFF) else component.invoke(gpu, "setForeground", 0xFFFFFF) component.invoke(gpu, "setBackground", 0x000000) end showBootable(bootables[i], i) end while true do local e = {computer.pullSignal()} if e[1] == "key_down" then local keycode = e[4] component.invoke(gpu, "setForeground", 0xFFFFFF) component.invoke(gpu, "setBackground", 0x000000) showBootable(bootables[sel], sel) if keycode == 0x1C then break elseif keycode == 0xC8 then sel = math.max(sel - 1, 1) elseif keycode == 0xD0 then sel = math.min(sel + 1, #bootables) end component.invoke(gpu, "setForeground", 0x000000) component.invoke(gpu, "setBackground", 0xFFFFFF) showBootable(bootables[sel], sel) end end boot(bootables[sel]) end error("no bootable medium found")