diff --git a/Cargo.lock b/Cargo.lock index 879631bf9b..f0f2b70b01 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5229,6 +5229,7 @@ dependencies = [ "fnv", "gnarle", "goblin", + "hex", "hubtools", "indexmap", "lpc55_sign", diff --git a/app/gemini-bu/app.toml b/app/gemini-bu/app.toml index ea285befad..3da601a27f 100644 --- a/app/gemini-bu/app.toml +++ b/app/gemini-bu/app.toml @@ -3,6 +3,7 @@ target = "thumbv7em-none-eabihf" board = "gemini-bu-1" chip = "../../chips/stm32h7" stacksize = 896 +fwid = true [kernel] name = "gemini-bu" diff --git a/app/gimlet/base.toml b/app/gimlet/base.toml index d1c465831f..ab4c804429 100644 --- a/app/gimlet/base.toml +++ b/app/gimlet/base.toml @@ -2,6 +2,7 @@ target = "thumbv7em-none-eabihf" chip = "../../chips/stm32h7" memory = "memory-large.toml" stacksize = 896 +fwid = true [kernel] name = "gimlet" diff --git a/app/gimletlet/app-meanwell.toml b/app/gimletlet/app-meanwell.toml index 847928c8ba..89d8e6e038 100644 --- a/app/gimletlet/app-meanwell.toml +++ b/app/gimletlet/app-meanwell.toml @@ -3,6 +3,7 @@ target = "thumbv7em-none-eabihf" board = "gimletlet-2" chip = "../../chips/stm32h7" stacksize = 896 +fwid = true [kernel] name = "gimletlet" diff --git a/app/gimletlet/app-mgmt.toml b/app/gimletlet/app-mgmt.toml index b96cb00a6f..767e9b929b 100644 --- a/app/gimletlet/app-mgmt.toml +++ b/app/gimletlet/app-mgmt.toml @@ -3,6 +3,7 @@ target = "thumbv7em-none-eabihf" board = "gimletlet-1" chip = "../../chips/stm32h7" stacksize = 1024 +fwid = true [kernel] name = "gimletlet" diff --git a/app/gimletlet/app-sidecar-emulator.toml b/app/gimletlet/app-sidecar-emulator.toml index a652e4839b..74a3e5e6a7 100644 --- a/app/gimletlet/app-sidecar-emulator.toml +++ b/app/gimletlet/app-sidecar-emulator.toml @@ -4,6 +4,7 @@ board = "gimletlet-2" chip = "../../chips/stm32h7" memory = "memory-large.toml" stacksize = 896 +fwid = true [kernel] name = "gimletlet" diff --git a/app/gimletlet/app.toml b/app/gimletlet/app.toml index 7b6cc43e26..de2a375fde 100644 --- a/app/gimletlet/app.toml +++ b/app/gimletlet/app.toml @@ -6,6 +6,7 @@ memory = "memory-large.toml" stacksize = 896 epoch = 0 version = 0 +fwid = true [kernel] name = "gimletlet" diff --git a/app/psc/base.toml b/app/psc/base.toml index ebfe9a7f75..b7cac934ba 100644 --- a/app/psc/base.toml +++ b/app/psc/base.toml @@ -2,6 +2,7 @@ target = "thumbv7em-none-eabihf" chip = "../../chips/stm32h7" memory = "memory-large.toml" stacksize = 896 +fwid = true [kernel] name = "psc" diff --git a/app/sidecar/base.toml b/app/sidecar/base.toml index a40684da97..6580a16f7e 100644 --- a/app/sidecar/base.toml +++ b/app/sidecar/base.toml @@ -2,6 +2,7 @@ target = "thumbv7em-none-eabihf" chip = "../../chips/stm32h7" stacksize = 896 memory = "memory-large.toml" +fwid = true [kernel] name = "sidecar" diff --git a/build/xtask/Cargo.toml b/build/xtask/Cargo.toml index bf51f1c2e3..a1ddde639c 100644 --- a/build/xtask/Cargo.toml +++ b/build/xtask/Cargo.toml @@ -21,6 +21,7 @@ dunce = { workspace = true } filetime = { workspace = true } fnv = { workspace = true } goblin = { workspace = true } +hex = "0.4" hubtools = { workspace = true } indexmap = { workspace = true } multimap = { workspace = true } diff --git a/build/xtask/src/config.rs b/build/xtask/src/config.rs index acaae2eba7..763c5d3a4c 100644 --- a/build/xtask/src/config.rs +++ b/build/xtask/src/config.rs @@ -27,6 +27,8 @@ struct RawConfig { epoch: u32, #[serde(default)] version: u32, + #[serde(default)] + fwid: bool, memory: Option, #[serde(default)] image_names: Vec, @@ -52,6 +54,7 @@ pub struct Config { pub chip: String, pub epoch: u32, pub version: u32, + pub fwid: bool, pub image_names: Vec, pub external_images: Vec, pub signing: Option, @@ -177,6 +180,7 @@ impl Config { chip: toml.chip, epoch: toml.epoch, version: toml.version, + fwid: toml.fwid, signing: toml.signing, stacksize: toml.stacksize, kernel: toml.kernel, diff --git a/build/xtask/src/dist.rs b/build/xtask/src/dist.rs index 0dcf4cd78f..9a8ea4b9e3 100644 --- a/build/xtask/src/dist.rs +++ b/build/xtask/src/dist.rs @@ -3,6 +3,7 @@ // file, You can obtain one at https://mozilla.org/MPL/2.0/. use std::collections::{BTreeMap, BTreeSet, HashMap, VecDeque}; +use std::ffi::OsStr; use std::fmt::Write as _; use std::fs::{self, File}; use std::hash::{Hash, Hasher}; @@ -16,6 +17,7 @@ use atty::Stream; use indexmap::IndexMap; use multimap::MultiMap; use path_slash::{PathBufExt, PathExt}; +use sha3::{Digest, Sha3_256}; use zerocopy::AsBytes; use crate::{ @@ -535,6 +537,10 @@ pub fn package( archive.overwrite()?; } + if cfg.toml.fwid { + write_fwid(&cfg, &image_name, &flash, &archive_name)?; + } + // Unzip the signed + caboose'd images into our build directory let archive = hubtools::RawHubrisArchive::load(&archive_name) .context("loading archive with hubtools")?; @@ -549,6 +555,54 @@ pub fn package( Ok(allocated) } +// generate file with hash of expected flash contents +fn write_fwid( + cfg: &PackageConfig, + image_name: &String, + flash: &Range, + archive_name: &PathBuf, +) -> Result<()> { + let mut archive = hubtools::RawHubrisArchive::load(archive_name) + .context("loading archive with hubtools")?; + + let bin = archive + .extract_file("img/final.bin") + .context("extracting final.bin after signing & caboosing")?; + + let chip_name = Path::new(&cfg.toml.chip); + + // determine FWID calculation method from chip (directory) name + let pad = match chip_name.file_name().and_then(OsStr::to_str) { + Some("stm32h7") => { + // all unprogrammed flash is read as 0xff + Some(vec![ + 0xff_u8; + flash.end as usize - flash.start as usize - bin.len() + ]) + } + Some(_) => bail!("unexpected chip name, cannot calculate fwid"), + None => bail!("Failed to get file name of {}", chip_name.display()), + }; + + let mut sha = Sha3_256::new(); + sha.update(&bin); + + if let Some(pad) = pad { + sha.update(&pad); + } + + let digest = sha.finalize(); + + let mut file = File::create(&cfg.img_file("final.fwid", image_name))?; + let fwid = hex::encode(&digest); + writeln!(file, "{}", fwid)?; + + archive.add_file("img/final.fwid", fwid.as_bytes())?; + archive.overwrite()?; + + Ok(()) +} + fn write_gdb_script(cfg: &PackageConfig, image_name: &str) -> Result<()> { // Humility doesn't know about images right now. The gdb symbol file // paths all assume a flat layout with everything in dist. For now,