Merge "docs(fuzz): Adding fuzzing documentation"
diff --git a/Makefile b/Makefile
index 4936ff7..3ebf566 100644
--- a/Makefile
+++ b/Makefile
@@ -1,12 +1,12 @@
#
-# Copyright (c) 2018-2024, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2025, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
# TFTF Version
VERSION_MAJOR := 2
-VERSION_MINOR := 12
+VERSION_MINOR := 13
MAKE_HELPERS_DIRECTORY := make_helpers/
include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
@@ -171,6 +171,7 @@
$(eval $(call assert_boolean,ENABLE_REALM_PAYLOAD_TESTS))
$(eval $(call assert_boolean,TRANSFER_LIST))
$(eval $(call assert_boolean,SPMC_AT_EL3))
+$(eval $(call assert_boolean,CACTUS_PWR_MGMT_SUPPORT))
################################################################################
# Process build options
@@ -199,6 +200,7 @@
$(eval $(call add_define,TFTF_DEFINES,TRANSFER_LIST))
$(eval $(call add_define,TFTF_DEFINES,PLAT_AMU_GROUP1_COUNTERS_MASK))
$(eval $(call add_define,TFTF_DEFINES,SPMC_AT_EL3))
+$(eval $(call add_define,TFTF_DEFINES,CACTUS_PWR_MGMT_SUPPORT))
################################################################################
diff --git a/docs/change-log.rst b/docs/change-log.rst
index 0f22ded..964b13c 100644
--- a/docs/change-log.rst
+++ b/docs/change-log.rst
@@ -7,6 +7,148 @@
Tests are not guaranteed to be compatible. This also means that a version
upgrade on the TF-A-Tests side might not necessarily introduce any new feature.
+Version 2.13
+------------
+
+New features
+^^^^^^^^^^^^
+
+More features and tests are introduced in this release to enhance validation and
+support in the following areas:
+
+- Realm Management Extension
+- FF-A and SPM Testing
+- Fuzzing Framework
+- System Functionality Tests (e.g., PointerAuth, RAS registers, SMCCC feature
+ availability, FPMR access)
+- Firmware Handoff
+- Platform Enhancements
+
+Realm Management Extension
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ - Added and updated tests for `FEAT_MPAM` on Realms.
+ - Added AUX RTT support for planes.
+ - Added MbedTLS as a submodule.
+ - Added PCIe helpers.
+ - Added support for planes shared buffer.
+ - Added support for RSI Planes ABI.
+ - Added support for s2poe/pie for planes.
+ - Added test for multi REC planes.
+ - Added test for RSI_PLANE_REG_READ/WRITE command.
+ - Added test for validating RTT calls.
+ - Added test case to enter all planes.
+ - Added tests for realm attestation.
+ - Allocated memory for multiple planes.
+ - Called `RMI_PDEV` ABIs from host realm management.
+ - Enhanced Realm memory exception tests for planes.
+ - Extended RIPAS tests for planes.
+ - Fixed `rmi_realm_params` structure not being zeroed upon realm creation.
+ - Fixed bug in `RMI_RTT_SET_S2AP` command helper.
+ - Fixed multi REC PMU tests.
+ - Fixed PMU save/restore registers.
+ - Fixed position of `RTT_S2AP_INDIRECT` bit in `RmiFeatureRegister0`.
+ - Fixed Realm PMU tests.
+ - Fixed Realm tests marking all memory as RAM.
+ - Fixed the LPA2 flag setting for BRBE test.
+ - Handled permission fault for planes.
+ - Made PCIe tests default for testing.
+ - Undelegated PDEV granules upon DA ABI failure so later tests do not fail.
+ - Validated NS EL1/EL2 context is preserved by RMM.
+
+TFTF
+^^^^
+
+- SPM/FF-A Testing:
+
+ - Added a second instance of the Cactus S-EL1 partition to validate HOB generation.
+ - Added support for PPI timer interrupts.
+ - Added v1.2 fields to RXTX header.
+ - Fixed indirect messaging tests by adding ME handling.
+ - Introduced an enum type for FF-A errors.
+ - Refilled TX buffer after undelegation.
+ - Skipped CPU cycle allocation for SP vCPU to reach message loop.
+ - Skipped enabling/disabling SRI physical interrupts in TFTF.
+ - Specify the secure partition package for an SP
+
+- New Tests
+
+ - Fuzzing Enhancements
+
+ - Added fuzzing for vendor EL3 SMCCC calls.
+ - Enabled capability for randomized fuzzing inputs.
+ - Fixed single-feature testing behaviour.
+ - Introduced support for all SDEI calls, and the FF-A interface.
+
+ - Functionality Tests
+
+ - Added RAS system registers access test.
+ - Added test for `SMCCC_ARCH_WORKAROUND_4`.
+ - Added test for ARMv8.3 PointerAuth instructions.
+ - Added test for FPMR register access.
+ - Added tests for `SMCCC_ARCH_FEATURE_AVAILABILITY`.
+ - Added two new features and fixed TRNDR handling in availability tests
+ - Check SCTLR2, THE and D128 sysregs read/writes work as expected.
+ - Denied prohibited ABIs during `CPU_OFF` PSCI message handling.
+ - Evaluated EL3–RMM IDE KM interface in TRP.
+ - Validated `psci_is_last_cpu_to_idle_at_pwrlvl`.
+ - Verified save/restore logic for `BRBCR_EL1`.
+
+ - Firmware Handoff
+
+ - Added AArch32 handoff tests.
+ - Imported Measured Boot drivers from TF-A to support event log testing.
+ - Added tests for validating an event log received from a Transfer List.
+
+- Platforms:
+
+ - Versal NET
+
+ - Provided fix to prevent continuous interrupts by properly cleaning up
+ TTC timer in cancel routine.
+
+ - Versal
+
+ - Added platform specific function to return custom entry address.
+ - Updated Versal-2 test skip list.
+ - Updated Versal-2 TFTF and UART base address.
+
+ - Neoverse-RD
+
+ - Added TFTF support for RD-V3 platform.
+ - Deprecated and remove NRD1, RD-N1-Edge, RD-V1, SGI-575 platform
+ variants.
+
+- Miscellaneous
+
+ - Added `bdf` macro.
+ - Added `xpaci` instruction to exception report.
+ - Added build flag to control support for CPU_OFF PSCI message.
+ - Added Cortex-X925 and updated Cortex-X4 to Errata ABI.
+ - Added HOB definitions to TFTF.
+ - Added MbedTLS support and updated version to v3.6.3.
+ - Added new interface to get an invalid entrypoint address.
+ - Added register definitions needed for SMCCC_ARCH_FEATURE_AVAILABILITY
+ - Added split workaround check in Errata ABI test.
+ - Added support for SMC calls with no ret vals in x8.
+ - Updated ARM GCC toolchain requirements to 14.2.Rel1.
+ - Updated Cortex-A710 errata list.
+
+Cactus (Secure-EL1 FF-A test partition)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ - Added boot-time prints for Cactus-StMM HOB list.
+ - Added support for receiving PSCI messages through direct request framework message.
+ - Added mapping for boot information regions.
+ - Moved StMM to Cactus tertiary.
+
+Issues resolved since last release
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ - Applied fix to synchronize SME context before it is used.
+ - Fixed reporting of BRBE support with later revisions.
+ - Fixed compile error in `test_irq_spurious_gicv2.c`.
+
Version 2.12
------------
@@ -1996,7 +2138,7 @@
--------------
-*Copyright (c) 2018-2022, Arm Limited. All rights reserved.*
+*Copyright (c) 2018-2025, Arm Limited. All rights reserved.*
.. _Arm Neoverse Reference Design N1 Edge (RD-N1-Edge): https://developer.arm.com/products/system-design/reference-design/neoverse-reference-design
.. _Arm SGI-575: https://developer.arm.com/products/system-design/fixed-virtual-platforms
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 08343e3..3f62958 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -155,6 +155,14 @@
- ``SPMC_AT_EL3``: This flag is required to match the feature set of Cactus SP that
are implemented in TF-A EL3 SPMC. Default value is 0.
+- ``CACTUS_PWR_MGMT_SUPPORT``: If a Cactus SP subscribes to receiving power
+ management framework message through its partition manifest, this flag
+ controls whether the SP supports handling the aforementioned message. This
+ option can take either 0 (unsupported) or 1 (supported). Default value is 1.
+
+ Note that a value of 0 is particularly useful in stress testing of power
+ management handling by the SPMC.
+
Realm payload specific Build Options
------------------------------------
diff --git a/docs/getting_started/requirements.rst b/docs/getting_started/requirements.rst
index 14e4458..3c27b9d 100644
--- a/docs/getting_started/requirements.rst
+++ b/docs/getting_started/requirements.rst
@@ -25,7 +25,7 @@
======================== =====================
Name Version
======================== =====================
-Mbed TLS 3.6.2
+Mbed TLS 3.6.3
======================== =====================
Toolchain
@@ -40,7 +40,7 @@
Note that at least Python 3.8 is required.
Download and install the GNU cross-toolchain from Arm. The TF-A Tests have
-been tested with version 13.3.Rel1 (gcc 13.3):
+been tested with version 14.2.Rel1 (GCC 14.2):
- `GCC cross-toolchain`_
@@ -53,4 +53,4 @@
--------------
-*Copyright (c) 2019-2024, Arm Limited. All rights reserved.*
+*Copyright (c) 2019-2025, Arm Limited. All rights reserved.*
diff --git a/ext/mbedtls b/ext/mbedtls
index 107ea89..22098d4 160000
--- a/ext/mbedtls
+++ b/ext/mbedtls
@@ -1 +1 @@
-Subproject commit 107ea89daaefb9867ea9121002fbbdf926780e98
+Subproject commit 22098d41c6620ce07cf8a0134d37302355e1e5ef
diff --git a/include/common/firmware_image_package.h b/include/common/firmware_image_package.h
index 2a144ba..1bc6672 100644
--- a/include/common/firmware_image_package.h
+++ b/include/common/firmware_image_package.h
@@ -16,6 +16,8 @@
/* ToC Entry UUIDs */
#define UUID_FIRMWARE_UPDATE_SCP_BL2U \
{{0x65, 0x92, 0x27, 0x03}, {0x2f, 0x74}, {0xe6, 0x44}, 0x8d, 0xff, {0x57, 0x9a, 0xc1, 0xff, 0x06, 0x10} }
+#define UUID_TRUSTED_BOOT_FIRMWARE_BL2 \
+ {{0x5f, 0xf9, 0xec, 0x0b}, {0x4d, 0x22}, {0x3e, 0x4d}, 0xa5, 0x44, {0xc3, 0x9d, 0x81, 0xc7, 0x3f, 0x0a} }
#define UUID_FIRMWARE_UPDATE_BL2U \
{{0x60, 0xb3, 0xeb, 0x37}, {0xc1, 0xe5}, {0xea, 0x41}, 0x9d, 0xf3, {0x19, 0xed, 0xa1, 0x1f, 0x68, 0x01} }
#define UUID_FIRMWARE_UPDATE_NS_BL2U \
diff --git a/include/common/sha_common_macros.h b/include/common/sha_common_macros.h
new file mode 100644
index 0000000..d690e08
--- /dev/null
+++ b/include/common/sha_common_macros.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2024, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SHA_COMMON_MACROS_H
+#define SHA_COMMON_MACROS_H
+
+#define MD5_DIGEST_SIZE 16U
+#define SHA1_DIGEST_SIZE 20U
+#define SHA224_DIGEST_SIZE 28U
+#define SHA256_DIGEST_SIZE 32U
+#define SHA384_DIGEST_SIZE 48U
+#define SHA512_224_DIGEST_SIZE 28U
+#define SHA512_256_DIGEST_SIZE 32U
+#define SHA512_DIGEST_SIZE 64U
+
+#endif /* SHA_COMMON_MACROS_H */
diff --git a/include/common/test_helpers.h b/include/common/test_helpers.h
index 8ca4cdf..1ab35ba 100644
--- a/include/common/test_helpers.h
+++ b/include/common/test_helpers.h
@@ -279,6 +279,14 @@
} \
} while (false)
+#define SKIP_TEST_IF_RAS_NOT_SUPPORTED() \
+ do { \
+ if(!is_feat_ras_present()){ \
+ tftf_testcase_printf("ARMv8.2-RAS not supported\n"); \
+ return TEST_RESULT_SKIPPED; \
+ } \
+ } while (false)
+
#ifdef __aarch64__
#define SKIP_TEST_IF_PA_SIZE_LESS_THAN(n) \
do { \
diff --git a/include/configs/tftf_mbedtls_config.h b/include/configs/tftf_mbedtls_config.h
index 77e7ba9..9ad0b71 100644
--- a/include/configs/tftf_mbedtls_config.h
+++ b/include/configs/tftf_mbedtls_config.h
@@ -21,8 +21,8 @@
/* For snprintf function declaration */
#include <stdio.h>
-/* This file is compatible with release 3.6.2 */
-#define MBEDTLS_CONFIG_VERSION 0x03060200
+/* This file is compatible with release 3.6.3 */
+#define MBEDTLS_CONFIG_VERSION 0x03060300
/* Configuration file to build mbed TLS with the required features for TFTF */
#define MBEDTLS_PLATFORM_MEMORY
diff --git a/include/drivers/auth/crypto_mod.h b/include/drivers/auth/crypto_mod.h
new file mode 100644
index 0000000..bec19da
--- /dev/null
+++ b/include/drivers/auth/crypto_mod.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2015-2023, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CRYPTO_MOD_H
+#define CRYPTO_MOD_H
+
+#define CRYPTO_AUTH_VERIFY_ONLY 1
+#define CRYPTO_HASH_CALC_ONLY 2
+#define CRYPTO_AUTH_VERIFY_AND_HASH_CALC 3
+
+/* Return values */
+enum crypto_ret_value {
+ CRYPTO_SUCCESS = 0,
+ CRYPTO_ERR_INIT,
+ CRYPTO_ERR_HASH,
+ CRYPTO_ERR_SIGNATURE,
+ CRYPTO_ERR_DECRYPTION,
+ CRYPTO_ERR_UNKNOWN
+};
+
+#define CRYPTO_MAX_IV_SIZE 16U
+#define CRYPTO_MAX_TAG_SIZE 16U
+
+/* Decryption algorithm */
+enum crypto_dec_algo {
+ CRYPTO_GCM_DECRYPT = 0
+};
+
+/* Message digest algorithm */
+enum crypto_md_algo {
+ CRYPTO_MD_SHA256,
+ CRYPTO_MD_SHA384,
+ CRYPTO_MD_SHA512,
+};
+
+/* Maximum size as per the known stronger hash algorithm i.e.SHA512 */
+#define CRYPTO_MD_MAX_SIZE 64U
+
+/*
+ * Cryptographic library descriptor
+ */
+typedef struct crypto_lib_desc_s {
+ const char *name;
+
+ /* Initialize library. This function is not expected to fail. All errors
+ * must be handled inside the function, asserting or panicking in case of
+ * a non-recoverable error */
+ void (*init)(void);
+
+ /* Verify a digital signature. Return one of the
+ * 'enum crypto_ret_value' options */
+ int (*verify_signature)(void *data_ptr, unsigned int data_len,
+ void *sig_ptr, unsigned int sig_len,
+ void *sig_alg, unsigned int sig_alg_len,
+ void *pk_ptr, unsigned int pk_len);
+
+ /* Verify a hash. Return one of the 'enum crypto_ret_value' options */
+ int (*verify_hash)(void *data_ptr, unsigned int data_len,
+ void *digest_info_ptr, unsigned int digest_info_len);
+
+ /* Calculate a hash. Return hash value */
+ int (*calc_hash)(enum crypto_md_algo md_alg, void *data_ptr,
+ unsigned int data_len,
+ unsigned char output[CRYPTO_MD_MAX_SIZE]);
+
+ /* Convert Public key (optional) */
+ int (*convert_pk)(void *full_pk_ptr, unsigned int full_pk_len,
+ void **hashed_pk_ptr, unsigned int *hashed_pk_len);
+
+ /*
+ * Authenticated decryption. Return one of the
+ * 'enum crypto_ret_value' options.
+ */
+ int (*auth_decrypt)(enum crypto_dec_algo dec_algo, void *data_ptr,
+ size_t len, const void *key, unsigned int key_len,
+ unsigned int key_flags, const void *iv,
+ unsigned int iv_len, const void *tag,
+ unsigned int tag_len);
+} crypto_lib_desc_t;
+
+/* Public functions */
+#if CRYPTO_SUPPORT
+void crypto_mod_init(void);
+#else
+static inline void crypto_mod_init(void)
+{
+}
+#endif /* CRYPTO_SUPPORT */
+
+#if (CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY) || \
+ (CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC)
+int crypto_mod_verify_signature(void *data_ptr, unsigned int data_len,
+ void *sig_ptr, unsigned int sig_len,
+ void *sig_alg_ptr, unsigned int sig_alg_len,
+ void *pk_ptr, unsigned int pk_len);
+int crypto_mod_verify_hash(void *data_ptr, unsigned int data_len,
+ void *digest_info_ptr, unsigned int digest_info_len);
+#endif /* (CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY) || \
+ (CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC) */
+
+int crypto_mod_auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr,
+ size_t len, const void *key, unsigned int key_len,
+ unsigned int key_flags, const void *iv,
+ unsigned int iv_len, const void *tag,
+ unsigned int tag_len);
+
+#if (CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY) || \
+ (CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC)
+int crypto_mod_calc_hash(enum crypto_md_algo alg, void *data_ptr,
+ unsigned int data_len,
+ unsigned char output[CRYPTO_MD_MAX_SIZE]);
+#endif /* (CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY) || \
+ (CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC) */
+
+int crypto_mod_convert_pk(void *full_pk_ptr, unsigned int full_pk_len,
+ void **hashed_pk_ptr, unsigned int *hashed_pk_len);
+
+/* Macro to register a cryptographic library */
+#define REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash, \
+ _calc_hash, _auth_decrypt, _convert_pk) \
+ const crypto_lib_desc_t crypto_lib_desc = { \
+ .name = _name, \
+ .init = _init, \
+ .verify_signature = _verify_signature, \
+ .verify_hash = _verify_hash, \
+ .calc_hash = _calc_hash, \
+ .auth_decrypt = _auth_decrypt, \
+ .convert_pk = _convert_pk \
+ }
+
+extern const crypto_lib_desc_t crypto_lib_desc;
+
+#endif /* CRYPTO_MOD_H */
diff --git a/include/drivers/measured_boot/event_log/tcg.h b/include/drivers/measured_boot/event_log/tcg.h
new file mode 100644
index 0000000..653f9c2
--- /dev/null
+++ b/include/drivers/measured_boot/event_log/tcg.h
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TCG_H
+#define TCG_H
+
+#include <stdint.h>
+#include <common/sha_common_macros.h>
+
+#define TCG_ID_EVENT_SIGNATURE_03 "Spec ID Event03"
+#define TCG_STARTUP_LOCALITY_SIGNATURE "StartupLocality"
+
+#define TCG_SPEC_VERSION_MAJOR_TPM2 2
+#define TCG_SPEC_VERSION_MINOR_TPM2 0
+#define TCG_SPEC_ERRATA_TPM2 2
+
+/*
+ * Event types
+ * Ref. Table 9 Events
+ * TCG PC Client Platform Firmware Profile Specification.
+ */
+#define EV_PREBOOT_CERT U(0x00000000)
+#define EV_POST_CODE U(0x00000001)
+#define EV_UNUSED U(0x00000002)
+#define EV_NO_ACTION U(0x00000003)
+#define EV_SEPARATOR U(0x00000004)
+#define EV_ACTION U(0x00000005)
+#define EV_EVENT_TAG U(0x00000006)
+#define EV_S_CRTM_CONTENTS U(0x00000007)
+#define EV_S_CRTM_VERSION U(0x00000008)
+#define EV_CPU_MICROCODE U(0x00000009)
+#define EV_PLATFORM_CONFIG_FLAGS U(0x0000000A)
+#define EV_TABLE_OF_DEVICES U(0x0000000B)
+#define EV_COMPACT_HASH U(0x0000000C)
+#define EV_IPL U(0x0000000D)
+#define EV_IPL_PARTITION_DATA U(0x0000000E)
+#define EV_NONHOST_CODE U(0x0000000F)
+#define EV_NONHOST_CONFIG U(0x00000010)
+#define EV_NONHOST_INFO U(0x00000011)
+#define EV_OMIT_BOOT_DEVICE_EVENTS U(0x00000012)
+#define EV_EFI_EVENT_BASE U(0x80000000)
+#define EV_EFI_VARIABLE_DRIVER_CONFIG U(0x80000001)
+#define EV_EFI_VARIABLE_BOOT U(0x80000002)
+#define EV_EFI_BOOT_SERVICES_APPLICATION U(0x80000003)
+#define EV_EFI_BOOT_SERVICES_DRIVER U(0x80000004)
+#define EV_EFI_RUNTIME_SERVICES_DRIVER U(0x80000005)
+#define EV_EFI_GPT_EVENT U(0x80000006)
+#define EV_EFI_ACTION U(0x80000007)
+#define EV_EFI_PLATFORM_FIRMWARE_BLOB U(0x80000008)
+#define EV_EFI_HANDOFF_TABLES U(0x80000009)
+#define EV_EFI_HCRTM_EVENT U(0x80000010)
+#define EV_EFI_VARIABLE_AUTHORITY U(0x800000E0)
+
+/*
+ * TPM_ALG_ID constants.
+ * Ref. Table 9 - Definition of (UINT16) TPM_ALG_ID Constants
+ * Trusted Platform Module Library. Part 2: Structures
+ */
+#define TPM_ALG_SHA256 0x000B
+#define TPM_ALG_SHA384 0x000C
+#define TPM_ALG_SHA512 0x000D
+
+/* TCG Platform Type */
+#define PLATFORM_CLASS_CLIENT 0
+#define PLATFORM_CLASS_SERVER 1
+
+enum {
+ /*
+ * SRTM, BIOS, Host Platform Extensions, Embedded
+ * Option ROMs and PI Drivers
+ */
+ PCR_0 = 0,
+ /* Host Platform Configuration */
+ PCR_1,
+ /* UEFI driver and application Code */
+ PCR_2,
+ /* UEFI driver and application Configuration and Data */
+ PCR_3,
+ /* UEFI Boot Manager Code (usually the MBR) and Boot Attempts */
+ PCR_4,
+ /*
+ * Boot Manager Code Configuration and Data (for use
+ * by the Boot Manager Code) and GPT/Partition Table
+ */
+ PCR_5,
+ /* Host Platform Manufacturer Specific */
+ PCR_6,
+ /* Secure Boot Policy */
+ PCR_7,
+ /* 8-15: Defined for use by the Static OS */
+ PCR_8,
+ /* Debug */
+ PCR_16 = 16,
+
+ /* D-CRTM-measurements by DRTM implementation */
+ PCR_17 = 17,
+ /* DCE measurements by DRTM implementation */
+ PCR_18 = 18
+};
+
+#pragma pack(push, 1)
+
+/*
+ * PCR Event Header
+ * TCG EFI Protocol Specification
+ * 5.3 Event Log Header
+ */
+typedef struct {
+ /* PCRIndex:
+ * The PCR Index to which this event is extended
+ */
+ uint32_t pcr_index;
+
+ /* EventType:
+ * SHALL be an EV_NO_ACTION event
+ */
+ uint32_t event_type;
+
+ /* SHALL be 20 Bytes of 0x00 */
+ uint8_t digest[SHA1_DIGEST_SIZE];
+
+ /* The size of the event */
+ uint32_t event_size;
+
+ /* SHALL be a TCG_EfiSpecIdEvent */
+ uint8_t event[]; /* [event_data_size] */
+} tcg_pcr_event_t;
+
+/*
+ * Log Header Entry Data
+ * Ref. Table 14 TCG_EfiSpecIdEventAlgorithmSize
+ * TCG PC Client Platform Firmware Profile 9.4.5.1
+ */
+typedef struct {
+ /* Algorithm ID (hashAlg) of the Hash used by BIOS */
+ uint16_t algorithm_id;
+
+ /* The size of the digest produced by the implemented Hash algorithm */
+ uint16_t digest_size;
+} id_event_algorithm_size_t;
+
+/*
+ * TCG_EfiSpecIdEvent structure
+ * Ref. Table 15 TCG_EfiSpecIdEvent
+ * TCG PC Client Platform Firmware Profile 9.4.5.1
+ */
+typedef struct {
+ /*
+ * The NUL-terminated ASCII string "Spec ID Event03".
+ * SHALL be set to {0x53, 0x70, 0x65, 0x63, 0x20, 0x49, 0x44,
+ * 0x20, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x33, 0x00}.
+ */
+ uint8_t signature[16];
+
+ /*
+ * The value for the Platform Class.
+ * The enumeration is defined in the TCG ACPI Specification Client
+ * Common Header.
+ */
+ uint32_t platform_class;
+
+ /*
+ * The PC Client Platform Profile Specification minor version number
+ * this BIOS supports.
+ * Any BIOS supporting this version (2.0) MUST set this value to 0x00.
+ */
+ uint8_t spec_version_minor;
+
+ /*
+ * The PC Client Platform Profile Specification major version number
+ * this BIOS supports.
+ * Any BIOS supporting this version (2.0) MUST set this value to 0x02.
+ */
+ uint8_t spec_version_major;
+
+ /*
+ * The PC Client Platform Profile Specification errata version number
+ * this BIOS supports.
+ * Any BIOS supporting this version (2.0) MUST set this value to 0x02.
+ */
+ uint8_t spec_errata;
+
+ /*
+ * Specifies the size of the UINTN fields used in various data
+ * structures used in this specification.
+ * 0x01 indicates UINT32 and 0x02 indicates UINT64.
+ */
+ uint8_t uintn_size;
+
+ /*
+ * The number of Hash algorithms in the digestSizes field.
+ * This field MUST be set to a value of 0x01 or greater.
+ */
+ uint32_t number_of_algorithms;
+
+ /*
+ * Each TCG_EfiSpecIdEventAlgorithmSize SHALL contain an algorithmId
+ * and digestSize for each hash algorithm used in the TCG_PCR_EVENT2
+ * structure, the first of which is a Hash algorithmID and the second
+ * is the size of the respective digest.
+ */
+ id_event_algorithm_size_t digest_size[]; /* number_of_algorithms */
+} id_event_struct_header_t;
+
+typedef struct {
+ /*
+ * Size in bytes of the VendorInfo field.
+ * Maximum value MUST be FFh bytes.
+ */
+ uint8_t vendor_info_size;
+
+ /*
+ * Provided for use by Platform Firmware implementer. The value might
+ * be used, for example, to provide more detailed information about the
+ * specific BIOS such as BIOS revision numbers, etc. The values within
+ * this field are not standardized and are implementer-specific.
+ * Platform-specific or -unique information MUST NOT be provided in
+ * this field.
+ *
+ */
+ uint8_t vendor_info[]; /* [vendorInfoSize] */
+} id_event_struct_data_t;
+
+typedef struct {
+ id_event_struct_header_t struct_header;
+ id_event_struct_data_t struct_data;
+} id_event_struct_t;
+
+typedef struct {
+ tcg_pcr_event_t header;
+ id_event_struct_header_t struct_header;
+} id_event_headers_t;
+
+/* TPMT_HA Structure */
+typedef struct {
+ /* Selector of the hash contained in the digest that implies
+ * the size of the digest
+ */
+ uint16_t algorithm_id; /* AlgorithmId */
+
+ /* Digest, depends on AlgorithmId */
+ uint8_t digest[]; /* Digest[] */
+} tpmt_ha;
+
+/*
+ * TPML_DIGEST_VALUES Structure
+ */
+typedef struct {
+ /* The number of digests in the list */
+ uint32_t count; /* Count */
+
+ /* The list of tagged digests, as sent to the TPM as part of a
+ * TPM2_PCR_Extend or as received from a TPM2_PCR_Event command
+ */
+ tpmt_ha digests[]; /* Digests[Count] */
+} tpml_digest_values;
+
+/*
+ * TCG_PCR_EVENT2 header
+ */
+typedef struct {
+ /* The PCR Index to which this event was extended */
+ uint32_t pcr_index; /* PCRIndex */
+
+ /* Type of event */
+ uint32_t event_type; /* EventType */
+
+ /* Digests:
+ * A counted list of tagged digests, which contain the digest of
+ * the event data (or external data) for all active PCR banks
+ */
+ tpml_digest_values digests; /* Digests */
+} event2_header_t;
+
+typedef struct event2_data {
+ /* The size of the event data */
+ uint32_t event_size; /* EventSize */
+
+ /* The data of the event */
+ uint8_t event[]; /* Event[EventSize] */
+} event2_data_t;
+
+/*
+ * Startup Locality Event
+ * Ref. TCG PC Client Platform Firmware Profile 9.4.5.3
+ */
+typedef struct {
+ /*
+ * The NUL-terminated ASCII string "StartupLocality" SHALL be
+ * set to {0x53 0x74 0x61 0x72 0x74 0x75 0x70 0x4C 0x6F 0x63
+ * 0x61 0x6C 0x69 0x74 0x79 0x00}
+ */
+ uint8_t signature[16];
+
+ /* The Locality Indicator which sent the TPM2_Startup command */
+ uint8_t startup_locality;
+} startup_locality_event_t;
+
+#pragma pack(pop)
+
+#endif /* TCG_H */
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index 09835b5..d9009dd 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -273,6 +273,7 @@
#define ID_AA64DFR0_PMUVER_SHIFT U(8)
#define ID_AA64DFR0_PMUVER_MASK ULL(0xf)
#define ID_AA64DFR0_PMUVER_NOT_SUPPORTED ULL(0)
+#define ID_AA64DFR0_PMUVER_V3P9_SUPPORTED ULL(9)
/* ID_AA64DFR0_EL1.TraceVer definitions */
#define ID_AA64DFR0_TRACEVER_SHIFT U(4)
@@ -285,6 +286,10 @@
/* ID_AA64ISAR0_EL1 definitions */
#define ID_AA64ISAR0_EL1 S3_0_C0_C6_0
+#define ID_AA64ISAR0_RNDR_MASK ULL(0xf)
+#define ID_AA64ISAR0_RNDR_SHIFT U(60)
+#define ID_AA64ISAR0_RNDR_WIDTH U(4)
+#define ID_AA64ISAR0_RNDR_SUPPORTED ULL(0x1)
#define ID_AA64ISAR0_TLB_MASK ULL(0xf)
#define ID_AA64ISAR0_TLB_SHIFT U(56)
#define ID_AA64ISAR0_TLB_WIDTH U(4)
@@ -408,6 +413,10 @@
#define ID_AA64MMFR1_EL1_PAN_SUPPORTED ULL(0x1)
#define ID_AA64MMFR1_EL1_PAN2_SUPPORTED ULL(0x2)
#define ID_AA64MMFR1_EL1_PAN3_SUPPORTED ULL(0x3)
+#define ID_AA64MMFR1_EL1_TWED_SHIFT U(32)
+#define ID_AA64MMFR1_EL1_TWED_MASK ULL(0xf)
+#define ID_AA64MMFR1_EL1_TWED_WIDTH U(4)
+#define ID_AA64MMFR1_EL1_TWED_SUPPORTED ULL(0x1)
#define ID_AA64MMFR1_EL1_HCX_SHIFT U(40)
#define ID_AA64MMFR1_EL1_HCX_MASK ULL(0xf)
#define ID_AA64MMFR1_EL1_HCX_SUPPORTED ULL(0x1)
@@ -1335,6 +1344,7 @@
* Definitions for system register interface to MPAM
******************************************************************************/
#define MPAMIDR_EL1 S3_0_C10_C4_4
+#define MPAMSM_EL1 S3_0_C10_C5_3
#define MPAM2_EL2 S3_4_C10_C5_0
#define MPAMHCR_EL2 S3_4_C10_C4_0
#define MPAM3_EL3 S3_6_C10_C5_0
diff --git a/include/lib/aarch64/arch_features.h b/include/lib/aarch64/arch_features.h
index cee8dd2..3b4fffc 100644
--- a/include/lib/aarch64/arch_features.h
+++ b/include/lib/aarch64/arch_features.h
@@ -230,6 +230,13 @@
ID_AA64ISAR2_WFXT_MASK) == ID_AA64ISAR2_WFXT_SUPPORTED);
}
+static inline bool is_feat_rng_present(void)
+{
+ return (((read_id_aa64isar0_el1() >> ID_AA64ISAR0_RNDR_SHIFT) &
+ ID_AA64ISAR0_RNDR_MASK)
+ >= ID_AA64ISAR0_RNDR_SUPPORTED);
+}
+
static inline bool is_feat_rng_trap_present(void)
{
return (((read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_RNDR_TRAP_SHIFT) &
@@ -273,6 +280,12 @@
ID_AA64DFR0_PMUVER_MASK) != ID_AA64DFR0_PMUVER_NOT_SUPPORTED);
}
+static inline bool is_feat_pmuv3p9_present(void)
+{
+ return (((read_id_aa64dfr0_el1() >> ID_AA64DFR0_PMUVER_SHIFT) &
+ ID_AA64DFR0_PMUVER_MASK) >= ID_AA64DFR0_PMUVER_V3P9_SUPPORTED);
+}
+
static inline bool get_feat_hpmn0_supported(void)
{
return (((read_id_aa64dfr0_el1() >> ID_AA64DFR0_HPMN0_SHIFT) &
@@ -477,6 +490,12 @@
return amu_get_version() >= ID_AA64PFR0_AMU_V1P1;
}
+static inline bool is_feat_twed_present(void)
+{
+ return EXTRACT(ID_AA64MMFR1_EL1_TWED, read_id_aa64mmfr1_el1())
+ >= ID_AA64MMFR1_EL1_TWED_SUPPORTED;
+}
+
static inline bool is_feat_trbe_present(void)
{
return EXTRACT(ID_AA64DFR0_TRACEBUFFER, read_id_aa64dfr0_el1())
diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h
index 42e104c..ed705bf 100644
--- a/include/lib/aarch64/arch_helpers.h
+++ b/include/lib/aarch64/arch_helpers.h
@@ -525,6 +525,7 @@
DEFINE_RENAME_SYSREG_RW_FUNCS(mpam2_el2, MPAM2_EL2)
DEFINE_RENAME_SYSREG_RW_FUNCS(mpamhcr_el2, MPAMHCR_EL2)
DEFINE_RENAME_SYSREG_WRITE_FUNC(mpamidr_el1, MPAMIDR_EL1)
+DEFINE_RENAME_SYSREG_WRITE_FUNC(mpamsm_el1, MPAMSM_EL1)
DEFINE_RENAME_SYSREG_WRITE_FUNC(mpam0_el1, MPAM0_EL1)
DEFINE_RENAME_SYSREG_WRITE_FUNC(mpam1_el1, MPAM1_EL1)
diff --git a/include/lib/event_log/event_handoff.h b/include/lib/event_log/event_handoff.h
new file mode 100644
index 0000000..e969d1f
--- /dev/null
+++ b/include/lib/event_log/event_handoff.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+#ifndef HANDOFF_H
+#define HANDOFF_H
+
+#include <stdint.h>
+
+#include <lib/transfer_list.h>
+
+/**
+ * Initializes or extends the TPM event log in the transfer list.
+ *
+ * If an event log entry exists, attempts to resize it. Otherwise, adds a new entry.
+ * Copies old data if needed. Updates free to reflect available space.
+ *
+ * @param tl Pointer to the transfer list header.
+ * @param req_size Requested size (bytes)
+ * @param free Available size (bytes)
+ * @return Pointer to writable space in the log, or NULL on failure.
+ */
+uint8_t *transfer_list_event_log_extend(struct transfer_list_header *tl,
+ size_t req_size, size_t *free);
+
+/**
+ * Finalizes the event log after writing is complete.
+ *
+ * Resizes the event log to match actual data written, updates checksum,
+ * and flushes cache for the next stage.
+ *
+ * @param tl Pointer to the transfer list header.
+ * @param cursor End offset of written log data.
+ * @return Pointer to finalized log data (past reserved bytes), or NULL.
+ */
+uint8_t *transfer_list_event_log_finish(struct transfer_list_header *tl,
+ uintptr_t cursor);
+
+#define EVENT_LOG_RESERVED_BYTES U(4)
+
+#endif /* HANDOFF_H */
diff --git a/include/lib/event_log/event_log.h b/include/lib/event_log/event_log.h
new file mode 100644
index 0000000..b5adfdc
--- /dev/null
+++ b/include/lib/event_log/event_log.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2020-2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef EVENT_LOG_H
+#define EVENT_LOG_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <drivers/auth/crypto_mod.h>
+#include "event_handoff.h"
+#include "tcg.h"
+
+/*
+ * Set Event Log debug level to one of:
+ *
+ * LOG_LEVEL_ERROR
+ * LOG_LEVEL_INFO
+ * LOG_LEVEL_WARNING
+ * LOG_LEVEL_VERBOSE
+ */
+#if EVENT_LOG_LEVEL == LOG_LEVEL_ERROR
+#define LOG_EVENT ERROR
+#elif EVENT_LOG_LEVEL == LOG_LEVEL_NOTICE
+#define LOG_EVENT NOTICE
+#elif EVENT_LOG_LEVEL == LOG_LEVEL_WARNING
+#define LOG_EVENT WARN
+#elif EVENT_LOG_LEVEL == LOG_LEVEL_INFO
+#define LOG_EVENT INFO
+#elif EVENT_LOG_LEVEL == LOG_LEVEL_VERBOSE
+#define LOG_EVENT VERBOSE
+#else
+#define LOG_EVENT printf
+#endif
+
+/* Number of hashing algorithms supported */
+#define HASH_ALG_COUNT 1U
+
+#define EVLOG_INVALID_ID UINT32_MAX
+
+#define MEMBER_SIZE(type, member) sizeof(((type *)0)->member)
+
+typedef struct {
+ unsigned int id;
+ const char *name;
+ unsigned int pcr;
+} event_log_metadata_t;
+
+#define ID_EVENT_SIZE (sizeof(id_event_headers_t) + \
+ (sizeof(id_event_algorithm_size_t) * HASH_ALG_COUNT) + \
+ sizeof(id_event_struct_data_t))
+
+#define LOC_EVENT_SIZE (sizeof(event2_header_t) + \
+ sizeof(tpmt_ha) + TCG_DIGEST_SIZE + \
+ sizeof(event2_data_t) + \
+ sizeof(startup_locality_event_t))
+
+#define LOG_MIN_SIZE (ID_EVENT_SIZE + LOC_EVENT_SIZE)
+
+#define EVENT2_HDR_SIZE (sizeof(event2_header_t) + \
+ sizeof(tpmt_ha) + TCG_DIGEST_SIZE + \
+ sizeof(event2_data_t))
+
+/* Functions' declarations */
+
+/**
+ * Initialize the Event Log buffer.
+ *
+ * Sets global pointers to manage the Event Log memory region,
+ * allowing subsequent log operations to write into the buffer.
+ *
+ * @param[in] event_log_start Pointer to the start of the Event Log buffer.
+ * @param[in] event_log_finish Pointer to the end of the buffer
+ * (i.e., one byte past the last valid address).
+ *
+ * @return 0 on success, or -EINVAL if the input range is invalid.
+ */
+int event_log_buf_init(uint8_t *event_log_start, uint8_t *event_log_finish);
+
+/**
+ * Dump the contents of the Event Log.
+ *
+ * Outputs the raw contents of the Event Log buffer, typically
+ * for debugging or audit purposes.
+ *
+ * @param[in] log_addr Pointer to the start of the Event Log buffer.
+ * @param[in] log_size Size of the Event Log buffer in bytes.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int event_log_dump(uint8_t *log_addr, size_t log_size);
+
+/**
+ * Initialize the Event Log subsystem.
+ *
+ * Wrapper around `event_log_buf_init()` to configure the memory range
+ * for the Event Log buffer.
+ *
+ * @param[in] event_log_start Pointer to the start of the Event Log buffer.
+ * @param[in] event_log_finish Pointer to the end of the buffer
+ * (i.e., one byte past the last valid address).
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int event_log_init(uint8_t *event_log_start, uint8_t *event_log_finish);
+
+/**
+ * Measure input data and log its hash to the Event Log.
+ *
+ * Computes the cryptographic hash of the specified data and records it
+ * in the Event Log as a TCG_PCR_EVENT2 structure using event type EV_POST_CODE.
+ * Useful for firmware or image attestation.
+ *
+ * @param[in] data_base Pointer to the base of the data to be measured.
+ * @param[in] data_size Size of the data in bytes.
+ * @param[in] data_id Identifier used to match against metadata.
+ * @param[in] metadata_ptr Pointer to an array of event_log_metadata_t.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int event_log_measure_and_record(uintptr_t data_base, uint32_t data_size,
+ uint32_t data_id,
+ const event_log_metadata_t *metadata_ptr);
+
+/**
+ * Measure the input data and return its hash.
+ *
+ * Computes the cryptographic hash of the specified memory region using
+ * the default hashing algorithm configured in the Event Log subsystem.
+ *
+ * @param[in] data_base Pointer to the base of the data to be measured.
+ * @param[in] data_size Size of the data in bytes.
+ * @param[out] hash_data Buffer to hold the resulting hash output
+ * (must be at least CRYPTO_MD_MAX_SIZE bytes).
+ *
+ * @return 0 on success, or an error code on failure.
+ */
+int event_log_measure(uintptr_t data_base, uint32_t data_size,
+ unsigned char hash_data[CRYPTO_MD_MAX_SIZE]);
+
+/**
+ * Record a measurement event in the Event Log.
+ *
+ * Writes a TCG_PCR_EVENT2 structure to the Event Log using the
+ * provided hash and metadata. This function assumes the buffer
+ * has enough space and that `event_log_buf_init()` has been called.
+ *
+ * @param[in] hash Pointer to the digest (TCG_DIGEST_SIZE bytes).
+ * @param[in] event_type Type of the event, as defined in tcg.h.
+ * @param[in] metadata_ptr Pointer to an event_log_metadata_t structure
+ * providing event-specific context (e.g., PCR index, name).
+ *
+ * @return 0 on success, or -ENOMEM if the buffer has insufficient space.
+ */
+int event_log_record(const uint8_t *hash, uint32_t event_type,
+ const event_log_metadata_t *metadata_ptr);
+
+/**
+ * Initialize the Event Log with mandatory header events.
+ *
+ * Writes the Specification ID (SpecID) and Startup Locality events
+ * as required by the TCG PC Client Platform Firmware Profile.
+ * These must be the first entries in the Event Log.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int event_log_write_header(void);
+
+/**
+ * Write the SpecID event to the Event Log.
+ *
+ * Records the TCG_EfiSpecIDEventStruct to declare the structure
+ * and supported algorithms of the Event Log format.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int event_log_write_specid_event(void);
+
+/**
+ * Get the current size of the Event Log.
+ *
+ * Calculates how many bytes of the Event Log buffer have been used,
+ * based on the current log pointer and the start of the buffer.
+ *
+ * @param[in] event_log_start Pointer to the start of the Event Log buffer.
+ *
+ * @return The number of bytes currently used in the Event Log.
+ */
+size_t event_log_get_cur_size(uint8_t *event_log_start);
+
+#endif /* EVENT_LOG_H */
diff --git a/include/lib/event_log/tcg.h b/include/lib/event_log/tcg.h
new file mode 100644
index 0000000..653f9c2
--- /dev/null
+++ b/include/lib/event_log/tcg.h
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TCG_H
+#define TCG_H
+
+#include <stdint.h>
+#include <common/sha_common_macros.h>
+
+#define TCG_ID_EVENT_SIGNATURE_03 "Spec ID Event03"
+#define TCG_STARTUP_LOCALITY_SIGNATURE "StartupLocality"
+
+#define TCG_SPEC_VERSION_MAJOR_TPM2 2
+#define TCG_SPEC_VERSION_MINOR_TPM2 0
+#define TCG_SPEC_ERRATA_TPM2 2
+
+/*
+ * Event types
+ * Ref. Table 9 Events
+ * TCG PC Client Platform Firmware Profile Specification.
+ */
+#define EV_PREBOOT_CERT U(0x00000000)
+#define EV_POST_CODE U(0x00000001)
+#define EV_UNUSED U(0x00000002)
+#define EV_NO_ACTION U(0x00000003)
+#define EV_SEPARATOR U(0x00000004)
+#define EV_ACTION U(0x00000005)
+#define EV_EVENT_TAG U(0x00000006)
+#define EV_S_CRTM_CONTENTS U(0x00000007)
+#define EV_S_CRTM_VERSION U(0x00000008)
+#define EV_CPU_MICROCODE U(0x00000009)
+#define EV_PLATFORM_CONFIG_FLAGS U(0x0000000A)
+#define EV_TABLE_OF_DEVICES U(0x0000000B)
+#define EV_COMPACT_HASH U(0x0000000C)
+#define EV_IPL U(0x0000000D)
+#define EV_IPL_PARTITION_DATA U(0x0000000E)
+#define EV_NONHOST_CODE U(0x0000000F)
+#define EV_NONHOST_CONFIG U(0x00000010)
+#define EV_NONHOST_INFO U(0x00000011)
+#define EV_OMIT_BOOT_DEVICE_EVENTS U(0x00000012)
+#define EV_EFI_EVENT_BASE U(0x80000000)
+#define EV_EFI_VARIABLE_DRIVER_CONFIG U(0x80000001)
+#define EV_EFI_VARIABLE_BOOT U(0x80000002)
+#define EV_EFI_BOOT_SERVICES_APPLICATION U(0x80000003)
+#define EV_EFI_BOOT_SERVICES_DRIVER U(0x80000004)
+#define EV_EFI_RUNTIME_SERVICES_DRIVER U(0x80000005)
+#define EV_EFI_GPT_EVENT U(0x80000006)
+#define EV_EFI_ACTION U(0x80000007)
+#define EV_EFI_PLATFORM_FIRMWARE_BLOB U(0x80000008)
+#define EV_EFI_HANDOFF_TABLES U(0x80000009)
+#define EV_EFI_HCRTM_EVENT U(0x80000010)
+#define EV_EFI_VARIABLE_AUTHORITY U(0x800000E0)
+
+/*
+ * TPM_ALG_ID constants.
+ * Ref. Table 9 - Definition of (UINT16) TPM_ALG_ID Constants
+ * Trusted Platform Module Library. Part 2: Structures
+ */
+#define TPM_ALG_SHA256 0x000B
+#define TPM_ALG_SHA384 0x000C
+#define TPM_ALG_SHA512 0x000D
+
+/* TCG Platform Type */
+#define PLATFORM_CLASS_CLIENT 0
+#define PLATFORM_CLASS_SERVER 1
+
+enum {
+ /*
+ * SRTM, BIOS, Host Platform Extensions, Embedded
+ * Option ROMs and PI Drivers
+ */
+ PCR_0 = 0,
+ /* Host Platform Configuration */
+ PCR_1,
+ /* UEFI driver and application Code */
+ PCR_2,
+ /* UEFI driver and application Configuration and Data */
+ PCR_3,
+ /* UEFI Boot Manager Code (usually the MBR) and Boot Attempts */
+ PCR_4,
+ /*
+ * Boot Manager Code Configuration and Data (for use
+ * by the Boot Manager Code) and GPT/Partition Table
+ */
+ PCR_5,
+ /* Host Platform Manufacturer Specific */
+ PCR_6,
+ /* Secure Boot Policy */
+ PCR_7,
+ /* 8-15: Defined for use by the Static OS */
+ PCR_8,
+ /* Debug */
+ PCR_16 = 16,
+
+ /* D-CRTM-measurements by DRTM implementation */
+ PCR_17 = 17,
+ /* DCE measurements by DRTM implementation */
+ PCR_18 = 18
+};
+
+#pragma pack(push, 1)
+
+/*
+ * PCR Event Header
+ * TCG EFI Protocol Specification
+ * 5.3 Event Log Header
+ */
+typedef struct {
+ /* PCRIndex:
+ * The PCR Index to which this event is extended
+ */
+ uint32_t pcr_index;
+
+ /* EventType:
+ * SHALL be an EV_NO_ACTION event
+ */
+ uint32_t event_type;
+
+ /* SHALL be 20 Bytes of 0x00 */
+ uint8_t digest[SHA1_DIGEST_SIZE];
+
+ /* The size of the event */
+ uint32_t event_size;
+
+ /* SHALL be a TCG_EfiSpecIdEvent */
+ uint8_t event[]; /* [event_data_size] */
+} tcg_pcr_event_t;
+
+/*
+ * Log Header Entry Data
+ * Ref. Table 14 TCG_EfiSpecIdEventAlgorithmSize
+ * TCG PC Client Platform Firmware Profile 9.4.5.1
+ */
+typedef struct {
+ /* Algorithm ID (hashAlg) of the Hash used by BIOS */
+ uint16_t algorithm_id;
+
+ /* The size of the digest produced by the implemented Hash algorithm */
+ uint16_t digest_size;
+} id_event_algorithm_size_t;
+
+/*
+ * TCG_EfiSpecIdEvent structure
+ * Ref. Table 15 TCG_EfiSpecIdEvent
+ * TCG PC Client Platform Firmware Profile 9.4.5.1
+ */
+typedef struct {
+ /*
+ * The NUL-terminated ASCII string "Spec ID Event03".
+ * SHALL be set to {0x53, 0x70, 0x65, 0x63, 0x20, 0x49, 0x44,
+ * 0x20, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x33, 0x00}.
+ */
+ uint8_t signature[16];
+
+ /*
+ * The value for the Platform Class.
+ * The enumeration is defined in the TCG ACPI Specification Client
+ * Common Header.
+ */
+ uint32_t platform_class;
+
+ /*
+ * The PC Client Platform Profile Specification minor version number
+ * this BIOS supports.
+ * Any BIOS supporting this version (2.0) MUST set this value to 0x00.
+ */
+ uint8_t spec_version_minor;
+
+ /*
+ * The PC Client Platform Profile Specification major version number
+ * this BIOS supports.
+ * Any BIOS supporting this version (2.0) MUST set this value to 0x02.
+ */
+ uint8_t spec_version_major;
+
+ /*
+ * The PC Client Platform Profile Specification errata version number
+ * this BIOS supports.
+ * Any BIOS supporting this version (2.0) MUST set this value to 0x02.
+ */
+ uint8_t spec_errata;
+
+ /*
+ * Specifies the size of the UINTN fields used in various data
+ * structures used in this specification.
+ * 0x01 indicates UINT32 and 0x02 indicates UINT64.
+ */
+ uint8_t uintn_size;
+
+ /*
+ * The number of Hash algorithms in the digestSizes field.
+ * This field MUST be set to a value of 0x01 or greater.
+ */
+ uint32_t number_of_algorithms;
+
+ /*
+ * Each TCG_EfiSpecIdEventAlgorithmSize SHALL contain an algorithmId
+ * and digestSize for each hash algorithm used in the TCG_PCR_EVENT2
+ * structure, the first of which is a Hash algorithmID and the second
+ * is the size of the respective digest.
+ */
+ id_event_algorithm_size_t digest_size[]; /* number_of_algorithms */
+} id_event_struct_header_t;
+
+typedef struct {
+ /*
+ * Size in bytes of the VendorInfo field.
+ * Maximum value MUST be FFh bytes.
+ */
+ uint8_t vendor_info_size;
+
+ /*
+ * Provided for use by Platform Firmware implementer. The value might
+ * be used, for example, to provide more detailed information about the
+ * specific BIOS such as BIOS revision numbers, etc. The values within
+ * this field are not standardized and are implementer-specific.
+ * Platform-specific or -unique information MUST NOT be provided in
+ * this field.
+ *
+ */
+ uint8_t vendor_info[]; /* [vendorInfoSize] */
+} id_event_struct_data_t;
+
+typedef struct {
+ id_event_struct_header_t struct_header;
+ id_event_struct_data_t struct_data;
+} id_event_struct_t;
+
+typedef struct {
+ tcg_pcr_event_t header;
+ id_event_struct_header_t struct_header;
+} id_event_headers_t;
+
+/* TPMT_HA Structure */
+typedef struct {
+ /* Selector of the hash contained in the digest that implies
+ * the size of the digest
+ */
+ uint16_t algorithm_id; /* AlgorithmId */
+
+ /* Digest, depends on AlgorithmId */
+ uint8_t digest[]; /* Digest[] */
+} tpmt_ha;
+
+/*
+ * TPML_DIGEST_VALUES Structure
+ */
+typedef struct {
+ /* The number of digests in the list */
+ uint32_t count; /* Count */
+
+ /* The list of tagged digests, as sent to the TPM as part of a
+ * TPM2_PCR_Extend or as received from a TPM2_PCR_Event command
+ */
+ tpmt_ha digests[]; /* Digests[Count] */
+} tpml_digest_values;
+
+/*
+ * TCG_PCR_EVENT2 header
+ */
+typedef struct {
+ /* The PCR Index to which this event was extended */
+ uint32_t pcr_index; /* PCRIndex */
+
+ /* Type of event */
+ uint32_t event_type; /* EventType */
+
+ /* Digests:
+ * A counted list of tagged digests, which contain the digest of
+ * the event data (or external data) for all active PCR banks
+ */
+ tpml_digest_values digests; /* Digests */
+} event2_header_t;
+
+typedef struct event2_data {
+ /* The size of the event data */
+ uint32_t event_size; /* EventSize */
+
+ /* The data of the event */
+ uint8_t event[]; /* Event[EventSize] */
+} event2_data_t;
+
+/*
+ * Startup Locality Event
+ * Ref. TCG PC Client Platform Firmware Profile 9.4.5.3
+ */
+typedef struct {
+ /*
+ * The NUL-terminated ASCII string "StartupLocality" SHALL be
+ * set to {0x53 0x74 0x61 0x72 0x74 0x75 0x70 0x4C 0x6F 0x63
+ * 0x61 0x6C 0x69 0x74 0x79 0x00}
+ */
+ uint8_t signature[16];
+
+ /* The Locality Indicator which sent the TPM2_Startup command */
+ uint8_t startup_locality;
+} startup_locality_event_t;
+
+#pragma pack(pop)
+
+#endif /* TCG_H */
diff --git a/include/lib/transfer_list.h b/include/lib/transfer_list.h
index f1e4181..eee2b82 100644
--- a/include/lib/transfer_list.h
+++ b/include/lib/transfer_list.h
@@ -48,6 +48,7 @@
TL_TAG_HOB_BLOCK = 2,
TL_TAG_HOB_LIST = 3,
TL_TAG_ACPI_TABLE_AGGREGATE = 4,
+ TL_TAG_TPM_EVLOG = 5,
};
enum transfer_list_ops {
@@ -91,6 +92,10 @@
*/
};
+struct transfer_list_entry *
+transfer_list_next(struct transfer_list_header *tl,
+ struct transfer_list_entry *last);
+
bool transfer_list_verify_checksum(const struct transfer_list_header *tl);
void *transfer_list_entry_data(struct transfer_list_entry *entry);
diff --git a/include/lib/utils_def.h b/include/lib/utils_def.h
index 0013d19..0128277 100644
--- a/include/lib/utils_def.h
+++ b/include/lib/utils_def.h
@@ -184,4 +184,44 @@
#define CONCAT(x, y) x##y
#define CONC(x, y) CONCAT(x, y)
+/* add operation together with checking whether the operation overflowed
+ * The result is '*res',
+ * return 0 on success and 1 on overflow
+ */
+#define add_overflow(a, b, res) __builtin_add_overflow((a), (b), (res))
+
+/*
+ * Round up a value to align with a given size and
+ * check whether overflow happens.
+ * The rounduped value is '*res',
+ * return 0 on success and 1 on overflow
+ */
+#define round_up_overflow(v, size, res) \
+ (__extension__({ \
+ typeof(res) __res = res; \
+ typeof(*(__res)) __roundup_tmp = 0; \
+ typeof(v) __roundup_mask = (typeof(v))(size) - 1; \
+ \
+ add_overflow((v), __roundup_mask, &__roundup_tmp) ? \
+ 1 : \
+ (void)(*(__res) = __roundup_tmp & ~__roundup_mask), \
+ 0; \
+ }))
+
+/*
+ * Add a with b, then round up the result to align with a given size and
+ * check whether overflow happens.
+ * The rounduped value is '*res',
+ * return 0 on success and 1 on overflow
+ */
+#define add_with_round_up_overflow(a, b, size, res) \
+ (__extension__({ \
+ typeof(a) __a = (a); \
+ typeof(__a) __add_res = 0; \
+ \
+ add_overflow((__a), (b), &__add_res) ? 1 : \
+ round_up_overflow(__add_res, (size), (res)) ? 1 : \
+ 0; \
+ }))
+
#endif /* UTILS_DEF_H */
diff --git a/include/runtime_services/cactus_message_loop.h b/include/runtime_services/cactus_message_loop.h
index 4d963ac..a13f42f 100644
--- a/include/runtime_services/cactus_message_loop.h
+++ b/include/runtime_services/cactus_message_loop.h
@@ -42,3 +42,5 @@
bool cactus_handle_cmd(struct ffa_value *cmd_args, struct ffa_value *ret,
struct mailbox_buffers *mb);
+
+struct ffa_value cactus_handle_framework_msg(struct ffa_value args);
diff --git a/include/runtime_services/ffa_helpers.h b/include/runtime_services/ffa_helpers.h
index 0a63e96..67fd393 100644
--- a/include/runtime_services/ffa_helpers.h
+++ b/include/runtime_services/ffa_helpers.h
@@ -349,6 +349,33 @@
return (args.arg2 >> 48) & 0xFFFFU;
}
+/**
+ * FF-A Framework message helpers
+ */
+#define FFA_FRAMEWORK_MSG_BIT (1U << 31)
+
+#define FFA_FRAMEWORK_MSG_MASK 0xFFU
+
+#define FFA_FRAMEWORK_MSG_PSCI_REQ 0U
+#define FFA_FRAMEWORK_MSG_PSCI_RESP 2U
+
+static inline uint32_t ffa_framework_msg_flags(struct ffa_value args)
+{
+ return (uint32_t)args.arg2;
+}
+
+static inline bool ffa_is_framework_msg(struct ffa_value args)
+{
+ return (ffa_func_id(args) == FFA_MSG_SEND_DIRECT_REQ_SMC32 ||
+ ffa_func_id(args) == FFA_MSG_SEND_DIRECT_REQ_SMC64) &&
+ ((ffa_framework_msg_flags(args) & FFA_FRAMEWORK_MSG_BIT) != 0);
+}
+
+static inline uint32_t ffa_get_framework_msg(struct ffa_value args)
+{
+ return ffa_framework_msg_flags(args) & FFA_FRAMEWORK_MSG_MASK;
+}
+
typedef uint64_t ffa_notification_bitmap_t;
/**
@@ -933,7 +960,12 @@
uint32_t arg1, uint32_t arg2,
uint32_t arg3, uint32_t arg4);
+struct ffa_value ffa_framework_msg_send_direct_resp(ffa_id_t source_id,
+ ffa_id_t dest_id, uint32_t msg,
+ uint32_t status_code);
+
struct ffa_value ffa_run(uint32_t dest_id, uint32_t vcpu_id);
+struct ffa_value ffa_yield(void);
struct ffa_value ffa_version(uint32_t input_version);
struct ffa_value ffa_id_get(void);
struct ffa_value ffa_spm_id_get(void);
diff --git a/include/runtime_services/ffa_svc.h b/include/runtime_services/ffa_svc.h
index ddf4559..4c82507 100644
--- a/include/runtime_services/ffa_svc.h
+++ b/include/runtime_services/ffa_svc.h
@@ -15,18 +15,22 @@
* FFA error codes.
* Don't forget to update `ffa_error_name` if you add a new one.
*/
-#define FFA_ERROR_NOT_SUPPORTED -1
-#define FFA_ERROR_INVALID_PARAMETER -2
-#define FFA_ERROR_NO_MEMORY -3
-#define FFA_ERROR_BUSY -4
-#define FFA_ERROR_INTERRUPTED -5
-#define FFA_ERROR_DENIED -6
-#define FFA_ERROR_RETRY -7
-#define FFA_ERROR_ABORTED -8
-#define FFA_ERROR_NO_DATA -9
+/* clang-format off */
+enum ffa_error {
+ FFA_ERROR_NOT_SUPPORTED = -1,
+ FFA_ERROR_INVALID_PARAMETER = -2,
+ FFA_ERROR_NO_MEMORY = -3,
+ FFA_ERROR_BUSY = -4,
+ FFA_ERROR_INTERRUPTED = -5,
+ FFA_ERROR_DENIED = -6,
+ FFA_ERROR_RETRY = -7,
+ FFA_ERROR_ABORTED = -8,
+ FFA_ERROR_NO_DATA = -9,
+};
+/* clang-format on */
/* Return the name of the error code. */
-static inline const char *ffa_error_name(int32_t error)
+static inline const char *ffa_error_name(enum ffa_error error)
{
switch (error) {
case FFA_ERROR_NOT_SUPPORTED:
@@ -47,9 +51,8 @@
return "FFA_ERROR_ABORTED";
case FFA_ERROR_NO_DATA:
return "FFA_ERROR_NO_DATA";
- default:
- return "UNKNOWN";
}
+ return "UNKNOWN";
}
/* The macros below are used to identify FFA calls from the SMC function ID */
diff --git a/include/runtime_services/host_realm_managment/host_realm_rmi.h b/include/runtime_services/host_realm_managment/host_realm_rmi.h
index 771a125..4a87ede 100644
--- a/include/runtime_services/host_realm_managment/host_realm_rmi.h
+++ b/include/runtime_services/host_realm_managment/host_realm_rmi.h
@@ -583,7 +583,7 @@
#define RMI_FEATURE_REGISTER_0_MAX_NUM_AUX_PLANES_SHIFT 45UL
#define RMI_FEATURE_REGISTER_0_MAX_NUM_AUX_PLANES_WIDTH 4UL
-#define RMI_FEATURE_REGISTER_0_RTT_S2AP_INDIRECT BIT(50)
+#define RMI_FEATURE_REGISTER_0_RTT_S2AP_INDIRECT BIT(49)
/* Possible values for RmiPlaneRttFeature */
#define RMI_PLANE_RTT_AUX 0UL
diff --git a/include/runtime_services/spm_common.h b/include/runtime_services/spm_common.h
index fa755b9..33ee54e 100644
--- a/include/runtime_services/spm_common.h
+++ b/include/runtime_services/spm_common.h
@@ -106,10 +106,10 @@
bool check_spmc_execution_level(void);
-unsigned int get_ffa_feature_test_target(
- const struct ffa_features_test **test_target);
+size_t get_ffa_feature_test_target(
+ const struct ffa_features_test **test_target);
bool ffa_features_test_targets(const struct ffa_features_test *targets,
- uint32_t test_target_size);
+ size_t test_target_size);
/**
* Helper to conduct a memory retrieve. This is to be called by the receiver
diff --git a/include/runtime_services/spm_test_helpers.h b/include/runtime_services/spm_test_helpers.h
index 14b2fb5..93675ce 100644
--- a/include/runtime_services/spm_test_helpers.h
+++ b/include/runtime_services/spm_test_helpers.h
@@ -15,14 +15,16 @@
#define SKIP_TEST_IF_FFA_VERSION_LESS_THAN(major, minor) \
do { \
struct ffa_value ret = ffa_version(FFA_VERSION_COMPILED); \
- enum ffa_version version = ret.fid; \
+ enum ffa_version version; \
\
- if (version == FFA_ERROR_NOT_SUPPORTED) { \
+ if (ret.fid == FFA_ERROR_NOT_SUPPORTED) { \
tftf_testcase_printf("FFA_VERSION not supported.\n"); \
return TEST_RESULT_SKIPPED; \
} \
\
- if (!ffa_version_is_valid(version)) { \
+ version = ret.fid; \
+ \
+ if (!ffa_version_is_valid(version)) { \
tftf_testcase_printf("FFA_VERSION bad response: %x\n", \
version); \
return TEST_RESULT_FAIL; \
diff --git a/include/runtime_services/ven_el3_svc.h b/include/runtime_services/ven_el3_svc.h
index 3a61ecd..04f501e 100644
--- a/include/runtime_services/ven_el3_svc.h
+++ b/include/runtime_services/ven_el3_svc.h
@@ -19,6 +19,6 @@
#define VEN_EL3_SVC_VERSION 0x8700ff03
#define VEN_EL3_SVC_VERSION_MAJOR 1
-#define VEN_EL3_SVC_VERSION_MINOR 0
+#define VEN_EL3_SVC_VERSION_MINOR 1
#endif /* VEN_EL3_SVC_H */
diff --git a/lib/event_log/event_handoff.c b/lib/event_log/event_handoff.c
new file mode 100644
index 0000000..238ea27
--- /dev/null
+++ b/lib/event_log/event_handoff.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+
+#include <common/debug.h>
+#include <drivers/measured_boot/event_log/event_handoff.h>
+
+#include <platform_def.h>
+
+static uint8_t *get_log_ptr(struct transfer_list_entry *te, size_t offset)
+{
+ uint8_t *base_ptr = transfer_list_entry_data(te);
+
+ if (base_ptr == NULL) {
+ return NULL;
+ }
+
+ return base_ptr + offset;
+}
+
+uint8_t *transfer_list_event_log_extend(struct transfer_list_header *tl,
+ size_t req_size, size_t *free)
+{
+ struct transfer_list_entry *existing_entry;
+ struct transfer_list_entry *new_entry;
+ uint8_t *old_data;
+ size_t existing_offset;
+ size_t old_size;
+
+ if (tl == NULL || free == NULL || req_size == 0) {
+ ERROR("Invalid arguments to event log extend.\n");
+ return NULL;
+ }
+
+ existing_entry = transfer_list_find(tl, TL_TAG_TPM_EVLOG);
+ existing_offset = EVENT_LOG_RESERVED_BYTES;
+
+ if (existing_entry != NULL) {
+ existing_offset = existing_entry->data_size;
+
+ if (transfer_list_set_data_size(tl, existing_entry,
+ req_size + existing_offset)) {
+ VERBOSE("TPM event log entry resized: new space %zu bytes at offset %zu\n",
+ req_size, existing_offset);
+
+ *free = existing_entry->data_size - existing_offset;
+
+ return get_log_ptr(existing_entry, existing_offset);
+ }
+ }
+
+ /* Add new entry (resize failed or no existing entry) */
+ new_entry = transfer_list_add(tl, TL_TAG_TPM_EVLOG,
+ req_size + existing_offset, NULL);
+
+ if (new_entry == NULL) {
+ ERROR("Failed to add TPM event log entry to transfer list.\n");
+ return NULL;
+ }
+
+ VERBOSE("New TPM event log entry added at %p\n",
+ transfer_list_entry_data(new_entry));
+
+ if (existing_entry != NULL) {
+ old_data = transfer_list_entry_data(existing_entry);
+ old_size = existing_offset;
+
+ VERBOSE("Copying existing event log (%zu bytes) to new entry at %p\n",
+ old_size, transfer_list_entry_data(new_entry));
+
+ memmove(transfer_list_entry_data(new_entry), old_data,
+ old_size);
+
+ transfer_list_rem(tl, existing_entry);
+ }
+
+ *free = new_entry->data_size - existing_offset;
+
+ return get_log_ptr(new_entry, existing_offset);
+}
+
+uint8_t *transfer_list_event_log_finish(struct transfer_list_header *tl,
+ uintptr_t cursor)
+{
+ uintptr_t entry_data_base;
+ size_t final_log_size;
+ struct transfer_list_entry *entry;
+
+ entry = transfer_list_find(tl, TL_TAG_TPM_EVLOG);
+ entry_data_base = (uintptr_t)transfer_list_entry_data(entry);
+
+ if (cursor < entry_data_base ||
+ cursor >= entry_data_base + entry->data_size) {
+ ERROR("Invalid cursor: outside event log bounds.\n");
+ return NULL;
+ }
+
+ final_log_size = cursor - entry_data_base;
+
+ if (!transfer_list_set_data_size(tl, entry, final_log_size)) {
+ ERROR("Unable to resize event log TE.\n");
+ return NULL;
+ }
+
+ transfer_list_update_checksum(tl);
+
+ VERBOSE("TPM event log finalized: trimmed to %zu bytes",
+ final_log_size - EVENT_LOG_RESERVED_BYTES);
+
+ /* Ensure changes are visible to the next stage. */
+ flush_dcache_range((uintptr_t)tl, tl->size);
+
+ return get_log_ptr(entry, EVENT_LOG_RESERVED_BYTES);
+}
diff --git a/lib/event_log/event_log.c b/lib/event_log/event_log.c
new file mode 100644
index 0000000..761ff29
--- /dev/null
+++ b/lib/event_log/event_log.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 2020-2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include "crypto_mod.h"
+#include "event_log.h"
+
+#if TPM_ALG_ID == TPM_ALG_SHA512
+#define CRYPTO_MD_ID CRYPTO_MD_SHA512
+#elif TPM_ALG_ID == TPM_ALG_SHA384
+#define CRYPTO_MD_ID CRYPTO_MD_SHA384
+#elif TPM_ALG_ID == TPM_ALG_SHA256
+#define CRYPTO_MD_ID CRYPTO_MD_SHA256
+#else
+# error Invalid TPM algorithm.
+#endif /* TPM_ALG_ID */
+
+/* Running Event Log Pointer */
+static uint8_t *log_ptr;
+
+/* Pointer to the first byte past end of the Event Log buffer */
+static uintptr_t log_end;
+
+/* TCG_EfiSpecIdEvent */
+static const id_event_headers_t id_event_header = {
+ .header = {
+ .pcr_index = PCR_0,
+ .event_type = EV_NO_ACTION,
+ .digest = {0},
+ .event_size = (uint32_t)(sizeof(id_event_struct_t) +
+ (sizeof(id_event_algorithm_size_t) *
+ HASH_ALG_COUNT))
+ },
+
+ .struct_header = {
+ .signature = TCG_ID_EVENT_SIGNATURE_03,
+ .platform_class = PLATFORM_CLASS_CLIENT,
+ .spec_version_minor = TCG_SPEC_VERSION_MINOR_TPM2,
+ .spec_version_major = TCG_SPEC_VERSION_MAJOR_TPM2,
+ .spec_errata = TCG_SPEC_ERRATA_TPM2,
+ .uintn_size = (uint8_t)(sizeof(unsigned int) /
+ sizeof(uint32_t)),
+ .number_of_algorithms = HASH_ALG_COUNT
+ }
+};
+
+static const event2_header_t locality_event_header = {
+ /*
+ * All EV_NO_ACTION events SHALL set
+ * TCG_PCR_EVENT2.pcrIndex = 0, unless otherwise specified
+ */
+ .pcr_index = PCR_0,
+
+ /*
+ * All EV_NO_ACTION events SHALL set
+ * TCG_PCR_EVENT2.eventType = 03h
+ */
+ .event_type = EV_NO_ACTION,
+
+ /*
+ * All EV_NO_ACTION events SHALL set TCG_PCR_EVENT2.digests to all
+ * 0x00's for each allocated Hash algorithm
+ */
+ .digests = {
+ .count = HASH_ALG_COUNT
+ }
+};
+
+int event_log_record(const uint8_t *hash, uint32_t event_type,
+ const event_log_metadata_t *metadata_ptr)
+{
+ void *ptr = log_ptr;
+ uint32_t name_len = 0U;
+
+ /* event_log_buf_init() must have been called prior to this. */
+ if (hash == NULL || metadata_ptr == NULL || log_ptr == NULL) {
+ return -EINVAL;
+ }
+
+ if (metadata_ptr->name != NULL) {
+ name_len = (uint32_t)strlen(metadata_ptr->name) + 1U;
+ }
+
+ /* Check for space in Event Log buffer */
+ if (((uintptr_t)ptr + (uint32_t)EVENT2_HDR_SIZE + name_len) > log_end) {
+ return -ENOMEM;
+ }
+
+ /*
+ * As per TCG specifications, firmware components that are measured
+ * into PCR[0] must be logged in the event log using the event type
+ * EV_POST_CODE.
+ */
+ /* TCG_PCR_EVENT2.PCRIndex */
+ ((event2_header_t *)ptr)->pcr_index = metadata_ptr->pcr;
+
+ /* TCG_PCR_EVENT2.EventType */
+ ((event2_header_t *)ptr)->event_type = event_type;
+
+ /* TCG_PCR_EVENT2.Digests.Count */
+ ptr = (uint8_t *)ptr + offsetof(event2_header_t, digests);
+ ((tpml_digest_values *)ptr)->count = HASH_ALG_COUNT;
+
+ /* TCG_PCR_EVENT2.Digests[] */
+ ptr = (uint8_t *)((uintptr_t)ptr +
+ offsetof(tpml_digest_values, digests));
+
+ /* TCG_PCR_EVENT2.Digests[].AlgorithmId */
+ ((tpmt_ha *)ptr)->algorithm_id = TPM_ALG_ID;
+
+ /* TCG_PCR_EVENT2.Digests[].Digest[] */
+ ptr = (uint8_t *)((uintptr_t)ptr + offsetof(tpmt_ha, digest));
+
+ /* Copy digest */
+ (void)memcpy(ptr, (const void *)hash, TCG_DIGEST_SIZE);
+
+ /* TCG_PCR_EVENT2.EventSize */
+ ptr = (uint8_t *)((uintptr_t)ptr + TCG_DIGEST_SIZE);
+ ((event2_data_t *)ptr)->event_size = name_len;
+
+ /* Copy event data to TCG_PCR_EVENT2.Event */
+ if (metadata_ptr->name != NULL) {
+ (void)memcpy((void *)(((event2_data_t *)ptr)->event),
+ (const void *)metadata_ptr->name, name_len);
+ }
+
+ /* End of event data */
+ log_ptr = (uint8_t *)((uintptr_t)ptr +
+ offsetof(event2_data_t, event) + name_len);
+
+ return 0;
+}
+
+int event_log_buf_init(uint8_t *event_log_start, uint8_t *event_log_finish)
+{
+ if (event_log_start == NULL || event_log_finish == NULL ||
+ event_log_start > event_log_finish) {
+ return -EINVAL;
+ }
+
+ log_ptr = event_log_start;
+ log_end = (uintptr_t)event_log_finish;
+
+ return 0;
+}
+
+int event_log_init(uint8_t *event_log_start, uint8_t *event_log_finish)
+{
+ return event_log_buf_init(event_log_start, event_log_finish);
+}
+
+int event_log_write_specid_event(void)
+{
+ void *ptr;
+
+ /* event_log_buf_init() must have been called prior to this. */
+ if (log_ptr == NULL) {
+ return -EFAULT;
+ }
+
+ if (((uintptr_t)log_ptr + ID_EVENT_SIZE) > log_end) {
+ return -ENOMEM;
+ }
+
+ ptr = log_ptr;
+
+ /*
+ * Add Specification ID Event first
+ *
+ * Copy TCG_EfiSpecIDEventStruct structure header
+ */
+ (void)memcpy(ptr, (const void *)&id_event_header,
+ sizeof(id_event_header));
+ ptr = (uint8_t *)((uintptr_t)ptr + sizeof(id_event_header));
+
+ /* TCG_EfiSpecIdEventAlgorithmSize structure */
+ ((id_event_algorithm_size_t *)ptr)->algorithm_id = TPM_ALG_ID;
+ ((id_event_algorithm_size_t *)ptr)->digest_size = TCG_DIGEST_SIZE;
+ ptr = (uint8_t *)((uintptr_t)ptr + sizeof(id_event_algorithm_size_t));
+
+ /*
+ * TCG_EfiSpecIDEventStruct.vendorInfoSize
+ * No vendor data
+ */
+ ((id_event_struct_data_t *)ptr)->vendor_info_size = 0;
+ log_ptr = (uint8_t *)((uintptr_t)ptr +
+ offsetof(id_event_struct_data_t, vendor_info));
+
+ return 0;
+}
+
+int event_log_write_header(void)
+{
+ const char locality_signature[] = TCG_STARTUP_LOCALITY_SIGNATURE;
+ void *ptr;
+ int rc;
+
+ rc = event_log_write_specid_event();
+ if (rc < 0) {
+ return rc;
+ }
+
+ if (((uintptr_t)log_ptr + LOC_EVENT_SIZE) > log_end) {
+ return -ENOMEM;
+ }
+
+ ptr = log_ptr;
+
+ /*
+ * The Startup Locality event should be placed in the log before
+ * any event which extends PCR[0].
+ *
+ * Ref. TCG PC Client Platform Firmware Profile 9.4.5.3
+ */
+
+ /* Copy Startup Locality Event Header */
+ (void)memcpy(ptr, (const void *)&locality_event_header,
+ sizeof(locality_event_header));
+ ptr = (uint8_t *)((uintptr_t)ptr + sizeof(locality_event_header));
+
+ /* TCG_PCR_EVENT2.Digests[].AlgorithmId */
+ ((tpmt_ha *)ptr)->algorithm_id = TPM_ALG_ID;
+
+ /* TCG_PCR_EVENT2.Digests[].Digest[] */
+ (void)memset(&((tpmt_ha *)ptr)->digest, 0, TCG_DIGEST_SIZE);
+ ptr = (uint8_t *)((uintptr_t)ptr +
+ offsetof(tpmt_ha, digest) + TCG_DIGEST_SIZE);
+
+ /* TCG_PCR_EVENT2.EventSize */
+ ((event2_data_t *)ptr)->event_size =
+ (uint32_t)sizeof(startup_locality_event_t);
+ ptr = (uint8_t *)((uintptr_t)ptr + offsetof(event2_data_t, event));
+
+ /* TCG_EfiStartupLocalityEvent.Signature */
+ (void)memcpy(ptr, (const void *)locality_signature,
+ sizeof(TCG_STARTUP_LOCALITY_SIGNATURE));
+
+ /*
+ * TCG_EfiStartupLocalityEvent.StartupLocality = 0:
+ * the platform's boot firmware
+ */
+ ((startup_locality_event_t *)ptr)->startup_locality = 0U;
+ log_ptr = (uint8_t *)((uintptr_t)ptr + sizeof(startup_locality_event_t));
+
+ return 0;
+}
+
+int event_log_measure(uintptr_t data_base, uint32_t data_size,
+ unsigned char hash_data[CRYPTO_MD_MAX_SIZE])
+{
+ /* Calculate hash */
+ return crypto_mod_calc_hash(CRYPTO_MD_ID,
+ (void *)data_base, data_size, hash_data);
+}
+
+int event_log_measure_and_record(uintptr_t data_base, uint32_t data_size,
+ uint32_t data_id,
+ const event_log_metadata_t *metadata_ptr)
+{
+ unsigned char hash_data[CRYPTO_MD_MAX_SIZE];
+ int rc;
+
+ if (metadata_ptr == NULL) {
+ return -EINVAL;
+ }
+
+ /* Get the metadata associated with this image. */
+ while (metadata_ptr->id != data_id) {
+ if (metadata_ptr->id == EVLOG_INVALID_ID) {
+ return -EINVAL;
+ }
+
+ metadata_ptr++;
+ }
+
+ /* Measure the payload with algorithm selected by EventLog driver */
+ rc = event_log_measure(data_base, data_size, hash_data);
+ if (rc != 0) {
+ return rc;
+ }
+
+ rc = event_log_record(hash_data, EV_POST_CODE, metadata_ptr);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
+size_t event_log_get_cur_size(uint8_t *event_log_start)
+{
+ assert(event_log_start != NULL);
+ assert(log_ptr >= event_log_start);
+
+ return (size_t)((uintptr_t)log_ptr - (uintptr_t)event_log_start);
+}
diff --git a/lib/event_log/event_log.mk b/lib/event_log/event_log.mk
new file mode 100644
index 0000000..df55c62
--- /dev/null
+++ b/lib/event_log/event_log.mk
@@ -0,0 +1,54 @@
+#
+# Copyright (c) 2020-2025, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Path to library sources
+EVENT_LOG_SRC_DIR := lib/event_log/
+
+# Default log level to dump the event log (LOG_LEVEL_INFO)
+EVENT_LOG_LEVEL ?= 40
+
+EVENT_LOG_SOURCES := ${EVENT_LOG_SRC_DIR}event_print.c
+
+INCLUDES += -Iinclude/lib/event_log \
+ -Iinclude/drivers/auth
+
+ifdef CRYPTO_SUPPORT
+# Measured Boot hash algorithm.
+# SHA-256 (or stronger) is required for all devices that are TPM 2.0 compliant.
+ifdef TPM_HASH_ALG
+ $(warning "TPM_HASH_ALG is deprecated. Please use MBOOT_EL_HASH_ALG instead.")
+ MBOOT_EL_HASH_ALG := ${TPM_HASH_ALG}
+else
+ MBOOT_EL_HASH_ALG := sha256
+endif
+
+ifeq (${MBOOT_EL_HASH_ALG}, sha512)
+ TPM_ALG_ID := TPM_ALG_SHA512
+ TCG_DIGEST_SIZE := 64U
+else ifeq (${MBOOT_EL_HASH_ALG}, sha384)
+ TPM_ALG_ID := TPM_ALG_SHA384
+ TCG_DIGEST_SIZE := 48U
+else
+ TPM_ALG_ID := TPM_ALG_SHA256
+ TCG_DIGEST_SIZE := 32U
+endif #MBOOT_EL_HASH_ALG
+
+# Set definitions for event log library.
+$(eval $(call add_define,TFTF_DEFINES,TPM_ALG_ID))
+$(eval $(call add_define,TFTF_DEFINES,EVENT_LOG_LEVEL))
+$(eval $(call add_define,TFTF_DEFINES,TCG_DIGEST_SIZE))
+
+EVENT_LOG_SOURCES := ${EVENT_LOG_SRC_DIR}event_log.c
+
+INCLUDES += -Iinclude/lib/event_log \
+ -Iinclude/drivers/auth
+
+ifeq (${TRANSFER_LIST}, 1)
+EVENT_LOG_SOURCES += ${EVENT_LOG_SRC_DIR}/event_handoff.c
+INCLUDES += -Iinclude/lib
+endif
+
+endif
diff --git a/lib/event_log/event_print.c b/lib/event_log/event_print.c
new file mode 100644
index 0000000..234a694
--- /dev/null
+++ b/lib/event_log/event_print.c
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2020-2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include "event_log.h"
+
+/**
+ * Print a TCG_EfiSpecIDEventStruct entry from the event log.
+ *
+ * This function extracts and prints a TCG_EfiSpecIDEventStruct
+ * entry from the event log for debugging or auditing purposes.
+ *
+ * @param[in,out] log_addr Pointer to the current position in the Event Log.
+ * Updated to the next entry after processing.
+ * @param[in,out] log_size Pointer to the remaining Event Log size.
+ * Updated to reflect the remaining bytes.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+static int event_log_print_id_event(uint8_t **log_addr, size_t *log_size)
+{
+ unsigned int i;
+ uint8_t info_size, *info_size_ptr;
+ void *ptr = *log_addr;
+ id_event_headers_t *event = (id_event_headers_t *)ptr;
+ id_event_algorithm_size_t *alg_ptr;
+ uint32_t event_size, number_of_algorithms;
+ size_t digest_len;
+ const uint8_t *end_ptr = (uint8_t *)((uintptr_t)*log_addr + *log_size);
+
+ if (*log_size < sizeof(id_event_headers_t)) {
+ return -EINVAL;
+ }
+
+ /* The fields of the event log header are defined to be PCRIndex of 0,
+ * EventType of EV_NO_ACTION, Digest of 20 bytes of 0, and
+ * Event content defined as TCG_EfiSpecIDEventStruct.
+ */
+ LOG_EVENT("TCG_EfiSpecIDEvent:\n");
+ LOG_EVENT(" PCRIndex : %u\n", event->header.pcr_index);
+ if (event->header.pcr_index != (uint32_t)PCR_0) {
+ return -EINVAL;
+ }
+
+ LOG_EVENT(" EventType : %u\n", event->header.event_type);
+ if (event->header.event_type != EV_NO_ACTION) {
+ return -EINVAL;
+ }
+
+ LOG_EVENT(" Digest :");
+ for (i = 0U; i < sizeof(event->header.digest); ++i) {
+ uint8_t val = event->header.digest[i];
+
+ (void)printf(" %02x", val);
+ if ((i & U(0xF)) == 0U) {
+ (void)printf("\n");
+ LOG_EVENT("\t\t :");
+ }
+ }
+
+ if ((i & U(0xF)) != 0U) {
+ (void)printf("\n");
+ }
+
+ /* EventSize */
+ event_size = event->header.event_size;
+ LOG_EVENT(" EventSize : %u\n", event_size);
+
+ LOG_EVENT(" Signature : %s\n",
+ event->struct_header.signature);
+ LOG_EVENT(" PlatformClass : %u\n",
+ event->struct_header.platform_class);
+ LOG_EVENT(" SpecVersion : %u.%u.%u\n",
+ event->struct_header.spec_version_major,
+ event->struct_header.spec_version_minor,
+ event->struct_header.spec_errata);
+ LOG_EVENT(" UintnSize : %u\n",
+ event->struct_header.uintn_size);
+
+ /* NumberOfAlgorithms */
+ number_of_algorithms = event->struct_header.number_of_algorithms;
+ LOG_EVENT(" NumberOfAlgorithms : %u\n", number_of_algorithms);
+
+ /* Address of DigestSizes[] */
+ alg_ptr = event->struct_header.digest_size;
+
+ /* Size of DigestSizes[] */
+ digest_len = number_of_algorithms * sizeof(id_event_algorithm_size_t);
+ if (digest_len > (uintptr_t)end_ptr - (uintptr_t)alg_ptr) {
+ return -EFAULT;
+ }
+
+ LOG_EVENT(" DigestSizes :\n");
+ for (i = 0U; i < number_of_algorithms; ++i) {
+ LOG_EVENT(" #%u AlgorithmId : SHA", i);
+ uint16_t algorithm_id = alg_ptr[i].algorithm_id;
+
+ switch (algorithm_id) {
+ case TPM_ALG_SHA256:
+ (void)printf("256\n");
+ break;
+ case TPM_ALG_SHA384:
+ (void)printf("384\n");
+ break;
+ case TPM_ALG_SHA512:
+ (void)printf("512\n");
+ break;
+ default:
+ (void)printf("?\n");
+ ERROR("Algorithm 0x%x not found\n", algorithm_id);
+ return -ENOENT;
+ }
+
+ LOG_EVENT(" DigestSize : %u\n",
+ alg_ptr[i].digest_size);
+ }
+
+ /* Address of VendorInfoSize */
+ info_size_ptr = (uint8_t *)((uintptr_t)alg_ptr + digest_len);
+ if ((uintptr_t)info_size_ptr > (uintptr_t)end_ptr) {
+ return -EFAULT;
+ }
+
+ info_size = *info_size_ptr++;
+ LOG_EVENT(" VendorInfoSize : %u\n", info_size);
+
+ /* Check VendorInfo end address */
+ if (((uintptr_t)info_size_ptr + info_size) > (uintptr_t)end_ptr) {
+ return -EFAULT;
+ }
+
+ /* Check EventSize */
+ if (event_size !=
+ (sizeof(id_event_struct_t) + digest_len + info_size)) {
+ return -EFAULT;
+ }
+
+ if (info_size != 0U) {
+ LOG_EVENT(" VendorInfo :");
+ for (i = 0U; i < info_size; ++i) {
+ (void)printf(" %02x", *info_size_ptr++);
+ }
+ (void)printf("\n");
+ }
+
+ *log_size -= (uintptr_t)info_size_ptr - (uintptr_t)*log_addr;
+ *log_addr = info_size_ptr;
+
+ return 0;
+}
+
+/**
+ * Print a TCG_PCR_EVENT2 entry from the event log.
+ *
+ * This function extracts and prints a TCG_PCR_EVENT2 structure
+ * from the event log for debugging or auditing purposes.
+ *
+ * @param[in,out] log_addr Pointer to the current position in the Event Log.
+ * Updated to the next entry after processing.
+ * @param[in,out] log_size Pointer to the remaining Event Log size.
+ * Updated to reflect the remaining bytes.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+static int event_log_print_pcr_event2(uint8_t **log_addr, size_t *log_size)
+{
+ uint32_t event_size, count;
+ size_t sha_size, digests_size = 0U;
+ void *ptr = *log_addr;
+ const uint8_t *end_ptr = (uint8_t *)((uintptr_t)*log_addr + *log_size);
+
+ if (*log_size < sizeof(event2_header_t)) {
+ return -EINVAL;
+ }
+
+ LOG_EVENT("PCR_Event2:\n");
+ LOG_EVENT(" PCRIndex : %u\n",
+ ((event2_header_t *)ptr)->pcr_index);
+ LOG_EVENT(" EventType : %u\n",
+ ((event2_header_t *)ptr)->event_type);
+
+ count = ((event2_header_t *)ptr)->digests.count;
+ if (count < 1U) {
+ LOG_EVENT("Invalid Digests Count : %u\n", count);
+ return -EINVAL;
+ }
+
+ LOG_EVENT(" Digests Count : %u\n", count);
+
+ /* Address of TCG_PCR_EVENT2.Digests[] */
+ ptr = (uint8_t *)ptr + sizeof(event2_header_t);
+ if ((uintptr_t)ptr > (uintptr_t)end_ptr) {
+ return -EFAULT;
+ }
+
+ for (unsigned int i = 0U; i < count; ++i) {
+ /* Check AlgorithmId address */
+ if (((uintptr_t)ptr + offsetof(tpmt_ha, digest)) >
+ (uintptr_t)end_ptr) {
+ return -EFAULT;
+ }
+
+ LOG_EVENT(" #%u AlgorithmId : SHA", i);
+ switch (((tpmt_ha *)ptr)->algorithm_id) {
+ case TPM_ALG_SHA256:
+ sha_size = SHA256_DIGEST_SIZE;
+ (void)printf("256\n");
+ break;
+ case TPM_ALG_SHA384:
+ sha_size = SHA384_DIGEST_SIZE;
+ (void)printf("384\n");
+ break;
+ case TPM_ALG_SHA512:
+ sha_size = SHA512_DIGEST_SIZE;
+ (void)printf("512\n");
+ break;
+ default:
+ (void)printf("?\n");
+ printf("Algorithm 0x%x not found\n",
+ ((tpmt_ha *)ptr)->algorithm_id);
+ return -ENOENT;
+ }
+
+ /* End of Digest[] */
+ ptr = (uint8_t *)((uintptr_t)ptr + offsetof(tpmt_ha, digest));
+ if (((uintptr_t)ptr + sha_size) > (uintptr_t)end_ptr) {
+ return -EFAULT;
+ }
+
+ /* Total size of all digests */
+ digests_size += sha_size;
+
+ LOG_EVENT(" Digest :");
+ for (unsigned int j = 0U; j < sha_size; ++j) {
+ (void)printf(" %02x", *(uint8_t *)ptr++);
+ if ((j & U(0xF)) == U(0xF)) {
+ (void)printf("\n");
+ if (j < (sha_size - 1U)) {
+ LOG_EVENT("\t\t :");
+ }
+ }
+ }
+ }
+
+ /* TCG_PCR_EVENT2.EventSize */
+ if (((uintptr_t)ptr + offsetof(event2_data_t, event)) >
+ (uintptr_t)end_ptr) {
+ return -EFAULT;
+ }
+
+ event_size = ((event2_data_t *)ptr)->event_size;
+ LOG_EVENT(" EventSize : %u\n", event_size);
+
+ /* Address of TCG_PCR_EVENT2.Event[EventSize] */
+ ptr = (uint8_t *)((uintptr_t)ptr + offsetof(event2_data_t, event));
+
+ /* End of TCG_PCR_EVENT2.Event[EventSize] */
+ if (((uintptr_t)ptr + event_size) > (uintptr_t)end_ptr) {
+ return -EFAULT;
+ }
+
+ if ((event_size == sizeof(startup_locality_event_t)) &&
+ (strcmp((const char *)ptr, TCG_STARTUP_LOCALITY_SIGNATURE) == 0)) {
+ LOG_EVENT(" Signature : %s\n",
+ ((startup_locality_event_t *)ptr)->signature);
+ LOG_EVENT(" StartupLocality : %u\n",
+ ((startup_locality_event_t *)ptr)->startup_locality);
+ } else {
+ LOG_EVENT(" Event : %s\n", (uint8_t *)ptr);
+ }
+
+ *log_size -= (uintptr_t)ptr + event_size - (uintptr_t)*log_addr;
+ *log_addr = (uint8_t *)ptr + event_size;
+
+ return 0;
+}
+
+int event_log_dump(uint8_t *log_addr, size_t log_size)
+{
+ int rc;
+
+ if (log_addr == NULL) {
+ return -EINVAL;
+ }
+
+ /* Print TCG_EfiSpecIDEvent */
+ rc = event_log_print_id_event(&log_addr, &log_size);
+
+ if (rc < 0) {
+ return rc;
+ }
+
+ while (log_size != 0U) {
+ rc = event_log_print_pcr_event2(&log_addr, &log_size);
+ if (rc < 0) {
+ return rc;
+ }
+ }
+ return 0;
+}
diff --git a/lib/power_management/suspend/aarch64/asm_tftf_suspend.S b/lib/power_management/suspend/aarch64/asm_tftf_suspend.S
index c643475..770a1bd 100644
--- a/lib/power_management/suspend/aarch64/asm_tftf_suspend.S
+++ b/lib/power_management/suspend/aarch64/asm_tftf_suspend.S
@@ -130,6 +130,9 @@
msr ttbr0_el2, x3
msr tcr_el2, x4
msr vbar_el2, x5
+
+ /* make sure whatever just got turned on is in effect */
+ isb
/*
* Check if the processor supports SME
*/
diff --git a/lib/transfer_list/transfer_list.c b/lib/transfer_list/transfer_list.c
index c83b0b3..13ff6ff 100644
--- a/lib/transfer_list/transfer_list.c
+++ b/lib/transfer_list/transfer_list.c
@@ -8,13 +8,63 @@
#include <transfer_list.h>
+/*******************************************************************************
+ * Search for an existing transfer entry with the specified tag id from a
+ * transfer list
+ * Return pointer to the found transfer entry or NULL on error
+ ******************************************************************************/
struct transfer_list_entry *transfer_list_find(struct transfer_list_header *tl,
uint16_t tag_id)
{
- struct transfer_list_entry *te = (void *)tl + tl->hdr_size;
+ struct transfer_list_entry *te = NULL;
- while (te->tag_id != tag_id) {
- te += round_up(te->hdr_size + te->data_size, tl->alignment);
+ do {
+ te = transfer_list_next(tl, te);
+ } while (te && (te->tag_id != tag_id));
+
+ return te;
+}
+
+/*******************************************************************************
+ * Enumerate the next transfer entry
+ * Return pointer to the next transfer entry or NULL on error
+ ******************************************************************************/
+struct transfer_list_entry *transfer_list_next(struct transfer_list_header *tl,
+ struct transfer_list_entry *last)
+{
+ struct transfer_list_entry *te = NULL;
+ uintptr_t tl_ev = 0;
+ uintptr_t va = 0;
+ uintptr_t ev = 0;
+ size_t sz = 0;
+
+ if (!tl) {
+ return NULL;
+ }
+
+ tl_ev = (uintptr_t)tl + tl->size;
+
+ if (last) {
+ va = (uintptr_t)last;
+ /* check if the total size overflow */
+ if (add_overflow(last->hdr_size, last->data_size, &sz)) {
+ return NULL;
+ }
+ /* roundup to the next entry */
+ if (add_with_round_up_overflow(va, sz, TRANSFER_LIST_GRANULE,
+ &va)) {
+ return NULL;
+ }
+ } else {
+ va = (uintptr_t)tl + tl->hdr_size;
+ }
+
+ te = (struct transfer_list_entry *)va;
+
+ if (va + sizeof(*te) > tl_ev || te->hdr_size < sizeof(*te) ||
+ add_overflow(te->hdr_size, te->data_size, &sz) ||
+ add_overflow(va, sz, &ev) || ev > tl_ev) {
+ return NULL;
}
return te;
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 3a7f8bf..337c6a6 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -59,3 +59,10 @@
# This flag is required to match the feature set of Cactus SP that are
# implemented in TF-A EL3 SPMC.
SPMC_AT_EL3 := 0
+
+# If a Cactus SP subscribes to receiving power management framework message
+# through its partition manifest, this flag controls whether the SP supports
+# handling the aforementioned message. This option can take either 0
+# (unsupported) or 1 (supported). Default value is 1. Note that a value of 0 is
+# particularly useful in stress testing of power management handling by the SPMC.
+CACTUS_PWR_MGMT_SUPPORT := 1
diff --git a/plat/amd/versal2/include/platform_def.h b/plat/amd/versal2/include/platform_def.h
index 61392a7..89a8cde 100644
--- a/plat/amd/versal2/include/platform_def.h
+++ b/plat/amd/versal2/include/platform_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2024-2025, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -12,7 +12,7 @@
#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
#define PLATFORM_LINKER_ARCH aarch64
-#define TFTF_BASE U(0x8000000)
+#define TFTF_BASE U(0x40000000)
#define CACHE_WRITEBACK_GRANULE U(0x40)
@@ -77,13 +77,14 @@
/* ARM PL011 UART */
#define PL011_UART0_BASE U(0xf1920000)
+#define PL011_UART1_BASE U(0xf1930000)
#define PL011_BAUDRATE U(115200)
#define PL011_UART_CLK_IN_HZ U(100000000)
-#define PLAT_ARM_UART_BASE PL011_UART0_BASE
+#define PLAT_ARM_UART_BASE PL011_UART1_BASE
#define PLAT_ARM_UART_SIZE U(0x1000)
-#define CRASH_CONSOLE_BASE PL011_UART0_BASE
+#define CRASH_CONSOLE_BASE PL011_UART1_BASE
#define CRASH_CONSOLE_SIZE PLAT_ARM_UART_SIZE
/*******************************************************************************
diff --git a/plat/amd/versal2/tests_to_skip.txt b/plat/amd/versal2/tests_to_skip.txt
index 2c286ec..3179879 100644
--- a/plat/amd/versal2/tests_to_skip.txt
+++ b/plat/amd/versal2/tests_to_skip.txt
@@ -33,6 +33,7 @@
SIMD,SVE Registers context/Check that SIMD registers context is preserved
FF-A Interrupt
FF-A Notifications
+FF-A Group0 interrupts/FF-A Group0 normal world
#TESTS: AMD-Xilinx tests
AMD-Xilinx tests
@@ -47,10 +48,12 @@
PSCI CPU Suspend/CPU suspend to standby at level 2
PSCI CPU Suspend in OSI mode/CPU suspend to powerdown at level 0 in OSI mode
PSCI CPU Suspend in OSI mode/CPU suspend to powerdown at level 1 in OSI mode
+CPU Hotplug/Invalid entry point
PSCI System Suspend Validation/System suspend multiple times
PSCI System Suspend Validation/system suspend from all cores
PSCI System Suspend Validation/Validate suspend to RAM functionality
PSCI System Suspend Validation/Validate PSCI System Suspend API
+PSCI System Suspend Validation/Suspend system with cores in suspend
#PSCI
PSCI Features
diff --git a/plat/arm/neoverse_rd/common/include/nrd1/nrd_css_def1.h b/plat/arm/neoverse_rd/common/include/nrd1/nrd_css_def1.h
deleted file mode 100644
index 2668c62..0000000
--- a/plat/arm/neoverse_rd/common/include/nrd1/nrd_css_def1.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- * This file is limited to include the CSS specific memory and interrupt map
- * definitions for the first generation platforms based on the A75, N1 and V1
- * CPUs. There are minor differences in the memory map of these platforms and
- * those differences are not in the scope of this file.
- */
-
-#ifndef NRD_CSS_DEF1_H
-#define NRD_CSS_DEF1_H
-
-/*******************************************************************************
- * CSS memory map related defines
- ******************************************************************************/
-
-/* Sub-system Peripherals */
-#define NRD_CSS_PERIPH0_BASE UL(0x2A000000)
-#define NRD_CSS_PERIPH0_SIZE UL(0x26000000)
-
-/* Peripherals and PCIe expansion area */
-#define NRD_CSS_PERIPH1_BASE UL(0x60000000)
-#define NRD_CSS_PERIPH1_SIZE UL(0x20000000)
-
-/* DRAM base address and size */
-#define NRD_CSS_DRAM1_BASE UL(0x80000000)
-#define NRD_CSS_DRAM1_SIZE UL(0x80000000)
-
-/* AP Non-Secure UART related constants */
-#define NRD_CSS_NSEC_UART_BASE UL(0x2A400000)
-
-/* Base address of trusted watchdog */
-#define NRD_CSS_TWDOG_BASE UL(0x2A480000)
-
-/* Base address of non-trusted watchdog */
-#define NRD_CSS_WDOG_BASE UL(0x1C0F0000)
-
-/* Memory mapped Generic timer interfaces */
-#define NRD_CSS_NSEC_CNT_BASE1 UL(0x2A830000)
-
-#endif /* NRD_CSS_DEF1_H */
\ No newline at end of file
diff --git a/plat/arm/neoverse_rd/common/include/nrd1/nrd_css_fw_def1.h b/plat/arm/neoverse_rd/common/include/nrd1/nrd_css_fw_def1.h
deleted file mode 100644
index 55356e6..0000000
--- a/plat/arm/neoverse_rd/common/include/nrd1/nrd_css_fw_def1.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- * This file is limited to include the CSS firmware specific definitions for
- * the first generation platforms based on the A75, N1 and V1 CPUs.
- */
-
-#ifndef NRD1_CSS_FW_DEF1_H
-#define NRD1_CSS_FW_DEF1_H
-
-#include "nrd_css_def1.h"
-
-/*******************************************************************************
- * Console config
- ******************************************************************************/
-
-#define NRD_CSS_NSEC_CLK_IN_HZ UL(7372800)
-
-#endif /* NRD_CSS_FW_DEF1_H */
\ No newline at end of file
diff --git a/plat/arm/neoverse_rd/common/include/nrd1/nrd_plat_arm_def1.h b/plat/arm/neoverse_rd/common/include/nrd1/nrd_plat_arm_def1.h
deleted file mode 100644
index 6a5085f..0000000
--- a/plat/arm/neoverse_rd/common/include/nrd1/nrd_plat_arm_def1.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- * This file is limited to include the platform port definitions for the
- * first generation platforms based on the A75, N1 and V1 CPUs.
- */
-
-#ifndef NRD_PLAT_ARM_DEF1_H
-#define NRD_PLAT_ARM_DEF1_H
-
-#ifndef __ASSEMBLER__
-#include <lib/mmio.h>
-#endif /* __ASSEMBLER__ */
-
-#include <lib/utils_def.h>
-#include "nrd_css_fw_def1.h"
-#include "nrd_ros_def1.h"
-
-/*******************************************************************************
- * Linker related definitions
- ******************************************************************************/
-
-/* Platform binary types for linking */
-#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
-#define PLATFORM_LINKER_ARCH aarch64
-
-/*******************************************************************************
- * Stack size
- ******************************************************************************/
-
-/* Size of cacheable stacks */
-#define PLATFORM_STACK_SIZE U(0x1400) /* 5120 bytes */
-
-/* Size of coherent stacks */
-#define PCPU_DV_MEM_STACK_SIZE U(0x600) /* 1536 bytes */
-
-/*******************************************************************************
- * Core count
- ******************************************************************************/
-
-#define PLATFORM_CORE_COUNT (PLAT_ARM_CLUSTER_COUNT * \
- NRD_MAX_CPUS_PER_CLUSTER)
-#define PLATFORM_NUM_AFFS (PLAT_ARM_CLUSTER_COUNT + \
- PLATFORM_CORE_COUNT)
-
-/*******************************************************************************
- * Power related definitions
- ******************************************************************************/
-
-#define PLATFORM_MAX_AFFLVL MPIDR_AFFLVL1
-
-#define PLAT_MAX_PWR_LEVEL PLATFORM_MAX_AFFLVL
-#define PLAT_MAX_PWR_STATES_PER_LVL U(2)
-
-/* Local state bit width for each level in the state-ID field of power state */
-#define PLAT_LOCAL_PSTATE_WIDTH U(4)
-
-/*******************************************************************************
- * XLAT definitions
- ******************************************************************************/
-
-/* Platform specific page table and MMU setup constants */
-#define MAX_XLAT_TABLES U(6)
-#define MAX_MMAP_REGIONS U(16)
-
-/*******************************************************************************
- * I/O definitions
- ******************************************************************************/
-
-/* I/O Storage NOR flash device */
-#define MAX_IO_DEVICES U(1)
-#define MAX_IO_HANDLES U(1)
-
-/*******************************************************************************
- * Non-Secure Software Generated Interupts IDs
- ******************************************************************************/
-
-/* Non-Secure Software Generated Interupts IDs */
-#define IRQ_NS_SGI_0 U(0)
-#define IRQ_NS_SGI_7 U(7)
-
-/* Maximum SPI */
-#define PLAT_MAX_SPI_OFFSET_ID U(64)
-
-/*******************************************************************************
- * Timer related config
- ******************************************************************************/
-
-/* Per-CPU Hypervisor Timer Interrupt ID */
-#define IRQ_PCPU_HP_TIMER U(26)
-
-/* Memory mapped Generic timer interfaces */
-#define SYS_CNT_BASE1 NRD_CSS_NSEC_CNT_BASE1
-
-/* AP_REFCLK Generic Timer, Non-secure. */
-#define IRQ_CNTPSIRQ1 U(92)
-
-/* Times(in ms) used by test code for completion of different events */
-#define PLAT_SUSPEND_ENTRY_TIME U(15)
-#define PLAT_SUSPEND_ENTRY_EXIT_TIME U(30)
-
-/*******************************************************************************
- * Console config
- ******************************************************************************/
-
-#define PLAT_ARM_UART_BASE NRD_CSS_NSEC_UART_BASE
-#define PLAT_ARM_UART_CLK_IN_HZ NRD_CSS_NSEC_CLK_IN_HZ
-
-/*******************************************************************************
- * DRAM config
- ******************************************************************************/
-
-/* TF-A reserves DRAM space 0xFF000000- 0xFFFFFFFF for TZC */
-#define DRAM_BASE NRD_CSS_DRAM1_BASE
-#define DRAM_SIZE (NRD_CSS_DRAM1_SIZE - 0x1000000)
-
-/*******************************************************************************
- * Cache related config
- ******************************************************************************/
-
-#define CACHE_WRITEBACK_SHIFT U(6)
-#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
-
-/*******************************************************************************
- * Run-time address of the TFTF image.
- * It has to match the location where the Trusted Firmware-A loads the BL33
- * image.
- ******************************************************************************/
-
-#define TFTF_BASE UL(0xE0000000)
-
-/*******************************************************************************
- * TFTF NVM configs
- ******************************************************************************/
-
-#define TFTF_NVM_OFFSET U(0x0)
-#define TFTF_NVM_SIZE UL(0x08000000) /* 128 MB */
-
-/*******************************************************************************
- * Watchdog related config
- ******************************************************************************/
-
-/* Base address of trusted watchdog (SP805) */
-#define SP805_TWDOG_BASE NRD_CSS_TWDOG_BASE
-
-/* Base address of non-trusted watchdog (SP805) */
-#define SP805_WDOG_BASE NRD_CSS_WDOG_BASE
-
-/* Trusted watchdog (SP805) Interrupt ID */
-#define IRQ_TWDOG_INTID U(86)
-
-/*******************************************************************************
- * Flash related config
- ******************************************************************************/
-
-/* Base address and size of external NVM flash */
-#define FLASH_BASE NRD_ROS_FLASH_BASE
-#define FLASH_SIZE NRD_ROS_FLASH_SIZE
-#define NOR_FLASH_BLOCK_SIZE UL(0x40000) /* 256KB */
-
-#endif /* NRD_PLAT_ARM_DEF1_H */
\ No newline at end of file
diff --git a/plat/arm/neoverse_rd/common/include/nrd1/nrd_ros_def1.h b/plat/arm/neoverse_rd/common/include/nrd1/nrd_ros_def1.h
deleted file mode 100644
index 3c1764b..0000000
--- a/plat/arm/neoverse_rd/common/include/nrd1/nrd_ros_def1.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- * This file is limited to include the RoS specific definitions for the first
- * generation platforms based on the A75, N1 and V1 CPUs. RoS (Rest Of System)
- * is used to refer to the part of the reference design platform that excludes
- * CSS.
- */
-
-#ifndef NRD_ROS_DEF1_H
-#define NRD_ROS_DEF1_H
-
-/*******************************************************************************
- * ROS configs
- ******************************************************************************/
-
-/* Base address and size of external NVM flash */
-#define NRD_ROS_FLASH_BASE UL(0x08000000) /* 128MB */
-#define NRD_ROS_FLASH_SIZE UL(0x04000000) /* 64MB */
-
-#endif /* NRD_ROS_DEF1_H */
\ No newline at end of file
diff --git a/plat/arm/neoverse_rd/platform/rdn1edge/include/platform_def.h b/plat/arm/neoverse_rd/platform/rdn1edge/include/platform_def.h
deleted file mode 100644
index 544e7b8..0000000
--- a/plat/arm/neoverse_rd/platform/rdn1edge/include/platform_def.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2019-2024, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef PLATFORM_DEF_H
-#define PLATFORM_DEF_H
-
-#include <nrd1/nrd_plat_arm_def1.h>
-
-#define PLAT_ARM_CLUSTER_COUNT U(2)
-#define NRD_MAX_CPUS_PER_CLUSTER U(4)
-#define NRD_MAX_PE_PER_CPU U(1)
-
-/* GIC related constants */
-#define PLAT_ARM_GICD_BASE UL(0x30000000)
-#define PLAT_ARM_GICC_BASE UL(0x2C000000)
-#define PLAT_ARM_GICR_BASE UL(0x300C0000)
-
-/* Platform specific page table and MMU setup constants */
-#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
-#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
-
-#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/neoverse_rd/platform/rdn1edge/platform.mk b/plat/arm/neoverse_rd/platform/rdn1edge/platform.mk
deleted file mode 100644
index 9f92efd..0000000
--- a/plat/arm/neoverse_rd/platform/rdn1edge/platform.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Copyright (c) 2019-2024, Arm Limited and Contributors. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-include plat/arm/neoverse_rd/common/nrd_common.mk
-
-PLAT_INCLUDES += -Iplat/arm/neoverse_rd/platform/rdn1edge/include/
-
-PLAT_SOURCES += plat/arm/neoverse_rd/platform/rdn1edge/topology.c
-
-PLAT_TESTS_SKIP_LIST := plat/arm/neoverse_rd/platform/rdn1edge/tests_to_skip.txt
-
-ifdef NRD_PLATFORM_VARIANT
-$(error "NRD_PLATFORM_VARIANT should not be set for RD-N1-Edge, \
- currently set to ${NRD_PLATFORM_VARIANT}.")
-endif
diff --git a/plat/arm/neoverse_rd/platform/rdn1edge/tests_to_skip.txt b/plat/arm/neoverse_rd/platform/rdn1edge/tests_to_skip.txt
deleted file mode 100644
index 6341809..0000000
--- a/plat/arm/neoverse_rd/platform/rdn1edge/tests_to_skip.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# Copyright (c) 2019-2024, Arm Limited and Contributors. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-# OS-initiated mode is not supported on RD-N1Edge
-PSCI CPU Suspend in OSI mode
-
-# System suspend is not supported as there are no wakeup sources in RD-N1Edge FVP
-PSCI STAT/Stats test cases after system suspend
-PSCI System Suspend Validation
diff --git a/plat/arm/neoverse_rd/platform/rdn1edge/topology.c b/plat/arm/neoverse_rd/platform/rdn1edge/topology.c
deleted file mode 100644
index cb79ba6..0000000
--- a/plat/arm/neoverse_rd/platform/rdn1edge/topology.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2019-2024, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <assert.h>
-#include <plat_topology.h>
-#include <tftf_lib.h>
-
-static const struct {
- unsigned int cluster_id;
- unsigned int cpu_id;
-} plat_cores[] = {
- /* Cluster0: 4 cores*/
- { 0, 0 },
- { 0, 1 },
- { 0, 2 },
- { 0, 3 },
- /* Cluster1: 4 cores */
- { 1, 0 },
- { 1, 1 },
- { 1, 2 },
- { 1, 3 },
-};
-
-/*
- * The power domain tree descriptor. The cluster power domains are
- * arranged so that when the PSCI generic code creates the power domain tree,
- * the indices of the CPU power domain nodes it allocates match the linear
- * indices returned by plat_core_pos_by_mpidr().
- */
-const unsigned char plat_pd_tree_desc[] = {
- /* Number of root nodes */
- PLAT_ARM_CLUSTER_COUNT,
- /* Number of children for the 1st node */
- NRD_MAX_CPUS_PER_CLUSTER,
- /* Number of children for the 2nd node */
- NRD_MAX_CPUS_PER_CLUSTER
-};
-
-const unsigned char *tftf_plat_get_pwr_domain_tree_desc(void)
-{
- return plat_pd_tree_desc;
-}
-
-uint64_t tftf_plat_get_mpidr(unsigned int core_pos)
-{
- unsigned int mpid;
-
- assert(core_pos < PLATFORM_CORE_COUNT);
-
- mpid = make_mpid(
- plat_cores[core_pos].cluster_id,
- plat_cores[core_pos].cpu_id);
-
- return mpid;
-}
diff --git a/plat/arm/neoverse_rd/platform/rdv1/include/platform_def.h b/plat/arm/neoverse_rd/platform/rdv1/include/platform_def.h
deleted file mode 100644
index de94ac9..0000000
--- a/plat/arm/neoverse_rd/platform/rdv1/include/platform_def.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2022-2024, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef PLATFORM_DEF_H
-#define PLATFORM_DEF_H
-
-#include <nrd1/nrd_plat_arm_def1.h>
-
-#define PLAT_ARM_CLUSTER_COUNT U(16)
-#define NRD_MAX_CPUS_PER_CLUSTER U(1)
-#define NRD_MAX_PE_PER_CPU U(1)
-
-/* GIC related constants */
-#define PLAT_ARM_GICD_BASE UL(0x30000000)
-#define PLAT_ARM_GICR_BASE UL(0x30140000)
-#define PLAT_ARM_GICC_BASE UL(0x2C000000)
-
-/* Platform specific page table and MMU setup constants */
-#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 42)
-#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 42)
-
-#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/neoverse_rd/platform/rdv1/platform.mk b/plat/arm/neoverse_rd/platform/rdv1/platform.mk
deleted file mode 100644
index cfb8543..0000000
--- a/plat/arm/neoverse_rd/platform/rdv1/platform.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Copyright (c) 2022-2024, Arm Limited and Contributors. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-include plat/arm/neoverse_rd/common/nrd_common.mk
-
-PLAT_INCLUDES += -Iplat/arm/neoverse_rd/platform/rdv1/include/
-
-PLAT_SOURCES += plat/arm/neoverse_rd/platform/rdv1/topology.c
-
-PLAT_TESTS_SKIP_LIST := plat/arm/neoverse_rd/platform/rdv1/tests_to_skip.txt
-
-ifdef NRD_PLATFORM_VARIANT
-$(error "NRD_PLATFORM_VARIANT should not be set for RD-V1, \
- currently set to ${NRD_PLATFORM_VARIANT}.")
-endif
diff --git a/plat/arm/neoverse_rd/platform/rdv1/tests_to_skip.txt b/plat/arm/neoverse_rd/platform/rdv1/tests_to_skip.txt
deleted file mode 100644
index d62b9dd..0000000
--- a/plat/arm/neoverse_rd/platform/rdv1/tests_to_skip.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# Copyright (c) 2022-2024, Arm Limited and Contributors. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-# OS-initiated mode is not supported on RD-V1
-PSCI CPU Suspend in OSI mode
-
-# System suspend is not supported as there are no wakeup sources in RD-V1 FVP
-PSCI STAT/Stats test cases after system suspend
-PSCI System Suspend Validation
-
-# The following tests hang during the test execution
-Timer framework Validation/Stress test the timer framework
-PSCI Affinity Info/Affinity info level0 powerdown
-PSCI CPU Suspend/CPU suspend to powerdown at level 0
-PSCI CPU Suspend/CPU suspend to powerdown at level 1
-
-# The following tests are not supported on RD-V1
-CPU extensions/Use trace buffer control Registers
-CPU extensions/Use trace filter control Registers
diff --git a/plat/arm/neoverse_rd/platform/rdv1/topology.c b/plat/arm/neoverse_rd/platform/rdv1/topology.c
deleted file mode 100644
index 882bffb..0000000
--- a/plat/arm/neoverse_rd/platform/rdv1/topology.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2022-2024, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <assert.h>
-#include <plat_topology.h>
-#include <tftf_lib.h>
-
-static const struct {
- unsigned int cluster_id;
- unsigned int cpu_id;
-} plat_cores[] = {
- /* Cluster0: 1 core */
- { 0, 0 },
- /* Cluster1: 1 core */
- { 1, 0 },
- /* Cluster2: 1 core */
- { 2, 0 },
- /* Cluster3: 1 core */
- { 3, 0 },
- /* Cluster4: 1 core */
- { 4, 0 },
- /* Cluster5: 1 core */
- { 5, 0 },
- /* Cluster6: 1 core */
- { 6, 0 },
- /* Cluster7: 1 core */
- { 7, 0 },
- /* Cluster8: 1 core */
- { 8, 0 },
- /* Cluster9: 1 core */
- { 9, 0 },
- /* Cluster10: 1 core */
- { 10, 0 },
- /* Cluster11: 1 core */
- { 11, 0 },
- /* Cluster12: 1 core */
- { 12, 0 },
- /* Cluster13: 1 core */
- { 13, 0 },
- /* Cluster14: 1 core */
- { 14, 0 },
- /* Cluster15: 1 core */
- { 15, 0 },
-};
-
-/*
- * The power domain tree descriptor. The cluster power domains are
- * arranged so that when the PSCI generic code creates the power domain tree,
- * the indices of the CPU power domain nodes it allocates match the linear
- * indices returned by plat_core_pos_by_mpidr().
- */
-const unsigned char plat_pd_tree_desc[] = {
- /* Number of root nodes */
- PLAT_ARM_CLUSTER_COUNT,
- /* Number of children for the 1st node */
- NRD_MAX_CPUS_PER_CLUSTER,
- /* Number of children for the 2nd node */
- NRD_MAX_CPUS_PER_CLUSTER,
- /* Number of children for the 3rd node */
- NRD_MAX_CPUS_PER_CLUSTER,
- /* Number of children for the 4th node */
- NRD_MAX_CPUS_PER_CLUSTER,
- /* Number of children for the 5th node */
- NRD_MAX_CPUS_PER_CLUSTER,
- /* Number of children for the 6th node */
- NRD_MAX_CPUS_PER_CLUSTER,
- /* Number of children for the 7th node */
- NRD_MAX_CPUS_PER_CLUSTER,
- /* Number of children for the 8th node */
- NRD_MAX_CPUS_PER_CLUSTER,
- /* Number of children for the 9th node */
- NRD_MAX_CPUS_PER_CLUSTER,
- /* Number of children for the 10th node */
- NRD_MAX_CPUS_PER_CLUSTER,
- /* Number of children for the 11th node */
- NRD_MAX_CPUS_PER_CLUSTER,
- /* Number of children for the 12th node */
- NRD_MAX_CPUS_PER_CLUSTER,
- /* Number of children for the 13th node */
- NRD_MAX_CPUS_PER_CLUSTER,
- /* Number of children for the 14th node */
- NRD_MAX_CPUS_PER_CLUSTER,
- /* Number of children for the 15th node */
- NRD_MAX_CPUS_PER_CLUSTER,
- /* Number of children for the 16th node */
- NRD_MAX_CPUS_PER_CLUSTER
-};
-
-const unsigned char *tftf_plat_get_pwr_domain_tree_desc(void)
-{
- return plat_pd_tree_desc;
-}
-
-uint64_t tftf_plat_get_mpidr(unsigned int core_pos)
-{
- unsigned int mpid;
-
- assert(core_pos < PLATFORM_CORE_COUNT);
-
- mpid = make_mpid(plat_cores[core_pos].cluster_id,
- plat_cores[core_pos].cpu_id);
-
- return (uint64_t)mpid;
-}
diff --git a/plat/arm/neoverse_rd/platform/sgi575/include/platform_def.h b/plat/arm/neoverse_rd/platform/sgi575/include/platform_def.h
deleted file mode 100644
index e8a4606..0000000
--- a/plat/arm/neoverse_rd/platform/sgi575/include/platform_def.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef PLATFORM_DEF_H
-#define PLATFORM_DEF_H
-
-#include <nrd1/nrd_plat_arm_def1.h>
-
-#define PLAT_ARM_CLUSTER_COUNT U(2)
-#define NRD_MAX_CPUS_PER_CLUSTER U(4)
-#define NRD_MAX_PE_PER_CPU U(1)
-
-/* GIC related constants */
-#define PLAT_ARM_GICD_BASE UL(0x30000000)
-#define PLAT_ARM_GICC_BASE UL(0x2C000000)
-#define PLAT_ARM_GICR_BASE UL(0x300C0000)
-
-/* Platform specific page table and MMU setup constants */
-#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
-#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
-
-#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/neoverse_rd/platform/sgi575/platform.mk b/plat/arm/neoverse_rd/platform/sgi575/platform.mk
deleted file mode 100644
index 5e81be5..0000000
--- a/plat/arm/neoverse_rd/platform/sgi575/platform.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-include plat/arm/neoverse_rd/common/nrd_common.mk
-
-PLAT_INCLUDES += -Iplat/arm/neoverse_rd/platform/sgi575/include/
-
-PLAT_SOURCES += plat/arm/neoverse_rd/platform/sgi575/sgi575_topology.c
-
-PLAT_TESTS_SKIP_LIST := plat/arm/neoverse_rd/platform/sgi575/tests_to_skip.txt
-
-ifdef NRD_PLATFORM_VARIANT
-$(error "NRD_PLATFORM_VARIANT should not be set for SGI-575, \
- currently set to ${NRD_PLATFORM_VARIANT}.")
-endif
diff --git a/plat/arm/neoverse_rd/platform/sgi575/sgi575_topology.c b/plat/arm/neoverse_rd/platform/sgi575/sgi575_topology.c
deleted file mode 100644
index f38c197..0000000
--- a/plat/arm/neoverse_rd/platform/sgi575/sgi575_topology.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <assert.h>
-#include <plat_topology.h>
-#include <tftf_lib.h>
-
-static const struct {
- unsigned int cluster_id;
- unsigned int cpu_id;
-} sgi575_cores[] = {
- /* Cluster0: 4 cores*/
- { 0, 0 },
- { 0, 1 },
- { 0, 2 },
- { 0, 3 },
- /* Cluster1: 4 cores */
- { 1, 0 },
- { 1, 1 },
- { 1, 2 },
- { 1, 3 },
-};
-
-/*
- * The power domain tree descriptor. The cluster power domains are
- * arranged so that when the PSCI generic code creates the power domain tree,
- * the indices of the CPU power domain nodes it allocates match the linear
- * indices returned by plat_core_pos_by_mpidr().
- */
-const unsigned char sgi575_pd_tree_desc[] = {
- /* Number of root nodes */
- PLAT_ARM_CLUSTER_COUNT,
- /* Number of children for the 1st node */
- NRD_MAX_CPUS_PER_CLUSTER,
- /* Number of children for the 2nd node */
- NRD_MAX_CPUS_PER_CLUSTER
-};
-
-const unsigned char *tftf_plat_get_pwr_domain_tree_desc(void)
-{
- return sgi575_pd_tree_desc;
-}
-
-uint64_t tftf_plat_get_mpidr(unsigned int core_pos)
-{
- unsigned int mpid;
-
- assert(core_pos < PLATFORM_CORE_COUNT);
-
- mpid = make_mpid(
- sgi575_cores[core_pos].cluster_id,
- sgi575_cores[core_pos].cpu_id);
-
- return mpid;
-}
diff --git a/plat/arm/neoverse_rd/platform/sgi575/tests_to_skip.txt b/plat/arm/neoverse_rd/platform/sgi575/tests_to_skip.txt
deleted file mode 100644
index 8817946..0000000
--- a/plat/arm/neoverse_rd/platform/sgi575/tests_to_skip.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# Copyright (c) 2020-2024, Arm Limited and Contributors. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-# OS-initiated mode is not supported on SGI-575
-PSCI CPU Suspend in OSI mode
-
-# System suspend is not supported as there are no wakeup sources in SGI-575 FVP
-PSCI STAT/Stats test cases after system suspend
-PSCI System Suspend Validation
diff --git a/plat/xilinx/common/timer/timers.c b/plat/xilinx/common/timer/timers.c
index f53cd84..da8467b 100644
--- a/plat/xilinx/common/timer/timers.c
+++ b/plat/xilinx/common/timer/timers.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2025, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -26,6 +26,7 @@
#define TTC_IER_OFFSET U(0x60) /* Interrupt Enable Reg, RW */
#define TTC_CNT_CNTRL_DISABLE_MASK BIT(0)
+#define TTC_ISR_INTERVAL_BIT BIT_32(0)
#define TTC_CLK_SEL_MASK GENMASK(1, 0)
@@ -68,12 +69,22 @@
static int cancel_timer(void)
{
+ uint32_t status;
+ uint32_t reg;
+
+ status = timer_read_32(TTC_ISR_OFFSET);
+ if (status & TTC_ISR_INTERVAL_BIT) {
+ VERBOSE("Timer Interval Interrupt Event! %x\n", status);
+ } else {
+ INFO("Its not a Timer Interval Interrupt Event %d\n", status);
+ }
/* Disable Interrupt */
timer_write_32(TTC_IER_OFFSET, 0);
/* Disable Counter */
- timer_write_32(TTC_CLK_CNTRL_OFFSET, !CLK_CNTRL_PRESCALE_EN);
- timer_write_32(TTC_CNT_CNTRL_OFFSET, !CLK_CNTRL_PRESCALE_EN);
+ reg = timer_read_32(TTC_CNT_CNTRL_OFFSET);
+ reg |= TTC_CNT_CNTRL_DISABLE_MASK;
+ timer_write_32(TTC_CNT_CNTRL_OFFSET, reg);
return RET_SUCCESS;
}
diff --git a/plat/xilinx/versal_net/include/platform_def.h b/plat/xilinx/versal_net/include/platform_def.h
index 92a7ba0..12c5910 100644
--- a/plat/xilinx/versal_net/include/platform_def.h
+++ b/plat/xilinx/versal_net/include/platform_def.h
@@ -99,7 +99,7 @@
#define IRQ_NS_SGI_7 7
/* Per-CPU Hypervisor Timer Interrupt ID */
-#define IRQ_PCPU_HP_TIMER U(29)
+#define IRQ_PCPU_HP_TIMER U(26)
/* Datasheet: TIME00 event*/
#define IRQ_CNTPSIRQ1 U(29)
diff --git a/realm/realm_mpam.c b/realm/realm_mpam.c
index 913e451..e38d045 100644
--- a/realm/realm_mpam.c
+++ b/realm/realm_mpam.c
@@ -7,16 +7,27 @@
#include <arch_helpers.h>
#include <sync.h>
#include <realm_helpers.h>
+#include <utils_def.h>
/* Check if Realm gets undefined abort when it access MPAM registers */
bool test_realm_mpam_undef_abort(void)
{
+ void (*write_reg[])(u_register_t) = {write_mpam0_el1,
+ write_mpam1_el1,
+ write_mpamsm_el1,
+ write_mpamidr_el1};
+ unsigned int n_access = ARRAY_SIZE(write_reg);
+
realm_reset_undef_abort_count();
/* Install exception handler to catch undefined abort */
register_custom_sync_exception_handler(realm_sync_exception_handler);
- write_mpam0_el1(0UL);
+
+ for (unsigned int i = 0U; i < n_access; i++) {
+ write_reg[i](0UL);
+ }
+
unregister_custom_sync_exception_handler();
- return (realm_get_undef_abort_count() != 0UL);
+ return (realm_get_undef_abort_count() == (unsigned long)n_access);
}
diff --git a/realm/realm_payload_main.c b/realm/realm_payload_main.c
index 58de955..70687f1 100644
--- a/realm/realm_payload_main.c
+++ b/realm/realm_payload_main.c
@@ -243,7 +243,7 @@
} else {
realm_printf("rsi_ipa_state_get failed top=0x%lx",
"new_top=0x%lx ripas=%u ret=0x%lx\n",
- ripas);
+ top, new_top, ripas, ret);
return false;
}
}
diff --git a/spm/cactus/cactus.mk b/spm/cactus/cactus.mk
index 7d39221..34565f0 100644
--- a/spm/cactus/cactus.mk
+++ b/spm/cactus/cactus.mk
@@ -100,6 +100,7 @@
$(eval $(call add_define,CACTUS_DEFINES,PLAT_${PLAT}))
$(eval $(call add_define,CACTUS_DEFINES,PLAT_XLAT_TABLES_DYNAMIC))
$(eval $(call add_define,CACTUS_DEFINES,SPMC_AT_EL3))
+$(eval $(call add_define,CACTUS_DEFINES,CACTUS_PWR_MGMT_SUPPORT))
$(CACTUS_DTB) : $(BUILD_PLAT)/cactus $(BUILD_PLAT)/cactus/cactus.elf
$(CACTUS_DTB) : $(CACTUS_DTS)
diff --git a/spm/cactus/cactus_main.c b/spm/cactus/cactus_main.c
index 8554709..4a28862 100644
--- a/spm/cactus/cactus_main.c
+++ b/spm/cactus/cactus_main.c
@@ -102,6 +102,11 @@
continue;
}
+ if (ffa_is_framework_msg(ffa_ret)) {
+ ffa_ret = cactus_handle_framework_msg(ffa_ret);
+ continue;
+ }
+
destination = ffa_dir_msg_dest(ffa_ret);
if (destination != vm_id) {
ERROR("%s(%u) invalid vm id 0x%x\n",
diff --git a/spm/cactus/cactus_tests/cactus_message_loop.c b/spm/cactus/cactus_tests/cactus_message_loop.c
index c0abf2b..aba3124 100644
--- a/spm/cactus/cactus_tests/cactus_message_loop.c
+++ b/spm/cactus/cactus_tests/cactus_message_loop.c
@@ -11,7 +11,9 @@
#include <ffa_helpers.h>
#include <events.h>
#include <platform.h>
+#include <sp_helpers.h>
#include <spm_helpers.h>
+#include <psci.h>
/**
* Counter of the number of handled requests, for each CPU. The number of
@@ -99,3 +101,87 @@
CACTUS_ERROR_UNHANDLED);
return true;
}
+
+struct ffa_value cactus_handle_framework_msg(struct ffa_value args)
+{
+ ffa_id_t source_id = ffa_dir_msg_source(args);
+ ffa_id_t destination_id = ffa_dir_msg_dest(args);
+ uint32_t status_code;
+
+#if CACTUS_PWR_MGMT_SUPPORT == 1
+ uint32_t framework_msg = ffa_get_framework_msg(args);
+ uint32_t psci_function = args.arg3;
+ struct ffa_value ret;
+
+ /*
+ * As of now, Cactus supports receiving only PSCI power management
+ * request as framework message.
+ */
+ if (framework_msg != FFA_FRAMEWORK_MSG_PSCI_REQ) {
+ ERROR("Unsupported framework message received by SP:%x\n",
+ destination_id);
+ status_code = PSCI_E_DENIED;
+ goto out;
+ }
+
+ /* Cactus only supports receiving CPU_OFF PSCI function as message. */
+ if (psci_function != SMC_PSCI_CPU_OFF) {
+ ERROR("Unsupported PSCI function(%x) received by SP:%x through "
+ "framework message\n", psci_function, destination_id);
+ status_code = PSCI_E_DENIED;
+ goto out;
+ }
+
+ /* Only SPMC can send the PSCI framework message. */
+ if (source_id != SPMC_ID) {
+ ERROR("Framework message source illegal %x\n", source_id);
+ status_code = PSCI_E_DENIED;
+ goto out;
+ }
+
+ status_code = PSCI_E_SUCCESS;
+
+ /*
+ * FF-A spec states that SPs are prohibited from invoking Direct
+ * request, FFA_RUN and FFA_YIELD interfaces while handling power
+ * management framework message. Make the Cactus SP intentionally
+ * invoke prohibited interfaces and attest that SPMC should deny such
+ * invocations.
+ */
+ ret = cactus_success_resp(destination_id, source_id, status_code);
+
+ /* Non-framework direct response must be denied. */
+ EXPECT(ffa_func_id(ret), FFA_ERROR);
+ EXPECT(ffa_error_code(ret), FFA_ERROR_DENIED);
+
+ ret = cactus_echo_send_cmd(destination_id, SP_ID(4), 0x9999);
+
+ /* Direct request message must be denied. */
+ EXPECT(ffa_func_id(ret), FFA_ERROR);
+ EXPECT(ffa_error_code(ret), FFA_ERROR_DENIED);
+
+ ret = ffa_run(SP_ID(4), 0);
+
+ /* FFA_RUN invocation must be denied. */
+ EXPECT(ffa_func_id(ret), FFA_ERROR);
+ EXPECT(ffa_error_code(ret), FFA_ERROR_DENIED);
+
+ ret = ffa_yield();
+
+ /* FFA_YIELD invocation must be denied. */
+ EXPECT(ffa_func_id(ret), FFA_ERROR);
+ EXPECT(ffa_error_code(ret), FFA_ERROR_DENIED);
+
+ /*
+ * Return successful status for PSCI power management request through
+ * direct response Framework message.
+ */
+ VERBOSE("PSCI power management request handled successfully by SP:%x\n",
+ destination_id);
+out:
+#else
+ status_code = PSCI_E_DENIED;
+#endif
+ return ffa_framework_msg_send_direct_resp(destination_id, source_id,
+ FFA_FRAMEWORK_MSG_PSCI_RESP, status_code);
+}
diff --git a/spm/cactus/plat/arm/fvp/fdts/cactus-secondary.dts b/spm/cactus/plat/arm/fvp/fdts/cactus-secondary.dts
index 0f6c23d..a8130c6 100644
--- a/spm/cactus/plat/arm/fvp/fdts/cactus-secondary.dts
+++ b/spm/cactus/plat/arm/fvp/fdts/cactus-secondary.dts
@@ -30,6 +30,7 @@
messaging-method = <3>; /* Direct messaging only */
ns-interrupts-action = <2>; /* Non secure interrupts are signaled. */
notification-support; /* Support receipt of notifications. */
+ power-management-messages = <1>; /* Support CPU_OFF power management message. */
rx_tx-info {
compatible = "arm,ffa-manifest-rx_tx-buffer";
diff --git a/spm/cactus/plat/arm/fvp/fdts/cactus.dts b/spm/cactus/plat/arm/fvp/fdts/cactus.dts
index 4d95069..03a7d17 100644
--- a/spm/cactus/plat/arm/fvp/fdts/cactus.dts
+++ b/spm/cactus/plat/arm/fvp/fdts/cactus.dts
@@ -30,6 +30,7 @@
messaging-method = <7>; /* Indirect Messaging and direct messaging. */
ns-interrupts-action = <1>; /* Managed exit is supported */
notification-support; /* Support receipt of notifications. */
+ power-management-messages = <1>; /* Support CPU_OFF power management message. */
/* Boot protocol */
gp-register-num = <0>;
diff --git a/spm/common/sp_tests/sp_test_ffa.c b/spm/common/sp_tests/sp_test_ffa.c
index e7dd720..94576d1 100644
--- a/spm/common/sp_tests/sp_test_ffa.c
+++ b/spm/common/sp_tests/sp_test_ffa.c
@@ -83,9 +83,7 @@
{
const struct ffa_features_test *func_id_targets;
/* Get common features between tftf and cactus. */
- unsigned int test_target_size =
- get_ffa_feature_test_target(&func_id_targets);
- /* Specific to SPs. */
+ size_t test_target_size = get_ffa_feature_test_target(&func_id_targets);
struct ffa_features_test feature_id_targets[] = {
{"FFA_FEATURE_MEI", FFA_FEATURE_MEI, FFA_SUCCESS_SMC32, 0,
FFA_VERSION_1_1},
diff --git a/tftf/framework/aarch32/entrypoint.S b/tftf/framework/aarch32/entrypoint.S
index eaa0788..3e40ab9 100644
--- a/tftf/framework/aarch32/entrypoint.S
+++ b/tftf/framework/aarch32/entrypoint.S
@@ -16,6 +16,12 @@
* ----------------------------------------------------------------------------
*/
func tftf_entrypoint
+#if TRANSFER_LIST
+ mov r4, r0
+ mov r5, r1
+ mov r6, r2
+ mov r7, r3
+#endif
bl arch_init
/* --------------------------------------------------------------------
@@ -53,6 +59,19 @@
bl zeromem
/* --------------------------------------------------------------------
+ * Save transfer list and hw_config addresses passed in registers r0 to
+ * r3 from the previous bootloader.
+ * --------------------------------------------------------------------
+ */
+#if TRANSFER_LIST
+ mov r0, r4
+ mov r1, r5
+ mov r2, r6
+ mov r3, r7
+ bl save_handoff_params
+#endif
+
+ /* --------------------------------------------------------------------
* Give ourselves a small coherent stack to ease the pain of
* initializing the MMU
* --------------------------------------------------------------------
@@ -172,3 +191,18 @@
/* Primary core MPID already saved */
b panic
endfunc save_primary_mpid
+
+/* ----------------------------------------------------------------------------
+ * Save transfer list and hw_config addresses passed in registers r0 to r3 from
+ * the previous bootloader.
+ * ----------------------------------------------------------------------------
+ */
+func save_handoff_params
+ ldr r4, =ns_tl
+ str r3, [r4]
+ ldr r4, =tl_signature
+ str r1, [r4]
+ ldr r4, =hw_config_base
+ str r2, [r4]
+ bx lr
+endfunc save_handoff_params
diff --git a/tftf/framework/framework.mk b/tftf/framework/framework.mk
index d5d3300..098f2b8 100644
--- a/tftf/framework/framework.mk
+++ b/tftf/framework/framework.mk
@@ -55,6 +55,7 @@
lib/${ARCH}/misc_helpers.S \
lib/delay/delay.c \
lib/events/events.c \
+ ${EVENT_LOG_SOURCES} \
lib/extensions/amu/${ARCH}/amu.c \
lib/extensions/amu/${ARCH}/amu_helpers.S \
lib/exceptions/irq.c \
diff --git a/tftf/tests/extensions/pauth/test_pauth.c b/tftf/tests/extensions/pauth/test_pauth.c
index ada2f1d..f964266 100644
--- a/tftf/tests/extensions/pauth/test_pauth.c
+++ b/tftf/tests/extensions/pauth/test_pauth.c
@@ -58,13 +58,10 @@
SKIP_TEST_IF_PAUTH_NOT_SUPPORTED();
#if ARM_ARCH_AT_LEAST(8, 3)
+ u_register_t reg = 42;
+
/* Pointer authentication instructions */
- __asm__ volatile (
- "paciasp\n"
- "autiasp\n"
- "paciasp\n"
- "xpaclri"
- );
+ __asm__ volatile ("pacdza %0\n" : "+r"(reg));
return TEST_RESULT_SUCCESS;
#else
tftf_testcase_printf("Pointer Authentication instructions "
diff --git a/tftf/tests/extensions/ras/test_ras.c b/tftf/tests/extensions/ras/test_ras.c
new file mode 100644
index 0000000..cd27f16
--- /dev/null
+++ b/tftf/tests/extensions/ras/test_ras.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <test_helpers.h>
+#include <tftf_lib.h>
+#include <tftf.h>
+
+/*
+ * FEAT_RAS introduces EL1 system registers to query error records, those
+ * CPU specific parts of the RAS extension can be accessed independently of
+ * any FFH/KFH handling setup or any system specific RAS implementation.
+ * Reading these registers will trap to EL3 and crash when EL3 has not
+ * allowed access, which is controlled by the SCR_EL3.TERR bit.
+ */
+
+test_result_t test_ras_reg_access(void)
+{
+ SKIP_TEST_IF_AARCH32();
+
+#ifdef __aarch64__
+ SKIP_TEST_IF_RAS_NOT_SUPPORTED();
+
+ read_erridr_el1();
+
+ return TEST_RESULT_SUCCESS;
+#endif
+}
diff --git a/tftf/tests/misc_tests/test_firmware_handoff.c b/tftf/tests/misc_tests/test_firmware_handoff.c
index 00cebd3..026f057 100644
--- a/tftf/tests/misc_tests/test_firmware_handoff.c
+++ b/tftf/tests/misc_tests/test_firmware_handoff.c
@@ -6,10 +6,13 @@
#include <assert.h>
+#include <drivers/measured_boot/event_log/tcg.h>
#include <test_helpers.h>
#include <tftf_lib.h>
#include <transfer_list.h>
+#include "event_log.h"
+
extern u_register_t hw_config_base;
extern u_register_t ns_tl;
extern u_register_t tl_signature;
@@ -20,8 +23,15 @@
{
struct transfer_list_header *tl = (struct transfer_list_header *)ns_tl;
- assert(tl_signature ==
- TRANSFER_LIST_HANDOFF_X1_VALUE(TRANSFER_LIST_VERSION));
+#if __aarch64__
+ uint64_t signature = TRANSFER_LIST_HANDOFF_X1_VALUE(TRANSFER_LIST_VERSION);
+#else
+ uint32_t signature = TRANSFER_LIST_HANDOFF_R1_VALUE(TRANSFER_LIST_VERSION);
+#endif /* __aarch64__ */
+
+ if (signature != tl_signature) {
+ return TEST_RESULT_FAIL;
+ }
if (transfer_list_check_header(tl) == TL_OPS_NON) {
return TEST_RESULT_FAIL;
@@ -54,3 +64,31 @@
return TEST_RESULT_SUCCESS;
}
+
+test_result_t test_handoff_event_payload(void)
+{
+
+ struct transfer_list_header *tl = (struct transfer_list_header *)ns_tl;
+ struct transfer_list_entry *te;
+ uint8_t *log_addr;
+ size_t log_size;
+
+ tftf_testcase_printf(
+ "Validate that a TPM event log can be successfully dumped when "
+ "present in the transfer list.");
+
+ te = transfer_list_find(tl, TL_TAG_TPM_EVLOG);
+ if (te == NULL) {
+ return TEST_RESULT_SKIPPED;
+ }
+
+ /* 4-bytes are reserved in TE data section. */
+ log_addr = (uint8_t *)transfer_list_entry_data(te) + U(4);
+ log_size = te->data_size - U(4);
+
+ if (event_log_dump(log_addr, log_size) != 0) {
+ return TEST_RESULT_FAIL;
+ }
+
+ return TEST_RESULT_SUCCESS;
+}
diff --git a/tftf/tests/neg_scenario_tests/test_fwu_image_size.c b/tftf/tests/neg_scenario_tests/test_fwu_image_size.c
new file mode 100644
index 0000000..0bf4d29
--- /dev/null
+++ b/tftf/tests/neg_scenario_tests/test_fwu_image_size.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <firmware_image_package.h>
+#include <fwu_nvm.h>
+#include <image_loader.h>
+#include <io_storage.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <psci.h>
+#include <smccc.h>
+#include <status.h>
+#include <tftf_lib.h>
+#include <uuid.h>
+#include <uuid_utils.h>
+
+/*
+ * @TEST_AIM@ validate FWU IMAGE SIZE invalid scenario
+ * TEST SUCCESS if FWU FIP IMAGE SIZE is found invalid and Fails to Proceed
+ * TEST FAIL in case FWU process is able to reboot
+ */
+
+static fip_toc_entry_t *
+find_fiptoc_entry_t(const int fip_base, const uuid_t *uuid)
+{
+ fip_toc_entry_t *current_file =
+ (fip_toc_entry_t *) (fip_base + sizeof(fip_toc_header_t));
+
+ while (!is_uuid_null(&(current_file->uuid))) {
+ if (uuid_equal(&(current_file->uuid), uuid))
+ return current_file;
+
+ current_file += 1;
+ };
+ return NULL;
+}
+
+test_result_t test_fwu_image_size(void)
+{
+ STATUS status;
+ int fip_base = PLAT_ARM_FIP_BASE;
+ int fwu_fip_base = PLAT_ARM_FWU_FIP_BASE;
+
+ const uuid_t bl2 = UUID_TRUSTED_BOOT_FIRMWARE_BL2;
+ const uuid_t bl2u = UUID_FIRMWARE_UPDATE_BL2U;
+
+ fip_toc_entry_t *bl2_entry;
+ fip_toc_entry_t *bl2u_entry;
+
+ uintptr_t bl2_entry_address, bl2u_entry_address;
+
+ int corrupt_size = 0xFFFF;
+ int offset;
+
+ smc_args args = { SMC_PSCI_SYSTEM_RESET };
+ smc_ret_values ret = {0};
+
+ /* retrieve bl2 and bl2u */
+ bl2_entry = find_fiptoc_entry_t(fip_base, &bl2);
+ bl2_entry_address = (uintptr_t)bl2_entry;
+
+ bl2u_entry = find_fiptoc_entry_t(fwu_fip_base, &bl2u);
+ bl2u_entry_address = (intptr_t)bl2u_entry;
+
+ /* Reboot has not occurred yet */
+ tftf_testcase_printf("not rebooted yet\n");
+
+ /* Corrupt FWU_FIP_SIZE */
+ tftf_testcase_printf("bl2_entry_address value is (%lx)\n", bl2_entry_address);
+
+ /*
+ * corrupt bl2 in fip
+ * corrupt toc entry size field of bl2u
+ */
+
+ /* corrupt bl2 image */
+ offset = bl2_entry_address + sizeof(uuid_t) + sizeof(uint64_t) - FLASH_BASE;
+ status = fwu_nvm_write(offset, &corrupt_size, sizeof(uint64_t));
+
+ if (status != STATUS_SUCCESS) {
+ tftf_testcase_printf("staus not success error %d\n", status);
+ return TEST_RESULT_FAIL;
+ }
+
+ /* corrupt toc bl2u entry */
+ offset = bl2u_entry_address + sizeof(uuid_t) + sizeof(uint64_t) - FLASH_BASE;
+ status = fwu_nvm_write(offset, &corrupt_size, sizeof(uint64_t));
+
+ if (status != STATUS_SUCCESS) {
+ tftf_testcase_printf("status not success error %d\n", status);
+ return TEST_RESULT_FAIL;
+ }
+
+ /* Notify that we are rebooting now. */
+ tftf_notify_reboot();
+
+ /* Request PSCI system reset. */
+ ret = tftf_smc(&args);
+
+ /* The PSCI SYSTEM_RESET call is not supposed to return */
+ tftf_testcase_printf("System didn't reboot properly (%d)\n",
+ (unsigned int)ret.ret0);
+
+ return TEST_RESULT_FAIL;
+}
diff --git a/tftf/tests/runtime_services/arm_arch_svc/smccc_feature_availability.c b/tftf/tests/runtime_services/arm_arch_svc/smccc_feature_availability.c
index 1418ca1..7c7f91b 100644
--- a/tftf/tests/runtime_services/arm_arch_svc/smccc_feature_availability.c
+++ b/tftf/tests/runtime_services/arm_arch_svc/smccc_feature_availability.c
@@ -79,12 +79,13 @@
CHECK_BIT_SET(is_feat_tcr2_supported, SCR_TCR2EN_BIT);
CHECK_BIT_SET(is_feat_the_supported, SCR_RCWMASKEn_BIT);
CHECK_BIT_SET(is_feat_sme_supported, SCR_ENTP2_BIT);
- CHECK_BIT_SET(is_feat_rng_trap_present, SCR_TRNDR_BIT);
+ CHECK_BIT_SET(is_feat_rng_present, SCR_TRNDR_BIT);
CHECK_BIT_SET(is_feat_gcs_present, SCR_GCSEn_BIT);
CHECK_BIT_SET(get_feat_hcx_support, SCR_HXEn_BIT);
CHECK_BIT_SET(is_feat_ls64_accdata_present, SCR_ADEn_BIT);
CHECK_BIT_SET(is_feat_ls64_accdata_present, SCR_EnAS0_BIT);
CHECK_BIT_SET(is_feat_amuv1p1_present, SCR_AMVOFFEN_BIT);
+ CHECK_BIT_SET(is_feat_twed_present, SCR_TWEDEn_BIT);
CHECK_BIT_SET(get_armv8_6_ecv_support, SCR_ECVEN_BIT);
CHECK_BIT_SET(is_armv8_6_fgt_present, SCR_FGTEN_BIT);
CHECK_BIT_SET(is_feat_mte2_present, SCR_ATA_BIT);
@@ -108,6 +109,7 @@
CHECK_BIT_SET(is_feat_trbe_present, MDCR_NSTB(1));
CHECK_BIT_SET(get_armv8_4_trf_support, MDCR_TTRF_BIT);
CHECK_BIT_SET(is_feat_spe_supported, MDCR_NSPB(1));
+ CHECK_BIT_SET(is_feat_pmuv3p9_present, MDCR_EnPM2_BIT);
CHECK_BIT_SET(is_feat_doublelock_present, MDCR_TDOSA_BIT);
CHECK_BIT_SET(always_present, MDCR_TDA_BIT);
CHECK_BIT_SET(get_feat_pmuv3_supported, MDCR_TPM_BIT);
diff --git a/tftf/tests/runtime_services/host_realm_managment/host_rmi_pdev.c b/tftf/tests/runtime_services/host_realm_managment/host_rmi_pdev.c
index c43c374..572bc2a 100644
--- a/tftf/tests/runtime_services/host_realm_managment/host_rmi_pdev.c
+++ b/tftf/tests/runtime_services/host_realm_managment/host_rmi_pdev.c
@@ -378,6 +378,10 @@
/* Allocate granule for PDEV and delegate */
tdi->pdev = page_alloc(PAGE_SIZE);
+ if (tdi->pdev == NULL) {
+ return -1;
+ }
+
memset(tdi->pdev, 0, GRANULE_SIZE);
ret = host_rmi_granule_delegate((u_register_t)tdi->pdev);
if (ret != RMI_SUCCESS) {
@@ -393,48 +397,67 @@
ret = host_rmi_pdev_aux_count(tdi->pdev_flags, &count);
if (ret != RMI_SUCCESS) {
ERROR("host_rmi_pdev_aux_count() failed 0x%lx\n", ret);
- return -1;
+ goto err_undelegate_pdev;
}
tdi->pdev_aux_num = count;
/* Allocate aux granules for PDEV and delegate */
INFO("PDEV create requires %u aux pages\n", tdi->pdev_aux_num);
for (i = 0; i < tdi->pdev_aux_num; i++) {
- tdi->pdev_aux[i] = page_alloc(PAGE_SIZE);
- ret = host_rmi_granule_delegate((u_register_t)tdi->pdev_aux[i]);
+ void *pdev_aux = page_alloc(PAGE_SIZE);
+
+ if (pdev_aux == NULL) {
+ goto err_undelegate_pdev_aux;
+ }
+
+ ret = host_rmi_granule_delegate((u_register_t)pdev_aux);
if (ret != RMI_SUCCESS) {
ERROR("Aux granule delegate failed 0x%lx\n", ret);
- return -1;
+ goto err_undelegate_pdev_aux;
}
+
+ tdi->pdev_aux[i] = pdev_aux;
}
/* Allocate dev_comm_data and send/recv buffer for Dev communication */
tdi->dev_comm_data = (struct rmi_dev_comm_data *)page_alloc(PAGE_SIZE);
+ if (tdi->dev_comm_data == NULL) {
+ goto err_undelegate_pdev_aux;
+ }
+
memset(tdi->dev_comm_data, 0, sizeof(struct rmi_dev_comm_data));
+
tdi->dev_comm_data->enter.req_addr = (unsigned long)
page_alloc(PAGE_SIZE);
+ if (tdi->dev_comm_data->enter.req_addr == 0UL) {
+ goto err_undelegate_pdev_aux;
+ }
+
tdi->dev_comm_data->enter.resp_addr = (unsigned long)
page_alloc(PAGE_SIZE);
+ if (tdi->dev_comm_data->enter.resp_addr == 0UL) {
+ goto err_undelegate_pdev_aux;
+ }
/* Allocate buffer to cache device certificate */
tdi->cert_slot_id = 0;
tdi->cert_chain = (uint8_t *)page_alloc(HOST_PDEV_CERT_LEN_MAX);
tdi->cert_chain_len = 0;
if (tdi->cert_chain == NULL) {
- return -1;
+ goto err_undelegate_pdev_aux;
}
/* Allocate buffer to store extracted public key */
tdi->public_key = (void *)page_alloc(PAGE_SIZE);
if (tdi->public_key == NULL) {
- return -1;
+ goto err_undelegate_pdev_aux;
}
tdi->public_key_len = PAGE_SIZE;
/* Allocate buffer to store public key metadata */
tdi->public_key_metadata = (void *)page_alloc(PAGE_SIZE);
if (tdi->public_key_metadata == NULL) {
- return -1;
+ goto err_undelegate_pdev_aux;
}
tdi->public_key_metadata_len = PAGE_SIZE;
@@ -442,13 +465,27 @@
tdi->meas = (uint8_t *)page_alloc(HOST_PDEV_MEAS_LEN_MAX);
tdi->meas_len = 0;
if (tdi->meas == NULL) {
- return -1;
+ goto err_undelegate_pdev_aux;
}
/* Set algorithm to use for device digests */
tdi->pdev_hash_algo = RMI_HASH_SHA_512;
return 0;
+
+err_undelegate_pdev_aux:
+ /* Undelegate all the delegated pages */
+ for (int i = 0; i < tdi->pdev_aux_num; i++) {
+ if (tdi->pdev_aux[i]) {
+ host_rmi_granule_undelegate((u_register_t)
+ tdi->pdev_aux[i]);
+ }
+ }
+
+err_undelegate_pdev:
+ host_rmi_granule_undelegate((u_register_t)tdi->pdev);
+
+ return -1;
}
/*
@@ -578,3 +615,41 @@
return TEST_RESULT_SUCCESS;
}
+
+
+/*
+ * This function invokes PDEV_CREATE on TRP and tries to test
+ * the EL3 RMM-EL3 IDE KM interface. Will be skipped on TF-RMM.
+ */
+test_result_t host_realm_test_root_port_key_management(void)
+{
+ struct host_tdi *tdi;
+ int ret;
+
+ if (host_rmi_version(RMI_ABI_VERSION_VAL) != 0U) {
+ tftf_testcase_printf("RMM is not TRP\n");
+ return TEST_RESULT_SKIPPED;
+ }
+
+ /* Initialize Host NS heap memory */
+ ret = page_pool_init((u_register_t)PAGE_POOL_BASE,
+ (u_register_t)PAGE_POOL_MAX_SIZE);
+ if (ret != HEAP_INIT_SUCCESS) {
+ ERROR("Failed to init heap pool %d\n", ret);
+ return TEST_RESULT_FAIL;
+ }
+
+ tdi = &g_tdi;
+
+ /*
+ * Call rmi_pdev_create with invalid pdev, expect an error
+ * to be returned from TRP.
+ */
+ ret = host_tdi_pdev_create(tdi);
+ if (ret != 0) {
+ return TEST_RESULT_SUCCESS;
+ }
+
+ ERROR("RMI_PDEV_CREATE did not return error as expected\n");
+ return TEST_RESULT_FAIL;
+}
diff --git a/tftf/tests/runtime_services/realm_payload/host_realm_brbe_tests.c b/tftf/tests/runtime_services/realm_payload/host_realm_brbe_tests.c
index 9f6246b..3816422 100644
--- a/tftf/tests/runtime_services/realm_payload/host_realm_brbe_tests.c
+++ b/tftf/tests/runtime_services/realm_payload/host_realm_brbe_tests.c
@@ -30,6 +30,11 @@
SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
SKIP_TEST_IF_BRBE_NOT_SUPPORTED();
+ if (is_feat_52b_on_4k_2_supported()) {
+ feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
+ sl = RTT_MIN_LEVEL_LPA2;
+ }
+
if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
feature_flag, feature_flag1, sl, rec_flag, 1U, 0U)) {
return TEST_RESULT_FAIL;
diff --git a/tftf/tests/runtime_services/realm_payload/host_realm_payload_simd_tests.c b/tftf/tests/runtime_services/realm_payload/host_realm_payload_simd_tests.c
index 023ec1c..1c2f58e 100644
--- a/tftf/tests/runtime_services/realm_payload/host_realm_payload_simd_tests.c
+++ b/tftf/tests/runtime_services/realm_payload/host_realm_payload_simd_tests.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2023-2025, Arm Limited. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -147,9 +147,16 @@
sve_vq = EXTRACT(RMI_FEATURE_REGISTER_0_SVE_VL, rmi_feat_reg0);
/*
- * Pass a sve_vq that is greater than the value supported by RMM
- * and check whether creating Realm fails
+ * TODO: The TFTF framework packs the sve_vl to feature flag for which the max value
+ * is 15 and then unpacks it to rmi_realm_params. Hence the value is clipped to 4 bits
+ * and hence it is not possible for test to send a value higher than this. Refactor
+ * this part of TFTF and then remove this limitation.
*/
+ if (sve_vq == SVE_VQ_ARCH_MAX) {
+ INFO("RMI supports arch max SVE VL %u, skipping\n", (sve_vq + 1));
+ return TEST_RESULT_SKIPPED;
+ }
+
rc = host_create_sve_realm_payload(&realm, true, (sve_vq + 1));
if (rc == TEST_RESULT_SUCCESS) {
ERROR("Error: Realm created with invalid SVE VL %u\n", (sve_vq + 1));
diff --git a/tftf/tests/runtime_services/realm_payload/host_realm_payload_tests.c b/tftf/tests/runtime_services/realm_payload/host_realm_payload_tests.c
index 51dc94b..2478d4f 100644
--- a/tftf/tests/runtime_services/realm_payload/host_realm_payload_tests.c
+++ b/tftf/tests/runtime_services/realm_payload/host_realm_payload_tests.c
@@ -2724,7 +2724,7 @@
/* RTT Fold */
ret = host_realm_fold_rtt(realm.rd, base, 3L);
if (ret != RMI_SUCCESS) {
- ERROR("host_rmi_rtt_fold failed ret=0x%lx\n", ret);
+ ERROR("host_realm_fold_rtt failed ret=0x%lx\n", ret);
goto destroy_realm;
}
@@ -2732,7 +2732,7 @@
ret = host_rmi_rtt_readentry(realm.rd, base, 3L, &rtt);
if (ret != RMI_SUCCESS || rtt.walk_level != 2L || rtt.state != RMI_UNASSIGNED
|| (rtt.ripas != RMI_EMPTY)) {
- ERROR("host_rmi_fold_rtt failed ret=0x%lx rtt.state=0x%lx"
+ ERROR("host_rmi_rtt_readentry failed ret=0x%lx rtt.state=0x%lx"
" rtt.walk_level=0x%lx rtt.out_addr=0x%llx\n",
ret, rtt.state, rtt.walk_level, rtt.out_addr);
goto destroy_realm;
@@ -2743,7 +2743,7 @@
/* RTT Fold */
ret = host_realm_fold_rtt(realm.rd, base, 2L);
if (ret != RMI_SUCCESS) {
- ERROR("host_rmi_rtt_fold failed ret=0x%lx\n", ret);
+ ERROR("host_realm_fold_rtt failed ret=0x%lx\n", ret);
goto destroy_realm;
}
@@ -2751,7 +2751,7 @@
ret = host_rmi_rtt_readentry(realm.rd, base, 3L, &rtt);
if (ret != RMI_SUCCESS || rtt.walk_level != 1L || rtt.state != RMI_UNASSIGNED
|| (rtt.ripas != RMI_EMPTY)) {
- ERROR("host_rmi_fold_rtt failed ret=0x%lx rtt.state=0x%lx"
+ ERROR("host_rmi_rtt_readentry failed ret=0x%lx rtt.state=0x%lx"
" rtt.walk_level=0x%lx rtt.out_addr=0x%llx\n",
ret, rtt.state, rtt.walk_level, rtt.out_addr);
goto destroy_realm;
@@ -2762,7 +2762,7 @@
/* RTT Fold */
ret = host_realm_fold_rtt(realm.rd, base, 1L);
if (ret != RMI_SUCCESS) {
- ERROR("host_rmi_rtt_fold failed ret=0x%lx\n", ret);
+ ERROR("host_realm_fold_rtt failed ret=0x%lx\n", ret);
goto destroy_realm;
}
@@ -2770,7 +2770,7 @@
ret = host_rmi_rtt_readentry(realm.rd, base, 3L, &rtt);
if (ret != RMI_SUCCESS || rtt.walk_level != 0L || rtt.state != RMI_UNASSIGNED
|| (rtt.ripas != RMI_EMPTY)) {
- ERROR("host_rmi_fold_rtt failed ret=0x%lx rtt.state=0x%lx"
+ ERROR("host_rmi_rtt_readentry failed ret=0x%lx rtt.state=0x%lx"
" rtt.walk_level=0x%lx rtt.out_addr=0x%llx\n",
ret, rtt.state, rtt.walk_level, rtt.out_addr);
goto destroy_realm;
@@ -2900,7 +2900,7 @@
/* RTT Fold */
ret = host_realm_fold_rtt(realm.rd, base, 3L);
if (ret != RMI_SUCCESS) {
- ERROR("host_rmi_rtt_fold failed ret=0x%lx\n", ret);
+ ERROR("host_realm_fold_rtt failed ret=0x%lx\n", ret);
goto destroy_realm;
}
@@ -2908,7 +2908,7 @@
ret = host_rmi_rtt_readentry(realm.rd, base, 3L, &rtt);
if (ret != RMI_SUCCESS || rtt.walk_level != 2L || rtt.state != RMI_UNASSIGNED
|| (rtt.ripas != RMI_RAM)) {
- ERROR("host_rmi_fold_rtt failed ret=0x%lx rtt.state=0x%lx"
+ ERROR("host_rmi_rtt_readentry failed ret=0x%lx rtt.state=0x%lx"
" rtt.walk_level=0x%lx rtt.out_addr=0x%llx\n",
ret, rtt.state, rtt.walk_level, rtt.out_addr);
goto destroy_realm;
@@ -2919,7 +2919,7 @@
/* RTT Fold */
ret = host_realm_fold_rtt(realm.rd, base, 2L);
if (ret != RMI_SUCCESS) {
- ERROR("host_rmi_rtt_fold failed ret=0x%lx\n", ret);
+ ERROR("host_realm_fold_rtt failed ret=0x%lx\n", ret);
goto destroy_realm;
}
@@ -2927,7 +2927,7 @@
ret = host_rmi_rtt_readentry(realm.rd, base, 3L, &rtt);
if (ret != RMI_SUCCESS || rtt.walk_level != 1L || rtt.state != RMI_UNASSIGNED
|| (rtt.ripas != RMI_RAM)) {
- ERROR("host_rmi_fold_rtt failed ret=0x%lx rtt.state=0x%lx"
+ ERROR("host_rmi_rtt_readentry failed ret=0x%lx rtt.state=0x%lx"
" rtt.walk_level=0x%lx rtt.out_addr=0x%llx\n",
ret, rtt.state, rtt.walk_level, rtt.out_addr);
goto destroy_realm;
@@ -2938,7 +2938,7 @@
/* RTT Fold */
ret = host_realm_fold_rtt(realm.rd, base, 1L);
if (ret != RMI_SUCCESS) {
- ERROR("host_rmi_rtt_fold failed ret=0x%lx\n", ret);
+ ERROR("host_realm_fold_rtt failed ret=0x%lx\n", ret);
goto destroy_realm;
}
@@ -2946,7 +2946,7 @@
ret = host_rmi_rtt_readentry(realm.rd, base, 3L, &rtt);
if (ret != RMI_SUCCESS || rtt.walk_level != 0L || rtt.state != RMI_UNASSIGNED
|| (rtt.ripas != RMI_RAM)) {
- ERROR("host_rmi_fold_rtt failed ret=0x%lx rtt.state=0x%lx"
+ ERROR("host_rmi_rtt_readentry failed ret=0x%lx rtt.state=0x%lx"
" rtt.walk_level=0x%lx rtt.out_addr=0x%llx\n",
ret, rtt.state, rtt.walk_level, rtt.out_addr);
goto destroy_realm;
@@ -3066,14 +3066,14 @@
/* RTT Fold */
ret = host_realm_fold_rtt(realm.rd, ns_ipa, 2L);
if (ret != RMI_SUCCESS) {
- ERROR("host_rmi_rtt_fold failed ret=0x%lx\n", ret);
+ ERROR("host_realm_fold_rtt failed ret=0x%lx\n", ret);
goto destroy_realm;
}
/* Walk should terminate at L1 */
ret = host_rmi_rtt_readentry(realm.rd, ns_ipa, 3L, &rtt);
if (ret != RMI_SUCCESS || rtt.walk_level != 1L || rtt.state != RMI_ASSIGNED) {
- ERROR("host_rmi_fold_rtt failed ret=0x%lx rtt.state=0x%lx"
+ ERROR("host_rmi_rtt_readentry failed ret=0x%lx rtt.state=0x%lx"
" rtt.walk_level=0x%lx rtt.out_addr=0x%llx\n",
ret, rtt.state, rtt.walk_level, rtt.out_addr);
goto destroy_realm;
@@ -3160,7 +3160,7 @@
/* RTT Fold */
ret = host_realm_fold_rtt(realm.rd, base, 3U);
if (ret != RMI_SUCCESS) {
- ERROR("host_rmi_rtt_fold failed ret=0x%lx\n", ret);
+ ERROR("host_realm_fold_rtt failed ret=0x%lx\n", ret);
goto undelegate_destroy;
}
@@ -3168,7 +3168,7 @@
ret = host_rmi_rtt_readentry(realm.rd, base, 3L, &rtt);
if (ret != RMI_SUCCESS || rtt.walk_level != 2L || rtt.state != RMI_ASSIGNED ||
rtt.ripas != RMI_EMPTY) {
- ERROR("host_rmi_fold_rtt failed ret=0x%lx rtt.state=0x%lx"
+ ERROR("host_rmi_rtt_readentry failed ret=0x%lx rtt.state=0x%lx"
" rtt.walk_level=0x%lx rtt.out_addr=0x%llx\n",
ret, rtt.state, rtt.walk_level, rtt.out_addr);
goto undelegate_destroy;
@@ -3276,7 +3276,7 @@
/* RTT Fold */
ret = host_realm_fold_rtt(realm.rd, base, 3L);
if (ret != RMI_SUCCESS) {
- ERROR("host_rmi_rtt_fold failed ret=0x%lx\n", ret);
+ ERROR("host_realm_fold_rtt failed ret=0x%lx\n", ret);
goto undelegate_destroy;
}
@@ -3284,7 +3284,7 @@
ret = host_rmi_rtt_readentry(realm.rd, base, 3L, &rtt);
if (ret != RMI_SUCCESS || rtt.walk_level != 2L || rtt.state != RMI_ASSIGNED ||
rtt.ripas != RMI_RAM) {
- ERROR("host_rmi_fold_rtt failed ret=0x%lx rtt.state=0x%lx"
+ ERROR("host_rmi_rtt_readentry failed ret=0x%lx rtt.state=0x%lx"
" rtt.walk_level=0x%lx rtt.out_addr=0x%llx ripas=0x%lx\n",
ret, rtt.state, rtt.walk_level, rtt.out_addr, rtt.ripas);
goto undelegate_destroy;
diff --git a/tftf/tests/runtime_services/secure_service/ffa_helpers.c b/tftf/tests/runtime_services/secure_service/ffa_helpers.c
index e0388db..3dc7036 100644
--- a/tftf/tests/runtime_services/secure_service/ffa_helpers.c
+++ b/tftf/tests/runtime_services/secure_service/ffa_helpers.c
@@ -142,6 +142,29 @@
return ffa_service_call(&args);
}
+struct ffa_value ffa_framework_msg_send_direct_resp(ffa_id_t source_id,
+ ffa_id_t dest_id, uint32_t msg,
+ uint32_t status_code)
+{
+ struct ffa_value args = {
+ .fid = FFA_MSG_SEND_DIRECT_RESP_SMC32,
+ .arg1 = ((uint32_t)(source_id << 16)) | (dest_id),
+ .arg2 = ((uint32_t)(1 << 31)) | (msg & 0xFF),
+ .arg3 = status_code,
+ };
+
+ return ffa_service_call(&args);
+}
+
+struct ffa_value ffa_yield(void)
+{
+ struct ffa_value args = {
+ .fid = FFA_MSG_YIELD,
+ };
+
+ return ffa_service_call(&args);
+}
+
void ffa_memory_region_init_header(struct ffa_memory_region *memory_region,
ffa_id_t sender,
ffa_memory_attributes_t attributes,
diff --git a/tftf/tests/runtime_services/secure_service/spm_common.c b/tftf/tests/runtime_services/secure_service/spm_common.c
index 4405c50..029113f 100644
--- a/tftf/tests/runtime_services/secure_service/spm_common.c
+++ b/tftf/tests/runtime_services/secure_service/spm_common.c
@@ -210,15 +210,11 @@
*
* Returns number of elements in the *test_target.
*/
-unsigned int get_ffa_feature_test_target(
- const struct ffa_features_test **test_target)
+size_t get_ffa_feature_test_target(const struct ffa_features_test **test_target)
{
- if (test_target != NULL) {
- *test_target = ffa_feature_test_target;
- }
-
- return sizeof(ffa_feature_test_target) /
- sizeof(struct ffa_features_test);
+ assert(test_target != NULL);
+ *test_target = ffa_feature_test_target;
+ return ARRAY_SIZE(ffa_feature_test_target);
}
/**
@@ -226,7 +222,7 @@
* FFA_FEATURES calls.
*/
bool ffa_features_test_targets(const struct ffa_features_test *targets,
- uint32_t test_target_size)
+ size_t test_target_size)
{
bool ret = true;
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_setup_and_discovery.c b/tftf/tests/runtime_services/secure_service/test_ffa_setup_and_discovery.c
index 5effe53..1586fe6 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_setup_and_discovery.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_setup_and_discovery.c
@@ -98,8 +98,7 @@
FFA_VERSION_1_1},
{"FFA_YIELD_32", FFA_MSG_YIELD, FFA_ERROR},
};
- unsigned int test_target_size =
- get_ffa_feature_test_target(&func_ids_target);
+ size_t test_target_size = get_ffa_feature_test_target(&func_ids_target);
SKIP_TEST_IF_FFA_VERSION_LESS_THAN(1, 0);
diff --git a/tftf/tests/runtime_services/standard_service/errata_abi/api_tests/test_errata_abi_functionality.c b/tftf/tests/runtime_services/standard_service/errata_abi/api_tests/test_errata_abi_functionality.c
index 98c567d..178516c 100644
--- a/tftf/tests/runtime_services/standard_service/errata_abi/api_tests/test_errata_abi_functionality.c
+++ b/tftf/tests/runtime_services/standard_service/errata_abi/api_tests/test_errata_abi_functionality.c
@@ -303,7 +303,7 @@
{2008768, 0x00, 0x20, 0x00},
{2017096, 0x00, 0x20, 0x00},
{2055002, 0x10, 0x20, 0x00},
- {2058056, 0x00, 0x10, 0x00},
+ {2058056, 0x00, 0x21, 0x00},
{2081180, 0x00, 0x20, 0x00},
{2083908, 0x20, 0x20, 0x00},
{2136059, 0x00, 0x20, 0x00},
diff --git a/tftf/tests/tests-cpu-extensions.mk b/tftf/tests/tests-cpu-extensions.mk
index 9358c49..37e41de 100644
--- a/tftf/tests/tests-cpu-extensions.mk
+++ b/tftf/tests/tests-cpu-extensions.mk
@@ -19,6 +19,7 @@
extensions/mte/test_mte.c \
extensions/pauth/test_pauth.c \
extensions/pmuv3/test_pmuv3.c \
+ extensions/ras/test_ras.c \
extensions/sctlr2/test_sctlr2.c \
extensions/sme/test_sme.c \
extensions/sme/test_sme2.c \
diff --git a/tftf/tests/tests-cpu-extensions.xml b/tftf/tests/tests-cpu-extensions.xml
index 632e231..dd60bc1 100644
--- a/tftf/tests/tests-cpu-extensions.xml
+++ b/tftf/tests/tests-cpu-extensions.xml
@@ -19,6 +19,7 @@
<testcase name="Check for Pointer Authentication key leakage from EL3" function="test_pauth_leakage" />
<testcase name="Check for Pointer Authentication key leakage from TSP" function="test_pauth_leakage_tsp" />
<testcase name="Access MPAM registers" function="test_mpam_reg_access" />
+ <testcase name="Access RAS registers" function="test_ras_reg_access" />
<testcase name="Use MTE Instructions" function="test_mte_instructions" />
<testcase name="Check for MTE register leakage" function="test_mte_leakage" />
<testcase name="Use FGT Registers" function="test_fgt_enabled" />
diff --git a/tftf/tests/tests-firmware-handoff.mk b/tftf/tests/tests-firmware-handoff.mk
index 515188a..65dfc4b 100644
--- a/tftf/tests/tests-firmware-handoff.mk
+++ b/tftf/tests/tests-firmware-handoff.mk
@@ -6,8 +6,12 @@
ifeq (${TRANSFER_LIST}, 1)
+include lib/event_log/event_log.mk
+
TESTS_SOURCES += $(addprefix tftf/tests/misc_tests/, \
test_firmware_handoff.c \
)
+TESTS_SOURCES += ${EVENT_LOG_SOURCES}
+
endif
diff --git a/tftf/tests/tests-firmware-handoff.xml b/tftf/tests/tests-firmware-handoff.xml
index 4b4b2a4..9b456cc 100644
--- a/tftf/tests/tests-firmware-handoff.xml
+++ b/tftf/tests/tests-firmware-handoff.xml
@@ -10,5 +10,6 @@
<testsuite name="Firmware Handoff" description="Validate transfer list managed by firmware handoff framework">
<testcase name="Validate transfer list header" function="test_handoff_header" />
<testcase name="Validate HW_CONFIG in transfer list" function="test_handoff_dtb_payload" />
+ <testcase name="Validate event log in transfer list" function="test_handoff_event_payload" />
</testsuite>
</testsuites>
diff --git a/tftf/tests/tests-neg_scenario.mk b/tftf/tests/tests-neg_scenario.mk
new file mode 100644
index 0000000..38093e6
--- /dev/null
+++ b/tftf/tests/tests-neg_scenario.mk
@@ -0,0 +1,13 @@
+#
+# Copyright (c) 2025, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+TESTS_SOURCES += $(addprefix tftf/tests/neg_scenario_tests/, \
+ test_fwu_image_size.c \
+)
+
+TESTS_SOURCES += plat/common/fwu_nvm_accessors.c \
+ plat/common/image_loader.c \
+ plat/arm/common/arm_fwu_io_storage.c
diff --git a/tftf/tests/tests-neg_scenario.xml b/tftf/tests/tests-neg_scenario.xml
new file mode 100644
index 0000000..bfec31c
--- /dev/null
+++ b/tftf/tests/tests-neg_scenario.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ Copyright (c) 2025, Arm Limited. All rights reserved.
+
+ SPDX-License-Identifier: BSD-3-Clause
+-->
+
+<testsuites>
+
+ <testsuite name="neg scenario test" description="Validate firmware update failure in a scenario where BL2 is corrupted, triggering a firmware update that fails due to a BL2U size corruption.">
+ <testcase name="FWU imageSize Failure" function="test_fwu_image_size" />
+ </testsuite>
+
+</testsuites>
diff --git a/tftf/tests/tests-realm-payload.xml b/tftf/tests/tests-realm-payload.xml
index 875c793..b9e83fe 100644
--- a/tftf/tests/tests-realm-payload.xml
+++ b/tftf/tests/tests-realm-payload.xml
@@ -158,5 +158,8 @@
<!-- Test case related to FEAT_BRBE -->
<testcase name="Test if BRBE realted registers are preserved "
function="host_realm_test_brbe_save_restore" />
+ <!-- Test case for EL3-RMM IDE KM Interface -->
+ <testcase name="Test for Root Port Key management interface"
+ function="host_realm_test_root_port_key_management" />
</testsuite>
</testsuites>