Skip to content

Commit 08f72fc

Browse files
committed
Work with the epoch value as a u32. Do not use ImageHeader epoch field.
1 parent 8266990 commit 08f72fc

File tree

5 files changed

+96
-195
lines changed

5 files changed

+96
-195
lines changed

Cargo.lock

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

hubedit/src/main.rs

+17-32
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ pub enum Command {
3434
version: String,
3535

3636
#[clap(short, long)]
37-
epoch: Option<String>,
37+
epoch: Option<u32>,
3838

3939
#[clap(short, long)]
4040
force: bool,
@@ -151,10 +151,9 @@ fn main() -> Result<()> {
151151
}
152152
}
153153
if no_defaults {
154-
archive.write_version_to_caboose(&version, epoch.as_ref())?;
154+
archive.write_version_to_caboose(&version, epoch)?;
155155
} else {
156-
archive
157-
.write_default_caboose(Some(&version), epoch.as_ref())?;
156+
archive.write_default_caboose(Some(&version), epoch)?;
158157
}
159158
archive.overwrite()?;
160159
}
@@ -173,36 +172,22 @@ fn main() -> Result<()> {
173172
// or have no caboose, or have no caboose with an `EPOC` value.
174173
// The default epoch value is zero.
175174

176-
let (version, caboose_epoch) =
177-
if let Ok(caboose) = archive.read_caboose() {
178-
let version = match caboose.version() {
179-
Ok(vers) => {
180-
std::str::from_utf8(vers).unwrap_or("").to_string()
181-
}
182-
Err(_) => "".to_string(),
183-
};
184-
let epoch =
185-
std::str::from_utf8(caboose.epoch().unwrap_or(&[b'0']))
186-
.unwrap_or("0")
187-
.parse::<u32>()
188-
.unwrap_or(0u32);
189-
(version.clone(), epoch)
190-
} else {
191-
// No caboose
192-
("".to_string(), 0u32)
175+
let (version, epoch) = if let Ok(caboose) = archive.read_caboose() {
176+
let version = match caboose.version() {
177+
Ok(vers) => {
178+
std::str::from_utf8(vers).unwrap_or("").to_string()
179+
}
180+
Err(_) => "".to_string(),
193181
};
194-
let header_epoch = archive.image.image_header_epoch().unwrap_or(0);
195-
196-
println!("Version: \"{}\"", version);
197-
if header_epoch == caboose_epoch {
198-
println!("Epoch: {}", header_epoch);
182+
let epoch = caboose.epoch_u32().unwrap_or(0u32);
183+
(version.clone(), epoch)
199184
} else {
200-
println!("Epoch: {}", 0u32);
201-
bail!(format!(
202-
"Epoch mismatch: ImageHeader({}) != Caboose({})",
203-
header_epoch, caboose_epoch
204-
));
205-
}
185+
// No caboose
186+
("".to_string(), 0u32)
187+
};
188+
189+
println!("Version: \"{version}\"");
190+
println!("Epoch: {epoch}");
206191
}
207192
Command::ReplaceImage { image } => {
208193
let contents = std::fs::read(&image).with_context(|| {

hubtools/src/bootleby.rs

+6-10
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ fn header_offset(elf: &object::read::File) -> Result<u64, Error> {
5757
Err(Error::MissingHeader)
5858
}
5959

60-
fn add_image_header(path: PathBuf, epoch: u32) -> Result<Vec<u8>, Error> {
60+
fn add_image_header(path: PathBuf) -> Result<Vec<u8>, Error> {
6161
// We can't construct an ELF object from a mutable reference so we
6262
// work on the file path and return the bytes
6363
let mut f = std::fs::read(path).map_err(Error::FileReadError)?;
@@ -72,11 +72,7 @@ fn add_image_header(path: PathBuf, epoch: u32) -> Result<Vec<u8>, Error> {
7272
let offset = header_offset(&elf)?;
7373
drop(elf);
7474

75-
let header = header::ImageHeader {
76-
total_image_len: len as u32,
77-
epoch,
78-
..Default::default()
79-
};
75+
let header = header::ImageHeader::new(len as usize);
8076

8177
header
8278
.write_to_prefix(&mut f[(offset as usize)..])
@@ -92,9 +88,7 @@ pub fn bootleby_to_archive(
9288
gitc: String,
9389
epoc: Option<u32>,
9490
) -> Result<Vec<u8>, Error> {
95-
let image_header_epoch: u32 = epoc.unwrap_or(0u32);
96-
let epoc = image_header_epoch.to_string();
97-
let f = add_image_header(path, image_header_epoch)?;
91+
let f = add_image_header(path)?;
9892

9993
let img = RawHubrisImage::from_generic_elf(&f)?;
10094

@@ -109,7 +103,9 @@ pub fn bootleby_to_archive(
109103
chip = "lpc55"
110104
epoch = {}
111105
"#,
112-
name, board, epoc
106+
name,
107+
board,
108+
epoc.unwrap_or(0u32)
113109
);
114110

115111
archive.add_file("elf/kernel", &f)?;

hubtools/src/caboose.rs

+31-29
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,18 @@ impl Caboose {
5252
self.get_tag(tags::EPOC)
5353
}
5454

55+
/// Interpret the `EPOC` value as a u32 if present and well formed.
56+
pub fn epoch_u32(&self) -> Option<u32> {
57+
if let Ok(epoc) = self.epoch() {
58+
if let Ok(epoc_str) = std::str::from_utf8(epoc) {
59+
if let Ok(number) = epoc_str.parse::<u32>() {
60+
return Some(number);
61+
}
62+
}
63+
}
64+
None
65+
}
66+
5567
fn get_tag(&self, tag: [u8; 4]) -> Result<&[u8], CabooseError> {
5668
use tlvc::TlvcReader;
5769
let mut reader = TlvcReader::begin(self.as_slice())
@@ -99,7 +111,7 @@ pub struct CabooseBuilder {
99111
name: Option<String>,
100112
version: Option<String>,
101113
sign: Option<String>,
102-
epoch: Option<String>,
114+
epoch: Option<u32>,
103115
}
104116

105117
impl CabooseBuilder {
@@ -128,19 +140,8 @@ impl CabooseBuilder {
128140
self
129141
}
130142

131-
pub fn epoch<S: Into<String>>(mut self, epoch: S) -> Self {
132-
let epoch: String = epoch.into();
133-
match epoch.len() {
134-
0 => self.epoch = Some("0".to_string()),
135-
_ => {
136-
if let Ok(epoch) = epoch.parse::<u32>() {
137-
self.epoch = Some(format!("{epoch}").to_owned());
138-
} else {
139-
// Any invalid value is treated as zero
140-
self.epoch = Some("0".to_string())
141-
}
142-
}
143-
}
143+
pub fn epoch(mut self, epoch: u32) -> Self {
144+
self.epoch = Some(epoch);
144145
self
145146
}
146147

@@ -152,7 +153,7 @@ impl CabooseBuilder {
152153
(tags::NAME, self.name),
153154
(tags::VERS, self.version),
154155
(tags::SIGN, self.sign),
155-
(tags::EPOC, self.epoch),
156+
(tags::EPOC, self.epoch.map(|e| e.to_string())),
156157
] {
157158
let Some(value) = maybe_value else {
158159
continue;
@@ -224,7 +225,7 @@ mod tests {
224225
.board("bar")
225226
.name("fizz")
226227
.version("buzz")
227-
.epoch("")
228+
.epoch(0)
228229
.build();
229230
assert_eq!(caboose.git_commit(), Ok("foo".as_bytes()));
230231
assert_eq!(caboose.board(), Ok("bar".as_bytes()));
@@ -233,29 +234,30 @@ mod tests {
233234
assert_eq!(caboose.epoch(), Ok("0".as_bytes()));
234235
}
235236

237+
#[test]
238+
fn builder_can_make_caboose_with_zero_epoch() {
239+
let caboose = CabooseBuilder::default().epoch(0).build();
240+
assert_eq!(caboose.epoch(), Ok("0".as_bytes()));
241+
}
242+
236243
#[test]
237244
fn builder_can_make_caboose_with_non_zero_epoch() {
238-
let caboose = CabooseBuilder::default().epoch("1234567890").build();
245+
let caboose = CabooseBuilder::default().epoch(1234567890).build();
239246
assert_eq!(caboose.epoch(), Ok("1234567890".as_bytes()));
240247
}
241248

242249
#[test]
243-
fn builder_will_normalize_empty_epoch() {
244-
let caboose = CabooseBuilder::default().epoch("").build();
245-
assert_eq!(caboose.epoch(), Ok("0".as_bytes()));
250+
fn builder_missing_tag_epoc() {
251+
let caboose = CabooseBuilder::default().build();
252+
assert_eq!(
253+
caboose.epoch(),
254+
Err(CabooseError::MissingTag { tag: tags::EPOC })
255+
);
246256
}
247257

248258
#[test]
249259
fn builder_will_normalize_short_epoch() {
250-
let caboose = CabooseBuilder::default().epoch("1234").build();
260+
let caboose = CabooseBuilder::default().epoch(1234).build();
251261
assert_eq!(caboose.epoch(), Ok("1234".as_bytes()));
252262
}
253-
254-
#[test]
255-
fn builder_will_convert_u64_epoch_to_zero() {
256-
let caboose = CabooseBuilder::default()
257-
.epoch("4294967296") // u32::MAX_VALUE + 1
258-
.build();
259-
assert_eq!(caboose.epoch(), Ok("0".as_bytes()));
260-
}
261263
}

0 commit comments

Comments
 (0)