From 3002752a22c875d8b4b4711f56035b6ce60761a9 Mon Sep 17 00:00:00 2001 From: Miguel Osorio Date: Wed, 20 Dec 2023 15:46:22 -0800 Subject: [PATCH] [rom_ext] Add AST patching to rom_ext. Add a mechanism to patch the AST configuration in the rom_ext stage. The data is loaded from the `kFlashCtrlInfoPageFactoryId` info page. The configuration is only applied if the first two words read from flash are not 00s or UINT32_t. Signed-off-by: Miguel Osorio --- sw/device/silicon_creator/lib/drivers/BUILD | 2 + sw/device/silicon_creator/lib/drivers/ast.c | 82 ++++++++++++++++++- sw/device/silicon_creator/lib/drivers/ast.h | 18 ++++ sw/device/silicon_creator/rom_ext/BUILD | 7 +- sw/device/silicon_creator/rom_ext/rom_ext.c | 16 ++-- sw/device/silicon_creator/rom_ext/sival/BUILD | 2 +- 6 files changed, 115 insertions(+), 12 deletions(-) diff --git a/sw/device/silicon_creator/lib/drivers/BUILD b/sw/device/silicon_creator/lib/drivers/BUILD index 6538e1d99100a..58f2b11b15cb3 100644 --- a/sw/device/silicon_creator/lib/drivers/BUILD +++ b/sw/device/silicon_creator/lib/drivers/BUILD @@ -106,9 +106,11 @@ cc_library( srcs = ["ast.c"], hdrs = ["ast.h"], deps = [ + ":flash_ctrl", ":lifecycle", ":otp", "//hw/ip/otp_ctrl/data:otp_ctrl_regs", + "//hw/top_earlgrey/ip/ast/data:ast_regs", "//hw/top_earlgrey/ip/sensor_ctrl/data:sensor_ctrl_regs", "//hw/top_earlgrey/sw/autogen:top_earlgrey", "//sw/device/lib/arch:device", diff --git a/sw/device/silicon_creator/lib/drivers/ast.c b/sw/device/silicon_creator/lib/drivers/ast.c index 606ecbf4cbfe6..6f93a9f3fee01 100644 --- a/sw/device/silicon_creator/lib/drivers/ast.c +++ b/sw/device/silicon_creator/lib/drivers/ast.c @@ -8,8 +8,10 @@ #include "sw/device/lib/base/abs_mmio.h" #include "sw/device/lib/base/csr.h" #include "sw/device/lib/base/multibits.h" +#include "sw/device/silicon_creator/lib/drivers/flash_ctrl.h" #include "sw/device/silicon_creator/lib/drivers/otp.h" +#include "ast_regs.h" #include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" #include "otp_ctrl_regs.h" #include "sensor_ctrl_regs.h" @@ -20,7 +22,29 @@ const uint32_t kAstCheckPollCpuCycles = 10000; #endif enum { - kBase = TOP_EARLGREY_SENSOR_CTRL_AON_BASE_ADDR, + kBaseSensorCtrl = TOP_EARLGREY_SENSOR_CTRL_AON_BASE_ADDR, + kBaseAst = TOP_EARLGREY_AST_BASE_ADDR, + + /** + * AST Calibration Data Size - Bank 0, Page 0 + * + * Number of AST calibration words that will be stored in flash / OTP. + * + * Must match `kFlashInfoAstCalibrationDataSizeIn32BitWords` in + * //sw/device/silicon_creator/manuf/lib/flash_info_fields.h. + */ + kAstCalibrationDataSizeIn32BitWords = + (AST_REGAL_REG_OFFSET + sizeof(uint32_t)) / sizeof(uint32_t), + + /** + * The starting offset of the AST calibration data within the + * `kFlashCtrlInfoPageFactoryId` info flash page. + * + * Must be compatible to the `kFlashInfoFieldAstCalibrationData` byte offset + * in //sw/device/silicon_creator/manuf/lib/flash_info_fields.c. + */ + kAstCalibrationDataInfoFlashByteOffset = + OTP_CTRL_PARAM_DEVICE_ID_SIZE + OTP_CTRL_PARAM_MANUF_STATE_SIZE, }; rom_error_t ast_check(lifecycle_state_t lc_state) { @@ -76,7 +100,8 @@ rom_error_t ast_check(lifecycle_state_t lc_state) { OT_WARN_UNUSED_RESULT static bool done_bit_get(void) { - uint32_t reg = abs_mmio_read32(kBase + SENSOR_CTRL_STATUS_REG_OFFSET); + uint32_t reg = + abs_mmio_read32(kBaseSensorCtrl + SENSOR_CTRL_STATUS_REG_OFFSET); return bitfield_bit32_read(reg, SENSOR_CTRL_STATUS_AST_INIT_DONE_BIT); } @@ -96,3 +121,56 @@ hardened_bool_t ast_init_done(void) { } return res; } + +/** + * Loads AST patch from kFlashCtrlInfoPageFactoryId page. + * + * The `ast_data` offset must be equivalent to the one used in + * //sw/device/silicon_creator/manuf/lib/ast_program.c. + * + * The info flash configuration must also be the same used to program the page, + * otherwise the data read will be garbled. + * + * @param[out] ast_data Pointer to the buffer used to store the data read. + * + * @return The result of the operation. + */ +OT_WARN_UNUSED_RESULT +static rom_error_t load_ast_config_from_flash(uint32_t *ast_data) { + flash_ctrl_info_perms_set(&kFlashCtrlInfoPageFactoryId, + (flash_ctrl_perms_t){ + .read = kMultiBitBool4True, + .write = kMultiBitBool4False, + .erase = kMultiBitBool4False, + }); + flash_ctrl_info_cfg_set(&kFlashCtrlInfoPageFactoryId, + (flash_ctrl_cfg_t){ + .scrambling = kMultiBitBool4False, + .ecc = kMultiBitBool4True, + .he = kMultiBitBool4False, + }); + return flash_ctrl_info_read(&kFlashCtrlInfoPageFactoryId, + kAstCalibrationDataInfoFlashByteOffset, + kAstCalibrationDataSizeIn32BitWords, ast_data); +} + +rom_error_t ast_patch(lifecycle_state_t lc_state) { + uint32_t ast_data[kAstCalibrationDataSizeIn32BitWords]; + HARDENED_RETURN_IF_ERROR(load_ast_config_from_flash(ast_data)); + + // Skip patching logic if either of the first two words don't seem to be + // configured. + if (ast_data[0] == 0 || ast_data[0] == UINT32_MAX) { + return ast_check(lc_state); + } + + if (ast_data[1] == 0 || ast_data[1] == UINT32_MAX) { + return ast_check(lc_state); + } + + for (size_t i = 0; i < kAstCalibrationDataSizeIn32BitWords; ++i) { + abs_mmio_write32(kBaseAst + i * sizeof(uint32_t), ast_data[i]); + } + + return ast_check(lc_state); +} diff --git a/sw/device/silicon_creator/lib/drivers/ast.h b/sw/device/silicon_creator/lib/drivers/ast.h index 93a886555851c..c4e3cab9b69b5 100644 --- a/sw/device/silicon_creator/lib/drivers/ast.h +++ b/sw/device/silicon_creator/lib/drivers/ast.h @@ -16,6 +16,8 @@ extern "C" { /** * Check that the AST is in the expected state. * + * @param lc_state The current life cycle state. + * * @return an error if the AST is not in the expected state. */ OT_WARN_UNUSED_RESULT @@ -30,6 +32,22 @@ rom_error_t ast_check(lifecycle_state_t lc_state); OT_WARN_UNUSED_RESULT hardened_bool_t ast_init_done(void); +/** + * Conditionally patch the AST registers using data stored in an info partition + * used to store manufacturing information. + * + * The patch is skipped if any of the first to AST words stored in the info + * partition are equivalent to 0 or UINT32_MAX. + * + * This function also calls `ast_check()` before returning. + * + * @param lc_state The current life cycle state. + * + * @return an error if the AST is not in the expected state. + */ +OT_WARN_UNUSED_RESULT +rom_error_t ast_patch(lifecycle_state_t lc_state); + #ifdef __cplusplus } #endif diff --git a/sw/device/silicon_creator/rom_ext/BUILD b/sw/device/silicon_creator/rom_ext/BUILD index 80eb391007bd8..0e5930744f4f2 100644 --- a/sw/device/silicon_creator/rom_ext/BUILD +++ b/sw/device/silicon_creator/rom_ext/BUILD @@ -219,6 +219,7 @@ cc_library( "//sw/device/silicon_creator/lib/base:sec_mmio", "//sw/device/silicon_creator/lib/base:static_critical", "//sw/device/silicon_creator/lib/boot_svc:boot_svc_msg", + "//sw/device/silicon_creator/lib/drivers:ast", "//sw/device/silicon_creator/lib/drivers:flash_ctrl", "//sw/device/silicon_creator/lib/drivers:hmac", "//sw/device/silicon_creator/lib/drivers:ibex", @@ -234,14 +235,14 @@ cc_library( ], ) -manifest({ +manifest(d = { "name": "manifest_standard", "address_translation": hex(CONST.HARDENED_FALSE), "identifier": hex(CONST.ROM_EXT), "visibility": ["//visibility:public"], }) -manifest({ +manifest(d = { "name": "manifest_virtual", "address_translation": hex(CONST.HARDENED_TRUE), "identifier": hex(CONST.ROM_EXT), @@ -301,7 +302,7 @@ opentitan_binary( ], ) -manifest({ +manifest(d = { "name": "manifest_bad_address_translation", "address_translation": "0", "identifier": hex(CONST.ROM_EXT), diff --git a/sw/device/silicon_creator/rom_ext/rom_ext.c b/sw/device/silicon_creator/rom_ext/rom_ext.c index 619c85499d6c6..82e2f1e6504b3 100644 --- a/sw/device/silicon_creator/rom_ext/rom_ext.c +++ b/sw/device/silicon_creator/rom_ext/rom_ext.c @@ -21,6 +21,7 @@ #include "sw/device/silicon_creator/lib/boot_svc/boot_svc_header.h" #include "sw/device/silicon_creator/lib/boot_svc/boot_svc_msg.h" #include "sw/device/silicon_creator/lib/dbg_print.h" +#include "sw/device/silicon_creator/lib/drivers/ast.h" #include "sw/device/silicon_creator/lib/drivers/flash_ctrl.h" #include "sw/device/silicon_creator/lib/drivers/hmac.h" #include "sw/device/silicon_creator/lib/drivers/ibex.h" @@ -106,16 +107,19 @@ void rom_ext_check_rom_expectations(void) { sec_mmio_check_values(rnd_uint32()); } -void rom_ext_init(void) { +OT_WARN_UNUSED_RESULT +static rom_error_t rom_ext_init(void) { sec_mmio_next_stage_init(); - lc_state = lifecycle_state_get(); - - // TODO: Verify ePMP expectations from ROM. - pinmux_init(); // Configure UART0 as stdout. uart_init(kUartNCOValue); + + // TODO: Verify ePMP expectations from ROM. + + // Conditionally patch AST and check that it is in the expected state. + HARDENED_RETURN_IF_ERROR(ast_patch(lc_state)); + return kErrorOk; } void rom_ext_sram_exec(hardened_bool_t enable) { @@ -530,7 +534,7 @@ static rom_error_t rom_ext_try_boot(void) { void rom_ext_main(void) { rom_ext_check_rom_expectations(); - rom_ext_init(); + SHUTDOWN_IF_ERROR(rom_ext_init()); dbg_printf("Starting ROM_EXT\r\n"); rom_error_t error = rom_ext_try_boot(); // If the boot failed, enter bootstrap if it's enabled. diff --git a/sw/device/silicon_creator/rom_ext/sival/BUILD b/sw/device/silicon_creator/rom_ext/sival/BUILD index 2265e79606795..9bb129d2e0954 100644 --- a/sw/device/silicon_creator/rom_ext/sival/BUILD +++ b/sw/device/silicon_creator/rom_ext/sival/BUILD @@ -17,7 +17,7 @@ LINK_ORDER = [ "$(location //sw/device/lib/crt)", ] -manifest({ +manifest(d = { "name": "manifest_sival", "address_translation": hex(CONST.HARDENED_FALSE), "identifier": hex(CONST.ROM_EXT),