-
Notifications
You must be signed in to change notification settings - Fork 196
Transient boot selection #2050
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
base: master
Are you sure you want to change the base?
Transient boot selection #2050
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,6 +18,7 @@ use drv_lpc55_update_api::{ | |
SlotId, SwitchDuration, UpdateTarget, VersionedRotBootInfo, | ||
}; | ||
use drv_update_api::UpdateError; | ||
use hex_literal::hex; | ||
use idol_runtime::{ | ||
ClientError, Leased, LenLimit, NotificationHandler, RequestError, R, W, | ||
}; | ||
|
@@ -40,6 +41,10 @@ const PAGE_SIZE: u32 = BYTES_PER_FLASH_PAGE as u32; | |
#[link_section = ".bootstate"] | ||
static BOOTSTATE: MaybeUninit<[u8; 0x1000]> = MaybeUninit::uninit(); | ||
|
||
#[used] | ||
#[link_section = ".transient_override"] | ||
static mut TRANSIENT_OVERRIDE: MaybeUninit<[u8; 32]> = MaybeUninit::uninit(); | ||
|
||
#[derive(Copy, Clone, PartialEq)] | ||
enum UpdateState { | ||
NoUpdate, | ||
|
@@ -503,6 +508,12 @@ impl idl::InOrderUpdateImpl for ServerImpl<'_> { | |
ringbuf_entry!(Trace::State(self.state)); | ||
self.next_block = None; | ||
self.fw_cache.fill(0); | ||
// The sequence: [update, set transient preference, update] is legal. | ||
// Clear any stale transient preference before update. | ||
// Stage0 doesn't support transient override. | ||
if component == RotComponent::Hubris { | ||
set_hubris_transient_override(None); | ||
} | ||
Comment on lines
+511
to
+516
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 think I see what this is trying to do but I'm not sure this is the right place. This would make 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. Okay I re-read the RFD and double checked the bootleby source, the transient command is supposed to be nuked on boot by bootleby. I'm still not quite sure what makes this a 'stale' choice. 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. It's not actually stale until some flash has been altered. Given the sequence where SlotId::B is active:
This is a corner case since we normally expect update, set-preference, reset. We could wait until the first block of an image is received or that block is written to cancel the boot once directive. 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 agree it's a corner case. Fixing it in this way is a pretty poor developer experience because there's no indication that the boot setting has changed which will frustrate everyone. The transient boot setting should not be cancelled without some indication. We also have the exact same issue with the persistent settings. I get the theory is to avoid booting into a potentially bad image because we're now relying on bootleby to correctly determine that the slot is unbootable but this feels like it causes more problems than it solves. I think this issue of boot settings would be better tracked as a separate issue. |
||
Ok(()) | ||
} | ||
|
||
|
@@ -907,8 +918,11 @@ impl ServerImpl<'_> { | |
) -> Result<(), RequestError<UpdateError>> { | ||
match duration { | ||
SwitchDuration::Once => { | ||
// TODO deposit command token into buffer | ||
return Err(UpdateError::NotImplemented.into()); | ||
// TODO check Rollback policy vs epoch before activating. | ||
// TODO: prep-image-update should clear transient selection. | ||
// e.g. update, activate, update, reboot should not have | ||
// transient boot set. | ||
set_hubris_transient_override(Some(slot)); | ||
} | ||
SwitchDuration::Forever => { | ||
// Locate and return the authoritative CFPA flash word number | ||
|
@@ -1337,6 +1351,35 @@ fn bootstate() -> Result<RotBootStateV2, HandoffDataLoadError> { | |
RotBootStateV2::load_from_addr(addr) | ||
} | ||
|
||
fn set_transient_override(preference: [u8; 32]) { | ||
// Safety: Data is consumed by Bootleby on next boot. | ||
// There are no concurrent writers possible. | ||
// Calling this function multiple times is ok. | ||
// Bootleby is careful to vet contents before acting. | ||
unsafe { | ||
TRANSIENT_OVERRIDE.write(preference); | ||
} | ||
} | ||
|
||
pub fn set_hubris_transient_override(bank: Option<SlotId>) { | ||
// Preference constants are taken from bootleby:src/lib.rs | ||
const PREFER_SLOT_A: [u8; 32] = hex!( | ||
"edb23f2e9b399c3d57695262f29615910ed10c8d9b261bfc2076b8c16c84f66d" | ||
); | ||
const PREFER_SLOT_B: [u8; 32] = hex!( | ||
"70ed2914e6fdeeebbb02763b96da9faa0160b7fc887425f4d45547071d0ce4ba" | ||
); | ||
// Bootleby writes all zeros after reading. We write all ones to reset. | ||
const PREFER_NOTHING: [u8; 32] = [0xffu8; 32]; | ||
|
||
match bank { | ||
// Do we need a value that says we were here and cleared? | ||
None => set_transient_override(PREFER_NOTHING), | ||
Some(SlotId::A) => set_transient_override(PREFER_SLOT_A), | ||
Some(SlotId::B) => set_transient_override(PREFER_SLOT_B), | ||
} | ||
} | ||
|
||
fn round_up_to_flash_page(offset: u32) -> Option<u32> { | ||
offset.checked_next_multiple_of(BYTES_PER_FLASH_PAGE as u32) | ||
} | ||
|
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.
Can we use the non-secure alias
0x2003ffe0
? This better matches what we do for our other addressesThere 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.
Yes.