From 2a7078d6d349f345b17addbec845609b1c29ac90 Mon Sep 17 00:00:00 2001 From: XeonSquared Date: Thu, 3 Aug 2023 10:21:32 +1000 Subject: [PATCH] add bootloader compatible with mtpt --- partition/README.md | 2 +- partition/driveboot.lua | 68 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 partition/driveboot.lua diff --git a/partition/README.md b/partition/README.md index ec8d769..18a594e 100644 --- a/partition/README.md +++ b/partition/README.md @@ -1,4 +1,4 @@ -# Simple partition table format +# Minitel Partition Table (MTPT) This document specifies a general partition table format suitable for both unmanaged disks, and tapes. diff --git a/partition/driveboot.lua b/partition/driveboot.lua new file mode 100644 index 0000000..390fc69 --- /dev/null +++ b/partition/driveboot.lua @@ -0,0 +1,68 @@ +function computer.getBootAddress() + return component.invoke(component.list("eeprom")(),"getData") +end +function computer.setBootAddress(a) + return component.invoke(component.list("eeprom")(),"setData",a) +end +return (function() +local rv +local function getProxy(addr) + if type(addr) == "string" then + return component.proxy(addr) + end + return addr +end + +local eformat = "c20c4>I4>I4" +function parsePartitions(s) + local rt = {} + for i = 1, s:len(), 32 do + local n, t, start, length = string.unpack(eformat, s, i) + n = n:gsub("\0", "") + if n ~= "" then + rt[#rt+1] = {n,t,start,length} + end + end + return rt +end + +function getPartitions(drive) + return parsePartitions(drive.readSector(drive.getCapacity() / drive.getSectorSize())) +end + +local function offsetSector(part,sector) + if sector < 1 or sector > part[4] then error("invalid offset, not in a usable sector") end + return (part[3] - 1) + sector +end +local function readSector(drive,part,sector) + return drive.readSector(offsetSector(part,sector)):gsub("\0+$","") +end +local function readPart(drive,part) + local rv = "" + for i = 1, part[4] do + rv=rv .. readSector(drive,part,i) + end + return rv +end + +local candidates={computer.getBootAddress()} +for a,_ in component.list("drive") do + candidates[#candidates+1] = a +end +for i,a in ipairs(candidates) do + computer.beep(("."):rep(i)) + local d = getProxy(a) + if type(d) == "table" then + for k,v in ipairs(getPartitions(d)) do + if v[2] == "boot" then + local rv = load(readPart(d,v)) + if rv then + computer.beep("-") + computer.setBootAddress(a) + return rv + end + end + end + end +end +end)()()