Skip to content

Commit 8e4612a

Browse files
authored
Make manifest fields non-optional (#658)
Now that #657 makes it impossible to construct a partially-initialized `HubrisArchive`, there are many fields which are guaranteed to be `Some(..)`. This PR makes them non-optional, then fixes downstream users.
1 parent d89e5cc commit 8e4612a

10 files changed

Lines changed: 83 additions & 122 deletions

File tree

cmd/discover/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ fn discover_run(context: &mut ExecutionContext) -> Result<()> {
315315
let subargs = DiscoverArgs::try_parse_from(&context.cli.cmd)?;
316316
let hubris = &context.cli.try_archive()?;
317317

318-
let image_id = hubris.as_ref().and_then(|h| h.image_id());
318+
let image_id = hubris.as_ref().map(|h| h.image_id());
319319
if image_id.is_none() {
320320
humility::warn!("no archive provided; not checking for compatibility");
321321
}

cmd/dump/src/lib.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
//! ```
6666
//!
6767
68-
use anyhow::{Result, anyhow, bail};
68+
use anyhow::{Result, bail};
6969
use clap::{ArgGroup, CommandFactory, Parser};
7070
use humility::core::Core;
7171
use humility::hubris::*;
@@ -325,11 +325,7 @@ fn get_dump_agent<'a>(
325325
{
326326
humility::msg!("using UDP dump agent");
327327

328-
let imageid = &hubris
329-
.imageid
330-
.as_ref()
331-
.ok_or_else(|| anyhow!("missing image ID"))?
332-
.1;
328+
let imageid = hubris.image_id();
333329

334330
Ok(Box::new(UdpDumpAgent::new(core, imageid)?))
335331
} else {

cmd/host/src/lib.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -334,15 +334,11 @@ fn print_panic(d: Vec<u8>) -> Result<()> {
334334

335335
/// Print a warning message if the archive is not for a `cosmo` board
336336
fn check_post_code_target(hubris: &HubrisArchive) {
337-
if !hubris.manifest.board.as_ref().is_some_and(|b| b.contains("cosmo")) {
337+
if !hubris.manifest.board.contains("cosmo") {
338338
humility::warn!(
339-
"POST code buffer is only present on 'cosmo' hardware{}; \
340-
hiffy may fail and time out",
341-
if let Some(board) = &hubris.manifest.board {
342-
format!(" but this is a '{board}'")
343-
} else {
344-
String::new()
345-
}
339+
"POST code buffer is only present on 'cosmo' hardware \
340+
but this is a '{}'; hiffy may fail and time out",
341+
hubris.manifest.board,
346342
)
347343
}
348344
}

cmd/hydrate/src/lib.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
//! By default, this writes to `hubris.core.TASK_NAME.N` (where `N` is the
1818
//! lowest available value); use `--out` to specify a different path name.
1919
20-
use anyhow::{Context, Result, anyhow, bail};
20+
use anyhow::{Context, Result, bail};
2121
use clap::{ArgGroup, CommandFactory, Parser};
2222
use humility::hubris::HubrisFlashMap;
2323
use humility_arch_arm::ARMRegister;
@@ -173,9 +173,7 @@ fn run(context: &mut ExecutionContext) -> Result<()> {
173173

174174
// compare archive ID
175175
let archive = &context.cli.archive()?;
176-
let expected_id = archive
177-
.image_id()
178-
.ok_or_else(|| anyhow!("missing image ID in archive"))?;
176+
let expected_id = archive.image_id();
179177
if archive_id != expected_id {
180178
bail!(
181179
"image ID mismatch: archive ID is {expected_id:02x?}, \

cmd/manifest/src/lib.rs

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -74,24 +74,15 @@ fn manifestcmd(context: &mut ExecutionContext) -> Result<()> {
7474

7575
let size = |task| hubris.lookup_module(task).unwrap().memsize;
7676

77-
print("version", manifest.version.as_deref().unwrap_or("<unknown>"));
77+
print("version", manifest.version.as_str());
7878
print("git rev", manifest.gitrev.as_deref().unwrap_or("<unknown>"));
7979

80-
println!(
81-
"{:>12} => {}",
82-
"image id",
83-
match &hubris.imageid {
84-
Some(s) => {
85-
format!("{:x?}", s.1)
86-
}
87-
None => "<none>".to_string(),
88-
},
89-
);
90-
91-
print("board", manifest.board.as_deref().unwrap_or("<unknown>"));
92-
print("name", manifest.name.as_deref().unwrap_or("<unknown>"));
80+
println!("{:>12} => {:x?}", "image id", hubris.image_id());
81+
82+
print("board", manifest.board.as_str());
83+
print("name", manifest.name.as_str());
9384
print("image", manifest.image.as_deref().unwrap_or("<unknown>"));
94-
print("target", manifest.target.as_deref().unwrap_or("<unknown>"));
85+
print("target", manifest.target.as_str());
9586
print("features", &manifest.features.join(", "));
9687

9788
let ttl = hubris.modules().fold(0, |ttl, m| ttl + m.memsize);

cmd/spd/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -372,10 +372,10 @@ fn dump_ddr4_over_i2c(
372372
subargs: &SpdArgs,
373373
) -> Result<()> {
374374
// Warn the user that we probably can't talk to DDR4s on non-Gimlet hardware
375-
if !hubris.manifest.target.as_ref().is_some_and(|t| t.contains("gimlet")) {
375+
if !hubris.manifest.target.contains("gimlet") {
376376
humility::warn!(
377377
"trying to talk to DDR4 SPDs on an invalid target `{}`",
378-
hubris.manifest.target.as_deref().unwrap_or("<unknown>")
378+
hubris.manifest.target,
379379
);
380380
};
381381

humility-core/src/hubris.rs

Lines changed: 60 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,13 @@ const MAX_HUBRIS_VERSION: u32 = 11;
4242

4343
#[derive(Debug, Serialize)]
4444
pub struct HubrisManifest {
45-
pub version: Option<String>,
45+
pub version: String,
4646
pub gitrev: Option<String>,
4747
pub features: Vec<String>,
48-
pub board: Option<String>,
48+
pub board: String,
4949
pub image: Option<String>,
50-
pub name: Option<String>,
51-
pub target: Option<String>,
50+
pub name: String,
51+
pub target: String,
5252
pub task_features: HashMap<String, Vec<String>>,
5353
pub task_irqs: HashMap<String, Vec<(u32, u32)>>,
5454
pub task_notifications: HashMap<String, Vec<String>>,
@@ -73,9 +73,9 @@ impl HubrisManifest {
7373
config: &HubrisConfig,
7474
rev: HubrisManifestRev,
7575
) -> Result<Self> {
76-
let board = Some(config.board.clone());
77-
let name = Some(config.name.clone());
78-
let target = Some(config.target.clone());
76+
let board = config.board.clone();
77+
let name = config.name.clone();
78+
let target = config.target.clone();
7979
let features = match config.kernel.features {
8080
Some(ref features) => features.clone(),
8181
None => vec![],
@@ -537,9 +537,8 @@ impl<'a> IntoIterator for &'a HubrisI2cBusList {
537537
}
538538

539539
/// Portions of the [`HubrisManifest`] that are loaded from archive files
540-
#[derive(Default)]
541540
pub struct HubrisManifestRev {
542-
pub version: Option<String>,
541+
pub version: String,
543542
pub gitrev: Option<String>,
544543
pub image: Option<String>,
545544
}
@@ -1156,7 +1155,7 @@ pub struct HubrisArchive {
11561155
pub manifest: HubrisManifest,
11571156

11581157
// image ID
1159-
pub imageid: Option<(u32, Vec<u8>)>,
1158+
imageid: (u32, Vec<u8>),
11601159

11611160
// loaded regions
11621161
loaded: BTreeMap<u32, HubrisRegion>,
@@ -1353,19 +1352,23 @@ impl HubrisArchive {
13531352
}
13541353

13551354
// First, we'll load aspects of configuration.
1356-
let mut manifest_rev = HubrisManifestRev::default();
1357-
if let Ok(git_rev) = hubris.extract_file("git-rev") {
1358-
manifest_rev.gitrev =
1359-
Some(std::str::from_utf8(&git_rev)?.to_string());
1360-
}
1355+
let gitrev = if let Ok(git_rev) = hubris.extract_file("git-rev") {
1356+
Some(std::str::from_utf8(&git_rev)?.to_string())
1357+
} else {
1358+
None
1359+
};
13611360

1362-
if let Ok(image_name) = hubris.extract_file("image-name") {
1363-
manifest_rev.image =
1364-
Some(std::str::from_utf8(&image_name)?.to_string());
1365-
}
1361+
let image = if let Ok(image_name) = hubris.extract_file("image-name") {
1362+
Some(std::str::from_utf8(&image_name)?.to_string())
1363+
} else {
1364+
None
1365+
};
13661366

1367-
manifest_rev.version =
1368-
Some(format!("hubris build archive v{}", archive_version));
1367+
let manifest_rev = HubrisManifestRev {
1368+
version: format!("hubris build archive v{archive_version}"),
1369+
gitrev,
1370+
image,
1371+
};
13691372

13701373
// Load the main manifest config file
13711374
let app = hubris.extract_file("app.toml")?;
@@ -1424,7 +1427,7 @@ impl HubrisArchive {
14241427
// forward slash: regardless of platform, paths within a ZIP archive
14251428
// use the forward slash as a separator.
14261429
//
1427-
let mut loader = HubrisObjectLoader::new(0)?;
1430+
let mut loader = HubrisObjectLoader::new(0);
14281431
loader.load_object(
14291432
"kernel",
14301433
HubrisTask::Kernel,
@@ -1481,7 +1484,7 @@ impl HubrisArchive {
14811484
.into_par_iter()
14821485
.map(|(id, name, buf)| {
14831486
let id: u32 = id.try_into().unwrap();
1484-
let mut loader = HubrisObjectLoader::new(id + 1)?;
1487+
let mut loader = HubrisObjectLoader::new(id + 1);
14851488
loader.load_object(&name, HubrisTask::Task(id), &buf)?;
14861489
Ok(loader)
14871490
})
@@ -1533,9 +1536,12 @@ impl HubrisArchive {
15331536
loader.structs_byname.insert(name.clone(), *goff);
15341537
}
15351538

1539+
let Some(imageid) = loader.imageid else {
1540+
bail!("missing image id");
1541+
};
15361542
Ok(Self {
15371543
hubris_archive: hubris,
1538-
imageid: loader.imageid,
1544+
imageid,
15391545
manifest,
15401546
loaded: loader.loaded,
15411547
task_dump,
@@ -1609,11 +1615,6 @@ impl HubrisArchive {
16091615
flash.chip
16101616
}
16111617

1612-
/// Destroys the `HubrisArchive`, returning the raw archive data
1613-
pub fn take_raw_archive(self) -> Vec<u8> {
1614-
self.hubris_archive.zip
1615-
}
1616-
16171618
/// Helper function to load a dump into a [`RawHubrisArchive`]
16181619
///
16191620
/// Returns a tuple of `(raw archive, dump task)`; the second field is
@@ -1683,10 +1684,6 @@ impl HubrisArchive {
16831684
Ok((archive, task_dump))
16841685
}
16851686

1686-
pub fn loaded(&self) -> bool {
1687-
!self.modules.is_empty()
1688-
}
1689-
16901687
///
16911688
/// Takes a list of potentially similar types and deduplicates the list.
16921689
///
@@ -2094,42 +2091,30 @@ impl HubrisArchive {
20942091
return Ok(());
20952092
}
20962093

2097-
//
20982094
// To validate that what we're running on the target matches what
20992095
// we have in the archive, we are going to check the image ID, an
2100-
// identifer created for this purpose. If we don't have an image ID,
2101-
// we check the legacy mechanism of the .hubris_app_table; if we
2102-
// don't have either of these, we don't have a way of validating the
2103-
// archive and we fail.
2104-
//
2105-
if let Some(imageid) = &self.imageid {
2106-
let addr = imageid.0;
2107-
let nbytes = imageid.1.len();
2108-
assert!(nbytes > 0);
2109-
2110-
let mut id = vec![0; nbytes];
2111-
core.read_8(addr, &mut id[0..nbytes]).with_context(|| {
2112-
format!(
2113-
"failed to read image ID at 0x{:x}; board mismatch?",
2114-
addr
2115-
)
2116-
})?;
2096+
// identifer created for this purpose.
2097+
let addr = self.imageid.0;
2098+
let nbytes = self.imageid.1.len();
2099+
assert!(nbytes > 0);
2100+
2101+
let mut id = vec![0; nbytes];
2102+
core.read_8(addr, &mut id[0..nbytes]).with_context(|| {
2103+
format!("failed to read image ID at 0x{:x}; board mismatch?", addr)
2104+
})?;
21172105

2118-
let deltas = id
2119-
.iter()
2120-
.zip(imageid.1.iter())
2121-
.filter(|&(lhs, rhs)| lhs != rhs)
2122-
.count();
2106+
let deltas = id
2107+
.iter()
2108+
.zip(self.imageid.1.iter())
2109+
.filter(|&(lhs, rhs)| lhs != rhs)
2110+
.count();
21232111

2124-
if deltas > 0 || id.len() != imageid.1.len() {
2125-
bail!(
2112+
if deltas > 0 || id.len() != self.imageid.1.len() {
2113+
bail!(
21262114
"image ID in archive ({:x?}) does not equal \
21272115
ID at 0x{:x} ({:x?})",
2128-
imageid.1, imageid.0, id,
2116+
self.imageid.1, self.imageid.0, id,
21292117
);
2130-
}
2131-
} else {
2132-
bail!("could not find HUBRIS_IMAGE_ID");
21332118
}
21342119

21352120
if criteria == HubrisValidate::ArchiveMatch {
@@ -2333,12 +2318,12 @@ impl HubrisArchive {
23332318
Ok(())
23342319
}
23352320

2336-
pub fn image_id_addr(&self) -> Option<u32> {
2337-
self.imageid.as_ref().map(|i| i.0)
2321+
pub fn image_id_addr(&self) -> u32 {
2322+
self.imageid.0
23382323
}
23392324

2340-
pub fn image_id(&self) -> Option<&[u8]> {
2341-
self.imageid.as_ref().map(|i| i.1.as_slice())
2325+
pub fn image_id(&self) -> &[u8] {
2326+
&self.imageid.1
23422327
}
23432328

23442329
pub fn member_offset(
@@ -2751,12 +2736,12 @@ impl HubrisArchive {
27512736
// always 8-byte aligned; if we have our 17 floating point registers
27522737
// here, we also have an unstored pad.)
27532738
//
2754-
let (nregs_fp, align) =
2755-
if self.manifest.target.as_ref().unwrap() == "thumbv6m-none-eabi" {
2756-
(0, 0)
2757-
} else {
2758-
(17, 1)
2759-
};
2739+
let (nregs_fp, align) = if self.manifest.target == "thumbv6m-none-eabi"
2740+
{
2741+
(0, 0)
2742+
} else {
2743+
(17, 1)
2744+
};
27602745

27612746
let nregs_frame: usize = NREGS_CORE + nregs_fp + align;
27622747

@@ -3729,8 +3714,8 @@ struct HubrisObjectLoader {
37293714
}
37303715

37313716
impl HubrisObjectLoader {
3732-
fn new(object_id: u32) -> Result<Self> {
3733-
Ok(Self {
3717+
fn new(object_id: u32) -> Self {
3718+
Self {
37343719
object_id,
37353720
imageid: None,
37363721
arrays: HashMap::new(),
@@ -3759,7 +3744,7 @@ impl HubrisObjectLoader {
37593744
structs_byname: MultiMap::new(),
37603745
subprograms: HashMap::new(),
37613746
syscall_pushes: HashMap::new(),
3762-
})
3747+
}
37633748
}
37643749

37653750
fn merge(&mut self, loader: HubrisObjectLoader) -> Result<()> {

humility-dump-agent/src/udp.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pub struct UdpDumpAgent<'a> {
1111
}
1212

1313
impl<'a> UdpDumpAgent<'a> {
14-
pub fn new(core: &'a mut dyn Core, image_id: &Vec<u8>) -> Result<Self> {
14+
pub fn new(core: &'a mut dyn Core, image_id: &[u8]) -> Result<Self> {
1515
let mut udp_dump = Self { core };
1616

1717
udp_dump.check_imageid(image_id)?;
@@ -83,7 +83,7 @@ impl<'a> UdpDumpAgent<'a> {
8383
Ok(reply)
8484
}
8585

86-
fn check_imageid(&mut self, image_id: &Vec<u8>) -> Result<()> {
86+
fn check_imageid(&mut self, image_id: &[u8]) -> Result<()> {
8787
let r = self.dump_remote_action(humpty::udp::Request::GetImageId)?;
8888

8989
match r {

0 commit comments

Comments
 (0)