diff --git a/rom/dev/README.md b/rom/dev/README.md index 21b3d8800a..d552030539 100644 --- a/rom/dev/README.md +++ b/rom/dev/README.md @@ -237,17 +237,16 @@ The following flows are conducted when the ROM is operating in the manufacturing #### UDS Provisioning 1. On reset, the ROM checks if the `UDS_PROGRAM_REQ` bit in the `SS_DBG_MANUF_SERVICE_REG_REQ` register is set. If the bit is set, ROM initiates the UDS seed programming flow by setting the `UDS_PROGRAM_IN_PROGRESS` bit in the `SS_DBG_MANUF_SERVICE_REG_RSP` register. If the flow fails at some point past reading the REQ bits, the flow will be aborted and an error returned. -2. ROM then retrieves a 512-bit value from the iTRNG, the UDS Seed programming base address from the `SS_UDS_SEED_PROGRAMMING_BASE_ADDR_L` and `SS_UDS_SEED_PROGRAMMING_BASE_ADDR_H` registers and the Fuse Controller's base address from the `SS_OTP_FC_BASE_ADDR_L` and `SS_OTP_FC_BASE_ADDR_H` registers. +2. ROM then retrieves a 512-bit value from the iTRNG, the UDS Seed programming base address from the `SS_UDS_SEED_BASE_ADDR_L` and `SS_UDS_SEED_BASE_ADDR_H` registers and the Fuse Controller's base address from the `SS_OTP_FC_BASE_ADDR_L` and `SS_OTP_FC_BASE_ADDR_H` registers. 3. ROM then retrieves the UDS granularity from the `CPTRA_HW_CONFIG` register Bit6 to learn if the fuse row is accessible with 32-bit or 64-bit granularity. 4. ROM then performs the following steps until all the 512 bits of the UDS seed are programmed: - 1. The ROM verifies the idle state of the DAI by reading the `STATUS` register `DAI_IDLE` bit (Bit 14) of the Fuse Controller, located at offset 0x10 from the Fuse Controller's base address. + 1. The ROM verifies the idle state of the DAI by reading the `STATUS` register `DAI_IDLE` bit (Bit-21) of the Fuse Controller, located at offset 0x10 from the Fuse Controller's base address. 2. If the granularity is 32-bit, the ROM writes the next word from the UDS seed to the `DIRECT_ACCESS_WDATA_0` register. If the granularity is 64-bit, the ROM writes the next two words to `the DIRECT_ACCESS_WDATA_0` and `DIRECT_ACCESS_WDATA_1` registers, located at offsets 0x44 and 0x48 respectively from the Fuse Controller's base address. 3. The ROM writes the lower 32 bits of the UDS Seed programming base address to the `DIRECT_ACCESS_ADDRESS` register at offset 0x40. 4. The ROM triggers the UDS seed write command by writing 0x2 to the `DIRECT_ACCESS_CMD` register at offset 0x3C. - 5. [OPEN] Handle DAI error. - 6. The ROM increments the `DIRECT_ACCESS_ADDRESS` register by 4 for 32-bit granularity or 8 for 64-bit granularity and repeats the process for the remaining words of the UDS seed. + 5. The ROM increments the `DIRECT_ACCESS_ADDRESS` register by 4 for 32-bit granularity or 8 for 64-bit granularity and repeats the process for the remaining words of the UDS seed. 5. The ROM continuously polls the Fuse Controller's `STATUS` register until the DAI state returns to idle. diff --git a/rom/dev/src/flow/uds_programming.rs b/rom/dev/src/flow/uds_programming.rs index ccd5543d5f..082804829d 100644 --- a/rom/dev/src/flow/uds_programming.rs +++ b/rom/dev/src/flow/uds_programming.rs @@ -18,11 +18,11 @@ use caliptra_common::cprintln; use caliptra_drivers::{AxiAddr, CaliptraError, CaliptraResult, Lifecycle}; const STATUS_REG_OFFSET: u64 = 0x10; -const DIRECT_ACCESS_WDATA_0_REG_OFFSET: u64 = 0x44; -const DIRECT_ACCESS_WDATA_1_REG_OFFSET: u64 = 0x48; -const DIRECT_ACCESS_ADDRESS_REG_OFFSET: u64 = 0x40; -const DIRECT_ACCESS_CMD_REG_OFFSET: u64 = 0x3C; -const DAI_IDLE_BIT: u32 = 1 << 14; +const DIRECT_ACCESS_WDATA_0_REG_OFFSET: u64 = 0x60; +const DIRECT_ACCESS_WDATA_1_REG_OFFSET: u64 = 0x64; +const DIRECT_ACCESS_ADDRESS_REG_OFFSET: u64 = 0x5C; +const DIRECT_ACCESS_CMD_REG_OFFSET: u64 = 0x58; +const DAI_IDLE_BIT: u32 = 1 << 21; const DIRECT_ACCESS_CMD_WRITE: u32 = 0x2; const DIRECT_ACCESS_CMD_DIGEST: u32 = 0x4; @@ -33,8 +33,6 @@ impl UdsProgrammingFlow { #[inline(never)] #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] pub fn program_uds(env: &mut RomEnv) -> CaliptraResult<()> { - cprintln!("[uds] ++"); - // Check if UDS programming is requested. if !env.soc_ifc.uds_program_req() { return Ok(()); @@ -55,6 +53,7 @@ impl UdsProgrammingFlow { } // Update the UDS programming state. + cprintln!("[uds] Updating the UDS programming state"); env.soc_ifc .set_uds_programming_flow_state(true /* in_progress */); @@ -85,13 +84,15 @@ impl UdsProgrammingFlow { while { let status_value = env.dma.read_dword(AxiAddr::from(status_reg_addr))?; (status_value & DAI_IDLE_BIT) == 0 - } { - // [TODO][CAP2] Handle errors. - } + } {} // Write the UDS seed to the DIRECT_ACCESS_WDATA_0 register // and the DIRECT_ACCESS_WDATA_1 register (for 64-bit granularity). let wdata_0 = seed[seed_index]; + cprintln!( + "[uds] Writing the UDS seed to the DIRECT_ACCESS_WDATA_0: {:x} register, wdata_0: {:#x}", + direct_access_wdata_0_reg_addr, wdata_0 + ); env.dma .write_dword(AxiAddr::from(direct_access_wdata_0_reg_addr), wdata_0)?; if uds_fuse_row_granularity_64 { @@ -100,6 +101,10 @@ impl UdsProgrammingFlow { } // 64-bit granularity let wdata_1 = seed[seed_index + 1]; + cprintln!( + "[uds] Writing the UDS seed to the DIRECT_ACCESS_WDATA_1: {:x} register, wdata_1: {:#x}", + direct_access_wdata_1_reg_addr, wdata_1 + ); env.dma .write_dword(AxiAddr::from(direct_access_wdata_1_reg_addr), wdata_1)?; seed_index += 2; @@ -109,12 +114,16 @@ impl UdsProgrammingFlow { } // Write the lower 32 bits of the UDS Seed programming destination address to the DIRECT_ACCESS_ADDRESS register. + cprintln!("[uds] Writing the lower 32 bits of the UDS Seed programming destination address: {:x} to the DIRECT_ACCESS_ADDRESS register: {:x}", + uds_seed_dest_address, direct_access_address_reg_addr); env.dma.write_dword( AxiAddr::from(direct_access_address_reg_addr), uds_seed_dest_address, )?; // Trigger the UDS seed write command + cprintln!("[uds] Triggering the UDS seed write command, direct_access_cmd_reg_addr: {:x}, command: {:#x}", + direct_access_cmd_reg_addr, DIRECT_ACCESS_CMD_WRITE); env.dma.write_dword( AxiAddr::from(direct_access_cmd_reg_addr), DIRECT_ACCESS_CMD_WRITE, @@ -133,18 +142,19 @@ impl UdsProgrammingFlow { while { let status_value = env.dma.read_dword(AxiAddr::from(status_reg_addr))?; (status_value & DAI_IDLE_BIT) == 0 - } { - // [TODO][CAP2] Handle errors. - } + } {} // Write the lower 32 bits of the UDS Seed programming base address to the DIRECT_ACCESS_ADDRESS register. - cprintln!("[uds] Triggering the partition digest operation"); + cprintln!("[uds] Triggering the partition digest operation, direct_access_address_reg_addr: {:x}, uds_seed_dest_address: {:#x}", + direct_access_address_reg_addr, env.soc_ifc.uds_seed_dest_base_addr_low()); env.dma.write_dword( AxiAddr::from(direct_access_address_reg_addr), env.soc_ifc.uds_seed_dest_base_addr_low(), )?; // Trigger the digest calculation command + cprintln!("[uds] Triggering the digest calculation command, direct_access_cmd_reg_addr: {:x}, command: {:#x}", + direct_access_cmd_reg_addr, DIRECT_ACCESS_CMD_DIGEST); env.dma.write_dword( AxiAddr::from(direct_access_cmd_reg_addr), DIRECT_ACCESS_CMD_DIGEST, @@ -154,17 +164,17 @@ impl UdsProgrammingFlow { while { let status_value = env.dma.read_dword(AxiAddr::from(status_reg_addr))?; (status_value & DAI_IDLE_BIT) == 0 - } { - // [TODO][CAP2] Handle errors. - } + } {} Ok(()) })(); // Set the UDS programming result. + cprintln!("[uds] Setting the UDS programming result"); env.soc_ifc.set_uds_programming_flow_status(result.is_ok()); // Update the UDS programming state. + cprintln!("[uds] Updating the UDS programming state"); env.soc_ifc .set_uds_programming_flow_state(false /* in_progress */);