From 2f645f6081bdda63596bd3ad394d0bc2e1c0fecc Mon Sep 17 00:00:00 2001 From: PizieDust Date: Tue, 23 May 2023 12:25:20 +0100 Subject: [PATCH 01/11] Test --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 9721dd7..f1605b1 100644 --- a/README.md +++ b/README.md @@ -35,3 +35,4 @@ To do items * Implement tools to manipulate MBR-formatted disk images to construct, inspect or fill partitions that can later be used in Mirage unikernels. + From 45dd198bbb89e8e80c9e1ea5c9f485eaf91b82b1 Mon Sep 17 00:00:00 2001 From: PizieDust Date: Wed, 31 May 2023 14:35:14 +0100 Subject: [PATCH 02/11] display the total size of each partition in bytes --- bin/mbr_inspect.ml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bin/mbr_inspect.ml b/bin/mbr_inspect.ml index ea1d3f4..4250793 100644 --- a/bin/mbr_inspect.ml +++ b/bin/mbr_inspect.ml @@ -30,7 +30,9 @@ let print_mbr_fields print_bootstrap_code mbr = cylinders heads sectors; Printf.printf " lba_begin: %ld\n" part.Mbr.Partition.first_absolute_sector_lba; - Printf.printf " size_sectors: %ld\n" part.Mbr.Partition.sectors) + Printf.printf " size_sectors: %ld\n" part.Mbr.Partition.sectors; + let partition_size = Int64.mul (Int64.of_int32 part.Mbr.Partition.sectors) (Int64.of_int Mbr.sizeof) in + Printf.printf " Total Partition Size: %Ld bytes\n" partition_size) mbr.partitions let read_mbrs print_bootstrap_code mbrs = From 6259ed61bf70dc88b6cf354323501fe781c36edf Mon Sep 17 00:00:00 2001 From: PizieDust Date: Wed, 31 May 2023 14:35:36 +0100 Subject: [PATCH 03/11] create an mbr formatted disk --- bin/create_mbr_disk.ml | 67 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 bin/create_mbr_disk.ml diff --git a/bin/create_mbr_disk.ml b/bin/create_mbr_disk.ml new file mode 100644 index 0000000..cfb03b0 --- /dev/null +++ b/bin/create_mbr_disk.ml @@ -0,0 +1,67 @@ +open Cmdliner + +let create_mbr_disk destination partition_files = + let sector_size = Mbr.sizeof in + let num_partitions = List.length partition_files in + Printf.printf "Total partitions to create: %d\n" num_partitions; + + let partition_sizes = + List.map (fun file -> (Unix.stat file).Unix.st_size) partition_files + in + + let partition_size = List.fold_left (+) 0 partition_sizes in + let mbr_size = Mbr.sizeof in + let total_size = partition_size + mbr_size in + + Printf.printf "Total disk size: %d bytes\n" + total_size; + + let partitions = + List.mapi (fun i size -> + Printf.printf "Creating partition: %d" (i+1); + let start_sector = (i + 1) * sector_size in + let num_sectors = (size + sector_size - 1) / sector_size in + match + Mbr.Partition.make ~active:false ~partition_type:6 (Int32.of_int start_sector) (Int32.of_int num_sectors) + with + | Ok partition -> + Printf.printf " - OK\n"; + partition + | Error msg -> failwith msg + ) partition_sizes + in + + (* Mbr.make smart constructor checks for partition overlap, more than 1 active partitions and too many partitions *) + let mbr = + match Mbr.make partitions with + | Ok mbr -> mbr + | Error msg -> failwith ("Failed to create MBR: " ^ msg) + in + + let oc = open_out_gen [ Open_wronly; Open_binary; Open_creat; Open_trunc ] 0o644 destination in + seek_out oc (total_size - 1); (* Seek to the last byte of the file *) + output_byte oc 0; (* Write a single byte to extend the file size *) + close_out oc; + + let oc = open_out_bin destination in + let mbr_buffer = Cstruct.create Mbr.sizeof in + Mbr.marshal mbr_buffer mbr; + output oc (Cstruct.to_bytes mbr_buffer) 0 Mbr.sizeof; + close_out oc; + Unix.truncate destination total_size + +let destination = + let doc = "Output file for the MBR formatted disk image" in + Arg.(required & opt (some string) None & info ["d"; "destination"] ~docv:"destination" ~doc) + +let partition_files = + let doc = "Data files to be written to the partitions" in + Arg.(value & pos_all file [] & info [] ~docv:"partition_files" ~doc) + +let cmd = + let doc = "Create an MBR formatted disk image with an MBR header." in + let info = Cmd.info "create_mbr_disk" ~version:"1.0.0" ~doc in + Cmd.v info Term.(const create_mbr_disk $ destination $ partition_files) + +let main () = exit (Cmd.eval cmd) +let () = main () From 98b21492cffd1c91fe1837c74c4bc1e221313343 Mon Sep 17 00:00:00 2001 From: PizieDust Date: Wed, 31 May 2023 14:35:54 +0100 Subject: [PATCH 04/11] binary to create mbr formmated disk --- bin/dune | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/dune b/bin/dune index edbeaa7..6feb427 100644 --- a/bin/dune +++ b/bin/dune @@ -1,3 +1,3 @@ (executables - (names mbr_inspect read_partition write_partition resize_partition) + (names mbr_inspect read_partition write_partition resize_partition create_mbr_disk) (libraries mbr cstruct cmdliner unix)) From f084834dedd4e0c6ca56fe2720b677f8bd204650 Mon Sep 17 00:00:00 2001 From: PizieDust Date: Wed, 31 May 2023 20:25:12 +0100 Subject: [PATCH 05/11] display total size of all partitions --- bin/mbr_inspect.ml | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/bin/mbr_inspect.ml b/bin/mbr_inspect.ml index 4250793..1872e5b 100644 --- a/bin/mbr_inspect.ml +++ b/bin/mbr_inspect.ml @@ -11,6 +11,18 @@ let print_mbr_fields print_bootstrap_code mbr = Printf.printf " minutes: %d\n" mbr.Mbr.minutes; Printf.printf " hours: %d\n" mbr.Mbr.hours; Printf.printf " disk_signature: %lx\n" mbr.Mbr.disk_signature; + let total_disk_size = + List.fold_left + (fun acc part -> + let partition_size = + Int64.mul + (Int64.of_int32 part.Mbr.Partition.sectors) + (Int64.of_int Mbr.sizeof) + in + Int64.add acc partition_size) + Int64.zero mbr.partitions + in + Printf.printf " disk_size: %Ld bytes\n" total_disk_size; List.iteri (fun i part -> let chs_begin = part.Mbr.Partition.first_absolute_sector_chs in @@ -31,8 +43,12 @@ let print_mbr_fields print_bootstrap_code mbr = Printf.printf " lba_begin: %ld\n" part.Mbr.Partition.first_absolute_sector_lba; Printf.printf " size_sectors: %ld\n" part.Mbr.Partition.sectors; - let partition_size = Int64.mul (Int64.of_int32 part.Mbr.Partition.sectors) (Int64.of_int Mbr.sizeof) in - Printf.printf " Total Partition Size: %Ld bytes\n" partition_size) + let partition_size = + Int64.mul + (Int64.of_int32 part.Mbr.Partition.sectors) + (Int64.of_int Mbr.sizeof) + in + Printf.printf " partition_size: %Ld bytes\n" partition_size) mbr.partitions let read_mbrs print_bootstrap_code mbrs = From a22f307b1b795b2f6ae924542eb93597883b7bb7 Mon Sep 17 00:00:00 2001 From: PizieDust Date: Wed, 31 May 2023 20:25:31 +0100 Subject: [PATCH 06/11] fix linting --- bin/create_mbr_disk.ml | 47 +++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/bin/create_mbr_disk.ml b/bin/create_mbr_disk.ml index cfb03b0..bc4d6aa 100644 --- a/bin/create_mbr_disk.ml +++ b/bin/create_mbr_disk.ml @@ -7,41 +7,37 @@ let create_mbr_disk destination partition_files = let partition_sizes = List.map (fun file -> (Unix.stat file).Unix.st_size) partition_files - in + in - let partition_size = List.fold_left (+) 0 partition_sizes in + let partition_size = List.fold_left ( + ) 0 partition_sizes in let mbr_size = Mbr.sizeof in let total_size = partition_size + mbr_size in - Printf.printf "Total disk size: %d bytes\n" - total_size; + Printf.printf "Total disk size: %d bytes\n" total_size; let partitions = - List.mapi (fun i size -> - Printf.printf "Creating partition: %d" (i+1); - let start_sector = (i + 1) * sector_size in - let num_sectors = (size + sector_size - 1) / sector_size in - match - Mbr.Partition.make ~active:false ~partition_type:6 (Int32.of_int start_sector) (Int32.of_int num_sectors) - with - | Ok partition -> - Printf.printf " - OK\n"; - partition - | Error msg -> failwith msg - ) partition_sizes + List.mapi + (fun i size -> + Printf.printf "Creating partition: %d" (i + 1); + let start_sector = (i + 1) * sector_size in + let num_sectors = (size + sector_size - 1) / sector_size in + match + Mbr.Partition.make ~active:false ~partition_type:1 + (Int32.of_int start_sector) + (Int32.of_int num_sectors) + with + | Ok partition -> + Printf.printf " - OK\n"; + partition + | Error msg -> failwith msg) + partition_sizes in - (* Mbr.make smart constructor checks for partition overlap, more than 1 active partitions and too many partitions *) let mbr = match Mbr.make partitions with | Ok mbr -> mbr | Error msg -> failwith ("Failed to create MBR: " ^ msg) - in - - let oc = open_out_gen [ Open_wronly; Open_binary; Open_creat; Open_trunc ] 0o644 destination in - seek_out oc (total_size - 1); (* Seek to the last byte of the file *) - output_byte oc 0; (* Write a single byte to extend the file size *) - close_out oc; + in let oc = open_out_bin destination in let mbr_buffer = Cstruct.create Mbr.sizeof in @@ -52,7 +48,10 @@ let create_mbr_disk destination partition_files = let destination = let doc = "Output file for the MBR formatted disk image" in - Arg.(required & opt (some string) None & info ["d"; "destination"] ~docv:"destination" ~doc) + Arg.( + required + & opt (some string) None + & info [ "d"; "destination" ] ~docv:"destination" ~doc) let partition_files = let doc = "Data files to be written to the partitions" in From 5d89da40868cd6049757dc3573a54ac08cce8a3d Mon Sep 17 00:00:00 2001 From: PizieDust Date: Thu, 1 Jun 2023 08:32:56 +0100 Subject: [PATCH 07/11] fmt linting --- bin/dune | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/bin/dune b/bin/dune index 6feb427..0766ab4 100644 --- a/bin/dune +++ b/bin/dune @@ -1,3 +1,8 @@ (executables - (names mbr_inspect read_partition write_partition resize_partition create_mbr_disk) + (names + mbr_inspect + read_partition + write_partition + resize_partition + create_mbr_disk) (libraries mbr cstruct cmdliner unix)) From 8fb035dbbf1c04ac63e7f4b8df68b4609927219a Mon Sep 17 00:00:00 2001 From: PizieDust Date: Thu, 1 Jun 2023 08:44:04 +0100 Subject: [PATCH 08/11] fail if more than 4 files (partitions) --- bin/create_mbr_disk.ml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bin/create_mbr_disk.ml b/bin/create_mbr_disk.ml index bc4d6aa..5cf38c0 100644 --- a/bin/create_mbr_disk.ml +++ b/bin/create_mbr_disk.ml @@ -3,7 +3,11 @@ open Cmdliner let create_mbr_disk destination partition_files = let sector_size = Mbr.sizeof in let num_partitions = List.length partition_files in - Printf.printf "Total partitions to create: %d\n" num_partitions; + if num_partitions > 4 then + failwith + "Too many partition files. Limit number of files to 4 as MBR supports at \ + most 4 partitions" + else Printf.printf "Total partitions to create: %d\n" num_partitions; let partition_sizes = List.map (fun file -> (Unix.stat file).Unix.st_size) partition_files From 6c64ff9b5d9c52fcb45936a334abb5681230261c Mon Sep 17 00:00:00 2001 From: PizieDust Date: Mon, 26 Jun 2023 08:51:59 +0100 Subject: [PATCH 09/11] replace exceptions with simple error messages --- bin/create_mbr_disk.ml | 88 ++++++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 42 deletions(-) diff --git a/bin/create_mbr_disk.ml b/bin/create_mbr_disk.ml index 5cf38c0..93f444d 100644 --- a/bin/create_mbr_disk.ml +++ b/bin/create_mbr_disk.ml @@ -3,52 +3,56 @@ open Cmdliner let create_mbr_disk destination partition_files = let sector_size = Mbr.sizeof in let num_partitions = List.length partition_files in - if num_partitions > 4 then - failwith + if num_partitions > 4 then ( + Printf.printf "Too many partition files. Limit number of files to 4 as MBR supports at \ - most 4 partitions" - else Printf.printf "Total partitions to create: %d\n" num_partitions; + most 4 partitions"; + exit 2) + else ( + Printf.printf "Total partitions to create: %d\n" num_partitions; + let partition_sizes = + List.map (fun file -> (Unix.stat file).Unix.st_size) partition_files + in - let partition_sizes = - List.map (fun file -> (Unix.stat file).Unix.st_size) partition_files - in + let partition_size = List.fold_left ( + ) 0 partition_sizes in + let mbr_size = Mbr.sizeof in + let total_size = partition_size + mbr_size in - let partition_size = List.fold_left ( + ) 0 partition_sizes in - let mbr_size = Mbr.sizeof in - let total_size = partition_size + mbr_size in + Printf.printf "Total disk size: %d bytes\n" total_size; - Printf.printf "Total disk size: %d bytes\n" total_size; - - let partitions = - List.mapi - (fun i size -> - Printf.printf "Creating partition: %d" (i + 1); - let start_sector = (i + 1) * sector_size in - let num_sectors = (size + sector_size - 1) / sector_size in - match - Mbr.Partition.make ~active:false ~partition_type:1 - (Int32.of_int start_sector) - (Int32.of_int num_sectors) - with - | Ok partition -> - Printf.printf " - OK\n"; - partition - | Error msg -> failwith msg) - partition_sizes - in - (* Mbr.make smart constructor checks for partition overlap, more than 1 active partitions and too many partitions *) - let mbr = - match Mbr.make partitions with - | Ok mbr -> mbr - | Error msg -> failwith ("Failed to create MBR: " ^ msg) - in - - let oc = open_out_bin destination in - let mbr_buffer = Cstruct.create Mbr.sizeof in - Mbr.marshal mbr_buffer mbr; - output oc (Cstruct.to_bytes mbr_buffer) 0 Mbr.sizeof; - close_out oc; - Unix.truncate destination total_size + let partitions = + List.mapi + (fun i size -> + Printf.printf "Creating partition: %d" (i + 1); + let start_sector = (i + 1) * sector_size in + let num_sectors = (size + sector_size - 1) / sector_size in + match + Mbr.Partition.make ~active:false ~partition_type:1 + (Int32.of_int start_sector) + (Int32.of_int num_sectors) + with + | Ok partition -> + Printf.printf " - OK\n"; + partition + | Error msg -> + Printf.printf "Failed to create MBR: %s" msg; + exit 1) + partition_sizes + in + (* Mbr.make smart constructor checks for partition overlap, more than 1 active partitions and too many partitions *) + let mbr = + match Mbr.make partitions with + | Ok mbr -> mbr + | Error msg -> + Printf.printf "Failed to create MBR: %s" msg; + exit 1 + in + let oc = open_out_bin destination in + let mbr_buffer = Cstruct.create Mbr.sizeof in + Mbr.marshal mbr_buffer mbr; + output oc (Cstruct.to_bytes mbr_buffer) 0 Mbr.sizeof; + close_out oc; + Unix.truncate destination total_size) let destination = let doc = "Output file for the MBR formatted disk image" in From 3b5444d1e87d418b7eefb85d45244183d0fce3cd Mon Sep 17 00:00:00 2001 From: PizieDust Date: Mon, 26 Jun 2023 08:53:50 +0100 Subject: [PATCH 10/11] use 6 as partition type --- bin/create_mbr_disk.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/create_mbr_disk.ml b/bin/create_mbr_disk.ml index 93f444d..99b7ce6 100644 --- a/bin/create_mbr_disk.ml +++ b/bin/create_mbr_disk.ml @@ -27,7 +27,7 @@ let create_mbr_disk destination partition_files = let start_sector = (i + 1) * sector_size in let num_sectors = (size + sector_size - 1) / sector_size in match - Mbr.Partition.make ~active:false ~partition_type:1 + Mbr.Partition.make ~active:false ~partition_type:6 (Int32.of_int start_sector) (Int32.of_int num_sectors) with From 9f88cdefbb7fb831f695d794cda579042c77dd15 Mon Sep 17 00:00:00 2001 From: PizieDust Date: Tue, 27 Jun 2023 06:31:47 +0100 Subject: [PATCH 11/11] error out if data size is not a mul of 512 --- bin/create_mbr_disk.ml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/bin/create_mbr_disk.ml b/bin/create_mbr_disk.ml index 99b7ce6..8f2a283 100644 --- a/bin/create_mbr_disk.ml +++ b/bin/create_mbr_disk.ml @@ -7,7 +7,7 @@ let create_mbr_disk destination partition_files = Printf.printf "Too many partition files. Limit number of files to 4 as MBR supports at \ most 4 partitions"; - exit 2) + exit 1) else ( Printf.printf "Total partitions to create: %d\n" num_partitions; let partition_sizes = @@ -18,12 +18,16 @@ let create_mbr_disk destination partition_files = let mbr_size = Mbr.sizeof in let total_size = partition_size + mbr_size in - Printf.printf "Total disk size: %d bytes\n" total_size; - let partitions = List.mapi (fun i size -> - Printf.printf "Creating partition: %d" (i + 1); + if size mod 512 <> 0 then ( + Printf.eprintf + "Partition %d will contain data that can't fill up the partiton. \ + The data should have a size which is a multiple of %d\n" + (i + 1) mbr_size; + exit 1) + else Printf.printf "Creating partition: %d" (i + 1); let start_sector = (i + 1) * sector_size in let num_sectors = (size + sector_size - 1) / sector_size in match @@ -39,6 +43,7 @@ let create_mbr_disk destination partition_files = exit 1) partition_sizes in + (* Mbr.make smart constructor checks for partition overlap, more than 1 active partitions and too many partitions *) let mbr = match Mbr.make partitions with