diff options
| author | Manish Pandey <manish.pandey2@arm.com> | 2026-06-29 13:05:39 +0000 |
|---|---|---|
| committer | TrustedFirmware Code Review <review@review.trustedfirmware.org> | 2026-06-29 13:05:39 +0000 |
| commit | 51d431f4486a0a4c624525d3e77e4696dc9ce087 (patch) | |
| tree | 24706c12016fed4f997875bcafccda4b9e51e812 | |
| parent | 31255dd9b2e14c1ebe4eab1b8f4984cde72c51d5 (diff) | |
| parent | dd6bd54c40c7f51e59428afb31a4e79fa2ef0e07 (diff) | |
| download | arm-trusted-firmware-51d431f4486a0a4c624525d3e77e4696dc9ce087.tar.gz arm-trusted-firmware-51d431f4486a0a4c624525d3e77e4696dc9ce087.zip | |
Merge changes from topic "hm/mecid" into integration
* changes:
feat(firme): add COMMON_MECID_WIDTH feat reporting
refactor(firme): suffix FIRME func IDs with _FID
feat(rmmd): route MEC refresh via FIRME
feat(firme): introduce FIRME MECID service
| -rw-r--r-- | bl31/bl31.mk | 3 | ||||
| -rw-r--r-- | docs/components/firme.rst | 2 | ||||
| -rw-r--r-- | docs/porting-guide.rst | 48 | ||||
| -rw-r--r-- | include/arch/aarch64/arch.h | 3 | ||||
| -rw-r--r-- | include/plat/common/platform.h | 1 | ||||
| -rw-r--r-- | include/services/firme/firme_mecid.h | 61 | ||||
| -rw-r--r-- | include/services/firme_svc.h | 63 | ||||
| -rw-r--r-- | plat/arm/board/fvp/fvp_common.c | 16 | ||||
| -rw-r--r-- | plat/arm/board/neoverse_rd/platform/rdv3/rdv3_common.c | 14 | ||||
| -rw-r--r-- | plat/qemu/common/qemu_common.c | 13 | ||||
| -rw-r--r-- | services/std_svc/firme/firme_base_service.c | 12 | ||||
| -rw-r--r-- | services/std_svc/firme/firme_main.c | 40 | ||||
| -rw-r--r-- | services/std_svc/firme/firme_mecid.c | 96 | ||||
| -rw-r--r-- | services/std_svc/rmmd/rmmd_main.c | 44 | ||||
| -rw-r--r-- | services/std_svc/std_svc_setup.c | 6 |
15 files changed, 329 insertions, 93 deletions
diff --git a/bl31/bl31.mk b/bl31/bl31.mk index 3a645d014..29b79e173 100644 --- a/bl31/bl31.mk +++ b/bl31/bl31.mk @@ -216,7 +216,8 @@ endif ifeq (${FIRME_SUPPORT},1) BL31_SOURCES += services/std_svc/firme/firme_main.c \ services/std_svc/firme/firme_base_service.c \ - services/std_svc/firme/firme_granule_management_service.c + services/std_svc/firme/firme_granule_management_service.c \ + services/std_svc/firme/firme_mecid.c endif BL31_DEFAULT_LINKER_SCRIPT_SOURCE := bl31/bl31.ld.S diff --git a/docs/components/firme.rst b/docs/components/firme.rst index ad090b85a..7ab5211a5 100644 --- a/docs/components/firme.rst +++ b/docs/components/firme.rst @@ -58,7 +58,7 @@ Current status operation. - The IDE key management, MECID management, attestation, and integrated device management services are not implemented yet. -- ``FIRME_GM_GPI_OP_CONTINUE`` is mandatory in the ``1.0 alp2`` specification, +- ``FIRME_GM_GPI_OP_CONTINUE_FID`` is mandatory in the ``1.0 alp2`` specification, but it is not implemented yet. As a result, the current implementation tracks FIRME ``1.0 alp2`` for diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst index 9dcb72f93..3372c1e0a 100644 --- a/docs/porting-guide.rst +++ b/docs/porting-guide.rst @@ -2365,24 +2365,54 @@ RMM image and stores it in the area specified by manifest. When ENABLE_RMM is disabled, this function is not used. -Function : plat_rmmd_mecid_key_update() [when ENABLE_RMM == 1] +Function : plat_firme_get_common_mecid_width() [when FIRME_SUPPORT == 1] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uint8_t + +This function is invoked by BL31's FIRME MECID management service during +initialization to obtain the system MECID width. This is the smallest supported +MECID width for the entire system. + +The returned value uses the same encoding as ``MECIDR_EL2.MECIDWidthm1``. That +is, it is the system MECID width minus one. The common MECID width is defined as +the smallest MECID width supported across the entire system (see rule IQDYKJ in +the M.b version of the Arm ARM for details). The FIRME MECID management service +advertises the returned value in FIRME MECID feature register 1. + +This function needs to be implemented by a platform if it enables FIRME support +and advertises the FIRME MECID management service. + +Function : plat_firme_mec_refresh() [when FIRME_SUPPORT == 1] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :: - Argument : uint16_t, unsigned int + Argument : uint16_t, uint8_t Return : int -This function is invoked by BL31's RMMD when there is a request from the RMM -monitor to update the tweak for the encryption key associated to a MECID. +This function is invoked by BL31's FIRME MECID management service when there is +a request to refresh the Memory Encryption Context (MEC) associated with a +MECID. + +The first parameter (``uint16_t mecid``) contains the MECID whose associated +MEC is to be refreshed. The second parameter (``uint8_t reason``) specifies the +reason for the refresh. Possible values are: +``MEC_REFRESH_REASON_REALM_CREATE`` for Realm creation and +``MEC_REFRESH_REASON_REALM_DESTROY`` for Realm destruction. -The first parameter (``uint16_t mecid``) contains the MECID for which the -encryption key is to be updated. The second argument specifies the reason -for key update. Possible values are: 0 - Realm creation, 1 - Realm destruction. +The FIRME MECID management service validates that FEAT_MEC is supported and +that the MECID fits within the common MECID width before calling this function. -Return value is 0 upon success and -EFAULT otherwise. +The function returns a FIRME status code. It should return ``FIRME_SUCCESS`` on +success, or an appropriate negative FIRME error code such as +``FIRME_INVALID_PARAMETERS``, ``FIRME_DENIED`` or ``FIRME_RETRY`` on failure. -This function needs to be implemented by a platform if it enables RME. +This function needs to be implemented by a platform if it enables FIRME support +and advertises the FIRME MECID management service. Function : plat_rmmd_reserve_memory() [when ENABLE_RMM == 1] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h index bbd04ded1..4aa8035f3 100644 --- a/include/arch/aarch64/arch.h +++ b/include/arch/aarch64/arch.h @@ -1992,8 +1992,9 @@ * FEAT_MEC - Memory Encryption Contexts ******************************************************************************/ #define MECIDR_EL2 S3_4_C10_C8_7 -#define MECIDR_EL2_MECIDWidthm1_MASK U(0xf) #define MECIDR_EL2_MECIDWidthm1_SHIFT U(0) +#define MECIDR_EL2_MECIDWidthm1_WIDTH U(4) +#define MECIDR_EL2_MECIDWidthm1_MASK GENMASK(3, 0) /****************************************************************************** * FEAT_FGWTE3 - Fine Grained Write Trap diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h index 4d4682cd6..b953c2893 100644 --- a/include/plat/common/platform.h +++ b/include/plat/common/platform.h @@ -409,7 +409,6 @@ int plat_rmmd_el3_token_sign_push_req( int plat_rmmd_el3_token_sign_pull_resp(struct el3_token_sign_response *resp); size_t plat_rmmd_get_el3_rmm_shared_mem(uintptr_t *shared); int plat_rmmd_load_manifest(struct rmm_manifest *manifest); -int plat_rmmd_mecid_key_update(uint16_t mecid, unsigned int reason); uintptr_t plat_rmmd_reserve_memory(size_t size, unsigned long alignment); /* The following 4 functions are to be implemented if diff --git a/include/services/firme/firme_mecid.h b/include/services/firme/firme_mecid.h new file mode 100644 index 000000000..7ec043350 --- /dev/null +++ b/include/services/firme/firme_mecid.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2026, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FIRME_MEC_H +#define FIRME_MEC_H + +#include <stdint.h> + +#include <services/firme/firme_abi.h> + +#define FIRME_MECID_MGMT_VERSION_MAJOR U(1) +#define FIRME_MECID_MGMT_VERSION_MINOR U(0) + +#define FIRME_MEC_FNUM_REFRESH U(0x7) + +/* + * FIRME_MEC_REFRESH + * + * This function refreshes the MEC linked to a given MECID by invalidating the + * existing MEC, generating a new one, and associating the new MEC with that MECID. + * + * Supported from v1.0 + * + * Arguments + * arg0(w0): Function ID 0xC4000407 + * arg1(x1): MEC params Bits[63:48]: Reserved (SBZ). + * Bits[47:32]: MECID. + * Bits[31:1]: Reserved (SBZ). + * Bits[0]: MEC refresh reason. + * – 0b’0: Realm creation. + * – 0b’1: Realm destruction + * + * Return + * ret0(x0): Status FIRME_SUCCESS + * FIRME_NOT_SUPPORTED + * FIRME_INVALID_PARAMETERS + * FIRME_RETRY + */ +#define FIRME_MEC_REFRESH_FID FIRME_FID(FIRME_MEC_FNUM_REFRESH) + +#define MEC_REFRESH_REASON_REALM_CREATE U(0) +#define MEC_REFRESH_REASON_REALM_DESTROY U(1) + +#define MEC_PARAM_MECID_SHIFT U(32) +#define MEC_PARAM_MECID_WIDTH U(16) +#define MEC_PARAM_MECID_MASK MASK(MEC_PARAM_MECID) + +#define FIRME_MECID_FEATURE_REG_COUNT U(2) +#define FIRME_MECID_FEAT_REG0_MEC_REFRESH_BIT BIT(0) +#define FIRME_MECID_FEAT_REG1_COMMON_MECID_WIDTH_BITS_SHIFT U(0) +#define FIRME_MECID_FEAT_REG1_COMMON_MECID_WIDTH_BITS_WIDTH U(4) +#define FIRME_MECID_FEAT_REG1_COMMON_MECID_WIDTH_BITS_MASK MASK(FIRME_MECID_FEAT_REG1_COMMON_MECID_WIDTH_BITS) + +int32_t firme_mecid_service_init(void); +int plat_firme_mec_refresh(uint16_t mecid, uint8_t reason); +uint8_t plat_firme_get_common_mecid_width(void); + +#endif /* FIRME_MEC_H */ diff --git a/include/services/firme_svc.h b/include/services/firme_svc.h index c229d116b..483de0862 100644 --- a/include/services/firme_svc.h +++ b/include/services/firme_svc.h @@ -110,7 +110,10 @@ typedef struct { #define FIRME_BASE_MAX_SH_BUF_PG_CNT_MASK U(0x3FFF) #define FIRME_BASE_SERVICE_LIST_SHIFT U(16) #define FIRME_BASE_SERVICE_LIST_MASK U(0xFFFF) -#define FIRME_BASE_SERVICE_GRANULE_MGMT_BIT BIT(16) +#define FIRME_BASE_SERVICE_BIT(_id) BIT((_id) + \ + FIRME_BASE_SERVICE_LIST_SHIFT) +#define FIRME_BASE_SERVICE_GRANULE_MGMT_BIT FIRME_BASE_SERVICE_BIT(0) +#define FIRME_BASE_SERVICE_MECID_BIT FIRME_BASE_SERVICE_BIT(2) /* Granule management service feature register definitions. */ #define FIRME_GM_GPI_SET_BIT BIT(0) @@ -194,36 +197,56 @@ typedef struct { /* These are unimplemented so far and will be added in the future. */ /* Granule management service ABIs */ -#define FIRME_GM_GPI_OP_CONTINUE SMC64_FIRME_FID(U(0x12)) -#define FIRME_GM_L1_GPT_CREATE SMC64_FIRME_FID(U(0xE)) -#define FIRME_GM_L1_GPT_DESTROY SMC64_FIRME_FID(U(0xF)) +#define FIRME_GM_GPI_OP_CONTINUE_FID SMC64_FIRME_FID(U(0x12)) +#define FIRME_GM_L1_GPT_CREATE_FID SMC64_FIRME_FID(U(0xE)) +#define FIRME_GM_L1_GPT_DESTROY_FID SMC64_FIRME_FID(U(0xF)) /* IDE key management service */ -#define FIRME_IDE_KEYSET_PROG SMC64_FIRME_FID(U(0x3)) -#define FIRME_IDE_KEYSET_GO SMC64_FIRME_FID(U(0x4)) -#define FIRME_IDE_KEYSET_STOP SMC64_FIRME_FID(U(0x5)) -#define FIRME_IDE_KEYSET_POLL SMC64_FIRME_FID(U(0x6)) +#define FIRME_IDE_KEYSET_PROG_FID SMC64_FIRME_FID(U(0x3)) +#define FIRME_IDE_KEYSET_GO_FID SMC64_FIRME_FID(U(0x4)) +#define FIRME_IDE_KEYSET_STOP_FID SMC64_FIRME_FID(U(0x5)) +#define FIRME_IDE_KEYSET_POLL_FID SMC64_FIRME_FID(U(0x6)) /* MECID management service */ -#define FIRME_MEC_REFRESH SMC64_FIRME_FID(U(0x7)) +#define FIRME_MEC_REFRESH_FID SMC64_FIRME_FID(U(0x7)) + +#define MEC_REFRESH_REASON_REALM_CREATE U(0) +#define MEC_REFRESH_REASON_REALM_DESTROY U(1) + +#define MEC_PARAM_MECID_SHIFT U(32) +#define MEC_PARAM_MECID_WIDTH U(16) +#define MEC_PARAM_MECID_MASK MASK(MEC_PARAM_MECID) + +#define FIRME_MECID_FEATURE_REG_COUNT U(2) +#define FIRME_MECID_FEAT_REG0_MEC_REFRESH_BIT BIT(0) +#define FIRME_MECID_FEAT_REG1_COMMON_MECID_WIDTH_BITS_SHIFT U(0) +#define FIRME_MECID_FEAT_REG1_COMMON_MECID_WIDTH_BITS_WIDTH U(4) +#define FIRME_MECID_FEAT_REG1_COMMON_MECID_WIDTH_BITS_MASK MASK(FIRME_MECID_FEAT_REG1_COMMON_MECID_WIDTH_BITS) /* Attestation service */ -#define FIRME_ATTEST_PAT_GET SMC64_FIRME_FID(U(0x8)) -#define FIRME_ATTEST_RAK_GET SMC64_FIRME_FID(U(0x9)) -#define FIRME_ATTEST_RAT_SIGN SMC64_FIRME_FID(U(0xA)) -#define FIRME_ATTEST_PAT_EXT_CLAIMS_STAGE SMC64_FIRME_FID(U(0xB)) -#define FIRME_ATTEST_PAT_EXT_CLAIMS_CLEAR SMC64_FIRME_FID(U(0xC)) -#define FIRME_ATTEST_PAT_EXT_CLAIMS_FINALISE SMC64_FIRME_FID(U(0xD)) +#define FIRME_ATTEST_PAT_GET_FID SMC64_FIRME_FID(U(0x8)) +#define FIRME_ATTEST_RAK_GET_FID SMC64_FIRME_FID(U(0x9)) +#define FIRME_ATTEST_RAT_SIGN_FID SMC64_FIRME_FID(U(0xA)) +#define FIRME_ATTEST_PAT_EXT_CLAIMS_STAGE_FID SMC64_FIRME_FID(U(0xB)) +#define FIRME_ATTEST_PAT_EXT_CLAIMS_CLEAR_FID SMC64_FIRME_FID(U(0xC)) +#define FIRME_ATTEST_PAT_EXT_CLAIMS_FINALISE_FID SMC64_FIRME_FID(U(0xD)) /* Integrated device management service */ -#define FIRME_IDEV_OP_START SMC64_FIRME_FID(U(0x10)) -#define FIRME_IDEV_OP_CONTINUE SMC64_FIRME_FID(U(0x11)) +#define FIRME_IDEV_OP_START_FID SMC64_FIRME_FID(U(0x10)) +#define FIRME_IDEV_OP_CONTINUE_FID SMC64_FIRME_FID(U(0x11)) /* Top level handler for FIRME SMC calls. */ +int32_t firme_init(void); + uint64_t firme_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, void *cookie, void *handle, uint64_t flags); firme_service_info_t *firme_granule_mgmt_service_get_info(void); +firme_service_info_t *firme_mecid_service_get_info(void); + +int32_t firme_mecid_service_init(void); +int plat_firme_mec_refresh(uint16_t mecid, uint8_t reason); +uint8_t plat_firme_get_common_mecid_width(void); u_register_t firme_base_service_handler(firme_instance_e instance, uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, @@ -236,4 +259,10 @@ u_register_t firme_granule_mgmt_service_handler(firme_instance_e instance, uint64_t x4, void *cookie, void *handle, uint64_t flags); +u_register_t firme_mecid_service_handler(firme_instance_e instance, + uint32_t smc_fid, uint64_t x1, + uint64_t x2, uint64_t x3, + uint64_t x4, void *cookie, + void *handle, uint64_t flags); + #endif /* FIRME_SVC_H */ diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c index af32ad20f..0e8f0ac14 100644 --- a/plat/arm/board/fvp/fvp_common.c +++ b/plat/arm/board/fvp/fvp_common.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2026, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include <assert.h> +#include <stdint.h> #include <string.h> #include <arch.h> @@ -23,6 +24,7 @@ #include <platform_def.h> #include <services/arm_arch_svc.h> #include <services/rmm_core_manifest.h> +#include <services/firme_svc.h> #if SPM_MM #include <services/spm_mm_partition.h> #endif @@ -1065,7 +1067,7 @@ int plat_rmmd_load_manifest(struct rmm_manifest *manifest) /* * Update encryption key associated with @mecid. */ -int plat_rmmd_mecid_key_update(uint16_t mecid, unsigned int reason) +int plat_firme_mec_refresh(uint16_t mecid, uint8_t reason) { /* * FVP does not provide an interface to change the encryption key associated @@ -1073,4 +1075,14 @@ int plat_rmmd_mecid_key_update(uint16_t mecid, unsigned int reason) */ return 0; } + +uint8_t plat_firme_get_common_mecid_width(void) +{ + + /* + * Use the PE MECID width as the system MECID width is expected to be the same for all + * system components on FVP. + */ + return (uint8_t)EXTRACT(MECIDR_EL2_MECIDWidthm1, read_mecidr_el2()); +} #endif /* ENABLE_RMM */ diff --git a/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_common.c b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_common.c index 8a7ddc420..d0c3a7dd6 100644 --- a/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_common.c +++ b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_common.c @@ -4,12 +4,15 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include <stdint.h> + #include <common/debug.h> #include <drivers/arm/gic600_multichip.h> #include <drivers/arm/mhu.h> #include <drivers/arm/sfcp.h> #include <plat/arm/common/plat_arm.h> #include <plat/common/platform.h> +#include <services/firme_svc.h> #include <platform_def.h> #include <nrd_plat.h> @@ -188,15 +191,22 @@ int plat_rmmd_load_manifest(struct rmm_manifest *manifest) /* * Update encryption key associated with @mecid. */ -int plat_rmmd_mecid_key_update(uint16_t mecid, unsigned int reason) +int plat_firme_mec_refresh(uint16_t mecid, uint8_t reason) { /* * RDV3 does not support FEAT_MEC. - * This empty hook is for compilation to succeed. + * FIXME: This hook is needed to maintain backward compatibility with RMMD. Drop once we + * have more fine grained control over what services are exposed and how. */ return 0; } +uint8_t plat_firme_get_common_mecid_width(void) +{ + /* RDV3 does not support FEAT_MEC. */ + return 0U; +} + int plat_spmd_handle_group0_interrupt(uint32_t intid) { /* diff --git a/plat/qemu/common/qemu_common.c b/plat/qemu/common/qemu_common.c index f5e19b9b1..3c19f6ba5 100644 --- a/plat/qemu/common/qemu_common.c +++ b/plat/qemu/common/qemu_common.c @@ -1,18 +1,21 @@ /* - * Copyright (c) 2015-2025, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2026, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ +#include <stdint.h> #include <string.h> #include <platform_def.h> +#include <arch.h> #include <arch_helpers.h> #include <common/bl_common.h> #include <lib/xlat_tables/xlat_tables_v2.h> #include <services/el3_spmc_ffa_memory.h> +#include <services/firme_svc.h> #if ENABLE_RMM #include <services/rmm_core_manifest.h> #endif @@ -760,7 +763,7 @@ int plat_rmmd_load_manifest(struct rmm_manifest *manifest) /* * Update encryption key associated with @mecid. */ -int plat_rmmd_mecid_key_update(uint16_t mecid, unsigned int reason) +int plat_firme_mec_refresh(uint16_t mecid, uint8_t reason) { /* * QEMU does not provide an interface to change the encryption key @@ -768,6 +771,12 @@ int plat_rmmd_mecid_key_update(uint16_t mecid, unsigned int reason) */ return 0; } + +uint8_t plat_firme_get_common_mecid_width(void) +{ + /* Safe default value for common MECID width. */ + return (uint8_t)EXTRACT(MECIDR_EL2_MECIDWidthm1, read_mecidr_el2()); +} #endif /* ENABLE_RMM */ /** diff --git a/services/std_svc/firme/firme_base_service.c b/services/std_svc/firme/firme_base_service.c index 27c414a00..347f8f980 100644 --- a/services/std_svc/firme/firme_base_service.c +++ b/services/std_svc/firme/firme_base_service.c @@ -45,6 +45,12 @@ static uint64_t firme_base_get_feat_reg_1(firme_instance_e instance) reg |= FIRME_BASE_SERVICE_GRANULE_MGMT_BIT; } + info = firme_mecid_service_get_info(); + if ((info != NULL) && + ((info->instance_support & BIT(instance)) != 0U)) { + reg |= FIRME_BASE_SERVICE_MECID_BIT; + } + return reg; } @@ -64,6 +70,9 @@ static int32_t get_firme_service_version(firme_instance_e instance, case FIRME_GRANULE_MGMT_ID: info = firme_granule_mgmt_service_get_info(); break; + case FIRME_MECID_MGMT_ID: + info = firme_mecid_service_get_info(); + break; default: return FIRME_NOT_SUPPORTED; } @@ -99,6 +108,9 @@ static int32_t get_firme_feature_reg(uint64_t *reg, firme_instance_e instance, case FIRME_GRANULE_MGMT_ID: info = firme_granule_mgmt_service_get_info(); break; + case FIRME_MECID_MGMT_ID: + info = firme_mecid_service_get_info(); + break; } if ((info != NULL) && (reg_index < info->num_feature_regs) && diff --git a/services/std_svc/firme/firme_main.c b/services/std_svc/firme/firme_main.c index c2bf33d4b..96cde89fc 100644 --- a/services/std_svc/firme/firme_main.c +++ b/services/std_svc/firme/firme_main.c @@ -29,9 +29,9 @@ static inline bool is_granule_mgmt_service_fid(uint32_t fid) { switch (fid) { case FIRME_GM_GPI_SET_FID: - case FIRME_GM_GPI_OP_CONTINUE: - case FIRME_GM_L1_GPT_CREATE: - case FIRME_GM_L1_GPT_DESTROY: + case FIRME_GM_GPI_OP_CONTINUE_FID: + case FIRME_GM_L1_GPT_CREATE_FID: + case FIRME_GM_L1_GPT_DESTROY_FID: return true; default: return false; @@ -41,10 +41,10 @@ static inline bool is_granule_mgmt_service_fid(uint32_t fid) static inline bool is_ide_key_mgmt_service_fid(uint32_t fid) { switch (fid) { - case FIRME_IDE_KEYSET_PROG: - case FIRME_IDE_KEYSET_GO: - case FIRME_IDE_KEYSET_STOP: - case FIRME_IDE_KEYSET_POLL: + case FIRME_IDE_KEYSET_PROG_FID: + case FIRME_IDE_KEYSET_GO_FID: + case FIRME_IDE_KEYSET_STOP_FID: + case FIRME_IDE_KEYSET_POLL_FID: return true; default: return false; @@ -53,7 +53,7 @@ static inline bool is_ide_key_mgmt_service_fid(uint32_t fid) static inline bool is_mecid_service_fid(uint32_t fid) { - if (fid == FIRME_MEC_REFRESH) { + if (fid == FIRME_MEC_REFRESH_FID) { return true; } else { return false; @@ -63,12 +63,12 @@ static inline bool is_mecid_service_fid(uint32_t fid) static inline bool is_attestation_service_fid(uint32_t fid) { switch (fid) { - case FIRME_ATTEST_PAT_GET: - case FIRME_ATTEST_RAK_GET: - case FIRME_ATTEST_RAT_SIGN: - case FIRME_ATTEST_PAT_EXT_CLAIMS_STAGE: - case FIRME_ATTEST_PAT_EXT_CLAIMS_CLEAR: - case FIRME_ATTEST_PAT_EXT_CLAIMS_FINALISE: + case FIRME_ATTEST_PAT_GET_FID: + case FIRME_ATTEST_RAK_GET_FID: + case FIRME_ATTEST_RAT_SIGN_FID: + case FIRME_ATTEST_PAT_EXT_CLAIMS_STAGE_FID: + case FIRME_ATTEST_PAT_EXT_CLAIMS_CLEAR_FID: + case FIRME_ATTEST_PAT_EXT_CLAIMS_FINALISE_FID: return true; default: return false; @@ -78,8 +78,8 @@ static inline bool is_attestation_service_fid(uint32_t fid) static inline bool is_integrated_device_mgmt_service_fid(uint32_t fid) { switch (fid) { - case FIRME_IDEV_OP_START: - case FIRME_IDEV_OP_CONTINUE: + case FIRME_IDEV_OP_START_FID: + case FIRME_IDEV_OP_CONTINUE_FID: return true; default: return false; @@ -99,6 +99,11 @@ static inline firme_instance_e get_instance_from_flags(uint64_t flags) panic(); } +int32_t firme_init(void) +{ + return firme_mecid_service_init(); +} + uint64_t firme_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, void *cookie, void *handle, uint64_t flags) { @@ -120,6 +125,9 @@ uint64_t firme_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, } else if (is_mecid_service_fid(smc_fid)) { + return firme_mecid_service_handler(instance, smc_fid, x1, x2, + x3, x4, cookie, handle, + flags); } else if (is_attestation_service_fid(smc_fid)) { diff --git a/services/std_svc/firme/firme_mecid.c b/services/std_svc/firme/firme_mecid.c new file mode 100644 index 000000000..ee26cb6cd --- /dev/null +++ b/services/std_svc/firme/firme_mecid.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2026, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdbool.h> +#include <stdint.h> + +#include <arch.h> +#include <arch_features.h> +#include <services/firme_svc.h> +#include <smccc_helpers.h> + +/* Only supported ABI is MEC_REFRESH for Realm callers. */ +static firme_service_info_t mecid_info = { + .version = FIRME_VERSION(FIRME_MECID_MGMT_VERSION_MAJOR, + FIRME_MECID_MGMT_VERSION_MINOR), + .instance_support = BIT(FIRME_REALM), + .num_feature_regs = FIRME_MECID_FEATURE_REG_COUNT, + .feature_reg = { FIRME_MECID_FEAT_REG0_MEC_REFRESH_BIT, 0U }, +}; + +firme_service_info_t *firme_mecid_service_get_info(void) +{ + if (!is_feat_mec_supported()) { + return NULL; + } + + return &mecid_info; +} + +int32_t firme_mecid_service_init(void) +{ + uint64_t __maybe_unused mecid_width; + + if (is_feat_mec_supported()) { + mecid_width = (uint64_t)plat_firme_get_common_mecid_width(); + if ((mecid_width & + ~FIRME_MECID_FEAT_REG1_COMMON_MECID_WIDTH_BITS_MASK) != 0U) { + return FIRME_INVALID_PARAMETERS; + } + + mecid_info.feature_reg[1] = EXTRACT(FIRME_MECID_FEAT_REG1_COMMON_MECID_WIDTH_BITS, mecid_width); + } + + return 0; +} + +static int firme_mec_refresh(u_register_t mec_params) +{ + uint64_t common_mecid_width; + uint16_t mecid; + + /* + * Check whether FEAT_MEC is supported by the hardware. If not, return + * unknown SMC. + */ + if (!is_feat_mec_supported()) { + return FIRME_NOT_SUPPORTED; + } + + /* + * Check whether the MECID parameter fits within the common MECID width. + */ + common_mecid_width = (mecid_info.feature_reg[1] & + FIRME_MECID_FEAT_REG1_COMMON_MECID_WIDTH_BITS_MASK) + 1U; + mecid = EXTRACT(MEC_PARAM_MECID, mec_params); + + if (mecid > common_mecid_width) { + return FIRME_INVALID_PARAMETERS; + } + + return plat_firme_mec_refresh(mecid, mec_params & BIT(0)); +} + +u_register_t firme_mecid_service_handler(firme_instance_e instance, + uint32_t smc_fid, uint64_t x1, + uint64_t x2, uint64_t x3, + uint64_t x4, void *cookie, + void *handle, uint64_t flags) +{ + (void)instance; + (void)x2; + (void)x3; + (void)x4; + (void)cookie; + (void)handle; + (void)flags; + + if (smc_fid != FIRME_MEC_REFRESH_FID || instance != FIRME_REALM) { + SMC_RET1(handle, FIRME_NOT_SUPPORTED); + } + + SMC_RET1(handle, firme_mec_refresh(x1)); +} diff --git a/services/std_svc/rmmd/rmmd_main.c b/services/std_svc/rmmd/rmmd_main.c index 521bb9e16..c648a452a 100644 --- a/services/std_svc/rmmd/rmmd_main.c +++ b/services/std_svc/rmmd/rmmd_main.c @@ -32,6 +32,7 @@ #include <plat/common/platform.h> #include <platform_def.h> #include <services/rmmd_svc.h> +#include <services/firme_svc.h> #include <smccc_helpers.h> #include <lib/extensions/sme.h> #include <lib/extensions/sve.h> @@ -455,46 +456,6 @@ static int rmm_el3_ifc_get_feat_register(uint64_t feat_reg_idx, return E_RMM_OK; } -/* - * Update encryption key associated with mecid included in x1. - */ -static int rmmd_mecid_key_update(uint64_t x1) -{ - uint64_t mecid_width, mecid_width_mask; - uint16_t mecid; - unsigned int reason; - int ret; - - /* - * Check whether FEAT_MEC is supported by the hardware. If not, return - * unknown SMC. - */ - if (is_feat_mec_supported() == false) { - return E_RMM_UNK; - } - - /* - * Check whether the mecid parameter is at most MECIDR_EL2.MECIDWidthm1 + 1 - * in length. - */ - mecid_width = ((read_mecidr_el2() >> MECIDR_EL2_MECIDWidthm1_SHIFT) & - MECIDR_EL2_MECIDWidthm1_MASK) + 1UL; - mecid_width_mask = ((1UL << mecid_width) - 1UL); - - mecid = (x1 >> MECID_SHIFT) & MECID_MASK; - if ((mecid & ~mecid_width_mask) != 0U) { - return E_RMM_INVAL; - } - - reason = (x1 >> MEC_REFRESH_REASON_SHIFT) & MEC_REFRESH_REASON_MASK; - ret = plat_rmmd_mecid_key_update(mecid, reason); - - if (ret != 0) { - return E_RMM_UNK; - } - return E_RMM_OK; -} - /******************************************************************************* * This function handles RMM-EL3 interface SMCs ******************************************************************************/ @@ -585,7 +546,8 @@ uint64_t rmmd_rmm_el3_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, rmmd_rmm_sync_exit(x1); } case RMM_MEC_REFRESH: - ret = rmmd_mecid_key_update(x1); + ret = firme_handler(FIRME_MEC_REFRESH_FID, x1, x2, x3, x4, + cookie, handle, flags); SMC_RET1(handle, ret); default: WARN("RMMD: Unsupported RMM-EL3 call 0x%08x\n", smc_fid); diff --git a/services/std_svc/std_svc_setup.c b/services/std_svc/std_svc_setup.c index c2b953fc2..fb402cc6e 100644 --- a/services/std_svc/std_svc_setup.c +++ b/services/std_svc/std_svc_setup.c @@ -83,6 +83,12 @@ static int32_t std_svc_setup(void) trng_setup(); #endif /* TRNG_SUPPORT */ +#if FIRME_SUPPORT + if (firme_init() != 0) { + ret = 1; + } +#endif /* FIRME_SUPPORT */ + #if DRTM_SUPPORT if (drtm_setup() != 0) { ret = 1; |
