upstream: https://github.com/mirage/ocaml-gpt
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(mbr,gpt): migrate MBR and GPT binary codecs to Wire.Codec

Replace hand-written get/set helpers and explicit offset constants with
type-safe Wire.Codec definitions for MBR partition entries (16 bytes),
GPT partition entries (128 bytes), and GPT headers (92 bytes). Add Wire
roundtrip tests for all three structures.

+283 -159
+1 -1
lib/dune
··· 1 1 (library 2 2 (public_name gpt) 3 3 (name gpt) 4 - (libraries bytesrw uuidm checkseum mbr) 4 + (libraries bytesrw uuidm checkseum mbr wire) 5 5 (modules gpt))
+164 -157
lib/gpt.ml
··· 16 16 17 17 open Result.Syntax 18 18 19 - let guid_len = 16 20 - 21 19 (* The size of a header not counting the reserved space *) 22 20 let sizeof = 92 23 21 ··· 26 24 let min_sector_size = 512 27 25 let max_sector_size = 4096 28 26 29 - (* Binary reading helpers - little-endian *) 30 - let get_u8 s off = Char.code (Bytes.get s off) 31 - let get_u16_le s off = get_u8 s off lor (get_u8 s (off + 1) lsl 8) 27 + (* Wire type helpers *) 28 + let uuid_typ = 29 + Wire.map 30 + (fun s -> Option.get (Uuidm.of_mixed_endian_binary_string s)) 31 + Uuidm.to_mixed_endian_binary_string 32 + (Wire.byte_array ~size:(Wire.int 16)) 32 33 33 - let get_u32_le s off = 34 - Int32.logor 35 - (Int32.of_int (get_u16_le s off)) 36 - (Int32.shift_left (Int32.of_int (get_u16_le s (off + 2))) 16) 37 - 38 - let get_u64_le s off = 39 - Int64.logor 40 - (Int64.of_int32 (get_u32_le s off)) 41 - (Int64.shift_left (Int64.of_int32 (get_u32_le s (off + 4))) 32) 42 - 43 - (* Binary writing helpers - little-endian *) 44 - let set_u8 s off v = Bytes.set s off (Char.chr (v land 0xff)) 45 - 46 - let set_u16_le s off v = 47 - set_u8 s off (v land 0xff); 48 - set_u8 s (off + 1) ((v lsr 8) land 0xff) 49 - 50 - let set_u32_le s off v = 51 - set_u16_le s off (Int32.to_int (Int32.logand v 0xffffl)); 52 - set_u16_le s (off + 2) 53 - (Int32.to_int (Int32.logand (Int32.shift_right_logical v 16) 0xffffl)) 54 - 55 - let set_u64_le s off v = 56 - set_u32_le s off (Int64.to_int32 v); 57 - set_u32_le s (off + 4) (Int64.to_int32 (Int64.shift_right_logical v 32)) 34 + let uint32_as_int32 = 35 + Wire.map 36 + (fun u -> Int32.of_int (Wire.UInt32.to_int u)) 37 + (fun i -> Wire.UInt32.of_int (Int32.to_int i)) 38 + Wire.uint32 58 39 59 40 module Reader = Bytesrw.Bytes.Reader 60 41 module Writer = Bytesrw.Bytes.Writer ··· 111 92 && String.for_all (Char.equal '\000') p.name 112 93 113 94 let sizeof = 128 114 - let type_guid_offset = 0 115 - let partition_guid_offset = 16 116 - let starting_lba_offset = 32 117 - let ending_lba_offset = 40 118 - let attributes_offset = 48 119 - let name_offset = 56 95 + 96 + let codec = 97 + let open Wire.Codec in 98 + record "GptPartition" 99 + (fun type_guid partition_guid starting_lba ending_lba attributes name -> 100 + { 101 + type_guid; 102 + partition_guid; 103 + starting_lba; 104 + ending_lba; 105 + attributes; 106 + name; 107 + }) 108 + |+ field "type_guid" uuid_typ (fun t -> t.type_guid) 109 + |+ field "partition_guid" uuid_typ (fun t -> t.partition_guid) 110 + |+ field "starting_lba" Wire.uint64 (fun t -> t.starting_lba) 111 + |+ field "ending_lba" Wire.uint64 (fun t -> t.ending_lba) 112 + |+ field "attributes" Wire.uint64 (fun t -> t.attributes) 113 + |+ field "name" (Wire.byte_array ~size:(Wire.int 72)) (fun t -> t.name) 114 + |> seal 115 + 116 + let struct_ = Wire.Codec.to_struct codec 120 117 121 118 let unmarshal buf off = 122 119 if Bytes.length buf < off + sizeof then 123 120 Printf.ksprintf invalid_arg "Partition entry too small: %d < %d" 124 121 (Bytes.length buf - off) 125 122 sizeof; 126 - let type_guid_bytes = 127 - Bytes.sub_string buf (off + type_guid_offset) guid_len 128 - in 129 - let type_guid = 130 - Option.get (Uuidm.of_mixed_endian_binary_string type_guid_bytes) 131 - in 132 - let partition_guid_bytes = 133 - Bytes.sub_string buf (off + partition_guid_offset) guid_len 134 - in 135 - let partition_guid = 136 - Option.get (Uuidm.of_mixed_endian_binary_string partition_guid_bytes) 137 - in 138 - let starting_lba = get_u64_le buf (off + starting_lba_offset) in 139 - let ending_lba = get_u64_le buf (off + ending_lba_offset) in 140 - let attributes = get_u64_le buf (off + attributes_offset) in 141 - let name = Bytes.sub_string buf (off + name_offset) 72 in 142 - { type_guid; partition_guid; starting_lba; ending_lba; attributes; name } 123 + Wire.Codec.decode codec buf off 143 124 144 - let marshal (buf : bytes) off t = 145 - Bytes.blit_string 146 - (Uuidm.to_mixed_endian_binary_string t.type_guid) 147 - 0 buf (off + type_guid_offset) guid_len; 148 - Bytes.blit_string 149 - (Uuidm.to_mixed_endian_binary_string t.partition_guid) 150 - 0 buf 151 - (off + partition_guid_offset) 152 - guid_len; 153 - set_u64_le buf (off + starting_lba_offset) t.starting_lba; 154 - set_u64_le buf (off + ending_lba_offset) t.ending_lba; 155 - set_u64_le buf (off + attributes_offset) t.attributes; 156 - let name_len = min 72 (String.length t.name) in 157 - Bytes.blit_string t.name 0 buf (off + name_offset) name_len; 158 - if name_len < 72 then 159 - Bytes.fill buf (off + name_offset + name_len) (72 - name_len) '\000' 125 + let marshal (buf : bytes) off t = Wire.Codec.encode codec t buf off 160 126 161 127 let to_string t = 162 128 let buf = Bytes.create sizeof in ··· 164 130 Bytes.to_string buf 165 131 end 166 132 133 + (* Raw header type for Wire codec (no partitions list) *) 134 + type raw_header = { 135 + revision : int32; 136 + header_size : int32; 137 + header_crc32 : int32; 138 + reserved : int32; 139 + current_lba : int64; 140 + backup_lba : int64; 141 + first_usable_lba : int64; 142 + last_usable_lba : int64; 143 + disk_guid : Uuidm.t; 144 + partition_entry_lba : int64; 145 + num_partition_entries : int32; 146 + partition_size : int32; 147 + partitions_crc32 : int32; 148 + } 149 + 150 + let header_codec = 151 + let open Wire.Codec in 152 + record "GptHeader" 153 + (fun 154 + _sig 155 + revision 156 + header_size 157 + header_crc32 158 + reserved 159 + current_lba 160 + backup_lba 161 + first_usable_lba 162 + last_usable_lba 163 + disk_guid 164 + partition_entry_lba 165 + num_partition_entries 166 + partition_size 167 + partitions_crc32 168 + -> 169 + { 170 + revision; 171 + header_size; 172 + header_crc32; 173 + reserved; 174 + current_lba; 175 + backup_lba; 176 + first_usable_lba; 177 + last_usable_lba; 178 + disk_guid; 179 + partition_entry_lba; 180 + num_partition_entries; 181 + partition_size; 182 + partitions_crc32; 183 + }) 184 + |+ field "signature" 185 + (Wire.byte_array ~size:(Wire.int 8)) 186 + (fun _ -> "EFI PART") 187 + |+ field "revision" uint32_as_int32 (fun h -> h.revision) 188 + |+ field "header_size" uint32_as_int32 (fun h -> h.header_size) 189 + |+ field "header_crc32" uint32_as_int32 (fun h -> h.header_crc32) 190 + |+ field "reserved" uint32_as_int32 (fun h -> h.reserved) 191 + |+ field "current_lba" Wire.uint64 (fun h -> h.current_lba) 192 + |+ field "backup_lba" Wire.uint64 (fun h -> h.backup_lba) 193 + |+ field "first_usable_lba" Wire.uint64 (fun h -> h.first_usable_lba) 194 + |+ field "last_usable_lba" Wire.uint64 (fun h -> h.last_usable_lba) 195 + |+ field "disk_guid" uuid_typ (fun h -> h.disk_guid) 196 + |+ field "partition_entry_lba" Wire.uint64 (fun h -> h.partition_entry_lba) 197 + |+ field "num_partition_entries" uint32_as_int32 (fun h -> 198 + h.num_partition_entries) 199 + |+ field "partition_size" uint32_as_int32 (fun h -> h.partition_size) 200 + |+ field "partitions_crc32" uint32_as_int32 (fun h -> h.partitions_crc32) 201 + |> seal 202 + 203 + let header_struct_ = Wire.Codec.to_struct header_codec 204 + 167 205 type t = { 168 206 revision : int32; 169 207 header_size : int32; ··· 182 220 } 183 221 184 222 let signature = "EFI PART" 185 - let signature_offset = 0 186 - let signature_len = 8 187 - let revision_offset = 8 188 - let header_size_offset = 12 189 - let header_crc32_offset = 16 190 - let reserved_offset = 20 191 - let current_lba_offset = 24 192 - let backup_lba_offset = 32 193 - let first_usable_lba_offset = 40 194 - let last_usable_lba_offset = 48 195 - let disk_guid_offset = 56 196 - let partition_entry_lba_offset = 72 197 - let num_partition_entries_offset = 80 198 - let partition_size_offset = 84 199 - let partitions_crc32_offset = 88 223 + 224 + let raw_header_of_t t = 225 + { 226 + revision = t.revision; 227 + header_size = t.header_size; 228 + header_crc32 = t.header_crc32; 229 + reserved = t.reserved; 230 + current_lba = t.current_lba; 231 + backup_lba = t.backup_lba; 232 + first_usable_lba = t.first_usable_lba; 233 + last_usable_lba = t.last_usable_lba; 234 + disk_guid = t.disk_guid; 235 + partition_entry_lba = t.partition_entry_lba; 236 + num_partition_entries = t.num_partition_entries; 237 + partition_size = t.partition_size; 238 + partitions_crc32 = t.partitions_crc32; 239 + } 200 240 201 241 let marshal_header_bytes buf header = 202 - Bytes.blit_string signature 0 buf 0 (String.length signature); 203 - set_u32_le buf revision_offset header.revision; 204 - set_u32_le buf header_size_offset header.header_size; 205 - set_u32_le buf header_crc32_offset 0l; 206 - (* zero for CRC calculation *) 207 - set_u32_le buf reserved_offset header.reserved; 208 - set_u64_le buf current_lba_offset header.current_lba; 209 - set_u64_le buf backup_lba_offset header.backup_lba; 210 - set_u64_le buf first_usable_lba_offset header.first_usable_lba; 211 - set_u64_le buf last_usable_lba_offset header.last_usable_lba; 212 - Bytes.blit_string 213 - (Uuidm.to_mixed_endian_binary_string header.disk_guid) 214 - 0 buf disk_guid_offset guid_len; 215 - set_u64_le buf partition_entry_lba_offset header.partition_entry_lba; 216 - set_u32_le buf num_partition_entries_offset header.num_partition_entries; 217 - set_u32_le buf partition_size_offset header.partition_size; 218 - set_u32_le buf partitions_crc32_offset header.partitions_crc32 242 + let raw = { (raw_header_of_t header) with header_crc32 = 0l } in 243 + Wire.Codec.encode header_codec raw buf 0 219 244 220 245 let calculate_header_crc32 header = 221 246 let buf = Bytes.create sizeof in ··· 358 383 if Bytes.length buf < sizeof then 359 384 Printf.ksprintf invalid_arg "GPT too small: %d < %d" (Bytes.length buf) 360 385 sizeof; 361 - let sig_str = Bytes.sub_string buf signature_offset signature_len in 386 + (* Validate signature from raw bytes before decoding *) 387 + let sig_str = Bytes.sub_string buf 0 8 in 362 388 let* () = 363 389 match sig_str with 364 390 | "EFI PART" -> Ok () ··· 366 392 Error 367 393 (Printf.sprintf "Signature not found; expected 'EFI PART', got '%s'" x) 368 394 in 369 - let revision = get_u32_le buf revision_offset in 395 + (* Decode header fields via Wire codec *) 396 + let raw = Wire.Codec.decode header_codec buf 0 in 370 397 let* () = 371 - if revision = 0x010000l then Ok () 398 + if raw.revision = 0x010000l then Ok () 372 399 else 373 400 Error 374 401 (Printf.sprintf "Unknown revision; expected 0x10000, got 0x%08lx" 375 - revision) 402 + raw.revision) 376 403 in 377 - let header_size = get_u32_le buf header_size_offset in 378 - let header_crc32 = get_u32_le buf header_crc32_offset in 404 + (* Validate header CRC32 (CRC field at offset 16 is zeroed for calculation) *) 379 405 let* () = 380 - let header_size_int = Int32.to_int header_size in 406 + let header_size_int = Int32.to_int raw.header_size in 381 407 let buf_str = Bytes.to_string buf in 382 408 let crc32 = 383 - Checkseum.Crc32.digest_string buf_str 0 header_crc32_offset 384 - Checkseum.Crc32.default 409 + Checkseum.Crc32.digest_string buf_str 0 16 Checkseum.Crc32.default 385 410 in 386 411 let crc32 = Checkseum.Crc32.digest_string "\000\000\000\000" 0 4 crc32 in 387 412 let crc32 = 388 - Checkseum.Crc32.digest_string buf_str (header_crc32_offset + 4) 389 - (header_size_int - header_crc32_offset - 4) 390 - crc32 413 + Checkseum.Crc32.digest_string buf_str 20 (header_size_int - 20) crc32 391 414 in 392 415 let header_crc32' = Checkseum.Crc32.to_int32 crc32 in 393 - if header_crc32' = header_crc32 then Ok () 416 + if header_crc32' = raw.header_crc32 then Ok () 394 417 else Error "Bad GPT header checksum" 395 418 in 396 - let reserved = get_u32_le buf reserved_offset in 397 - let current_lba = get_u64_le buf current_lba_offset in 398 - let backup_lba = get_u64_le buf backup_lba_offset in 399 - let first_usable_lba = get_u64_le buf first_usable_lba_offset in 400 - let last_usable_lba = get_u64_le buf last_usable_lba_offset in 401 419 (* Security: validate LBA ordering *) 402 420 let* () = 403 - if Int64.compare first_usable_lba last_usable_lba > 0 then 421 + if Int64.compare raw.first_usable_lba raw.last_usable_lba > 0 then 404 422 Error 405 423 (Printf.sprintf "first_usable_lba %Ld > last_usable_lba %Ld" 406 - first_usable_lba last_usable_lba) 424 + raw.first_usable_lba raw.last_usable_lba) 407 425 else Ok () 408 426 in 409 - let disk_guid_bytes = Bytes.sub_string buf disk_guid_offset guid_len in 410 - let* disk_guid = 411 - match Uuidm.of_mixed_endian_binary_string disk_guid_bytes with 412 - | Some guid -> Ok guid 413 - | None -> 414 - Error 415 - (Printf.sprintf "Failed to parse disk_guid; got '%s'" disk_guid_bytes) 416 - in 417 - let partition_entry_lba = get_u64_le buf partition_entry_lba_offset in 418 - let num_partition_entries = get_u32_le buf num_partition_entries_offset in 419 427 (* Security: validate num_partition_entries to prevent memory exhaustion *) 420 - let num_partition_entries_int = Int32.to_int num_partition_entries in 428 + let num_partition_entries_int = Int32.to_int raw.num_partition_entries in 421 429 let* () = 422 430 if 423 431 num_partition_entries_int < 0 ··· 428 436 num_partition_entries_int max_partition_entries) 429 437 else Ok () 430 438 in 431 - let partitions_crc32 = get_u32_le buf partitions_crc32_offset in 432 - let partition_size = get_u32_le buf partition_size_offset in 433 439 let* () = 434 - if partition_size <> Int32.of_int Partition.sizeof then 435 - Error (Printf.sprintf "Unexpected partition size: %lu" partition_size) 440 + if raw.partition_size <> Int32.of_int Partition.sizeof then 441 + Error (Printf.sprintf "Unexpected partition size: %lu" raw.partition_size) 436 442 else Ok () 437 443 in 438 444 let partition_entry_sectors = ··· 440 446 / sector_size 441 447 in 442 448 Ok 443 - ( `Read_partition_table (partition_entry_lba, partition_entry_sectors), 449 + ( `Read_partition_table (raw.partition_entry_lba, partition_entry_sectors), 444 450 fun table_buf -> 445 451 let table_size = num_partition_entries_int * Partition.sizeof in 446 452 if Bytes.length table_buf < table_size then ··· 452 458 |> Checkseum.Crc32.to_int32 453 459 in 454 460 let* () = 455 - if Int32.equal partitions_crc32' partitions_crc32 then Ok () 461 + if Int32.equal partitions_crc32' raw.partitions_crc32 then Ok () 456 462 else Error "Bad partition table checksum" 457 463 in 458 464 let rev_partitions = ··· 471 477 List.fold_left 472 478 (fun r p -> 473 479 let* () = r in 474 - if Int64.compare p.Partition.starting_lba first_usable_lba < 0 480 + if Int64.compare p.Partition.starting_lba raw.first_usable_lba < 0 475 481 then 476 482 Error 477 483 (Printf.sprintf 478 484 "Partition starting_lba %Ld < first_usable_lba %Ld" 479 - p.Partition.starting_lba first_usable_lba) 480 - else if Int64.compare p.Partition.ending_lba last_usable_lba > 0 485 + p.Partition.starting_lba raw.first_usable_lba) 486 + else if 487 + Int64.compare p.Partition.ending_lba raw.last_usable_lba > 0 481 488 then 482 489 Error 483 490 (Printf.sprintf 484 491 "Partition ending_lba %Ld > last_usable_lba %Ld" 485 - p.Partition.ending_lba last_usable_lba) 492 + p.Partition.ending_lba raw.last_usable_lba) 486 493 else if 487 494 Int64.compare p.Partition.starting_lba p.Partition.ending_lba 488 495 > 0 ··· 495 502 in 496 503 Ok 497 504 { 498 - revision; 499 - header_size; 500 - header_crc32; 501 - reserved; 502 - current_lba; 503 - backup_lba; 504 - first_usable_lba; 505 - last_usable_lba; 506 - disk_guid; 507 - partition_entry_lba; 508 - num_partition_entries; 505 + revision = raw.revision; 506 + header_size = raw.header_size; 507 + header_crc32 = raw.header_crc32; 508 + reserved = raw.reserved; 509 + current_lba = raw.current_lba; 510 + backup_lba = raw.backup_lba; 511 + first_usable_lba = raw.first_usable_lba; 512 + last_usable_lba = raw.last_usable_lba; 513 + disk_guid = raw.disk_guid; 514 + partition_entry_lba = raw.partition_entry_lba; 515 + num_partition_entries = raw.num_partition_entries; 509 516 partitions; 510 - partition_size; 511 - partitions_crc32; 517 + partition_size = raw.partition_size; 518 + partitions_crc32 = raw.partitions_crc32; 512 519 } ) 513 520 514 521 let of_string s ~sector_size = unmarshal_bytes (Bytes.of_string s) ~sector_size ··· 524 531 in 525 532 { t with header_crc32 = Optint.to_int32 (calculate_header_crc32 t) } 526 533 in 527 - marshal_header_bytes buf t; 528 - set_u32_le buf header_crc32_offset t.header_crc32; 534 + let raw = raw_header_of_t t in 535 + Wire.Codec.encode header_codec raw buf 0; 529 536 Bytes.to_string buf 530 537 531 538 let marshal_partition_table_to_string ~sector_size t =
+31
lib/gpt.mli
··· 45 45 46 46 val sizeof : int 47 47 (** Size of a partition entry in bytes (128). *) 48 + 49 + val codec : t Wire.Codec.t 50 + (** Wire codec for a 128-byte GPT partition entry. *) 51 + 52 + val struct_ : Wire.struct_ 53 + (** Wire struct definition for a partition entry. *) 48 54 end 55 + 56 + (** {1 Raw header (Wire codec)} *) 57 + 58 + type raw_header = { 59 + revision : int32; 60 + header_size : int32; 61 + header_crc32 : int32; 62 + reserved : int32; 63 + current_lba : int64; 64 + backup_lba : int64; 65 + first_usable_lba : int64; 66 + last_usable_lba : int64; 67 + disk_guid : Uuidm.t; 68 + partition_entry_lba : int64; 69 + num_partition_entries : int32; 70 + partition_size : int32; 71 + partitions_crc32 : int32; 72 + } 73 + (** Raw GPT header without partition list, for Wire codec serialization. *) 74 + 75 + val header_codec : raw_header Wire.Codec.t 76 + (** Wire codec for a 92-byte GPT header. *) 77 + 78 + val header_struct_ : Wire.struct_ 79 + (** Wire struct definition for a GPT header. *) 49 80 50 81 type t = private { 51 82 revision : int32;
+1 -1
test/dune
··· 1 1 (test 2 2 (name test_gpt) 3 - (libraries gpt alcotest fmt)) 3 + (libraries gpt wire alcotest fmt))
+86
test/test_gpt.ml
··· 258 258 let gpt_test_collection = 259 259 [ ("gpt marshal then unmarshal", `Quick, test_marshal_unmarshal) ] 260 260 261 + let test_partition_wire_size () = 262 + Alcotest.(check int) 263 + "partition wire_size" 128 264 + (Wire.Codec.wire_size Gpt.Partition.codec) 265 + 266 + let test_header_wire_size () = 267 + Alcotest.(check int) 268 + "header wire_size" 92 269 + (Wire.Codec.wire_size Gpt.header_codec) 270 + 271 + let test_partition_wire_roundtrip () = 272 + let type_guid = 273 + Option.get (Uuidm.of_string "12345678-1234-1234-1234-123456789abc") 274 + in 275 + let p = 276 + get_ok 277 + (Gpt.Partition.make ~type_guid 278 + ~name:(name_of_ascii "Wire Test") 279 + ~attributes:0x80L 2048L 4095L) 280 + in 281 + let buf = Bytes.create 128 in 282 + Wire.Codec.encode Gpt.Partition.codec p buf 0; 283 + let p' = Wire.Codec.decode Gpt.Partition.codec buf 0 in 284 + Alcotest.(check bool) "type_guid" true (Uuidm.equal p.type_guid p'.type_guid); 285 + Alcotest.(check bool) 286 + "partition_guid" true 287 + (Uuidm.equal p.partition_guid p'.partition_guid); 288 + Alcotest.(check int64) "starting_lba" p.starting_lba p'.starting_lba; 289 + Alcotest.(check int64) "ending_lba" p.ending_lba p'.ending_lba; 290 + Alcotest.(check int64) "attributes" p.attributes p'.attributes; 291 + Alcotest.(check string) "name" p.name p'.name 292 + 293 + let test_header_wire_roundtrip () = 294 + let disk_guid = 295 + Option.get (Uuidm.of_string "aabbccdd-1122-3344-5566-778899aabbcc") 296 + in 297 + let raw : Gpt.raw_header = 298 + { 299 + revision = 0x010000l; 300 + header_size = 92l; 301 + header_crc32 = 0x12345678l; 302 + reserved = 0l; 303 + current_lba = 1L; 304 + backup_lba = 16383L; 305 + first_usable_lba = 34L; 306 + last_usable_lba = 16350L; 307 + disk_guid; 308 + partition_entry_lba = 2L; 309 + num_partition_entries = 128l; 310 + partition_size = 128l; 311 + partitions_crc32 = 0xdeadbeeFl; 312 + } 313 + in 314 + let buf = Bytes.create 92 in 315 + Wire.Codec.encode Gpt.header_codec raw buf 0; 316 + let raw' = Wire.Codec.decode Gpt.header_codec buf 0 in 317 + Alcotest.(check int32) "revision" raw.revision raw'.revision; 318 + Alcotest.(check int32) "header_size" raw.header_size raw'.header_size; 319 + Alcotest.(check int32) "header_crc32" raw.header_crc32 raw'.header_crc32; 320 + Alcotest.(check int32) "reserved" raw.reserved raw'.reserved; 321 + Alcotest.(check int64) "current_lba" raw.current_lba raw'.current_lba; 322 + Alcotest.(check int64) "backup_lba" raw.backup_lba raw'.backup_lba; 323 + Alcotest.(check int64) 324 + "first_usable_lba" raw.first_usable_lba raw'.first_usable_lba; 325 + Alcotest.(check int64) 326 + "last_usable_lba" raw.last_usable_lba raw'.last_usable_lba; 327 + Alcotest.(check bool) 328 + "disk_guid" true 329 + (Uuidm.equal raw.disk_guid raw'.disk_guid); 330 + Alcotest.(check int64) 331 + "partition_entry_lba" raw.partition_entry_lba raw'.partition_entry_lba; 332 + Alcotest.(check int32) 333 + "num_partition_entries" raw.num_partition_entries raw'.num_partition_entries; 334 + Alcotest.(check int32) "partition_size" raw.partition_size raw'.partition_size; 335 + Alcotest.(check int32) 336 + "partitions_crc32" raw.partitions_crc32 raw'.partitions_crc32 337 + 338 + let wire_test_collection = 339 + [ 340 + ("partition wire_size = 128", `Quick, test_partition_wire_size); 341 + ("header wire_size = 92", `Quick, test_header_wire_size); 342 + ("partition wire roundtrip", `Quick, test_partition_wire_roundtrip); 343 + ("header wire roundtrip", `Quick, test_header_wire_roundtrip); 344 + ] 345 + 261 346 let () = 262 347 Alcotest.run "Ocaml Gpt" 263 348 [ 264 349 ("Test GPT Partitions", partition_test_collection); 265 350 ("Test GPT Header", gpt_header_test_collection); 266 351 ("Test GPT", gpt_test_collection); 352 + ("Wire", wire_test_collection); 267 353 ]