From 6a14a51e794aee558fcb232eb025f6cb0b1be351 Mon Sep 17 00:00:00 2001 From: rmsyn Date: Sat, 7 Jan 2023 14:17:21 -0700 Subject: [PATCH 1/3] remove try! calls Use the ? operator to replace try! calls --- src/lib.rs | 128 ++++++++++++++++++++++++++--------------------------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 2511800..2bcd0a9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -206,34 +206,34 @@ impl DeviceTree { // // version 17 fields // 36 size_dt_struct: u32, - if try!(buffer.read_be_u32(0)) != MAGIC_NUMBER { + if buffer.read_be_u32(0)? != MAGIC_NUMBER { return Err(DeviceTreeError::InvalidMagicNumber); } // check total size - if try!(buffer.read_be_u32(4)) as usize != buffer.len() { + if buffer.read_be_u32(4)? as usize != buffer.len() { return Err(DeviceTreeError::SizeMismatch); } // check version - let version = try!(buffer.read_be_u32(20)); + let version = buffer.read_be_u32(20)?; if version != SUPPORTED_VERSION { return Err(DeviceTreeError::VersionNotSupported); } - let off_dt_struct = try!(buffer.read_be_u32(8)) as usize; - let off_dt_strings = try!(buffer.read_be_u32(12)) as usize; - let off_mem_rsvmap = try!(buffer.read_be_u32(16)) as usize; - let boot_cpuid_phys = try!(buffer.read_be_u32(28)); + let off_dt_struct = buffer.read_be_u32(8)? as usize; + let off_dt_strings = buffer.read_be_u32(12)? as usize; + let off_mem_rsvmap = buffer.read_be_u32(16)? as usize; + let boot_cpuid_phys = buffer.read_be_u32(28)?; // load reserved memory list let mut reserved = Vec::new(); let mut pos = off_mem_rsvmap; loop { - let offset = try!(buffer.read_be_u64(pos)); + let offset = buffer.read_be_u64(pos)?; pos += 8; - let size = try!(buffer.read_be_u64(pos)); + let size = buffer.read_be_u64(pos)?; pos += 8; reserved.push((offset, size)); @@ -243,7 +243,7 @@ impl DeviceTree { } } - let (_, root) = try!(Node::load(buffer, off_dt_struct, off_dt_strings)); + let (_, root) = Node::load(buffer, off_dt_struct, off_dt_strings)?; Ok(DeviceTree { version: version, @@ -268,67 +268,67 @@ impl DeviceTree { // Magic let len = dtb.len(); - try!(dtb.write_be_u32(len, MAGIC_NUMBER)); + dtb.write_be_u32(len, MAGIC_NUMBER)?; let size_off = dtb.len(); - try!(dtb.write_be_u32(size_off, 0)); // Fill in size later + dtb.write_be_u32(size_off, 0)?; // Fill in size later let off_dt_struct = dtb.len(); - try!(dtb.write_be_u32(off_dt_struct, 0)); // Fill in off_dt_struct later + dtb.write_be_u32(off_dt_struct, 0)?; // Fill in off_dt_struct later let off_dt_strings = dtb.len(); - try!(dtb.write_be_u32(off_dt_strings, 0)); // Fill in off_dt_strings later + dtb.write_be_u32(off_dt_strings, 0)?; // Fill in off_dt_strings later let off_mem_rsvmap = dtb.len(); - try!(dtb.write_be_u32(off_mem_rsvmap, 0)); // Fill in off_mem_rsvmap later + dtb.write_be_u32(off_mem_rsvmap, 0)?; // Fill in off_mem_rsvmap later // Version let len = dtb.len(); - try!(dtb.write_be_u32(len, SUPPORTED_VERSION)); + dtb.write_be_u32(len, SUPPORTED_VERSION)?; // Last comp version let len = dtb.len(); - try!(dtb.write_be_u32(len, COMPAT_VERSION)); + dtb.write_be_u32(len, COMPAT_VERSION)?; // boot_cpuid_phys let len = dtb.len(); - try!(dtb.write_be_u32(len, self.boot_cpuid_phys)); + dtb.write_be_u32(len, self.boot_cpuid_phys)?; let off_size_strings = dtb.len(); - try!(dtb.write_be_u32(off_size_strings, 0)); // Fill in size_dt_strings later + dtb.write_be_u32(off_size_strings, 0)?; // Fill in size_dt_strings later let off_size_struct = dtb.len(); - try!(dtb.write_be_u32(off_size_struct, 0)); // Fill in size_dt_struct later + dtb.write_be_u32(off_size_struct, 0)?; // Fill in size_dt_struct later // Memory Reservation Block - try!(dtb.pad(8)); + dtb.pad(8)?; let len = dtb.len(); - try!(dtb.write_be_u32(off_mem_rsvmap, len as u32)); + dtb.write_be_u32(off_mem_rsvmap, len as u32)?; for reservation in self.reserved.iter() { // address let len = dtb.len(); - try!(dtb.write_be_u64(len, reservation.0)); + dtb.write_be_u64(len, reservation.0)?; // size let len = dtb.len(); - try!(dtb.write_be_u64(len, reservation.1)); + dtb.write_be_u64(len, reservation.1)?; } // Structure Block - try!(dtb.pad(4)); + dtb.pad(4)?; let structure_start = dtb.len(); - try!(dtb.write_be_u32(off_dt_struct, structure_start as u32)); - try!(self.root.store(&mut dtb, &mut strings)); + dtb.write_be_u32(off_dt_struct, structure_start as u32)?; + self.root.store(&mut dtb, &mut strings)?; - try!(dtb.pad(4)); + dtb.pad(4)?; let len = dtb.len(); - try!(dtb.write_be_u32(len, OF_DT_END)); + dtb.write_be_u32(len, OF_DT_END)?; let len = dtb.len(); - try!(dtb.write_be_u32(off_size_struct, (len - structure_start) as u32)); - try!(dtb.write_be_u32(off_size_strings, strings.buffer.len() as u32)); + dtb.write_be_u32(off_size_struct, (len - structure_start) as u32)?; + dtb.write_be_u32(off_size_strings, strings.buffer.len() as u32)?; // Strings Block - try!(dtb.pad(4)); + dtb.pad(4)?; let len = dtb.len(); - try!(dtb.write_be_u32(off_dt_strings, len as u32)); + dtb.write_be_u32(off_dt_strings, len as u32)?; dtb.extend_from_slice(&strings.buffer); let len = dtb.len(); - try!(dtb.write_be_u32(size_off, len as u32)); + dtb.write_be_u32(size_off, len as u32)?; Ok(dtb) } @@ -341,30 +341,30 @@ impl Node { off_dt_strings: usize, ) -> Result<(usize, Node), DeviceTreeError> { // check for DT_BEGIN_NODE - if try!(buffer.read_be_u32(start)) != OF_DT_BEGIN_NODE { + if buffer.read_be_u32(start)? != OF_DT_BEGIN_NODE { return Err(DeviceTreeError::ParseError(start)); } - let raw_name = try!(buffer.read_bstring0(start + 4)); + let raw_name = buffer.read_bstring0(start + 4)?; // read all the props let mut pos = align(start + 4 + raw_name.len() + 1, 4); let mut props = Vec::new(); - while try!(buffer.read_be_u32(pos)) == OF_DT_PROP { - let val_size = try!(buffer.read_be_u32(pos + 4)) as usize; - let name_offset = try!(buffer.read_be_u32(pos + 8)) as usize; + while buffer.read_be_u32(pos)? == OF_DT_PROP { + let val_size = buffer.read_be_u32(pos + 4)? as usize; + let name_offset = buffer.read_be_u32(pos + 8)? as usize; // get value slice let val_start = pos + 12; let val_end = val_start + val_size; - let val = try!(buffer.subslice(val_start, val_end)); + let val = buffer.subslice(val_start, val_end)?; // lookup name in strings table - let prop_name = try!(buffer.read_bstring0(off_dt_strings + name_offset)); + let prop_name = buffer.read_bstring0(off_dt_strings + name_offset)?; - props.push((try!(str::from_utf8(prop_name)).to_owned(), val.to_owned())); + props.push((str::from_utf8(prop_name)?.to_owned(), val.to_owned())); pos = align(val_end, 4); } @@ -372,14 +372,14 @@ impl Node { // finally, parse children let mut children = Vec::new(); - while try!(buffer.read_be_u32(pos)) == OF_DT_BEGIN_NODE { - let (new_pos, child_node) = try!(Node::load(buffer, pos, off_dt_strings)); + while buffer.read_be_u32(pos)? == OF_DT_BEGIN_NODE { + let (new_pos, child_node) = Node::load(buffer, pos, off_dt_strings)?; pos = new_pos; children.push(child_node); } - if try!(buffer.read_be_u32(pos)) != OF_DT_END_NODE { + if buffer.read_be_u32(pos)? != OF_DT_END_NODE { return Err(DeviceTreeError::ParseError(pos)); } @@ -388,7 +388,7 @@ impl Node { Ok(( pos, Node { - name: try!(str::from_utf8(raw_name)).to_owned(), + name: str::from_utf8(raw_name)?.to_owned(), props: props, children: children, }, @@ -431,14 +431,14 @@ impl Node { } pub fn prop_str<'a>(&'a self, name: &str) -> Result<&'a str, PropError> { - let raw = try!(self.prop_raw(name).ok_or(PropError::NotFound)); + let raw = self.prop_raw(name).ok_or(PropError::NotFound)?; let l = raw.len(); if l < 1 || raw[l - 1] != 0 { return Err(PropError::Missing0); } - Ok(try!(str::from_utf8(&raw[..(l - 1)]))) + Ok(str::from_utf8(&raw[..(l - 1)])?) } pub fn prop_raw<'a>(&'a self, name: &str) -> Option<&'a Vec> { @@ -451,15 +451,15 @@ impl Node { } pub fn prop_u64(&self, name: &str) -> Result { - let raw = try!(self.prop_raw(name).ok_or(PropError::NotFound)); + let raw = self.prop_raw(name).ok_or(PropError::NotFound)?; - Ok(try!(raw.as_slice().read_be_u64(0))) + Ok(raw.as_slice().read_be_u64(0)?) } pub fn prop_u32(&self, name: &str) -> Result { - let raw = try!(self.prop_raw(name).ok_or(PropError::NotFound)); + let raw = self.prop_raw(name).ok_or(PropError::NotFound)?; - Ok(try!(raw.as_slice().read_be_u32(0))) + Ok(raw.as_slice().read_be_u32(0)?) } pub fn store( @@ -467,25 +467,25 @@ impl Node { structure: &mut Vec, strings: &mut StringTable, ) -> Result<(), DeviceTreeError> { - try!(structure.pad(4)); + structure.pad(4)?; let len = structure.len(); - try!(structure.write_be_u32(len, OF_DT_BEGIN_NODE)); + structure.write_be_u32(len, OF_DT_BEGIN_NODE)?; - try!(structure.write_bstring0(&self.name)); + structure.write_bstring0(&self.name)?; for prop in self.props.iter() { - try!(structure.pad(4)); + structure.pad(4)?; let len = structure.len(); - try!(structure.write_be_u32(len, OF_DT_PROP)); + structure.write_be_u32(len, OF_DT_PROP)?; // Write property value length - try!(structure.pad(4)); + structure.pad(4)?; let len = structure.len(); - try!(structure.write_be_u32(len, prop.1.len() as u32)); + structure.write_be_u32(len, prop.1.len() as u32)?; // Write name offset - try!(structure.pad(4)); + structure.pad(4)?; let len = structure.len(); - try!(structure.write_be_u32(len, strings.add_string(&prop.0))); + structure.write_be_u32(len, strings.add_string(&prop.0))?; // Store the property value structure.extend_from_slice(&prop.1); @@ -493,12 +493,12 @@ impl Node { // Recurse on children for child in self.children.iter() { - try!(child.store(structure, strings)); + child.store(structure, strings)?; } - try!(structure.pad(4)); + structure.pad(4)?; let len = structure.len(); - try!(structure.write_be_u32(len, OF_DT_END_NODE)); + structure.write_be_u32(len, OF_DT_END_NODE)?; Ok(()) } } From 9277f192cfc2e17cdc0afc3669282d17d18ff1be Mon Sep 17 00:00:00 2001 From: rmsyn Date: Sat, 7 Jan 2023 14:08:07 -0700 Subject: [PATCH 2/3] convert to no_std crate Change uses of std data structures to equivalents from core, alloc, and hashbrown --- Cargo.toml | 3 +++ src/lib.rs | 45 +++++++++++---------------------------------- src/util.rs | 1 + tests/roundtrip.rs | 28 ++++++++++++++++++++++++++++ 4 files changed, 43 insertions(+), 34 deletions(-) create mode 100644 tests/roundtrip.rs diff --git a/Cargo.toml b/Cargo.toml index a3d4b23..2abe377 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,5 +7,8 @@ description = "Reads and parses Linux device tree images" repository = "https://github.com/mbr/device_tree-rs" documentation = "https://mbr.github.io/device_tree-rs/device_tree/" +[dependencies] +hashbrown = "0.13" + [features] string-dedup = [] # Requires std diff --git a/src/lib.rs b/src/lib.rs index 2bcd0a9..017b11c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,10 +18,11 @@ //! //! # Examples //! -//! ```ignore +//! ```rust +//! # use std::{fs, io::Read}; //! fn main() { //! // read file into memory -//! let mut input = fs::File::open("sample.dtb").unwrap(); +//! let mut input = fs::File::open("examples/bcm2709-rpi-2-b.dtb").unwrap(); //! let mut buf = Vec::new(); //! input.read_to_end(&mut buf).unwrap(); //! @@ -30,10 +31,14 @@ //! } //! ``` -extern crate core; +#![no_std] + +extern crate alloc; +extern crate hashbrown; pub mod util; +use alloc::{borrow::ToOwned, string::String, vec::Vec}; use core::str; use util::{align, SliceRead, SliceReadError, VecWrite, VecWriteError}; @@ -131,7 +136,7 @@ impl From for DeviceTreeError { #[cfg(feature = "string-dedup")] mod advancedstringtable { - use std::collections::HashMap; + use hashbrown::HashMap; pub struct StringTable { pub buffer: Vec, @@ -161,6 +166,8 @@ mod advancedstringtable { #[cfg(not(feature = "string-dedup"))] mod stringtable { + use alloc::vec::Vec; + pub struct StringTable { pub buffer: Vec, } @@ -514,33 +521,3 @@ impl From for PropError { PropError::SliceReadError(e) } } - -#[cfg(test)] -mod test { - use std::fs; - use std::io::{Read, Write}; - - use super::*; - - #[test] - fn roundtrip() { - // read file into memory - let buf = include_bytes!("../examples/bcm2709-rpi-2-b.dtb"); - let original_fdt = DeviceTree::load(buf).unwrap(); - - let dtb = original_fdt.store().unwrap(); - let mut output = fs::OpenOptions::new() - .write(true) - .create(true) - .open("output.dtb") - .unwrap(); - output.write_all(&dtb).unwrap(); - - let mut input = fs::File::open("output.dtb").unwrap(); - let mut buf = Vec::new(); - input.read_to_end(&mut buf).unwrap(); - let generated_fdt = DeviceTree::load(buf.as_slice()).unwrap(); - - assert!(original_fdt == generated_fdt); - } -} diff --git a/src/util.rs b/src/util.rs index b592d28..203876d 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,4 +1,5 @@ pub use core::{convert, fmt, option, result, str}; +use alloc::vec::Vec; #[inline] pub fn align(val: usize, to: usize) -> usize { diff --git a/tests/roundtrip.rs b/tests/roundtrip.rs new file mode 100644 index 0000000..765081f --- /dev/null +++ b/tests/roundtrip.rs @@ -0,0 +1,28 @@ +extern crate device_tree; + +use std::fs; +use std::io::{Read, Write}; + +use device_tree::*; + +#[test] +fn roundtrip() { + // read file into memory + let buf = include_bytes!("../examples/bcm2709-rpi-2-b.dtb"); + let original_fdt = DeviceTree::load(buf).unwrap(); + + let dtb = original_fdt.store().unwrap(); + let mut output = fs::OpenOptions::new() + .write(true) + .create(true) + .open("output.dtb") + .unwrap(); + output.write_all(&dtb).unwrap(); + + let mut input = fs::File::open("output.dtb").unwrap(); + let mut buf = Vec::new(); + input.read_to_end(&mut buf).unwrap(); + let generated_fdt = DeviceTree::load(buf.as_slice()).unwrap(); + + assert!(original_fdt == generated_fdt); +} From a41df372eb302c71eb5a6a033d10758551edfde4 Mon Sep 17 00:00:00 2001 From: rmsyn Date: Sat, 7 Jan 2023 14:19:32 -0700 Subject: [PATCH 3/3] cargo fmt --- src/util.rs | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/util.rs b/src/util.rs index 203876d..3d60500 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,5 +1,5 @@ -pub use core::{convert, fmt, option, result, str}; use alloc::vec::Vec; +pub use core::{convert, fmt, option, result, str}; #[inline] pub fn align(val: usize, to: usize) -> usize { @@ -27,10 +27,10 @@ impl<'a> SliceRead for &'a [u8] { return Err(SliceReadError::UnexpectedEndOfInput); } - Ok( - (self[pos] as u32) << 24 | (self[pos + 1] as u32) << 16 | (self[pos + 2] as u32) << 8 - | (self[pos + 3] as u32), - ) + Ok((self[pos] as u32) << 24 + | (self[pos + 1] as u32) << 16 + | (self[pos + 2] as u32) << 8 + | (self[pos + 3] as u32)) } fn read_be_u64(&self, pos: usize) -> SliceReadResult { @@ -39,12 +39,14 @@ impl<'a> SliceRead for &'a [u8] { return Err(SliceReadError::UnexpectedEndOfInput); } - Ok( - (self[pos] as u64) << 56 | (self[pos + 1] as u64) << 48 | (self[pos + 2] as u64) << 40 - | (self[pos + 3] as u64) << 32 | (self[pos + 4] as u64) << 24 - | (self[pos + 5] as u64) << 16 | (self[pos + 6] as u64) << 8 - | (self[pos + 7] as u64), - ) + Ok((self[pos] as u64) << 56 + | (self[pos + 1] as u64) << 48 + | (self[pos + 2] as u64) << 40 + | (self[pos + 3] as u64) << 32 + | (self[pos + 4] as u64) << 24 + | (self[pos + 5] as u64) << 16 + | (self[pos + 6] as u64) << 8 + | (self[pos + 7] as u64)) } fn read_bstring0(&self, pos: usize) -> SliceReadResult<&[u8]> {