diff --git a/hw/opentitan/Kconfig b/hw/opentitan/Kconfig index ad2b5dd61001f..d4c89b620571f 100644 --- a/hw/opentitan/Kconfig +++ b/hw/opentitan/Kconfig @@ -55,6 +55,7 @@ config OT_EDN config OT_ENTROPY_SRC select OT_NOISE_SRC + select OT_OTP_IF bool config OT_FLASH @@ -89,6 +90,7 @@ config OT_KEY_SINK config OT_KEYMGR select OT_KEY_SINK select OT_LC_CTRL + select OT_OTP_IF select OT_ROM_CTRL bool @@ -103,6 +105,7 @@ config OT_KMAC bool config OT_LC_CTRL + select OT_OTP_IF bool config OT_MBX @@ -117,23 +120,25 @@ config OT_OTBN select OT_BIGNUMBER bool -config OT_OTP - select OT_OTP_BE_IF - config OT_OTP_BE_IF bool config OT_OTP_DJ - select OT_OTP + select OT_OTP_IF select OT_PRESENT bool config OT_OTP_EG - select OT_OTP + select OT_OTP_IF + select OT_PRESENT + bool + +config OT_OTP_IF bool config OT_OTP_OT_BE select OT_OTP_BE_IF + select OT_OTP_IF bool config OT_PINMUX_DJ @@ -184,6 +189,7 @@ config OT_SPI_HOST config OT_SRAM_CTRL select OT_PRESENT + select OT_OTP_IF bool config OT_TIMER diff --git a/hw/opentitan/meson.build b/hw/opentitan/meson.build index 2049687268bc3..655e9e49c06f9 100644 --- a/hw/opentitan/meson.build +++ b/hw/opentitan/meson.build @@ -34,10 +34,10 @@ system_ss.add(when: 'CONFIG_OT_LC_CTRL', if_true: files('ot_lc_ctrl.c')) system_ss.add(when: 'CONFIG_OT_MBX', if_true: files('ot_mbx.c')) system_ss.add(when: 'CONFIG_OT_NOISE_SRC', if_true: files('ot_noise_src.c')) system_ss.add(when: 'CONFIG_OT_OTBN', if_true: files('ot_otbn.c')) -system_ss.add(when: 'CONFIG_OT_OTP', if_true: files('ot_otp.c')) system_ss.add(when: 'CONFIG_OT_OTP_BE_IF', if_true: files('ot_otp_be_if.c')) system_ss.add(when: 'CONFIG_OT_OTP_DJ', if_true: files('ot_otp_dj.c')) system_ss.add(when: 'CONFIG_OT_OTP_EG', if_true: files('ot_otp_eg.c')) +system_ss.add(when: 'CONFIG_OT_OTP_IF', if_true: files('ot_otp_if.c')) system_ss.add(when: 'CONFIG_OT_OTP_OT_BE', if_true: files('ot_otp_ot_be.c')) system_ss.add(when: 'CONFIG_OT_PINMUX_EG', if_true: files('ot_pinmux_eg.c')) system_ss.add(when: 'CONFIG_OT_PINMUX_DJ', if_true: files('ot_pinmux_dj.c')) diff --git a/hw/opentitan/ot_csrng.c b/hw/opentitan/ot_csrng.c index f21cf113f3d8f..07a292ec3d0c2 100644 --- a/hw/opentitan/ot_csrng.c +++ b/hw/opentitan/ot_csrng.c @@ -39,7 +39,7 @@ #include "hw/opentitan/ot_csrng.h" #include "hw/opentitan/ot_entropy_src.h" #include "hw/opentitan/ot_fifo32.h" -#include "hw/opentitan/ot_otp.h" +#include "hw/opentitan/ot_otp_if.h" #include "hw/qdev-properties.h" #include "hw/registerfields.h" #include "hw/riscv/ibex_common.h" @@ -353,7 +353,7 @@ struct OtCSRNGState { OtCSRNGQueue cmd_requests; OtEntropySrcState *entropy_src; - OtOTPState *otp_ctrl; + DeviceState *otp_ctrl; }; /* clang-format off */ @@ -1822,9 +1822,10 @@ static void ot_csrng_regs_write(void *opaque, hwaddr addr, uint64_t val64, if (change) { xtrace_ot_csrng_info("handling CTRL change", val32); ot_csrng_handle_enable(s); - OtOTPClass *oc = - OBJECT_GET_CLASS(OtOTPClass, s->otp_ctrl, TYPE_OT_OTP); - const OtOTPHWCfg *hw_cfg = oc->get_hw_cfg(s->otp_ctrl); + + OtOTPIfClass *oc = OT_OTP_IF_GET_CLASS(s->otp_ctrl); + OtOTPIf *oi = OT_OTP_IF(s->otp_ctrl); + const OtOTPHWCfg *hw_cfg = oc->get_hw_cfg(oi); g_assert(hw_cfg); if (hw_cfg->en_csrng_sw_app_read_mb8 == OT_MULTIBITBOOL8_TRUE) { uint32_t sw_app_en = FIELD_EX32(val32, CTRL, SW_APP_ENABLE); @@ -1938,8 +1939,8 @@ static void ot_csrng_regs_write(void *opaque, hwaddr addr, uint64_t val64, static Property ot_csrng_properties[] = { DEFINE_PROP_LINK("entropy-src", OtCSRNGState, entropy_src, TYPE_OT_ENTROPY_SRC, OtEntropySrcState *), - DEFINE_PROP_LINK("otp-ctrl", OtCSRNGState, otp_ctrl, TYPE_OT_OTP, - OtOTPState *), + DEFINE_PROP_LINK("otp-ctrl", OtCSRNGState, otp_ctrl, TYPE_OT_OTP_IF, + DeviceState *), DEFINE_PROP_END_OF_LIST(), }; @@ -2013,6 +2014,8 @@ static void ot_csrng_realize(DeviceState *dev, Error **errp) g_assert(s->entropy_src); g_assert(s->otp_ctrl); + + (void)OBJECT_CHECK(OtOTPIf, s->otp_ctrl, TYPE_OT_OTP_IF); } static void ot_csrng_init(Object *obj) diff --git a/hw/opentitan/ot_entropy_src.c b/hw/opentitan/ot_entropy_src.c index 2bfee3f802c8b..1cfe56e1ef85c 100644 --- a/hw/opentitan/ot_entropy_src.c +++ b/hw/opentitan/ot_entropy_src.c @@ -1,5 +1,5 @@ /* - * QEMU OpenTitan Earlgrey 1.0.0 Entropy Source device + * QEMU OpenTitan Earlgrey Entropy Source device * * Copyright (c) 2023-2025 Rivos, Inc. * Copyright (c) 2025 lowRISC contributors. @@ -43,7 +43,6 @@ #include "hw/opentitan/ot_entropy_src.h" #include "hw/opentitan/ot_fifo32.h" #include "hw/opentitan/ot_noise_src.h" -#include "hw/opentitan/ot_otp.h" #include "hw/qdev-properties.h" #include "hw/registerfields.h" #include "hw/riscv/ibex_common.h" @@ -489,7 +488,6 @@ struct OtEntropySrcState { char *ot_id; unsigned version; /* emulated version */ DeviceState *noise_src; - OtOTPState *otp_ctrl; }; static const uint16_t OtEDNFsmStateCode[] = { @@ -1803,8 +1801,6 @@ static Property ot_entropy_src_properties[] = { DEFINE_PROP_UINT32("version", OtEntropySrcState, version, 0), DEFINE_PROP_LINK("noise-src", OtEntropySrcState, noise_src, TYPE_DEVICE, DeviceState *), - DEFINE_PROP_LINK("otp-ctrl", OtEntropySrcState, otp_ctrl, TYPE_OT_OTP, - OtOTPState *), DEFINE_PROP_END_OF_LIST(), }; @@ -1901,7 +1897,6 @@ static void ot_entropy_src_realize(DeviceState *dev, Error **errp) /* emulated version should be specified */ g_assert(s->version > 0); g_assert(s->noise_src); - g_assert(s->otp_ctrl); (void)OBJECT_CHECK(OtNoiseSrcIf, s->noise_src, TYPE_OT_NOISE_SRC_IF); } diff --git a/hw/opentitan/ot_keymgr.c b/hw/opentitan/ot_keymgr.c index a4b59f803b422..7eddcf2588416 100644 --- a/hw/opentitan/ot_keymgr.c +++ b/hw/opentitan/ot_keymgr.c @@ -49,7 +49,7 @@ #include "hw/opentitan/ot_kmac.h" #include "hw/opentitan/ot_lc_ctrl.h" #include "hw/opentitan/ot_otbn.h" -#include "hw/opentitan/ot_otp.h" +#include "hw/opentitan/ot_otp_if.h" #include "hw/opentitan/ot_prng.h" #include "hw/opentitan/ot_rom_ctrl.h" #include "hw/qdev-properties.h" @@ -452,7 +452,7 @@ typedef struct OtKeyMgrState { uint8_t kmac_app; OtFlashState *flash_ctrl; OtLcCtrlState *lc_ctrl; - OtOTPState *otp_ctrl; + DeviceState *otp_ctrl; OtRomCtrlState *rom_ctrl; DeviceState *key_sinks[KEYMGR_KEY_SINK_COUNT]; char *seed_xstrs[KEYMGR_SEED_COUNT]; @@ -1068,8 +1068,9 @@ static size_t ot_keymgr_kdf_append_km_div(OtKeyMgrState *s) static size_t ot_keymgr_kdf_append_dev_id(OtKeyMgrState *s) { - OtOTPClass *otp_oc = OBJECT_GET_CLASS(OtOTPClass, s->otp_ctrl, TYPE_OT_OTP); - const OtOTPHWCfg *hw_cfg = otp_oc->get_hw_cfg(s->otp_ctrl); + OtOTPIfClass *oc = OT_OTP_IF_GET_CLASS(s->otp_ctrl); + OtOTPIf *oi = OT_OTP_IF(s->otp_ctrl); + const OtOTPHWCfg *hw_cfg = oc->get_hw_cfg(oi); ot_keymgr_kdf_push_bytes(s, hw_cfg->device_id, OT_OTP_HWCFG_DEVICE_ID_BYTES); @@ -1193,12 +1194,12 @@ static size_t ot_keymgr_kdf_append_key_version(OtKeyMgrState *s) static void ot_keymgr_get_root_key(OtKeyMgrState *s, OtOTPKeyMgrSecret *share0, OtOTPKeyMgrSecret *share1) { - OtOTPClass *oc = OBJECT_GET_CLASS(OtOTPClass, s->otp_ctrl, TYPE_OT_OTP); - g_assert(oc); - oc->get_keymgr_secret(s->otp_ctrl, - OTP_KEYMGR_SECRET_CREATOR_ROOT_KEY_SHARE0, share0); - oc->get_keymgr_secret(s->otp_ctrl, - OTP_KEYMGR_SECRET_CREATOR_ROOT_KEY_SHARE1, share1); + OtOTPIfClass *oc = OT_OTP_IF_GET_CLASS(s->otp_ctrl); + OtOTPIf *oi = OT_OTP_IF(s->otp_ctrl); + oc->get_keymgr_secret(oi, OTP_KEYMGR_SECRET_CREATOR_ROOT_KEY_SHARE0, + share0); + oc->get_keymgr_secret(oi, OTP_KEYMGR_SECRET_CREATOR_ROOT_KEY_SHARE1, + share1); if (trace_event_get_state(TRACE_OT_KEYMGR_DUMP_CREATOR_ROOT_KEY)) { trace_ot_keymgr_dump_creator_root_key( @@ -2332,8 +2333,8 @@ static Property ot_keymgr_properties[] = { DEFINE_PROP_UINT8("kmac-app", OtKeyMgrState, kmac_app, UINT8_MAX), DEFINE_PROP_LINK("lc-ctrl", OtKeyMgrState, lc_ctrl, TYPE_OT_LC_CTRL, OtLcCtrlState *), - DEFINE_PROP_LINK("otp-ctrl", OtKeyMgrState, otp_ctrl, TYPE_OT_OTP, - OtOTPState *), + DEFINE_PROP_LINK("otp-ctrl", OtKeyMgrState, otp_ctrl, TYPE_OT_OTP_IF, + DeviceState *), DEFINE_PROP_LINK("rom_ctrl", OtKeyMgrState, rom_ctrl, TYPE_OT_ROM_CTRL, OtRomCtrlState *), DEFINE_PROP_LINK("aes", OtKeyMgrState, key_sinks[KEYMGR_KEY_SINK_AES], @@ -2399,6 +2400,8 @@ static void ot_keymgr_reset_enter(Object *obj, ResetType type) g_assert(s->otp_ctrl); g_assert(s->rom_ctrl); + (void)OBJECT_CHECK(OtOTPIf, s->otp_ctrl, TYPE_OT_OTP_IF); + /* reset registers */ memset(s->regs, 0u, sizeof(s->regs)); s->regs[R_CFG_REGWEN] = 0x1u; diff --git a/hw/opentitan/ot_keymgr_dpe.c b/hw/opentitan/ot_keymgr_dpe.c index 422607e2df221..780cbb8becf77 100644 --- a/hw/opentitan/ot_keymgr_dpe.c +++ b/hw/opentitan/ot_keymgr_dpe.c @@ -41,7 +41,7 @@ #include "hw/opentitan/ot_kmac.h" #include "hw/opentitan/ot_lc_ctrl.h" #include "hw/opentitan/ot_otbn.h" -#include "hw/opentitan/ot_otp.h" +#include "hw/opentitan/ot_otp_if.h" #include "hw/opentitan/ot_prng.h" #include "hw/opentitan/ot_rom_ctrl.h" #include "hw/qdev-properties.h" @@ -410,7 +410,7 @@ typedef struct OtKeyMgrDpeState { OtKMACState *kmac; uint8_t kmac_app; OtLcCtrlState *lc_ctrl; - OtOTPState *otp; + DeviceState *otp_ctrl; OtRomCtrlState *rom_ctrl[NUM_ROM_DIGEST_INPUTS]; DeviceState *key_sinks[KEYMGR_DPE_KEY_SINK_COUNT]; char *seed_xstrs[KEYMGR_DPE_SEED_COUNT]; @@ -1027,9 +1027,9 @@ ot_keymgr_dpe_kdf_append_creator_seed(OtKeyMgrDpeState *s, bool *dvalid) { OtOTPKeyMgrSecret secret = { 0u }; - OtOTPClass *otp_oc = OBJECT_GET_CLASS(OtOTPClass, s->otp, TYPE_OT_OTP); - g_assert(otp_oc); - otp_oc->get_keymgr_secret(s->otp, OTP_KEYMGR_SECRET_CREATOR_SEED, &secret); + OtOTPIfClass *oc = OT_OTP_IF_GET_CLASS(s->otp_ctrl); + OtOTPIf *oi = OT_OTP_IF(s->otp_ctrl); + oc->get_keymgr_secret(oi, OTP_KEYMGR_SECRET_CREATOR_SEED, &secret); ot_keymgr_dpe_kdf_push_bytes(s, secret.secret, OT_OTP_KEYMGR_SECRET_SIZE); *dvalid &= ot_keymgr_dpe_valid_data_check(secret.secret, @@ -1076,8 +1076,9 @@ static size_t ot_keymgr_dpe_kdf_append_km_div(OtKeyMgrDpeState *s, bool *dvalid) static size_t ot_keymgr_dpe_kdf_append_dev_id(OtKeyMgrDpeState *s, bool *dvalid) { - OtOTPClass *otp_oc = OBJECT_GET_CLASS(OtOTPClass, s->otp, TYPE_OT_OTP); - const OtOTPHWCfg *hw_cfg = otp_oc->get_hw_cfg(s->otp); + OtOTPIfClass *oc = OT_OTP_IF_GET_CLASS(s->otp_ctrl); + OtOTPIf *oi = OT_OTP_IF(s->otp_ctrl); + const OtOTPHWCfg *hw_cfg = oc->get_hw_cfg(oi); ot_keymgr_dpe_kdf_push_bytes(s, hw_cfg->device_id, OT_OTP_HWCFG_DEVICE_ID_BYTES); @@ -1106,8 +1107,9 @@ ot_keymgr_dpe_kdf_append_owner_seed(OtKeyMgrDpeState *s, bool *dvalid) { OtOTPKeyMgrSecret secret = { 0u }; - OtOTPClass *otp_oc = OBJECT_GET_CLASS(OtOTPClass, s->otp, TYPE_OT_OTP); - otp_oc->get_keymgr_secret(s->otp, OTP_KEYMGR_SECRET_OWNER_SEED, &secret); + OtOTPIfClass *oc = OT_OTP_IF_GET_CLASS(s->otp_ctrl); + OtOTPIf *oi = OT_OTP_IF(s->otp_ctrl); + oc->get_keymgr_secret(oi, OTP_KEYMGR_SECRET_OWNER_SEED, &secret); ot_keymgr_dpe_kdf_push_bytes(s, secret.secret, OT_OTP_KEYMGR_SECRET_SIZE); *dvalid &= ot_keymgr_dpe_valid_data_check(secret.secret, @@ -1445,11 +1447,11 @@ static void ot_keymgr_dpe_xchange_main_fsm_state( static void ot_keymgr_dpe_get_root_key( OtKeyMgrDpeState *s, OtOTPKeyMgrSecret *share0, OtOTPKeyMgrSecret *share1) { - OtOTPClass *oc = OBJECT_GET_CLASS(OtOTPClass, s->otp, TYPE_OT_OTP); - g_assert(oc); - oc->get_keymgr_secret(s->otp, OTP_KEYMGR_SECRET_CREATOR_ROOT_KEY_SHARE0, + OtOTPIfClass *oc = OT_OTP_IF_GET_CLASS(s->otp_ctrl); + OtOTPIf *oi = OT_OTP_IF(s->otp_ctrl); + oc->get_keymgr_secret(oi, OTP_KEYMGR_SECRET_CREATOR_ROOT_KEY_SHARE0, share0); - oc->get_keymgr_secret(s->otp, OTP_KEYMGR_SECRET_CREATOR_ROOT_KEY_SHARE1, + oc->get_keymgr_secret(oi, OTP_KEYMGR_SECRET_CREATOR_ROOT_KEY_SHARE1, share1); if (trace_event_get_state(TRACE_OT_KEYMGR_DPE_DUMP_CREATOR_ROOT_KEY)) { @@ -2004,8 +2006,8 @@ static Property ot_keymgr_dpe_properties[] = { DEFINE_PROP_UINT8("kmac-app", OtKeyMgrDpeState, kmac_app, UINT8_MAX), DEFINE_PROP_LINK("lc-ctrl", OtKeyMgrDpeState, lc_ctrl, TYPE_OT_LC_CTRL, OtLcCtrlState *), - DEFINE_PROP_LINK("otp-ctrl", OtKeyMgrDpeState, otp, TYPE_OT_OTP, - OtOTPState *), + DEFINE_PROP_LINK("otp-ctrl", OtKeyMgrDpeState, otp_ctrl, TYPE_OT_OTP_IF, + DeviceState *), DEFINE_PROP_LINK("rom0", OtKeyMgrDpeState, rom_ctrl[0], TYPE_OT_ROM_CTRL, OtRomCtrlState *), DEFINE_PROP_LINK("rom1", OtKeyMgrDpeState, rom_ctrl[1], TYPE_OT_ROM_CTRL, @@ -2061,10 +2063,12 @@ static void ot_keymgr_dpe_reset_enter(Object *obj, ResetType type) g_assert(s->kmac); g_assert(s->kmac_app != UINT8_MAX); g_assert(s->lc_ctrl); - g_assert(s->otp); + g_assert(s->otp_ctrl); g_assert(s->rom_ctrl[0]); g_assert(s->rom_ctrl[1]); + (void)OBJECT_CHECK(OtOTPIf, s->otp_ctrl, TYPE_OT_OTP_IF); + s->key_sinks[KEYMGR_DPE_KEY_SINK_KMAC] = DEVICE(s->kmac); /* reset registers */ diff --git a/hw/opentitan/ot_lc_ctrl.c b/hw/opentitan/ot_lc_ctrl.c index 25be5342bd50d..d2c79edeea2d0 100644 --- a/hw/opentitan/ot_lc_ctrl.c +++ b/hw/opentitan/ot_lc_ctrl.c @@ -38,7 +38,7 @@ #include "hw/opentitan/ot_common.h" #include "hw/opentitan/ot_kmac.h" #include "hw/opentitan/ot_lc_ctrl.h" -#include "hw/opentitan/ot_otp.h" +#include "hw/opentitan/ot_otp_if.h" #include "hw/opentitan/ot_pwrmgr.h" #include "hw/opentitan/ot_socdbg_ctrl.h" #include "hw/qdev-properties.h" @@ -410,7 +410,7 @@ struct OtLcCtrlState { /* properties */ char *ot_id; - OtOTPState *otp_ctrl; + DeviceState *otp_ctrl; OtKMACState *kmac; char *raw_unlock_token_xstr; char *km_div_xstrs[LC_DIV_COUNT]; @@ -1136,14 +1136,14 @@ static void ot_lc_ctrl_kmac_handle_resp(void *opaque, const OtKMACAppRsp *rsp) static uint32_t ot_lc_ctrl_load_lc_info(OtLcCtrlState *s) { - OtOTPClass *oc = OBJECT_GET_CLASS(OtOTPClass, s->otp_ctrl, TYPE_OT_OTP); + OtOTPIfClass *oc = OT_OTP_IF_GET_CLASS(s->otp_ctrl); + OtOTPIf *oi = OT_OTP_IF(s->otp_ctrl); OtLcCtrlStateValue lc_state; OtLcCtrlTransitionCountValue lc_tcount; uint8_t lc_valid; uint8_t secret_valid; const OtOTPTokens *tokens = NULL; - oc->get_lc_info(s->otp_ctrl, lc_tcount, lc_state, &lc_valid, &secret_valid, - &tokens); + oc->get_lc_info(oi, lc_tcount, lc_state, &lc_valid, &secret_valid, &tokens); if (s->force_raw) { trace_ot_lc_ctrl_load_lc_info_force_raw(s->ot_id); @@ -1215,8 +1215,9 @@ static uint32_t ot_lc_ctrl_load_lc_info(OtLcCtrlState *s) 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); + OtOTPIfClass *oc = OT_OTP_IF_GET_CLASS(s->otp_ctrl); + OtOTPIf *oi = OT_OTP_IF(s->otp_ctrl); + const OtOTPHWCfg *hw_cfg = oc->get_hw_cfg(oi); static_assert(sizeof(hw_cfg->device_id) == LC_DEV_ID_WIDTH, "HW_CFG Device ID size does not match size in registers"); @@ -1294,7 +1295,8 @@ static void ot_lc_ctrl_handle_otp_ack(void *opaque, bool ack) static void ot_lc_ctrl_program_otp(OtLcCtrlState *s, unsigned lc_tcount, OtLcState lc_state) { - OtOTPClass *oc = OBJECT_GET_CLASS(OtOTPClass, s->otp_ctrl, TYPE_OT_OTP); + OtOTPIfClass *oc = OT_OTP_IF_GET_CLASS(s->otp_ctrl); + OtOTPIf *oi = OT_OTP_IF(s->otp_ctrl); if (!oc->program_req) { qemu_log_mask(LOG_UNIMP, @@ -1310,7 +1312,7 @@ static void ot_lc_ctrl_program_otp(OtLcCtrlState *s, unsigned lc_tcount, const uint16_t *transition_val = s->lc_transitions[tcix]; const uint16_t *state_val = s->lc_states[stix]; - if (!oc->program_req(s->otp_ctrl, transition_val, state_val, + if (!oc->program_req(oi, transition_val, state_val, &ot_lc_ctrl_handle_otp_ack, s)) { trace_ot_lc_ctrl_error(s->ot_id, "OTP program request rejected"); s->regs[R_STATUS] |= R_STATUS_STATE_ERROR_MASK; @@ -2137,8 +2139,8 @@ static void ot_lc_ctrl_get_keymgr_div(const OtLcCtrlState *s, static Property ot_lc_ctrl_properties[] = { DEFINE_PROP_STRING(OT_COMMON_DEV_ID, OtLcCtrlState, ot_id), - DEFINE_PROP_LINK("otp-ctrl", OtLcCtrlState, otp_ctrl, TYPE_OT_OTP, - OtOTPState *), + DEFINE_PROP_LINK("otp-ctrl", OtLcCtrlState, otp_ctrl, TYPE_OT_OTP_IF, + DeviceState *), DEFINE_PROP_LINK("kmac", OtLcCtrlState, kmac, TYPE_OT_KMAC, OtKMACState *), DEFINE_PROP_STRING("raw_unlock_token", OtLcCtrlState, raw_unlock_token_xstr), @@ -2256,6 +2258,9 @@ static void ot_lc_ctrl_realize(DeviceState *dev, Error **errp) g_assert(s->otp_ctrl); g_assert(s->kmac); g_assert(s->kmac_app != UINT8_MAX); + + (void)OBJECT_CHECK(OtOTPIf, s->otp_ctrl, TYPE_OT_OTP_IF); + OtKMACClass *kc = OT_KMAC_GET_CLASS(s->kmac); g_assert(kc->connect_app); g_assert(kc->app_request); diff --git a/hw/opentitan/ot_otp_dj.c b/hw/opentitan/ot_otp_dj.c index 85cd469cc60bc..ea6a2251f239c 100644 --- a/hw/opentitan/ot_otp_dj.c +++ b/hw/opentitan/ot_otp_dj.c @@ -42,6 +42,7 @@ #include "hw/opentitan/ot_lc_ctrl.h" #include "hw/opentitan/ot_otp_be_if.h" #include "hw/opentitan/ot_otp_dj.h" +#include "hw/opentitan/ot_otp_if.h" #include "hw/opentitan/ot_present.h" #include "hw/opentitan/ot_prng.h" #include "hw/opentitan/ot_pwrmgr.h" @@ -626,6 +627,7 @@ typedef enum { /* TODO: wr and rd lock need to be rewritten (not simple boolean) */ typedef struct { + const char *name; uint16_t size; uint16_t offset; uint16_t digest_offset; @@ -645,8 +647,6 @@ typedef struct { #define OT_OTP_DJ_PARTS -#define OTP_PART_LIFE_CYCLE_SIZE 88u - /* NOLINTNEXTLINE */ #include "ot_otp_dj_parts.c" @@ -665,7 +665,7 @@ typedef struct { OtOTPUnbufState u; } state; struct { - uint32_t *data; /* size, see OtOTPPartDescs; w/o digest data */ + uint32_t *data; /* size, see OtOTPPartDesc w/o digest data */ uint64_t next_digest; /* computed HW digest to store into OTP cell */ } buffer; /* only meaningful for buffered partitions */ uint64_t digest; /* digest as read from OTP back end at init time */ @@ -688,7 +688,7 @@ typedef struct { OtOTPError error; ot_otp_program_ack_fn ack_fn; void *ack_data; - uint16_t data[OTP_PART_LIFE_CYCLE_SIZE / sizeof(uint16_t)]; + uint16_t *data; unsigned hpos; /* current offset in data */ } OtOTPLCIController; @@ -727,7 +727,7 @@ typedef struct { } OtOTPScrmblKeyInit; struct OtOTPDjState { - OtOTPState parent_obj; + SysBusDevice parent_obj; struct { MemoryRegion ctrl; @@ -747,7 +747,10 @@ struct OtOTPDjState { OtOTPLcBroadcast lc_broadcast; OtOTPDAIController *dai; OtOTPLCIController *lci; - OtOTPPartController *partctrls; + OtOTPPartController *part_ctrls; + const OtOTPPartDesc *part_descs; + unsigned part_count; + unsigned part_life_cycle; /* index of the Life Cycle partition */ OtOTPKeyGen *keygen; OtOTPScrmblKeyInit *scrmbl_key_init; OtOtpBeCharacteristics be_chars; @@ -756,8 +759,8 @@ struct OtOTPDjState { uint64_t sram_iv; uint8_t sram_const[16u]; /* OTP scrambling key constants, not constants for deriving other keys */ - uint8_t *otp_scramble_keys[ARRAY_SIZE(OtOTPPartDescs)]; /* may be NULL */ - uint8_t *inv_default_parts[ARRAY_SIZE(OtOTPPartDescs)]; /* may be NULL */ + uint8_t **otp_scramble_keys; /* some entries may be NULL */ + uint8_t **inv_default_parts; /* some entries may be NULL */ OtOTPStorage *otp; OtOTPHWCfg *hw_cfg; @@ -773,12 +776,17 @@ struct OtOTPDjState { char *digest_iv_xstr; char *sram_const_xstr; char *sram_iv_xstr; - char *otp_scramble_key_xstrs[ARRAY_SIZE(OtOTPPartDescs)]; /* may be NULL */ - char *inv_default_part_xstrs[ARRAY_SIZE(OtOTPPartDescs)]; /* may be NULL */ + char **otp_scramble_key_xstrs; /* some entries may be NULL */ + char **inv_default_part_xstrs; /* some entries may be NULL */ uint8_t edn_ep; bool fatal_escalate; }; +struct OtOTPDjClass { + SysBusDeviceClass parent_class; + ResettablePhases parent_phases; +}; + #define REG_NAME_ENTRY(_reg_) [R_##_reg_] = stringify(_reg_) static const char *REG_NAMES[REGS_COUNT] = { /* clang-format off */ @@ -926,35 +934,6 @@ static const char *OTP_TOKEN_NAMES[] = { /* clang-format on */ }; -static const char *PART_NAMES[] = { - /* clang-format off */ - OTP_NAME_ENTRY(OTP_PART_VENDOR_TEST), - OTP_NAME_ENTRY(OTP_PART_CREATOR_SW_CFG), - OTP_NAME_ENTRY(OTP_PART_OWNER_SW_CFG), - OTP_NAME_ENTRY(OTP_PART_OWNERSHIP_SLOT_STATE), - OTP_NAME_ENTRY(OTP_PART_ROT_CREATOR_AUTH), - OTP_NAME_ENTRY(OTP_PART_ROT_OWNER_AUTH_SLOT0), - OTP_NAME_ENTRY(OTP_PART_ROT_OWNER_AUTH_SLOT1), - OTP_NAME_ENTRY(OTP_PART_PLAT_INTEG_AUTH_SLOT0), - OTP_NAME_ENTRY(OTP_PART_PLAT_INTEG_AUTH_SLOT1), - OTP_NAME_ENTRY(OTP_PART_PLAT_OWNER_AUTH_SLOT0), - OTP_NAME_ENTRY(OTP_PART_PLAT_OWNER_AUTH_SLOT1), - OTP_NAME_ENTRY(OTP_PART_PLAT_OWNER_AUTH_SLOT2), - OTP_NAME_ENTRY(OTP_PART_PLAT_OWNER_AUTH_SLOT3), - OTP_NAME_ENTRY(OTP_PART_EXT_NVM), - OTP_NAME_ENTRY(OTP_PART_ROM_PATCH), - OTP_NAME_ENTRY(OTP_PART_HW_CFG0), - OTP_NAME_ENTRY(OTP_PART_HW_CFG1), - OTP_NAME_ENTRY(OTP_PART_SECRET0), - OTP_NAME_ENTRY(OTP_PART_SECRET1), - OTP_NAME_ENTRY(OTP_PART_SECRET2), - OTP_NAME_ENTRY(OTP_PART_SECRET3), - OTP_NAME_ENTRY(OTP_PART_LIFE_CYCLE), - /* fake partitions */ - OTP_NAME_ENTRY(OTP_ENTRY_DAI), - OTP_NAME_ENTRY(OTP_ENTRY_KDI), - /* clang-format on */ -}; static const char *ERR_CODE_NAMES[] = { /* clang-format off */ @@ -991,8 +970,6 @@ static const char *ERR_CODE_NAMES[] = { ((unsigned)(_tk_) < ARRAY_SIZE(OTP_TOKEN_NAMES) ? \ OTP_TOKEN_NAMES[(_tk_)] : \ "?") -#define PART_NAME(_pt_) \ - (((unsigned)(_pt_)) < ARRAY_SIZE(PART_NAMES) ? PART_NAMES[(_pt_)] : "?") #define ERR_CODE_NAME(_err_) \ (((unsigned)(_err_)) < ARRAY_SIZE(ERR_CODE_NAMES) ? \ ERR_CODE_NAMES[(_err_)] : \ @@ -1023,26 +1000,6 @@ ot_otp_dj_lci_change_state_line(OtOTPDjState *s, OtOTPLCIState state, int line); #define ot_otp_hexdump(_s_, _b_, _l_) #endif -static inline unsigned ot_otp_dj_part_data_offset(unsigned pix) -{ - return (unsigned)(OtOTPPartDescs[pix].offset); -} - -static inline unsigned ot_otp_dj_part_data_byte_size(unsigned pix) -{ - size_t size = OtOTPPartDescs[pix].size; - - if (OtOTPPartDescs[pix].hw_digest || OtOTPPartDescs[pix].sw_digest) { - size -= sizeof(uint32_t) * NUM_DIGEST_WORDS; - } - - if (OtOTPPartDescs[pix].zeroizable) { - size -= sizeof(uint32_t) * NUM_ZER_WORDS; - } - - return (unsigned)size; -} - static void ot_otp_dj_update_irqs(OtOTPDjState *s) { uint32_t levels = s->regs[R_INTR_STATE] & s->regs[R_INTR_ENABLE]; @@ -1090,14 +1047,54 @@ static void ot_otp_dj_update_alerts(OtOTPDjState *s) } } -static bool ot_otp_dj_is_wide_granule(unsigned part_ix, unsigned address) +static const char *ot_otp_dj_part_name(const OtOTPDjState *s, unsigned part_ix) { - if (part_ix < OTP_PART_COUNT) { - if (OtOTPPartDescs[part_ix].secret) { + if (part_ix < s->part_count) { + return s->part_descs[part_ix].name; + } + + if (part_ix == s->part_count) { + return "DAI"; + } + + if (part_ix == s->part_count + 1u) { + return "KDI"; + } + + return "?"; +} + +static inline unsigned +ot_otp_dj_part_data_offset(const OtOTPDjState *s, unsigned part_ix) +{ + return (unsigned)(s->part_descs[part_ix].offset); +} + +static inline unsigned +ot_otp_dj_part_data_byte_size(const OtOTPDjState *s, unsigned part_ix) +{ + size_t size = s->part_descs[part_ix].size; + + if (s->part_descs[part_ix].hw_digest || s->part_descs[part_ix].sw_digest) { + size -= sizeof(uint32_t) * NUM_DIGEST_WORDS; + } + + if (s->part_descs[part_ix].zeroizable) { + size -= sizeof(uint32_t) * NUM_ZER_WORDS; + } + + return (unsigned)size; +} + +static bool ot_otp_dj_is_wide_granule(const OtOTPDjState *s, unsigned part_ix, + unsigned address) +{ + if (part_ix < s->part_count) { + if (s->part_descs[part_ix].secret) { return true; } - if (OtOTPPartDescs[part_ix].digest_offset == + if (s->part_descs[part_ix].digest_offset == (address & OTP_DIGEST_ADDR_MASK)) { return true; } @@ -1106,19 +1103,19 @@ static bool ot_otp_dj_is_wide_granule(unsigned part_ix, unsigned address) return false; } -static bool ot_otp_dj_is_buffered(unsigned part_ix) +static bool ot_otp_dj_is_buffered(const OtOTPDjState *s, unsigned part_ix) { - if (part_ix < OTP_PART_COUNT) { - return OtOTPPartDescs[part_ix].buffered; + if (part_ix < s->part_count) { + return s->part_descs[part_ix].buffered; } return false; } -static bool ot_otp_dj_is_secret(unsigned part_ix) +static bool ot_otp_dj_is_secret(const OtOTPDjState *s, unsigned part_ix) { - if (part_ix < OTP_PART_COUNT) { - return OtOTPPartDescs[part_ix].secret; + if (part_ix < s->part_count) { + return s->part_descs[part_ix].secret; } return false; @@ -1140,10 +1137,25 @@ static bool ot_otp_dj_is_ecc_enabled(const OtOTPDjState *s) ot_otp_dj_is_backend_ecc_enabled(s); } -static bool ot_otp_dj_has_digest(unsigned partition) +static bool ot_otp_dj_has_digest(const OtOTPDjState *s, unsigned part_ix) { - return OtOTPPartDescs[partition].hw_digest || - OtOTPPartDescs[partition].sw_digest; + return s->part_descs[part_ix].hw_digest || s->part_descs[part_ix].sw_digest; +} + +static bool ot_otp_dj_is_part_digest_offset(const OtOTPDjState *s, + unsigned part_ix, hwaddr addr) +{ + uint16_t offset = s->part_descs[part_ix].digest_offset; + + return (offset != UINT16_MAX) && ((addr & ~OTP_DIGEST_ADDR_MASK) == offset); +} + +static bool ot_otp_dj_is_part_zer_offset(const OtOTPDjState *s, + unsigned part_ix, hwaddr addr) +{ + uint16_t offset = s->part_descs[part_ix].zer_offset; + + return (offset != UINT16_MAX) && ((addr & ~OTP_ZER_ADDR_MASK) == offset); } static void ot_otp_dj_disable_all_partitions(OtOTPDjState *s) @@ -1151,22 +1163,23 @@ static void ot_otp_dj_disable_all_partitions(OtOTPDjState *s) DAI_CHANGE_STATE(s, OTP_DAI_ERROR); LCI_CHANGE_STATE(s, OTP_LCI_ERROR); - for (unsigned pix = 0; pix < OTP_PART_COUNT; pix++) { - OtOTPPartController *pctrl = &s->partctrls[pix]; + for (unsigned pix = 0; pix < s->part_count; pix++) { + OtOTPPartController *pctrl = &s->part_ctrls[pix]; pctrl->failed = true; } } -static void ot_otp_dj_set_error(OtOTPDjState *s, unsigned part, OtOTPError err) +static void ot_otp_dj_set_error(OtOTPDjState *s, unsigned part_ix, + OtOTPError err) { - g_assert(part < OTP_ENTRY_COUNT); + g_assert(part_ix < OTP_ENTRY_COUNT); uint32_t errval = ((uint32_t)err) & ERR_CODE_MASK; - if (errval || errval != s->regs[R_ERR_CODE_0 + part]) { - trace_ot_otp_set_error(s->ot_id, PART_NAME(part), part, - ERR_CODE_NAME(err), err); + if (errval || errval != s->regs[R_ERR_CODE_0 + part_ix]) { + trace_ot_otp_set_error(s->ot_id, ot_otp_dj_part_name(s, part_ix), + part_ix, ERR_CODE_NAME(err), err); } - s->regs[R_ERR_CODE_0 + part] = errval; + s->regs[R_ERR_CODE_0 + part_ix] = errval; switch (err) { case OTP_MACRO_ERROR: @@ -1224,13 +1237,13 @@ static uint32_t ot_otp_dj_get_status(const OtOTPDjState *s) static int ot_otp_dj_get_part_from_address(const OtOTPDjState *s, hwaddr addr) { - for (unsigned ix = 0; ix < OTP_PART_COUNT; ix++) { - const OtOTPPartDesc *part = &OtOTPPartDescs[ix]; + for (unsigned part_ix = 0; part_ix < s->part_count; part_ix++) { + const OtOTPPartDesc *part = &s->part_descs[part_ix]; if ((addr >= part->offset) && ((addr + sizeof(uint32_t)) <= (part->offset + part->size))) { - trace_ot_otp_addr_to_part(s->ot_id, (uint32_t)addr, PART_NAME(ix), - ix); - return (OtOTPPartitionType)ix; + trace_ot_otp_addr_to_part(s->ot_id, (uint32_t)addr, + ot_otp_dj_part_name(s, part_ix), part_ix); + return (OtOTPPartitionType)part_ix; } } @@ -1382,11 +1395,11 @@ static int ot_otp_dj_apply_ecc(OtOTPDjState *s, unsigned part_ix) { g_assert(ot_otp_dj_is_ecc_enabled(s)); - unsigned start = OtOTPPartDescs[part_ix].offset >> 2u; - unsigned end = - (ot_otp_dj_is_buffered((int)part_ix) && ot_otp_dj_has_digest(part_ix)) ? - (unsigned)(OtOTPPartDescs[part_ix].digest_offset >> 2u) : - start + (unsigned)(OtOTPPartDescs[part_ix].size >> 2u); + unsigned start = s->part_descs[part_ix].offset >> 2u; + unsigned end = (ot_otp_dj_is_buffered(s, (int)part_ix) && + ot_otp_dj_has_digest(s, part_ix)) ? + (unsigned)(s->part_descs[part_ix].digest_offset >> 2u) : + start + (unsigned)(s->part_descs[part_ix].size >> 2u); g_assert(start < end && (end / sizeof(uint32_t)) < s->otp->data_size); for (unsigned ix = start; ix < end; ix++) { @@ -1403,9 +1416,10 @@ static int ot_otp_dj_apply_ecc(OtOTPDjState *s, unsigned part_ix) */ ot_otp_dj_set_error(s, part_ix, otp_err); if (err > 1) { - trace_ot_otp_ecc_init_error(s->ot_id, PART_NAME(part_ix), + trace_ot_otp_ecc_init_error(s->ot_id, + ot_otp_dj_part_name(s, part_ix), part_ix, ix << 2u, *word, ecc); - s->partctrls[part_ix].failed = true; + s->part_ctrls[part_ix].failed = true; return -1; } } @@ -1416,9 +1430,9 @@ static int ot_otp_dj_apply_ecc(OtOTPDjState *s, unsigned part_ix) static uint64_t ot_otp_dj_get_part_digest(OtOTPDjState *s, unsigned part_ix) { - g_assert(!ot_otp_dj_is_buffered(part_ix)); + g_assert(!ot_otp_dj_is_buffered(s, part_ix)); - uint16_t offset = OtOTPPartDescs[part_ix].digest_offset; + uint16_t offset = s->part_descs[part_ix].digest_offset; if (offset == UINT16_MAX) { return 0u; @@ -1427,7 +1441,7 @@ static uint64_t ot_otp_dj_get_part_digest(OtOTPDjState *s, unsigned part_ix) const uint8_t *data = (const uint8_t *)s->otp->data; uint64_t digest = ldq_le_p(data + offset); - if (OtOTPPartDescs[part_ix].integrity && ot_otp_dj_is_ecc_enabled(s)) { + if (s->part_descs[part_ix].integrity && ot_otp_dj_is_ecc_enabled(s)) { unsigned waddr = offset >> 2u; unsigned ewaddr = waddr >> 1u; g_assert(ewaddr < s->otp->ecc_size); @@ -1438,20 +1452,6 @@ static uint64_t ot_otp_dj_get_part_digest(OtOTPDjState *s, unsigned part_ix) return digest; } -static bool ot_otp_dj_is_part_digest_offset(unsigned part_ix, hwaddr addr) -{ - uint16_t offset = OtOTPPartDescs[part_ix].digest_offset; - - return (offset != UINT16_MAX) && ((addr & ~OTP_DIGEST_ADDR_MASK) == offset); -} - -static bool ot_otp_dj_is_part_zer_offset(unsigned part_ix, hwaddr addr) -{ - uint16_t offset = OtOTPPartDescs[part_ix].zer_offset; - - return (offset != UINT16_MAX) && ((addr & ~OTP_ZER_ADDR_MASK) == offset); -} - static uint32_t ot_otp_dj_get_part_digest_reg(OtOTPDjState *s, uint32_t offset) { /* @@ -1480,8 +1480,8 @@ static uint32_t ot_otp_dj_get_part_digest_reg(OtOTPDjState *s, uint32_t offset) /* part_ix: the partition number in the global partition array */ unsigned part_ix = 0; /* traverse the partition array and count each partition with a digest */ - for (unsigned part_dig_ix = 0; part_ix < OTP_PART_COUNT; part_ix++) { - if (ot_otp_dj_has_digest(part_ix)) { + for (unsigned part_dig_ix = 0; part_ix < s->part_count; part_ix++) { + if (ot_otp_dj_has_digest(s, part_ix)) { /* * stop searching if we've found the part-with-digest defined from * the offset argument. Otherwise, increment the part-with-digest @@ -1499,11 +1499,10 @@ static uint32_t ot_otp_dj_get_part_digest_reg(OtOTPDjState *s, uint32_t offset) * with the partition table or the register definitions, as it is assumed * that LifeCycle partition is the last partition. */ - static_assert(OTP_PART_LIFE_CYCLE == NUM_PART - 1, - "LC is expected to be the last partition"); - g_assert(part_ix < OTP_PART_COUNT); + g_assert(s->part_life_cycle == s->part_count - 1u); + g_assert(part_ix < s->part_count); - const OtOTPPartController *pctrl = &s->partctrls[part_ix]; + const OtOTPPartController *pctrl = &s->part_ctrls[part_ix]; uint64_t digest = pctrl->digest; if (hi) { @@ -1513,12 +1512,20 @@ static uint32_t ot_otp_dj_get_part_digest_reg(OtOTPDjState *s, uint32_t offset) return (uint32_t)digest; } -static bool ot_otp_dj_is_readable(OtOTPDjState *s, unsigned part_ix) +static uint32_t +ot_otp_dj_get_sw_readlock(const OtOTPDjState *s, unsigned rdlk_ix) +{ + uint32_t reg = R_VENDOR_TEST_READ_LOCK + rdlk_ix; + + return (bool)SHARED_FIELD_EX32(s->regs[reg], READ_LOCK); +} + +static bool ot_otp_dj_is_readable(const OtOTPDjState *s, unsigned part_ix) { - g_assert(part_ix < OTP_PART_COUNT); + g_assert(part_ix < s->part_count); - const OtOTPPartDesc *pdesc = &OtOTPPartDescs[part_ix]; - const OtOTPPartController *pctrl = &s->partctrls[part_ix]; + const OtOTPPartDesc *pdesc = &s->part_descs[part_ix]; + const OtOTPPartController *pctrl = &s->part_ctrls[part_ix]; if (pdesc->secret) { /* secret partitions are only readable if digest is not yet set. */ @@ -1537,7 +1544,7 @@ static bool ot_otp_dj_is_readable(OtOTPDjState *s, unsigned part_ix) unsigned roffset = 0; unsigned pix; - for (pix = 0; pix < OTP_PART_COUNT; pix++) { + for (pix = 0; pix < s->part_count; pix++) { if (pix == part_ix) { break; } @@ -1551,21 +1558,19 @@ static bool ot_otp_dj_is_readable(OtOTPDjState *s, unsigned part_ix) * static_assert, but C being C, constants are not defined as such * at build time... */ - g_assert(!OtOTPPartDescs[OTP_PART_LIFE_CYCLE].read_lock_csr); + g_assert(!s->part_descs[s->part_life_cycle].read_lock_csr); /* * If the previous loop reached the last partition, something * seriously wrong occurred. Use this feature as a sanity check */ - g_assert(pix < OTP_PART_LIFE_CYCLE); + g_assert(pix < s->part_life_cycle); /* * now that the count of read_lock_csr is known, use it to access * the register for the selected partition */ - uint32_t reg = R_VENDOR_TEST_READ_LOCK + roffset; - - return (bool)SHARED_FIELD_EX32(s->regs[reg], READ_LOCK); + return ot_otp_dj_get_sw_readlock(s, roffset); } static void @@ -1649,18 +1654,18 @@ static void ot_otp_dj_lc_broadcast_bh(void *opaque) s->ot_id); break; case OT_OTP_LC_CREATOR_SEED_SW_RW_EN: - for (unsigned ix = 0; ix < OTP_PART_COUNT; ix++) { - if (OtOTPPartDescs[ix].iskeymgr_creator) { - s->partctrls[ix].read_lock = !level; - s->partctrls[ix].write_lock = !level; + for (unsigned ix = 0; ix < s->part_count; ix++) { + if (s->part_descs[ix].iskeymgr_creator) { + s->part_ctrls[ix].read_lock = !level; + s->part_ctrls[ix].write_lock = !level; } } break; case OT_OTP_LC_OWNER_SEED_SW_RW_EN: - for (unsigned ix = 0; ix < OTP_PART_COUNT; ix++) { - if (OtOTPPartDescs[ix].iskeymgr_owner) { - s->partctrls[ix].read_lock = !level; - s->partctrls[ix].write_lock = !level; + for (unsigned ix = 0; ix < s->part_count; ix++) { + if (s->part_descs[ix].iskeymgr_owner) { + s->part_ctrls[ix].read_lock = !level; + s->part_ctrls[ix].write_lock = !level; } } break; @@ -1713,7 +1718,7 @@ static uint64_t ot_otp_dj_compute_partition_digest( static uint64_t ot_otp_dj_load_partition_digest(OtOTPDjState *s, unsigned partition) { - unsigned digoff = (unsigned)OtOTPPartDescs[partition].digest_offset; + unsigned digoff = (unsigned)s->part_descs[partition].digest_offset; if ((digoff + sizeof(uint64_t)) > s->otp->data_size) { error_setg(&error_fatal, "%s: partition located outside storage?", @@ -1735,12 +1740,12 @@ ot_otp_dj_load_partition_digest(OtOTPDjState *s, unsigned partition) return digest; } -static void ot_otp_dj_unscramble_partition(OtOTPDjState *s, unsigned ix) +static void ot_otp_dj_unscramble_partition(OtOTPDjState *s, unsigned part_ix) { - OtOTPPartController *pctrl = &s->partctrls[ix]; + OtOTPPartController *pctrl = &s->part_ctrls[part_ix]; - unsigned offset = (unsigned)OtOTPPartDescs[ix].offset; - unsigned part_size = ot_otp_dj_part_data_byte_size(ix); + unsigned offset = (unsigned)s->part_descs[part_ix].offset; + unsigned part_size = ot_otp_dj_part_data_byte_size(s, part_ix); /* part_size should be a multiple of PRESENT block size */ g_assert((part_size & (sizeof(uint64_t) - 1u)) == 0u); @@ -1757,13 +1762,14 @@ static void ot_otp_dj_unscramble_partition(OtOTPDjState *s, unsigned ix) g_assert(pctrl->buffer.data != NULL); uint64_t *clear = (uint64_t *)pctrl->buffer.data; - const uint8_t *scrambling_key = s->otp_scramble_keys[ix]; + const uint8_t *scrambling_key = s->otp_scramble_keys[part_ix]; g_assert(scrambling_key); OtPresentState *ps = ot_present_new(); ot_present_init(ps, scrambling_key); - trace_ot_otp_unscramble_partition(s->ot_id, PART_NAME(ix), ix, part_size); + trace_ot_otp_unscramble_partition(s->ot_id, ot_otp_dj_part_name(s, part_ix), + part_ix, part_size); /* neither the digest block nor the zeroizable block are scrambled */ for (unsigned dix = 0u; dix < dword_count; dix++) { ot_present_decrypt(ps, scrambled[dix], &clear[dix]); @@ -1772,30 +1778,30 @@ static void ot_otp_dj_unscramble_partition(OtOTPDjState *s, unsigned ix) ot_present_free(ps); } -static void ot_otp_dj_bufferize_partition(OtOTPDjState *s, unsigned ix) +static void ot_otp_dj_bufferize_partition(OtOTPDjState *s, unsigned part_ix) { - OtOTPPartController *pctrl = &s->partctrls[ix]; + OtOTPPartController *pctrl = &s->part_ctrls[part_ix]; g_assert(pctrl->buffer.data != NULL); - if (OtOTPPartDescs[ix].hw_digest) { - pctrl->digest = ot_otp_dj_load_partition_digest(s, ix); + if (s->part_descs[part_ix].hw_digest) { + pctrl->digest = ot_otp_dj_load_partition_digest(s, part_ix); } else { pctrl->digest = 0; } - if (OtOTPPartDescs[ix].secret) { + if (s->part_descs[part_ix].secret) { /* secret partitions need to be unscrambled */ if (s->blk) { /* * nothing to unscramble if no OTP data is loaded * scrambling keys in this case may not be known */ - ot_otp_dj_unscramble_partition(s, ix); + ot_otp_dj_unscramble_partition(s, part_ix); } } else { - unsigned offset = (unsigned)OtOTPPartDescs[ix].offset; - unsigned part_size = ot_otp_dj_part_data_byte_size(ix); + unsigned offset = (unsigned)s->part_descs[part_ix].offset; + unsigned part_size = ot_otp_dj_part_data_byte_size(s, part_ix); const uint8_t *base = (const uint8_t *)s->otp->data; base += offset; @@ -1805,12 +1811,13 @@ static void ot_otp_dj_bufferize_partition(OtOTPDjState *s, unsigned ix) } static void -ot_otp_dj_check_buffered_partition_integrity(OtOTPDjState *s, unsigned ix) +ot_otp_dj_check_buffered_partition_integrity(OtOTPDjState *s, unsigned part_ix) { - OtOTPPartController *pctrl = &s->partctrls[ix]; + OtOTPPartController *pctrl = &s->part_ctrls[part_ix]; if (pctrl->digest == 0) { - trace_ot_otp_skip_digest(s->ot_id, PART_NAME(ix), ix); + trace_ot_otp_skip_digest(s->ot_id, ot_otp_dj_part_name(s, part_ix), + part_ix); pctrl->locked = false; return; } @@ -1820,27 +1827,28 @@ ot_otp_dj_check_buffered_partition_integrity(OtOTPDjState *s, unsigned ix) /* * digests are always calculated over the original data (scrambled or not) */ - const uint8_t *part_data = - ((const uint8_t *)s->otp->data) + ot_otp_dj_part_data_offset(ix); - unsigned part_size = ot_otp_dj_part_data_byte_size(ix); + const uint8_t *part_data = ((const uint8_t *)s->otp->data) + + ot_otp_dj_part_data_offset(s, part_ix); + unsigned part_size = ot_otp_dj_part_data_byte_size(s, part_ix); uint64_t digest = ot_otp_dj_compute_partition_digest(s, part_data, part_size); if (digest != pctrl->digest) { - trace_ot_otp_mismatch_digest(s->ot_id, PART_NAME(ix), ix, digest, - pctrl->digest); + trace_ot_otp_mismatch_digest(s->ot_id, ot_otp_dj_part_name(s, part_ix), + part_ix, digest, pctrl->digest); TRACE_OTP("compute digest of %s: %016" PRIx64 " from %s\n", - PART_NAME(ix), digest, + ot_otp_dj_part_name(s, part_ix), digest, ot_otp_hexdump(s, part_data, part_size)); pctrl->failed = true; /* this is a fatal error */ - ot_otp_dj_set_error(s, ix, OTP_CHECK_FAIL_ERROR); + ot_otp_dj_set_error(s, part_ix, OTP_CHECK_FAIL_ERROR); /* TODO: revert buffered part to default */ } else { - trace_ot_otp_integrity_report(s->ot_id, PART_NAME(ix), ix, "digest OK"); + trace_ot_otp_integrity_report(s->ot_id, ot_otp_dj_part_name(s, part_ix), + part_ix, "digest OK"); } } @@ -1916,7 +1924,9 @@ static void ot_otp_dj_dai_read(OtOTPDjState *s) return; } - if (partition >= OTP_PART_LIFE_CYCLE) { + unsigned part_ix = (unsigned)partition; + + if (part_ix >= OTP_PART_LIFE_CYCLE) { qemu_log_mask( LOG_GUEST_ERROR, "%s: %s: life cycle partition cannot be accessed from DAI\n", @@ -1925,34 +1935,33 @@ static void ot_otp_dj_dai_read(OtOTPDjState *s) return; } - const OtOTPPartController *pctrl = &s->partctrls[partition]; + const OtOTPPartController *pctrl = &s->part_ctrls[part_ix]; if (pctrl->failed) { qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: partition %s is disabled\n", - __func__, s->ot_id, PART_NAME(partition)); + __func__, s->ot_id, ot_otp_dj_part_name(s, part_ix)); return; } - unsigned part_ix = (unsigned)partition; bool is_readable = ot_otp_dj_is_readable(s, part_ix); - bool is_wide = ot_otp_dj_is_wide_granule(part_ix, address); - bool is_buffered = ot_otp_dj_is_buffered(part_ix); - bool is_secret = ot_otp_dj_is_secret(part_ix); - bool is_digest = ot_otp_dj_is_part_digest_offset(part_ix, address); - bool is_zer = ot_otp_dj_is_part_zer_offset(part_ix, address); + bool is_wide = ot_otp_dj_is_wide_granule(s, part_ix, address); + bool is_buffered = ot_otp_dj_is_buffered(s, part_ix); + bool is_secret = ot_otp_dj_is_secret(s, part_ix); + bool is_digest = ot_otp_dj_is_part_digest_offset(s, part_ix, address); + bool is_zer = ot_otp_dj_is_part_zer_offset(s, part_ix, address); /* "in all partitions, the digest itself is ALWAYS readable." */ if (!is_digest && !is_zer && !is_readable) { qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: partition %s @ 0x%04x not readable\n", __func__, - s->ot_id, PART_NAME(partition), address); + s->ot_id, ot_otp_dj_part_name(s, part_ix), address); ot_otp_dj_dai_set_error(s, OTP_ACCESS_ERROR); return; } - unsigned part_offset = address - ot_otp_dj_part_data_offset(partition); + unsigned part_offset = address - ot_otp_dj_part_data_offset(s, part_ix); unsigned part_waddr = part_offset >> 2u; bool do_ecc = - OtOTPPartDescs[part_ix].integrity && ot_otp_dj_is_ecc_enabled(s); + s->part_descs[part_ix].integrity && ot_otp_dj_is_ecc_enabled(s); DAI_CHANGE_STATE(s, OTP_DAI_READ_WAIT); @@ -1962,14 +1971,14 @@ static void ot_otp_dj_dai_read(OtOTPDjState *s) const uint32_t *data = (const uint32_t *)s->otp->data; /* parenthesis inform the C linter sizeof() call is valid with 'data */ - data += (ot_otp_dj_part_data_offset(partition) / sizeof(uint32_t)); + data += (ot_otp_dj_part_data_offset(s, part_ix) / sizeof(uint32_t)); if (is_wide || is_digest) { /* 64-bit requests */ part_waddr &= ~0b1u; g_assert((part_waddr + 1u) * sizeof(uint32_t) < - OtOTPPartDescs[partition].size); + s->part_descs[part_ix].size); data_lo = data[part_waddr]; data_hi = data[part_waddr + 1u]; @@ -1987,8 +1996,7 @@ static void ot_otp_dj_dai_read(OtOTPDjState *s) cell_count *= 2u; } else { /* 32-bit request */ - g_assert(part_waddr * sizeof(uint32_t) < - OtOTPPartDescs[partition].size); + g_assert(part_waddr * sizeof(uint32_t) < s->part_descs[part_ix].size); data_lo = data[part_waddr]; data_hi = 0u; @@ -2014,7 +2022,7 @@ static void ot_otp_dj_dai_read(OtOTPDjState *s) * if the partition is a secret partition, OTP storage is scrambled * except the digest and the zeroification fields */ - const uint8_t *scrambling_key = s->otp_scramble_keys[partition]; + const uint8_t *scrambling_key = s->otp_scramble_keys[part_ix]; g_assert(scrambling_key); uint64_t tmp_data = ((uint64_t)data_hi << 32u) | data_lo; OtPresentState *ps = ot_present_new(); @@ -2059,8 +2067,8 @@ static int ot_otp_dj_dai_write_u64(OtOTPDjState *s, unsigned address) uint32_t hi = s->regs[R_DIRECT_ACCESS_WDATA_1]; unsigned part_ix = (unsigned)s->dai->partition; - bool is_secret = ot_otp_dj_is_secret(part_ix); - bool is_zer = ot_otp_dj_is_part_zer_offset(part_ix, address); + bool is_secret = ot_otp_dj_is_secret(s, part_ix); + bool is_zer = ot_otp_dj_is_part_zer_offset(s, part_ix, address); if (is_secret && !is_zer) { const uint8_t *scrambling_key = s->otp_scramble_keys[part_ix]; @@ -2117,7 +2125,9 @@ static int ot_otp_dj_dai_write_u64(OtOTPDjState *s, unsigned address) return -1; } - trace_ot_otp_dai_new_dword_ecc(s->ot_id, PART_NAME(s->dai->partition), + trace_ot_otp_dai_new_dword_ecc(s->ot_id, + ot_otp_dj_part_name(s, (unsigned)s->dai + ->partition), s->dai->partition, *dst, *edst); } @@ -2170,7 +2180,9 @@ static int ot_otp_dj_dai_write_u32(OtOTPDjState *s, unsigned address) return -1; } - trace_ot_otp_dai_new_word_ecc(s->ot_id, PART_NAME(s->dai->partition), + trace_ot_otp_dai_new_word_ecc(s->ot_id, + ot_otp_dj_part_name(s, (unsigned)s->dai + ->partition), s->dai->partition, *dst, *edst); } @@ -2212,7 +2224,7 @@ static void ot_otp_dj_dai_write(OtOTPDjState *s) unsigned part_ix = (unsigned)partition; - if (part_ix >= OTP_PART_LIFE_CYCLE) { + if (part_ix >= s->part_life_cycle) { qemu_log_mask( LOG_GUEST_ERROR, "%s: %s: Life cycle partition cannot be accessed from DAI\n", @@ -2221,17 +2233,18 @@ static void ot_otp_dj_dai_write(OtOTPDjState *s) return; } - OtOTPPartController *pctrl = &s->partctrls[part_ix]; + OtOTPPartController *pctrl = &s->part_ctrls[part_ix]; if (pctrl->failed) { qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: partition %s is disabled\n", - __func__, s->ot_id, PART_NAME(part_ix)); + __func__, s->ot_id, ot_otp_dj_part_name(s, part_ix)); return; } if (pctrl->locked) { qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: partition %s (%u) is locked\n", - __func__, s->ot_id, PART_NAME(part_ix), part_ix); + __func__, s->ot_id, ot_otp_dj_part_name(s, part_ix), + part_ix); ot_otp_dj_dai_set_error(s, OTP_ACCESS_ERROR); return; } @@ -2239,22 +2252,22 @@ static void ot_otp_dj_dai_write(OtOTPDjState *s) if (pctrl->write_lock) { qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: artition %s (%u) is write locked\n", __func__, - s->ot_id, PART_NAME(part_ix), part_ix); + s->ot_id, ot_otp_dj_part_name(s, part_ix), part_ix); ot_otp_dj_dai_set_error(s, OTP_ACCESS_ERROR); return; } - bool is_digest = ot_otp_dj_is_part_digest_offset(part_ix, address); - bool is_wide = ot_otp_dj_is_wide_granule(part_ix, address); + bool is_digest = ot_otp_dj_is_part_digest_offset(s, part_ix, address); + bool is_wide = ot_otp_dj_is_wide_granule(s, part_ix, address); if (is_digest) { - if (OtOTPPartDescs[partition].hw_digest) { + if (s->part_descs[part_ix].hw_digest) { /* should have been a Digest command, not a Write command */ qemu_log_mask( LOG_GUEST_ERROR, "%s: %s: partition %s (%u) HW digest cannot be directly " "written\n", - __func__, s->ot_id, PART_NAME(part_ix), part_ix); + __func__, s->ot_id, ot_otp_dj_part_name(s, part_ix), part_ix); ot_otp_dj_dai_set_error(s, OTP_ACCESS_ERROR); return; } @@ -2320,7 +2333,9 @@ static void ot_otp_dj_dai_digest(OtOTPDjState *s) return; } - if (partition >= OTP_PART_LIFE_CYCLE) { + unsigned part_ix = (unsigned)partition; + + if (part_ix >= s->part_life_cycle) { qemu_log_mask( LOG_GUEST_ERROR, "%s: %s: Life cycle partition cannot be accessed from DAI\n", @@ -2329,25 +2344,27 @@ static void ot_otp_dj_dai_digest(OtOTPDjState *s) return; } - if (!OtOTPPartDescs[partition].hw_digest) { + if (!s->part_descs[part_ix].hw_digest) { qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: Invalid partition, no HW digest on %s (#%u)\n", - __func__, s->ot_id, PART_NAME(partition), partition); + __func__, s->ot_id, ot_otp_dj_part_name(s, part_ix), + part_ix); ot_otp_dj_dai_set_error(s, OTP_ACCESS_ERROR); return; } - OtOTPPartController *pctrl = &s->partctrls[partition]; + OtOTPPartController *pctrl = &s->part_ctrls[part_ix]; if (pctrl->failed) { qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: partition %s is disabled\n", - __func__, s->ot_id, PART_NAME(partition)); + __func__, s->ot_id, ot_otp_dj_part_name(s, part_ix)); return; } if (pctrl->locked) { qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: Partition %s (%u) is locked\n", - __func__, s->ot_id, PART_NAME(partition), partition); + __func__, s->ot_id, ot_otp_dj_part_name(s, part_ix), + part_ix); ot_otp_dj_dai_set_error(s, OTP_ACCESS_ERROR); return; } @@ -2355,16 +2372,16 @@ static void ot_otp_dj_dai_digest(OtOTPDjState *s) if (pctrl->write_lock) { qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: Partition %s (%u) is write locked\n", __func__, - s->ot_id, PART_NAME(partition), partition); + s->ot_id, ot_otp_dj_part_name(s, part_ix), part_ix); ot_otp_dj_dai_set_error(s, OTP_ACCESS_ERROR); return; } DAI_CHANGE_STATE(s, OTP_DAI_DIG_READ); - const uint8_t *data = - ((const uint8_t *)s->otp->data) + ot_otp_dj_part_data_offset(partition); - unsigned part_size = ot_otp_dj_part_data_byte_size(partition); + const uint8_t *data = ((const uint8_t *)s->otp->data) + + ot_otp_dj_part_data_offset(s, part_ix); + unsigned part_size = ot_otp_dj_part_data_byte_size(s, part_ix); DAI_CHANGE_STATE(s, OTP_DAI_DIG); @@ -2387,12 +2404,14 @@ static void ot_otp_dj_dai_write_digest(void *opaque) { OtOTPDjState *s = OT_OTP_DJ(opaque); - g_assert((s->dai->partition >= 0) && (s->dai->partition < OTP_PART_COUNT)); + g_assert((s->dai->partition >= 0) && (s->dai->partition < s->part_count)); DAI_CHANGE_STATE(s, OTP_DAI_WRITE); - OtOTPPartController *pctrl = &s->partctrls[s->dai->partition]; - unsigned address = OtOTPPartDescs[s->dai->partition].digest_offset; + unsigned part_ix = (unsigned)s->dai->partition; + + OtOTPPartController *pctrl = &s->part_ctrls[part_ix]; + unsigned address = s->part_descs[part_ix].digest_offset; unsigned dwaddr = address / sizeof(uint64_t); uint64_t *dst = &((uint64_t *)s->otp->data)[dwaddr]; uint64_t data = pctrl->buffer.next_digest; @@ -2436,8 +2455,8 @@ static void ot_otp_dj_dai_write_digest(void *opaque) return; } - trace_ot_otp_dai_new_digest_ecc(s->ot_id, PART_NAME(s->dai->partition), - s->dai->partition, *dst, *edst); + trace_ot_otp_dai_new_digest_ecc(s->ot_id, ot_otp_dj_part_name(s, part_ix), + part_ix, *dst, *edst); DAI_CHANGE_STATE(s, OTP_DAI_WRITE_WAIT); @@ -2454,8 +2473,10 @@ static void ot_otp_dj_dai_complete(void *opaque) switch (s->dai->state) { case OTP_DAI_READ_WAIT: g_assert(s->dai->partition >= 0); - trace_ot_otp_dai_read(s->ot_id, PART_NAME(s->dai->partition), - s->dai->partition, + trace_ot_otp_dai_read(s->ot_id, + ot_otp_dj_part_name(s, + (unsigned)s->dai->partition), + (unsigned)s->dai->partition, s->regs[R_DIRECT_ACCESS_RDATA_1], s->regs[R_DIRECT_ACCESS_RDATA_1]); s->dai->partition = -1; @@ -2839,10 +2860,9 @@ static MemTxResult ot_otp_dj_swcfg_read_with_attrs( void *opaque, hwaddr addr, uint64_t *data, unsigned size, MemTxAttrs attrs) { OtOTPDjState *s = OT_OTP_DJ(opaque); + (void)size; (void)attrs; - g_assert(addr + size <= SW_CFG_WINDOW_SIZE); - hwaddr reg = R32_OFF(addr); int partition = ot_otp_dj_get_part_from_address(s, addr); @@ -2855,7 +2875,7 @@ static MemTxResult ot_otp_dj_swcfg_read_with_attrs( unsigned part_ix = (unsigned)partition; - if (ot_otp_dj_is_buffered(part_ix)) { + if (ot_otp_dj_is_buffered(s, part_ix)) { trace_ot_otp_access_error_on(s->ot_id, partition, addr, "buffered"); ot_otp_dj_set_error(s, part_ix, OTP_ACCESS_ERROR); @@ -2864,8 +2884,8 @@ static MemTxResult ot_otp_dj_swcfg_read_with_attrs( } bool is_readable = ot_otp_dj_is_readable(s, part_ix); - bool is_digest = ot_otp_dj_is_part_digest_offset(part_ix, addr); - bool is_zer = ot_otp_dj_is_part_zer_offset(part_ix, addr); + bool is_digest = ot_otp_dj_is_part_digest_offset(s, part_ix, addr); + bool is_zer = ot_otp_dj_is_part_zer_offset(s, part_ix, addr); if (!is_readable && !(is_digest || is_zer)) { trace_ot_otp_access_error_on(s->ot_id, partition, addr, "not readable"); @@ -2889,10 +2909,10 @@ static MemTxResult ot_otp_dj_swcfg_read_with_attrs( } static void ot_otp_dj_get_lc_info( - const OtOTPState *s, uint16_t *lc_tcount, uint16_t *lc_state, + const OtOTPIf *dev, uint16_t *lc_tcount, uint16_t *lc_state, uint8_t *lc_valid, uint8_t *secret_valid, const OtOTPTokens **tokens) { - const OtOTPDjState *ds = OT_OTP_DJ(s); + const OtOTPDjState *ds = OT_OTP_DJ(dev); const OtOTPStorage *otp = ds->otp; if (lc_tcount) { @@ -2905,15 +2925,15 @@ static void ot_otp_dj_get_lc_info( } if (lc_valid) { - *lc_valid = !(ds->partctrls[OTP_PART_SECRET0].failed || - ds->partctrls[OTP_PART_SECRET2].failed || - ds->partctrls[OTP_PART_LIFE_CYCLE].failed) ? + *lc_valid = !(ds->part_ctrls[OTP_PART_SECRET0].failed || + ds->part_ctrls[OTP_PART_SECRET2].failed || + ds->part_ctrls[ds->part_life_cycle].failed) ? OT_MULTIBITBOOL_LC4_TRUE : OT_MULTIBITBOOL_LC4_FALSE; } if (secret_valid) { - *secret_valid = (!ds->partctrls[OTP_PART_SECRET2].failed && - ds->partctrls[OTP_PART_SECRET2].locked) ? + *secret_valid = (!ds->part_ctrls[OTP_PART_SECRET2].failed && + ds->part_ctrls[OTP_PART_SECRET2].locked) ? OT_MULTIBITBOOL_LC4_TRUE : OT_MULTIBITBOOL_LC4_FALSE; } @@ -2922,9 +2942,9 @@ static void ot_otp_dj_get_lc_info( } } -static const OtOTPHWCfg *ot_otp_dj_get_hw_cfg(const OtOTPState *s) +static const OtOTPHWCfg *ot_otp_dj_get_hw_cfg(const OtOTPIf *dev) { - const OtOTPDjState *ds = OT_OTP_DJ(s); + const OtOTPDjState *ds = OT_OTP_DJ(dev); return (const OtOTPHWCfg *)ds->hw_cfg; } @@ -3043,10 +3063,10 @@ static void ot_otp_dj_generate_scrambling_key( OtPresentState *ps = s->keygen->present; /* read the key seed from the OTP SECRET1 partition */ - OtOTPPartController *pctrl = &s->partctrls[OTP_PART_SECRET1]; - g_assert(ot_otp_dj_is_buffered(OTP_PART_SECRET1)); + OtOTPPartController *pctrl = &s->part_ctrls[OTP_PART_SECRET1]; + g_assert(ot_otp_dj_is_buffered(s, OTP_PART_SECRET1)); uint32_t poffset = - OtOTPPartDescs[OTP_PART_SECRET1].offset / sizeof(uint32_t); + s->part_descs[OTP_PART_SECRET1].offset / sizeof(uint32_t); const uint32_t *key_seed = &pctrl->buffer.data[key_reg - poffset]; /* check the key seed's validity */ @@ -3090,10 +3110,10 @@ static void ot_otp_dj_generate_scrambling_key( } } -static void ot_otp_dj_get_otp_key(OtOTPState *s, OtOTPKeyType type, +static void ot_otp_dj_get_otp_key(OtOTPIf *dev, OtOTPKeyType type, OtOTPKey *key) { - OtOTPDjState *ds = OT_OTP_DJ(s); + OtOTPDjState *ds = OT_OTP_DJ(dev); hwaddr key_offset; @@ -3138,9 +3158,9 @@ static void ot_otp_dj_get_otp_key(OtOTPState *s, OtOTPKeyType type, } static void ot_otp_dj_get_keymgr_secret( - OtOTPState *s, OtOTPKeyMgrSecretType type, OtOTPKeyMgrSecret *secret) + OtOTPIf *dev, OtOTPKeyMgrSecretType type, OtOTPKeyMgrSecret *secret) { - OtOTPDjState *ds = OT_OTP_DJ(s); + OtOTPDjState *ds = OT_OTP_DJ(dev); int partition; size_t offset; @@ -3148,20 +3168,20 @@ static void ot_otp_dj_get_keymgr_secret( case OTP_KEYMGR_SECRET_CREATOR_ROOT_KEY_SHARE0: partition = OTP_PART_SECRET2; offset = A_SECRET2_CREATOR_ROOT_KEY_SHARE0 - - OtOTPPartDescs[partition].offset; + ds->part_descs[partition].offset; break; case OTP_KEYMGR_SECRET_CREATOR_ROOT_KEY_SHARE1: partition = OTP_PART_SECRET2; offset = A_SECRET2_CREATOR_ROOT_KEY_SHARE1 - - OtOTPPartDescs[partition].offset; + ds->part_descs[partition].offset; break; case OTP_KEYMGR_SECRET_CREATOR_SEED: partition = OTP_PART_SECRET2; - offset = A_SECRET2_CREATOR_SEED - OtOTPPartDescs[partition].offset; + offset = A_SECRET2_CREATOR_SEED - ds->part_descs[partition].offset; break; case OTP_KEYMGR_SECRET_OWNER_SEED: partition = OTP_PART_SECRET3; - offset = A_SECRET3_OWNER_SEED - OtOTPPartDescs[partition].offset; + offset = A_SECRET3_OWNER_SEED - ds->part_descs[partition].offset; break; default: error_report("%s: %s: invalid OTP keymgr secret type: %d", __func__, @@ -3172,25 +3192,25 @@ static void ot_otp_dj_get_keymgr_secret( } unsigned part_ix = (unsigned)partition; - g_assert(ot_otp_dj_is_buffered(part_ix)); + g_assert(ot_otp_dj_is_buffered(ds, part_ix)); const uint8_t *data_ptr; if (ds->lc_broadcast.current_level & BIT(OT_OTP_LC_SEED_HW_RD_EN)) { - data_ptr = (const uint8_t *)ds->partctrls[part_ix].buffer.data; + data_ptr = (const uint8_t *)ds->part_ctrls[part_ix].buffer.data; } else { /* source data from PartInvDefault instead of real buffer */ data_ptr = ds->inv_default_parts[part_ix]; } - secret->valid = ds->partctrls[part_ix].digest != 0; + secret->valid = ds->part_ctrls[part_ix].digest != 0; memcpy(secret->secret, &data_ptr[offset], OT_OTP_KEYMGR_SECRET_SIZE); } -static bool ot_otp_dj_program_req(OtOTPState *s, const uint16_t *lc_tcount, +static bool ot_otp_dj_program_req(OtOTPIf *dev, const uint16_t *lc_tcount, const uint16_t *lc_state, ot_otp_program_ack_fn ack, void *opaque) { - OtOTPDjState *ds = OT_OTP_DJ(s); + OtOTPDjState *ds = OT_OTP_DJ(dev); OtOTPLCIController *lci = ds->lci; switch (lci->state) { @@ -3220,7 +3240,7 @@ static bool ot_otp_dj_program_req(OtOTPState *s, const uint16_t *lc_tcount, memcpy(&lci->data[hpos], lc_state, LC_STATE_SIZE); hpos += LC_STATE_SIZE / sizeof(uint16_t); g_assert(hpos == - OtOTPPartDescs[OTP_PART_LIFE_CYCLE].size / sizeof(uint16_t)); + ds->part_descs[ds->part_life_cycle].size / sizeof(uint16_t)); /* current position in LC buffer to write to backend */ lci->hpos = 0u; @@ -3245,7 +3265,7 @@ static void ot_otp_dj_lci_write_complete(OtOTPDjState *s, bool success) * if the LC partition has been modified somehow, even if the request * has failed, update the backend file */ - const OtOTPPartDesc *lcdesc = &OtOTPPartDescs[OTP_PART_LIFE_CYCLE]; + const OtOTPPartDesc *lcdesc = &s->part_descs[s->part_life_cycle]; unsigned lc_off = lcdesc->offset / sizeof(uint32_t); uintptr_t offset = (uintptr_t)s->otp->data - (uintptr_t)s->otp->storage; if (ot_otp_dj_write_backend(s, &s->otp->data[lc_off], @@ -3282,7 +3302,7 @@ static void ot_otp_dj_lci_write_complete(OtOTPDjState *s, bool success) lci->hpos = 0u; if (!success && lci->error != OTP_NO_ERROR) { - ot_otp_dj_set_error(s, OTP_PART_LIFE_CYCLE, lci->error); + ot_otp_dj_set_error(s, s->part_life_cycle, lci->error); } (*ack_fn)(ack_data, success); @@ -3292,7 +3312,7 @@ static void ot_otp_dj_lci_write_word(void *opaque) { OtOTPDjState *s = OT_OTP_DJ(opaque); OtOTPLCIController *lci = s->lci; - const OtOTPPartDesc *lcdesc = &OtOTPPartDescs[OTP_PART_LIFE_CYCLE]; + const OtOTPPartDesc *lcdesc = &s->part_descs[s->part_life_cycle]; /* should not be called if already in error */ if (lci->state == OTP_LCI_ERROR) { @@ -3434,8 +3454,8 @@ static void ot_otp_dj_pwr_load(OtOTPDjState *s) size_t data_size = 0u; size_t ecc_size = 0u; - for (unsigned ix = 0u; ix < OTP_PART_COUNT; ix++) { - size_t psize = (size_t)OtOTPPartDescs[ix].size; + for (unsigned part_ix = 0u; part_ix < s->part_count; part_ix++) { + size_t psize = (size_t)s->part_descs[part_ix].size; size_t dsize = ROUND_UP(psize, sizeof(uint64_t)); data_size += dsize; /* up to 1 ECC byte for 2 data bytes */ @@ -3563,28 +3583,28 @@ static void ot_otp_dj_pwr_load_tokens(OtOTPDjState *s) switch (tkx) { case OTP_TOKEN_TEST_UNLOCK: - partition = OTP_PART_SECRET0; + partition = (unsigned)OTP_PART_SECRET0; secret_addr = A_SECRET0_TEST_UNLOCK_TOKEN; break; case OTP_TOKEN_TEST_EXIT: partition = OTP_PART_SECRET0; - secret_addr = A_SECRET0_TEST_EXIT_TOKEN; + secret_addr = (unsigned)A_SECRET0_TEST_EXIT_TOKEN; break; case OTP_TOKEN_RMA: partition = OTP_PART_SECRET2; - secret_addr = A_SECRET2_RMA_TOKEN; + secret_addr = (unsigned)A_SECRET2_RMA_TOKEN; break; default: g_assert_not_reached(); break; } - OtOTPPartController *pctrl = &s->partctrls[partition]; + OtOTPPartController *pctrl = &s->part_ctrls[partition]; g_assert(pctrl->buffer.data != NULL); /* byte offset of the secret within the partition */ unsigned secret_offset = - secret_addr - ot_otp_dj_part_data_offset(partition); + secret_addr - ot_otp_dj_part_data_offset(s, partition); g_assert(secret_offset + sizeof(OtOTPTokenValue) <= OtOTPPartDescs[partition].size); @@ -3592,7 +3612,7 @@ static void ot_otp_dj_pwr_load_tokens(OtOTPDjState *s) memcpy(&value, &pctrl->buffer.data[secret_offset / sizeof(uint32_t)], sizeof(OtOTPTokenValue)); - if (s->partctrls[partition].locked) { + if (s->part_ctrls[partition].locked) { tokens->values[tkx] = value; tokens->valid_bm |= 1u << tkx; } @@ -3605,25 +3625,25 @@ static void ot_otp_dj_pwr_load_tokens(OtOTPDjState *s) static void ot_otp_dj_pwr_initialize_partitions(OtOTPDjState *s) { - for (unsigned ix = 0; ix < OTP_PART_COUNT; ix++) { + for (unsigned ix = 0; ix < s->part_count; ix++) { /* sanity check: all secret partitions are also buffered */ - g_assert(!OtOTPPartDescs[ix].secret || OtOTPPartDescs[ix].buffered); + g_assert(!s->part_descs[ix].secret || s->part_descs[ix].buffered); - if (ot_otp_dj_is_ecc_enabled(s) && OtOTPPartDescs[ix].integrity) { + if (ot_otp_dj_is_ecc_enabled(s) && s->part_descs[ix].integrity) { if (ot_otp_dj_apply_ecc(s, ix)) { continue; } } - if (OtOTPPartDescs[ix].sw_digest) { - s->partctrls[ix].digest = ot_otp_dj_get_part_digest(s, ix); - s->partctrls[ix].locked = s->partctrls[ix].digest != 0; + if (s->part_descs[ix].sw_digest) { + s->part_ctrls[ix].digest = ot_otp_dj_get_part_digest(s, ix); + s->part_ctrls[ix].locked = s->part_ctrls[ix].digest != 0; continue; } - if (OtOTPPartDescs[ix].buffered) { + if (s->part_descs[ix].buffered) { ot_otp_dj_bufferize_partition(s, ix); - if (OtOTPPartDescs[ix].hw_digest) { + if (s->part_descs[ix].hw_digest) { ot_otp_dj_check_buffered_partition_integrity(s, ix); } continue; @@ -3799,54 +3819,65 @@ static void ot_otp_dj_configure_sram(OtOTPDjState *s) static void ot_otp_dj_configure_part_scramble_keys(OtOTPDjState *s) { - for (unsigned ix = 0u; ix < ARRAY_SIZE(OtOTPPartDescs); ix++) { - if (!OtOTPPartDescs[ix].secret) { + for (unsigned part_ix = 0u; part_ix < s->part_count; part_ix++) { + if (!s->part_descs[part_ix].secret) { continue; } - if (!s->otp_scramble_key_xstrs[ix]) { + if (!s->otp_scramble_key_xstrs[part_ix]) { /* if OTP data is loaded, unscrambling keys are mandatory */ if (s->blk) { error_setg(&error_fatal, "%s: %s Missing OTP scrambling key for part %s (%u)", - __func__, s->ot_id, PART_NAME(ix), ix); + __func__, s->ot_id, ot_otp_dj_part_name(s, part_ix), + part_ix); return; } continue; } - size_t len = strlen(s->otp_scramble_key_xstrs[ix]); + size_t len = strlen(s->otp_scramble_key_xstrs[part_ix]); if (len != OTP_SCRAMBLING_KEY_BYTES * 2u) { error_setg( &error_fatal, "%s: %s Invalid OTP scrambling key length %zu for part %s (%u)", - __func__, s->ot_id, len, PART_NAME(ix), ix); + __func__, s->ot_id, len, ot_otp_dj_part_name(s, part_ix), + part_ix); return; } - g_assert(!s->otp_scramble_keys[ix]); + g_assert(!s->otp_scramble_keys[part_ix]); - s->otp_scramble_keys[ix] = g_new0(uint8_t, OTP_SCRAMBLING_KEY_BYTES); - if (ot_common_parse_hexa_str(s->otp_scramble_keys[ix], - s->otp_scramble_key_xstrs[ix], + s->otp_scramble_keys[part_ix] = + g_new0(uint8_t, OTP_SCRAMBLING_KEY_BYTES); + if (ot_common_parse_hexa_str(s->otp_scramble_keys[part_ix], + s->otp_scramble_key_xstrs[part_ix], OTP_SCRAMBLING_KEY_BYTES, true, true)) { error_setg(&error_fatal, "%s: %s unable to parse otp_scramble_keys[%u] for %s", - __func__, s->ot_id, ix, PART_NAME(ix)); + __func__, s->ot_id, part_ix, + ot_otp_dj_part_name(s, part_ix)); return; } - TRACE_OTP("otp_scramble_keys[%s] %s", PART_NAME(ix), - ot_otp_hexdump(s, s->otp_scramble_keys[ix], + TRACE_OTP("otp_scramble_keys[%s] %s", ot_otp_dj_part_name(s, part_ix), + ot_otp_hexdump(s, s->otp_scramble_keys[part_ix], OTP_SCRAMBLING_KEY_BYTES)); } } -static void ot_otp_dj_class_add_scramble_key_props(OtOTPClass *odc) +static void ot_otp_dj_add_scramble_key_props(OtOTPDjState *s) { + /* + * @todo: we know the number of secret partitions, so use it rather than + * whole partition count + */ + s->otp_scramble_keys = g_new0(uint8_t *, s->part_count); + s->otp_scramble_key_xstrs = g_new0(char *, s->part_count); + unsigned secret_ix = 0u; - for (unsigned ix = 0u; ix < ARRAY_SIZE(OtOTPPartDescs); ix++) { - if (!OtOTPPartDescs[ix].secret) { + for (unsigned part_ix = 0u; part_ix < s->part_count; part_ix++) { + if (!s->part_descs[part_ix].secret) { continue; } @@ -3858,68 +3889,79 @@ static void ot_otp_dj_class_add_scramble_key_props(OtOTPClass *odc) */ prop->name = g_strdup_printf("secret%u_scramble_key", secret_ix++); prop->info = &qdev_prop_string; - prop->offset = offsetof(OtOTPDjState, otp_scramble_key_xstrs) + - sizeof(char *) * ix; + /* + * Property stores the address of the stored string as a relative offset + * from the parent address + */ + prop->offset = + (intptr_t)&s->otp_scramble_key_xstrs[part_ix] - (intptr_t)s; - object_class_property_add(OBJECT_CLASS(odc), prop->name, - prop->info->name, prop->info->get, - prop->info->set, prop->info->release, prop); + object_property_add(OBJECT(s), prop->name, prop->info->name, + prop->info->get, prop->info->set, + prop->info->release, prop); } } static void ot_otp_dj_configure_inv_default_parts(OtOTPDjState *s) { - for (unsigned ix = 0; ix < ARRAY_SIZE(OtOTPPartDescs); ix++) { - if (!s->inv_default_part_xstrs[ix]) { + for (unsigned part_ix = 0; part_ix < s->part_count; part_ix++) { + if (!s->inv_default_part_xstrs[part_ix]) { continue; } - const OtOTPPartDesc *part = &OtOTPPartDescs[ix]; + const OtOTPPartDesc *part = &s->part_descs[part_ix]; size_t len; - len = strlen(s->inv_default_part_xstrs[ix]); + len = strlen(s->inv_default_part_xstrs[part_ix]); if (len != part->size * 2u) { error_setg(&error_fatal, "%s: %s invalid inv_default_part[%u] length\n", __func__, - s->ot_id, ix); + s->ot_id, part_ix); return; } - g_assert(!s->inv_default_parts[ix]); + g_assert(!s->inv_default_parts[part_ix]); - s->inv_default_parts[ix] = g_new0(uint8_t, part->size + 1u); - if (ot_common_parse_hexa_str(s->inv_default_parts[ix], - s->inv_default_part_xstrs[ix], part->size, - false, true)) { + s->inv_default_parts[part_ix] = g_new0(uint8_t, part->size + 1u); + if (ot_common_parse_hexa_str(s->inv_default_parts[part_ix], + s->inv_default_part_xstrs[part_ix], + part->size, false, true)) { error_setg(&error_fatal, "%s: %s unable to parse inv_default_part[%u]\n", - __func__, s->ot_id, ix); + __func__, s->ot_id, part_ix); return; } - TRACE_OTP("inv_default_part[%s] %s", PART_NAME(ix), - ot_otp_hexdump(s, s->inv_default_parts[ix], part->size)); + TRACE_OTP("inv_default_part[%s] %s", ot_otp_dj_part_name(s, part_ix), + ot_otp_hexdump(s, s->inv_default_parts[part_ix], part->size)); } } -static void ot_otp_dj_class_add_inv_def_props(OtOTPClass *odc) +static void ot_otp_dj_add_inv_def_props(OtOTPDjState *s) { - for (unsigned ix = 0; ix < ARRAY_SIZE(OtOTPPartDescs); ix++) { - if (!OtOTPPartDescs[ix].buffered) { + s->inv_default_parts = g_new0(uint8_t *, s->part_count); + s->inv_default_part_xstrs = g_new0(char *, s->part_count); + + for (unsigned part_ix = 0; part_ix < s->part_count; part_ix++) { + if (!s->part_descs[part_ix].buffered) { continue; } Property *prop = g_new0(Property, 1u); - prop->name = g_strdup_printf("inv_default_part_%u", ix); + prop->name = g_strdup_printf("inv_default_part_%u", part_ix); prop->info = &qdev_prop_string; - prop->offset = offsetof(OtOTPDjState, inv_default_part_xstrs) + - sizeof(char *) * ix; + /* + * Property stores the address of the stored string as a relative offset + * from the parent address + */ + prop->offset = + (intptr_t)&s->inv_default_part_xstrs[part_ix] - (intptr_t)s; - object_class_property_add(OBJECT_CLASS(odc), prop->name, - prop->info->name, prop->info->get, - prop->info->set, prop->info->release, prop); + object_property_add(OBJECT(s), prop->name, prop->info->name, + prop->info->get, prop->info->set, + prop->info->release, prop); } } @@ -3956,7 +3998,7 @@ static const MemoryRegionOps ot_otp_dj_swcfg_ops = { static void ot_otp_dj_reset_enter(Object *obj, ResetType type) { - OtOTPClass *c = OT_OTP_GET_CLASS(obj); + OtOTPDjClass *c = OT_OTP_DJ_GET_CLASS(obj); OtOTPDjState *s = OT_OTP_DJ(obj); /* @@ -4026,21 +4068,21 @@ static void ot_otp_dj_reset_enter(Object *obj, ResetType type) ot_otp_dj_update_alerts(s); ibex_irq_set(&s->pwc_otp_rsp, 0); - for (unsigned ix = 0; ix < OTP_PART_COUNT; ix++) { + for (unsigned part_ix = 0; part_ix < s->part_count; part_ix++) { /* TODO: initialize with actual default partition data once known */ - if (OtOTPPartDescs[ix].buffered) { - s->partctrls[ix].state.b = OTP_BUF_IDLE; + if (s->part_descs[part_ix].buffered) { + s->part_ctrls[part_ix].state.b = OTP_BUF_IDLE; } else { - s->partctrls[ix].state.u = OTP_UNBUF_IDLE; + s->part_ctrls[part_ix].state.u = OTP_UNBUF_IDLE; continue; } - unsigned part_size = ot_otp_dj_part_data_byte_size(ix); - memset(s->partctrls[ix].buffer.data, 0, part_size); - s->partctrls[ix].digest = 0; - if (OtOTPPartDescs[ix].iskeymgr_creator || - OtOTPPartDescs[ix].iskeymgr_owner) { - s->partctrls[ix].read_lock = true; - s->partctrls[ix].write_lock = true; + unsigned part_size = ot_otp_dj_part_data_byte_size(s, part_ix); + memset(s->part_ctrls[part_ix].buffer.data, 0, part_size); + s->part_ctrls[part_ix].digest = 0; + if (s->part_descs[part_ix].iskeymgr_creator || + s->part_descs[part_ix].iskeymgr_owner) { + s->part_ctrls[part_ix].read_lock = true; + s->part_ctrls[part_ix].write_lock = true; } } DAI_CHANGE_STATE(s, OTP_DAI_RESET); @@ -4049,7 +4091,7 @@ static void ot_otp_dj_reset_enter(Object *obj, ResetType type) static void ot_otp_dj_reset_exit(Object *obj, ResetType type) { - OtOTPClass *c = OT_OTP_GET_CLASS(obj); + OtOTPDjClass *c = OT_OTP_DJ_GET_CLASS(obj); OtOTPDjState *s = OT_OTP_DJ(obj); trace_ot_otp_reset(s->ot_id, "exit"); @@ -4107,17 +4149,17 @@ static void ot_otp_dj_init(Object *obj) * - "swcfg", software config window * offset SW_CFG_WINDOW, size SW_CFG_WINDOW_SIZE */ - memory_region_init(&s->mmio.ctrl, obj, TYPE_OT_OTP "-ctrl", + memory_region_init(&s->mmio.ctrl, obj, TYPE_OT_OTP_DJ "-ctrl", SW_CFG_WINDOW + SW_CFG_WINDOW_SIZE); sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->mmio.ctrl); memory_region_init_io(&s->mmio.sub.regs, obj, &ot_otp_dj_reg_ops, s, - TYPE_OT_OTP "-regs", REGS_SIZE); + TYPE_OT_OTP_DJ "-regs", REGS_SIZE); memory_region_add_subregion(&s->mmio.ctrl, 0u, &s->mmio.sub.regs); /* TODO: it might be worthwhile to use a ROM-kind here */ memory_region_init_io(&s->mmio.sub.swcfg, obj, &ot_otp_dj_swcfg_ops, s, - TYPE_OT_OTP "-swcfg", SW_CFG_WINDOW_SIZE); + TYPE_OT_OTP_DJ "-swcfg", SW_CFG_WINDOW_SIZE); memory_region_add_subregion(&s->mmio.ctrl, SW_CFG_WINDOW, &s->mmio.sub.swcfg); @@ -4136,23 +4178,29 @@ static void ot_otp_dj_init(Object *obj) qdev_init_gpio_in_named(DEVICE(obj), &ot_otp_dj_lc_broadcast_recv, OT_LC_BROADCAST, OT_OTP_LC_BROADCAST_COUNT); + s->part_descs = OtOTPPartDescs; + s->part_count = ARRAY_SIZE(OtOTPPartDescs); + s->part_life_cycle = OTP_PART_LIFE_CYCLE; + s->hw_cfg = g_new0(OtOTPHWCfg, 1u); s->tokens = g_new0(OtOTPTokens, 1u); s->regs = g_new0(uint32_t, REGS_COUNT); s->dai = g_new0(OtOTPDAIController, 1u); s->lci = g_new0(OtOTPLCIController, 1u); - s->partctrls = g_new0(OtOTPPartController, OTP_PART_COUNT); + s->part_ctrls = g_new0(OtOTPPartController, s->part_count); s->keygen = g_new0(OtOTPKeyGen, 1u); s->otp = g_new0(OtOTPStorage, 1u); s->scrmbl_key_init = g_new0(OtOTPScrmblKeyInit, 1u); + s->lci->data = g_new0(uint16_t, s->part_descs[s->part_life_cycle].size / + sizeof(uint16_t)); - for (unsigned ix = 0; ix < OTP_PART_COUNT; ix++) { - if (!OtOTPPartDescs[ix].buffered) { + for (unsigned part_ix = 0; part_ix < s->part_count; part_ix++) { + if (!s->part_descs[part_ix].buffered) { continue; } size_t part_words = - ot_otp_dj_part_data_byte_size(ix) / sizeof(uint32_t); - s->partctrls[ix].buffer.data = g_new0(uint32_t, part_words); + ot_otp_dj_part_data_byte_size(s, part_ix) / sizeof(uint32_t); + s->part_ctrls[part_ix].buffer.data = g_new0(uint32_t, part_words); } ot_fifo32_create(&s->keygen->entropy_buf, OTP_ENTROPY_BUF_COUNT); @@ -4170,6 +4218,9 @@ static void ot_otp_dj_init(Object *obj) int64_t now = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); ot_prng_reseed(s->keygen->prng, (uint32_t)now); + ot_otp_dj_add_scramble_key_props(s); + ot_otp_dj_add_inv_def_props(s); + #ifdef OT_OTP_DEBUG s->hexstr = g_new0(char, OT_OTP_HEXSTR_SIZE); #endif @@ -4180,36 +4231,36 @@ static void ot_otp_dj_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); (void)data; - g_assert(OTP_PART_LIFE_CYCLE_SIZE == - OtOTPPartDescs[OTP_PART_LIFE_CYCLE].size); - dc->realize = &ot_otp_dj_realize; device_class_set_props(dc, ot_otp_dj_properties); set_bit(DEVICE_CATEGORY_MISC, dc->categories); ResettableClass *rc = RESETTABLE_CLASS(klass); - OtOTPClass *oc = OT_OTP_CLASS(klass); + OtOTPDjClass *djc = OT_OTP_DJ_CLASS(klass); resettable_class_set_parent_phases(rc, &ot_otp_dj_reset_enter, NULL, &ot_otp_dj_reset_exit, - &oc->parent_phases); + &djc->parent_phases); + OtOTPIfClass *oc = OT_OTP_IF_CLASS(klass); oc->get_lc_info = &ot_otp_dj_get_lc_info; oc->get_hw_cfg = &ot_otp_dj_get_hw_cfg; oc->get_otp_key = &ot_otp_dj_get_otp_key; oc->get_keymgr_secret = &ot_otp_dj_get_keymgr_secret; oc->program_req = &ot_otp_dj_program_req; - - ot_otp_dj_class_add_scramble_key_props(oc); - ot_otp_dj_class_add_inv_def_props(oc); } static const TypeInfo ot_otp_dj_info = { .name = TYPE_OT_OTP_DJ, - .parent = TYPE_OT_OTP, + .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(OtOTPDjState), .instance_init = &ot_otp_dj_init, - .class_size = sizeof(OtOTPClass), + .class_size = sizeof(OtOTPDjClass), .class_init = &ot_otp_dj_class_init, + .interfaces = + (InterfaceInfo[]){ + { TYPE_OT_OTP_IF }, + {}, + }, }; static void ot_otp_dj_register_types(void) diff --git a/hw/opentitan/ot_otp_dj_parts.c b/hw/opentitan/ot_otp_dj_parts.c index 411802ead16f5..2073bb692219d 100644 --- a/hw/opentitan/ot_otp_dj_parts.c +++ b/hw/opentitan/ot_otp_dj_parts.c @@ -10,6 +10,7 @@ /* NOLINTBEGIN */ static const OtOTPPartDesc OtOTPPartDescs[] = { [OTP_PART_VENDOR_TEST] = { + .name = "VENDOR_TEST", .size = 64u, .offset = 0u, .zer_offset = UINT16_MAX, @@ -25,6 +26,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .zeroizable = false, }, [OTP_PART_CREATOR_SW_CFG] = { + .name = "CREATOR_SW_CFG", .size = 304u, .offset = 64u, .zer_offset = UINT16_MAX, @@ -40,6 +42,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .zeroizable = false, }, [OTP_PART_OWNER_SW_CFG] = { + .name = "OWNER_SW_CFG", .size = 600u, .offset = 368u, .zer_offset = UINT16_MAX, @@ -55,6 +58,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .zeroizable = false, }, [OTP_PART_OWNERSHIP_SLOT_STATE] = { + .name = "OWNERSHIP_SLOT_STATE", .size = 48u, .offset = 968u, .zer_offset = UINT16_MAX, @@ -70,6 +74,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .zeroizable = false, }, [OTP_PART_ROT_CREATOR_AUTH] = { + .name = "ROT_CREATOR_AUTH", .size = 1424u, .offset = 1016u, .zer_offset = UINT16_MAX, @@ -85,6 +90,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .zeroizable = false, }, [OTP_PART_ROT_OWNER_AUTH_SLOT0] = { + .name = "ROT_OWNER_AUTH_SLOT0", .size = 328u, .offset = 2440u, .zer_offset = UINT16_MAX, @@ -100,6 +106,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .zeroizable = false, }, [OTP_PART_ROT_OWNER_AUTH_SLOT1] = { + .name = "ROT_OWNER_AUTH_SLOT1", .size = 328u, .offset = 2768u, .zer_offset = UINT16_MAX, @@ -115,6 +122,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .zeroizable = false, }, [OTP_PART_PLAT_INTEG_AUTH_SLOT0] = { + .name = "PLAT_INTEG_AUTH_SLOT0", .size = 328u, .offset = 3096u, .zer_offset = UINT16_MAX, @@ -130,6 +138,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .zeroizable = false, }, [OTP_PART_PLAT_INTEG_AUTH_SLOT1] = { + .name = "PLAT_INTEG_AUTH_SLOT1", .size = 328u, .offset = 3424u, .zer_offset = UINT16_MAX, @@ -145,6 +154,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .zeroizable = false, }, [OTP_PART_PLAT_OWNER_AUTH_SLOT0] = { + .name = "PLAT_OWNER_AUTH_SLOT0", .size = 328u, .offset = 3752u, .zer_offset = UINT16_MAX, @@ -160,6 +170,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .zeroizable = false, }, [OTP_PART_PLAT_OWNER_AUTH_SLOT1] = { + .name = "PLAT_OWNER_AUTH_SLOT1", .size = 328u, .offset = 4080u, .zer_offset = UINT16_MAX, @@ -175,6 +186,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .zeroizable = false, }, [OTP_PART_PLAT_OWNER_AUTH_SLOT2] = { + .name = "PLAT_OWNER_AUTH_SLOT2", .size = 328u, .offset = 4408u, .zer_offset = UINT16_MAX, @@ -190,6 +202,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .zeroizable = false, }, [OTP_PART_PLAT_OWNER_AUTH_SLOT3] = { + .name = "PLAT_OWNER_AUTH_SLOT3", .size = 328u, .offset = 4736u, .zer_offset = UINT16_MAX, @@ -205,6 +218,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .zeroizable = false, }, [OTP_PART_EXT_NVM] = { + .name = "EXT_NVM", .size = 1024u, .offset = 5064u, .zer_offset = UINT16_MAX, @@ -220,6 +234,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .zeroizable = false, }, [OTP_PART_ROM_PATCH] = { + .name = "ROM_PATCH", .size = 9864u, .offset = 6088u, .zer_offset = UINT16_MAX, @@ -235,6 +250,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .zeroizable = false, }, [OTP_PART_HW_CFG0] = { + .name = "HW_CFG0", .size = 72u, .offset = 15952u, .zer_offset = UINT16_MAX, @@ -249,6 +265,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .zeroizable = false, }, [OTP_PART_HW_CFG1] = { + .name = "HW_CFG1", .size = 16u, .offset = 16024u, .zer_offset = UINT16_MAX, @@ -263,6 +280,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .zeroizable = false, }, [OTP_PART_SECRET0] = { + .name = "SECRET0", .size = 48u, .offset = 16040u, .zer_offset = 16080u, @@ -277,6 +295,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .zeroizable = true, }, [OTP_PART_SECRET1] = { + .name = "SECRET1", .size = 32u, .offset = 16088u, .zer_offset = 16112u, @@ -291,6 +310,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .zeroizable = true, }, [OTP_PART_SECRET2] = { + .name = "SECRET2", .size = 128u, .offset = 16120u, .zer_offset = 16240u, @@ -306,6 +326,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .iskeymgr_creator = true, }, [OTP_PART_SECRET3] = { + .name = "SECRET3", .size = 48u, .offset = 16248u, .zer_offset = 16288u, @@ -321,6 +342,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .iskeymgr_owner = true, }, [OTP_PART_LIFE_CYCLE] = { + .name = "LIFE_CYCLE", .size = 88u, .offset = 16296u, .zer_offset = UINT16_MAX, diff --git a/hw/opentitan/ot_otp_eg.c b/hw/opentitan/ot_otp_eg.c index 068cc8e933c3b..f1bc11bb65ca9 100644 --- a/hw/opentitan/ot_otp_eg.c +++ b/hw/opentitan/ot_otp_eg.c @@ -41,6 +41,7 @@ #include "hw/opentitan/ot_lc_ctrl.h" #include "hw/opentitan/ot_otp_be_if.h" #include "hw/opentitan/ot_otp_eg.h" +#include "hw/opentitan/ot_otp_if.h" #include "hw/opentitan/ot_present.h" #include "hw/opentitan/ot_prng.h" #include "hw/opentitan/ot_pwrmgr.h" @@ -563,6 +564,7 @@ typedef enum { /* TODO: wr and rd lock need to be rewritten (not simple boolean) */ typedef struct { + const char *name; uint16_t size; uint16_t offset; uint16_t digest_offset; @@ -599,7 +601,7 @@ typedef struct { OtOTPUnbufState u; } state; struct { - uint32_t *data; /* size, see OtOTPPartDescs; w/o digest data */ + uint32_t *data; /* size, see OtOTPPartDesc w/o digest data */ uint64_t next_digest; /* computed HW digest to store into OTP cell */ } buffer; /* only meaningful for buffered partitions */ uint64_t digest; /* digest as read from OTP back end at init time */ @@ -622,7 +624,7 @@ typedef struct { OtOTPError error; ot_otp_program_ack_fn ack_fn; void *ack_data; - uint16_t data[OTP_PART_LIFE_CYCLE_SIZE / sizeof(uint16_t)]; + uint16_t *data; unsigned hpos; /* current offset in data */ } OtOTPLCIController; @@ -661,7 +663,7 @@ typedef struct { } OtOTPScrmblKeyInit; struct OtOTPEgState { - OtOTPState parent_obj; + SysBusDevice parent_obj; struct { MemoryRegion ctrl; @@ -681,7 +683,10 @@ struct OtOTPEgState { OtOTPLcBroadcast lc_broadcast; OtOTPDAIController *dai; OtOTPLCIController *lci; - OtOTPPartController *partctrls; + OtOTPPartController *part_ctrls; + const OtOTPPartDesc *part_descs; + unsigned part_count; + unsigned part_life_cycle; /* index of the Life Cycle partition */ OtOTPKeyGen *keygen; OtOTPScrmblKeyInit *scrmbl_key_init; OtOtpBeCharacteristics be_chars; @@ -694,8 +699,8 @@ struct OtOTPEgState { uint64_t flash_addr_iv; uint8_t flash_addr_const[16u]; /* OTP scrambling key constants, not constants for deriving other keys */ - uint8_t *otp_scramble_keys[ARRAY_SIZE(OtOTPPartDescs)]; /* may be NULL */ - uint8_t *inv_default_parts[ARRAY_SIZE(OtOTPPartDescs)]; /* may be NULL */ + uint8_t **otp_scramble_keys; /* some entries may be NULL */ + uint8_t **inv_default_parts; /* some entries may be NULL */ OtOTPStorage *otp; OtOTPHWCfg *hw_cfg; @@ -715,12 +720,17 @@ struct OtOTPEgState { char *flash_data_const_xstr; char *flash_addr_iv_xstr; char *flash_addr_const_xstr; - char *otp_scramble_key_xstrs[ARRAY_SIZE(OtOTPPartDescs)]; /* may be NULL */ - char *inv_default_part_xstrs[ARRAY_SIZE(OtOTPPartDescs)]; /* may be NULL */ + char **otp_scramble_key_xstrs; /* some entries may be NULL */ + char **inv_default_part_xstrs; /* some entries may be NULL */ uint8_t edn_ep; bool fatal_escalate; }; +struct OtOTPEgClass { + SysBusDeviceClass parent_class; + ResettablePhases parent_phases; +}; + #define REG_NAME_ENTRY(_reg_) [R_##_reg_] = stringify(_reg_) static const char *REG_NAMES[REGS_COUNT] = { /* clang-format off */ @@ -829,24 +839,9 @@ static const char *OTP_TOKEN_NAMES[] = { /* clang-format on */ }; -static const char *PART_NAMES[] = { - /* clang-format off */ - OTP_NAME_ENTRY(OTP_PART_VENDOR_TEST), - OTP_NAME_ENTRY(OTP_PART_CREATOR_SW_CFG), - OTP_NAME_ENTRY(OTP_PART_OWNER_SW_CFG), - OTP_NAME_ENTRY(OTP_PART_ROT_CREATOR_AUTH_CODESIGN), - OTP_NAME_ENTRY(OTP_PART_ROT_CREATOR_AUTH_STATE), - OTP_NAME_ENTRY(OTP_PART_HW_CFG0), - OTP_NAME_ENTRY(OTP_PART_HW_CFG1), - OTP_NAME_ENTRY(OTP_PART_SECRET0), - OTP_NAME_ENTRY(OTP_PART_SECRET1), - OTP_NAME_ENTRY(OTP_PART_SECRET2), - OTP_NAME_ENTRY(OTP_PART_LIFE_CYCLE), +/* clang-format off */ /* fake partitions */ - OTP_NAME_ENTRY(OTP_ENTRY_DAI), - OTP_NAME_ENTRY(OTP_ENTRY_KDI), - /* clang-format on */ -}; +/* clang-format on */ static const char *ERR_CODE_NAMES[] = { /* clang-format off */ @@ -883,8 +878,6 @@ static const char *ERR_CODE_NAMES[] = { ((unsigned)(_tk_) < ARRAY_SIZE(OTP_TOKEN_NAMES) ? \ OTP_TOKEN_NAMES[(_tk_)] : \ "?") -#define PART_NAME(_pt_) \ - (((unsigned)(_pt_)) < ARRAY_SIZE(PART_NAMES) ? PART_NAMES[(_pt_)] : "?") #define ERR_CODE_NAME(_err_) \ (((unsigned)(_err_)) < ARRAY_SIZE(ERR_CODE_NAMES) ? \ ERR_CODE_NAMES[(_err_)] : \ @@ -915,21 +908,6 @@ ot_otp_eg_lci_change_state_line(OtOTPEgState *s, OtOTPLCIState state, int line); #define ot_otp_hexdump(_s_, _b_, _l_) #endif -static inline unsigned ot_otp_eg_part_data_offset(unsigned pix) -{ - return (unsigned)(OtOTPPartDescs[pix].offset); -} - -static inline unsigned ot_otp_eg_part_data_byte_size(unsigned pix) -{ - size_t size = OtOTPPartDescs[pix].size; - - if (OtOTPPartDescs[pix].hw_digest || OtOTPPartDescs[pix].sw_digest) { - size -= sizeof(uint32_t) * NUM_DIGEST_WORDS; - } - - return (unsigned)size; -} static void ot_otp_eg_update_irqs(OtOTPEgState *s) { @@ -978,14 +956,50 @@ static void ot_otp_eg_update_alerts(OtOTPEgState *s) } } -static bool ot_otp_eg_is_wide_granule(unsigned part_ix, unsigned address) +static const char *ot_otp_eg_part_name(const OtOTPEgState *s, unsigned part_ix) +{ + if (part_ix < s->part_count) { + return s->part_descs[part_ix].name; + } + + if (part_ix == s->part_count) { + return "DAI"; + } + + if (part_ix == s->part_count + 1u) { + return "KDI"; + } + + return "?"; +} + +static inline unsigned +ot_otp_eg_part_data_offset(const OtOTPEgState *s, unsigned part_ix) +{ + return (unsigned)(s->part_descs[part_ix].offset); +} + +static inline unsigned +ot_otp_eg_part_data_byte_size(const OtOTPEgState *s, unsigned part_ix) +{ + size_t size = s->part_descs[part_ix].size; + + if (s->part_descs[part_ix].hw_digest || s->part_descs[part_ix].sw_digest) { + size -= sizeof(uint32_t) * NUM_DIGEST_WORDS; + } + + return (unsigned)size; +} + +static bool ot_otp_eg_is_wide_granule(const OtOTPEgState *s, unsigned part_ix, + unsigned address) { - if (part_ix < OTP_PART_COUNT) { - if (OtOTPPartDescs[part_ix].secret) { + if (part_ix < s->part_count) { + if (s->part_descs[part_ix].secret) { return true; } - if (OtOTPPartDescs[part_ix].digest_offset == + if (s->part_descs[part_ix].digest_offset == (address & OTP_DIGEST_ADDR_MASK)) { return true; } @@ -994,19 +1008,19 @@ static bool ot_otp_eg_is_wide_granule(unsigned part_ix, unsigned address) return false; } -static bool ot_otp_eg_is_buffered(unsigned part_ix) +static bool ot_otp_eg_is_buffered(const OtOTPEgState *s, unsigned part_ix) { - if (part_ix < OTP_PART_COUNT) { - return OtOTPPartDescs[part_ix].buffered; + if (part_ix < s->part_count) { + return s->part_descs[part_ix].buffered; } return false; } -static bool ot_otp_eg_is_secret(unsigned part_ix) +static bool ot_otp_eg_is_secret(const OtOTPEgState *s, unsigned part_ix) { - if (part_ix < OTP_PART_COUNT) { - return OtOTPPartDescs[part_ix].secret; + if (part_ix < s->part_count) { + return s->part_descs[part_ix].secret; } return false; @@ -1028,33 +1042,42 @@ static bool ot_otp_eg_is_ecc_enabled(const OtOTPEgState *s) ot_otp_eg_is_backend_ecc_enabled(s); } -static bool ot_otp_eg_has_digest(unsigned partition) +static bool ot_otp_eg_has_digest(const OtOTPEgState *s, unsigned part_ix) { - return OtOTPPartDescs[partition].hw_digest || - OtOTPPartDescs[partition].sw_digest; + return s->part_descs[part_ix].hw_digest || s->part_descs[part_ix].sw_digest; } +static bool ot_otp_eg_is_part_digest_offset(const OtOTPEgState *s, + unsigned part_ix, hwaddr addr) +{ + uint16_t offset = s->part_descs[part_ix].digest_offset; + + return (offset != UINT16_MAX) && ((addr & ~OTP_DIGEST_ADDR_MASK) == offset); +} + + static void ot_otp_eg_disable_all_partitions(OtOTPEgState *s) { DAI_CHANGE_STATE(s, OTP_DAI_ERROR); LCI_CHANGE_STATE(s, OTP_LCI_ERROR); - for (unsigned pix = 0; pix < OTP_PART_COUNT; pix++) { - OtOTPPartController *pctrl = &s->partctrls[pix]; + for (unsigned pix = 0; pix < s->part_count; pix++) { + OtOTPPartController *pctrl = &s->part_ctrls[pix]; pctrl->failed = true; } } -static void ot_otp_eg_set_error(OtOTPEgState *s, unsigned part, OtOTPError err) +static void ot_otp_eg_set_error(OtOTPEgState *s, unsigned part_ix, + OtOTPError err) { - g_assert(part < OTP_ENTRY_COUNT); + g_assert(part_ix < OTP_ENTRY_COUNT); uint32_t errval = ((uint32_t)err) & ERR_CODE_MASK; - if (errval || errval != s->regs[R_ERR_CODE_0 + part]) { - trace_ot_otp_set_error(s->ot_id, PART_NAME(part), part, - ERR_CODE_NAME(err), err); + if (errval || errval != s->regs[R_ERR_CODE_0 + part_ix]) { + trace_ot_otp_set_error(s->ot_id, ot_otp_eg_part_name(s, part_ix), + part_ix, ERR_CODE_NAME(err), err); } - s->regs[R_ERR_CODE_0 + part] = errval; + s->regs[R_ERR_CODE_0 + part_ix] = errval; switch (err) { case OTP_MACRO_ERROR: @@ -1112,13 +1135,13 @@ static uint32_t ot_otp_eg_get_status(const OtOTPEgState *s) static int ot_otp_eg_get_part_from_address(const OtOTPEgState *s, hwaddr addr) { - for (unsigned ix = 0; ix < OTP_PART_COUNT; ix++) { - const OtOTPPartDesc *part = &OtOTPPartDescs[ix]; + for (unsigned part_ix = 0; part_ix < s->part_count; part_ix++) { + const OtOTPPartDesc *part = &s->part_descs[part_ix]; if ((addr >= part->offset) && ((addr + sizeof(uint32_t)) <= (part->offset + part->size))) { - trace_ot_otp_addr_to_part(s->ot_id, (uint32_t)addr, PART_NAME(ix), - ix); - return (OtOTPPartitionType)ix; + trace_ot_otp_addr_to_part(s->ot_id, (uint32_t)addr, + ot_otp_eg_part_name(s, part_ix), part_ix); + return (OtOTPPartitionType)part_ix; } } @@ -1270,11 +1293,11 @@ static int ot_otp_eg_apply_ecc(OtOTPEgState *s, unsigned part_ix) { g_assert(ot_otp_eg_is_ecc_enabled(s)); - unsigned start = OtOTPPartDescs[part_ix].offset >> 2u; - unsigned end = - (ot_otp_eg_is_buffered((int)part_ix) && ot_otp_eg_has_digest(part_ix)) ? - (unsigned)(OtOTPPartDescs[part_ix].digest_offset >> 2u) : - start + (unsigned)(OtOTPPartDescs[part_ix].size >> 2u); + unsigned start = s->part_descs[part_ix].offset >> 2u; + unsigned end = (ot_otp_eg_is_buffered(s, (int)part_ix) && + ot_otp_eg_has_digest(s, part_ix)) ? + (unsigned)(s->part_descs[part_ix].digest_offset >> 2u) : + start + (unsigned)(s->part_descs[part_ix].size >> 2u); g_assert(start < end && (end / sizeof(uint32_t)) < s->otp->data_size); for (unsigned ix = start; ix < end; ix++) { @@ -1291,9 +1314,10 @@ static int ot_otp_eg_apply_ecc(OtOTPEgState *s, unsigned part_ix) */ ot_otp_eg_set_error(s, part_ix, otp_err); if (err > 1) { - trace_ot_otp_ecc_init_error(s->ot_id, PART_NAME(part_ix), + trace_ot_otp_ecc_init_error(s->ot_id, + ot_otp_eg_part_name(s, part_ix), part_ix, ix << 2u, *word, ecc); - s->partctrls[part_ix].failed = true; + s->part_ctrls[part_ix].failed = true; return -1; } } @@ -1304,9 +1328,9 @@ static int ot_otp_eg_apply_ecc(OtOTPEgState *s, unsigned part_ix) static uint64_t ot_otp_eg_get_part_digest(OtOTPEgState *s, unsigned part_ix) { - g_assert(!ot_otp_eg_is_buffered(part_ix)); + g_assert(!ot_otp_eg_is_buffered(s, part_ix)); - uint16_t offset = OtOTPPartDescs[part_ix].digest_offset; + uint16_t offset = s->part_descs[part_ix].digest_offset; if (offset == UINT16_MAX) { return 0u; @@ -1315,7 +1339,7 @@ static uint64_t ot_otp_eg_get_part_digest(OtOTPEgState *s, unsigned part_ix) const uint8_t *data = (const uint8_t *)s->otp->data; uint64_t digest = ldq_le_p(data + offset); - if (OtOTPPartDescs[part_ix].integrity && ot_otp_eg_is_ecc_enabled(s)) { + if (s->part_descs[part_ix].integrity && ot_otp_eg_is_ecc_enabled(s)) { unsigned waddr = offset >> 2u; unsigned ewaddr = waddr >> 1u; g_assert(ewaddr < s->otp->ecc_size); @@ -1326,13 +1350,6 @@ static uint64_t ot_otp_eg_get_part_digest(OtOTPEgState *s, unsigned part_ix) return digest; } -static bool ot_otp_eg_is_part_digest_offset(unsigned part_ix, hwaddr addr) -{ - uint16_t offset = OtOTPPartDescs[part_ix].digest_offset; - - return (offset != UINT16_MAX) && ((addr & ~OTP_DIGEST_ADDR_MASK) == offset); -} - static uint32_t ot_otp_eg_get_part_digest_reg(OtOTPEgState *s, uint32_t offset) { /* @@ -1361,8 +1378,8 @@ static uint32_t ot_otp_eg_get_part_digest_reg(OtOTPEgState *s, uint32_t offset) /* part_ix: the partition number in the global partition array */ unsigned part_ix = 0; /* traverse the partition array and count each partition with a digest */ - for (unsigned part_dig_ix = 0; part_ix < OTP_PART_COUNT; part_ix++) { - if (ot_otp_eg_has_digest(part_ix)) { + for (unsigned part_dig_ix = 0; part_ix < s->part_count; part_ix++) { + if (ot_otp_eg_has_digest(s, part_ix)) { /* * stop searching if we've found the part-with-digest defined from * the offset argument. Otherwise, increment the part-with-digest @@ -1380,11 +1397,10 @@ static uint32_t ot_otp_eg_get_part_digest_reg(OtOTPEgState *s, uint32_t offset) * with the partition table or the register definitions, as it is assumed * that LifeCycle partition is the last partition. */ - static_assert(OTP_PART_LIFE_CYCLE == NUM_PART - 1, - "LC is expected to be the last partition"); - g_assert(part_ix < OTP_PART_COUNT); + g_assert(s->part_life_cycle == s->part_count - 1u); + g_assert(part_ix < s->part_count); - const OtOTPPartController *pctrl = &s->partctrls[part_ix]; + const OtOTPPartController *pctrl = &s->part_ctrls[part_ix]; uint64_t digest = pctrl->digest; if (hi) { @@ -1394,12 +1410,20 @@ static uint32_t ot_otp_eg_get_part_digest_reg(OtOTPEgState *s, uint32_t offset) return (uint32_t)digest; } -static bool ot_otp_eg_is_readable(OtOTPEgState *s, unsigned part_ix) +static uint32_t +ot_otp_eg_get_sw_readlock(const OtOTPEgState *s, unsigned rdlk_ix) +{ + uint32_t reg = R_VENDOR_TEST_READ_LOCK + rdlk_ix; + + return (bool)SHARED_FIELD_EX32(s->regs[reg], READ_LOCK); +} + +static bool ot_otp_eg_is_readable(const OtOTPEgState *s, unsigned part_ix) { - g_assert(part_ix < OTP_PART_COUNT); + g_assert(part_ix < s->part_count); - const OtOTPPartDesc *pdesc = &OtOTPPartDescs[part_ix]; - const OtOTPPartController *pctrl = &s->partctrls[part_ix]; + const OtOTPPartDesc *pdesc = &s->part_descs[part_ix]; + const OtOTPPartController *pctrl = &s->part_ctrls[part_ix]; if (pdesc->secret) { /* secret partitions are only readable if digest is not yet set. */ @@ -1418,7 +1442,7 @@ static bool ot_otp_eg_is_readable(OtOTPEgState *s, unsigned part_ix) unsigned roffset = 0; unsigned pix; - for (pix = 0; pix < OTP_PART_COUNT; pix++) { + for (pix = 0; pix < s->part_count; pix++) { if (pix == part_ix) { break; } @@ -1432,21 +1456,19 @@ static bool ot_otp_eg_is_readable(OtOTPEgState *s, unsigned part_ix) * static_assert, but C being C, constants are not defined as such * at build time... */ - g_assert(!OtOTPPartDescs[OTP_PART_LIFE_CYCLE].read_lock_csr); + g_assert(!s->part_descs[s->part_life_cycle].read_lock_csr); /* * If the previous loop reached the last partition, something * seriously wrong occurred. Use this feature as a sanity check */ - g_assert(pix < OTP_PART_LIFE_CYCLE); + g_assert(pix < s->part_life_cycle); /* * now that the count of read_lock_csr is known, use it to access * the register for the selected partition */ - uint32_t reg = R_VENDOR_TEST_READ_LOCK + roffset; - - return (bool)SHARED_FIELD_EX32(s->regs[reg], READ_LOCK); + return ot_otp_eg_get_sw_readlock(s, roffset); } static void @@ -1530,18 +1552,18 @@ static void ot_otp_eg_lc_broadcast_bh(void *opaque) s->ot_id); break; case OT_OTP_LC_CREATOR_SEED_SW_RW_EN: - for (unsigned ix = 0; ix < OTP_PART_COUNT; ix++) { - if (OtOTPPartDescs[ix].iskeymgr_creator) { - s->partctrls[ix].read_lock = !level; - s->partctrls[ix].write_lock = !level; + for (unsigned ix = 0; ix < s->part_count; ix++) { + if (s->part_descs[ix].iskeymgr_creator) { + s->part_ctrls[ix].read_lock = !level; + s->part_ctrls[ix].write_lock = !level; } } break; case OT_OTP_LC_OWNER_SEED_SW_RW_EN: - for (unsigned ix = 0; ix < OTP_PART_COUNT; ix++) { - if (OtOTPPartDescs[ix].iskeymgr_owner) { - s->partctrls[ix].read_lock = !level; - s->partctrls[ix].write_lock = !level; + for (unsigned ix = 0; ix < s->part_count; ix++) { + if (s->part_descs[ix].iskeymgr_owner) { + s->part_ctrls[ix].read_lock = !level; + s->part_ctrls[ix].write_lock = !level; } } break; @@ -1594,7 +1616,7 @@ static uint64_t ot_otp_eg_compute_partition_digest( static uint64_t ot_otp_eg_load_partition_digest(OtOTPEgState *s, unsigned partition) { - unsigned digoff = (unsigned)OtOTPPartDescs[partition].digest_offset; + unsigned digoff = (unsigned)s->part_descs[partition].digest_offset; if ((digoff + sizeof(uint64_t)) > s->otp->data_size) { error_setg(&error_fatal, "%s: partition located outside storage?", @@ -1616,12 +1638,12 @@ ot_otp_eg_load_partition_digest(OtOTPEgState *s, unsigned partition) return digest; } -static void ot_otp_eg_unscramble_partition(OtOTPEgState *s, unsigned ix) +static void ot_otp_eg_unscramble_partition(OtOTPEgState *s, unsigned part_ix) { - OtOTPPartController *pctrl = &s->partctrls[ix]; + OtOTPPartController *pctrl = &s->part_ctrls[part_ix]; - unsigned offset = (unsigned)OtOTPPartDescs[ix].offset; - unsigned part_size = ot_otp_eg_part_data_byte_size(ix); + unsigned offset = (unsigned)s->part_descs[part_ix].offset; + unsigned part_size = ot_otp_eg_part_data_byte_size(s, part_ix); /* part_size should be a multiple of PRESENT block size */ g_assert((part_size & (sizeof(uint64_t) - 1u)) == 0u); @@ -1638,13 +1660,14 @@ static void ot_otp_eg_unscramble_partition(OtOTPEgState *s, unsigned ix) g_assert(pctrl->buffer.data != NULL); uint64_t *clear = (uint64_t *)pctrl->buffer.data; - const uint8_t *scrambling_key = s->otp_scramble_keys[ix]; + const uint8_t *scrambling_key = s->otp_scramble_keys[part_ix]; g_assert(scrambling_key); OtPresentState *ps = ot_present_new(); ot_present_init(ps, scrambling_key); - trace_ot_otp_unscramble_partition(s->ot_id, PART_NAME(ix), ix, part_size); + trace_ot_otp_unscramble_partition(s->ot_id, ot_otp_eg_part_name(s, part_ix), + part_ix, part_size); /* neither the digest block nor the zeroizable block are scrambled */ for (unsigned dix = 0u; dix < dword_count; dix++) { ot_present_decrypt(ps, scrambled[dix], &clear[dix]); @@ -1653,30 +1676,30 @@ static void ot_otp_eg_unscramble_partition(OtOTPEgState *s, unsigned ix) ot_present_free(ps); } -static void ot_otp_eg_bufferize_partition(OtOTPEgState *s, unsigned ix) +static void ot_otp_eg_bufferize_partition(OtOTPEgState *s, unsigned part_ix) { - OtOTPPartController *pctrl = &s->partctrls[ix]; + OtOTPPartController *pctrl = &s->part_ctrls[part_ix]; g_assert(pctrl->buffer.data != NULL); - if (OtOTPPartDescs[ix].hw_digest) { - pctrl->digest = ot_otp_eg_load_partition_digest(s, ix); + if (s->part_descs[part_ix].hw_digest) { + pctrl->digest = ot_otp_eg_load_partition_digest(s, part_ix); } else { pctrl->digest = 0; } - if (OtOTPPartDescs[ix].secret) { + if (s->part_descs[part_ix].secret) { /* secret partitions need to be unscrambled */ if (s->blk) { /* * nothing to unscramble if no OTP data is loaded * scrambling keys in this case may not be known */ - ot_otp_eg_unscramble_partition(s, ix); + ot_otp_eg_unscramble_partition(s, part_ix); } } else { - unsigned offset = (unsigned)OtOTPPartDescs[ix].offset; - unsigned part_size = ot_otp_eg_part_data_byte_size(ix); + unsigned offset = (unsigned)s->part_descs[part_ix].offset; + unsigned part_size = ot_otp_eg_part_data_byte_size(s, part_ix); const uint8_t *base = (const uint8_t *)s->otp->data; base += offset; @@ -1686,12 +1709,13 @@ static void ot_otp_eg_bufferize_partition(OtOTPEgState *s, unsigned ix) } static void -ot_otp_eg_check_buffered_partition_integrity(OtOTPEgState *s, unsigned ix) +ot_otp_eg_check_buffered_partition_integrity(OtOTPEgState *s, unsigned part_ix) { - OtOTPPartController *pctrl = &s->partctrls[ix]; + OtOTPPartController *pctrl = &s->part_ctrls[part_ix]; if (pctrl->digest == 0) { - trace_ot_otp_skip_digest(s->ot_id, PART_NAME(ix), ix); + trace_ot_otp_skip_digest(s->ot_id, ot_otp_eg_part_name(s, part_ix), + part_ix); pctrl->locked = false; return; } @@ -1701,27 +1725,28 @@ ot_otp_eg_check_buffered_partition_integrity(OtOTPEgState *s, unsigned ix) /* * digests are always calculated over the original data (scrambled or not) */ - const uint8_t *part_data = - ((const uint8_t *)s->otp->data) + ot_otp_eg_part_data_offset(ix); - unsigned part_size = ot_otp_eg_part_data_byte_size(ix); + const uint8_t *part_data = ((const uint8_t *)s->otp->data) + + ot_otp_eg_part_data_offset(s, part_ix); + unsigned part_size = ot_otp_eg_part_data_byte_size(s, part_ix); uint64_t digest = ot_otp_eg_compute_partition_digest(s, part_data, part_size); if (digest != pctrl->digest) { - trace_ot_otp_mismatch_digest(s->ot_id, PART_NAME(ix), ix, digest, - pctrl->digest); + trace_ot_otp_mismatch_digest(s->ot_id, ot_otp_eg_part_name(s, part_ix), + part_ix, digest, pctrl->digest); TRACE_OTP("compute digest of %s: %016" PRIx64 " from %s\n", - PART_NAME(ix), digest, + ot_otp_eg_part_name(s, part_ix), digest, ot_otp_hexdump(s, part_data, part_size)); pctrl->failed = true; /* this is a fatal error */ - ot_otp_eg_set_error(s, ix, OTP_CHECK_FAIL_ERROR); + ot_otp_eg_set_error(s, part_ix, OTP_CHECK_FAIL_ERROR); /* TODO: revert buffered part to default */ } else { - trace_ot_otp_integrity_report(s->ot_id, PART_NAME(ix), ix, "digest OK"); + trace_ot_otp_integrity_report(s->ot_id, ot_otp_eg_part_name(s, part_ix), + part_ix, "digest OK"); } } @@ -1797,7 +1822,8 @@ static void ot_otp_eg_dai_read(OtOTPEgState *s) return; } - if (partition >= OTP_PART_LIFE_CYCLE) { + unsigned part_ix = (unsigned)partition; + if (part_ix >= OTP_PART_LIFE_CYCLE) { qemu_log_mask( LOG_GUEST_ERROR, "%s: %s: life cycle partition cannot be accessed from DAI\n", @@ -1806,33 +1832,32 @@ static void ot_otp_eg_dai_read(OtOTPEgState *s) return; } - const OtOTPPartController *pctrl = &s->partctrls[partition]; + const OtOTPPartController *pctrl = &s->part_ctrls[part_ix]; if (pctrl->failed) { qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: partition %s is disabled\n", - __func__, s->ot_id, PART_NAME(partition)); + __func__, s->ot_id, ot_otp_eg_part_name(s, part_ix)); return; } - unsigned part_ix = (unsigned)partition; bool is_readable = ot_otp_eg_is_readable(s, part_ix); - bool is_wide = ot_otp_eg_is_wide_granule(part_ix, address); - bool is_buffered = ot_otp_eg_is_buffered(part_ix); - bool is_secret = ot_otp_eg_is_secret(part_ix); - bool is_digest = ot_otp_eg_is_part_digest_offset(part_ix, address); + bool is_wide = ot_otp_eg_is_wide_granule(s, part_ix, address); + bool is_buffered = ot_otp_eg_is_buffered(s, part_ix); + bool is_secret = ot_otp_eg_is_secret(s, part_ix); + bool is_digest = ot_otp_eg_is_part_digest_offset(s, part_ix, address); /* "in all partitions, the digest itself is ALWAYS readable." */ if (!is_digest && !is_readable) { qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: partition %s @ 0x%04x not readable\n", __func__, - s->ot_id, PART_NAME(partition), address); + s->ot_id, ot_otp_eg_part_name(s, part_ix), address); ot_otp_eg_dai_set_error(s, OTP_ACCESS_ERROR); return; } - unsigned part_offset = address - ot_otp_eg_part_data_offset(partition); + unsigned part_offset = address - ot_otp_eg_part_data_offset(s, part_ix); unsigned part_waddr = part_offset >> 2u; bool do_ecc = - OtOTPPartDescs[part_ix].integrity && ot_otp_eg_is_ecc_enabled(s); + s->part_descs[part_ix].integrity && ot_otp_eg_is_ecc_enabled(s); DAI_CHANGE_STATE(s, OTP_DAI_READ_WAIT); @@ -1842,14 +1867,14 @@ static void ot_otp_eg_dai_read(OtOTPEgState *s) const uint32_t *data = (const uint32_t *)s->otp->data; /* parenthesis inform the C linter sizeof() call is valid with 'data */ - data += (ot_otp_eg_part_data_offset(partition) / sizeof(uint32_t)); + data += (ot_otp_eg_part_data_offset(s, part_ix) / sizeof(uint32_t)); if (is_wide || is_digest) { /* 64-bit requests */ part_waddr &= ~0b1u; g_assert((part_waddr + 1u) * sizeof(uint32_t) < - OtOTPPartDescs[partition].size); + s->part_descs[part_ix].size); data_lo = data[part_waddr]; data_hi = data[part_waddr + 1u]; @@ -1867,8 +1892,7 @@ static void ot_otp_eg_dai_read(OtOTPEgState *s) cell_count *= 2u; } else { /* 32-bit request */ - g_assert(part_waddr * sizeof(uint32_t) < - OtOTPPartDescs[partition].size); + g_assert(part_waddr * sizeof(uint32_t) < s->part_descs[part_ix].size); data_lo = data[part_waddr]; data_hi = 0u; @@ -1894,7 +1918,7 @@ static void ot_otp_eg_dai_read(OtOTPEgState *s) * if the partition is a secret partition, OTP storage is scrambled * except the digest and the zeroification fields */ - const uint8_t *scrambling_key = s->otp_scramble_keys[partition]; + const uint8_t *scrambling_key = s->otp_scramble_keys[part_ix]; g_assert(scrambling_key); uint64_t tmp_data = ((uint64_t)data_hi << 32u) | data_lo; OtPresentState *ps = ot_present_new(); @@ -1939,7 +1963,7 @@ static int ot_otp_eg_dai_write_u64(OtOTPEgState *s, unsigned address) uint32_t hi = s->regs[R_DIRECT_ACCESS_WDATA_1]; unsigned part_ix = (unsigned)s->dai->partition; - bool is_secret = ot_otp_eg_is_secret(part_ix); + bool is_secret = ot_otp_eg_is_secret(s, part_ix); if (is_secret) { const uint8_t *scrambling_key = s->otp_scramble_keys[part_ix]; @@ -1996,7 +2020,9 @@ static int ot_otp_eg_dai_write_u64(OtOTPEgState *s, unsigned address) return -1; } - trace_ot_otp_dai_new_dword_ecc(s->ot_id, PART_NAME(s->dai->partition), + trace_ot_otp_dai_new_dword_ecc(s->ot_id, + ot_otp_eg_part_name(s, (unsigned)s->dai + ->partition), s->dai->partition, *dst, *edst); } @@ -2049,7 +2075,9 @@ static int ot_otp_eg_dai_write_u32(OtOTPEgState *s, unsigned address) return -1; } - trace_ot_otp_dai_new_word_ecc(s->ot_id, PART_NAME(s->dai->partition), + trace_ot_otp_dai_new_word_ecc(s->ot_id, + ot_otp_eg_part_name(s, (unsigned)s->dai + ->partition), s->dai->partition, *dst, *edst); } @@ -2091,7 +2119,7 @@ static void ot_otp_eg_dai_write(OtOTPEgState *s) unsigned part_ix = (unsigned)partition; - if (part_ix >= OTP_PART_LIFE_CYCLE) { + if (part_ix >= s->part_life_cycle) { qemu_log_mask( LOG_GUEST_ERROR, "%s: %s: Life cycle partition cannot be accessed from DAI\n", @@ -2100,17 +2128,18 @@ static void ot_otp_eg_dai_write(OtOTPEgState *s) return; } - OtOTPPartController *pctrl = &s->partctrls[part_ix]; + OtOTPPartController *pctrl = &s->part_ctrls[part_ix]; if (pctrl->failed) { qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: partition %s is disabled\n", - __func__, s->ot_id, PART_NAME(part_ix)); + __func__, s->ot_id, ot_otp_eg_part_name(s, part_ix)); return; } if (pctrl->locked) { qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: partition %s (%u) is locked\n", - __func__, s->ot_id, PART_NAME(part_ix), part_ix); + __func__, s->ot_id, ot_otp_eg_part_name(s, part_ix), + part_ix); ot_otp_eg_dai_set_error(s, OTP_ACCESS_ERROR); return; } @@ -2118,22 +2147,22 @@ static void ot_otp_eg_dai_write(OtOTPEgState *s) if (pctrl->write_lock) { qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: artition %s (%u) is write locked\n", __func__, - s->ot_id, PART_NAME(part_ix), part_ix); + s->ot_id, ot_otp_eg_part_name(s, part_ix), part_ix); ot_otp_eg_dai_set_error(s, OTP_ACCESS_ERROR); return; } - bool is_digest = ot_otp_eg_is_part_digest_offset(part_ix, address); - bool is_wide = ot_otp_eg_is_wide_granule(part_ix, address); + bool is_digest = ot_otp_eg_is_part_digest_offset(s, part_ix, address); + bool is_wide = ot_otp_eg_is_wide_granule(s, part_ix, address); if (is_digest) { - if (OtOTPPartDescs[partition].hw_digest) { + if (s->part_descs[part_ix].hw_digest) { /* should have been a Digest command, not a Write command */ qemu_log_mask( LOG_GUEST_ERROR, "%s: %s: partition %s (%u) HW digest cannot be directly " "written\n", - __func__, s->ot_id, PART_NAME(part_ix), part_ix); + __func__, s->ot_id, ot_otp_eg_part_name(s, part_ix), part_ix); ot_otp_eg_dai_set_error(s, OTP_ACCESS_ERROR); return; } @@ -2199,7 +2228,9 @@ static void ot_otp_eg_dai_digest(OtOTPEgState *s) return; } - if (partition >= OTP_PART_LIFE_CYCLE) { + unsigned part_ix = (unsigned)partition; + + if (part_ix >= s->part_life_cycle) { qemu_log_mask( LOG_GUEST_ERROR, "%s: %s: Life cycle partition cannot be accessed from DAI\n", @@ -2208,25 +2239,27 @@ static void ot_otp_eg_dai_digest(OtOTPEgState *s) return; } - if (!OtOTPPartDescs[partition].hw_digest) { + if (!s->part_descs[part_ix].hw_digest) { qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: Invalid partition, no HW digest on %s (#%u)\n", - __func__, s->ot_id, PART_NAME(partition), partition); + __func__, s->ot_id, ot_otp_eg_part_name(s, part_ix), + part_ix); ot_otp_eg_dai_set_error(s, OTP_ACCESS_ERROR); return; } - OtOTPPartController *pctrl = &s->partctrls[partition]; + OtOTPPartController *pctrl = &s->part_ctrls[part_ix]; if (pctrl->failed) { qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: partition %s is disabled\n", - __func__, s->ot_id, PART_NAME(partition)); + __func__, s->ot_id, ot_otp_eg_part_name(s, part_ix)); return; } if (pctrl->locked) { qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: Partition %s (%u) is locked\n", - __func__, s->ot_id, PART_NAME(partition), partition); + __func__, s->ot_id, ot_otp_eg_part_name(s, part_ix), + part_ix); ot_otp_eg_dai_set_error(s, OTP_ACCESS_ERROR); return; } @@ -2234,16 +2267,16 @@ static void ot_otp_eg_dai_digest(OtOTPEgState *s) if (pctrl->write_lock) { qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: Partition %s (%u) is write locked\n", __func__, - s->ot_id, PART_NAME(partition), partition); + s->ot_id, ot_otp_eg_part_name(s, part_ix), part_ix); ot_otp_eg_dai_set_error(s, OTP_ACCESS_ERROR); return; } DAI_CHANGE_STATE(s, OTP_DAI_DIG_READ); - const uint8_t *data = - ((const uint8_t *)s->otp->data) + ot_otp_eg_part_data_offset(partition); - unsigned part_size = ot_otp_eg_part_data_byte_size(partition); + const uint8_t *data = ((const uint8_t *)s->otp->data) + + ot_otp_eg_part_data_offset(s, part_ix); + unsigned part_size = ot_otp_eg_part_data_byte_size(s, part_ix); DAI_CHANGE_STATE(s, OTP_DAI_DIG); @@ -2266,12 +2299,13 @@ static void ot_otp_eg_dai_write_digest(void *opaque) { OtOTPEgState *s = OT_OTP_EG(opaque); - g_assert((s->dai->partition >= 0) && (s->dai->partition < OTP_PART_COUNT)); + g_assert((s->dai->partition >= 0) && (s->dai->partition < s->part_count)); DAI_CHANGE_STATE(s, OTP_DAI_WRITE); - OtOTPPartController *pctrl = &s->partctrls[s->dai->partition]; - unsigned address = OtOTPPartDescs[s->dai->partition].digest_offset; + unsigned part_ix = (unsigned)s->dai->partition; + OtOTPPartController *pctrl = &s->part_ctrls[part_ix]; + unsigned address = s->part_descs[part_ix].digest_offset; unsigned dwaddr = address / sizeof(uint64_t); uint64_t *dst = &((uint64_t *)s->otp->data)[dwaddr]; uint64_t data = pctrl->buffer.next_digest; @@ -2315,8 +2349,8 @@ static void ot_otp_eg_dai_write_digest(void *opaque) return; } - trace_ot_otp_dai_new_digest_ecc(s->ot_id, PART_NAME(s->dai->partition), - s->dai->partition, *dst, *edst); + trace_ot_otp_dai_new_digest_ecc(s->ot_id, ot_otp_eg_part_name(s, part_ix), + part_ix, *dst, *edst); DAI_CHANGE_STATE(s, OTP_DAI_WRITE_WAIT); @@ -2333,8 +2367,10 @@ static void ot_otp_eg_dai_complete(void *opaque) switch (s->dai->state) { case OTP_DAI_READ_WAIT: g_assert(s->dai->partition >= 0); - trace_ot_otp_dai_read(s->ot_id, PART_NAME(s->dai->partition), - s->dai->partition, + trace_ot_otp_dai_read(s->ot_id, + ot_otp_eg_part_name(s, + (unsigned)s->dai->partition), + (unsigned)s->dai->partition, s->regs[R_DIRECT_ACCESS_RDATA_1], s->regs[R_DIRECT_ACCESS_RDATA_1]); s->dai->partition = -1; @@ -2716,10 +2752,9 @@ static MemTxResult ot_otp_eg_swcfg_read_with_attrs( void *opaque, hwaddr addr, uint64_t *data, unsigned size, MemTxAttrs attrs) { OtOTPEgState *s = OT_OTP_EG(opaque); + (void)size; (void)attrs; - g_assert(addr + size <= SW_CFG_WINDOW_SIZE); - hwaddr reg = R32_OFF(addr); int partition = ot_otp_eg_get_part_from_address(s, addr); @@ -2732,7 +2767,7 @@ static MemTxResult ot_otp_eg_swcfg_read_with_attrs( unsigned part_ix = (unsigned)partition; - if (ot_otp_eg_is_buffered(part_ix)) { + if (ot_otp_eg_is_buffered(s, part_ix)) { trace_ot_otp_access_error_on(s->ot_id, partition, addr, "buffered"); ot_otp_eg_set_error(s, part_ix, OTP_ACCESS_ERROR); @@ -2741,7 +2776,7 @@ static MemTxResult ot_otp_eg_swcfg_read_with_attrs( } bool is_readable = ot_otp_eg_is_readable(s, part_ix); - bool is_digest = ot_otp_eg_is_part_digest_offset(part_ix, addr); + bool is_digest = ot_otp_eg_is_part_digest_offset(s, part_ix, addr); if (!is_readable && !is_digest) { trace_ot_otp_access_error_on(s->ot_id, partition, addr, "not readable"); @@ -2765,10 +2800,10 @@ static MemTxResult ot_otp_eg_swcfg_read_with_attrs( } static void ot_otp_eg_get_lc_info( - const OtOTPState *s, uint16_t *lc_tcount, uint16_t *lc_state, + const OtOTPIf *dev, uint16_t *lc_tcount, uint16_t *lc_state, uint8_t *lc_valid, uint8_t *secret_valid, const OtOTPTokens **tokens) { - const OtOTPEgState *es = OT_OTP_EG(s); + const OtOTPEgState *es = OT_OTP_EG(dev); const OtOTPStorage *otp = es->otp; if (lc_tcount) { @@ -2781,15 +2816,15 @@ static void ot_otp_eg_get_lc_info( } if (lc_valid) { - *lc_valid = !(es->partctrls[OTP_PART_SECRET0].failed || - es->partctrls[OTP_PART_SECRET2].failed || - es->partctrls[OTP_PART_LIFE_CYCLE].failed) ? + *lc_valid = !(es->part_ctrls[OTP_PART_SECRET0].failed || + es->part_ctrls[OTP_PART_SECRET2].failed || + es->part_ctrls[OTP_PART_LIFE_CYCLE].failed) ? OT_MULTIBITBOOL_LC4_TRUE : OT_MULTIBITBOOL_LC4_FALSE; } if (secret_valid) { - *secret_valid = (!es->partctrls[OTP_PART_SECRET2].failed && - es->partctrls[OTP_PART_SECRET2].locked) ? + *secret_valid = (!es->part_ctrls[OTP_PART_SECRET2].failed && + es->part_ctrls[OTP_PART_SECRET2].locked) ? OT_MULTIBITBOOL_LC4_TRUE : OT_MULTIBITBOOL_LC4_FALSE; } @@ -2798,9 +2833,9 @@ static void ot_otp_eg_get_lc_info( } } -static const OtOTPHWCfg *ot_otp_eg_get_hw_cfg(const OtOTPState *s) +static const OtOTPHWCfg *ot_otp_eg_get_hw_cfg(const OtOTPIf *dev) { - const OtOTPEgState *es = OT_OTP_EG(s); + const OtOTPEgState *es = OT_OTP_EG(dev); return (const OtOTPHWCfg *)es->hw_cfg; } @@ -2919,10 +2954,10 @@ static void ot_otp_eg_generate_scrambling_key( OtPresentState *ps = s->keygen->present; /* read the key seed from the OTP SECRET1 partition */ - OtOTPPartController *pctrl = &s->partctrls[OTP_PART_SECRET1]; - g_assert(ot_otp_eg_is_buffered(OTP_PART_SECRET1)); + OtOTPPartController *pctrl = &s->part_ctrls[OTP_PART_SECRET1]; + g_assert(ot_otp_eg_is_buffered(s, OTP_PART_SECRET1)); uint32_t poffset = - OtOTPPartDescs[OTP_PART_SECRET1].offset / sizeof(uint32_t); + s->part_descs[OTP_PART_SECRET1].offset / sizeof(uint32_t); const uint32_t *key_seed = &pctrl->buffer.data[key_reg - poffset]; /* check the key seed's validity */ @@ -2966,10 +3001,10 @@ static void ot_otp_eg_generate_scrambling_key( } } -static void ot_otp_eg_get_otp_key(OtOTPState *s, OtOTPKeyType type, +static void ot_otp_eg_get_otp_key(OtOTPIf *dev, OtOTPKeyType type, OtOTPKey *key) { - OtOTPEgState *es = OT_OTP_EG(s); + OtOTPEgState *es = OT_OTP_EG(dev); hwaddr key_offset; @@ -3029,9 +3064,9 @@ static void ot_otp_eg_get_otp_key(OtOTPState *s, OtOTPKeyType type, } static void ot_otp_eg_get_keymgr_secret( - OtOTPState *s, OtOTPKeyMgrSecretType type, OtOTPKeyMgrSecret *secret) + OtOTPIf *dev, OtOTPKeyMgrSecretType type, OtOTPKeyMgrSecret *secret) { - OtOTPEgState *es = OT_OTP_EG(s); + OtOTPEgState *es = OT_OTP_EG(dev); int partition; size_t offset; @@ -3039,12 +3074,12 @@ static void ot_otp_eg_get_keymgr_secret( case OTP_KEYMGR_SECRET_CREATOR_ROOT_KEY_SHARE0: partition = OTP_PART_SECRET2; offset = A_SECRET2_CREATOR_ROOT_KEY_SHARE0 - - OtOTPPartDescs[partition].offset; + es->part_descs[partition].offset; break; case OTP_KEYMGR_SECRET_CREATOR_ROOT_KEY_SHARE1: partition = OTP_PART_SECRET2; offset = A_SECRET2_CREATOR_ROOT_KEY_SHARE1 - - OtOTPPartDescs[partition].offset; + es->part_descs[partition].offset; break; case OTP_KEYMGR_SECRET_CREATOR_SEED: case OTP_KEYMGR_SECRET_OWNER_SEED: @@ -3057,25 +3092,25 @@ static void ot_otp_eg_get_keymgr_secret( } unsigned part_ix = (unsigned)partition; - g_assert(ot_otp_eg_is_buffered(part_ix)); + g_assert(ot_otp_eg_is_buffered(es, part_ix)); const uint8_t *data_ptr; if (es->lc_broadcast.current_level & BIT(OT_OTP_LC_SEED_HW_RD_EN)) { - data_ptr = (const uint8_t *)es->partctrls[part_ix].buffer.data; + data_ptr = (const uint8_t *)es->part_ctrls[part_ix].buffer.data; } else { /* source data from PartInvDefault instead of real buffer */ data_ptr = es->inv_default_parts[part_ix]; } - secret->valid = es->partctrls[part_ix].digest != 0; + secret->valid = es->part_ctrls[part_ix].digest != 0; memcpy(secret->secret, &data_ptr[offset], OT_OTP_KEYMGR_SECRET_SIZE); } -static bool ot_otp_eg_program_req(OtOTPState *s, const uint16_t *lc_tcount, +static bool ot_otp_eg_program_req(OtOTPIf *dev, const uint16_t *lc_tcount, const uint16_t *lc_state, ot_otp_program_ack_fn ack, void *opaque) { - OtOTPEgState *es = OT_OTP_EG(s); + OtOTPEgState *es = OT_OTP_EG(dev); OtOTPLCIController *lci = es->lci; switch (lci->state) { @@ -3105,7 +3140,7 @@ static bool ot_otp_eg_program_req(OtOTPState *s, const uint16_t *lc_tcount, memcpy(&lci->data[hpos], lc_state, LC_STATE_SIZE); hpos += LC_STATE_SIZE / sizeof(uint16_t); g_assert(hpos == - OtOTPPartDescs[OTP_PART_LIFE_CYCLE].size / sizeof(uint16_t)); + es->part_descs[OTP_PART_LIFE_CYCLE].size / sizeof(uint16_t)); /* current position in LC buffer to write to backend */ lci->hpos = 0u; @@ -3130,7 +3165,7 @@ static void ot_otp_eg_lci_write_complete(OtOTPEgState *s, bool success) * if the LC partition has been modified somehow, even if the request * has failed, update the backend file */ - const OtOTPPartDesc *lcdesc = &OtOTPPartDescs[OTP_PART_LIFE_CYCLE]; + const OtOTPPartDesc *lcdesc = &s->part_descs[s->part_life_cycle]; unsigned lc_off = lcdesc->offset / sizeof(uint32_t); uintptr_t offset = (uintptr_t)s->otp->data - (uintptr_t)s->otp->storage; if (ot_otp_eg_write_backend(s, &s->otp->data[lc_off], @@ -3167,7 +3202,7 @@ static void ot_otp_eg_lci_write_complete(OtOTPEgState *s, bool success) lci->hpos = 0u; if (!success && lci->error != OTP_NO_ERROR) { - ot_otp_eg_set_error(s, OTP_PART_LIFE_CYCLE, lci->error); + ot_otp_eg_set_error(s, s->part_life_cycle, lci->error); } (*ack_fn)(ack_data, success); @@ -3177,7 +3212,7 @@ static void ot_otp_eg_lci_write_word(void *opaque) { OtOTPEgState *s = OT_OTP_EG(opaque); OtOTPLCIController *lci = s->lci; - const OtOTPPartDesc *lcdesc = &OtOTPPartDescs[OTP_PART_LIFE_CYCLE]; + const OtOTPPartDesc *lcdesc = &s->part_descs[s->part_life_cycle]; /* should not be called if already in error */ if (lci->state == OTP_LCI_ERROR) { @@ -3319,8 +3354,8 @@ static void ot_otp_eg_pwr_load(OtOTPEgState *s) size_t data_size = 0u; size_t ecc_size = 0u; - for (unsigned ix = 0u; ix < OTP_PART_COUNT; ix++) { - size_t psize = (size_t)OtOTPPartDescs[ix].size; + for (unsigned part_ix = 0u; part_ix < s->part_count; part_ix++) { + size_t psize = (size_t)s->part_descs[part_ix].size; size_t dsize = ROUND_UP(psize, sizeof(uint64_t)); data_size += dsize; /* up to 1 ECC byte for 2 data bytes */ @@ -3446,15 +3481,15 @@ static void ot_otp_eg_pwr_load_tokens(OtOTPEgState *s) switch (tkx) { case OTP_TOKEN_TEST_UNLOCK: - partition = OTP_PART_SECRET0; + partition = (unsigned)OTP_PART_SECRET0; secret_addr = A_SECRET0_TEST_UNLOCK_TOKEN; break; case OTP_TOKEN_TEST_EXIT: - partition = OTP_PART_SECRET0; + partition = (unsigned)OTP_PART_SECRET0; secret_addr = A_SECRET0_TEST_EXIT_TOKEN; break; case OTP_TOKEN_RMA: - partition = OTP_PART_SECRET2; + partition = (unsigned)OTP_PART_SECRET2; secret_addr = A_SECRET2_RMA_TOKEN; break; default: @@ -3462,12 +3497,12 @@ static void ot_otp_eg_pwr_load_tokens(OtOTPEgState *s) break; } - OtOTPPartController *pctrl = &s->partctrls[partition]; + OtOTPPartController *pctrl = &s->part_ctrls[partition]; g_assert(pctrl->buffer.data != NULL); /* byte offset of the secret within the partition */ unsigned secret_offset = - secret_addr - ot_otp_eg_part_data_offset(partition); + secret_addr - ot_otp_eg_part_data_offset(s, partition); g_assert(secret_offset + sizeof(OtOTPTokenValue) <= OtOTPPartDescs[partition].size); @@ -3475,7 +3510,7 @@ static void ot_otp_eg_pwr_load_tokens(OtOTPEgState *s) memcpy(&value, &pctrl->buffer.data[secret_offset / sizeof(uint32_t)], sizeof(OtOTPTokenValue)); - if (s->partctrls[partition].locked) { + if (s->part_ctrls[partition].locked) { tokens->values[tkx] = value; tokens->valid_bm |= 1u << tkx; } @@ -3488,25 +3523,25 @@ static void ot_otp_eg_pwr_load_tokens(OtOTPEgState *s) static void ot_otp_eg_pwr_initialize_partitions(OtOTPEgState *s) { - for (unsigned ix = 0; ix < OTP_PART_COUNT; ix++) { + for (unsigned ix = 0; ix < s->part_count; ix++) { /* sanity check: all secret partitions are also buffered */ - g_assert(!OtOTPPartDescs[ix].secret || OtOTPPartDescs[ix].buffered); + g_assert(!s->part_descs[ix].secret || s->part_descs[ix].buffered); - if (ot_otp_eg_is_ecc_enabled(s) && OtOTPPartDescs[ix].integrity) { + if (ot_otp_eg_is_ecc_enabled(s) && s->part_descs[ix].integrity) { if (ot_otp_eg_apply_ecc(s, ix)) { continue; } } - if (OtOTPPartDescs[ix].sw_digest) { - s->partctrls[ix].digest = ot_otp_eg_get_part_digest(s, ix); - s->partctrls[ix].locked = s->partctrls[ix].digest != 0; + if (s->part_descs[ix].sw_digest) { + s->part_ctrls[ix].digest = ot_otp_eg_get_part_digest(s, ix); + s->part_ctrls[ix].locked = s->part_ctrls[ix].digest != 0; continue; } - if (OtOTPPartDescs[ix].buffered) { + if (s->part_descs[ix].buffered) { ot_otp_eg_bufferize_partition(s, ix); - if (OtOTPPartDescs[ix].hw_digest) { + if (s->part_descs[ix].hw_digest) { ot_otp_eg_check_buffered_partition_integrity(s, ix); } continue; @@ -3773,54 +3808,65 @@ static void ot_otp_eg_configure_sram(OtOTPEgState *s) static void ot_otp_eg_configure_part_scramble_keys(OtOTPEgState *s) { - for (unsigned ix = 0u; ix < ARRAY_SIZE(OtOTPPartDescs); ix++) { - if (!OtOTPPartDescs[ix].secret) { + for (unsigned part_ix = 0u; part_ix < s->part_count; part_ix++) { + if (!s->part_descs[part_ix].secret) { continue; } - if (!s->otp_scramble_key_xstrs[ix]) { + if (!s->otp_scramble_key_xstrs[part_ix]) { /* if OTP data is loaded, unscrambling keys are mandatory */ if (s->blk) { error_setg(&error_fatal, "%s: %s Missing OTP scrambling key for part %s (%u)", - __func__, s->ot_id, PART_NAME(ix), ix); + __func__, s->ot_id, ot_otp_eg_part_name(s, part_ix), + part_ix); return; } continue; } - size_t len = strlen(s->otp_scramble_key_xstrs[ix]); + size_t len = strlen(s->otp_scramble_key_xstrs[part_ix]); if (len != OTP_SCRAMBLING_KEY_BYTES * 2u) { error_setg( &error_fatal, "%s: %s Invalid OTP scrambling key length %zu for part %s (%u)", - __func__, s->ot_id, len, PART_NAME(ix), ix); + __func__, s->ot_id, len, ot_otp_eg_part_name(s, part_ix), + part_ix); return; } - g_assert(!s->otp_scramble_keys[ix]); + g_assert(!s->otp_scramble_keys[part_ix]); - s->otp_scramble_keys[ix] = g_new0(uint8_t, OTP_SCRAMBLING_KEY_BYTES); - if (ot_common_parse_hexa_str(s->otp_scramble_keys[ix], - s->otp_scramble_key_xstrs[ix], + s->otp_scramble_keys[part_ix] = + g_new0(uint8_t, OTP_SCRAMBLING_KEY_BYTES); + if (ot_common_parse_hexa_str(s->otp_scramble_keys[part_ix], + s->otp_scramble_key_xstrs[part_ix], OTP_SCRAMBLING_KEY_BYTES, true, true)) { error_setg(&error_fatal, "%s: %s unable to parse otp_scramble_keys[%u] for %s", - __func__, s->ot_id, ix, PART_NAME(ix)); + __func__, s->ot_id, part_ix, + ot_otp_eg_part_name(s, part_ix)); return; } - TRACE_OTP("otp_scramble_keys[%s] %s", PART_NAME(ix), - ot_otp_hexdump(s, s->otp_scramble_keys[ix], + TRACE_OTP("otp_scramble_keys[%s] %s", ot_otp_eg_part_name(s, part_ix), + ot_otp_hexdump(s, s->otp_scramble_keys[part_ix], OTP_SCRAMBLING_KEY_BYTES)); } } -static void ot_otp_eg_class_add_scramble_key_props(OtOTPClass *odc) +static void ot_otp_eg_add_scramble_key_props(OtOTPEgState *s) { + /* + * @todo: we know the number of secret partitions, so use it rather than + * whole partition count + */ + s->otp_scramble_keys = g_new0(uint8_t *, s->part_count); + s->otp_scramble_key_xstrs = g_new0(char *, s->part_count); + unsigned secret_ix = 0u; - for (unsigned ix = 0u; ix < ARRAY_SIZE(OtOTPPartDescs); ix++) { - if (!OtOTPPartDescs[ix].secret) { + for (unsigned part_ix = 0u; part_ix < s->part_count; part_ix++) { + if (!s->part_descs[part_ix].secret) { continue; } @@ -3832,68 +3878,79 @@ static void ot_otp_eg_class_add_scramble_key_props(OtOTPClass *odc) */ prop->name = g_strdup_printf("secret%u_scramble_key", secret_ix++); prop->info = &qdev_prop_string; - prop->offset = offsetof(OtOTPEgState, otp_scramble_key_xstrs) + - sizeof(char *) * ix; + /* + * Property stores the address of the stored string as a relative offset + * from the parent address + */ + prop->offset = + (intptr_t)&s->otp_scramble_key_xstrs[part_ix] - (intptr_t)s; - object_class_property_add(OBJECT_CLASS(odc), prop->name, - prop->info->name, prop->info->get, - prop->info->set, prop->info->release, prop); + object_property_add(OBJECT(s), prop->name, prop->info->name, + prop->info->get, prop->info->set, + prop->info->release, prop); } } static void ot_otp_eg_configure_inv_default_parts(OtOTPEgState *s) { - for (unsigned ix = 0; ix < ARRAY_SIZE(OtOTPPartDescs); ix++) { - if (!s->inv_default_part_xstrs[ix]) { + for (unsigned part_ix = 0; part_ix < s->part_count; part_ix++) { + if (!s->inv_default_part_xstrs[part_ix]) { continue; } - const OtOTPPartDesc *part = &OtOTPPartDescs[ix]; + const OtOTPPartDesc *part = &s->part_descs[part_ix]; size_t len; - len = strlen(s->inv_default_part_xstrs[ix]); + len = strlen(s->inv_default_part_xstrs[part_ix]); if (len != part->size * 2u) { error_setg(&error_fatal, "%s: %s invalid inv_default_part[%u] length\n", __func__, - s->ot_id, ix); + s->ot_id, part_ix); return; } - g_assert(!s->inv_default_parts[ix]); + g_assert(!s->inv_default_parts[part_ix]); - s->inv_default_parts[ix] = g_new0(uint8_t, part->size + 1u); - if (ot_common_parse_hexa_str(s->inv_default_parts[ix], - s->inv_default_part_xstrs[ix], part->size, - false, true)) { + s->inv_default_parts[part_ix] = g_new0(uint8_t, part->size + 1u); + if (ot_common_parse_hexa_str(s->inv_default_parts[part_ix], + s->inv_default_part_xstrs[part_ix], + part->size, false, true)) { error_setg(&error_fatal, "%s: %s unable to parse inv_default_part[%u]\n", - __func__, s->ot_id, ix); + __func__, s->ot_id, part_ix); return; } - TRACE_OTP("inv_default_part[%s] %s", PART_NAME(ix), - ot_otp_hexdump(s, s->inv_default_parts[ix], part->size)); + TRACE_OTP("inv_default_part[%s] %s", ot_otp_eg_part_name(s, part_ix), + ot_otp_hexdump(s, s->inv_default_parts[part_ix], part->size)); } } -static void ot_otp_eg_class_add_inv_def_props(OtOTPClass *odc) +static void ot_otp_eg_add_inv_def_props(OtOTPEgState *s) { - for (unsigned ix = 0; ix < ARRAY_SIZE(OtOTPPartDescs); ix++) { - if (!OtOTPPartDescs[ix].buffered) { + s->inv_default_parts = g_new0(uint8_t *, s->part_count); + s->inv_default_part_xstrs = g_new0(char *, s->part_count); + + for (unsigned part_ix = 0; part_ix < s->part_count; part_ix++) { + if (!s->part_descs[part_ix].buffered) { continue; } Property *prop = g_new0(Property, 1u); - prop->name = g_strdup_printf("inv_default_part_%u", ix); + prop->name = g_strdup_printf("inv_default_part_%u", part_ix); prop->info = &qdev_prop_string; - prop->offset = offsetof(OtOTPEgState, inv_default_part_xstrs) + - sizeof(char *) * ix; + /* + * Property stores the address of the stored string as a relative offset + * from the parent address + */ + prop->offset = + (intptr_t)&s->inv_default_part_xstrs[part_ix] - (intptr_t)s; - object_class_property_add(OBJECT_CLASS(odc), prop->name, - prop->info->name, prop->info->get, - prop->info->set, prop->info->release, prop); + object_property_add(OBJECT(s), prop->name, prop->info->name, + prop->info->get, prop->info->set, + prop->info->release, prop); } } @@ -3934,7 +3991,7 @@ static const MemoryRegionOps ot_otp_eg_swcfg_ops = { static void ot_otp_eg_reset_enter(Object *obj, ResetType type) { - OtOTPClass *c = OT_OTP_GET_CLASS(obj); + OtOTPEgClass *c = OT_OTP_EG_GET_CLASS(obj); OtOTPEgState *s = OT_OTP_EG(obj); /* @@ -3994,21 +4051,21 @@ static void ot_otp_eg_reset_enter(Object *obj, ResetType type) ot_otp_eg_update_alerts(s); ibex_irq_set(&s->pwc_otp_rsp, 0); - for (unsigned ix = 0; ix < OTP_PART_COUNT; ix++) { + for (unsigned part_ix = 0; part_ix < s->part_count; part_ix++) { /* TODO: initialize with actual default partition data once known */ - if (OtOTPPartDescs[ix].buffered) { - s->partctrls[ix].state.b = OTP_BUF_IDLE; + if (s->part_descs[part_ix].buffered) { + s->part_ctrls[part_ix].state.b = OTP_BUF_IDLE; } else { - s->partctrls[ix].state.u = OTP_UNBUF_IDLE; + s->part_ctrls[part_ix].state.u = OTP_UNBUF_IDLE; continue; } - unsigned part_size = ot_otp_eg_part_data_byte_size(ix); - memset(s->partctrls[ix].buffer.data, 0, part_size); - s->partctrls[ix].digest = 0; - if (OtOTPPartDescs[ix].iskeymgr_creator || - OtOTPPartDescs[ix].iskeymgr_owner) { - s->partctrls[ix].read_lock = true; - s->partctrls[ix].write_lock = true; + unsigned part_size = ot_otp_eg_part_data_byte_size(s, part_ix); + memset(s->part_ctrls[part_ix].buffer.data, 0, part_size); + s->part_ctrls[part_ix].digest = 0; + if (s->part_descs[part_ix].iskeymgr_creator || + s->part_descs[part_ix].iskeymgr_owner) { + s->part_ctrls[part_ix].read_lock = true; + s->part_ctrls[part_ix].write_lock = true; } } DAI_CHANGE_STATE(s, OTP_DAI_RESET); @@ -4017,7 +4074,7 @@ static void ot_otp_eg_reset_enter(Object *obj, ResetType type) static void ot_otp_eg_reset_exit(Object *obj, ResetType type) { - OtOTPClass *c = OT_OTP_GET_CLASS(obj); + OtOTPEgClass *c = OT_OTP_EG_GET_CLASS(obj); OtOTPEgState *s = OT_OTP_EG(obj); trace_ot_otp_reset(s->ot_id, "exit"); @@ -4076,17 +4133,17 @@ static void ot_otp_eg_init(Object *obj) * - "swcfg", software config window * offset SW_CFG_WINDOW, size SW_CFG_WINDOW_SIZE */ - memory_region_init(&s->mmio.ctrl, obj, TYPE_OT_OTP "-ctrl", + memory_region_init(&s->mmio.ctrl, obj, TYPE_OT_OTP_EG "-ctrl", SW_CFG_WINDOW + SW_CFG_WINDOW_SIZE); sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->mmio.ctrl); memory_region_init_io(&s->mmio.sub.regs, obj, &ot_otp_eg_reg_ops, s, - TYPE_OT_OTP "-regs", REGS_SIZE); + TYPE_OT_OTP_EG "-regs", REGS_SIZE); memory_region_add_subregion(&s->mmio.ctrl, 0u, &s->mmio.sub.regs); /* TODO: it might be worthwhile to use a ROM-kind here */ memory_region_init_io(&s->mmio.sub.swcfg, obj, &ot_otp_eg_swcfg_ops, s, - TYPE_OT_OTP "-swcfg", SW_CFG_WINDOW_SIZE); + TYPE_OT_OTP_EG "-swcfg", SW_CFG_WINDOW_SIZE); memory_region_add_subregion(&s->mmio.ctrl, SW_CFG_WINDOW, &s->mmio.sub.swcfg); @@ -4105,23 +4162,29 @@ static void ot_otp_eg_init(Object *obj) qdev_init_gpio_in_named(DEVICE(obj), &ot_otp_eg_lc_broadcast_recv, OT_LC_BROADCAST, OT_OTP_LC_BROADCAST_COUNT); + s->part_descs = OtOTPPartDescs; + s->part_count = ARRAY_SIZE(OtOTPPartDescs); + s->part_life_cycle = OTP_PART_LIFE_CYCLE; + s->hw_cfg = g_new0(OtOTPHWCfg, 1u); s->tokens = g_new0(OtOTPTokens, 1u); s->regs = g_new0(uint32_t, REGS_COUNT); s->dai = g_new0(OtOTPDAIController, 1u); s->lci = g_new0(OtOTPLCIController, 1u); - s->partctrls = g_new0(OtOTPPartController, OTP_PART_COUNT); + s->part_ctrls = g_new0(OtOTPPartController, s->part_count); s->keygen = g_new0(OtOTPKeyGen, 1u); s->otp = g_new0(OtOTPStorage, 1u); s->scrmbl_key_init = g_new0(OtOTPScrmblKeyInit, 1u); + s->lci->data = g_new0(uint16_t, s->part_descs[s->part_life_cycle].size / + sizeof(uint16_t)); - for (unsigned ix = 0; ix < OTP_PART_COUNT; ix++) { - if (!OtOTPPartDescs[ix].buffered) { + for (unsigned part_ix = 0; part_ix < s->part_count; part_ix++) { + if (!s->part_descs[part_ix].buffered) { continue; } size_t part_words = - ot_otp_eg_part_data_byte_size(ix) / sizeof(uint32_t); - s->partctrls[ix].buffer.data = g_new0(uint32_t, part_words); + ot_otp_eg_part_data_byte_size(s, part_ix) / sizeof(uint32_t); + s->part_ctrls[part_ix].buffer.data = g_new0(uint32_t, part_words); } ot_fifo32_create(&s->keygen->entropy_buf, OTP_ENTROPY_BUF_COUNT); @@ -4139,6 +4202,9 @@ static void ot_otp_eg_init(Object *obj) int64_t now = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); ot_prng_reseed(s->keygen->prng, (uint32_t)now); + ot_otp_eg_add_scramble_key_props(s); + ot_otp_eg_add_inv_def_props(s); + #ifdef OT_OTP_DEBUG s->hexstr = g_new0(char, OT_OTP_HEXSTR_SIZE); #endif @@ -4149,36 +4215,36 @@ static void ot_otp_eg_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); (void)data; - g_assert(OTP_PART_LIFE_CYCLE_SIZE == - OtOTPPartDescs[OTP_PART_LIFE_CYCLE].size); - dc->realize = &ot_otp_eg_realize; device_class_set_props(dc, ot_otp_eg_properties); set_bit(DEVICE_CATEGORY_MISC, dc->categories); ResettableClass *rc = RESETTABLE_CLASS(klass); - OtOTPClass *oc = OT_OTP_CLASS(klass); + OtOTPEgClass *edc = OT_OTP_EG_CLASS(klass); resettable_class_set_parent_phases(rc, &ot_otp_eg_reset_enter, NULL, &ot_otp_eg_reset_exit, - &oc->parent_phases); + &edc->parent_phases); + OtOTPIfClass *oc = OT_OTP_IF_CLASS(klass); oc->get_lc_info = &ot_otp_eg_get_lc_info; oc->get_hw_cfg = &ot_otp_eg_get_hw_cfg; oc->get_otp_key = &ot_otp_eg_get_otp_key; oc->get_keymgr_secret = &ot_otp_eg_get_keymgr_secret; oc->program_req = &ot_otp_eg_program_req; - - ot_otp_eg_class_add_scramble_key_props(oc); - ot_otp_eg_class_add_inv_def_props(oc); } static const TypeInfo ot_otp_eg_info = { .name = TYPE_OT_OTP_EG, - .parent = TYPE_OT_OTP, + .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(OtOTPEgState), .instance_init = &ot_otp_eg_init, - .class_size = sizeof(OtOTPClass), + .class_size = sizeof(OtOTPEgClass), .class_init = &ot_otp_eg_class_init, + .interfaces = + (InterfaceInfo[]){ + { TYPE_OT_OTP_IF }, + {}, + }, }; static void ot_otp_eg_register_types(void) diff --git a/hw/opentitan/ot_otp_eg_parts.c b/hw/opentitan/ot_otp_eg_parts.c index dfdc986d00f4c..05e3a75a5b29a 100644 --- a/hw/opentitan/ot_otp_eg_parts.c +++ b/hw/opentitan/ot_otp_eg_parts.c @@ -7,6 +7,7 @@ /* NOLINTBEGIN */ static const OtOTPPartDesc OtOTPPartDescs[] = { [OTP_PART_VENDOR_TEST] = { + .name = "VENDOR_TEST", .size = 64u, .offset = 0u, .digest_offset = 56u, @@ -20,6 +21,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .integrity = false, }, [OTP_PART_CREATOR_SW_CFG] = { + .name = "CREATOR_SW_CFG", .size = 368u, .offset = 64u, .digest_offset = 424u, @@ -33,6 +35,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .integrity = true, }, [OTP_PART_OWNER_SW_CFG] = { + .name = "OWNER_SW_CFG", .size = 712u, .offset = 432u, .digest_offset = 1136u, @@ -46,6 +49,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .integrity = true, }, [OTP_PART_ROT_CREATOR_AUTH_CODESIGN] = { + .name = "ROT_CREATOR_AUTH_CODESIGN", .size = 472u, .offset = 1144u, .digest_offset = 1608u, @@ -59,6 +63,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .integrity = true, }, [OTP_PART_ROT_CREATOR_AUTH_STATE] = { + .name = "ROT_CREATOR_AUTH_STATE", .size = 40u, .offset = 1616u, .digest_offset = 1648u, @@ -72,6 +77,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .integrity = true, }, [OTP_PART_HW_CFG0] = { + .name = "HW_CFG0", .size = 72u, .offset = 1656u, .digest_offset = 1720u, @@ -84,6 +90,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .integrity = true, }, [OTP_PART_HW_CFG1] = { + .name = "HW_CFG1", .size = 16u, .offset = 1728u, .digest_offset = 1736u, @@ -96,6 +103,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .integrity = true, }, [OTP_PART_SECRET0] = { + .name = "SECRET0", .size = 40u, .offset = 1744u, .digest_offset = 1776u, @@ -108,6 +116,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .integrity = true, }, [OTP_PART_SECRET1] = { + .name = "SECRET1", .size = 88u, .offset = 1784u, .digest_offset = 1864u, @@ -120,6 +129,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .integrity = true, }, [OTP_PART_SECRET2] = { + .name = "SECRET2", .size = 88u, .offset = 1872u, .digest_offset = 1952u, @@ -133,6 +143,7 @@ static const OtOTPPartDesc OtOTPPartDescs[] = { .iskeymgr_creator = true, }, [OTP_PART_LIFE_CYCLE] = { + .name = "LIFE_CYCLE", .size = 88u, .offset = 1960u, .digest_offset = UINT16_MAX, diff --git a/hw/opentitan/ot_otp.c b/hw/opentitan/ot_otp_if.c similarity index 72% rename from hw/opentitan/ot_otp.c rename to hw/opentitan/ot_otp_if.c index d2132c7d7c6e9..ccafdab71c69c 100644 --- a/hw/opentitan/ot_otp.c +++ b/hw/opentitan/ot_otp_if.c @@ -1,7 +1,7 @@ /* - * QEMU OpenTitan One Time Programmable (OTP) memory controller + * QEMU OpenTitan One Time Programmable (OTP) memory controller public interface * - * Copyright (c) 2023-2025 Rivos, Inc. + * Copyright (c) 2025 Rivos, Inc. * * Author(s): * Emmanuel Blot @@ -26,14 +26,17 @@ */ #include "qemu/osdep.h" -#include "hw/opentitan/ot_common.h" -#include "hw/opentitan/ot_otp.h" +#include "hw/opentitan/ot_otp_if.h" -OT_OBJECT_DEFINE_ABSTRACT_TYPE(OtOTPState, OtOTPClass, ot_otp, OT_OTP, - SYS_BUS_DEVICE) +static const TypeInfo ot_otp_if_info = { + .name = TYPE_OT_OTP_IF, + .parent = TYPE_INTERFACE, + .class_size = sizeof(OtOTPIfClass), +}; -static void ot_otp_class_init(ObjectClass *oc, void *data) {} +static void ot_otp_if_register_types(void) +{ + type_register_static(&ot_otp_if_info); +} -static void ot_otp_init(Object *obj) {} - -static void ot_otp_finalize(Object *obj) {} +type_init(ot_otp_if_register_types); diff --git a/hw/opentitan/ot_otp_ot_be.c b/hw/opentitan/ot_otp_ot_be.c index f9568304ef376..7e575e0858d6d 100644 --- a/hw/opentitan/ot_otp_ot_be.c +++ b/hw/opentitan/ot_otp_ot_be.c @@ -31,8 +31,8 @@ #include "qemu/osdep.h" #include "qemu/log.h" #include "hw/opentitan/ot_common.h" -#include "hw/opentitan/ot_otp.h" #include "hw/opentitan/ot_otp_be_if.h" +#include "hw/opentitan/ot_otp_if.h" #include "hw/opentitan/ot_otp_ot_be.h" #include "hw/qdev-properties.h" #include "hw/registerfields.h" diff --git a/hw/opentitan/ot_sram_ctrl.c b/hw/opentitan/ot_sram_ctrl.c index 99c689e85c073..bff06f3770a7d 100644 --- a/hw/opentitan/ot_sram_ctrl.c +++ b/hw/opentitan/ot_sram_ctrl.c @@ -35,7 +35,7 @@ #include "qemu/typedefs.h" #include "hw/opentitan/ot_alert.h" #include "hw/opentitan/ot_common.h" -#include "hw/opentitan/ot_otp.h" +#include "hw/opentitan/ot_otp_if.h" #include "hw/opentitan/ot_prng.h" #include "hw/opentitan/ot_sram_ctrl.h" #include "hw/opentitan/ot_vmapper.h" @@ -136,7 +136,7 @@ struct OtSramCtrlState { char *hexstr; char *ot_id; - OtOTPState *otp_ctrl; /* optional */ + DeviceState *otp_ctrl; /* optional */ OtVMapperState *vmapper; /* optional */ uint32_t size; /* in bytes */ uint32_t init_chunk_words; /* init chunk size in words */ @@ -284,13 +284,15 @@ static void ot_sram_ctrl_reseed(OtSramCtrlState *s) * neither PRINCE block cipher nor shallow substitution-permutation. * Seed and Nonce are combined to initialize a QEMU PRNG instance. */ - OtOTPClass *oc = OBJECT_GET_CLASS(OtOTPClass, s->otp_ctrl, TYPE_OT_OTP); + OtOTPIfClass *oc = OT_OTP_IF_GET_CLASS(s->otp_ctrl); + OtOTPIf *oi = OT_OTP_IF(s->otp_ctrl); + if (!oc->get_otp_key) { /* on EarlGrey, OTP key handing has not been implemented */ qemu_log_mask(LOG_UNIMP, "%s: %s OTP does not support key generation\n", __func__, s->ot_id); } else { - oc->get_otp_key(s->otp_ctrl, OTP_KEY_SRAM, s->otp_key); + oc->get_otp_key(oi, OTP_KEY_SRAM, s->otp_key); TRACE_SRAM_CTRL("Scrambing seed: %s (valid: %u)", ot_sram_ctrl_hexdump(s, s->otp_key->seed, @@ -355,9 +357,10 @@ static void ot_sram_ctrl_update_exec(OtSramCtrlState *s) * Configuration need to be loaded on demand */ if (s->otp_ctrl) { - OtOTPClass *oc = OBJECT_GET_CLASS(OtOTPClass, s->otp_ctrl, TYPE_OT_OTP); - s->otp_ifetch = oc->get_hw_cfg(s->otp_ctrl)->en_sram_ifetch_mb8 == - OT_MULTIBITBOOL8_TRUE; + OtOTPIfClass *oc = OT_OTP_IF_GET_CLASS(s->otp_ctrl); + OtOTPIf *oi = OT_OTP_IF(s->otp_ctrl); + s->otp_ifetch = + oc->get_hw_cfg(oi)->en_sram_ifetch_mb8 == OT_MULTIBITBOOL8_TRUE; } bool ifetch = s->ifetch && s->csr_ifetch && s->otp_ifetch; @@ -668,8 +671,8 @@ static MemTxResult ot_sram_ctrl_mem_init_write_with_attrs( static Property ot_sram_ctrl_properties[] = { DEFINE_PROP_STRING(OT_COMMON_DEV_ID, OtSramCtrlState, ot_id), - DEFINE_PROP_LINK("otp-ctrl", OtSramCtrlState, otp_ctrl, TYPE_OT_OTP, - OtOTPState *), + DEFINE_PROP_LINK("otp-ctrl", OtSramCtrlState, otp_ctrl, TYPE_OT_OTP_IF, + DeviceState *), DEFINE_PROP_LINK("vmapper", OtSramCtrlState, vmapper, TYPE_OT_VMAPPER, OtVMapperState *), DEFINE_PROP_UINT32("size", OtSramCtrlState, size, 0u), @@ -752,6 +755,8 @@ static void ot_sram_ctrl_realize(DeviceState *dev, Error **errp) */ g_assert(s->ifetch || !s->otp_ctrl || s->vmapper); + (void)OBJECT_CHECK(OtOTPIf, s->otp_ctrl, TYPE_OT_OTP_IF); + s->wsize = DIV_ROUND_UP(s->size, sizeof(uint32_t)); unsigned size = s->wsize * sizeof(uint32_t); diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index 18ea1b3ce6cca..80d963156b0c0 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -45,6 +45,7 @@ config OT_DARJEELING select OT_LC_CTRL select OT_MBX select OT_OTBN + select OT_OTP_IF select OT_OTP_DJ select OT_OTP_OT_BE select OT_PINMUX_DJ @@ -90,6 +91,7 @@ config OT_EARLGREY select OT_LC_CTRL select OT_OTBN select OT_OTP_EG + select OT_OTP_IF select OT_OTP_OT_BE select OT_PINMUX_EG select OT_PLIC_EXT diff --git a/hw/riscv/ot_darjeeling.c b/hw/riscv/ot_darjeeling.c index b267500cb0500..a1b1e99a715b3 100644 --- a/hw/riscv/ot_darjeeling.c +++ b/hw/riscv/ot_darjeeling.c @@ -55,6 +55,7 @@ #include "hw/opentitan/ot_mbx.h" #include "hw/opentitan/ot_otbn.h" #include "hw/opentitan/ot_otp_dj.h" +#include "hw/opentitan/ot_otp_if.h" #include "hw/opentitan/ot_otp_ot_be.h" #include "hw/opentitan/ot_pinmux_dj.h" #include "hw/opentitan/ot_plic_ext.h" @@ -758,8 +759,7 @@ static const IbexDeviceDef ot_dj_soc_devices[] = { OT_DJ_SOC_GPIO_ALERT(1, 36) ), .link = IBEXDEVICELINKDEFS( - OT_DJ_SOC_DEVLINK("noise-src", AST), - OT_DJ_SOC_DEVLINK("otp-ctrl", OTP_CTRL) + OT_DJ_SOC_DEVLINK("noise-src", AST) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("version", 3) diff --git a/hw/riscv/ot_earlgrey.c b/hw/riscv/ot_earlgrey.c index 0fdfc591cefbb..3ee40ee69572a 100644 --- a/hw/riscv/ot_earlgrey.c +++ b/hw/riscv/ot_earlgrey.c @@ -57,6 +57,7 @@ #include "hw/opentitan/ot_lc_ctrl.h" #include "hw/opentitan/ot_otbn.h" #include "hw/opentitan/ot_otp_eg.h" +#include "hw/opentitan/ot_otp_if.h" #include "hw/opentitan/ot_otp_ot_be.h" #include "hw/opentitan/ot_pinmux_eg.h" #include "hw/opentitan/ot_plic_ext.h" @@ -1246,8 +1247,7 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { OT_EG_SOC_GPIO_ALERT(1, 54) ), .link = IBEXDEVICELINKDEFS( - OT_EG_SOC_DEVLINK("noise-src", AST), - OT_EG_SOC_DEVLINK("otp-ctrl", OTP_CTRL) + OT_EG_SOC_DEVLINK("noise-src", AST) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("version", 2) @@ -1410,7 +1410,7 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { [OT_EG_SOC_SPLITTER_LC_HW_DEBUG] = { .type = TYPE_SPLIT_IRQ, .prop = IBEXDEVICEPROPDEFS( - IBEX_DEV_UINT_PROP("num-lines", 1u) /** @todo to be changed */ + IBEX_DEV_UINT_PROP("num-lines", 1u) /* @todo to be changed */ ) }, [OT_EG_SOC_SPLITTER_LC_ESCALATE] = { @@ -1422,7 +1422,7 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { OT_FLASH_LC_ESCALATE_EN) ), .prop = IBEXDEVICEPROPDEFS( - IBEX_DEV_UINT_PROP("num-lines", 2u) /** @todo to be changed */ + IBEX_DEV_UINT_PROP("num-lines", 2u) /* @todo to be changed */ ) }, [OT_EG_SOC_SPLITTER_LC_SEED_HW_RD] = { diff --git a/include/hw/opentitan/ot_otp_dj.h b/include/hw/opentitan/ot_otp_dj.h index 0a7b148cc2001..700d364990906 100644 --- a/include/hw/opentitan/ot_otp_dj.h +++ b/include/hw/opentitan/ot_otp_dj.h @@ -1,7 +1,7 @@ /* * QEMU OpenTitan Darjeeling One Time Programmable (OTP) memory controller * - * Copyright (c) 2023-2024 Rivos, Inc. + * Copyright (c) 2023-2025 Rivos, Inc. * * Author(s): * Emmanuel Blot @@ -29,9 +29,7 @@ #ifndef HW_OPENTITAN_OT_OTP_DJ_H #define HW_OPENTITAN_OT_OTP_DJ_H -#include "hw/opentitan/ot_otp.h" - #define TYPE_OT_OTP_DJ "ot-otp-dj" -OBJECT_DECLARE_TYPE(OtOTPDjState, OtOTPClass, OT_OTP_DJ) +OBJECT_DECLARE_TYPE(OtOTPDjState, OtOTPDjClass, OT_OTP_DJ) #endif /* HW_OPENTITAN_OT_OTP_DJ_H */ diff --git a/include/hw/opentitan/ot_otp_eg.h b/include/hw/opentitan/ot_otp_eg.h index 9a7f7759f593c..9431b4be5d9d6 100644 --- a/include/hw/opentitan/ot_otp_eg.h +++ b/include/hw/opentitan/ot_otp_eg.h @@ -1,7 +1,7 @@ /* * QEMU OpenTitan EarlGrey One Time Programmable (OTP) memory controller * - * Copyright (c) 2023-2024 Rivos, Inc. + * Copyright (c) 2023-2025 Rivos, Inc. * * Author(s): * Emmanuel Blot @@ -29,9 +29,7 @@ #ifndef HW_OPENTITAN_OT_OTP_EG_H #define HW_OPENTITAN_OT_OTP_EG_H -#include "hw/opentitan/ot_otp.h" - #define TYPE_OT_OTP_EG "ot-otp-eg" -OBJECT_DECLARE_TYPE(OtOTPEgState, OtOTPClass, OT_OTP_EG) +OBJECT_DECLARE_TYPE(OtOTPEgState, OtOTPEgClass, OT_OTP_EG) #endif /* HW_OPENTITAN_OT_OTP_EG_H */ diff --git a/include/hw/opentitan/ot_otp.h b/include/hw/opentitan/ot_otp_if.h similarity index 86% rename from include/hw/opentitan/ot_otp.h rename to include/hw/opentitan/ot_otp_if.h index 12a9fdc56016d..9e314f0cb3790 100644 --- a/include/hw/opentitan/ot_otp.h +++ b/include/hw/opentitan/ot_otp_if.h @@ -1,5 +1,5 @@ /* - * QEMU OpenTitan One Time Programmable (OTP) memory controller + * QEMU OpenTitan One Time Programmable (OTP) memory controller public interface * * Copyright (c) 2023-2025 Rivos, Inc. * @@ -26,15 +26,18 @@ * THE SOFTWARE. */ -#ifndef HW_OPENTITAN_OT_OTP_H -#define HW_OPENTITAN_OT_OTP_H +#ifndef HW_OPENTITAN_OT_OTP_IF_H +#define HW_OPENTITAN_OT_OTP_IF_H #include "qom/object.h" #include "hw/opentitan/ot_common.h" -#include "hw/sysbus.h" -#define TYPE_OT_OTP "ot-otp" -OBJECT_DECLARE_TYPE(OtOTPState, OtOTPClass, OT_OTP) +#define TYPE_OT_OTP_IF "ot-otp_if" +typedef struct OtOTPIfClass OtOTPIfClass; +typedef struct OtOTPIf OtOTPIf; + +DECLARE_CLASS_CHECKERS(OtOTPIfClass, OT_OTP_IF, TYPE_OT_OTP_IF) +#define OT_OTP_IF(_obj_) INTERFACE_CHECK(OtOTPIf, (_obj_), TYPE_OT_OTP_IF) /* Input signals from life cycle */ typedef enum { @@ -125,20 +128,15 @@ typedef struct { bool valid; /* whether the key/seed data is valid */ } OtOTPKeyMgrSecret; -struct OtOTPState { - SysBusDevice parent_obj; -}; - typedef void (*ot_otp_program_ack_fn)(void *opaque, bool ack); -struct OtOTPClass { - SysBusDeviceClass parent_class; - ResettablePhases parent_phases; +struct OtOTPIfClass { + InterfaceClass parent_class; /* * Provide OTP lifecycle information. * - * @s the OTP device + * @dev the OTP device * @lc_tcount if not NULL, updated with the raw LifeCycle transition count * buffer. * @lc_state if not NULL, updated with the raw LifeCycle state buffer. @@ -147,35 +145,35 @@ struct OtOTPClass { * * @note: lc_valid and secret_valid use OT_MULTIBITBOOL_LC4 encoding */ - void (*get_lc_info)(const OtOTPState *s, uint16_t *lc_state, + void (*get_lc_info)(const OtOTPIf *dev, uint16_t *lc_state, uint16_t *lc_tcount, uint8_t *lc_valid, uint8_t *secret_valid, const OtOTPTokens **tokens); /* * Retrieve HW configuration. * - * @s the OTP device + * @dev the OTP device * @return the HW config data (never NULL) */ - const OtOTPHWCfg *(*get_hw_cfg)(const OtOTPState *s); + const OtOTPHWCfg *(*get_hw_cfg)(const OtOTPIf *dev); /* * Retrieve SRAM scrambling key. * - * @s the OTP device + * @dev the OTP device * @type the type of the key to retrieve * @key the key record to update */ - void (*get_otp_key)(OtOTPState *s, OtOTPKeyType type, OtOTPKey *key); + void (*get_otp_key)(OtOTPIf *dev, OtOTPKeyType type, OtOTPKey *key); /* * Retrieve Key Manager secret (key or seeds). * - * @s the OTP device + * @dev the OTP device * @type the type of secret to retrieve * @secret the key manager secret record to update */ - void (*get_keymgr_secret)(OtOTPState *s, OtOTPKeyMgrSecretType type, + void (*get_keymgr_secret)(OtOTPIf *dev, OtOTPKeyMgrSecretType type, OtOTPKeyMgrSecret *secret); /** @@ -185,16 +183,16 @@ struct OtOTPClass { * callback. Conversely, it should always invoke the callback if the request * is accepted. * - * @s the OTP device + * @dev the OTP device * @lc_tcount the raw LifeCycle transition count buffer * @lc_state the raw LifeCycle state buffer * @ack the callback to asynchronously invoke on OTP completion/error * @opaque opaque data to forward to the ot_otp_program_ack_fn function * @return @c true if request is accepted, @c false is rejected. */ - bool (*program_req)(OtOTPState *s, const uint16_t *lc_tcount, + bool (*program_req)(OtOTPIf *dev, const uint16_t *lc_tcount, const uint16_t *lc_state, ot_otp_program_ack_fn ack, void *opaque); }; -#endif /* HW_OPENTITAN_OT_OTP_H */ +#endif /* HW_OPENTITAN_OT_OTP_IF_H */ diff --git a/python/qemu/ot/otp/descriptor.py b/python/qemu/ot/otp/descriptor.py index 4712a0afc19a4..6284acd248584 100644 --- a/python/qemu/ot/otp/descriptor.py +++ b/python/qemu/ot/otp/descriptor.py @@ -91,6 +91,7 @@ def save(self, kind: str, hjname: str, scriptname: str, cfp: TextIO) \ print('static const OtOTPPartDesc OtOTPPartDescs[] = {', file=cfp) for part in self._otpmap.enumerate_partitions(): print(f' [OTP_PART_{part.name}] = {{', file=cfp) + print(f' .name = "{part.name}",', file=cfp) print(f' .size = {part.size}u,', file=cfp) print(f' .offset = {part.offset}u,', file=cfp) if part.zer_offset is not None: diff --git a/scripts/opentitan/clang-tidy.yml b/scripts/opentitan/clang-tidy.yml index 1e40512c7f660..fac54d7bb36b6 100644 --- a/scripts/opentitan/clang-tidy.yml +++ b/scripts/opentitan/clang-tidy.yml @@ -26,7 +26,7 @@ Checks: '*, -hicpp-no-assembler, -hicpp-signed-bitwise, -llvmlibc-*, - -llvm-include-order, + -llvm-*, -misc-include-cleaner, -modernize-macro-to-enum, -performance-no-int-to-ptr,