-
Notifications
You must be signed in to change notification settings - Fork 64
Use BOOTED_IMAGE to warn when using wrong A/B image #712
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
evan-oxide
wants to merge
1
commit into
master
Choose a base branch
from
evan/booted-image-id-humility
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2071,36 +2071,39 @@ impl HubrisArchive { | |
| &self, | ||
| core: &mut dyn crate::core::Core, | ||
| criteria: HubrisValidate, | ||
| log: &Logger, | ||
| ) -> Result<()> { | ||
| let ntasks = self.ntasks(); | ||
| if core.is_net() || core.is_archive() { | ||
| return Ok(()); | ||
| } | ||
|
|
||
| // To validate that what we're running on the target matches what | ||
| // we have in the archive, we are going to check the image ID, an | ||
| // identifer created for this purpose. | ||
| let addr = self.imageid.0; | ||
| let nbytes = self.imageid.1.len(); | ||
| assert!(nbytes > 0); | ||
|
|
||
| let mut id = vec![0; nbytes]; | ||
| core.read_8(addr, &mut id[0..nbytes]).with_context(|| { | ||
| format!("failed to read image ID at 0x{:x}; board mismatch?", addr) | ||
| })?; | ||
|
|
||
| let deltas = id | ||
| .iter() | ||
| .zip(self.imageid.1.iter()) | ||
| .filter(|&(lhs, rhs)| lhs != rhs) | ||
| .count(); | ||
| // To validate that what we're running on the target matches what we | ||
| // have in the archive, we are going to check the image ID, an identifer | ||
| // created for this purpose. First try to read the ID of the image that | ||
| // actually booted, as recorded by the kernel. If that fails then fall | ||
| // back to reading the ID from FLASH, which can be misleading on targets | ||
| // with A/B images. For example, if the archive is an A image, then | ||
| // `read_image_id_from_flash` will return the ID of whichever A image | ||
| // was last flashed regardless of whether the target is currently | ||
| // running an A or B image. | ||
| let id = match self.booted_image(core) { | ||
| Ok((id, _)) => id, | ||
| Err(err) => { | ||
| info!( | ||
| log, | ||
| "can't detect booted image, reading image ID from FLASH ({})", | ||
| err | ||
| ); | ||
| self.read_image_id_from_flash(core)? | ||
| } | ||
| }; | ||
|
|
||
| if deltas > 0 || id.len() != self.imageid.1.len() { | ||
| if id != self.imageid.1 { | ||
|
Comment on lines
-2098
to
+2101
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can't think of any reason why the original code would need to do that manual comparison instead of just using |
||
| bail!( | ||
| "image ID in archive ({:x?}) does not equal \ | ||
| ID at 0x{:x} ({:x?})", | ||
| self.imageid.1, self.imageid.0, id, | ||
| ); | ||
| image ID of target ({:x?})", | ||
| self.imageid.1, id, | ||
| ); | ||
| } | ||
|
|
||
| if criteria == HubrisValidate::ArchiveMatch { | ||
|
|
@@ -2111,6 +2114,7 @@ impl HubrisArchive { | |
| return Ok(()); | ||
| } | ||
|
|
||
| let ntasks = self.ntasks(); | ||
| let (_, n) = self.task_table(core)?; | ||
|
|
||
| if n == ntasks as u32 { | ||
|
|
@@ -2170,6 +2174,67 @@ impl HubrisArchive { | |
| ); | ||
| } | ||
|
|
||
| /// Reads the kernel's `BOOTED_IMAGE` array to determine which image is | ||
| /// actually running on the target. | ||
| /// | ||
| /// Returns the image ID and the image name. | ||
| pub fn booted_image( | ||
| &self, | ||
| core: &mut dyn crate::core::Core, | ||
| ) -> Result<(Vec<u8>, String)> { | ||
| const MAGIC: &[u8] = b"HUBRISID"; | ||
| const ID_LEN: usize = 8; | ||
|
|
||
| // If BOOTED_IMAGE isn't in the symbol table, it's probably because the | ||
| // archive is too old. | ||
| let &(addr, size) = | ||
| self.esyms_byname.get("BOOTED_IMAGE").ok_or_else(|| { | ||
| anyhow!("BOOTED_IMAGE not in archive's symbol table") | ||
| })?; | ||
|
|
||
| let size = size as usize; | ||
| if size < ID_LEN + MAGIC.len() { | ||
| // Even if the name was empty, the fixed length parts wouldn't fit. | ||
| // Don't try to interpret it. | ||
| return Err(anyhow!("BOOTED_IMAGE array is unexpectedly short")); | ||
| } | ||
|
|
||
| let mut block = vec![0u8; size]; | ||
| core.read_8(addr, &mut block).with_context(|| { | ||
| format!("failed to read BOOTED_IMAGE at 0x{:x}", addr) | ||
| })?; | ||
|
|
||
| let id = &block[..ID_LEN]; | ||
| // We don't know the length of the name, but we know the lengths of the | ||
| // stuff on either side. | ||
| let name = &block[ID_LEN..size - MAGIC.len()]; | ||
| let magic = &block[size - MAGIC.len()..]; | ||
| if magic != MAGIC { | ||
| return Err( | ||
| anyhow!("BOOTED_IMAGE array does not contain magic marker"), | ||
| ); | ||
| } | ||
| let name_string = | ||
| String::from_utf8_lossy(name).trim_end_matches('\0').to_string(); | ||
|
|
||
| Ok((id.to_vec(), name_string)) | ||
| } | ||
|
|
||
| pub fn read_image_id_from_flash( | ||
| &self, | ||
| core: &mut dyn crate::core::Core, | ||
| ) -> Result<Vec<u8>> { | ||
| let addr = self.imageid.0; | ||
| let nbytes = self.imageid.1.len(); | ||
| assert!(nbytes > 0); | ||
|
|
||
| let mut id = vec![0; nbytes]; | ||
| core.read_8(addr, &mut id[0..nbytes]).with_context(|| { | ||
| format!("failed to read image ID at 0x{:x}; board mismatch?", addr) | ||
| })?; | ||
| Ok(id) | ||
| } | ||
|
|
||
| pub fn verify( | ||
| &self, | ||
| core: &mut dyn crate::core::Core, | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be worth checking the PC location here as part of the fallback when we can't read BOOTED_IMAGE. In addition to requiring the flash ID to match, we could either fail or warn if the PC suggests this is the wrong image slot.