Skip to content
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

Open
wants to merge 9 commits into
base: main-2.x
Choose a base branch
from

Conversation

swenson
Copy link
Contributor

@swenson swenson commented Jan 23, 2025

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.

@swenson swenson added the Caliptra v2.0 Items to be considered for v2.0 Release label Jan 23, 2025
@@ -62,7 +106,7 @@ pub struct DmaWriteTransaction {

/// Dma Widget
pub struct Dma {
dma: AxiDmaReg,
dma: Cell<Option<AxiDmaReg>>,
Copy link
Contributor Author

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.

Copy link
Collaborator

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.

@swenson swenson force-pushed the download-manifest-mcu-fw branch from 173817b to 9152e52 Compare January 23, 2025 21:53
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.
@swenson swenson force-pushed the download-manifest-mcu-fw branch from 9152e52 to c9b226d Compare January 23, 2025 22:00
@swenson swenson requested a review from jlmahowa-amd as a code owner January 23, 2025 22:57
self.dma.set(Some(dma));
Ok(result)
} else {
Err(CaliptraError::RUNTIME_INTERNAL) // should never happen
Copy link
Collaborator

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.

.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)?;
Copy link
Collaborator

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.

mhatrevi
mhatrevi previously approved these changes Jan 28, 2025
Copy link
Collaborator

@mhatrevi mhatrevi left a 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() {
Copy link
Collaborator

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.

Copy link
Contributor Author

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?

Comment on lines 45 to 51
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);
};
Copy link
Collaborator

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 {
Copy link
Collaborator

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?

Copy link
Contributor Author

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.)

Comment on lines +35 to +37
fn from_u32(val: u32) -> Self {
(val & 0xff) as u8
}
Copy link
Collaborator

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.

Copy link
Contributor Author

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 {
Copy link
Collaborator

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Caliptra v2.0 Items to be considered for v2.0 Release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants