summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManish Pandey <manish.pandey2@arm.com>2026-06-29 13:05:39 +0000
committerTrustedFirmware Code Review <review@review.trustedfirmware.org>2026-06-29 13:05:39 +0000
commit51d431f4486a0a4c624525d3e77e4696dc9ce087 (patch)
tree24706c12016fed4f997875bcafccda4b9e51e812
parent31255dd9b2e14c1ebe4eab1b8f4984cde72c51d5 (diff)
parentdd6bd54c40c7f51e59428afb31a4e79fa2ef0e07 (diff)
downloadarm-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.mk3
-rw-r--r--docs/components/firme.rst2
-rw-r--r--docs/porting-guide.rst48
-rw-r--r--include/arch/aarch64/arch.h3
-rw-r--r--include/plat/common/platform.h1
-rw-r--r--include/services/firme/firme_mecid.h61
-rw-r--r--include/services/firme_svc.h63
-rw-r--r--plat/arm/board/fvp/fvp_common.c16
-rw-r--r--plat/arm/board/neoverse_rd/platform/rdv3/rdv3_common.c14
-rw-r--r--plat/qemu/common/qemu_common.c13
-rw-r--r--services/std_svc/firme/firme_base_service.c12
-rw-r--r--services/std_svc/firme/firme_main.c40
-rw-r--r--services/std_svc/firme/firme_mecid.c96
-rw-r--r--services/std_svc/rmmd/rmmd_main.c44
-rw-r--r--services/std_svc/std_svc_setup.c6
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;