- (* Offset of the first EBR. *)
- let ebr_offs = sect *^ sector_size in
- (* EBR Signature? *)
- LargeFile.lseek fd (ebr_offs +^ 510L) SEEK_SET;
- let str = String.create 2 in
- if read fd str 0 2 <> 2 || str.[0] != '\x55' || str.[1] != '\xAA' then
- [] (* Not EBR *)
- else (
- (* Read the extended partition table entries (just 2 of them). *)
- LargeFile.lseek fd (ebr_offs +^ 446L) SEEK_SET;
- let str = String.create 32 in
- if read fd str 0 32 <> 32 then
- failwith (s_ "error reading extended partition")
- else (
- (* Extract partitions from the data. *)
- let part1, part2 =
- match List.map (get_partition str) [ 0; 16 ] with
- | [p1;p2] -> p1,p2
- | _ -> failwith (s_ "probe_extended_partition: internal error") in
- (* First partition entry has offset to the start of this partition. *)
- let part1 = { part1 with
- part_lba_start = sect +^ part1.part_lba_start } in
- (* Second partition entry is zeroes if end of list, otherwise points
- * to the next partition.
- *)
- if part2.part_status = NullEntry then
- [part1]
- else
- part1 :: probe_extended_partition
- (max-1) fd epart (sect +^ part2.part_lba_start)
+ try
+ (* Get the partition table (like a boot sector). *)
+ let bits = dev#read_bitstring (start *^ sector_size) sector_size in
+
+ (bitmatch bits with
+ | { _ : 3568 : bitstring; (* padding to byte offset 446 *)
+ part : 128 : bitstring; (* this partition *)
+ next : 128 : bitstring; (* pointer to next extended partition *)
+ _ : 128 : bitstring; (* ignored - should be zero *)
+ _ : 128 : bitstring;
+ 0x55 : 8; 0xAA : 8 } -> (* MBR signature *)
+
+ let (part, ppriv) = parse_mbr_entry part in
+
+ (* The first partition's LBA is actually offset relative
+ * to the current sector.
+ *)
+ let ppriv =
+ { ppriv with mbr_part_start = ppriv.mbr_part_start +^ start } in
+
+ let (next, npriv) = parse_mbr_entry next in
+
+ if next.part_status = NullEntry then
+ [ part, ppriv ] (* End of list. *)
+ else (
+ let start_of_next = start +^ npriv.mbr_part_start in
+ (part, ppriv) ::
+ probe_extended_partition (max-1) dev start_of_next
+ )
+
+ | { _ } ->
+ invalid_arg "mbr: invalid extended partition table"