#![doc = include_str!("../README.md")]
use log::{info, warn};
use serde::{Deserialize, Serialize};
pub mod dir;
pub mod fit;
pub mod ifd;
pub mod me;
pub mod meta;
pub mod part;
pub mod ver;
use fit::{Fit, FitError};
use ifd::{IFD, IfdError};
use me::ME;
pub const EMPTY: u8 = 0xff;
pub trait Removables {
fn removables(&self, retention_list: &[String]) -> Vec<core::ops::Range<usize>>;
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Firmware {
pub ifd: Result<IFD, IfdError>,
pub me: Option<Result<ME, String>>,
pub fit: Result<Fit, FitError>,
}
impl Firmware {
pub fn parse(data: &[u8], debug: bool) -> Self {
let ifd = IFD::parse(data);
let me = match &ifd {
Ok(ifd) => {
let me_region = ifd.regions.me_range();
let b = me_region.start;
info!("ME region start @ {b:08x}");
ME::parse(&data[me_region], b, debug)
}
Err(e) => {
warn!("Not a full image: {e:?}");
ME::parse(data, 0, debug)
}
};
let fit = Fit::new(data);
Self { ifd, me, fit }
}
pub fn scan(data: &[u8], debug: bool) -> Self {
let ifd = IFD::parse(data);
let me = ME::scan(data, debug);
let fit = Fit::new(data);
Self { ifd, me, fit }
}
}
pub(crate) fn dump48(data: &[u8]) {
println!("Here are 48 bytes:");
println!(" {:02x?}", &data[0x00..0x10]);
println!(" {:02x?}", &data[0x10..0x20]);
println!(" {:02x?}", &data[0x20..0x30]);
}