From 1d17e9274cab1cfc3acb3a1c707749fb71fd40b7 Mon Sep 17 00:00:00 2001 From: Alex Jones Date: Tue, 7 Oct 2025 10:30:21 +0100 Subject: [PATCH 1/2] [ot] hw/opentitan: ot_common: Add register span macros Adds macros for generic computing of the size of register spans for OpenTitan multi registers, which can be used to e.g. make static assertions to ensure that the size of macros matches the size of buffers being used. Co-authored-by: Emmanuel Blot Signed-off-by: Alex Jones --- include/hw/opentitan/ot_common.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/hw/opentitan/ot_common.h b/include/hw/opentitan/ot_common.h index 47b26cae35778..b53a5f937edc5 100644 --- a/include/hw/opentitan/ot_common.h +++ b/include/hw/opentitan/ot_common.h @@ -43,6 +43,15 @@ #define OT_TL_UL_D_WIDTH_BITS 32u #define OT_TL_UL_D_WIDTH_BYTES ((OT_TL_UL_D_WIDTH_BITS) / 8u) +/* ------------------------------------------------------------------------ */ +/* Register Span Definitions */ +/* ------------------------------------------------------------------------ */ + +#define OT_REG_NAME_IDX(_n_, _i_) (R_##_n_##_##_i_) +#define OT_REG_COUNT(_n_, _l_) \ + (OT_REG_NAME_IDX(_n_, _l_) - OT_REG_NAME_IDX(_n_, 0) + 1u) +#define OT_REG_SPAN(_n_, _l_) (OT_REG_COUNT(_n_, _l_) * sizeof(uint32_t)) + /* ------------------------------------------------------------------------ */ /* Multi-bit boolean values */ /* ------------------------------------------------------------------------ */ From f8469a9cb5c1e2f3a7f45846bafe6ab3faefa7a0 Mon Sep 17 00:00:00 2001 From: Alex Jones Date: Fri, 3 Oct 2025 17:31:20 +0100 Subject: [PATCH 2/2] [ot] hw/opentitan: ot_lc_ctrl: Fix HW_CFG load memcpy size calculation These `memcpy`s were accidentally using the size of the dereferenced byte array (i.e., always just 1 byte), and so were only copying the first byte of the HW_CFG device ID and manufacturing state that were being loaded from the OTP. Also add some local calculations and static assertions to check that the HW_CFG value sizes that are given do not become out of sync with the size of the registers. Signed-off-by: Alex Jones --- hw/opentitan/ot_lc_ctrl.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/hw/opentitan/ot_lc_ctrl.c b/hw/opentitan/ot_lc_ctrl.c index f961061605985..cba7905e304b2 100644 --- a/hw/opentitan/ot_lc_ctrl.c +++ b/hw/opentitan/ot_lc_ctrl.c @@ -146,6 +146,9 @@ REG32(MANUF_STATE_7, 0x88u) #define LC_TOKEN_WIDTH 16u /* 128 bits */ #define LC_TOKEN_DWORDS (LC_TOKEN_WIDTH / sizeof(uint64_t)) +#define LC_DEV_ID_WIDTH OT_REG_SPAN(DEVICE_ID, 7) +#define LC_MANUF_STATE_WIDTH OT_REG_SPAN(MANUF_STATE, 7) + #define REG_NAME_ENTRY(_reg_) [R_##_reg_] = stringify(_reg_) static const char *REG_NAMES[REGS_COUNT] = { REG_NAME_ENTRY(ALERT_TEST), @@ -435,7 +438,11 @@ typedef struct { } OtLcCtrlTransitionDesc; static_assert(sizeof(OtOTPTokenValue) == LC_TOKEN_WIDTH, - "Unexpected LC TOLEN WIDTH"); + "Unexpected LC Token width"); +static_assert(OT_OTP_HWCFG_DEVICE_ID_BYTES == LC_DEV_ID_WIDTH, + "Unexpected LC Device ID width"); +static_assert(OT_OTP_HWCFG_MANUF_STATE_BYTES == LC_MANUF_STATE_WIDTH, + "Unexpected LC Manufacturing State width"); #define KECCAK_STATE_BITS 1600u #define KECCAK_STATE_BYTES (KECCAK_STATE_BITS / 8u) @@ -1211,10 +1218,14 @@ static void ot_lc_ctrl_load_otp_hw_cfg(OtLcCtrlState *s) OtOTPClass *oc = OBJECT_GET_CLASS(OtOTPClass, s->otp_ctrl, TYPE_OT_OTP); const OtOTPHWCfg *hw_cfg = oc->get_hw_cfg(s->otp_ctrl); - memcpy(&s->regs[R_DEVICE_ID_0], &hw_cfg->device_id[0], - sizeof(*hw_cfg->device_id)); + static_assert(sizeof(hw_cfg->device_id) == LC_DEV_ID_WIDTH, + "HW_CFG Device ID size does not match size in registers"); + memcpy(&s->regs[R_DEVICE_ID_0], &hw_cfg->device_id[0], LC_DEV_ID_WIDTH); + + static_assert(sizeof(hw_cfg->manuf_state) == LC_MANUF_STATE_WIDTH, + "HW_CFG Manuf State size does not match size in registers"); memcpy(&s->regs[R_MANUF_STATE_0], &hw_cfg->manuf_state[0], - sizeof(*hw_cfg->manuf_state)); + LC_MANUF_STATE_WIDTH); if (!s->socdbg) { return;