diff --git a/src/me.rs b/src/me.rs index 5873c3e..b9692aa 100644 --- a/src/me.rs +++ b/src/me.rs @@ -80,7 +80,7 @@ impl FPTArea { Gen2Partition::Dir(d) => Some(d.clone()), _ => None, }) - .collect::>(); + .collect::>>(); dirs.iter() .map(|d| (d.entry.name(), d.check_signature())) .collect() @@ -104,14 +104,14 @@ impl FPTArea { pub fn check_ftpr_presence(&self) -> Result<(), String> { match &self.partitions { Partitions::Gen2(parts) => { - if parts.iter().find(|p| p.entry().name() == FTPR).is_some() { + if parts.iter().any(|p| p.entry().name() == FTPR) { Ok(()) } else { Err("not found".into()) } } Partitions::Gen3(parts) => { - if parts.iter().find(|p| p.entry().name() == FTPR).is_some() { + if parts.iter().any(|p| p.entry().name() == FTPR) { Ok(()) } else { Err("not found".into()) @@ -190,10 +190,7 @@ impl FPTArea { println!("Recreate ME region from components"); } - let mut res = match self.partitions.to_vec() { - Ok(r) => r, - Err(e) => return Err(e), - }; + let mut res = self.partitions.to_vec()?; if debug { println!(" Minimum size: {:08x}", res.len()); } diff --git a/src/part/fpt.rs b/src/part/fpt.rs index 4263bc0..69357bd 100644 --- a/src/part/fpt.rs +++ b/src/part/fpt.rs @@ -24,9 +24,9 @@ use zerocopy::{AlignmentError, ConvertError, FromBytes, IntoBytes, Ref, SizeErro use zerocopy_derive::{FromBytes, Immutable, IntoBytes}; use crate::{ - part::part::{retain, ClearOptions}, - ver::Version, EMPTY, + part::part::{ClearOptions, retain}, + ver::Version, }; pub const FTPR: &str = "FTPR"; @@ -142,16 +142,13 @@ impl Display for FPTHeader { } } +type EntryConvertError<'a> = + ConvertError, SizeError<&'a [u8], [FPTEntry]>, Infallible>; + #[derive(Debug)] pub enum FptError<'a> { ParseHeaderError(SizeError<&'a [u8], FPTHeader>), - ParseEntryError( - ConvertError< - AlignmentError<&'a [u8], [FPTEntry]>, - SizeError<&'a [u8], [FPTEntry]>, - Infallible, - >, - ), + ParseEntryError(EntryConvertError<'a>), } #[derive(Serialize, Deserialize, Clone, Copy, Debug, Eq, PartialEq)] @@ -293,22 +290,20 @@ const POSSIBLE_OFFSET: usize = 16; fn determine_offset(data: &[u8]) -> Option { let m = &data[..FPT_MAGIC_BYTES.len()]; if m.eq(FPT_MAGIC_BYTES) { - return Some(0); + Some(0) } else { let m = &data[POSSIBLE_OFFSET..POSSIBLE_OFFSET + FPT_MAGIC_BYTES.len()]; if m.eq(FPT_MAGIC_BYTES) { - return Some(POSSIBLE_OFFSET); + Some(POSSIBLE_OFFSET) } else { - return None; + None } } } impl<'a> FPT { pub fn parse(data: &'a [u8]) -> Option>> { - let Some(offset) = determine_offset(data) else { - return None; - }; + let offset = determine_offset(data)?; // Save for checksum recalculation let pre_header = &data[..offset]; let d = &data[offset..]; @@ -353,7 +348,7 @@ impl<'a> FPT { /// Two's complement of the sum of the bytes pub fn header_checksum(&self) -> u8 { - let mut c = self.header.clone(); + let mut c = self.header; // Initial checksum field itself must be 0. c.checksum = 0; let d = [self.pre_header.as_bytes(), c.as_bytes()].concat(); @@ -373,12 +368,12 @@ impl<'a> FPT { let f = e.flags; retain(e.name(), options) && e.size() > 0 && f.kind() != PartitionKind::NVRAM }) - .map(|e| *e) + .copied() .collect(); self.header.entries = self.entries.len() as u32; // clear EFFS presence flag if applicable if (!options.parts_force_retention.contains(&EFFS.into()) - && options.parts_force_deletion.len() == 0) + && options.parts_force_deletion.is_empty()) || options.parts_force_deletion.contains(&EFFS.into()) { // TODO: define bitfield, parameterize via API diff --git a/src/part/gen2.rs b/src/part/gen2.rs index 9549b08..a45d815 100644 --- a/src/part/gen2.rs +++ b/src/part/gen2.rs @@ -21,16 +21,16 @@ pub struct DirPartition { impl DirPartition { pub fn check_signature(&self) -> Result<(), String> { if self.dir.manifest.verify() { - return Ok(()); + Ok(()) } else { - return Err("hash mismatch".into()); + Err("hash mismatch".into()) } } } #[derive(Serialize, Deserialize, Clone, Debug)] pub enum Gen2Partition { - Dir(DirPartition), + Dir(Box), Data(DataPartition), MalformedOrUnknown(UnknownOrMalformedPartition), } @@ -71,7 +71,8 @@ impl Gen2Partition { let o = entry.offset(); let data = data.to_vec(); if let Ok(dir) = Directory::new(&data, o) { - Gen2Partition::Dir(DirPartition { dir, entry, data }) + let p = DirPartition { dir, entry, data }; + Gen2Partition::Dir(Box::new(p)) } else { if debug { let n = entry.name(); @@ -90,9 +91,7 @@ impl Gen2Partition { // rebase Huffman chunks let offset_diff = old_offset - offset; println!("Adjust Huffman LUT, diff: {offset_diff:08x}"); - if let Err(e) = p.dir.rebase_huffman_chunks(offset_diff) { - return Err(e); - } + p.dir.rebase_huffman_chunks(offset_diff)?; if let Some((mod_offset, huffman_mod)) = p.dir.get_huffman_mod() { let o = mod_offset; let l = LUT_HEADER_SIZE; @@ -110,8 +109,7 @@ impl Gen2Partition { } pub fn parse(fpt: &FPT, data: &[u8], debug: bool) -> Vec { - let parts = fpt - .entries + fpt.entries .iter() .map(|e| { let offset = e.offset(); @@ -131,13 +129,12 @@ pub fn parse(fpt: &FPT, data: &[u8], debug: bool) -> Vec { Gen2Partition::parse(&data[offset..end], *e, debug) } }) - .collect(); - parts + .collect() } -pub fn clean(parts: &Vec, options: &ClearOptions) -> Vec { +pub fn clean(parts: &[Gen2Partition], options: &ClearOptions) -> Vec { use log::info; - let res = parts + parts .iter() .filter(|p| { let e = p.entry(); @@ -158,16 +155,12 @@ pub fn clean(parts: &Vec, options: &ClearOptions) -> Vec { - dir_clean(&dir.dir, &retention_list, &mut cleaned); - } - _ => {} - }; + if let Gen2Partition::Dir(dir) = &p { + dir_clean(&dir.dir, &retention_list, &mut cleaned); + } p.set_data(cleaned); } p }) - .collect(); - res + .collect() } diff --git a/src/part/gen3.rs b/src/part/gen3.rs index 9ccae5c..99394e7 100644 --- a/src/part/gen3.rs +++ b/src/part/gen3.rs @@ -23,9 +23,9 @@ impl CPDPartition { pub fn check_signature(&self) -> Result<(), String> { if let Ok(m) = &self.cpd.manifest { if m.verify() { - return Ok(()); + Ok(()) } else { - return Err("hash mismatch".into()); + Err("hash mismatch".into()) } } else { Err("no manifest found".into()) @@ -139,8 +139,7 @@ impl Gen3Partition { } pub fn parse(fpt: &FPT, data: &[u8], debug: bool) -> Vec { - let parts = fpt - .entries + fpt.entries .iter() .map(|e| { let offset = e.offset(); @@ -160,11 +159,10 @@ pub fn parse(fpt: &FPT, data: &[u8], debug: bool) -> Vec { Gen3Partition::parse(&data[offset..end], *e, debug) } }) - .collect(); - parts + .collect() } -pub fn clean(parts: &Vec, options: &ClearOptions) -> Vec { +pub fn clean(parts: &[Gen3Partition], options: &ClearOptions) -> Vec { use log::info; // Step 1: Reduce down to the partitions to be kept, i.e., non-removable // ones. @@ -181,7 +179,7 @@ pub fn clean(parts: &Vec, options: &ClearOptions) -> Vec>(); if options.keep_modules { return reduced; @@ -193,12 +191,9 @@ pub fn clean(parts: &Vec, options: &ClearOptions) -> Vec { - dir_clean(&dir.cpd, &retention_list, &mut cleaned); - } - _ => {} - }; + if let Gen3Partition::Dir(dir) = &p { + dir_clean(&dir.cpd, &retention_list, &mut cleaned); + } p.set_data(cleaned); } // Step 3: Profit. diff --git a/src/part/part.rs b/src/part/part.rs index 65f4f81..8c8d5c8 100644 --- a/src/part/part.rs +++ b/src/part/part.rs @@ -72,14 +72,14 @@ pub struct ClearOptions { pub fn retain(part_name: String, options: &ClearOptions) -> bool { part_name == FTPR || options.parts_force_retention.contains(&part_name) - || (options.parts_force_deletion.len() > 0 + || (!options.parts_force_deletion.is_empty() && !options.parts_force_deletion.contains(&part_name)) } /// Clear out removable ranges in the FTPR directory -pub fn dir_clean(dir: &dyn Removables, retention_list: &Vec, data: &mut Vec) { +pub fn dir_clean(dir: &dyn Removables, retention_list: &[String], data: &mut [u8]) { use log::info; - for r in dir.removables(&retention_list) { + for r in dir.removables(retention_list) { let offset = r.start; let size = r.end - r.start; info!("Freeing {size:8} bytes @ {offset:08x}"); diff --git a/src/part/partitions.rs b/src/part/partitions.rs index b20d8d4..84c4c10 100644 --- a/src/part/partitions.rs +++ b/src/part/partitions.rs @@ -29,9 +29,9 @@ impl<'a> IntoIterator for &'a Partitions { fn into_iter(self) -> Self::IntoIter { match *self { - Partitions::Gen2(ref s) => Box::new(s.into_iter().map(|x| x as &dyn Partition)), - Partitions::Gen3(ref s) => Box::new(s.into_iter().map(|x| x as &dyn Partition)), - Partitions::Unknown(ref s) => Box::new(s.into_iter().map(|x| x as &dyn Partition)), + Partitions::Gen2(ref s) => Box::new(s.iter().map(|x| x as &dyn Partition)), + Partitions::Gen3(ref s) => Box::new(s.iter().map(|x| x as &dyn Partition)), + Partitions::Unknown(ref s) => Box::new(s.iter().map(|x| x as &dyn Partition)), } } } @@ -53,24 +53,19 @@ impl Partitions { // the 2nd or 3rd ME generation by looking at the directories themselves. // The heuristic may fail though, so we expose the ME generation // at a higher level instead where we add more detection features. - let is_gen3 = entries - .iter() - .find(|e| { - let o = e.offset(); - let l = o + CPD_MAGIC_BYTES.len(); - l < data.len() && data[o..l].eq(CPD_MAGIC_BYTES) - }) - .is_some(); + let is_gen3 = entries.iter().any(|e| { + let o = e.offset(); + let l = o + CPD_MAGIC_BYTES.len(); + l < data.len() && data[o..l].eq(CPD_MAGIC_BYTES) + }); - let partitions = if is_gen3 { + if is_gen3 { let parts = gen3::parse(fpt, data, debug); Partitions::Gen3(parts) } else { let parts = gen2::parse(fpt, data, debug); Partitions::Gen2(parts) - }; - - partitions + } } pub fn get_me_version(&self) -> Option { @@ -122,15 +117,15 @@ impl Partitions { pub fn clear(&mut self, options: &ClearOptions) { let parts = match &self { Partitions::Gen2(parts) => { - let res = gen2::clean(&parts, options); + let res = gen2::clean(parts, options); Partitions::Gen2(res) } Partitions::Gen3(parts) => { - let res = gen3::clean(&parts, options); + let res = gen3::clean(parts, options); Partitions::Gen3(res) } Partitions::Unknown(p) => { - let res = p.iter().map(|p| p.clone()).collect(); + let res = p.to_vec(); Partitions::Unknown(res) } }; @@ -162,19 +157,19 @@ impl Partitions { *self = match self { Partitions::Gen2(parts) => { let p = parts.iter_mut().find(|p| p.entry().name() == part_name); - if let Some(p) = p { - if let Err(e) = p.relocate(offset) { - return Err(format!("Cannot relocate partition: {e}")); - } + if let Some(p) = p + && let Err(e) = p.relocate(offset) + { + return Err(format!("Cannot relocate partition: {e}")); } Partitions::Gen2(parts.to_vec()) } Partitions::Gen3(parts) => { let p = parts.iter_mut().find(|p| p.entry().name() == part_name); - if let Some(p) = p { - if let Err(e) = p.relocate(offset) { - return Err(format!("Cannot relocate partition: {e}")); - } + if let Some(p) = p + && let Err(e) = p.relocate(offset) + { + return Err(format!("Cannot relocate partition: {e}")); } Partitions::Gen3(parts.to_vec()) } @@ -193,23 +188,20 @@ impl Partitions { let sorted_parts = &self.get_sorted(); // NOTE: We need to filter out NVRAM partitions, which have an offset of // 0xffff_ffff. - if let Some(last) = &sorted_parts + sorted_parts .into_iter() .filter(|p| { let f = p.entry().flags; f.kind() != PartitionKind::NVRAM }) .last() - { - Some(last.entry().clone()) - } else { - None - } + .as_ref() + .map(|last| *last.entry()) } pub fn to_vec(&self) -> Result, String> { use log::debug; - fn copy_parts(parts: &Vec<&dyn Partition>, data: &mut Vec) { + fn copy_parts(parts: &Vec<&dyn Partition>, data: &mut [u8]) { for p in parts { let e = p.entry(); let offset = p.entry().offset();