diff --git a/lib/dune b/lib/dune index 46c94c2..df9a12b 100644 --- a/lib/dune +++ b/lib/dune @@ -1,4 +1,4 @@ (library (public_name solo5-elftool) (name solo5_elftool) - (libraries owee cstruct cachet fmt)) + (libraries owee cachet fmt)) diff --git a/lib/solo5_elftool.ml b/lib/solo5_elftool.ml index ed957f4..84fced3 100644 --- a/lib/solo5_elftool.ml +++ b/lib/solo5_elftool.ml @@ -70,43 +70,41 @@ let guard m b = if not b then Error (`Msg m) else Ok () let sizeof_mft_entry = 104 let mft_max_entries = 64l -let parse_mft_entry buf = +let parse_mft_entry s = (* invariant: Cstruct.length buf = sizeof_mft_entry *) - let name_raw = Cstruct.sub buf 0 68 in - let typ = Cstruct.LE.get_uint32 buf 68 in - let u = Cstruct.sub buf 72 16 in - let b = Cstruct.sub buf 88 8 in - let attached = Cstruct.get_uint8 buf 96 <> 0 in + let name_raw = String.sub s 0 68 in + let typ = String.get_int32_le s 68 in + let u = String.sub s 72 16 in + let b = String.sub s 88 8 in + let attached = String.get_uint8 s 96 <> 0 in let* name = - Cstruct.cut ~sep:(Cstruct.create 1) name_raw - |> Option.map (fun (name, _) -> Cstruct.to_string name) + String.index_opt name_raw '\000' + |> Option.map (fun idx -> String.sub name_raw 0 idx) |> Option.to_result ~none:(`Msg "unterminated device name") in - let* () = guard "non-zero mft_entry.u" (Cstruct.for_all ((=) '\000') u) in - let* () = guard "non-zero mft_entry.b" (Cstruct.for_all ((=) '\000') b) in + let* () = guard "non-zero mft_entry.u" (String.for_all ((=) '\000') u) in + let* () = guard "non-zero mft_entry.b" (String.for_all ((=) '\000') b) in let* () = guard "non-zero mft_entry.attached" (not attached) in let* typ = mft_type_of_int typ in match typ with | Reserved_first -> - let* () = guard "non-zero RESERVED_FIRST" (Cstruct.for_all ((=) '\000') name_raw) in + let* () = guard "non-zero RESERVED_FIRST" (String.for_all ((=) '\000') name_raw) in Ok `Reserved_first | Dev_block_basic -> Ok (`Dev_block_basic name) | Dev_net_basic -> Ok (`Dev_net_basic name) -let parse_mft buf = - let buf = Cstruct.of_string buf in +let parse_mft s = let* () = guard "manifest too small" - (Cstruct.length buf >= 4 + 8 + sizeof_mft_entry) + (String.length s >= 4 + 8 + sizeof_mft_entry) in (* Solo5 defines a struct mft1_note consisting of the ELF note header * followed by a struct mft for reading and writing the ELF note. The note * header is 20 bytes long, so to get 8-byte alignment the note header is * padded with 4 bytes. See {[solo5/mft_abi.h]}. *) - let buf = Cstruct.shift buf 4 in - let version = Cstruct.LE.get_uint32 buf 0 - and entries = Cstruct.LE.get_uint32 buf 4 + let version = String.get_int32_le s 4 + and entries = String.get_int32_le s 8 in let* () = guard "unsupported manifest version" (version = 1l) in let* () = guard "zero manifest entries" (Int32.unsigned_compare entries 0l > 0) in @@ -118,25 +116,25 @@ let parse_mft buf = * mft_max_entries, so this is safely equivalent to: * (Option.get (Int32.unsigned_to_int entries) *) let entries = Int32.to_int entries in - let buf = Cstruct.shift buf 8 in + let off = 12 in let* () = guard "unexpected note size" - (Cstruct.length buf = entries * sizeof_mft_entry) + (String.length s = entries * sizeof_mft_entry + 12) in let* () = - match parse_mft_entry (Cstruct.sub buf 0 sizeof_mft_entry) with + match parse_mft_entry (String.sub s off sizeof_mft_entry) with | Ok `Reserved_first -> Ok () | _ -> Error (`Msg "expected RESERVED_FIRST") in - let buf = Cstruct.shift buf sizeof_mft_entry in + let off = off + sizeof_mft_entry in let entries = Array.init (entries - 1) - (fun i -> Cstruct.sub buf (i * sizeof_mft_entry) sizeof_mft_entry) + (fun i -> String.sub s (off + i * sizeof_mft_entry) sizeof_mft_entry) in let* entries = Array.fold_left - (fun r buf -> + (fun r s -> let* acc = r in - let* mft_entry = parse_mft_entry buf in + let* mft_entry = parse_mft_entry s in match mft_entry with | `Dev_block_basic name -> Ok (Dev_block_basic name :: acc) | `Dev_net_basic name -> Ok (Dev_net_basic name :: acc) @@ -147,13 +145,12 @@ let parse_mft buf = in Ok { version = Int32.to_int version; entries } -let parse_abi buf = - let buf = Cstruct.of_string buf in - let* () = guard "abi manifest size mismatch" (Cstruct.length buf = 4 * 4) in - let target = Cstruct.LE.get_uint32 buf 0 in - let version = Cstruct.LE.get_uint32 buf 4 in - let reserved0 = Cstruct.LE.get_uint32 buf 8 in - let reserved1 = Cstruct.LE.get_uint32 buf 12 in +let parse_abi s = + let* () = guard "abi manifest size mismatch" (String.length s = 4 * 4) in + let target = String.get_int32_le s 0 in + let version = String.get_int32_le s 4 in + let reserved0 = String.get_int32_le s 8 in + let reserved1 = String.get_int32_le s 12 in let* target = abi_target_of_int target in let* () = guard "non-zero reserved0" (reserved0 = 0l) in let* () = guard "non-zero reserved1" (reserved1 = 0l) in diff --git a/solo5-elftool.opam b/solo5-elftool.opam index 1580103..a36e000 100644 --- a/solo5-elftool.opam +++ b/solo5-elftool.opam @@ -15,8 +15,7 @@ build: [ depends: [ "ocaml" {>= "4.08.0"} "dune" {>= "2.9"} - "owee" {>= "0.4"} - "cstruct" {>= "6.0.0"} + "cachet" "fmt" {>= "0.8.7"} "cmdliner" {>= "1.1.0"} ]