diff --git a/partition/README.md b/partition/README.md index 5c45d76..ec8d769 100644 --- a/partition/README.md +++ b/partition/README.md @@ -9,7 +9,7 @@ The partition table resides at the end of the disk - the last sector of the disk - Ease of implementation for firmware to load from first partition - Compatibility with existing partition table formats -The partition table takes one sector (512 bytes) and is divided into 16 entries, 32 bytes each. +The partition table takes one sector (512 bytes) and is divided into 16 entries, 32 bytes each. The first entry must have a type of `mtpt` or the partition table is to be considered invalid. This first entry's name should be considered the label for the whole disk. ### Partition entry @@ -17,14 +17,14 @@ Each entry consists of: - A 20 byte name field, padded with null characters. - A 4 byte type field. This can be used either as a number or a string. - - A 4-byte start sector field. - - A 4-byte length field. + - A 32-bit big-endian start sector field. + - A 32-bit big-endian length field. Any entry with no name should be ignored. ## Tape considerations -It may prove easier to use a tape if one were to implement a virtual drive component that maps to the data on a tape. +In the case of tapes, the partition table uses the last whole sector and any remaining space, as some tapes aren't evenly divisible by 512 bytes. ## Booting diff --git a/partition/partition.lua b/partition/partition.lua index 43e0c98..b40b14a 100644 --- a/partition/partition.lua +++ b/partition/partition.lua @@ -1,50 +1,23 @@ local partition = {} -local entryPattern = "(" .. ("."):rep(20) .. ")(....)(....)(....)" - -local function cint(n,l) - local t={} - for i = 0, 7 do - t[i+1] = (n >> (i * 8)) & 0xFF - end - return string.reverse(string.char(table.unpack(t)):sub(1,l)) -end -local function toint(s) - local n = 0 - local i = 1 - for p in s:gmatch(".") do - n = n << 8 - n = n | string.byte(p) - i=i+1 - end - return n -end - -function partition.parse(sector) - local pt = {} - for name,ptype,sstart,slen in sector:gmatch(entryPattern) do - local pte = {} - pte.name = name:gsub("\0","") - if pte.name:len() > 0 then - pte.type = ptype - pte.start = toint(sstart) - pte.len = toint(slen) - pte.last = pte.start + toint(slen) - pt[#pt+1] = pte +local eformat = "c20c4>I4>I4" +function partition.parse(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 pt + return rt end function partition.generate(pt) local ps = "" - for k,v in pairs(pt) do - if not v.len then - v.len = v.last - v.start - end --- ps = ps .. ("\0"):rep(math.max(20-v.name:len(),0)) .. v.name:sub(1,20) .. v.type:sub(1,4) .. cint(v.start,4) .. cint(v.len,4) - ps = ps .. (("\0"):rep(20) .. v.name):sub(-20) .. v.type:sub(1,4) .. cint(v.start,4) .. cint(v.len,4) + for k,v in ipairs(pt) do + ps = ps .. string.pack(eformat, table.unpack(v)) end - return ps..("\0"):rep(512-ps:len()) + return ps end return partition