4d4e129
Reference ROM Specification
The reference ROM is executed when the MCU starts.
The ROM's main responsibilities to the overall Caliptra subsystem are to:
- Send non-secret fuses to Caliptra core
- Initialize I3C and the firmware recovery interface
- Jump to firmware
It can also handle any other custom SoC-specific initialization that needs to happen early.
Boot Flows
There are three main boot flows that needs to execute for its role in the Caliptra subsystem:
- Cold Boot Flow
- Firmware Update Flow
- Warm Reset Flow
These are selected based on the MCI RESET_REASON register that is set by hardware whenver the MCU is reset.
Cold Boot Flow
-
Check the MCI
RESET_REASONregister for MCU status (it should be in cold boot mode) -
Initialize I3C recovery interface. For AXI bypass boot, only the recovery interface initialization is required; basic I3C initialization can be skipped.
- For I3C boot: Initialize I3C registers according to the initialization sequence, then initialize I3C recovery interface per the recovery flow.
- For AXI bypass boot: Only initialize the recovery interface registers needed for streaming boot.
-
Assert Caliptra boot go signal to bring Caliptra out of reset.
-
Read Caliptra SoC
FLOW_STATUSregister to wait for Caliptra Ready for Fuses state. -
Anything SoC-specific can happen here
-
Read non-secret fuses from the OTP controller. The authoritative fuse map is contained in the main Caliptra specification.
-
Write fuse data to Caliptra SoC interface fuse registers. The following fuses are written to the corresponding Caliptra registers:
FUSE_PQC_KEY_TYPE: Vendor PQC key type (2 bits)FUSE_FMC_KEY_MANIFEST_SVN: FMC key manifest SVN (32 bits)FUSE_VENDOR_PK_HASH: Vendor public key hash (384 bits)FUSE_RUNTIME_SVN: Runtime SVN (128 bits)FUSE_SOC_MANIFEST_SVN: SoC manifest SVN (128 bits)FUSE_SOC_MANIFEST_MAX_SVN: SoC manifest max SVN (32 bits)FUSE_MANUF_DBG_UNLOCK_TOKEN: Manufacturing debug unlock token (128 bits)FUSE_ECC_REVOCATION: Vendor ECC key revocation (4 bits)FUSE_LMS_REVOCATION: Vendor LMS key revocation (32 bits)FUSE_MLDSA_REVOCATION: Vendor MLDSA key revocation (4 bits)CPTRA_OWNER_PK_HASH: Owner public key hash (384 bits, written only if non-zero, could be overridden by device ownership transfer)FUSE_SOC_STEPPING_ID: SoC stepping ID (16 bits)FUSE_ANTI_ROLLBACK_DISABLE: Anti-rollback disable (1 bit)FUSE_IDEVID_CERT_ATTR: IDevID certificate attributes (768 bits)FUSE_IDEVID_MANUF_HSM_ID: IDevID manufacturing HSM identifier (128 bits)SS_UDS_SEED_BASE_ADDR_L/H: UDS/FE partition base address in OTPSS_STRAP_GENERIC[0]: OTP DAI idle bit offset (bits[31:16])SS_STRAP_GENERIC[1]: OTP direct access command register offsetSS_STRAP_GENERIC[2]: iTRNG health test window size from OTP (bits[15:0]) and bypass mode flag (bit[31], from ROM parameters)CPTRA_I_TRNG_ENTROPY_CONFIG_0: iTRNG entropy configuration word 0, from OTPcptra_itrng_entropy_config_0CPTRA_I_TRNG_ENTROPY_CONFIG_1: iTRNG entropy configuration word 1, from OTPcptra_itrng_entropy_config_1- [MCI]
PROD_DEBUG_UNLOCK_PK_HASH_REGProduction debug unlock public key hashes (384 bytes total for 8 key hashes) SS_PROD_DEBUG_UNLOCK_AUTH_PK_HASH_REG_BANK_OFFSET: Offset ofPROD_DEBUG_UNLOCK_PK_HASH_REGwithin the MCI register bank (0x480). Caliptra ROM reads the expected hash for debug levelNfromMCI_BASE + offset + (N - 1) * 48.SS_NUM_OF_PROD_DEBUG_UNLOCK_AUTH_PK_HASHES: Number of production debug unlock PK hashes available (defaults to the number of entries in the reference fuse map, 8; overridable via theprod_debug_unlock_auth_pk_hash_countROM parameter).- See the ROM fuses documentation for details on how these are read and interpreted.
-
Configure MCU mailbox AXI users (see Security Configuration below).
-
Set mailbox AXI user lock registers.
-
[2.1] Set FC_FIPS_ZEROZATION to the appropriate value.
-
Configure the MCU SRAM execution region size by writing to the
FW_SRAM_EXEC_REGION_SIZEregister. If not specified inRomParameters, it defaults to reserving 32KB at the top of SRAM for the Protected Data Region. -
Set
SS_CONFIG_DONE_STICKY,SS_CONFIG_DONEregisters to lock MCI configuration. -
Verify PK hashes and MCU mailbox AXI users after locking (see Security Configuration below).
-
Poll on Caliptra
FLOW_STATUSregisters for Caliptra to deassert the Ready for Fuses state. -
Determine owner public key hash. The ROM determines which owner public key hash to write to Caliptra's
CPTRA_OWNER_PK_HASHregister. The source depends on whether Device Ownership Transfer (DOT) is configured and the current DOT state:- DOT configured and DOT blob present: The ROM runs the full DOT flow β derives the
DOT_EFFECTIVE_KEY, verifies the DOT blob's HMAC, and determines the owner from the blob's state:- Locked state (ODD, blob has CAK): The Code Authentication Key (CAK) from the DOT blob is used as the owner PK hash.
- Disabled state (ODD, no CAK): The DOT blob is authentic but contains no CAK. The ROM falls back to reading
CPTRA_SS_OWNER_PK_HASHfrom OTP fuses. - EVEN state (Uninitialized/Volatile): DOT does not provide a persistent owner. The ROM falls back to reading
CPTRA_SS_OWNER_PK_HASHfrom OTP fuses.
- DOT blob empty or corrupt in Locked (ODD) state: The ROM attempts DOT recovery (challenge/response or backup blob, depending on the platform's recovery policy). If recovery fails, this is a fatal error.
- DOT not configured: The ROM skips DOT entirely and reads the owner PK hash from
CPTRA_SS_OWNER_PK_HASHin OTP.
In summary,
CPTRA_SS_OWNER_PK_HASHin OTP serves as a fallback whenever DOT does not provide an owner. When DOT is in the Locked state, the CAK from the DOT blob supersedes the fuse value.Note: Revocation or rotation of the
CPTRA_SS_OWNER_PK_HASHfuse value is outside the scope of DOT. DOT provides its own key lifecycle (install, lock, unlock, disable) through the DOT blob and fuse array. If an integrator needs to revoke or rotate the fuse-based owner key independently, that must be managed through a separate platform-specific mechanism. - DOT configured and DOT blob present: The ROM runs the full DOT flow β derives the
-
Send the
RI_DOWNLOAD_FIRMWAREcommand to Caliptra to start the firmware loading process. Caliptra will:- Follow all of the steps in the Caliptra ROM documentation for firmware loading in the ROM cold reset.
- Transition to Caliptra runtime firmware.
- Load the SoC manifest over the recovery interface and verify it.
- Load the MCU runtime over the recovery interface registers to the MCU SRAM.
- Verify the MCU runtime against the SoC manifest.
- [2.1] If the MCU runtime is encrypted:
- Caliptra runtime returns to mailbox processing mode.
- MCU derives or imports the decryption key to the Caliptra cryptographic mailbox.
- MCU issues a CM_AES_GCM_DECRYPT_DMA command to decrypt the firmware in MCU SRAM.
- MCU issues the ACTIVATE_FIRMWARE command to Caliptra to activate the MCU firmware.
- Caliptra sets the MCI
FW_EXEC_CTRL[2]bit to indicate that MCU firmware is ready
-
Wait for Caliptra to indicate MCU firmware is ready by polling the firmware ready status.
-
Stash the MCU ROM and other security-sensitive measurements to Caliptra. (In 2.1 subsystem mode, this should happen after Caliptra runtime is available using CM_SHA_{INIT,UPDATE,FINAL}. In 2.0 or 2.1 core mode, this could potentially happen earlier using the CM_SHA ROM command.)
-
MCU ROM triggers a reset by writing
0x1to the MCIRESET_REQUESTregister. This generates a hardware reset of the MCU core while maintaining power. The MCI hardware automatically setsRESET_REASONtoFirmwareBootReset, causing the MCU to restart and enter the Firmware Boot Reset flow, which will jump to the loaded firmware.
sequenceDiagram
note right of mcu: check reset reason
mcu->>mci: assert Caliptra boot go
note right of mcu: initialize recovery interface
loop wait for ready for fuses
mcu->>caliptra: read flow status
end
note right of mcu: SoC-specific init
mcu->>otp: read non-secret fuses
otp->>mcu: non-secret fuses
mcu->>caliptra: set non-secret fuses
mcu->>mci: configure MCU mailbox AXI users
mcu->>mci: lock MCU mailbox AXI users
mcu->>mci: set FW_SRAM_EXEC_REGION_SIZE
mcu->>mci: set SS_CONFIG_DONE_STICKY
mcu->>mci: set SS_CONFIG_DONE
mcu->>mci: verify PK hashes
mcu->>mci: verify MCU mailbox AXI users
loop wait for NOT ready for fuses
mcu->>caliptra: read flow status
end
note right of mcu: determine owner PK hash (DOT or fuse fallback)
mcu->>caliptra: set owner PK hash
mcu->>caliptra: RI_DOWNLOAD_FIRMWARE command
note right of caliptra: authenticate FW header/TOC
note right of caliptra: verify signatures
note right of caliptra: load/decrypt Caliptra FW
note right of caliptra: derive runtime keys
alt encrypted MCU FW
note right of caliptra: decrypt and load MCU FW to SRAM
else unencrypted MCU FW
note right of caliptra: load MCU FW to SRAM
end
caliptra->>mci: set FW_EXEC_CTL[2]
loop wait for firmware ready
mcu->>mci: check FW_EXEC_CTL
end
mcu->>mci: write RESET_REQUEST (0x1)
note right of mcu: resets to Firmware Boot flow
Firmware Boot Flow
This flow is used to boot the MCU into the MCU Runtime Firmware following either a cold or warm reset. It ensures that the runtime firmware is properly loaded and ready for execution.
- Check the MCI
RESET_REASONregister for MCU status (it should be in firmware boot reset modeFirmwareBootReset). - Set flow checkpoint to indicate firmware boot flow has started.
- Compute the firmware entry offset starting from the MCU image header size.
- If the DOT manifests are enabled and
fw_manifest_dot_enabledis set, look for a firmware-manifest DOT section at the start of MCU SRAM. If found (identified by its magic value):- Advance the firmware entry offset past the DOT manifest section.
- Process the DOT commands contained in the manifest section (see DOT documentation). A fatal error is raised if DOT processing fails.
- Validate that firmware is present by checking that the first word at the computed firmware entry point (
sram_offset + firmware_offset) is non-zero. A fatal error (ROM_FW_BOOT_INVALID_FIRMWARE) is raised otherwise. - Set flow milestone to indicate firmware boot flow completion.
- Jump directly to runtime firmware at the computed SRAM entry point.
sequenceDiagram
note right of mcu: check reset reason (FirmwareBootReset)
note right of mcu: set flow checkpoint
alt DOT manifests enabled and DOT section present
note right of mcu: advance entry offset past DOT section
note right of mcu: process firmware-manifest DOT commands
end
note right of mcu: validate firmware at entry point
alt firmware valid
note right of mcu: set completion milestone
note right of mcu: jump to runtime firmware
else firmware invalid
note right of mcu: fatal error - halt
end
Hitless Firmware Update Flow
Hitless Update Flow is triggered when MCU runtime FW requests an update of the MCU firmware by sending the ACTIVATE_FIRMWARE mailbox command to Caliptra. Upon receiving the mailbox command, Caliptra initiates the MCU reset sequence, which copies the new firmware image into MCU SRAM and causes the MCU to reboot into ROM with RESET_REASON set to FirmwareHitlessUpdate.
- Check the MCI
RESET_REASONregister for reset status (it should beFirmwareHitlessUpdate). - Release the Caliptra mailbox by completing the response to the original
ACTIVATE_FIRMWAREcommand. This is required because the mailbox is still held by the command that triggered this reset. A fatal error (ROM_FW_HITLESS_UPDATE_CLEAR_MB_ERROR) is raised if the mailbox cannot be released. - Wait for Caliptra to indicate that MCU firmware is ready in SRAM (i.e., Caliptra has finished copying the new image).
- Compute the firmware entry offset starting from the MCU image header size. If the DOT manifests feature is enabled and
fw_manifest_dot_enabledis set, and a DOT firmware manifest section is present at the start of SRAM (identified by its magic value), advance the entry offset past that section. Note that unlike the Firmware Boot Flow, the hitless update flow does not re-process the DOT manifest commands β it only skips past the section so that the entry point lands on the firmware reset vector. - Jump directly to runtime firmware at the computed SRAM entry point.
sequenceDiagram
note right of mcu: check reset reason (FirmwareHitlessUpdate)
mcu->>caliptra: release mailbox (finish ACTIVATE_FIRMWARE response)
loop wait for firmware ready
mcu->>caliptra: check fw_ready status
end
alt DOT manifest enabled and DOT section present
note right of mcu: advance entry offset past DOT section
end
note right of mcu: jump to runtime firmware
Warm Reset Flow
Warm Reset Flow occurs when the subsystem reset is toggled while powergood is maintained high. This is allowed when MCU and Caliptra already loaded their respective mutable firmware prior to the warm reset. MCU and Caliptra firmware will not be reloaded in this flow; the firmware image persists in MCU SRAM across the warm reset because SRAM contents are preserved while powergood is held high.
Note that SS_CONFIG_DONE_STICKY remains set from cold boot, so sticky registers (PK hashes, fuses, etc.) are already locked and do not need to be rewritten or reverified. However, SS_CONFIG_DONE is cleared on warm reset and must be re-asserted. See Warm Reset Considerations for details on which registers need reconfiguration.
- Check the MCI
RESET_REASONregister for reset status (it should be in warm reset modeWarmReset). - Assert Caliptra boot go signal to bring Caliptra out of reset.
- Wait for Caliptra to be ready for fuses (even though fuses will not be rewritten β the handshake still needs to be completed).
- Configure the Caliptra watchdog timers (
CPTRA_WDT_CFG[0]and[1]) from straps. - Set the MCU NMI vector to the ROM base address.
- Configure the MCU watchdog timers. The values used depend on the current security state and device lifecycle:
- Debug unlocked: use the debug watchdog configuration.
- Debug locked + Manufacturing lifecycle: use the manufacturing watchdog configuration.
- Debug locked + other lifecycle: use the production watchdog configuration.
- Reconfigure Caliptra AXI user registers (mailbox users, fuse user, TRNG user, DMA user) from ROM parameters. These are non-sticky and must be re-applied on every warm reset.
- Reconfigure the MCU mailbox AXI users for mailbox 0 and mailbox 1.
- Configure the MCU SRAM execution region size by writing to the
FW_SRAM_EXEC_REGION_SIZEregister. The value comes from ROM parameters, or defaults to the SRAM size minus the protected region. - Set
SS_CONFIG_DONE_STICKY(no-op since it is already sticky from cold boot, but asserted for consistency) and thenSS_CONFIG_DONEto lock MCI configuration until the next warm reset. - Verify that both
SS_CONFIG_DONE_STICKYandSS_CONFIG_DONEare actually set. A fatal error is raised if either is not set (ROM_SOC_SS_CONFIG_DONE_VERIFY_FAILED). - Verify that the MCU mailbox AXI user registers match what was written (detect tampering after locking).
- Signal fuse write done to Caliptra to complete the fuse handshake protocol. This is required per the Caliptra integration specification even though fuses cannot be rewritten on warm reset.
- Wait for Caliptra to deassert the ready-for-fuses state.
- Wait for Caliptra boot FSM to reach the DONE state.
- Wait for Caliptra to indicate that MCU firmware is ready in SRAM (firmware is still present from before the warm reset).
- Validate that firmware is present by checking that the first word at the firmware entry point (
sram_offset + mcu_image_header_size) is non-zero. A fatal error (ROM_WARM_BOOT_INVALID_FIRMWARE) is raised otherwise. - Set flow checkpoint and milestone to indicate warm reset flow completion.
- Trigger a warm reset to transition to the
FirmwareBootResetflow, which will jump to the firmware.
sequenceDiagram
note right of mcu: check reset reason (WarmReset)
note right of mcu: set flow checkpoint
mcu->>caliptra: assert boot go signal
loop wait for ready for fuses
mcu->>caliptra: check ready for fuses status
end
mcu->>caliptra: configure Caliptra watchdog timers
note right of mcu: set NMI vector
mcu->>mci: configure MCU watchdog (by security state/lifecycle)
mcu->>caliptra: configure AXI users (mbox/fuse/trng/dma)
mcu->>mci: configure MCU mailbox AXI users
mcu->>mci: set FW_SRAM_EXEC_REGION_SIZE
mcu->>mci: set SS_CONFIG_DONE_STICKY
mcu->>mci: set SS_CONFIG_DONE
mcu->>mci: verify SS_CONFIG_DONE_STICKY and SS_CONFIG_DONE set
mcu->>mci: verify MCU mailbox AXI users unchanged
mcu->>caliptra: signal fuse write done
loop wait for NOT ready for fuses
mcu->>caliptra: check ready for fuses status
end
loop wait for Caliptra boot FSM done
mcu->>caliptra: check boot FSM status
end
loop wait for firmware ready
mcu->>caliptra: check firmware ready status
end
note right of mcu: validate firmware at entry point
note right of mcu: set completion milestone
mcu->>mci: trigger warm reset (to FirmwareBootReset)
Failures
On any fatal or non-fatal failure, MCU ROM can use the MCI registers FW_ERROR_FATAL and FW_ERROR_NON_FATAL to assert the appropriate errors.
In addition, SoC-specific failure handling may occur.
There will also be a watchdog timer running to ensure that the MCU is reset if not the ROM flow is not progressing properly.
Security Configuration
The MCU ROM is responsible for configuring and locking security-sensitive MCI registers during the boot process. This section describes the security requirements and verification steps that must be performed.
Configuration Locking
The MCI provides two configuration lock registers:
SS_CONFIG_DONE_STICKY: Locks configuration registers until the next cold reset. This is set during cold boot after all sticky configuration is complete.SS_CONFIG_DONE: Locks configuration registers until the next warm reset. This is set during both cold boot and warm boot flows.
These registers must be set after configuring security-sensitive registers and before signaling fuse write done to Caliptra.
Security Requirement: After setting these registers, MCU ROM must verify that they are actually set by reading them back. If either register fails to set, the ROM must trigger a fatal error (ROM_SOC_SS_CONFIG_DONE_VERIFY_FAILED) and halt. This ensures that the locking mechanism itself has not been tampered with.
Production Debug Unlock PK Hash Verification
The PROD_DEBUG_UNLOCK_PK_HASH_REG registers in MCI store the public key hashes used for production debug unlock authentication. These registers are writable by the MCU but have no access protections before SS_CONFIG_DONE_STICKY is set. This creates a window where another AXI user could potentially manipulate the PK hashes between configuration and locking.
Security Requirement: MCU ROM must verify that the PK hash values written to MCI match the expected values from the fuse controller after both SS_CONFIG_DONE_STICKY and SS_CONFIG_DONE are set. If verification fails, the ROM must trigger a fatal error and halt.
The verification process:
- MCU ROM writes PK hash values from fuses to
PROD_DEBUG_UNLOCK_PK_HASH_REGregisters - MCU ROM sets
SS_CONFIG_DONE_STICKYandSS_CONFIG_DONEto lock the registers - MCU ROM reads back the PK hash register values and compares them against the original fuse values
- If any mismatch is detected, MCU ROM reports a fatal error (
ROM_SOC_PK_HASH_VERIFY_FAILED)
MCU Mailbox AXI User Verification
The MBOX0_VALID_AXI_USER and MBOX1_VALID_AXI_USER registers control which AXI users can access the MCU mailboxes. These registers are locked using MBOX0_AXI_USER_LOCK and MBOX1_AXI_USER_LOCK, which make the corresponding AXI user registers read-only. Note that unlike the PK hash registers, the MBOX registers are not affected by SS_CONFIG_DONE*βonly the LOCK registers control their access.
Security Requirement: MCU ROM must configure the MCU mailbox AXI users, lock them using the LOCK registers, and verify that both the AXI user values and the lock register values match the expected configuration. If verification fails, the ROM must trigger a fatal error and halt. The verification is performed after SS_CONFIG_DONE_STICKY and SS_CONFIG_DONE are set to consolidate all MCI register verification in one place.
The verification process:
- MCU ROM configures
MBOX[0,1]_VALID_AXI_USERregisters with the expected AXI user values - MCU ROM sets
MBOX[0,1]_AXI_USER_LOCKto lock each configured slot (this makes the AXI user registers read-only) - MCU ROM sets
SS_CONFIG_DONE_STICKYandSS_CONFIG_DONE - MCU ROM verifies that both config done registers are actually set
- MCU ROM reads back the
MBOX[0,1]_VALID_AXI_USERregister values and compares them against the expected configuration - MCU ROM reads back the
MBOX[0,1]_AXI_USER_LOCKregister values and verifies they match the expected lock status - If any mismatch is detected in either the AXI user values or lock status, MCU ROM reports a fatal error (
ROM_SOC_MCU_MBOX_AXI_USER_VERIFY_FAILED)
Vendor PK Hash Volatile Lock
The MCU ROM supports locking the selected vendor public key hash slot (and all higher order slots) to prevent post-ROM manipulation. This is controlled by writing to the VENDOR_PK_HASH_VOLATILE_LOCK register.
Strapping Override:
The locking behavior is gated by bit 0 of the hardware strapping register SS_STRAP_GENERIC[3].
- Production Mode (Bit 0 is
0): The ROM automatically applies the volatile lock to the selected key slot index (locking that slot and all higher slots). - Provisioning Mode (Bit 0 is
1): The ROM skips applying the lock, allowing potential post-ROM code to provision higher order hash slots.
Note: In the current version, the lock register remains mutable past the ROM; therefore, the runtime firmware must be trusted to not overwrite the lock and corrupt the hashes.
Warm Reset Considerations
On warm reset, SS_CONFIG_DONE_STICKY remains set from the cold boot, so sticky registers are already locked and do not need to be reconfigured or verified. However, SS_CONFIG_DONE is cleared on warm reset, so:
- MCU ROM must set
SS_CONFIG_DONEafter configuring any non-sticky registers - MCU ROM must verify that
SS_CONFIG_DONEis actually set - Verification of sticky registers (PK hashes, MCU mailbox AXI users) is not required on warm reset since they are already locked