-
Notifications
You must be signed in to change notification settings - Fork 47
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
[runtime] Start recovery flow in the runtime #1904
base: main-2.x
Are you sure you want to change the base?
Conversation
@@ -62,7 +106,7 @@ pub struct DmaWriteTransaction { | |||
|
|||
/// Dma Widget | |||
pub struct Dma { | |||
dma: AxiDmaReg, | |||
dma: Cell<Option<AxiDmaReg>>, |
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.
We have to switch to a Cell
because the Mmio
and MmioMut
interfaces require that the methods use &self
instead of &mut self
, so we need interior mutability.
For safety, I used a with_dma()
to ensure that the AxiDmaReg
is only used by one function at a time, though this is probably overkill since Caliptra is single-threaded.
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.
Suggest simplifying the code (if possible) with the single-threaded execution assumption.
173817b
to
9152e52
Compare
This stubs out the recovery flow in the runtime. We also update the DMA peripheral so that it can be used as a `ureg::Mmio`, which will allow us to use the autogenerated I3C recovery register interface instead of hardcoding offsets. We also had to modify `ureg` slightly to remove the unused `impl Uint` for `u64` (because we don't don't support 64-bit AXI transfers) and add a `from_u32()` method for the (unused) `u8` and `u16` implementations. This builds on #1867 and rewrites it to use the updated DMA interface.
9152e52
to
c9b226d
Compare
drivers/src/dma.rs
Outdated
self.dma.set(Some(dma)); | ||
Ok(result) | ||
} else { | ||
Err(CaliptraError::RUNTIME_INTERNAL) // should never happen |
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.
Suggest renaming this to something like 'DRIVERS_INTERNAL' to disambiguate from a Runtime app error.
runtime/src/recovery_flow.rs
Outdated
.auth_manifest_image_metadata_col = image_metadata_collection; | ||
// [TODO][CAP2]: capture measurement of Soc manifest? | ||
// [TODO][CAP2]: this should be writing to MCU SRAM directly via AXI | ||
let _mcu_size_bytes = dma_recovery.download_image_to_mbox(SOC_MANIFEST_INDEX)?; |
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.
This should use the MCU_FIRMWARE_INDEX.
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.
Please see the feedback.
@@ -171,6 +176,9 @@ impl Drivers { | |||
ResetReason::ColdReset => { | |||
cfi_assert_eq(self.soc_ifc.reset_reason(), ResetReason::ColdReset); | |||
Self::initialize_dpe(self)?; | |||
if self.soc_ifc.active_mode() { |
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.
I wonder if this should be a build-time flag since for a given integration it's either active or not. Otoh, it's probably easier to have a less complicated test matrix for RT.
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.
Would we plan on building a separate active mode ROM then?
runtime/src/recovery_flow.rs
Outdated
let _soc_size_bytes = dma_recovery.download_image_to_mbox(SOC_MANIFEST_INDEX)?; | ||
let Some(preamble) = AuthManifestPreamble::read_from_prefix(drivers.mbox.raw_mailbox_contents()) else { | ||
return Err(CaliptraError::IMAGE_VERIFIER_ERR_MANIFEST_SIZE_MISMATCH); | ||
}; | ||
let Some(image_metadata_collection) = AuthManifestImageMetadataCollection::read_from_prefix(&drivers.mbox.raw_mailbox_contents()[AUTH_MANIFEST_PREAMBLE_SIZE..]) else { | ||
return Err(CaliptraError::IMAGE_VERIFIER_ERR_MANIFEST_SIZE_MISMATCH); | ||
}; |
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.
nit: can probably simplify this by making a single stuct that contains AuthManifestPreamble
and AuthManifestImageMetadataCollection
and then doing a single read.
} | ||
impl private::Sealed for u32 {} | ||
|
||
impl Uint for u64 { |
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.
Why is u64 removed here?
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.
We never use 64-bit registers, and I don't know if we have the semantics for it super well-defined given our 32-bit memory bus. (Things like, which word is written first.) So, it seemed easier to just to remove 64-bit support altogether.
(Side note, I'd also be a fan of removing 8- and 16-bit register support as well, since it also is a little murky semantically, and refactoring out the Uint
type altogether to just be u32
.)
fn from_u32(val: u32) -> Self { | ||
(val & 0xff) as u8 | ||
} |
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.
Is this needed for multiple types? I think I would prefer to the the truncation closer to the specific register that needs it so that we can review specific usages as not dropping any meaningful bytes.
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's not truly needed except on paper, as we don't have any 8- or 16-bit registers.
|
||
// // download SoC manifest | ||
let _soc_size_bytes = dma_recovery.download_image_to_mbox(SOC_MANIFEST_INDEX)?; | ||
let Some(manifest) = AuthorizationManifest::read_from_prefix(drivers.mbox.raw_mailbox_contents()) else { |
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.
This is not efficient. AuthorizationManifest is of 14284 bytes; most of the time there will only be a handful of image digests in it. I would simply add a TODO here to call the existing set_manifest_code.
This stubs out the recovery flow in the runtime.
We also update the DMA peripheral so that it can be used as a
ureg::Mmio
, which will allow us to use the autogenerated I3C recoveryregister interface instead of hardcoding offsets.
We also had to modify
ureg
slightly to remove the unusedimpl Uint
for
u64
(because we don't don't support 64-bit AXI transfers) and adda
from_u32()
method for the (unused)u8
andu16
implementations.This builds on #1867 and rewrites it to use the updated DMA interface.