From patchwork Wed Jul 30 11:53:15 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harsimran Singh Tungal X-Patchwork-Id: 67724 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8CFDDC87FCB for ; Wed, 30 Jul 2025 11:54:00 +0000 (UTC) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.web11.33471.1753876430621959233 for ; Wed, 30 Jul 2025 04:53:50 -0700 Authentication-Results: mx.groups.io; dkim=none (message not signed); spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: harsimransingh.tungal@arm.com) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 4C2692681; Wed, 30 Jul 2025 04:53:42 -0700 (PDT) Received: from e132995.cambridge.arm.com (e132995.arm.com [10.1.25.25]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 743C23F66E; Wed, 30 Jul 2025 04:53:49 -0700 (PDT) From: Harsimran Singh Tungal To: meta-arm@lists.yoctoproject.org Cc: Harsimran Singh Tungal Subject: [PATCH 01/13] arm-bsp/trusted-firmware-m: corstone1000: Permit FWU calls in RSE-COMMS Date: Wed, 30 Jul 2025 12:53:15 +0100 Message-Id: <20250730115327.3671160-2-harsimransingh.tungal@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250730115327.3671160-1-harsimransingh.tungal@arm.com> References: <20250730115327.3671160-1-harsimransingh.tungal@arm.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Wed, 30 Jul 2025 11:54:00 -0000 X-Groupsio-URL: https://lists.yoctoproject.org/g/meta-arm/message/6638 Add support to permit FWU calls in RSE-COMMS Trusted-Firmware-M for Corstone-1000 This change is required to allow the transmission of PSA FWU related calls between Cortex A and Cortex M side on Corstone-1000. For every PSA call from A side, the RSE-COMMS at M side validates, if the call is allowed or not. Signed-off-by: Harsimran Singh Tungal --- ...one1000-Allow-FWU-calls-in-RSE-COMMS.patch | 60 +++++++++++++++++++ .../trusted-firmware-m-corstone1000.inc | 1 + 2 files changed, 61 insertions(+) create mode 100644 meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0024-Platform-corstone1000-Allow-FWU-calls-in-RSE-COMMS.patch diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0024-Platform-corstone1000-Allow-FWU-calls-in-RSE-COMMS.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0024-Platform-corstone1000-Allow-FWU-calls-in-RSE-COMMS.patch new file mode 100644 index 00000000..0c1b53c0 --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0024-Platform-corstone1000-Allow-FWU-calls-in-RSE-COMMS.patch @@ -0,0 +1,60 @@ +From 47593ccd1b2a2210c0860d1670005780836f120b Mon Sep 17 00:00:00 2001 +From: Harsimran Singh Tungal +Date: Mon, 18 Nov 2024 11:40:25 +0000 +Subject: [PATCH] Platform: corstone1000: Permit FWU calls in RSE-COMMS + +Allow FWU calls to be dispatched by the RSE-COMMS for Corstone-1000. +This change is required to allow the transmission of PSA FWU related +calls between Cortex A and Cortex M side on Corstone-1000. +For every PSA call from A side, the RSE-COMMS at M side validates, if the +call is allowed or not. + +Upstream-Status: Backport [b1123e3bf99000dd45992c0638c8f9ae7dba2ed8] +Signed-off-by: Harsimran Singh Tungal +--- + .../corstone1000/rse_comms_permissions_hal.c | 22 +++++++++++++++++++ + 1 file changed, 22 insertions(+) + +diff --git a/platform/ext/target/arm/corstone1000/rse_comms_permissions_hal.c b/platform/ext/target/arm/corstone1000/rse_comms_permissions_hal.c +index 59724bc94..58ade2026 100644 +--- a/platform/ext/target/arm/corstone1000/rse_comms_permissions_hal.c ++++ b/platform/ext/target/arm/corstone1000/rse_comms_permissions_hal.c +@@ -33,6 +33,9 @@ + #ifdef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE + #include "tfm_its_defs.h" + #endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */ ++#ifdef TFM_PARTITION_FIRMWARE_UPDATE ++#include "tfm_fwu_defs.h" ++#endif /* TFM_PARTITION_FIRMWARE_UPDATE */ + + #define INVALID_REGION_COUNTER_MAX 128 + #define INVALID_SERVICE_COUNTER_MAX 64 +@@ -165,6 +168,25 @@ enum tfm_plat_err_t comms_permissions_service_check(psa_handle_t handle, + case TFM_DPE_SERVICE_HANDLE: + return TFM_PLAT_ERR_SUCCESS; + #endif /* TFM_PARTITION_DPE */ ++ ++#ifdef TFM_PARTITION_FIRMWARE_UPDATE ++ case TFM_FIRMWARE_UPDATE_SERVICE_HANDLE: ++ switch(type) { ++ case TFM_FWU_START: ++ case TFM_FWU_WRITE: ++ case TFM_FWU_FINISH: ++ case TFM_FWU_CANCEL: ++ case TFM_FWU_INSTALL: ++ case TFM_FWU_CLEAN: ++ case TFM_FWU_REJECT: ++ case TFM_FWU_REQUEST_REBOOT: ++ case TFM_FWU_ACCEPT: ++ case TFM_FWU_QUERY: ++ return TFM_PLAT_ERR_SUCCESS; ++ default: ++ goto out_err; ++ } ++#endif /* TFM_PARTITION_FIRMWARE_UPDATE */ + default: + goto out_err; + } +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-corstone1000.inc b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-corstone1000.inc index e3a07b72..f49a4271 100644 --- a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-corstone1000.inc +++ b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-corstone1000.inc @@ -42,6 +42,7 @@ SRC_URI:append:corstone1000 = " \ file://0021-platform-corstone1000-add-unique-guid-for-mps3.patch \ file://0022-CC312-alignment-of-cc312-differences.patch \ file://0023-Platform-CS1000-Remove-duplicate-configuration-parameters.patch \ + file://0024-Platform-corstone1000-Allow-FWU-calls-in-RSE-COMMS.patch \ " FILESEXTRAPATHS:prepend:corstone1000-mps3 := "${THISDIR}/files/corstone1000/psa-adac:" From patchwork Wed Jul 30 11:53:16 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Harsimran Singh Tungal X-Patchwork-Id: 67733 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id B21DEC87FCE for ; Wed, 30 Jul 2025 11:54:00 +0000 (UTC) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.web10.33467.1753876432088370931 for ; Wed, 30 Jul 2025 04:53:52 -0700 Authentication-Results: mx.groups.io; dkim=none (message not signed); spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: harsimransingh.tungal@arm.com) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id A16D32936; Wed, 30 Jul 2025 04:53:43 -0700 (PDT) Received: from e132995.cambridge.arm.com (e132995.arm.com [10.1.25.25]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id B39FC3F66E; Wed, 30 Jul 2025 04:53:50 -0700 (PDT) From: Harsimran Singh Tungal To: meta-arm@lists.yoctoproject.org Cc: Ali Can Ozaslan , Harsimran Singh Tungal Subject: [PATCH 02/13] arm-bsp/trusted-firmware-m: corstone1000: Add Bootloader Abstraction Layer (BAL) support Date: Wed, 30 Jul 2025 12:53:16 +0100 Message-Id: <20250730115327.3671160-3-harsimransingh.tungal@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250730115327.3671160-1-harsimransingh.tungal@arm.com> References: <20250730115327.3671160-1-harsimransingh.tungal@arm.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Wed, 30 Jul 2025 11:54:00 -0000 X-Groupsio-URL: https://lists.yoctoproject.org/g/meta-arm/message/6639 From: Ali Can Ozaslan Introduce Bootloader Abstraction Layer (BAL) support for Corstone-1000 to enable flexible integration of firmware update including partial capsule update. This change includes: - Enable the firmware update partition for Corstone-1000 and create placeholder bootloader abstraction layer for Corstone-1000. - Change the insertion logic of TFM_FWU_BOOTLOADER_LIB to select a new platform-specific bootloader abstraction layer. - Use the necessary flags to use the service and resolve any linker issues that may arise. - Migration of capsule update logic to a new BAL module under `platform/ext/target/corstone1000/bootloader/mcuboot/`. - Implementation of BAL APIs in `tfm_mcuboot_fwu.c` as per the PSA FWU state machine. - Removal of `uefi_capsule_parser.c` and `uefi_capsule_parser.h` as capsule parsing is done in U-Boot. - Enhancement of `uefi_fmp.c` to handle FMP metadata for multiple images. - Update of `provisioning.c` and `security_cnt_bl2.c` to handle new BAL return values. - Addition of `fwu_config.h.in` with default FWU configuration. - Metadata layout changes to include size and image GUIDs for U-Boot compatibility during FWU Accept flow. Signed-off-by: Harsimran Singh Tungal Signed-off-by: Ali Can Ozaslan --- ...m-specific-TFM_FWU_BOOTLOADER_LIB-se.patch | 73 + ...Platform-CS1000-Enable-FWU-partition.patch | 30 + ...e1000-Implement-Bootloader-Abstracti.patch | 5033 +++++++++++++++++ .../trusted-firmware-m-corstone1000.inc | 3 + 4 files changed, 5139 insertions(+) create mode 100644 meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0025-FWU-Make-platform-specific-TFM_FWU_BOOTLOADER_LIB-se.patch create mode 100644 meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0026-Platform-CS1000-Enable-FWU-partition.patch create mode 100644 meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0027-Platform-Corstone1000-Implement-Bootloader-Abstracti.patch diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0025-FWU-Make-platform-specific-TFM_FWU_BOOTLOADER_LIB-se.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0025-FWU-Make-platform-specific-TFM_FWU_BOOTLOADER_LIB-se.patch new file mode 100644 index 00000000..5c503141 --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0025-FWU-Make-platform-specific-TFM_FWU_BOOTLOADER_LIB-se.patch @@ -0,0 +1,73 @@ +From 5afc6fde140e4033c4b69450daed42c6a3dea2bc Mon Sep 17 00:00:00 2001 +From: Ali Can Ozaslan +Date: Wed, 30 Oct 2024 09:54:49 +0000 +Subject: [PATCH] FWU: Make platform specific TFM_FWU_BOOTLOADER_LIB selectable + to add + +Prepare the environment where partition firmware update can be +enabled and platform specific bootloader configuration can be used. + +FWU implementation provides an abstraction for the bootloader. +This bootloader abstraction layer is implemented for MCUBoot. +It can be used after making changes that can handle platform +specific behaviors. But the implementation limits it. + +When TFM_PARTITION_FIRMWARE_UPDATE is enabled, the configuration +becomes invalid. Therefore, the invalid configuration is limited +to the case where TFM_FWU_BOOTLOADER_LIB is used for MCUboot. +This makes the configuration valid when a platform specific +configuration is used. + +TFM_FWU_BOOTLOADER_LIB can only be added from a subdirectory, which +prevents the use of platform-specific bootloader configurations. +The logic has been changed to allow the use of platform-specific +bootloader configurations. + +Signed-off-by: Ali Can Ozaslan + +Upstream-Status: Backport [3357369d7b878b8e8ad9515f821ac2226ec7fb18] +--- + config/check_config.cmake | 2 +- + secure_fw/partitions/firmware_update/CMakeLists.txt | 12 ++++++++---- + 2 files changed, 9 insertions(+), 5 deletions(-) + +diff --git a/config/check_config.cmake b/config/check_config.cmake +index 1039b22f9..d1929f6da 100644 +--- a/config/check_config.cmake ++++ b/config/check_config.cmake +@@ -63,7 +63,7 @@ tfm_invalid_config(TFM_NS_NV_COUNTER_AMOUNT GREATER 3) + + tfm_invalid_config(NOT PLATFORM_HAS_FIRMWARE_UPDATE_SUPPORT AND TFM_PARTITION_FIRMWARE_UPDATE) + tfm_invalid_config(TFM_PARTITION_FIRMWARE_UPDATE AND NOT TFM_PARTITION_PLATFORM) +-tfm_invalid_config((MCUBOOT_UPGRADE_STRATEGY STREQUAL "DIRECT_XIP" OR MCUBOOT_UPGRADE_STRATEGY STREQUAL "RAM_LOAD") AND TFM_PARTITION_FIRMWARE_UPDATE) ++tfm_invalid_config((MCUBOOT_UPGRADE_STRATEGY STREQUAL "DIRECT_XIP" OR MCUBOOT_UPGRADE_STRATEGY STREQUAL "RAM_LOAD") AND TFM_PARTITION_FIRMWARE_UPDATE AND TFM_FWU_BOOTLOADER_LIB STREQUAL "mcuboot") + tfm_invalid_config(TFM_PARTITION_FIRMWARE_UPDATE AND NOT MCUBOOT_DATA_SHARING) + + ####################### Protected Storage Partition ############################### +diff --git a/secure_fw/partitions/firmware_update/CMakeLists.txt b/secure_fw/partitions/firmware_update/CMakeLists.txt +index b249597b9..ecb90e0f0 100644 +--- a/secure_fw/partitions/firmware_update/CMakeLists.txt ++++ b/secure_fw/partitions/firmware_update/CMakeLists.txt +@@ -37,11 +37,15 @@ target_sources(tfm_partitions + ${CMAKE_BINARY_DIR}/generated/secure_fw/partitions/firmware_update/auto_generated/load_info_tfm_firmware_update.c + ) + +-# The bootloader specific configuration. +-if ((NOT TFM_FWU_BOOTLOADER_LIB) OR (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/bootloader/${TFM_FWU_BOOTLOADER_LIB})) +- message(FATAL_ERROR "TFM_FWU_BOOTLOADER_LIB invalid") ++# Use platform specific bootloader configuration if present. ++if ((TFM_FWU_BOOTLOADER_LIB) AND (EXISTS ${TFM_FWU_BOOTLOADER_LIB})) ++ add_subdirectory(${TFM_FWU_BOOTLOADER_LIB} ${CMAKE_CURRENT_BINARY_DIR}/${TFM_FWU_BOOTLOADER_LIB}) ++else() ++ if ((NOT TFM_FWU_BOOTLOADER_LIB) OR (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/bootloader/${TFM_FWU_BOOTLOADER_LIB})) ++ message(FATAL_ERROR "TFM_FWU_BOOTLOADER_LIB invalid") ++ endif() ++ add_subdirectory(bootloader/${TFM_FWU_BOOTLOADER_LIB}) + endif() +-add_subdirectory(bootloader/${TFM_FWU_BOOTLOADER_LIB}) + + target_link_libraries(tfm_psa_rot_partition_fwu + PRIVATE +-- +2.34.1 + diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0026-Platform-CS1000-Enable-FWU-partition.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0026-Platform-CS1000-Enable-FWU-partition.patch new file mode 100644 index 00000000..c6b97733 --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0026-Platform-CS1000-Enable-FWU-partition.patch @@ -0,0 +1,30 @@ +From 1f8eb5887f3de167ac68c92b5b77efc51308603c Mon Sep 17 00:00:00 2001 +From: Ali Can Ozaslan +Date: Tue, 15 Oct 2024 12:50:16 +0000 +Subject: [PATCH] Platform: Corstone1000: Enable FWU partition + +Enable firmware update partition for Corstone-1000 platform. + +Increase the necessary flags to enable firmware update partition. +Set TFM_FWU_BOOTLOADER_LIB to use Corstone-1000 specific bootloader +configuration. Fix linker issues caused by enablement. + +Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TF-M/trusted-firmware-m/+/39515] +Signed-off-by: Ali Can Ozaslan + +--- +diff --git a/platform/ext/target/arm/corstone1000/config.cmake b/platform/ext/target/arm/corstone1000/config.cmake +index 6a805a122..1ba43a006 100644 +--- a/platform/ext/target/arm/corstone1000/config.cmake ++++ b/platform/ext/target/arm/corstone1000/config.cmake +@@ -56,6 +56,10 @@ set(TFM_PARTITION_CRYPTO ON CACHE BOOL "Enable Cryp + set(TFM_PARTITION_INITIAL_ATTESTATION ON CACHE BOOL "Enable Initial Attestation partition") + set(TFM_PARTITION_INTERNAL_TRUSTED_STORAGE ON CACHE BOOL "Enable Internal Trusted Storage partition") + ++set(TFM_PARTITION_FIRMWARE_UPDATE ON CACHE BOOL "Enable firmware update partition") ++set(PLATFORM_HAS_FIRMWARE_UPDATE_SUPPORT ON CACHE BOOL "Wheter the platform has firmware update support") ++set(MCUBOOT_DATA_SHARING ON CACHE BOOL "Enable Data Sharing") ++set(TFM_FWU_BOOTLOADER_LIB "${CMAKE_CURRENT_LIST_DIR}/bootloader/mcuboot" CACHE STRING "Bootloader configure file for Firmware Update partition") + + if (${CMAKE_BUILD_TYPE} STREQUAL Debug OR ${CMAKE_BUILD_TYPE} STREQUAL RelWithDebInfo) + set(ENABLE_FWU_AGENT_DEBUG_LOGS TRUE CACHE BOOL "Enable Firmware update agent debug logs.") diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0027-Platform-Corstone1000-Implement-Bootloader-Abstracti.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0027-Platform-Corstone1000-Implement-Bootloader-Abstracti.patch new file mode 100644 index 00000000..da275a19 --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0027-Platform-Corstone1000-Implement-Bootloader-Abstracti.patch @@ -0,0 +1,5033 @@ +From 929ac4fdf22bdc84f7363be3f9604c586800e2c1 Mon Sep 17 00:00:00 2001 +From: Ali Can Ozaslan +Date: Tue, 15 Oct 2024 12:50:16 +0000 +Subject: [PATCH 5/6] Platform: Corstone1000: Implement Bootloader Abstraction + Layer + +This commit introduces the Bootloader Abstraction Layer (BAL) for +Corstone-1000. The following changes are made: + +1. Move the previous Capsule Update implementation for Corstone-1000 +from "fwu_update_agent/" to "bootloader/mcuboot/". This serves as +the placeholder for the Bootloader Abstraction Layer (BAL). + +2. Move content of "fwu_agent.c" to "tfm_mcuboot_fwu.c". This source +file is the actual implementation of bootloader abstraction layer. +Adapt the previous Capsule Update implementation in +"tfm_mcuboot_fwu.c "to align with the PSA Firmware Update (FWU) +state machine. + +3. Remove "uefi_capsule_parser.c" and "uefi_capsule_parser.h". +The UEFI capsule header parsing is now done in U-Boot. + +4. Modify "uefi_fmp.c" to support modification of FMP information +for multiple images. In the previous capsule update implementation, +this file only supports updates FMP information for single +Corstone-1000 image. + +5. New functions for capsule update implementation in bootloader +abstraction layer supports different return values. Update checks of +return values in "provisioning.c" and "security_cnt_bl2.c", as these +files use functions defined in bootloader abstraction layer. + +6. Update "config.cmake" and "CMakeLists.txt" to support compilation +and configuration of bootloader abstraction layer for Corstone-1000. + +7. Create FWU configuration file "fwu_config.h.in" for Corstone-1000 +with default configuration values. + +8. FWU implementation in U-Boot expects to have metadata size field +updated in metadata. Store the metadata size in metadata, so U-Boot +can use it. + +9. Update metadata for FWU accept. Store image GUIDs and bank state +in metadata. This is used by the U-Boot to decide the trial state +and accept the images based on GUIDs. + +10. Add rollback version check. Bootloader abstraction layer refuses +to update the lower version firmware than the current version. + +11. Add support for FVP and MPS3 image GUID's. + +12. Add support for EFI ESRT v1 and code refactoring + +Add support to configure the ESRT entries during +tfm_fwu_query() function call. The ESRT image component +is defined to represent the ESRT image. The tfm_fwu_query() +function returns the ESRT data requested by FWU client in +the psa_fwu_impl_info_t structure object. +The psa_fwu_impl_info_t structure object is used to store +the ESRT entries for all the images. This structure object +is declared in psa_fwu_component_info_t structure which +stores all the data requested by update client via +tfm_fwu_query(). + +For Corstone-1000, the TFM_FWU_MAX_DIGEST_SIZE represents +the maximum size needed to store the ESRT entries for all +the images in a bank. +ESRT details can be found here: +https://uefi.org/specs/UEFI/2.9_A/23_Firmware_Update_and_Reporting.html#efi-system-resource-table + +13. Define max payload size and enable trial state + +14. Implement Partial Capsule Update Support +Introduces support for partial capsule updates +with the following changes: +-> Copy unchanged images from the other bank to the updated + bank to ensure consistency across banks. +-> Add image offsets and sizes for each payload to facilitate + accurate image management during updates. + +Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TF-M/trusted-firmware-m/+/39516/1] +Signed-off-by: Harsimran Singh Tungal +Signed-off-by: Ali Can Ozaslan +--- + .../target/arm/corstone1000/CMakeLists.txt | 36 +- + .../arm/corstone1000/bl1/provisioning.c | 4 +- + .../arm/corstone1000/bl2/security_cnt_bl2.c | 6 +- + .../arm/corstone1000/bootloader/fwu_agent.h | 123 + + .../corstone1000/bootloader/fwu_config.h.in | 58 + + .../bootloader/mcuboot/CMakeLists.txt | 52 + + .../bootloader/mcuboot/tfm_mcuboot_fwu.c | 2345 +++++++++++++++++ + .../mcuboot}/uefi_fmp.c | 111 +- + .../tfm_bootloader_fwu_abstraction.h | 189 ++ + .../uefi_fmp.h | 7 +- + .../ext/target/arm/corstone1000/config.cmake | 5 +- + .../corstone1000/fw_update_agent/fwu_agent.c | 1350 ---------- + .../corstone1000/fw_update_agent/fwu_agent.h | 73 - + .../fw_update_agent/uefi_capsule_parser.c | 175 -- + .../fw_update_agent/uefi_capsule_parser.h | 33 - + .../arm/corstone1000/partition/flash_layout.h | 14 +- + 16 files changed, 2882 insertions(+), 1699 deletions(-) + create mode 100644 platform/ext/target/arm/corstone1000/bootloader/fwu_agent.h + create mode 100644 platform/ext/target/arm/corstone1000/bootloader/fwu_config.h.in + create mode 100644 platform/ext/target/arm/corstone1000/bootloader/mcuboot/CMakeLists.txt + create mode 100644 platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c + rename platform/ext/target/arm/corstone1000/{fw_update_agent => bootloader/mcuboot}/uefi_fmp.c (66%) + create mode 100644 platform/ext/target/arm/corstone1000/bootloader/tfm_bootloader_fwu_abstraction.h + rename platform/ext/target/arm/corstone1000/{fw_update_agent => bootloader}/uefi_fmp.h (89%) + delete mode 100644 platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c + delete mode 100644 platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.h + delete mode 100644 platform/ext/target/arm/corstone1000/fw_update_agent/uefi_capsule_parser.c + delete mode 100644 platform/ext/target/arm/corstone1000/fw_update_agent/uefi_capsule_parser.h + +diff --git a/platform/ext/target/arm/corstone1000/CMakeLists.txt b/platform/ext/target/arm/corstone1000/CMakeLists.txt +index 3323cb8ce..e49dca49c 100644 +--- a/platform/ext/target/arm/corstone1000/CMakeLists.txt ++++ b/platform/ext/target/arm/corstone1000/CMakeLists.txt +@@ -1,5 +1,5 @@ + #------------------------------------------------------------------------------- +-# Copyright (c) 2020-2024, Arm Limited. All rights reserved. ++# Copyright (c) 2020-2025, Arm Limited. All rights reserved. + # Copyright (c) 2022 Cypress Semiconductor Corporation (an Infineon company) + # or an affiliate of Cypress Semiconductor Corporation. All rights reserved. + # +@@ -115,7 +115,7 @@ target_include_directories(platform_s + ${PLATFORM_DIR}/ext/target/arm/drivers/usart/pl011 + INTERFACE + cc312 +- fw_update_agent ++ bootloader + soft_crc + io + partition +@@ -133,9 +133,8 @@ target_sources(platform_s + Native_Driver/watchdog.c + Native_Driver/arm_watchdog_drv.c + $<$:${CMAKE_CURRENT_SOURCE_DIR}/services/src/tfm_platform_system.c> +- fw_update_agent/uefi_capsule_parser.c +- fw_update_agent/fwu_agent.c +- fw_update_agent/uefi_fmp.c ++ bootloader/mcuboot/tfm_mcuboot_fwu.c ++ bootloader/mcuboot/uefi_fmp.c + soft_crc/soft_crc.c + io/io_block.c + io/io_flash.c +@@ -201,9 +200,8 @@ target_sources(platform_bl1_1 + ./Native_Driver/watchdog.c + ./bl1/boot_hal_bl1_1.c + ./bl1/provisioning.c +- ./fw_update_agent/fwu_agent.c +- ./fw_update_agent/uefi_capsule_parser.c +- ./fw_update_agent/uefi_fmp.c ++ ./bootloader/mcuboot/tfm_mcuboot_fwu.c ++ ./bootloader/mcuboot/uefi_fmp.c + ./soft_crc/soft_crc.c + $<$>:${PLATFORM_DIR}/ext/accelerator/cc312/otp_cc312.c> + $<$>:${CMAKE_CURRENT_SOURCE_DIR}/bl1/cc312_rom_crypto.c> +@@ -233,7 +231,7 @@ target_include_directories(platform_bl1_1_interface + ./Device/Config + ./Native_Driver + ./CMSIS_Driver/Config +- ./fw_update_agent ++ ./bootloader + ./soft_crc + ${PLATFORM_DIR}/ext/target/arm/drivers/flash/cfi + ${PLATFORM_DIR}/ext/target/arm/drivers/flash/common +@@ -245,6 +243,7 @@ target_include_directories(platform_bl1_1_interface + ${PLATFORM_DIR}/ext/target/arm/drivers/usart/pl011 + $<$:${CMAKE_SOURCE_DIR}/platform/ext/accelerator/interface> + ${PLATFORM_DIR}/ext/accelerator/cc312/ ++ ${CMAKE_SOURCE_DIR}/lib/fih/inc/ + ) + + target_link_libraries(platform_bl1_1 +@@ -252,6 +251,11 @@ target_link_libraries(platform_bl1_1 + $<$>:cc312_rom> + ) + ++target_include_directories(platform_bl1_1 ++ PRIVATE ++ ${CMAKE_SOURCE_DIR}/interface/include # for psa/error.h ++) ++ + target_sources(platform_bl1_2 + PRIVATE + ./bl1/boot_hal_bl1_2.c +@@ -276,7 +280,7 @@ target_include_directories(platform_bl1_2 + ./Device/Config + ./Native_Driver + ./CMSIS_Driver/Config +- ./fw_update_agent ++ ./bootloader + ./soft_crc + ${PLATFORM_DIR}/ext/target/arm/drivers/flash/common + ${PLATFORM_DIR}/ext/target/arm/drivers/flash/cfi +@@ -285,6 +289,7 @@ target_include_directories(platform_bl1_2 + ${PLATFORM_DIR}/ext/target/arm/drivers/flash/n25q256a/ + ${PLATFORM_DIR}/ext/target/arm/drivers/flash/sst26vf064b/ + ${PLATFORM_DIR}/ext/accelerator/cc312/ ++ ${CMAKE_SOURCE_DIR}/interface/include # for psa/error.h + ) + + #========================= Platform BL2 =======================================# +@@ -301,7 +306,7 @@ target_sources(platform_bl2 + Native_Driver/watchdog.c + Native_Driver/arm_watchdog_drv.c + fip_parser/fip_parser.c +- fw_update_agent/fwu_agent.c ++ bootloader/mcuboot/tfm_mcuboot_fwu.c + bl2/security_cnt_bl2.c + $<$>:${PLATFORM_DIR}/ext/accelerator/cc312/otp_cc312.c> + io/io_block.c +@@ -358,6 +363,12 @@ target_compile_definitions(bl2 + $<$:CRYPTO_HW_ACCELERATOR_OTP_PROVISIONING> + $<$:PLATFORM_PSA_ADAC_SECURE_DEBUG> + ) ++ ++target_include_directories(bl2 ++ PRIVATE ++ ${CMAKE_SOURCE_DIR}/interface/include # for psa/error.h ++) ++ + target_compile_definitions(bootutil + PRIVATE + MULTIPLE_EXECUTABLE_RAM_REGIONS +@@ -369,7 +380,7 @@ target_include_directories(platform_bl2 + Device/Include + fip_parser + Native_Driver +- fw_update_agent ++ bootloader + soft_crc + io + ${PLATFORM_DIR}/ext/target/arm/drivers/flash/common +@@ -388,6 +399,7 @@ target_include_directories(platform_bl2 + ${MCUBOOT_PATH}/boot/bootutil/include # for fault_injection_hardening.h only + ${CMAKE_BINARY_DIR}/bl2/ext/mcuboot # for mcuboot_config.h only + $ ++ ${CMAKE_SOURCE_DIR}/interface/include # for psa/error.h + ) + + #========================= ns_agent_mailbox ===================================# +diff --git a/platform/ext/target/arm/corstone1000/bl1/provisioning.c b/platform/ext/target/arm/corstone1000/bl1/provisioning.c +index cc42bc0a1..1afa9d542 100644 +--- a/platform/ext/target/arm/corstone1000/bl1/provisioning.c ++++ b/platform/ext/target/arm/corstone1000/bl1/provisioning.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2021-2023, Arm Limited. All rights reserved. ++ * Copyright (c) 2021-2023, 2025, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * +@@ -100,7 +100,7 @@ enum tfm_plat_err_t provision_assembly_and_test(void) + } + + err = fwu_metadata_provision(); +- if (err != FWU_AGENT_SUCCESS) { ++ if (err != PSA_SUCCESS) { + return 1; + } + +diff --git a/platform/ext/target/arm/corstone1000/bl2/security_cnt_bl2.c b/platform/ext/target/arm/corstone1000/bl2/security_cnt_bl2.c +index da9f74e1c..c74c67d89 100644 +--- a/platform/ext/target/arm/corstone1000/bl2/security_cnt_bl2.c ++++ b/platform/ext/target/arm/corstone1000/bl2/security_cnt_bl2.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2019-2021, Arm Limited. All rights reserved. ++ * Copyright (c) 2019-2021, 2025, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * +@@ -76,7 +76,7 @@ int32_t boot_nv_security_counter_update(uint32_t image_id, + { + enum tfm_nv_counter_t nv_counter; + enum tfm_plat_err_t err; +- enum fwu_agent_error_t fwu_err; ++ psa_status_t fwu_err; + + nv_counter = get_nv_counter_from_image_id(image_id); + if (nv_counter >= TFM_BOOT_NV_COUNTER_MAX) { +@@ -100,7 +100,7 @@ int32_t boot_nv_security_counter_update(uint32_t image_id, + return -1; + } + +- if (fwu_err != FWU_AGENT_SUCCESS) { ++ if (fwu_err != PSA_SUCCESS) { + return -1; + } + +diff --git a/platform/ext/target/arm/corstone1000/bootloader/fwu_agent.h b/platform/ext/target/arm/corstone1000/bootloader/fwu_agent.h +new file mode 100644 +index 000000000..6b3a38b64 +--- /dev/null ++++ b/platform/ext/target/arm/corstone1000/bootloader/fwu_agent.h +@@ -0,0 +1,123 @@ ++/* ++ * Copyright (c) 2021-2023, 2025, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ * ++ */ ++ ++#ifndef FWU_AGENT_H ++#define FWU_AGENT_H ++ ++#include "psa/error.h" ++#include "../fip_parser/external/uuid.h" ++ ++#define ENABLE_FWU_AGENT_DEBUG_LOGS ++#ifdef ENABLE_FWU_AGENT_DEBUG_LOGS ++ #include ++ #define FWU_LOG_MSG(f_, ...) printf((f_), ##__VA_ARGS__) ++#else ++ #define FWU_LOG_MSG(f_, ...) ++#endif ++ ++#define FWU_ASSERT(_c_) \ ++ if (!(_c_)) { \ ++ FWU_LOG_MSG("%s:%d assert hit\n\r", __func__, __LINE__); \ ++ while(1) {}; \ ++ } \ ++ ++ ++/* Version used for the very first image of the device. */ ++#define FWU_IMAGE_INITIAL_VERSION 0 ++ ++#define EFI_SYSTEM_RESOURCE_TABLE_FIRMWARE_RESOURCE_VERSION 1 ++typedef struct { ++ uint32_t signature; ++ uint32_t header_size; ++ uint32_t fw_version; ++ uint32_t lowest_supported_version; ++} __packed fmp_payload_header_t; ++ ++typedef struct { ++ fmp_payload_header_t fmp_hdr; ++ size_t fmp_hdr_size_recvd; ++ size_t image_size_recvd; ++} __packed fmp_header_image_info_t; ++ ++/* Store image information common for both the banks */ ++typedef struct { ++ /* Total size of the image */ ++ uint32_t image_size; ++ ++ /* Offset of image within a bank */ ++ uint32_t image_offset; ++ ++ /* Image GUID */ ++ struct efi_guid image_guid; ++} __packed fwu_bank_image_info_t; ++ ++/* ESRT v1 */ ++struct __attribute__((__packed__)) efi_system_resource_entry { ++ struct efi_guid fw_class; ++ uint32_t fw_type; ++ uint32_t fw_version; ++ uint32_t lowest_supported_fw_version; ++ uint32_t capsule_flags; ++ uint32_t last_attempt_version; ++ uint32_t last_attempt_status; ++}; ++ ++struct __attribute__((__packed__)) efi_system_resource_table { ++ uint32_t fw_resource_count; ++ uint32_t fw_resource_count_max; ++ uint64_t fw_resource_version; ++ struct efi_system_resource_entry entries[]; ++}; ++ ++psa_status_t fwu_metadata_provision(void); ++psa_status_t fwu_metadata_init(void); ++ ++/* host to secure enclave: ++ * firwmare update image is sent accross ++ */ ++psa_status_t corstone1000_fwu_flash_image(void); ++ ++/* host to secure enclave: ++ * host responds with this api to acknowledge its successful ++ * boot. ++ */ ++psa_status_t corstone1000_fwu_host_ack(void); ++ ++void bl1_get_active_bl2_image(uint32_t *bank_offset); ++uint8_t bl2_get_boot_bank(void); ++ ++/* When in trial state, start the timer for host to respond. ++ * Diable timer when host responds back either by calling ++ * corstone1000_fwu_accept_image or corstone1000_fwu_select_previous. ++ * Otherwise, resets the system. ++ */ ++void host_acknowledgement_timer_to_reset(void); ++ ++enum fwu_nv_counter_index_t { ++ FWU_BL2_NV_COUNTER = 0, ++ FWU_TFM_NV_COUNTER, ++ FWU_TFA_NV_COUNTER, ++ FWU_MAX_NV_COUNTER_INDEX = FWU_TFA_NV_COUNTER ++}; ++ ++/* stage nv counter into private metadata section of the flash. ++ * staged nv counters are written to the otp when firmware update ++ * is successful ++ * the function assumes that the api is called in the boot loading ++ * stage ++ */ ++psa_status_t fwu_stage_nv_counter(enum fwu_nv_counter_index_t index, ++ uint32_t img_security_cnt); ++ ++/* ++ * Check if both metadata replica is valid by calculating and comparing crc32. ++ * If one of the replica is corrupted then update it with the valid replica. ++ * If both of the replicas are corrupted then the correction is not possible. ++ */ ++psa_status_t fwu_metadata_check_and_correct_integrity(void); ++ ++#endif /* FWU_AGENT_H */ +diff --git a/platform/ext/target/arm/corstone1000/bootloader/fwu_config.h.in b/platform/ext/target/arm/corstone1000/bootloader/fwu_config.h.in +new file mode 100644 +index 000000000..79e310e29 +--- /dev/null ++++ b/platform/ext/target/arm/corstone1000/bootloader/fwu_config.h.in +@@ -0,0 +1,58 @@ ++/* ++ * Copyright (c) 2025, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ * ++ */ ++ ++#ifndef __FWU_CONFIG_H__ ++#define __FWU_CONFIG_H__ ++ ++/* This file contains device specific configurations in FWU partition based ++ * on MCUboot. ++ */ ++ ++/* Components of the device. When porting a specific bootloader to FWU partition, ++ * the bootloader specific image types can be defined here. ++ */ ++#define FWU_COMPONENT_NUMBER 6 ++ ++/* Maximum number of FWU Images ++ * FWU_COMPONENT_NUMBER takes into account the fact our image index is starting from 1 and also we have an ESRT image ++ */ ++#define FWU_IMAGE_COUNT (FWU_COMPONENT_NUMBER - 2) ++ ++/* sizeof(struct efi_system_resource_entry) ++ * Size of one ESRT v1 Image entry structure object ++ */ ++#define ESRT_IMAGE_ENTRY_SIZE 40 ++ ++/* sizeof(struct efi_system_resource_table) - sizeof(struct efi_system_resource_entry) ++ * Size of remaining fields of ESRT v1 t ++ */ ++#define ESRT_REMAINING_FIELDS_SIZE 16 ++ ++#if FWU_COMPONENT_NUMBER > 1 ++#define FWU_COMPONENT_ID_SECURE 0x00U ++#define FWU_COMPONENT_ID_NONSECURE 0x01U ++#else ++#define FWU_COMPONENT_ID_FULL 0x00U ++#endif ++ ++/* The maximum size of an image digest in bytes. This is dependent ++ * on the hash algorithm used. ++ */ ++#define TFM_FWU_MAX_DIGEST_SIZE ((FWU_IMAGE_COUNT * ESRT_IMAGE_ENTRY_SIZE) + ESRT_REMAINING_FIELDS_SIZE) ++ ++/* The maximum permitted size for block in psa_fwu_write(), in bytes. */ ++#define TFM_CONFIG_FWU_MAX_WRITE_SIZE @TFM_CONFIG_FWU_MAX_WRITE_SIZE@ ++ ++/* The maximum permitted size for manifest in psa_fwu_start(), in bytes. */ ++#define TFM_CONFIG_FWU_MAX_MANIFEST_SIZE @TFM_CONFIG_FWU_MAX_MANIFEST_SIZE@ ++ ++/* Whether TRIAL component state is supported or not. This is device specific ++ * configuration. ++ */ ++#cmakedefine FWU_SUPPORT_TRIAL_STATE ++ ++#endif /* __FWU_CONFIG_H__ */ +diff --git a/platform/ext/target/arm/corstone1000/bootloader/mcuboot/CMakeLists.txt b/platform/ext/target/arm/corstone1000/bootloader/mcuboot/CMakeLists.txt +new file mode 100644 +index 000000000..7d57a57c7 +--- /dev/null ++++ b/platform/ext/target/arm/corstone1000/bootloader/mcuboot/CMakeLists.txt +@@ -0,0 +1,52 @@ ++#------------------------------------------------------------------------------- ++# Copyright (c) 2021-2022, 2025, Arm Limited. All rights reserved. ++# ++# SPDX-License-Identifier: BSD-3-Clause ++# ++#------------------------------------------------------------------------------- ++cmake_minimum_required(VERSION 3.21) ++ ++add_library(tfm_fwu_mcuboot_util INTERFACE) ++ ++target_sources(tfm_fwu_mcuboot_util ++ INTERFACE ++ ${MCUBOOT_PATH}/boot/bootutil/src/bootutil_public.c ++ ${MCUBOOT_PATH}/boot/bootutil/src/tlv.c ++ ${CMAKE_SOURCE_DIR}/bl2/src/flash_map.c ++ ${CMAKE_SOURCE_DIR}/bl2/ext/mcuboot/flash_map_extended.c ++ ./tfm_mcuboot_fwu.c ++ ./uefi_fmp.c ++ $<$:${CMAKE_SOURCE_DIR}/bl2/src/default_flash_map.c> ++) ++ ++target_include_directories(tfm_fwu_mcuboot_util ++ INTERFACE ++ ${CMAKE_BINARY_DIR}/bl2/ext/mcuboot ++ ${CMAKE_SOURCE_DIR}/bl2/ext/mcuboot/include ++ ${MCUBOOT_PATH}/boot/bootutil/include ++ ${MCUBOOT_PATH}/boot/bootutil/src ++ ${CMAKE_CURRENT_SOURCE_DIR}/../ ++ ${MBEDCRYPTO_PATH}/include ++) ++ ++target_link_libraries(tfm_fwu_mcuboot_util ++ INTERFACE ++ platform_region_defs ++) ++ ++target_link_libraries(tfm_psa_rot_partition_fwu ++ PRIVATE ++ tfm_fwu_mcuboot_util ++) ++ ++configure_file(${CMAKE_SOURCE_DIR}/platform/ext/target/arm/corstone1000/bootloader/fwu_config.h.in ++ ${CMAKE_BINARY_DIR}/platform/ext/target/arm/corstone1000/bootloader/fwu_config.h ++ @ONLY) ++set(FWU_DEVICE_CONFIG_FILE "${CMAKE_BINARY_DIR}/platform/ext/target/arm/corstone1000/bootloader/fwu_config.h") ++ ++target_compile_definitions(tfm_psa_rot_partition_fwu ++ PRIVATE ++ MCUBOOT_${MCUBOOT_UPGRADE_STRATEGY} ++ $<$:MCUBOOT_DIRECT_XIP_REVERT> ++ FWU_DEVICE_CONFIG_FILE="${FWU_DEVICE_CONFIG_FILE}" ++) +diff --git a/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c b/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c +new file mode 100644 +index 000000000..32fe44516 +--- /dev/null ++++ b/platform/ext/target/arm/corstone1000/bootloader/mcuboot/tfm_mcuboot_fwu.c +@@ -0,0 +1,2345 @@ ++/* ++ * Copyright (c) 2021-2025, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ * ++ */ ++#include ++#include "psa/crypto.h" ++#include "psa/error.h" ++#include "tfm_bootloader_fwu_abstraction.h" ++ ++#include ++#include ++#include "fwu_agent.h" ++#include "Driver_Flash.h" ++#include "flash_layout.h" ++#include "fip_parser/external/uuid.h" ++#include "region_defs.h" ++#include "flash_common.h" ++#include "platform_base_address.h" ++#include "platform_description.h" ++#include "tfm_plat_nv_counters.h" ++#include "tfm_plat_defs.h" ++#include "uefi_fmp.h" ++#include "uart_stdout.h" ++#include "soft_crc.h" ++#ifndef BL1_BUILD ++#include "partition.h" ++#include "platform.h" ++#endif ++ ++#define FWU_METADATA_VERSION 2 ++#define FWU_FW_STORE_DESC_OFFSET 0x20 ++#define NR_OF_MAX_FW_BANKS 4 ++ ++/* Size of a chunk transferred at once from one bank to another ++ * This is used when bank consistency is maintained during partial capsule update ++ */ ++#define FLASH_CHUNK_SIZE 512 ++ ++/* Possible states of the bank. ++ * Naming convention here matches the implementation in U-Boot ++ */ ++#define FWU_BANK_INVALID (uint8_t)0xFF ++#define FWU_BANK_VALID (uint8_t)0xFE ++#define FWU_BANK_ACCEPTED (uint8_t)0xFC ++ ++/* The component number for the ESRT image. ++ * The ESRT image is used to read ESRT entries for all the images in a bank ++ */ ++#define FWU_IMAGE_INDEX_ESRT FWU_COMPONENT_NUMBER - 1 ++ ++/* Index count for fake images to be ignored ++ * The image index for firmware images in capsule starts from 1. ++ * So, the image at index 0 should be ignored */ ++#define FWU_FAKE_IMAGES_INDEX_COUNT 1 ++#define FWU_FAKE_IMAGE_INDEX 0 ++ ++/* ++ * Metadata version 2 data structures defined by PSA_FW update specification ++ * at https://developer.arm.com/documentation/den0118/latest/ ++ */ ++ ++/* Properties of image in a bank */ ++struct fwu_image_properties { ++ ++ /* The UUID of the image in this bank */ ++ uuid_t img_uuid; ++ ++ /* [0]: bit describing the image acceptance status – ++ * status - 1 means the image is accepted ++ * [31:1]: MBZ ++ */ ++ uint32_t accepted; ++ ++ /* NOTE: using the reserved field */ ++ /* image version */ ++ uint32_t version; ++ ++} __packed; ++ ++/* Image entry information */ ++struct fwu_image_entry { ++ ++ /* The UUID identifying the image type */ ++ uuid_t img_type_uuid; ++ ++ /* The UUID of the storage volume where the image is located */ ++ uuid_t location_uuid; ++ ++ /* The Properties of images with img_type_uuid in the different FW banks */ ++ struct fwu_image_properties img_props[NR_OF_FW_BANKS]; ++ ++} __packed; ++ ++struct fwu_fw_store_descriptor { ++ ++ /* The number of firmware banks in the Firmware Store */ ++ uint8_t num_banks; ++ ++ /* Reserved */ ++ uint8_t reserved; ++ ++ /* The number of images per bank. This should be the number of entries in the img_entry array */ ++ uint16_t num_images; ++ ++ /* The size of image_entry(all banks) in bytes */ ++ uint16_t img_entry_size; ++ ++ /* The size of image bank info structure in bytes */ ++ uint16_t bank_info_entry_size; ++ ++ /* Array of fwu_image_entry structs */ ++ struct fwu_image_entry img_entry[NR_OF_IMAGES_IN_FW_BANK]; ++ ++} __packed; ++ ++struct fwu_metadata { ++ ++ /* The metadata CRC value */ ++ uint32_t crc_32; ++ ++ /* The metadata version */ ++ uint32_t version; ++ ++ /* The bank index with which device boots */ ++ uint32_t active_index; ++ ++ /* The previous bank index with which device booted successfully */ ++ uint32_t previous_active_index; ++ ++ /* The size of the entire metadata in bytes */ ++ uint32_t metadata_size; ++ ++ /* The offset of the image descriptor structure */ ++ uint16_t desc_offset; ++ ++ /* Reserved */ ++ uint16_t reserved1; ++ ++ /* The state of each bank ++ * Each bank_state entry can take one of the following values: ++ * • 0xFF: invalid – One or more images in the bank are corrupted or were partially overwritten. ++ * • 0xFE: valid – The bank contains a valid set of images, but some images are in an unaccepted state. ++ * • 0xFC: accepted – all of the images in the bank are valid and have been accepted. ++ */ ++ uint8_t bank_state[NR_OF_MAX_FW_BANKS]; ++ ++ /* Reserved */ ++ uint32_t reserved2; ++ ++ struct fwu_fw_store_descriptor fw_desc; ++ ++} __packed; ++ ++/* This is Corstone1000 speific metadata for OTA. ++ * Private metadata is written at next sector following ++ * FWU METADATA location */ ++struct fwu_private_metadata { ++ ++ /* The bank from which system is booted from */ ++ uint32_t boot_index; ++ ++ /* The tracking number of boot attempted so far */ ++ uint32_t boot_attempted; ++ ++ /* The temprary location of staged nv_counter before written to the otp */ ++ uint32_t nv_counter[NR_OF_IMAGES_IN_FW_BANK]; ++ ++ /* The current FMP version of each image */ ++ uint32_t fmp_version[NR_OF_IMAGES_IN_FW_BANK]; ++ ++ /* The last attempted FMP version of each image */ ++ uint32_t fmp_last_attempt_version[NR_OF_IMAGES_IN_FW_BANK]; ++ ++ /* The last attempted FMP status of each image */ ++ uint32_t fmp_last_attempt_status[NR_OF_IMAGES_IN_FW_BANK]; ++ ++} __packed; ++ ++/* ++ * struct fwu_esrt_data_wrapper - Wrapper for the ESRT data ++ * @data: The ESRT data ++ * @entries: The ESRT image entries ++ */ ++struct __attribute__((__packed__)) fwu_esrt_data_wrapper { ++ /* The ESRT data */ ++ struct efi_system_resource_table data; ++ ++ /* The ESRT image entries */ ++ struct efi_system_resource_entry entries[NR_OF_IMAGES_IN_FW_BANK]; ++}; ++ ++#define MAX_BOOT_ATTEMPTS_PER_BANK 3 ++ ++/* ++ * GUIDs for capsule updatable firmware images ++ * ++ * The GUIDs are generating with the UUIDv5 format. ++ * Namespace used for FVP GUIDs: 989f3a4e-46e0-4cd0-9877-a25c70c01329 ++ * Namespace used for MPS3 GUIDs: df1865d1-90fb-4d59-9c38-c9f2c1bba8cc ++ * Names: the image names stated in the fw_name field ++ */ ++fwu_bank_image_info_t fwu_image[NR_OF_IMAGES_IN_FW_BANK] = { ++#if PLATFORM_IS_FVP ++ // FVP payloads GUIDs ++ // bl2_signed ++ { ++ .image_size = SE_BL2_PARTITION_SIZE, ++ .image_offset = SE_BL2_PARTITION_BANK_OFFSET, ++ .image_guid = { ++ .time_low = 0xf1d883f9, ++ .time_mid = 0xdfeb, ++ .time_hi_and_version = 0x5363, ++ .clock_seq_and_node = {0x98, 0xd8, 0x68, 0x6e, 0xe3, 0xb6, 0x9f, 0x4f} ++ }, ++ }, ++ // tfm_s_signed ++ { ++ .image_size = TFM_PARTITION_SIZE, ++ .image_offset = TFM_PARTITION_BANK_OFFSET, ++ .image_guid = { ++ .time_low = 0x7fad470e, ++ .time_mid = 0x5ec5, ++ .time_hi_and_version = 0x5c03, ++ .clock_seq_and_node = {0xa2, 0xc1, 0x47, 0x56, 0xb4, 0x95, 0xde, 0x61} ++ }, ++ }, ++ // signed_fip-corstone1000 ++ { ++ .image_size = FIP_PARTITION_SIZE, ++ .image_offset = FIP_PARTITION_BANK_OFFSET, ++ .image_guid = { ++ .time_low = 0xf1933675, ++ .time_mid = 0x5a8c, ++ .time_hi_and_version = 0x5b6d, ++ .clock_seq_and_node = {0x9e, 0xf4, 0x84, 0x67, 0x39, 0xe8, 0x9b, 0xc8} ++ }, ++ }, ++ // Image.gz-initramfs-corstone1000-fvp ++ { ++ .image_size = INITRAMFS_PARTITION_SIZE, ++ .image_offset = INITRAMFS_PARTITION_BANK_OFFSET, ++ .image_guid = { ++ .time_low = 0xf771aff9, ++ .time_mid = 0xc7e9, ++ .time_hi_and_version = 0x5f99, ++ .clock_seq_and_node = {0x9e, 0xda, 0x23, 0x69, 0xdd, 0x69, 0x4f, 0x61} ++ }, ++ }, ++#else ++ // MPS3 payloads GUIDs ++ // bl2_signed payload GUID ++ { ++ .image_size = SE_BL2_PARTITION_SIZE, ++ .image_offset = SE_BL2_PARTITION_BANK_OFFSET, ++ .image_guid = { ++ .time_low = 0xfbfbefaa, ++ .time_mid = 0x0a56, ++ .time_hi_and_version = 0x50d5, ++ .clock_seq_and_node = {0xb6, 0x51, 0x74, 0x09, 0x1d, 0x3d, 0x62, 0xcf} ++ }, ++ }, ++ // tfm_s_signed ++ { ++ .image_size = TFM_PARTITION_SIZE, ++ .image_offset = TFM_PARTITION_BANK_OFFSET, ++ .image_guid = { ++ .time_low = 0xaf4cc7ad, ++ .time_mid = 0xee2e, ++ .time_hi_and_version = 0x5a39, ++ .clock_seq_and_node = {0xaa, 0xd5, 0xfa, 0xc8, 0xa1, 0xe6, 0x17, 0x3c} ++ }, ++ }, ++ // signed_fip-corstone1000 ++ { ++ .image_size = FIP_PARTITION_SIZE, ++ .image_offset = FIP_PARTITION_BANK_OFFSET, ++ .image_guid = { ++ .time_low = 0x55302f96, ++ .time_mid = 0xc4f0, ++ .time_hi_and_version = 0x5cf9, ++ .clock_seq_and_node = {0x86, 0x24, 0xe7, 0xcc, 0x38, 0x8f, 0x2b, 0x68} ++ }, ++ }, ++ // Image.gz-initramfs-corstone1000-mps3 ++ { ++ .image_size = INITRAMFS_PARTITION_SIZE, ++ .image_offset = INITRAMFS_PARTITION_BANK_OFFSET, ++ .image_guid = { ++ .time_low = 0x3e8ac972, ++ .time_mid = 0xc33c, ++ .time_hi_and_version = 0x5cc9, ++ .clock_seq_and_node = {0x90, 0xa0, 0xcd, 0xd3, 0x15, 0x96, 0x83, 0xea} ++ }, ++ }, ++#endif ++}; ++ ++struct fwu_metadata _metadata; ++ ++bool is_initialized = false; ++bool is_installed = false; ++ ++fmp_header_image_info_t fmp_header_image_info[FWU_COMPONENT_NUMBER]; ++struct fwu_esrt_data_wrapper esrt; ++ ++#define IMAGE_ACCEPTED (1) ++#define IMAGE_NOT_ACCEPTED (0) ++#define BANK_0 (0) ++#define BANK_1 (1) ++#define INVALID_VERSION (0xffffffff) ++#define INVALID_IMAGE (0xf) ++ ++#ifndef FWU_METADATA_FLASH_DEV ++ #ifndef FLASH_DEV_NAME ++ #error "FWU_METADATA_FLASH_DEV or FLASH_DEV_NAME must be defined in flash_layout.h" ++ #else ++ #define FWU_METADATA_FLASH_DEV FLASH_DEV_NAME ++ #endif ++#endif ++ ++/* Import the CMSIS flash device driver */ ++extern ARM_DRIVER_FLASH FWU_METADATA_FLASH_DEV; ++ ++#define SYSTICK_PER_MINUTE 60 ++#define BOOT_TIME_IN_MINUTES 6 ++#define HOST_ACK_SYSTICK_TIMEOUT (BOOT_TIME_IN_MINUTES * SYSTICK_PER_MINUTE) /* Number of system ticks to be precise. ++ * This is the value decided after monitoring the total time ++ * taken by the host to boot both on FVP and FPGA. ++ */ ++ ++#ifdef BL1_BUILD ++static psa_status_t private_metadata_read( ++ struct fwu_private_metadata* priv_metadata) ++{ ++ FWU_LOG_MSG("%s: enter\n\r", __func__); ++ ++ if (!priv_metadata) { ++ FWU_LOG_MSG("%s: ERROR - Null pointer received\n\r", __func__); ++ return PSA_ERROR_INVALID_ARGUMENT; ++ } ++ ++ int ret = FWU_METADATA_FLASH_DEV.ReadData(FWU_PRIVATE_METADATA_REPLICA_1_OFFSET, priv_metadata, ++ sizeof(*priv_metadata)); ++ if (ret < 0) { ++ FWU_LOG_MSG("%s: ERROR - Flash read failed (ret = %d)\n\r", __func__, ret); ++ return PSA_ERROR_STORAGE_FAILURE; ++ } ++ ++ if (ret != sizeof(*priv_metadata)) { ++ FWU_LOG_MSG("%s: ERROR - Incomplete metadata read (expected %zu, got %d)\n\r", ++ __func__, sizeof(*priv_metadata), ret); ++ return PSA_ERROR_INSUFFICIENT_DATA; ++ } ++ ++ FWU_LOG_MSG("%s: success: boot_index = %u\n\r", __func__, ++ priv_metadata->boot_index); ++ ++ return PSA_SUCCESS; ++} ++#else ++static psa_status_t private_metadata_read( ++ struct fwu_private_metadata* priv_metadata) ++{ ++ partition_entry_t *part; ++ uuid_t private_uuid = PRIVATE_METADATA_TYPE_UUID; ++ ++ FWU_LOG_MSG("%s: enter\n\r", __func__); ++ ++ if (!priv_metadata) { ++ FWU_LOG_MSG("%s: ERROR - Null pointer received\n\r", __func__); ++ return PSA_ERROR_INVALID_ARGUMENT; ++ } ++ ++ part = get_partition_entry_by_type(&private_uuid); ++ if (!part) { ++ FWU_LOG_MSG("Private metadata partition not found\n\r"); ++ return PSA_ERROR_GENERIC_ERROR; ++ } ++ ++ int ret = FWU_METADATA_FLASH_DEV.ReadData(part->start, priv_metadata, ++ sizeof(*priv_metadata)); ++ if (ret < 0) { ++ FWU_LOG_MSG("%s: ERROR - Flash read failed (ret = %d)\n\r", __func__, ret); ++ return PSA_ERROR_STORAGE_FAILURE; ++ } ++ ++ if (ret != sizeof(*priv_metadata)) { ++ FWU_LOG_MSG("%s: ERROR - Incomplete metadata read (expected %zu, got %d)\n\r", ++ __func__, sizeof(*priv_metadata), ret); ++ return PSA_ERROR_INSUFFICIENT_DATA; ++ } ++ ++ FWU_LOG_MSG("%s: success: boot_index = %u\n\r", __func__, ++ priv_metadata->boot_index); ++ ++ return PSA_SUCCESS; ++} ++#endif ++ ++#ifdef BL1_BUILD ++static psa_status_t private_metadata_write( ++ struct fwu_private_metadata* priv_metadata) ++{ ++ FWU_LOG_MSG("%s: enter: boot_index = %u\n\r", __func__, ++ priv_metadata->boot_index); ++ ++ if (!priv_metadata) { ++ FWU_LOG_MSG("%s: ERROR - Null pointer received\n\r", __func__); ++ return PSA_ERROR_INVALID_ARGUMENT; ++ } ++ ++ int ret = FWU_METADATA_FLASH_DEV.EraseSector(FWU_PRIVATE_METADATA_REPLICA_1_OFFSET); ++ if (ret != ARM_DRIVER_OK) { ++ FWU_LOG_MSG("%s: ERROR - Flash erase failed (ret = %d)\n\r", __func__, ret); ++ return PSA_ERROR_STORAGE_FAILURE; ++ } ++ ++ ret = FWU_METADATA_FLASH_DEV.ProgramData(FWU_PRIVATE_METADATA_REPLICA_1_OFFSET, ++ priv_metadata, sizeof(*priv_metadata)); ++ if (ret < 0) { ++ FWU_LOG_MSG("%s: ERROR - Flash write failed (ret = %d)\n\r", __func__, ret); ++ return PSA_ERROR_STORAGE_FAILURE; ++ } ++ ++ if (ret != sizeof(*priv_metadata)) { ++ FWU_LOG_MSG("%s: ERROR - Incomplete metadata write (expected %zu, written %d)\n\r", ++ __func__, sizeof(*priv_metadata), ret); ++ return PSA_ERROR_INSUFFICIENT_DATA; ++ } ++ ++ FWU_LOG_MSG("%s: success\n\r", __func__); ++ return PSA_SUCCESS; ++} ++#else ++static psa_status_t private_metadata_write( ++ struct fwu_private_metadata* priv_metadata) ++{ ++ uuid_t private_uuid = PRIVATE_METADATA_TYPE_UUID; ++ partition_entry_t *part; ++ ++ FWU_LOG_MSG("%s: enter: boot_index = %u\n\r", __func__, ++ priv_metadata->boot_index); ++ ++ if (!priv_metadata) { ++ FWU_LOG_MSG("%s: ERROR - Null pointer received\n\r", __func__); ++ return PSA_ERROR_INVALID_ARGUMENT; ++ } ++ ++ part = get_partition_entry_by_type(&private_uuid); ++ if (!part) { ++ FWU_LOG_MSG("Private metadata partition not found\n\r"); ++ return PSA_ERROR_GENERIC_ERROR; ++ } ++ ++ int ret = FWU_METADATA_FLASH_DEV.EraseSector(part->start); ++ if (ret != ARM_DRIVER_OK) { ++ FWU_LOG_MSG("%s: ERROR - Flash erase failed (ret = %d)\n\r", __func__, ret); ++ return PSA_ERROR_STORAGE_FAILURE; ++ } ++ ++ ret = FWU_METADATA_FLASH_DEV.ProgramData(part->start, ++ priv_metadata, sizeof(*priv_metadata)); ++ if (ret < 0) { ++ FWU_LOG_MSG("%s: ERROR - Flash write failed (ret = %d)\n\r", __func__, ret); ++ return PSA_ERROR_STORAGE_FAILURE; ++ } ++ ++ if (ret != sizeof(*priv_metadata)) { ++ FWU_LOG_MSG("%s: ERROR - Incomplete metadata write (expected %zu, written %d)\n\r", ++ __func__, sizeof(*priv_metadata), ret); ++ return PSA_ERROR_INSUFFICIENT_DATA; ++ } ++ ++ FWU_LOG_MSG("%s: success\n\r", __func__); ++ return PSA_SUCCESS; ++} ++#endif ++ ++static psa_status_t metadata_validate(struct fwu_metadata *metadata) ++{ ++ FWU_LOG_MSG("%s: enter:\n\r", __func__); ++ ++ if (!metadata) { ++ FWU_LOG_MSG("%s: ERROR - Null pointer received\n\r", __func__); ++ return PSA_ERROR_INVALID_ARGUMENT; ++ } ++ ++ uint32_t calculated_crc32 = crc32((uint8_t *)&(metadata->version), ++ sizeof(*metadata) - sizeof(uint32_t)); ++ ++ if (metadata->crc_32 != calculated_crc32) { ++ FWU_LOG_MSG("%s: failed: crc32 calculated: 0x%x, given: 0x%x\n\r", __func__, ++ calculated_crc32, metadata->crc_32); ++ return PSA_ERROR_GENERIC_ERROR; ++ } ++ ++ FWU_LOG_MSG("%s: success\n\r", __func__); ++ ++ return PSA_SUCCESS; ++} ++ ++#ifdef BL1_BUILD ++static psa_status_t metadata_read_without_validation(struct fwu_metadata *metadata) ++{ ++ FWU_LOG_MSG("%s: enter: flash addr = %u, size = %d\n\r", __func__, ++ FWU_METADATA_REPLICA_1_OFFSET, sizeof(*metadata)); ++ ++ if (!metadata) { ++ FWU_LOG_MSG("%s: ERROR - Null pointer received\n\r", __func__); ++ return PSA_ERROR_INVALID_ARGUMENT; ++ } ++ ++ int ret = FWU_METADATA_FLASH_DEV.ReadData(FWU_METADATA_REPLICA_1_OFFSET, ++ metadata, sizeof(*metadata)); ++ if (ret < 0) { ++ FWU_LOG_MSG("%s: ERROR - Flash read failed (ret = %d)\n\r", __func__, ret); ++ return PSA_ERROR_STORAGE_FAILURE; ++ } ++ ++ if (ret != sizeof(*metadata)) { ++ FWU_LOG_MSG("%s: ERROR - Incomplete metadata read (expected %zu, got %d)\n\r", ++ __func__, sizeof(*metadata), ret); ++ return PSA_ERROR_INSUFFICIENT_DATA; ++ } ++ ++ FWU_LOG_MSG("%s: success: active = %u, previous = %d\n\r", __func__, ++ metadata->active_index, metadata->previous_active_index); ++ ++ return PSA_SUCCESS; ++} ++#else ++static psa_status_t metadata_read_without_validation(struct fwu_metadata *metadata) ++{ ++ uuid_t metadata_uuid = FWU_METADATA_TYPE_UUID; ++ partition_entry_t *part; ++ ++ if (!metadata) { ++ FWU_LOG_MSG("%s: ERROR - Null pointer received\n\r", __func__); ++ return PSA_ERROR_INVALID_ARGUMENT; ++ } ++ ++ part = get_partition_entry_by_type(&metadata_uuid); ++ if (!part) { ++ FWU_LOG_MSG("%s: FWU metadata partition not found\n\r", __func__); ++ return PSA_ERROR_GENERIC_ERROR; ++ } ++ ++ FWU_LOG_MSG("%s: enter: flash addr = %u, size = %d\n\r", __func__, ++ part->start, sizeof(*metadata)); ++ ++ ++ int ret = FWU_METADATA_FLASH_DEV.ReadData(part->start, ++ metadata, sizeof(*metadata)); ++ if (ret < 0) { ++ FWU_LOG_MSG("%s: ERROR - Flash read failed (ret = %d)\n\r", __func__, ret); ++ return PSA_ERROR_STORAGE_FAILURE; ++ } ++ ++ if (ret != sizeof(*metadata)) { ++ FWU_LOG_MSG("%s: ERROR - Incomplete metadata read (expected %zu, got %d)\n\r", ++ __func__, sizeof(*metadata), ret); ++ return PSA_ERROR_INSUFFICIENT_DATA; ++ } ++ ++ FWU_LOG_MSG("%s: success: active = %u, previous = %d\n\r", __func__, ++ metadata->active_index, metadata->previous_active_index); ++ ++ return PSA_SUCCESS; ++} ++#endif ++ ++#ifdef BL1_BUILD ++static psa_status_t metadata_read(struct fwu_metadata *metadata, uint8_t replica_num) ++{ ++ uint32_t replica_offset = 0; ++ ++ FWU_LOG_MSG("%s: enter\n\r", __func__); ++ ++ if (!metadata) { ++ FWU_LOG_MSG("%s: ERROR - Null pointer received\n\r", __func__); ++ return PSA_ERROR_INVALID_ARGUMENT; ++ } ++ ++ if (replica_num == 1) { ++ replica_offset = FWU_METADATA_REPLICA_1_OFFSET; ++ } else if (replica_num == 2) { ++ replica_offset = FWU_METADATA_REPLICA_2_OFFSET; ++ } else { ++ FWU_LOG_MSG("%s: replica_num must be 1 or 2\n\r", __func__); ++ return PSA_ERROR_GENERIC_ERROR; ++ } ++ ++ FWU_LOG_MSG("%s: flash addr = %u, size = %d\n\r", __func__, ++ replica_offset, sizeof(*metadata)); ++ ++ ++ int ret = FWU_METADATA_FLASH_DEV.ReadData(replica_offset, ++ metadata, sizeof(*metadata)); ++ if (ret < 0) { ++ FWU_LOG_MSG("%s: ERROR - Flash read failed (ret = %d)\n\r", __func__, ret); ++ return PSA_ERROR_STORAGE_FAILURE; ++ } ++ ++ if (ret != sizeof(*metadata)) { ++ FWU_LOG_MSG("%s: ERROR - Incomplete metadata read (expected %zu, got %d)\n\r", ++ __func__, sizeof(*metadata), ret); ++ return PSA_ERROR_INSUFFICIENT_DATA; ++ } ++ ++ if (metadata_validate(metadata) != PSA_SUCCESS) { ++ FWU_LOG_MSG("%s: ERROR - Metadata validation failed\n\r", __func__); ++ return PSA_ERROR_GENERIC_ERROR; ++ } ++ ++ FWU_LOG_MSG("%s: success: active = %u, previous = %d\n\r", __func__, ++ metadata->active_index, metadata->previous_active_index); ++ ++ return PSA_SUCCESS; ++} ++#else ++static psa_status_t metadata_read(struct fwu_metadata *metadata, uint8_t replica_num) ++{ ++ uuid_t metadata_uuid = FWU_METADATA_TYPE_UUID; ++ partition_entry_t *part; ++ ++ FWU_LOG_MSG("%s: enter\n\r", __func__); ++ ++ if (!metadata) { ++ FWU_LOG_MSG("%s: ERROR - Null pointer received\n\r", __func__); ++ return PSA_ERROR_INVALID_ARGUMENT; ++ } ++ ++ if (replica_num == 1) { ++ part = get_partition_entry_by_type(&metadata_uuid); ++ } else if (replica_num == 2) { ++ part = get_partition_replica_by_type(&metadata_uuid); ++ } else { ++ FWU_LOG_MSG("%s: replica_num must be 1 or 2\n\r", __func__); ++ return PSA_ERROR_GENERIC_ERROR; ++ } ++ ++ if (!part) { ++ FWU_LOG_MSG("%s: FWU metadata partition not found\n\r", __func__); ++ return PSA_ERROR_GENERIC_ERROR; ++ } ++ ++ FWU_LOG_MSG("%s: enter: flash addr = %u, size = %d\n\r", __func__, ++ part->start, sizeof(*metadata)); ++ ++ int ret = FWU_METADATA_FLASH_DEV.ReadData(part->start, ++ metadata, sizeof(*metadata)); ++ if (ret < 0) { ++ FWU_LOG_MSG("%s: ERROR - Flash read failed (ret = %d)\n\r", __func__, ret); ++ return PSA_ERROR_STORAGE_FAILURE; ++ } ++ ++ if (ret != sizeof(*metadata)) { ++ FWU_LOG_MSG("%s: ERROR - Incomplete metadata read (expected %zu, got %d)\n\r", ++ __func__, sizeof(*metadata), ret); ++ return PSA_ERROR_INSUFFICIENT_DATA; ++ } ++ ++ if (metadata_validate(metadata) != PSA_SUCCESS) { ++ FWU_LOG_MSG("%s: ERROR - Metadata validation failed\n\r", __func__); ++ return PSA_ERROR_GENERIC_ERROR; ++ } ++ ++ FWU_LOG_MSG("%s: success: active = %u, previous = %d\n\r", __func__, ++ metadata->active_index, metadata->previous_active_index); ++ ++ return PSA_SUCCESS; ++} ++#endif ++ ++ ++#ifdef BL1_BUILD ++static psa_status_t metadata_write( ++ struct fwu_metadata *metadata, uint8_t replica_num) ++{ ++ uint32_t replica_offset = 0; ++ ++ FWU_LOG_MSG("%s: enter\n\r", __func__); ++ ++ if (!metadata) { ++ FWU_LOG_MSG("%s: ERROR - Null pointer received\n\r", __func__); ++ return PSA_ERROR_INVALID_ARGUMENT; ++ } ++ ++ if (replica_num == 1) { ++ replica_offset = FWU_METADATA_REPLICA_1_OFFSET; ++ } else if (replica_num == 2) { ++ replica_offset = FWU_METADATA_REPLICA_2_OFFSET; ++ } else { ++ FWU_LOG_MSG("%s: replica_num must be 1 or 2\n\r", __func__); ++ return PSA_ERROR_GENERIC_ERROR; ++ } ++ ++ FWU_LOG_MSG("%s: enter: flash addr = %u, size = %d\n\r", __func__, ++ replica_offset, sizeof(*metadata)); ++ ++ ++ int ret = FWU_METADATA_FLASH_DEV.EraseSector(replica_offset); ++ if (ret != ARM_DRIVER_OK) { ++ FWU_LOG_MSG("%s: ERROR - Flash erase failed (ret = %d)\n\r", __func__, ret); ++ return PSA_ERROR_STORAGE_FAILURE; ++ } ++ ++ ret = FWU_METADATA_FLASH_DEV.ProgramData(replica_offset, ++ metadata, sizeof(*metadata)); ++ if (ret < 0) { ++ FWU_LOG_MSG("%s: ERROR - Flash write failed (ret = %d)\n\r", __func__, ret); ++ return PSA_ERROR_STORAGE_FAILURE; ++ } ++ ++ if (ret != sizeof(*metadata)) { ++ FWU_LOG_MSG("%s: ERROR - Incomplete metadata write (expected %zu, written %d)\n\r", ++ __func__, sizeof(*metadata), ret); ++ return PSA_ERROR_INSUFFICIENT_DATA; ++ } ++ ++ FWU_LOG_MSG("%s: success: active = %u, previous = %d\n\r", __func__, ++ metadata->active_index, metadata->previous_active_index); ++ return PSA_SUCCESS; ++} ++#else ++static psa_status_t metadata_write( ++ struct fwu_metadata *metadata, uint8_t replica_num) ++{ ++ uuid_t metadata_uuid = FWU_METADATA_TYPE_UUID; ++ partition_entry_t *part; ++ ++ if (!metadata) { ++ FWU_LOG_MSG("%s: ERROR - Null pointer received\n\r", __func__); ++ return PSA_ERROR_INVALID_ARGUMENT; ++ } ++ ++ if (replica_num == 1) { ++ part = get_partition_entry_by_type(&metadata_uuid); ++ } else if (replica_num == 2) { ++ part = get_partition_replica_by_type(&metadata_uuid); ++ } else { ++ FWU_LOG_MSG("%s: replica_num must be 1 or 2\n\r", __func__); ++ return PSA_ERROR_GENERIC_ERROR; ++ } ++ ++ if (!part) { ++ FWU_LOG_MSG("%s: FWU metadata partition not found\n\r", __func__); ++ return PSA_ERROR_GENERIC_ERROR; ++ } ++ ++ FWU_LOG_MSG("%s: enter: flash addr = %u, size = %d\n\r", __func__, ++ part->start, sizeof(*metadata)); ++ ++ int ret = FWU_METADATA_FLASH_DEV.EraseSector(part->start); ++ if (ret != ARM_DRIVER_OK) { ++ FWU_LOG_MSG("%s: ERROR - Flash erase failed (ret = %d)\n\r", __func__, ret); ++ return PSA_ERROR_STORAGE_FAILURE; ++ } ++ ++ ret = FWU_METADATA_FLASH_DEV.ProgramData(part->start, ++ metadata, sizeof(*metadata)); ++ if (ret < 0) { ++ FWU_LOG_MSG("%s: ERROR - Flash write failed (ret = %d)\n\r", __func__, ret); ++ return PSA_ERROR_STORAGE_FAILURE; ++ } ++ ++ if (ret != sizeof(*metadata)) { ++ FWU_LOG_MSG("%s: ERROR - Incomplete metadata write (expected %zu, written %d)\n\r", ++ __func__, sizeof(*metadata), ret); ++ return PSA_ERROR_INSUFFICIENT_DATA; ++ } ++ ++ FWU_LOG_MSG("%s: success: active = %u, previous = %d\n\r", __func__, ++ metadata->active_index, metadata->previous_active_index); ++ return PSA_SUCCESS; ++} ++#endif ++ ++static psa_status_t metadata_write_both_replica( ++ struct fwu_metadata *metadata) ++{ ++ psa_status_t ret = PSA_ERROR_GENERIC_ERROR; ++ ++ ret = metadata_write(metadata, 1); ++ if (ret) { ++ return ret; ++ } ++ ++ ret = metadata_write(metadata, 2); ++ if (ret) { ++ return ret; ++ } ++ ++ return PSA_SUCCESS; ++} ++ ++psa_status_t fwu_metadata_check_and_correct_integrity(void) ++{ ++ psa_status_t ret_replica_1 = PSA_ERROR_GENERIC_ERROR; ++ psa_status_t ret_replica_2 = PSA_ERROR_GENERIC_ERROR; ++ ++ /* Check integrity of both metadata replica */ ++ ret_replica_1 = metadata_read(&_metadata, 1); ++ ret_replica_2 = metadata_read(&_metadata, 2); ++ ++ if (ret_replica_1 != PSA_SUCCESS && ret_replica_2 != PSA_SUCCESS) { ++ return PSA_ERROR_GENERIC_ERROR; ++ } else if (ret_replica_1 == PSA_SUCCESS && ret_replica_2 != PSA_SUCCESS) { ++ metadata_read(&_metadata, 1); ++ metadata_write(&_metadata, 2); ++ } else if (ret_replica_1 != PSA_SUCCESS && ret_replica_2 == PSA_SUCCESS) { ++ metadata_read(&_metadata, 2); ++ metadata_write(&_metadata, 1); ++ } ++ ++ return PSA_SUCCESS; ++} ++ ++psa_status_t fwu_metadata_init(void) ++{ ++ psa_status_t ret; ++ ARM_FLASH_INFO* flash_info; ++ ++ if (is_initialized) { ++ return PSA_SUCCESS; ++ } ++ ++ #ifndef BL1_BUILD ++ plat_io_storage_init(); ++ partition_init(PLATFORM_GPT_IMAGE); ++ #endif ++ ++ /* Code assumes everything fits into a sector */ ++ if (sizeof(struct fwu_metadata) > FWU_METADATA_FLASH_SECTOR_SIZE) { ++ return PSA_ERROR_GENERIC_ERROR; ++ } ++ ++ if (sizeof(struct fwu_private_metadata) > FWU_METADATA_FLASH_SECTOR_SIZE) { ++ return PSA_ERROR_GENERIC_ERROR; ++ } ++ ++ ret = FWU_METADATA_FLASH_DEV.Initialize(NULL); ++ if (ret != ARM_DRIVER_OK) { ++ return PSA_ERROR_GENERIC_ERROR; ++ } ++ ++ flash_info = FWU_METADATA_FLASH_DEV.GetInfo(); ++ if (flash_info->program_unit != 1) { ++ FWU_METADATA_FLASH_DEV.Uninitialize(); ++ return PSA_ERROR_GENERIC_ERROR; ++ } ++ ++ is_initialized = true; ++ ++ return PSA_SUCCESS; ++} ++ ++static bool skip_metadata_provision(void) ++{ ++ metadata_read(&_metadata, 1); ++ return (((_metadata.active_index < 2) || (_metadata.previous_active_index < 2)) ++ && (_metadata.active_index ^ _metadata.previous_active_index) ++ ); ++} ++ ++static psa_status_t fwu_metadata_configure(void) ++{ ++ /* Provision FWU Agent Metadata */ ++ ++ psa_status_t ret; ++ uint32_t image_version = FWU_IMAGE_INITIAL_VERSION; ++ ++ memset(&_metadata, 0, sizeof(struct fwu_metadata)); ++ ++ _metadata.version = FWU_METADATA_VERSION; ++ _metadata.active_index = BANK_0; ++ _metadata.previous_active_index = BANK_1; ++ _metadata.desc_offset= FWU_FW_STORE_DESC_OFFSET; ++ _metadata.metadata_size = sizeof(struct fwu_metadata); ++ ++ _metadata.fw_desc.num_banks = NR_OF_FW_BANKS; ++ _metadata.fw_desc.num_images = NR_OF_IMAGES_IN_FW_BANK; ++ _metadata.fw_desc.img_entry_size = sizeof(struct fwu_image_entry) * NR_OF_IMAGES_IN_FW_BANK; ++ _metadata.fw_desc.bank_info_entry_size = sizeof(struct fwu_image_properties) * NR_OF_FW_BANKS; ++ _metadata.bank_state[BANK_0] = FWU_BANK_ACCEPTED; ++ _metadata.bank_state[BANK_1] = FWU_BANK_ACCEPTED; ++ /* bank 0 is the place where images are located at the ++ * start of device lifecycle */ ++ ++ for (int i = 0; i < NR_OF_IMAGES_IN_FW_BANK; i++) { ++ ++ _metadata.fw_desc.img_entry[i].img_props[BANK_0].accepted = IMAGE_ACCEPTED; ++ _metadata.fw_desc.img_entry[i].img_props[BANK_0].version = image_version; ++ memcpy(&(_metadata.fw_desc.img_entry[i].img_props[BANK_0].img_uuid), (const void *)&fwu_image[i].image_guid, sizeof(struct efi_guid)); ++ ++ _metadata.fw_desc.img_entry[i].img_props[BANK_1].accepted = INVALID_IMAGE; ++ _metadata.fw_desc.img_entry[i].img_props[BANK_1].version = INVALID_VERSION; ++ memcpy(&(_metadata.fw_desc.img_entry[i].img_props[BANK_1].img_uuid), (const void *)&fwu_image[i].image_guid, sizeof(struct efi_guid)); ++ } ++ ++ /* Calculate CRC32 for fwu metadata. The first filed in the _metadata has to be the crc_32. ++ * This should be omited from the calculation. */ ++ _metadata.crc_32 = crc32((uint8_t *)&_metadata.version, ++ sizeof(struct fwu_metadata) - sizeof(uint32_t)); ++ ++ ret = metadata_write_both_replica(&_metadata); ++ if (ret) { ++ return ret; ++ } ++ ++ memset(&_metadata, 0, sizeof(_metadata)); ++ ret = metadata_read(&_metadata, 1); ++ if (ret) { ++ return ret; ++ } ++ FWU_LOG_MSG("%s: provisioned values: active = %u, previous = %d\n\r", ++ __func__, _metadata.active_index, _metadata.previous_active_index); ++ return PSA_SUCCESS; ++ ++} ++ ++static psa_status_t fwu_private_metadata_configure(void) ++{ ++ /* Provision Private metadata for update agent which is shared ++ beween BL1 and tf-m of secure enclave */ ++ ++ psa_status_t ret; ++ struct fwu_private_metadata priv_metadata; ++ ++ memset(&priv_metadata, 0, sizeof(struct fwu_private_metadata)); ++ ++ priv_metadata.boot_index = BANK_0; ++ priv_metadata.boot_attempted = 0; ++ ++ for (int i = 0; i < NR_OF_IMAGES_IN_FW_BANK; i++) { ++ priv_metadata.fmp_version[i] = FWU_IMAGE_INITIAL_VERSION; ++ priv_metadata.fmp_last_attempt_version[i] = FWU_IMAGE_INITIAL_VERSION; ++ priv_metadata.fmp_last_attempt_status[i] = LAST_ATTEMPT_STATUS_SUCCESS; ++ } ++ ret = private_metadata_write(&priv_metadata); ++ if (ret) { ++ return ret; ++ } ++ ++ memset(&priv_metadata, 0, sizeof(struct fwu_private_metadata)); ++ ret = private_metadata_read(&priv_metadata); ++ if (ret) { ++ return ret; ++ } ++ FWU_LOG_MSG("%s: provisioned values: boot_index = %u\n\r", __func__, ++ priv_metadata.boot_index); ++ return PSA_SUCCESS; ++} ++ ++psa_status_t fwu_metadata_provision(void) ++{ ++ psa_status_t ret; ++ ++ FWU_LOG_MSG("%s: enter\n\r", __func__); ++ ++ ret = fwu_metadata_init(); ++ if (ret) { ++ FWU_LOG_MSG("%s: ERROR FWU Metadata init failed \n\r", __func__); ++ return ret; ++ } ++ ++ /* ++ * check by chance if the previous reboot ++ * had a firmware data?. If yes, then don't initialize ++ * metadata ++ */ ++ if(skip_metadata_provision()) { ++ FWU_LOG_MSG("%s: Skipping Metadata provisioning \n\r", __func__); ++ return PSA_SUCCESS; ++ } ++ ++ ret = fwu_metadata_configure(); ++ if(ret) { ++ FWU_LOG_MSG("%s: ERROR FWU Metadata configure failed \n\r", __func__); ++ return ret; ++ } ++ ++ ret = fwu_private_metadata_configure(); ++ if(ret) { ++ FWU_LOG_MSG("%s: ERROR FWU Private Metadata configure failed \n\r", __func__); ++ return ret; ++ } ++ ++ FWU_LOG_MSG("%s: FWU METADATA PROVISIONED.\n\r", __func__); ++ return PSA_SUCCESS; ++} ++ ++static uint8_t get_fwu_image_state( ++ struct fwu_metadata *metadata, ++ struct fwu_private_metadata *priv_metadata, ++ uint32_t fwu_image_index) ++{ ++ FWU_LOG_MSG("%s: enter\n\r", __func__); ++ ++ if ((metadata->fw_desc.img_entry[fwu_image_index].img_props[metadata->active_index].accepted) ++ == (IMAGE_NOT_ACCEPTED)) { ++ FWU_LOG_MSG("%s: exit: Image %d PSA_FWU_TRIAL\n\r", __func__, fwu_image_index); ++ return PSA_FWU_TRIAL; ++ } ++ ++ FWU_LOG_MSG("%s: exit: Image %d PSA_FWU_READY\n\r", __func__, fwu_image_index); ++ return PSA_FWU_READY; ++} ++ ++static uint8_t get_fwu_agent_state( ++ struct fwu_metadata *metadata, ++ struct fwu_private_metadata *priv_metadata) ++{ ++ FWU_LOG_MSG("%s: enter\n\r", __func__); ++ ++ if (priv_metadata->boot_index != metadata->active_index) { ++ FWU_LOG_MSG("%s: exit: FWU Agent PSA_FWU_TRIAL (index mismatch)\n\r", __func__); ++ return PSA_FWU_TRIAL; ++ } ++ ++ for (int i=0; i < NR_OF_IMAGES_IN_FW_BANK; i++) { ++ if(get_fwu_image_state(metadata, priv_metadata, i) == PSA_FWU_TRIAL) { ++ FWU_LOG_MSG("%s: exit: FWU Agent PSA_FWU_TRIAL (an image still is in trial state)\n\r", __func__); ++ return PSA_FWU_TRIAL; ++ } ++ } ++ ++ FWU_LOG_MSG("%s: exit: FWU Agent PSA_FWU_READY\n\r", __func__); ++ return PSA_FWU_READY; ++} ++ ++static psa_status_t erase_image(uint32_t image_offset, uint32_t image_size) ++{ ++ int ret; ++ uint32_t sectors; ++ ++ FWU_LOG_MSG("%s: enter\n\r", __func__); ++ ++ if ((image_offset % FWU_METADATA_FLASH_SECTOR_SIZE) != 0) { ++ return PSA_ERROR_INVALID_ARGUMENT; ++ } ++ ++ if ((image_size % FWU_METADATA_FLASH_SECTOR_SIZE) != 0) { ++ return PSA_ERROR_GENERIC_ERROR; ++ } ++ ++ sectors = image_size / FWU_METADATA_FLASH_SECTOR_SIZE; ++ ++ FWU_LOG_MSG("%s: erasing sectors = %u, from offset = %u\n\r", __func__, ++ sectors, image_offset); ++ ++ for (int i = 0; i < sectors; i++) { ++ ret = FWU_METADATA_FLASH_DEV.EraseSector( ++ image_offset + (i * FWU_METADATA_FLASH_SECTOR_SIZE)); ++ if (ret != ARM_DRIVER_OK) { ++ return PSA_ERROR_GENERIC_ERROR; ++ } ++ } ++ ++ FWU_LOG_MSG("%s: exit\n\r", __func__); ++ return PSA_SUCCESS; ++} ++ ++static psa_status_t fwu_select_previous( ++ struct fwu_metadata *metadata, ++ struct fwu_private_metadata *priv_metadata) ++{ ++ psa_status_t ret; ++ uint8_t current_state; ++ uint32_t index; ++ ++ FWU_LOG_MSG("%s: enter\n\r", __func__); ++ ++ /* it is expected to receive this call only when ++ in trial state */ ++ current_state = get_fwu_agent_state(metadata, priv_metadata); ++ if (current_state != PSA_FWU_TRIAL) { ++ return PSA_ERROR_BAD_STATE; ++ } ++ ++ /* not expected to receive this call in this state, system ++ * did not boot from previous active index */ ++ if (metadata->previous_active_index != priv_metadata->boot_index) { ++ return PSA_ERROR_GENERIC_ERROR; ++ } ++ ++ FWU_LOG_MSG("%s: trial state: active index = %u, previous active = %u\n\r", ++ __func__, metadata->active_index, metadata->previous_active_index); ++ ++ index = metadata->previous_active_index; ++ for (int i = 0; i < NR_OF_IMAGES_IN_FW_BANK; i++) { ++ if (metadata->fw_desc.img_entry[i].img_props[index].accepted != IMAGE_ACCEPTED) ++ { ++ FWU_ASSERT(0); ++ } ++ } ++ ++ index = metadata->active_index; ++ metadata->bank_state[index] = FWU_BANK_INVALID; ++ metadata->active_index = metadata->previous_active_index; ++ metadata->previous_active_index = index; ++ ++ priv_metadata->boot_attempted = 0; ++ ++ ret = private_metadata_write(priv_metadata); ++ if (ret) { ++ return ret; ++ } ++ metadata->crc_32 = crc32((uint8_t *)&metadata->version, ++ sizeof(struct fwu_metadata) - sizeof(uint32_t)); ++ ++ ret = metadata_write_both_replica(metadata); ++ if (ret) { ++ return ret; ++ } ++ ++ FWU_LOG_MSG("%s: in regular state by choosing previous active bank\n\r", ++ __func__); ++ ++ FWU_LOG_MSG("%s: exit: ret = %d\n\r", __func__, ret); ++ return ret; ++ ++} ++ ++void bl1_get_active_bl2_image(uint32_t *offset) ++{ ++ struct fwu_private_metadata priv_metadata; ++ uint8_t current_state; ++ uint32_t boot_attempted; ++ uint32_t boot_index; ++ ++ FWU_LOG_MSG("%s: enter\n\r", __func__); ++ ++ if (fwu_metadata_init()) { ++ FWU_ASSERT(0); ++ } ++ ++ if (private_metadata_read(&priv_metadata)) { ++ FWU_ASSERT(0); ++ } ++ ++ if (metadata_read(&_metadata, 1)) { ++ FWU_ASSERT(0); ++ } ++ ++ current_state = get_fwu_agent_state(&_metadata, &priv_metadata); ++ ++ if (current_state == PSA_FWU_READY) { ++ boot_index = _metadata.active_index; ++ FWU_ASSERT(boot_index == priv_metadata.boot_index); ++ boot_attempted = 0; ++ } else if (current_state == PSA_FWU_TRIAL) { ++ boot_attempted = (++priv_metadata.boot_attempted); ++ FWU_LOG_MSG("%s: attempting boot number = %u\n\r", ++ __func__, boot_attempted); ++ if (boot_attempted <= MAX_BOOT_ATTEMPTS_PER_BANK) { ++ boot_index = _metadata.active_index; ++ FWU_LOG_MSG("%s: booting from trial bank: %u\n\r", ++ __func__, boot_index); ++ } else if (boot_attempted <= (2 * MAX_BOOT_ATTEMPTS_PER_BANK)) { ++ boot_index = _metadata.previous_active_index; ++ FWU_LOG_MSG("%s: gave up booting from trial bank\n\r", __func__); ++ FWU_LOG_MSG("%s: booting from previous active bank: %u\n\r", ++ __func__, boot_index); ++ } else { ++ FWU_LOG_MSG("%s: cannot boot system from any bank, halting...\n\r", __func__); ++ FWU_ASSERT(0); ++ } ++ } else { ++ FWU_ASSERT(0); ++ } ++ ++ priv_metadata.boot_index = boot_index; ++ if (private_metadata_write(&priv_metadata) < 0) { ++ FWU_ASSERT(0); ++ } ++ ++ if (boot_index == BANK_0) { ++ *offset = SE_BL2_BANK_0_OFFSET; ++ } else if (boot_index == BANK_1) { ++ *offset = SE_BL2_BANK_1_OFFSET; ++ } else { ++ FWU_ASSERT(0); ++ } ++ ++ FWU_LOG_MSG("%s: exit: booting from bank = %u, offset = 0x%x\n\r", __func__, ++ boot_index, *offset); ++ ++ return; ++} ++ ++uint8_t bl2_get_boot_bank(void) ++{ ++ uint8_t boot_index; ++ struct fwu_private_metadata priv_metadata; ++ FWU_LOG_MSG("%s: enter", __func__); ++ if (fwu_metadata_init()) { ++ FWU_ASSERT(0); ++ } ++ if (private_metadata_read(&priv_metadata)) { ++ FWU_ASSERT(0); ++ } ++ boot_index = priv_metadata.boot_index; ++ FWU_LOG_MSG("%s: exit: booting from bank = %u", __func__, boot_index); ++ return boot_index; ++} ++ ++static void disable_host_ack_timer(void) ++{ ++ FWU_LOG_MSG("%s: timer to reset is disabled\n\r", __func__); ++ SysTick->CTRL &= (~SysTick_CTRL_ENABLE_Msk); ++} ++ ++static psa_status_t update_nv_counters( ++ struct fwu_private_metadata* priv_metadata) ++{ ++ enum tfm_plat_err_t err; ++ uint32_t security_cnt; ++ enum tfm_nv_counter_t tfm_nv_counter_i; ++ ++ FWU_LOG_MSG("%s: enter\n\r", __func__); ++ ++ /* The FWU_BL2_NV_COUNTER (0) is not mirrored in the private metadata. It is ++ * directly updated in the bl1_2_validate_image_at_addr() function, in ++ * tfm/bl1/bl1_2/main.c. ++ * Because of this, the index starts from FWU_TFM_NV_COUNTER (1). */ ++ for (int i = FWU_TFM_NV_COUNTER; i <= FWU_MAX_NV_COUNTER_INDEX; i++) { ++ ++ switch (i) { ++ case FWU_TFM_NV_COUNTER: ++ tfm_nv_counter_i = PLAT_NV_COUNTER_BL2_0; ++ break; ++ case FWU_TFA_NV_COUNTER: ++ tfm_nv_counter_i = PLAT_NV_COUNTER_BL2_1; ++ break; ++ default: ++ FWU_ASSERT(0); ++ break; ++ } ++ ++ err = tfm_plat_read_nv_counter(tfm_nv_counter_i, ++ sizeof(security_cnt), (uint8_t *)&security_cnt); ++ if (err != TFM_PLAT_ERR_SUCCESS) { ++ FWU_LOG_MSG("%s: couldn't read NV counter\n\r", __func__); ++ return PSA_ERROR_GENERIC_ERROR; ++ } ++ ++ if (priv_metadata->nv_counter[i] < security_cnt) { ++ FWU_LOG_MSG("%s: staged NV counter is smaller than current value\n\r", __func__); ++ return PSA_ERROR_GENERIC_ERROR; ++ } else if (priv_metadata->nv_counter[i] > security_cnt) { ++ FWU_LOG_MSG("%s: updating index = %u nv counter = %u->%u\n\r", ++ __func__, i, security_cnt, ++ priv_metadata->nv_counter[i]); ++ err = tfm_plat_set_nv_counter(tfm_nv_counter_i, ++ priv_metadata->nv_counter[i]); ++ if (err != TFM_PLAT_ERR_SUCCESS) { ++ FWU_LOG_MSG("%s: couldn't write NV counter\n\r", __func__); ++ return PSA_ERROR_GENERIC_ERROR; ++ } ++ } ++ ++ } ++ ++ FWU_LOG_MSG("%s: exit\n\r", __func__); ++ return PSA_SUCCESS; ++} ++ ++psa_status_t corstone1000_fwu_host_ack(void) ++{ ++ psa_status_t ret; ++ struct fwu_private_metadata priv_metadata; ++ uint8_t current_state; ++ ++ FWU_LOG_MSG("%s: enter\n\r", __func__); ++ ++ if (!is_initialized) { ++ return PSA_ERROR_BAD_STATE; ++ } ++ ++ Select_Write_Mode_For_Shared_Flash(); ++ ++ /* This cannot be added to the fwu_metadata_init() because that function is ++ * called before the logging is enabled by TF-M. */ ++ ret = fwu_metadata_check_and_correct_integrity(); ++ if (ret != PSA_SUCCESS) { ++ FWU_LOG_MSG("fwu_metadata_check_and_correct_integrity failed\r\n"); ++ return ret; ++ } ++ ++ if (metadata_read(&_metadata, 1)) { ++ ret = PSA_ERROR_GENERIC_ERROR; ++ goto out; ++ } ++ ++ if (private_metadata_read(&priv_metadata)) { ++ ret = PSA_ERROR_GENERIC_ERROR; ++ goto out; ++ } ++ ++ current_state = get_fwu_agent_state(&_metadata, &priv_metadata); ++ if (current_state == PSA_FWU_READY) { ++ ++ ret = PSA_SUCCESS; /* nothing to be done */ ++ ++ for (int i = 0; i < NR_OF_IMAGES_IN_FW_BANK; i++) { ++ fmp_set_image_info(&fwu_image[i].image_guid, ++ priv_metadata.fmp_version[i], ++ priv_metadata.fmp_last_attempt_version[i], ++ priv_metadata.fmp_last_attempt_status[i]); ++ } ++ ++ goto out; ++ ++ } else if (current_state != PSA_FWU_TRIAL) { ++ FWU_ASSERT(0); ++ } ++ ++ if (_metadata.active_index != priv_metadata.boot_index) { ++ ++ /* firmware update failed, revert back to previous bank */ ++ ++ for (int i = 0; i < NR_OF_IMAGES_IN_FW_BANK; i++) { ++ if(get_fwu_image_state(&_metadata, &priv_metadata, i) == PSA_FWU_TRIAL) { ++ priv_metadata.fmp_last_attempt_version[i] = ++ _metadata.fw_desc.img_entry[i].img_props[_metadata.active_index].version; ++ ++ priv_metadata.fmp_last_attempt_status[i] = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL; ++ } ++ } ++ ret = fwu_select_previous(&_metadata, &priv_metadata); ++ ++ } ++ ++ if (ret == PSA_SUCCESS) { ++ disable_host_ack_timer(); ++ for (int i = 0; i < NR_OF_IMAGES_IN_FW_BANK; i++) { ++ fmp_set_image_info(&fwu_image[i].image_guid, ++ priv_metadata.fmp_version[i], ++ priv_metadata.fmp_last_attempt_version[i], ++ priv_metadata.fmp_last_attempt_status[i]); ++ } ++ } ++ ++out: ++ Select_XIP_Mode_For_Shared_Flash(); ++ ++ FWU_LOG_MSG("%s: exit: ret = %d\n\r", __func__, ret); ++ return ret; ++} ++ ++static int systic_counter = 0; ++ ++void SysTick_Handler(void) ++{ ++ systic_counter++; ++ if (systic_counter % 10 == 0) { ++ SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; ++ stdio_output_string("*", 1); ++ SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; ++ } ++ if (systic_counter == HOST_ACK_SYSTICK_TIMEOUT) { ++ SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; ++ stdio_output_string("timer expired!\n\r", ++ sizeof("timer expired!\n\r")); ++ NVIC_SystemReset(); ++ } ++} ++ ++/* When in trial state, start the timer for host to respond. ++ * Diable timer when host responds back either by calling ++ * corstone1000_fwu_accept_image or corstone1000_fwu_select_previous. ++ * Otherwise, resets the system. ++ */ ++void host_acknowledgement_timer_to_reset(void) ++{ ++ struct fwu_private_metadata priv_metadata; ++ uint8_t current_state; ++ ++ FWU_LOG_MSG("%s: enter\n\r", __func__); ++ ++ Select_Write_Mode_For_Shared_Flash(); ++ ++ if (!is_initialized) { ++ FWU_ASSERT(0); ++ } ++ ++ if (private_metadata_read(&priv_metadata)) { ++ FWU_ASSERT(0); ++ } ++ ++ if (metadata_read(&_metadata, 1)) { ++ FWU_ASSERT(0); ++ } ++ ++ Select_XIP_Mode_For_Shared_Flash(); ++ ++ current_state = get_fwu_agent_state(&_metadata, &priv_metadata); ++ ++ if (current_state == PSA_FWU_TRIAL) { ++ FWU_LOG_MSG("%s: in trial state, starting host ack timer\n\r", ++ __func__); ++ systic_counter = 0; ++ if (SysTick_Config(SysTick_LOAD_RELOAD_Msk)) { ++ FWU_LOG_MSG("%s: timer init failed\n\r", __func__); ++ FWU_ASSERT(0); ++ } else { ++ FWU_LOG_MSG("%s: timer started: seconds to expire : %u\n\r", ++ __func__, HOST_ACK_SYSTICK_TIMEOUT); ++ } ++ } ++ ++ FWU_LOG_MSG("%s: exit\n\r", __func__); ++ return; ++} ++ ++/* stage nv counter into private metadata section of the flash. ++ * staged nv counters are written to the otp when firmware update ++ * is successful ++ * the function assumes that the api is called in the boot loading ++ * stage ++ */ ++psa_status_t fwu_stage_nv_counter(enum fwu_nv_counter_index_t index, ++ uint32_t img_security_cnt) ++{ ++ struct fwu_private_metadata priv_metadata; ++ ++ FWU_LOG_MSG("%s: enter: index = %u, val = %u\n\r", __func__, ++ index, img_security_cnt); ++ ++ if (!is_initialized) { ++ FWU_ASSERT(0); ++ } ++ ++ if (index > FWU_MAX_NV_COUNTER_INDEX) { ++ return PSA_ERROR_INVALID_ARGUMENT; ++ } ++ ++ if (private_metadata_read(&priv_metadata)) { ++ FWU_ASSERT(0); ++ } ++ ++ if (priv_metadata.nv_counter[index] != img_security_cnt) { ++ priv_metadata.nv_counter[index] = img_security_cnt; ++ if (private_metadata_write(&priv_metadata)) { ++ FWU_ASSERT(0); ++ } ++ } ++ ++ FWU_LOG_MSG("%s: exit\n\r", __func__); ++ return PSA_SUCCESS; ++} ++ ++psa_status_t corstone1000_fwu_flash_image(void) ++{ ++ return PSA_SUCCESS; ++} ++ ++/* Verify if image index is valid or not */ ++bool is_image_index_valid(uint8_t fwu_image_index) { ++ return (fwu_image_index != FWU_FAKE_IMAGE_INDEX && ++ fwu_image_index != FWU_IMAGE_INDEX_ESRT && ++ fwu_image_index < FWU_COMPONENT_NUMBER); ++} ++ ++static psa_status_t get_esrt_data(struct fwu_esrt_data_wrapper *esrt) ++{ ++ FWU_LOG_MSG("%s: enter\n\r", __func__); ++ ++ if (!esrt) ++ { ++ FWU_LOG_MSG("%s: ERROR - Null pointer received\n\r", __func__); ++ return PSA_ERROR_INVALID_ARGUMENT; ++ } ++ ++ psa_status_t ret; ++ struct fwu_private_metadata priv_metadata; ++ ++ Select_Write_Mode_For_Shared_Flash(); ++ ++ if (private_metadata_read(&priv_metadata)) { ++ ret = PSA_ERROR_GENERIC_ERROR; ++ goto out; ++ } ++ ++ esrt->data.fw_resource_count = NR_OF_IMAGES_IN_FW_BANK; ++ esrt->data.fw_resource_count_max = NR_OF_IMAGES_IN_FW_BANK; ++ esrt->data.fw_resource_version = EFI_SYSTEM_RESOURCE_TABLE_FIRMWARE_RESOURCE_VERSION; ++ ++ for (int i = 0; i < NR_OF_IMAGES_IN_FW_BANK; i++) ++ { ++ memcpy(&esrt->entries[i].fw_class, &fwu_image[i].image_guid, sizeof(struct efi_guid)); ++ esrt->entries[i].fw_version = priv_metadata.fmp_version[i]; ++ esrt->entries[i].lowest_supported_fw_version = FWU_IMAGE_INITIAL_VERSION; ++ esrt->entries[i].last_attempt_version = priv_metadata.fmp_last_attempt_version[i]; ++ esrt->entries[i].last_attempt_status = priv_metadata.fmp_last_attempt_status[i]; ++ } ++ ret = PSA_SUCCESS; ++ ++out: ++ Select_XIP_Mode_For_Shared_Flash(); ++ FWU_LOG_MSG("%s: exit: ret = %d\n\r", __func__, ret); ++ return ret; ++} ++ ++static psa_status_t fwu_accept_image(struct fwu_metadata *metadata, ++ struct fwu_private_metadata *priv_metadata, ++ const psa_fwu_component_t *trials, ++ uint8_t number) ++{ ++ uint8_t current_state; ++ uint32_t image_bank_offset; ++ uint32_t active_bank_index; ++ uint32_t fwu_image_index; ++ psa_status_t ret; ++ ++ FWU_LOG_MSG("%s: enter\n\r", __func__); ++ ++ ++ /* booted from previous_active_bank, not expected ++ * to receive this call in this state, rather host should ++ * call corstone1000_fwu_select_previous */ ++ if (metadata->active_index != priv_metadata->boot_index) { ++ return PSA_ERROR_BAD_STATE; ++ } ++ ++ active_bank_index = metadata->active_index; ++ metadata->bank_state[active_bank_index] = FWU_BANK_ACCEPTED; ++ ++ for (int i = 0; i < number; i++) { ++ ++ if (!is_image_index_valid(trials[i])) { ++ FWU_LOG_MSG("%s: Invalid image index received \n\r", __func__); ++ continue; ++ } ++ ++ /* it is expected to receive this call only when ++ in trial state */ ++ fwu_image_index = trials[i] - FWU_FAKE_IMAGES_INDEX_COUNT; ++ ++ current_state = get_fwu_image_state(metadata, priv_metadata, fwu_image_index); ++ if (current_state != PSA_FWU_TRIAL) { ++ return PSA_ERROR_BAD_STATE; ++ } ++ ++ metadata->fw_desc.img_entry[fwu_image_index].img_props[active_bank_index].accepted = ++ IMAGE_ACCEPTED; ++ } ++ ++ priv_metadata->boot_attempted = 0; ++ ++ ret = private_metadata_write(priv_metadata); ++ if (ret) { ++ return ret; ++ } ++ metadata->crc_32 = crc32((uint8_t *)&metadata->version, ++ sizeof(struct fwu_metadata) - sizeof(uint32_t)); ++ ++ ret = metadata_write_both_replica(metadata); ++ if (ret) { ++ return ret; ++ } ++ ++ FWU_LOG_MSG("%s: exit: fwu state is changed to regular, ret - %d\n\r", __func__, ret); ++ return ret; ++} ++ ++static psa_status_t uint_to_image_version(uint32_t ver_in, psa_fwu_image_version_t *ver_out) ++{ ++ if (!ver_out) { ++ return PSA_ERROR_INVALID_ARGUMENT; ++ } ++ ++ ver_out->major = (uint8_t)((ver_in >> 24) & 0xF); ++ ver_out->minor = (uint8_t)((ver_in >> 16) & 0xF); ++ ver_out->patch = (uint16_t)(ver_in & 0xFF); ++ /* There's no room for the build number in the TS */ ++ return PSA_SUCCESS; ++} ++ ++static void fmp_header_image_info_init() ++{ ++ for (int i=0; iactive_index; ++ uint32_t bank_offset; ++ uint32_t image_offset; ++ uint8_t fwu_image_index = component - FWU_FAKE_IMAGES_INDEX_COUNT; /* Decrement to get the correct fwu image index */ ++ ++ FWU_LOG_MSG("%s: enter\n\r", __func__); ++ ++ if (active_index == BANK_0) { ++ bank_offset = BANK_1_PARTITION_OFFSET; ++ } else if (active_index == BANK_1) { ++ bank_offset = BANK_0_PARTITION_OFFSET; ++ } else { ++ FWU_LOG_MSG("ERROR: %s: active_index %d\n\r",__func__,active_index); ++ return PSA_ERROR_GENERIC_ERROR; ++ } ++ ++ image_offset = bank_offset + fwu_image[fwu_image_index].image_offset; ++ if (erase_image(image_offset, fwu_image[fwu_image_index].image_size)) { ++ return PSA_ERROR_GENERIC_ERROR; ++ } ++ ++ FWU_LOG_MSG("%s: exit: Staging area erased succesfully \n\r", __func__); ++ return PSA_SUCCESS; ++} ++ ++psa_status_t fwu_bootloader_init(void) ++{ ++ psa_status_t ret; ++ ++ FWU_LOG_MSG("%s: enter\n\r", __func__); ++ ++ ret = fwu_metadata_init(); ++ if (ret) { ++ return ret; ++ } ++ ++ /* Initialize the fmp_header_image_info object */ ++ fmp_header_image_info_init(); ++ ++ FWU_LOG_MSG("%s: exit: Initialized\n\r", __func__); ++ ++ return PSA_SUCCESS; ++} ++ ++psa_status_t fwu_bootloader_staging_area_init(psa_fwu_component_t component, ++ const void *manifest, ++ size_t manifest_size) ++{ ++ if (component >= FWU_COMPONENT_NUMBER) { ++ return PSA_ERROR_INVALID_ARGUMENT; ++ } ++ ++ if (!is_initialized) { ++ return PSA_ERROR_BAD_STATE; ++ } ++ ++ psa_status_t ret; ++ ++ FWU_LOG_MSG("%s: enter\n\r", __func__); ++ ++ Select_Write_Mode_For_Shared_Flash(); ++ ++ if (metadata_read(&_metadata, 1)) { ++ ret = PSA_ERROR_GENERIC_ERROR; ++ goto out; ++ } ++ ++ ret = erase_staging_area(&_metadata, component); ++ ++out: ++ Select_XIP_Mode_For_Shared_Flash(); ++ ++ FWU_LOG_MSG("%s: exit: ret = %d\n\r", __func__, ret); ++ return ret; ++} ++ ++psa_status_t parse_fmp_header(psa_fwu_component_t component, const void *block, size_t size) ++{ ++ /* Parse the incoming block to make sure complete FMP header is received */ ++ if (sizeof(fmp_header_image_info[component].fmp_hdr) >= (fmp_header_image_info[component].fmp_hdr_size_recvd + size)) { ++ memcpy(&fmp_header_image_info[component].fmp_hdr, block, size); ++ fmp_header_image_info[component].fmp_hdr_size_recvd += size; ++ return PSA_ERROR_INSUFFICIENT_DATA; ++ } ++ if (fmp_header_image_info[component].fmp_hdr_size_recvd != sizeof(fmp_header_image_info[component].fmp_hdr)) { ++ memcpy(&fmp_header_image_info[component].fmp_hdr, ++ block, ++ (sizeof(fmp_header_image_info[component].fmp_hdr) - fmp_header_image_info[component].fmp_hdr_size_recvd)); ++ ++ fmp_header_image_info[component].fmp_hdr_size_recvd = sizeof(fmp_header_image_info[component].fmp_hdr); ++ return PSA_SUCCESS; ++ } ++ ++} ++psa_status_t fwu_bootloader_load_image(psa_fwu_component_t component, ++ size_t block_offset, ++ const void *block, ++ size_t block_size) ++{ ++ ++ if (block == NULL) { ++ return PSA_ERROR_INVALID_ARGUMENT; ++ } ++ ++ if (!is_initialized) { ++ return PSA_ERROR_BAD_STATE; ++ } ++ ++ if (!is_image_index_valid(component)) { ++ FWU_LOG_MSG("%s: Invalid Component received \n\r", __func__); ++ return PSA_ERROR_GENERIC_ERROR; ++ } ++ ++ psa_status_t ret; ++ int drv_ret; ++ int image_index; ++ uint32_t bank_offset; ++ uint32_t active_index; ++ uint32_t previous_active_index; ++ uint32_t nr_images; ++ uint32_t current_state; ++ uint32_t image_offset; ++ uint32_t fw_version; ++ uint8_t fwu_image_index = component - FWU_FAKE_IMAGES_INDEX_COUNT; ++ struct fwu_private_metadata priv_metadata; ++ ++ FWU_LOG_MSG("%s: enter: block_offset = %u, block = 0x%p, block_size = %u\n\r" ++ , __func__, block_offset, block, block_size); ++ ++ /* Parse the incoming block to make sure complete FMP header is received */ ++ if (fmp_header_image_info[fwu_image_index].fmp_hdr_size_recvd != sizeof(fmp_header_image_info[fwu_image_index].fmp_hdr)) { ++ ret = parse_fmp_header(fwu_image_index, block, block_size); ++ if(ret == PSA_ERROR_INSUFFICIENT_DATA) { ++ return PSA_SUCCESS; ++ } ++ if (ret == PSA_SUCCESS) { ++ block_size -= fmp_header_image_info[fwu_image_index].fmp_hdr_size_recvd; ++ block += fmp_header_image_info[fwu_image_index].fmp_hdr_size_recvd; ++ } ++ } ++ ++ /* Store the version of new firmare */ ++ fw_version = fmp_header_image_info[fwu_image_index].fmp_hdr.fw_version; ++ FWU_LOG_MSG("%s: Updated info after payload header parsing: block_offset = %u, block = 0x%p, block_size = %u\n\r" ++ , __func__, block_offset, block, block_size); ++ /* Check if it is the dummy FMP or not */ ++ if (!fmp_header_image_info[fwu_image_index].fmp_hdr.header_size) ++ { ++ FWU_LOG_MSG("%s: Dummy FMP received \n\r", __func__); ++ /* Do something for dummy FMP's */ ++ return PSA_ERROR_GENERIC_ERROR; ++ } ++ ++ /* Write the block containing actual image to flash */ ++ ++ Select_Write_Mode_For_Shared_Flash(); ++ ++ if (metadata_read(&_metadata, 1)) { ++ ret = PSA_ERROR_GENERIC_ERROR; ++ goto out; ++ } ++ ++ if (private_metadata_read(&priv_metadata)) { ++ ret = PSA_ERROR_GENERIC_ERROR; ++ goto out; ++ } ++ ++ active_index = _metadata.active_index; ++ FWU_LOG_MSG("FMP version: 0x%d, metadata version : 0x%d\n", fw_version, ++ _metadata.fw_desc.img_entry[fwu_image_index].img_props[active_index].version); ++ if (fw_version <= ++ _metadata.fw_desc.img_entry[fwu_image_index].img_props[active_index].version) ++ { ++ /* Version is extracted from the fmp_payload_header */ ++ priv_metadata.fmp_last_attempt_version[fwu_image_index] = fmp_header_image_info[fwu_image_index].fmp_hdr.fw_version; ++ priv_metadata.fmp_last_attempt_status[fwu_image_index] = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL; ++ private_metadata_write(&priv_metadata); ++ ++ fmp_set_image_info(&fwu_image[fwu_image_index].image_guid, ++ priv_metadata.fmp_version[fwu_image_index], ++ priv_metadata.fmp_last_attempt_version[fwu_image_index], ++ priv_metadata.fmp_last_attempt_status[fwu_image_index]); ++ ++ FWU_LOG_MSG("ERROR: %s: version error\n\r",__func__); ++ ret = PSA_OPERATION_INCOMPLETE; ++ goto out; ++ } ++ ++ if (active_index == BANK_0) { ++ previous_active_index = BANK_1; ++ bank_offset = BANK_1_PARTITION_OFFSET; ++ } else if (active_index == BANK_1) { ++ previous_active_index = BANK_0; ++ bank_offset = BANK_0_PARTITION_OFFSET; ++ } else { ++ FWU_LOG_MSG("ERROR: %s: active_index %d\n\r",__func__,active_index); ++ return PSA_ERROR_DATA_INVALID; ++ } ++ ++ image_offset = bank_offset + fwu_image[fwu_image_index].image_offset; ++ ++ /* Firmware update process can only start in regular state. */ ++ current_state = get_fwu_image_state(&_metadata, &priv_metadata, fwu_image_index); ++ if (current_state != PSA_FWU_READY) { ++ ret = PSA_ERROR_BAD_STATE; ++ goto out; ++ } ++ ++ FWU_LOG_MSG("%s: writing image to the flash at offset = %u...\n\r", ++ __func__, (image_offset + fmp_header_image_info[fwu_image_index].image_size_recvd)); ++ drv_ret = FWU_METADATA_FLASH_DEV.ProgramData(image_offset + fmp_header_image_info[fwu_image_index].image_size_recvd, block, block_size); ++ FWU_LOG_MSG("%s: images are written to bank offset = %u\n\r", __func__, ++ image_offset); ++ if (drv_ret < 0 || drv_ret != block_size) { ++ FWU_LOG_MSG("Flashing image %d is not successful\n\r", component); ++ ++ /* Version is extracted from the fmp_payload_header */ ++ priv_metadata.fmp_last_attempt_version[fwu_image_index] = fmp_header_image_info[fwu_image_index].fmp_hdr.fw_version; ++ priv_metadata.fmp_last_attempt_status[fwu_image_index] = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL; ++ ++ private_metadata_write(&priv_metadata); ++ ++ fmp_set_image_info(&fwu_image[fwu_image_index].image_guid, ++ priv_metadata.fmp_version[fwu_image_index], ++ priv_metadata.fmp_last_attempt_version[fwu_image_index], ++ priv_metadata.fmp_last_attempt_status[fwu_image_index]); ++ ret = PSA_OPERATION_INCOMPLETE; ++ goto out; ++ } ++ else { ++ ret = PSA_SUCCESS; ++ } ++ FWU_LOG_MSG("%s: images are written to bank return status = %u\n\r", __func__, ++ ret); ++ fmp_header_image_info[fwu_image_index].image_size_recvd += block_size; ++ ++out: ++ Select_XIP_Mode_For_Shared_Flash(); ++ ++ FWU_LOG_MSG("%s: exit: ret = %d\n\r", __func__, ret); ++ return ret; ++} ++ ++static psa_status_t fwu_update_metadata(const psa_fwu_component_t *candidates, uint8_t number) ++{ ++ int ret; ++ uint32_t active_index; ++ uint32_t bank_offset; ++ uint32_t previous_active_index; ++ uint8_t fwu_image_index; ++ ++ FWU_LOG_MSG("%s: enter function\n\r", __func__); ++ ++ Select_Write_Mode_For_Shared_Flash(); ++ ++ if (metadata_read(&_metadata, 1)) { ++ ret = PSA_ERROR_GENERIC_ERROR; ++ goto out; ++ } ++ active_index = _metadata.active_index; ++ ++ if (active_index == BANK_0) { ++ previous_active_index = BANK_1; ++ bank_offset = BANK_1_PARTITION_OFFSET; ++ } else if (active_index == BANK_1) { ++ previous_active_index = BANK_0; ++ bank_offset = BANK_0_PARTITION_OFFSET; ++ } else { ++ FWU_LOG_MSG("ERROR: %s: active_index %d\n\r",__func__,active_index); ++ ret = PSA_ERROR_DATA_INVALID; ++ goto out; ++ } ++ ++ _metadata.active_index = previous_active_index; ++ _metadata.previous_active_index = active_index; ++ _metadata.bank_state[previous_active_index] = FWU_BANK_VALID; ++ ++ /* Change system state to trial bank state */ ++ for (int i = 0; i < number; i++) { ++ /* Skip image with index 0 and ESRT image */ ++ if(!is_image_index_valid(candidates[i])) { ++ FWU_LOG_MSG("%s: Invalid image index received \n\r", __func__); ++ continue; ++ } ++ ++ fwu_image_index = candidates[i] - FWU_FAKE_IMAGES_INDEX_COUNT; ++ _metadata.fw_desc.img_entry[fwu_image_index].img_props[previous_active_index].accepted = ++ IMAGE_NOT_ACCEPTED; ++ _metadata.fw_desc.img_entry[fwu_image_index].img_props[previous_active_index].version = fmp_header_image_info[fwu_image_index].fmp_hdr.fw_version; ++ } ++ ++ _metadata.crc_32 = crc32((uint8_t *)&_metadata.version, ++ sizeof(struct fwu_metadata) - sizeof(uint32_t)); ++ ++ ret = metadata_write_both_replica(&_metadata); ++ if (ret) { ++ goto out; ++ } ++ ++ ret = PSA_SUCCESS; ++ ++out: ++ Select_XIP_Mode_For_Shared_Flash(); ++ ++ FWU_LOG_MSG("%s: exit: ret = %d\n\r", __func__, ret); ++ return ret; ++} ++ ++static psa_status_t copy_image_from_other_bank(int image_index, ++ uint32_t active_index, ++ uint32_t previous_active_index) ++{ ++ uint32_t bank_offset[NR_OF_FW_BANKS] = {BANK_0_PARTITION_OFFSET, BANK_1_PARTITION_OFFSET}; ++ uint8_t data[FLASH_CHUNK_SIZE]; ++ size_t remaining_size = fwu_image[image_index].image_size; ++ size_t data_size; ++ size_t offset_read = bank_offset[active_index] + fwu_image[image_index].image_offset; ++ size_t offset_write = bank_offset[previous_active_index] + fwu_image[image_index].image_offset; ++ int data_transferred_count; ++ ++ FWU_LOG_MSG("%s: Enter \n\r", __func__); ++ ++ psa_status_t ret = erase_image(offset_write, fwu_image[image_index].image_size); ++ if (ret != PSA_SUCCESS) { ++ FWU_LOG_MSG("%s: ERROR - Flash erase failed for Image: %d\n\r", __func__, image_index); ++ return ret; ++ } ++ ++ while(remaining_size > 0) { ++ data_size = (remaining_size > FLASH_CHUNK_SIZE) ? FLASH_CHUNK_SIZE : remaining_size; ++ ++ /* read image data from flash */ ++ data_transferred_count = FWU_METADATA_FLASH_DEV.ReadData(offset_read, data, data_size); ++ if (data_transferred_count < 0) { ++ FWU_LOG_MSG("%s: ERROR - Flash read failed (ret = %d)\n\r", __func__, data_transferred_count); ++ return PSA_ERROR_STORAGE_FAILURE; ++ } ++ ++ if (data_transferred_count != data_size) { ++ FWU_LOG_MSG("%s: ERROR - Incomplete metadata read (expected %zu, got %d)\n\r", ++ __func__, data_size, data_transferred_count); ++ return PSA_ERROR_INSUFFICIENT_DATA; ++ } ++ ++ offset_read += data_size; ++ ++ /* write image data to flash */ ++ data_transferred_count = FWU_METADATA_FLASH_DEV.ProgramData(offset_write, data, data_size); ++ if (data_transferred_count < 0) { ++ FWU_LOG_MSG("%s: ERROR - Flash read failed (ret = %d)\n\r", __func__, data_transferred_count); ++ return PSA_ERROR_STORAGE_FAILURE; ++ } ++ ++ if (data_transferred_count != data_size) { ++ FWU_LOG_MSG("%s: ERROR - Incomplete metadata write (expected %zu, written %d)\n\r", ++ __func__, data_size, data_transferred_count); ++ return PSA_ERROR_INSUFFICIENT_DATA; ++ } ++ ++ offset_write += data_size; ++ remaining_size -= data_size; ++ } ++ ++ FWU_LOG_MSG("%s: exit \n\r", __func__); ++ return PSA_SUCCESS; ++} ++ ++static psa_status_t maintain_bank_consistency(void) ++{ ++ psa_status_t ret; ++ uint32_t active_index; ++ uint32_t previous_active_index; ++ struct fwu_private_metadata priv_metadata; ++ ++ FWU_LOG_MSG("%s: Enter \n\r", __func__); ++ Select_Write_Mode_For_Shared_Flash(); ++ ++ if (metadata_read(&_metadata, 1) || private_metadata_read(&priv_metadata)) { ++ ret = PSA_ERROR_GENERIC_ERROR; ++ goto out; ++ } ++ ++ active_index = _metadata.active_index; ++ if (active_index == BANK_0) { ++ previous_active_index = BANK_1; ++ } else if (active_index == BANK_1) { ++ previous_active_index = BANK_0; ++ } else { ++ FWU_LOG_MSG("ERROR: %s: active_index %d\n\r",__func__,active_index); ++ ret = PSA_ERROR_DATA_INVALID; ++ goto out; ++ } ++ ++ for (int i=0; i= FWU_COMPONENT_NUMBER) { ++ return PSA_ERROR_INVALID_ARGUMENT; ++ } ++ ++ /* Skipping image at 0th index ++ * The image index in the capsule starts from 1 ++ */ ++ if (!component) { ++ if(query_state) ++ info->state = PSA_FWU_READY; ++ return PSA_SUCCESS; ++ } ++ ++ struct fwu_private_metadata priv_metadata; ++ uint32_t version; ++ uint8_t fwu_image_index = component - 1; ++ uint8_t current_state; ++ psa_status_t ret; ++ ++ FWU_LOG_MSG("%s: enter\n\r", __func__); ++ ++ ++ Select_Write_Mode_For_Shared_Flash(); ++ if (private_metadata_read(&priv_metadata)) { ++ ret = PSA_ERROR_GENERIC_ERROR; ++ goto out; ++ } ++ ++ if (metadata_read(&_metadata, 1)) { ++ ret = PSA_ERROR_GENERIC_ERROR; ++ goto out; ++ } ++ ++ if (component == FWU_IMAGE_INDEX_ESRT) { ++ ++ size_t esrt_size = TFM_FWU_MAX_DIGEST_SIZE; ++ if (TFM_FWU_MAX_DIGEST_SIZE > sizeof(struct fwu_esrt_data_wrapper)) ++ esrt_size = sizeof(struct fwu_esrt_data_wrapper); ++ ++ /* Populate the ESRT */ ++ ret = get_esrt_data(&esrt); ++ if (ret) { ++ FWU_LOG_MSG("%s: ERROR : Unable to populate ESRT \n\r", __func__); ++ goto out; ++ } ++ ++ memcpy(&info->impl.candidate_digest, &esrt, esrt_size); ++ if (query_state) { ++ info->state = PSA_FWU_READY; ++ } ++ } ++ else { ++ current_state = get_fwu_image_state(&_metadata, &priv_metadata, fwu_image_index); ++ if (query_state) { ++ info->state = current_state; ++ } ++ ++ /* Fill the other required fields for component */ ++ info->max_size = fwu_image[fwu_image_index].image_size; ++ ++ version = _metadata.fw_desc.img_entry[fwu_image_index].img_props[_metadata.active_index].version; ++ ret = uint_to_image_version(version, &info->version); ++ if (ret) { ++ FWU_LOG_MSG("%s: ERROR : Image version not found \n\r", __func__); ++ goto out; ++ } ++ } ++ ++out: ++ Select_XIP_Mode_For_Shared_Flash(); ++ FWU_LOG_MSG("%s: exit: ret = %d\n\r", __func__, ret); ++ return ret; ++} ++ ++psa_status_t fwu_bootloader_clean_component(psa_fwu_component_t component) ++{ ++ return PSA_SUCCESS; ++} +diff --git a/platform/ext/target/arm/corstone1000/fw_update_agent/uefi_fmp.c b/platform/ext/target/arm/corstone1000/bootloader/mcuboot/uefi_fmp.c +similarity index 66% +rename from platform/ext/target/arm/corstone1000/fw_update_agent/uefi_fmp.c +rename to platform/ext/target/arm/corstone1000/bootloader/mcuboot/uefi_fmp.c +index 896658995..30956a440 100644 +--- a/platform/ext/target/arm/corstone1000/fw_update_agent/uefi_fmp.c ++++ b/platform/ext/target/arm/corstone1000/bootloader/mcuboot/uefi_fmp.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2022-2024, Arm Limited. All rights reserved. ++ * Copyright (c) 2022-2025, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * +@@ -9,11 +9,12 @@ + #include + #include "tfm_hal_device_header.h" + #include "uefi_fmp.h" ++#include "flash_layout.h" + + /* The count will increase when partial update is supported. + * At present, only full WIC is considered as updatable image. + */ +-#define NUMBER_OF_FMP_IMAGES 1 ++#define NUMBER_OF_FMP_IMAGES NR_OF_IMAGES_IN_FW_BANK + #define NO_OF_FMP_VARIABLES_PER_IMAGE 6 + + #define UEFI_ARCHITECTURE_64 +@@ -74,18 +75,41 @@ typedef __PACKED_STRUCT { + uint32_t ImageVersionNameSize; + } EFI_FIRMWARE_MANAGEMENT_PROTOCOL_IMAGE_INFO; + +- +-static uint16_t corstone_image_name0[] = { 'C', 'O', 'R', 'S', 'T', 'O', 'N', 'E', '1', '0', '0', '0', '_', 'W', 'I', 'C', '\0' }; +-static uint16_t corstone_version_name0[] = { 'C', 'O', 'R', 'S', 'T', 'O', 'N', 'E', '1', '0', '0', '0', '_', 'B', 'E', 'S', 'T', '\0'}; +- ++struct corstone_image_info { ++ uint8_t corstone_image_name[50]; ++ uint8_t corstone_version_name[50]; ++} __packed; ++ ++/* Change image names and version name when partial update is implemented */ ++struct corstone_image_info image_info[NUMBER_OF_FMP_IMAGES] = { ++ { ++ { 'C', 'O', 'R', 'S', 'T', 'O', 'N', 'E', '1', '0', '0', '0', '_', 'W', 'I', 'C', '\0' }, ++ { 'C', 'O', 'R', 'S', 'T', 'O', 'N', 'E', '1', '0', '0', '0', '_', 'B', 'E', 'S', 'T', '\0'}, ++ }, ++ { ++ { 'C', 'O', 'R', 'S', 'T', 'O', 'N', 'E', '1', '0', '0', '0', '_', 'W', 'I', 'C', '\0' }, ++ { 'C', 'O', 'R', 'S', 'T', 'O', 'N', 'E', '1', '0', '0', '0', '_', 'B', 'E', 'S', 'T', '\0'}, ++ }, ++ { ++ { 'C', 'O', 'R', 'S', 'T', 'O', 'N', 'E', '1', '0', '0', '0', '_', 'W', 'I', 'C', '\0' }, ++ { 'C', 'O', 'R', 'S', 'T', 'O', 'N', 'E', '1', '0', '0', '0', '_', 'B', 'E', 'S', 'T', '\0'}, ++ }, ++ { ++ { 'C', 'O', 'R', 'S', 'T', 'O', 'N', 'E', '1', '0', '0', '0', '_', 'W', 'I', 'C', '\0' }, ++ { 'C', 'O', 'R', 'S', 'T', 'O', 'N', 'E', '1', '0', '0', '0', '_', 'B', 'E', 'S', 'T', '\0'}, ++ }, ++}; + static EFI_FIRMWARE_MANAGEMENT_PROTOCOL_IMAGE_INFO fmp_info[NUMBER_OF_FMP_IMAGES]; + +-extern struct efi_guid full_capsule_image_guid; ++extern fwu_bank_image_info_t fwu_image[]; + + static bool is_fmp_info_initialized = false; + + static void init_fmp_info(void) + { ++ if(is_fmp_info_initialized) { ++ return; ++ } + memset(fmp_info, 0, + sizeof(EFI_FIRMWARE_MANAGEMENT_PROTOCOL_IMAGE_INFO) * NUMBER_OF_FMP_IMAGES); + +@@ -93,42 +117,44 @@ static void init_fmp_info(void) + * Add further details when partial image is supported. + */ + +- fmp_info[0].DescriptorVersion = 4; +- fmp_info[0].DescriptorCount = NUMBER_OF_FMP_IMAGES; +- fmp_info[0].DescriptorsSize = +- sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) + +- sizeof(corstone_image_name0) + sizeof(corstone_version_name0); +- +- fmp_info[0].ImageDescriptor.ImageIndex = 1; +- +- memcpy(&fmp_info[0].ImageDescriptor.ImageTypeId, &full_capsule_image_guid, +- sizeof(struct efi_guid)); +- +- fmp_info[0].ImageDescriptor.ImageId = 1; +- fmp_info[0].ImageDescriptor.Version = FWU_IMAGE_INITIAL_VERSION; +- fmp_info[0].ImageDescriptor.AttributesSupported = 1; +- fmp_info[0].ImageDescriptor.AttributesSetting = ( +- IMAGE_ATTRIBUTE_IMAGE_UPDATABLE | IMAGE_ATTRIBUTE_RESET_REQUIRED); +- fmp_info[0].ImageDescriptor.LowestSupportedImageVersion = +- FWU_IMAGE_INITIAL_VERSION; +- fmp_info[0].ImageDescriptor.LastAttemptVersion = FWU_IMAGE_INITIAL_VERSION; +- fmp_info[0].ImageDescriptor.LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS; +- +- fmp_info[0].ImageName = corstone_image_name0; +- fmp_info[0].ImageNameSize = sizeof(corstone_image_name0); +- fmp_info[0].ImageVersionName = corstone_version_name0; +- fmp_info[0].ImageVersionNameSize = sizeof(corstone_version_name0); +- ++ for (int i = 0; i < NUMBER_OF_FMP_IMAGES; i++) ++ { ++ fmp_info[i].DescriptorVersion = 4; ++ fmp_info[i].DescriptorCount = NUMBER_OF_FMP_IMAGES; ++ fmp_info[i].DescriptorsSize = ++ sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) + ++ sizeof(image_info[i].corstone_image_name) + sizeof(image_info[i].corstone_version_name); ++ ++ fmp_info[i].ImageDescriptor.ImageIndex = i+1; ++ ++ memcpy(&fmp_info[i].ImageDescriptor.ImageTypeId, &fwu_image[i].image_guid, ++ sizeof(struct efi_guid)); ++ ++ fmp_info[i].ImageDescriptor.ImageId = i+1; ++ fmp_info[i].ImageDescriptor.Version = FWU_IMAGE_INITIAL_VERSION; ++ fmp_info[i].ImageDescriptor.AttributesSupported = 1; ++ fmp_info[i].ImageDescriptor.AttributesSetting = ( ++ IMAGE_ATTRIBUTE_IMAGE_UPDATABLE | IMAGE_ATTRIBUTE_RESET_REQUIRED); ++ fmp_info[i].ImageDescriptor.LowestSupportedImageVersion = ++ FWU_IMAGE_INITIAL_VERSION; ++ fmp_info[i].ImageDescriptor.LastAttemptVersion = FWU_IMAGE_INITIAL_VERSION; ++ fmp_info[i].ImageDescriptor.LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS; ++ ++ fmp_info[i].ImageName = image_info[i].corstone_image_name; ++ fmp_info[i].ImageNameSize = sizeof(image_info[i].corstone_image_name); ++ fmp_info[i].ImageVersionName = image_info[i].corstone_version_name; ++ fmp_info[i].ImageVersionNameSize = sizeof(image_info[i].corstone_version_name); ++ } + is_fmp_info_initialized = true; + + return; + } + +-enum fwu_agent_error_t fmp_set_image_info(struct efi_guid *guid, ++psa_status_t fmp_set_image_info(struct efi_guid *guid, + uint32_t current_version, uint32_t attempt_version, + uint32_t last_attempt_status) + { +- enum fwu_agent_error_t status = FWU_AGENT_ERROR; ++ psa_status_t status = PSA_ERROR_GENERIC_ERROR; + + FWU_LOG_MSG("%s:%d Enter\n\r", __func__, __LINE__); + +@@ -149,7 +175,7 @@ enum fwu_agent_error_t fmp_set_image_info(struct efi_guid *guid, + "version=%u last_attempt_version=%u.\n\r", + last_attempt_status, current_version, + attempt_version); +- status = FWU_AGENT_SUCCESS; ++ status = PSA_SUCCESS; + break; + } + } +@@ -161,7 +187,7 @@ enum fwu_agent_error_t fmp_set_image_info(struct efi_guid *guid, + + #define NO_OF_FMP_VARIABLES (NUMBER_OF_FMP_IMAGES * NO_OF_FMP_VARIABLES_PER_IMAGE) + +-static enum fwu_agent_error_t pack_image_info(void *buffer, uint32_t size) ++static psa_status_t pack_image_info(void *buffer, uint32_t size) + { + typedef __PACKED_STRUCT { + uint32_t variable_count; +@@ -178,7 +204,7 @@ static enum fwu_agent_error_t pack_image_info(void *buffer, uint32_t size) + + if (size < current_size) { + FWU_LOG_MSG("%s:%d Buffer too small.\n\r", __func__, __LINE__); +- return FWU_AGENT_ERROR; ++ return PSA_ERROR_INVALID_ARGUMENT; + } + + packed_buffer->variable_count = NO_OF_FMP_VARIABLES; +@@ -201,7 +227,7 @@ static enum fwu_agent_error_t pack_image_info(void *buffer, uint32_t size) + + if (size < current_size) { + FWU_LOG_MSG("%s:%d Buffer too small.\n\r", __func__, __LINE__); +- return FWU_AGENT_ERROR; ++ return PSA_ERROR_BUFFER_TOO_SMALL; + } + + FWU_LOG_MSG("%s:%d ImageInfo size = %u, ImageName size = %u, " +@@ -222,12 +248,12 @@ static enum fwu_agent_error_t pack_image_info(void *buffer, uint32_t size) + + } + +- return FWU_AGENT_SUCCESS; ++ return PSA_SUCCESS; + } + +-enum fwu_agent_error_t fmp_get_image_info(void *buffer, uint32_t size) ++psa_status_t fmp_get_image_info(void *buffer, uint32_t size) + { +- enum fwu_agent_error_t status; ++ psa_status_t status; + + FWU_LOG_MSG("%s:%d Enter\n\r", __func__, __LINE__); + +@@ -237,4 +263,3 @@ enum fwu_agent_error_t fmp_get_image_info(void *buffer, uint32_t size) + + return status; + } +- +diff --git a/platform/ext/target/arm/corstone1000/bootloader/tfm_bootloader_fwu_abstraction.h b/platform/ext/target/arm/corstone1000/bootloader/tfm_bootloader_fwu_abstraction.h +new file mode 100644 +index 000000000..571f61be3 +--- /dev/null ++++ b/platform/ext/target/arm/corstone1000/bootloader/tfm_bootloader_fwu_abstraction.h +@@ -0,0 +1,189 @@ ++/* ++ * Copyright (c) 2021-2022, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ * ++ */ ++ ++#ifndef __TFM_BOOTLOADER_FWU_ABSTRACTION_H__ ++#define __TFM_BOOTLOADER_FWU_ABSTRACTION_H__ ++ ++#include "stdbool.h" ++#include "psa/update.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * Bootloader related initialization for firmware update, such as reading ++ * some necessary shared data from the memory if needed. ++ * ++ * \return PSA_SUCCESS On success ++ * PSA_ERROR_GENERIC_ERROR On failure ++ */ ++psa_status_t fwu_bootloader_init(void); ++ ++/** ++ * \brief Initialize the staging area of the component. ++ * ++ * The component is in READY state. Prepare the staging area of the component ++ * for image download. ++ * For example, initialize the staging area, open the flash area, and so on. ++ * The image will be written into the staging area later. ++ * ++ * \param[in] component The identifier of the target component in bootloader. ++ * \param[in] manifest A pointer to a buffer containing a detached manifest for ++ * the update. If the manifest is bundled with the firmware ++ * image, manifest must be NULL. ++ * \param[in] manifest_size Size of the manifest buffer in bytes. ++ * ++ * \return PSA_SUCCESS On success ++ * PSA_ERROR_INVALID_SIGNATURE A signature or integrity check on the ++ * manifest has failed. ++ * PSA_ERROR_INVALID_ARGUMENT Invalid input parameter ++ * PSA_ERROR_INSUFFICIENT_MEMORY ++ * PSA_ERROR_INSUFFICIENT_STORAGE ++ * PSA_ERROR_COMMUNICATION_FAILURE ++ * PSA_ERROR_STORAGE_FAILURE ++ * ++ */ ++psa_status_t fwu_bootloader_staging_area_init(psa_fwu_component_t component, ++ const void *manifest, ++ size_t manifest_size); ++ ++/** ++ * \brief Load the image into the target component. ++ * ++ * The component is in WRITING state. Write the image data into the target ++ * component. ++ * ++ * \param[in] component The identifier of the target component in bootloader. ++ * \param[in] image_offset The offset of the image being passed into block, in ++ * bytes ++ * \param[in] block A buffer containing a block of image data. This ++ * might be a complete image or a subset. ++ * \param[in] block_size Size of block. ++ * ++ * \return PSA_SUCCESS On success ++ * PSA_ERROR_INVALID_ARGUMENT Invalid input parameter ++ * PSA_ERROR_INSUFFICIENT_MEMORY There is no enough memory to ++ * process the update ++ * PSA_ERROR_INSUFFICIENT_STORAGE There is no enough storage to ++ * process the update ++ * PSA_ERROR_GENERIC_ERROR A fatal error occurred ++ * ++ */ ++psa_status_t fwu_bootloader_load_image(psa_fwu_component_t component, ++ size_t image_offset, ++ const void *block, ++ size_t block_size); ++ ++/** ++ * \brief Starts the installation of an image. ++ * ++ * The components are in CANDIDATE state. Check the authenticity and integrity of ++ * the staged image in the components. If a reboot is required to complete the ++ * check, then mark this image as a candidate so that the next time bootloader ++ * runs it will take this image as a candidate one to bootup. Return the error ++ * code PSA_SUCCESS_REBOOT. ++ * ++ * \param[in] candidates A list of components in CANDIDATE state. ++ * \param[in] number Number of components in CANDIDATE state. ++ * ++ * \return PSA_SUCCESS On success ++ * PSA_SUCCESS_REBOOT A system reboot is needed to finish installation ++ * TFM_SUCCESS_RESTART A restart of the updated component is required ++ * to complete the update ++ * PSA_ERROR_DEPENDENCY_NEEDED Another image needs to be installed to ++ * finish installation ++ * PSA_ERROR_INVALID_ARGUMENT Invalid input parameter ++ * PSA_ERROR_INVALID_SIGNATURE The signature is incorrect ++ * PSA_ERROR_GENERIC_ERROR A fatal error occurred ++ * TFM_ERROR_ROLLBACK_DETECTED The image is too old to be installed. ++ * If the image metadata contains a ++ * timestamp and it has expired, then ++ * this error is also returned. ++ */ ++psa_status_t fwu_bootloader_install_image(const psa_fwu_component_t *candidates, ++ uint8_t number); ++ ++/** ++ * \brief Mark the TRIAL(running) image in component as confirmed. ++ * ++ * Call this API to mark the running images as permanent/accepted to avoid ++ * revert when next time bootup. Usually, this API is called after the running ++ * images have been verified as valid. ++ * ++ * \param[in] candidates A list of components in TRIAL state. ++ * \param[in] number Number of components in TRIAL state. ++ * ++ * \return PSA_SUCCESS On success ++ * PSA_ERROR_INSUFFICIENT_MEMORY ++ * PSA_ERROR_INSUFFICIENT_STORAGE ++ * PSA_ERROR_COMMUNICATION_FAILURE ++ * PSA_ERROR_STORAGE_FAILURE ++ */ ++psa_status_t fwu_bootloader_mark_image_accepted(const psa_fwu_component_t *trials, ++ uint8_t number); ++ ++/** ++ * \brief Uninstall the staged image in the component. ++ * ++ * The component is in STAGED state. Uninstall the staged image in the component ++ * so that this image will not be treated as a candidate next time bootup. ++ * ++ * \return PSA_SUCCESS On success ++ * PSA_ERROR_INSUFFICIENT_MEMORY ++ * PSA_ERROR_INSUFFICIENT_STORAGE ++ * PSA_ERROR_COMMUNICATION_FAILURE ++ * PSA_ERROR_STORAGE_FAILURE ++ */ ++psa_status_t fwu_bootloader_reject_staged_image(psa_fwu_component_t component); ++ ++/** ++ * \brief Reject the trial image in the component. ++ * ++ * The component is in TRIAL state. Mark the running image in the component as ++ * rejected. ++ * ++ * \return PSA_SUCCESS On success ++ * PSA_ERROR_INSUFFICIENT_MEMORY ++ * PSA_ERROR_INSUFFICIENT_STORAGE ++ * PSA_ERROR_COMMUNICATION_FAILURE ++ * PSA_ERROR_STORAGE_FAILURE ++ */ ++psa_status_t fwu_bootloader_reject_trial_image(psa_fwu_component_t component); ++ ++/** ++ * \brief The component is in FAILED or UPDATED state. Clean the staging area of the component. ++ * ++ * \return PSA_SUCCESS On success ++ * PSA_ERROR_INVALID_ARGUMENT Invalid input parameter ++ * PSA_ERROR_STORAGE_FAILURE ++ */ ++psa_status_t fwu_bootloader_clean_component(psa_fwu_component_t component); ++ ++/** ++ * \brief Get the image information. ++ * ++ * Get the image information of the given component in staging area ++ * or the running area. ++ * ++ * \param[in] component The identifier of the target component in bootloader. ++ * \param[in] query_state Query 'state' field. ++ * \param[in] query_impl_info Query 'impl' field. ++ * \param[out] info Buffer containing return the component information. ++ ++ * \return PSA_SUCCESS On success ++ * PSA_ERROR_INVALID_ARGUMENT Invalid input parameter ++ * PSA_ERROR_GENERIC_ERROR A fatal error occurred ++ */ ++psa_status_t fwu_bootloader_get_image_info(psa_fwu_component_t component, ++ bool query_state, ++ bool query_impl_info, ++ psa_fwu_component_info_t *info); ++#ifdef __cplusplus ++} ++#endif ++#endif /* __TFM_BOOTLOADER_FWU_ABSTRACTION_H__ */ +diff --git a/platform/ext/target/arm/corstone1000/fw_update_agent/uefi_fmp.h b/platform/ext/target/arm/corstone1000/bootloader/uefi_fmp.h +similarity index 89% +rename from platform/ext/target/arm/corstone1000/fw_update_agent/uefi_fmp.h +rename to platform/ext/target/arm/corstone1000/bootloader/uefi_fmp.h +index d876bd7cf..a555d851f 100644 +--- a/platform/ext/target/arm/corstone1000/fw_update_agent/uefi_fmp.h ++++ b/platform/ext/target/arm/corstone1000/bootloader/uefi_fmp.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2022, Arm Limited. All rights reserved. ++ * Copyright (c) 2022, 2025, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * +@@ -40,7 +40,7 @@ + * attempt_version: attempted versions for the image + * + */ +-enum fwu_agent_error_t fmp_set_image_info(struct efi_guid *guid, ++psa_status_t fmp_set_image_info(struct efi_guid *guid, + uint32_t current_version, uint32_t attempt_version, + uint32_t last_attempt_status); + +@@ -51,6 +51,5 @@ enum fwu_agent_error_t fmp_set_image_info(struct efi_guid *guid, + * size : size of the buffer + * + */ +-enum fwu_agent_error_t fmp_get_image_info(void *buffer, uint32_t size); +- ++psa_status_t fmp_get_image_info(void *buffer, uint32_t size); + #endif /* UEFI_FMP_H */ +diff --git a/platform/ext/target/arm/corstone1000/config.cmake b/platform/ext/target/arm/corstone1000/config.cmake +index 1ba43a006..108d16f57 100644 +--- a/platform/ext/target/arm/corstone1000/config.cmake ++++ b/platform/ext/target/arm/corstone1000/config.cmake +@@ -1,5 +1,5 @@ + #------------------------------------------------------------------------------- +-# Copyright (c) 2020-2023, Arm Limited. All rights reserved. ++# Copyright (c) 2020-2023, 2025, Arm Limited. All rights reserved. + # Copyright (c) 2022 Cypress Semiconductor Corporation (an Infineon company) + # or an affiliate of Cypress Semiconductor Corporation. All rights reserved. + # +@@ -60,6 +60,9 @@ set(TFM_PARTITION_FIRMWARE_UPDATE ON CACHE BOOL "Enable firm + set(PLATFORM_HAS_FIRMWARE_UPDATE_SUPPORT ON CACHE BOOL "Wheter the platform has firmware update support") + set(MCUBOOT_DATA_SHARING ON CACHE BOOL "Enable Data Sharing") + set(TFM_FWU_BOOTLOADER_LIB "${CMAKE_CURRENT_LIST_DIR}/bootloader/mcuboot" CACHE STRING "Bootloader configure file for Firmware Update partition") ++set(TFM_CONFIG_FWU_MAX_MANIFEST_SIZE 0 CACHE STRING "The maximum permitted size for manifest in psa_fwu_start(), in bytes.") ++set(TFM_CONFIG_FWU_MAX_WRITE_SIZE 4096 CACHE STRING "The maximum permitted size for block in psa_fwu_write, in bytes.") ++set(FWU_SUPPORT_TRIAL_STATE ON CACHE BOOL "Device support TRIAL component state.") + + if (${CMAKE_BUILD_TYPE} STREQUAL Debug OR ${CMAKE_BUILD_TYPE} STREQUAL RelWithDebInfo) + set(ENABLE_FWU_AGENT_DEBUG_LOGS TRUE CACHE BOOL "Enable Firmware update agent debug logs.") +diff --git a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c +deleted file mode 100644 +index c9b3e4844..000000000 +--- a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c ++++ /dev/null +@@ -1,1350 +0,0 @@ +-/* +- * Copyright (c) 2021-2024, Arm Limited. All rights reserved. +- * +- * SPDX-License-Identifier: BSD-3-Clause +- * +- */ +- +-#include +-#include +-#include "fwu_agent.h" +-#include "Driver_Flash.h" +-#include "flash_layout.h" +-#include "fip_parser/external/uuid.h" +-#include "region_defs.h" +-#include "uefi_capsule_parser.h" +-#include "flash_common.h" +-#include "platform_base_address.h" +-#include "platform_description.h" +-#include "tfm_plat_nv_counters.h" +-#include "tfm_plat_defs.h" +-#include "uefi_fmp.h" +-#include "uart_stdout.h" +-#include "soft_crc.h" +-#ifndef BL1_BUILD +-#include "partition.h" +-#include "platform.h" +-#endif +- +-/* Properties of image in a bank */ +-struct fwu_image_properties { +- +- /* UUID of the image in this bank */ +- uuid_t img_uuid; +- +- /* [0]: bit describing the image acceptance status – +- * 1 means the image is accepted +- * [31:1]: MBZ +- */ +- uint32_t accepted; +- +- /* NOTE: using the reserved field */ +- /* image version */ +- uint32_t version; +- +-} __packed; +- +-/* Image entry information */ +-struct fwu_image_entry { +- +- /* UUID identifying the image type */ +- uuid_t img_type_uuid; +- +- /* UUID of the storage volume where the image is located */ +- uuid_t location_uuid; +- +- /* Properties of images with img_type_uuid in the different FW banks */ +- struct fwu_image_properties img_props[NR_OF_FW_BANKS]; +- +-} __packed; +- +-struct fwu_metadata { +- +- /* Metadata CRC value */ +- uint32_t crc_32; +- +- /* Metadata version */ +- uint32_t version; +- +- /* Bank index with which device boots */ +- uint32_t active_index; +- +- /* Previous bank index with which device booted successfully */ +- uint32_t previous_active_index; +- +- /* Image entry information */ +- struct fwu_image_entry img_entry[NR_OF_IMAGES_IN_FW_BANK]; +- +-} __packed; +- +-/* This is Corstone1000 speific metadata for OTA. +- * Private metadata is written at next sector following +- * FWU METADATA location */ +-struct fwu_private_metadata { +- +- /* boot_index: the bank from which system is booted from */ +- uint32_t boot_index; +- +- /* counter: tracking number of boot attempted so far */ +- uint32_t boot_attempted; +- +- /* staged nv_counter: temprary location before written to the otp */ +- uint32_t nv_counter[NR_OF_IMAGES_IN_FW_BANK]; +- +- /* FMP information */ +- uint32_t fmp_version; +- uint32_t fmp_last_attempt_version; +- uint32_t fmp_last_attempt_status; +- +-} __packed; +- +-#define MAX_BOOT_ATTEMPTS_PER_BANK 3 +- +-struct fwu_metadata _metadata; +- +-int is_initialized = 0; +- +-capsule_image_info_t capsule_info; +- +-enum fwu_agent_state_t { +- FWU_AGENT_STATE_UNKNOWN = -1, +- FWU_AGENT_STATE_REGULAR = 0, +- FWU_AGENT_STATE_TRIAL, +-}; +- +-struct efi_guid full_capsule_image_guid = { +- .time_low = 0x989f3a4e, +- .time_mid = 0x46e0, +- .time_hi_and_version = 0x4cd0, +- .clock_seq_and_node = {0x98, 0x77, 0xa2, 0x5c, 0x70, 0xc0, 0x13, 0x29} +-}; +- +- +-#define IMAGE_ACCEPTED (1) +-#define IMAGE_NOT_ACCEPTED (0) +-#define BANK_0 (0) +-#define BANK_1 (1) +-#define IMAGE_0 (0) +-#define IMAGE_1 (1) +-#define IMAGE_2 (2) +-#define IMAGE_3 (3) +-#define IMAGE_END (IMAGE_3) +-#define IMAGE_ALL (IMAGE_END + 1) +-#define IMAGE_NOT_RECOGNIZED (-1) +-#define INVALID_VERSION (0xffffffff) +- +- +-#ifndef FWU_METADATA_FLASH_DEV +- #ifndef FLASH_DEV_NAME +- #error "FWU_METADATA_FLASH_DEV or FLASH_DEV_NAME must be defined in flash_layout.h" +- #else +- #define FWU_METADATA_FLASH_DEV FLASH_DEV_NAME +- #endif +-#endif +- +-/* Import the CMSIS flash device driver */ +-extern ARM_DRIVER_FLASH FWU_METADATA_FLASH_DEV; +- +-#define HOST_ACK_TIMEOUT_SEC (6 * 60) /* ~seconds, not exact */ +- +-#ifdef BL1_BUILD +-static enum fwu_agent_error_t private_metadata_read( +- struct fwu_private_metadata* p_metadata) +-{ +- int ret; +- +- FWU_LOG_MSG("%s: enter\n\r", __func__); +- +- if (!p_metadata) { +- return FWU_AGENT_ERROR; +- } +- +- ret = FWU_METADATA_FLASH_DEV.ReadData(FWU_PRIVATE_METADATA_REPLICA_1_OFFSET, p_metadata, +- sizeof(struct fwu_private_metadata)); +- if (ret < 0 || ret != sizeof(struct fwu_private_metadata)) { +- return FWU_AGENT_ERROR; +- } +- +- FWU_LOG_MSG("%s: success: boot_index = %u\n\r", __func__, +- p_metadata->boot_index); +- +- return FWU_AGENT_SUCCESS; +-} +-#else +-static enum fwu_agent_error_t private_metadata_read( +- struct fwu_private_metadata* p_metadata) +-{ +- partition_entry_t *part; +- uuid_t private_uuid = PRIVATE_METADATA_TYPE_UUID; +- int ret; +- +- FWU_LOG_MSG("%s: enter\n\r", __func__); +- +- if (!p_metadata) { +- return FWU_AGENT_ERROR; +- } +- +- part = get_partition_entry_by_type(&private_uuid); +- if (!part) { +- FWU_LOG_MSG("Private metadata partition not found\n\r"); +- return FWU_AGENT_ERROR; +- } +- +- ret = FWU_METADATA_FLASH_DEV.ReadData(part->start, p_metadata, +- sizeof(struct fwu_private_metadata)); +- if (ret < 0 || ret != sizeof(struct fwu_private_metadata)) { +- return FWU_AGENT_ERROR; +- } +- +- FWU_LOG_MSG("%s: success: boot_index = %u\n\r", __func__, +- p_metadata->boot_index); +- +- return FWU_AGENT_SUCCESS; +-} +-#endif +- +-#ifdef BL1_BUILD +-static enum fwu_agent_error_t private_metadata_write( +- struct fwu_private_metadata* p_metadata) +-{ +- int ret; +- +- FWU_LOG_MSG("%s: enter: boot_index = %u\n\r", __func__, +- p_metadata->boot_index); +- +- if (!p_metadata) { +- return FWU_AGENT_ERROR; +- } +- +- ret = FWU_METADATA_FLASH_DEV.EraseSector(FWU_PRIVATE_METADATA_REPLICA_1_OFFSET); +- if (ret != ARM_DRIVER_OK) { +- return FWU_AGENT_ERROR; +- } +- +- ret = FWU_METADATA_FLASH_DEV.ProgramData(FWU_PRIVATE_METADATA_REPLICA_1_OFFSET, +- p_metadata, sizeof(struct fwu_private_metadata)); +- if (ret < 0 || ret != sizeof(struct fwu_private_metadata)) { +- return FWU_AGENT_ERROR; +- } +- +- FWU_LOG_MSG("%s: success\n\r", __func__); +- return FWU_AGENT_SUCCESS; +-} +-#else +-static enum fwu_agent_error_t private_metadata_write( +- struct fwu_private_metadata* p_metadata) +-{ +- uuid_t private_uuid = PRIVATE_METADATA_TYPE_UUID; +- partition_entry_t *part; +- int ret; +- +- FWU_LOG_MSG("%s: enter: boot_index = %u\n\r", __func__, +- p_metadata->boot_index); +- +- if (!p_metadata) { +- return FWU_AGENT_ERROR; +- } +- +- part = get_partition_entry_by_type(&private_uuid); +- if (!part) { +- FWU_LOG_MSG("Private metadata partition not found\n\r"); +- return FWU_AGENT_ERROR; +- } +- +- ret = FWU_METADATA_FLASH_DEV.EraseSector(part->start); +- if (ret != ARM_DRIVER_OK) { +- return FWU_AGENT_ERROR; +- } +- +- ret = FWU_METADATA_FLASH_DEV.ProgramData(part->start, +- p_metadata, sizeof(struct fwu_private_metadata)); +- if (ret < 0 || ret != sizeof(struct fwu_private_metadata)) { +- return FWU_AGENT_ERROR; +- } +- +- FWU_LOG_MSG("%s: success\n\r", __func__); +- return FWU_AGENT_SUCCESS; +-} +-#endif +- +-static enum fwu_agent_error_t metadata_validate(struct fwu_metadata *p_metadata) +-{ +- int ret; +- +- FWU_LOG_MSG("%s: enter:\n\r", __func__); +- +- if (!p_metadata) { +- return FWU_AGENT_ERROR; +- } +- +- uint32_t calculated_crc32 = crc32((uint8_t *)&(p_metadata->version), +- sizeof(struct fwu_metadata) - sizeof(uint32_t)); +- +- if (p_metadata->crc_32 != calculated_crc32) { +- FWU_LOG_MSG("%s: failed: crc32 calculated: 0x%x, given: 0x%x\n\r", __func__, +- calculated_crc32, p_metadata->crc_32); +- return FWU_AGENT_ERROR; +- } +- +- FWU_LOG_MSG("%s: success\n\r", __func__); +- +- return FWU_AGENT_SUCCESS; +-} +- +-#ifdef BL1_BUILD +-static enum fwu_agent_error_t metadata_read_without_validation(struct fwu_metadata *p_metadata) +-{ +- int ret; +- +- FWU_LOG_MSG("%s: enter: flash addr = %u, size = %d\n\r", __func__, +- FWU_METADATA_REPLICA_1_OFFSET, sizeof(struct fwu_metadata)); +- +- if (!p_metadata) { +- return FWU_AGENT_ERROR; +- } +- +- ret = FWU_METADATA_FLASH_DEV.ReadData(FWU_METADATA_REPLICA_1_OFFSET, +- p_metadata, sizeof(struct fwu_metadata)); +- if (ret < 0 || ret != sizeof(struct fwu_metadata)) { +- return FWU_AGENT_ERROR; +- } +- +- FWU_LOG_MSG("%s: success: active = %u, previous = %d\n\r", __func__, +- p_metadata->active_index, p_metadata->previous_active_index); +- +- return FWU_AGENT_SUCCESS; +-} +-#else +-static enum fwu_agent_error_t metadata_read_without_validation(struct fwu_metadata *p_metadata) +-{ +- uuid_t metadata_uuid = FWU_METADATA_TYPE_UUID; +- partition_entry_t *part; +- int ret; +- +- if (!p_metadata) { +- return FWU_AGENT_ERROR; +- } +- +- part = get_partition_entry_by_type(&metadata_uuid); +- if (!part) { +- FWU_LOG_MSG("%s: FWU metadata partition not found\n\r", __func__); +- return FWU_AGENT_ERROR; +- } +- +- FWU_LOG_MSG("%s: enter: flash addr = %u, size = %d\n\r", __func__, +- part->start, sizeof(struct fwu_metadata)); +- +- +- ret = FWU_METADATA_FLASH_DEV.ReadData(part->start, +- p_metadata, sizeof(struct fwu_metadata)); +- if (ret < 0 || ret != sizeof(struct fwu_metadata)) { +- return FWU_AGENT_ERROR; +- } +- +- FWU_LOG_MSG("%s: success: active = %u, previous = %d\n\r", __func__, +- p_metadata->active_index, p_metadata->previous_active_index); +- +- return FWU_AGENT_SUCCESS; +-} +-#endif +- +-#ifdef BL1_BUILD +-static enum fwu_agent_error_t metadata_read(struct fwu_metadata *p_metadata) +-{ +- int ret; +- +- FWU_LOG_MSG("%s: enter: flash addr = %u, size = %d\n\r", __func__, +- FWU_METADATA_REPLICA_1_OFFSET, sizeof(struct fwu_metadata)); +- +- if (!p_metadata) { +- return FWU_AGENT_ERROR; +- } +- +- ret = FWU_METADATA_FLASH_DEV.ReadData(FWU_METADATA_REPLICA_1_OFFSET, +- p_metadata, sizeof(struct fwu_metadata)); +- if (ret < 0 || ret != sizeof(struct fwu_metadata)) { +- return FWU_AGENT_ERROR; +- } +- +- if (metadata_validate(p_metadata) != FWU_AGENT_SUCCESS) { +- return FWU_AGENT_ERROR; +- } +- +- FWU_LOG_MSG("%s: success: active = %u, previous = %d\n\r", __func__, +- p_metadata->active_index, p_metadata->previous_active_index); +- +- return FWU_AGENT_SUCCESS; +-} +-#else +-static enum fwu_agent_error_t metadata_read(struct fwu_metadata *p_metadata) +-{ +- uuid_t metadata_uuid = FWU_METADATA_TYPE_UUID; +- partition_entry_t *part; +- int ret; +- +- if (!p_metadata) { +- return FWU_AGENT_ERROR; +- } +- +- part = get_partition_entry_by_type(&metadata_uuid); +- if (!part) { +- FWU_LOG_MSG("%s: FWU metadata partition not found\n\r", __func__); +- return FWU_AGENT_ERROR; +- } +- +- FWU_LOG_MSG("%s: enter: flash addr = %u, size = %d\n\r", __func__, +- part->start, sizeof(struct fwu_metadata)); +- +- ret = FWU_METADATA_FLASH_DEV.ReadData(part->start, +- p_metadata, sizeof(struct fwu_metadata)); +- if (ret < 0 || ret != sizeof(struct fwu_metadata)) { +- return FWU_AGENT_ERROR; +- } +- +- if (metadata_validate(p_metadata) != FWU_AGENT_SUCCESS) { +- return FWU_AGENT_ERROR; +- } +- +- FWU_LOG_MSG("%s: success: active = %u, previous = %d\n\r", __func__, +- p_metadata->active_index, p_metadata->previous_active_index); +- +- return FWU_AGENT_SUCCESS; +-} +-#endif +- +- +-#ifdef BL1_BUILD +-static enum fwu_agent_error_t metadata_write( +- struct fwu_metadata *p_metadata) +-{ +- int ret; +- +- FWU_LOG_MSG("%s: enter: flash addr = %u, size = %d\n\r", __func__, +- FWU_METADATA_REPLICA_1_OFFSET, sizeof(struct fwu_metadata)); +- +- if (!p_metadata) { +- return FWU_AGENT_ERROR; +- } +- +- ret = FWU_METADATA_FLASH_DEV.EraseSector(FWU_METADATA_REPLICA_1_OFFSET); +- if (ret != ARM_DRIVER_OK) { +- return FWU_AGENT_ERROR; +- } +- +- ret = FWU_METADATA_FLASH_DEV.ProgramData(FWU_METADATA_REPLICA_1_OFFSET, +- p_metadata, sizeof(struct fwu_metadata)); +- if (ret < 0 || ret != sizeof(struct fwu_metadata)) { +- return FWU_AGENT_ERROR; +- } +- +- FWU_LOG_MSG("%s: enter: flash addr = %u, size = %d\n\r", __func__, +- FWU_METADATA_REPLICA_2_OFFSET, sizeof(struct fwu_metadata)); +- +- ret = FWU_METADATA_FLASH_DEV.EraseSector(FWU_METADATA_REPLICA_2_OFFSET); +- if (ret != ARM_DRIVER_OK) { +- return FWU_AGENT_ERROR; +- } +- +- ret = FWU_METADATA_FLASH_DEV.ProgramData(FWU_METADATA_REPLICA_2_OFFSET, +- p_metadata, sizeof(struct fwu_metadata)); +- if (ret < 0 || ret != sizeof(struct fwu_metadata)) { +- return FWU_AGENT_ERROR; +- } +- +- FWU_LOG_MSG("%s: enter: flash addr = %u, size = %d\n\r", __func__, +- FWU_METADATA_REPLICA_2_OFFSET, sizeof(struct fwu_metadata)); +- +- ret = FWU_METADATA_FLASH_DEV.EraseSector(FWU_METADATA_REPLICA_2_OFFSET); +- if (ret != ARM_DRIVER_OK) { +- return FWU_AGENT_ERROR; +- } +- +- ret = FWU_METADATA_FLASH_DEV.ProgramData(FWU_METADATA_REPLICA_2_OFFSET, +- p_metadata, sizeof(struct fwu_metadata)); +- if (ret < 0 || ret != sizeof(struct fwu_metadata)) { +- return FWU_AGENT_ERROR; +- } +- +- FWU_LOG_MSG("%s: success: active = %u, previous = %d\n\r", __func__, +- p_metadata->active_index, p_metadata->previous_active_index); +- return FWU_AGENT_SUCCESS; +-} +-#else +-static enum fwu_agent_error_t metadata_write( +- struct fwu_metadata *p_metadata) +-{ +- uuid_t metadata_uuid = FWU_METADATA_TYPE_UUID; +- partition_entry_t *part; +- int ret; +- +- if (!p_metadata) { +- return FWU_AGENT_ERROR; +- } +- +- part = get_partition_entry_by_type(&metadata_uuid); +- if (!part) { +- FWU_LOG_MSG("%s: FWU metadata partition not found\n\r", __func__); +- return FWU_AGENT_ERROR; +- } +- +- FWU_LOG_MSG("%s: enter: flash addr = %u, size = %d\n\r", __func__, +- part->start, sizeof(struct fwu_metadata)); +- +- ret = FWU_METADATA_FLASH_DEV.EraseSector(part->start); +- if (ret != ARM_DRIVER_OK) { +- return FWU_AGENT_ERROR; +- } +- +- ret = FWU_METADATA_FLASH_DEV.ProgramData(part->start, +- p_metadata, sizeof(struct fwu_metadata)); +- if (ret < 0 || ret != sizeof(struct fwu_metadata)) { +- return FWU_AGENT_ERROR; +- } +- +- part = get_partition_replica_by_type(&metadata_uuid); +- if (!part) { +- FWU_LOG_MSG("%s: FWU metadata replica partition not found\n\r", __func__); +- return FWU_AGENT_ERROR; +- } +- +- FWU_LOG_MSG("%s: enter: flash addr = %u, size = %d\n\r", __func__, +- part->start, sizeof(struct fwu_metadata)); +- +- ret = FWU_METADATA_FLASH_DEV.EraseSector(part->start); +- if (ret != ARM_DRIVER_OK) { +- return FWU_AGENT_ERROR; +- } +- +- ret = FWU_METADATA_FLASH_DEV.ProgramData(part->start, +- p_metadata, sizeof(struct fwu_metadata)); +- if (ret < 0 || ret != sizeof(struct fwu_metadata)) { +- return FWU_AGENT_ERROR; +- } +- +- FWU_LOG_MSG("%s: enter: flash addr = %u, size = %d\n\r", __func__, +- FWU_METADATA_REPLICA_2_OFFSET, sizeof(struct fwu_metadata)); +- +- ret = FWU_METADATA_FLASH_DEV.EraseSector(FWU_METADATA_REPLICA_2_OFFSET); +- if (ret != ARM_DRIVER_OK) { +- return FWU_AGENT_ERROR; +- } +- +- ret = FWU_METADATA_FLASH_DEV.ProgramData(FWU_METADATA_REPLICA_2_OFFSET, +- p_metadata, sizeof(struct fwu_metadata)); +- if (ret < 0 || ret != sizeof(struct fwu_metadata)) { +- return FWU_AGENT_ERROR; +- } +- +- FWU_LOG_MSG("%s: success: active = %u, previous = %d\n\r", __func__, +- p_metadata->active_index, p_metadata->previous_active_index); +- return FWU_AGENT_SUCCESS; +-} +-#endif +- +- +-enum fwu_agent_error_t fwu_metadata_init(void) +-{ +- enum fwu_agent_error_t ret; +- ARM_FLASH_INFO* flash_info; +- +- if (is_initialized) { +- return FWU_AGENT_SUCCESS; +- } +- +- #ifndef BL1_BUILD +- plat_io_storage_init(); +- partition_init(PLATFORM_GPT_IMAGE); +- #endif +- +- /* Code assumes everything fits into a sector */ +- if (sizeof(struct fwu_metadata) > FWU_METADATA_FLASH_SECTOR_SIZE) { +- return FWU_AGENT_ERROR; +- } +- +- if (sizeof(struct fwu_private_metadata) > FWU_METADATA_FLASH_SECTOR_SIZE) { +- return FWU_AGENT_ERROR; +- } +- +- ret = FWU_METADATA_FLASH_DEV.Initialize(NULL); +- if (ret != ARM_DRIVER_OK) { +- return FWU_AGENT_ERROR; +- } +- +- flash_info = FWU_METADATA_FLASH_DEV.GetInfo(); +- if (flash_info->program_unit != 1) { +- FWU_METADATA_FLASH_DEV.Uninitialize(); +- return FWU_AGENT_ERROR; +- } +- +- is_initialized = 1; +- +- return FWU_AGENT_SUCCESS; +-} +- +-enum fwu_agent_error_t fwu_metadata_provision(void) +-{ +- enum fwu_agent_error_t ret; +- struct fwu_private_metadata priv_metadata; +- uint32_t image_version = FWU_IMAGE_INITIAL_VERSION; +- +- FWU_LOG_MSG("%s: enter\n\r", __func__); +- +- ret = fwu_metadata_init(); +- if (ret) { +- return ret; +- } +- +- /* +- * check by chance if the previous reboot +- * had a firmware data?. If yes, then don't initialize +- * metadata +- */ +- metadata_read(&_metadata); +- if(_metadata.active_index < 2 || _metadata.previous_active_index <2){ +- if(_metadata.active_index ^ _metadata.previous_active_index) +- return FWU_AGENT_SUCCESS; +- } +- /* Provision FWU Agent Metadata */ +- +- memset(&_metadata, 0, sizeof(struct fwu_metadata)); +- +- _metadata.version = 1; +- _metadata.active_index = BANK_0; +- _metadata.previous_active_index = BANK_1; +- +- /* bank 0 is the place where images are located at the +- * start of device lifecycle */ +- +- for (int i = 0; i < NR_OF_IMAGES_IN_FW_BANK; i++) { +- +- _metadata.img_entry[i].img_props[BANK_0].accepted = IMAGE_ACCEPTED; +- _metadata.img_entry[i].img_props[BANK_0].version = image_version; +- +- _metadata.img_entry[i].img_props[BANK_1].accepted = IMAGE_NOT_ACCEPTED; +- _metadata.img_entry[i].img_props[BANK_1].version = INVALID_VERSION; +- } +- +- /* Calculate CRC32 for fwu metadata */ +- _metadata.crc_32 = crc32((uint8_t *)&_metadata.version, +- sizeof(struct fwu_metadata) - sizeof(uint32_t)); +- +- ret = metadata_write(&_metadata); +- if (ret) { +- return ret; +- } +- +- memset(&_metadata, 0, sizeof(struct fwu_metadata)); +- ret = metadata_read(&_metadata); +- if (ret) { +- return ret; +- } +- FWU_LOG_MSG("%s: provisioned values: active = %u, previous = %d\n\r", +- __func__, _metadata.active_index, _metadata.previous_active_index); +- +- +- /* Provision Private metadata for update agent which is shared +- beween BL1 and tf-m of secure enclave */ +- +- memset(&priv_metadata, 0, sizeof(struct fwu_private_metadata)); +- +- priv_metadata.boot_index = BANK_0; +- priv_metadata.boot_attempted = 0; +- +- priv_metadata.fmp_version = FWU_IMAGE_INITIAL_VERSION; +- priv_metadata.fmp_last_attempt_version = FWU_IMAGE_INITIAL_VERSION; +- priv_metadata.fmp_last_attempt_status = LAST_ATTEMPT_STATUS_SUCCESS; +- +- ret = private_metadata_write(&priv_metadata); +- if (ret) { +- return ret; +- } +- +- memset(&priv_metadata, 0, sizeof(struct fwu_private_metadata)); +- ret = private_metadata_read(&priv_metadata); +- if (ret) { +- return ret; +- } +- FWU_LOG_MSG("%s: provisioned values: boot_index = %u\n\r", __func__, +- priv_metadata.boot_index); +- +- FWU_LOG_MSG("%s: FWU METADATA PROVISIONED.\n\r", __func__); +- return FWU_AGENT_SUCCESS; +-} +- +-static enum fwu_agent_state_t get_fwu_agent_state( +- struct fwu_metadata *metadata_ptr, +- struct fwu_private_metadata *priv_metadata_ptr) +-{ +- uint32_t boot_index; +- +- FWU_LOG_MSG("%s: enter\n\r", __func__); +- +- boot_index = priv_metadata_ptr->boot_index; +- +- if (boot_index != metadata_ptr->active_index) { +- return FWU_AGENT_STATE_TRIAL; +- } +- +- for (int i = 0; i < NR_OF_IMAGES_IN_FW_BANK; i++) { +- if ((metadata_ptr->img_entry[i].img_props[boot_index].accepted) +- == (IMAGE_NOT_ACCEPTED)) { +- return FWU_AGENT_STATE_TRIAL; +- } +- } +- +- FWU_LOG_MSG("%s: exit: FWU_AGENT_STATE_REGULAR\n\r", __func__); +- return FWU_AGENT_STATE_REGULAR; +-} +- +-static int get_image_info_in_bank(struct efi_guid* guid, uint32_t* image_bank_offset) +-{ +- if ((memcmp(guid, &full_capsule_image_guid, sizeof(struct efi_guid))) == 0) { +- *image_bank_offset = 0; +- return IMAGE_ALL; +- } +- +- return IMAGE_NOT_RECOGNIZED; +-} +- +-static enum fwu_agent_error_t erase_bank(uint32_t bank_offset) +-{ +- int ret; +- uint32_t sectors; +- +- FWU_LOG_MSG("%s: enter\n\r", __func__); +- +- if ((bank_offset % FWU_METADATA_FLASH_SECTOR_SIZE) != 0) { +- return FWU_AGENT_ERROR; +- } +- +- if ((BANK_PARTITION_SIZE % FWU_METADATA_FLASH_SECTOR_SIZE) != 0) { +- return FWU_AGENT_ERROR; +- } +- +- sectors = BANK_PARTITION_SIZE / FWU_METADATA_FLASH_SECTOR_SIZE; +- +- FWU_LOG_MSG("%s: erasing sectors = %u, from offset = %u\n\r", __func__, +- sectors, bank_offset); +- +- for (int i = 0; i < sectors; i++) { +- ret = FWU_METADATA_FLASH_DEV.EraseSector( +- bank_offset + (i * FWU_METADATA_FLASH_SECTOR_SIZE)); +- if (ret != ARM_DRIVER_OK) { +- return FWU_AGENT_ERROR; +- } +- } +- +- FWU_LOG_MSG("%s: exit\n\r", __func__); +- return FWU_AGENT_SUCCESS; +-} +- +- +-static enum fwu_agent_error_t flash_full_capsule( +- struct fwu_metadata* metadata, void* images, uint32_t size, +- uint32_t version) +-{ +- int ret; +- uint32_t active_index = metadata->active_index; +- uint32_t bank_offset; +- uint32_t previous_active_index; +- +- FWU_LOG_MSG("%s: enter: image = 0x%p, size = %u, version = %u\n\r" +- , __func__, images, size, version); +- +- if (!metadata || !images) { +- return FWU_AGENT_ERROR; +- } +- +- if (size > BANK_PARTITION_SIZE) { +- FWU_LOG_MSG("ERROR: %s: size error\n\r",__func__); +- return FWU_AGENT_ERROR; +- } +- +- if (version <= +- (metadata->img_entry[IMAGE_0].img_props[active_index].version)) { +- FWU_LOG_MSG("ERROR: %s: version error\n\r",__func__); +- return FWU_AGENT_ERROR; +- } +- +- if (active_index == BANK_0) { +- previous_active_index = BANK_1; +- bank_offset = BANK_1_PARTITION_OFFSET; +- } else if (active_index == BANK_1) { +- previous_active_index = BANK_0; +- bank_offset = BANK_0_PARTITION_OFFSET; +- } else { +- FWU_LOG_MSG("ERROR: %s: active_index %d\n\r",__func__,active_index); +- return FWU_AGENT_ERROR; +- } +- +- if (erase_bank(bank_offset)) { +- return FWU_AGENT_ERROR; +- } +- +- FWU_LOG_MSG("%s: writing capsule to the flash at offset = %u...\n\r", +- __func__, bank_offset); +- ret = FWU_METADATA_FLASH_DEV.ProgramData(bank_offset, images, size); +- if (ret < 0 || ret != size) { +- return FWU_AGENT_ERROR; +- } +- FWU_LOG_MSG("%s: images are written to bank offset = %u\n\r", __func__, +- bank_offset); +- +- /* Change system state to trial bank state */ +- for (int i = 0; i < NR_OF_IMAGES_IN_FW_BANK; i++) { +- metadata->img_entry[i].img_props[previous_active_index].accepted = +- IMAGE_NOT_ACCEPTED; +- metadata->img_entry[i].img_props[previous_active_index].version = version; +- } +- metadata->active_index = previous_active_index; +- metadata->previous_active_index = active_index; +- metadata->crc_32 = crc32((uint8_t *)&metadata->version, +- sizeof(struct fwu_metadata) - sizeof(uint32_t)); +- +- ret = metadata_write(metadata); +- if (ret) { +- return ret; +- } +- +- FWU_LOG_MSG("%s: exit\n\r", __func__); +- return FWU_AGENT_SUCCESS; +-} +- +-enum fwu_agent_error_t corstone1000_fwu_flash_image(void) +-{ +- enum fwu_agent_error_t ret; +- struct fwu_private_metadata priv_metadata; +- enum fwu_agent_state_t current_state; +- void *capsule_ptr = (char*)CORSTONE1000_HOST_DRAM_UEFI_CAPSULE; +- int image_index; +- uint32_t image_bank_offset; +- uint32_t nr_images; +- +- FWU_LOG_MSG("%s: enter\n\r", __func__); +- +- if (!is_initialized) { +- return FWU_AGENT_ERROR; +- } +- +- Select_Write_Mode_For_Shared_Flash(); +- +- if (metadata_read(&_metadata)) { +- ret = FWU_AGENT_ERROR; +- goto out; +- } +- +- if (private_metadata_read(&priv_metadata)) { +- ret = FWU_AGENT_ERROR; +- goto out; +- } +- +- /* Firmware update process can only start in regular state. */ +- current_state = get_fwu_agent_state(&_metadata, &priv_metadata); +- if (current_state != FWU_AGENT_STATE_REGULAR) { +- ret = FWU_AGENT_ERROR; +- goto out; +- } +- +- memset(&capsule_info, 0, sizeof(capsule_image_info_t)); +- if (uefi_capsule_retrieve_images(capsule_ptr, &capsule_info)) { +- ret = FWU_AGENT_ERROR; +- goto out; +- } +- nr_images = capsule_info.nr_image; +- +- for (int i = 0; i < nr_images; i++) { +- image_index = get_image_info_in_bank(&capsule_info.guid[i], +- &image_bank_offset); +- switch(image_index) { +- case IMAGE_ALL: +- +- ret = flash_full_capsule(&_metadata, capsule_info.image[i], +- capsule_info.size[i], +- capsule_info.version[i]); +- +- if (ret != FWU_AGENT_SUCCESS) { +- +- priv_metadata.fmp_last_attempt_version = capsule_info.version[i]; +- priv_metadata.fmp_last_attempt_status = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL; +- +- private_metadata_write(&priv_metadata); +- +- fmp_set_image_info(&full_capsule_image_guid, +- priv_metadata.fmp_version, +- priv_metadata.fmp_last_attempt_version, +- priv_metadata.fmp_last_attempt_status); +- } +- +- +- break; +- default: +- FWU_LOG_MSG("%s: sent image not recognized\n\r", __func__); +- ret = FWU_AGENT_ERROR; +- break; +- } +- } +- +-out: +- Select_XIP_Mode_For_Shared_Flash(); +- +- FWU_LOG_MSG("%s: exit: ret = %d\n\r", __func__, ret); +- return ret; +-} +- +-static enum fwu_agent_error_t accept_full_capsule( +- struct fwu_metadata* metadata, +- struct fwu_private_metadata* priv_metadata) +-{ +- uint32_t active_index = metadata->active_index; +- enum fwu_agent_error_t ret; +- +- FWU_LOG_MSG("%s: enter\n\r", __func__); +- +- for (int i = 0; i < NR_OF_IMAGES_IN_FW_BANK; i++) { +- metadata->img_entry[i].img_props[active_index].accepted = +- IMAGE_ACCEPTED; +- } +- +- priv_metadata->boot_attempted = 0; +- +- ret = private_metadata_write(priv_metadata); +- if (ret) { +- return ret; +- } +- metadata->crc_32 = crc32((uint8_t *)&metadata->version, +- sizeof(struct fwu_metadata) - sizeof(uint32_t)); +- +- ret = metadata_write(metadata); +- if (ret) { +- return ret; +- } +- +- FWU_LOG_MSG("%s: exit: fwu state is changed to regular\n\r", __func__); +- return FWU_AGENT_SUCCESS; +-} +- +-static enum fwu_agent_error_t fwu_accept_image(struct efi_guid* guid, +- struct fwu_metadata *metadata, +- struct fwu_private_metadata *priv_metadata) +-{ +- enum fwu_agent_state_t current_state; +- int image_index; +- uint32_t image_bank_offset; +- enum fwu_agent_error_t ret; +- +- FWU_LOG_MSG("%s: enter\n\r", __func__); +- +- /* it is expected to receive this call only when +- in trial state */ +- current_state = get_fwu_agent_state(metadata, priv_metadata); +- if (current_state != FWU_AGENT_STATE_TRIAL) { +- return FWU_AGENT_ERROR; +- } +- +- /* booted from previous_active_bank, not expected +- * to receive this call in this state, rather host should +- * call corstone1000_fwu_select_previous */ +- if (metadata->active_index != priv_metadata->boot_index) { +- return FWU_AGENT_ERROR; +- } +- +- image_index = get_image_info_in_bank(guid, &image_bank_offset); +- switch(image_index) { +- case IMAGE_ALL: +- ret = accept_full_capsule(metadata, priv_metadata); +- break; +- default: +- FWU_LOG_MSG("%s: sent image not recognized\n\r", __func__); +- ret = FWU_AGENT_ERROR; +- break; +- } +- +- FWU_LOG_MSG("%s: exit: ret = %d\n\r", __func__, ret); +- return ret; +-} +- +-static enum fwu_agent_error_t fwu_select_previous( +- struct fwu_metadata *metadata, +- struct fwu_private_metadata *priv_metadata) +-{ +- enum fwu_agent_error_t ret; +- enum fwu_agent_state_t current_state; +- uint32_t index; +- +- FWU_LOG_MSG("%s: enter\n\r", __func__); +- +- /* it is expected to receive this call only when +- in trial state */ +- current_state = get_fwu_agent_state(metadata, priv_metadata); +- if (current_state != FWU_AGENT_STATE_TRIAL) { +- return FWU_AGENT_ERROR; +- } +- +- /* not expected to receive this call in this state, system +- * did not boot from previous active index */ +- if (metadata->previous_active_index != priv_metadata->boot_index) { +- return FWU_AGENT_ERROR; +- } +- +- FWU_LOG_MSG("%s: trial state: active index = %u, previous active = %u\n\r", +- __func__, metadata->active_index, metadata->previous_active_index); +- +- index = metadata->previous_active_index; +- for (int i = 0; i < NR_OF_IMAGES_IN_FW_BANK; i++) { +- if (metadata->img_entry[i].img_props[index].accepted != IMAGE_ACCEPTED) +- { +- FWU_ASSERT(0); +- } +- } +- +- index = metadata->active_index; +- metadata->active_index = metadata->previous_active_index; +- metadata->previous_active_index = index; +- +- priv_metadata->boot_attempted = 0; +- +- ret = private_metadata_write(priv_metadata); +- if (ret) { +- return ret; +- } +- metadata->crc_32 = crc32((uint8_t *)&metadata->version, +- sizeof(struct fwu_metadata) - sizeof(uint32_t)); +- +- ret = metadata_write(metadata); +- if (ret) { +- return ret; +- } +- +- FWU_LOG_MSG("%s: in regular state by choosing previous active bank\n\r", +- __func__); +- +- FWU_LOG_MSG("%s: exit: ret = %d\n\r", __func__, ret); +- return ret; +- +-} +- +-void bl1_get_active_bl2_image(uint32_t *offset) +-{ +- struct fwu_private_metadata priv_metadata; +- enum fwu_agent_state_t current_state; +- uint32_t boot_attempted; +- uint32_t boot_index; +- +- FWU_LOG_MSG("%s: enter\n\r", __func__); +- +- if (fwu_metadata_init()) { +- FWU_ASSERT(0); +- } +- +- if (private_metadata_read(&priv_metadata)) { +- FWU_ASSERT(0); +- } +- +- if (metadata_read(&_metadata)) { +- FWU_ASSERT(0); +- } +- +- current_state = get_fwu_agent_state(&_metadata, &priv_metadata); +- +- if (current_state == FWU_AGENT_STATE_REGULAR) { +- boot_index = _metadata.active_index; +- FWU_ASSERT(boot_index == priv_metadata.boot_index); +- boot_attempted = 0; +- } else if (current_state == FWU_AGENT_STATE_TRIAL) { +- boot_attempted = (++priv_metadata.boot_attempted); +- FWU_LOG_MSG("%s: attempting boot number = %u\n\r", +- __func__, boot_attempted); +- if (boot_attempted <= MAX_BOOT_ATTEMPTS_PER_BANK) { +- boot_index = _metadata.active_index; +- FWU_LOG_MSG("%s: booting from trial bank: %u\n\r", +- __func__, boot_index); +- } else if (boot_attempted <= (2 * MAX_BOOT_ATTEMPTS_PER_BANK)) { +- boot_index = _metadata.previous_active_index; +- FWU_LOG_MSG("%s: gave up booting from trial bank\n\r", __func__); +- FWU_LOG_MSG("%s: booting from previous active bank: %u\n\r", +- __func__, boot_index); +- } else { +- FWU_LOG_MSG("%s: cannot boot system from any bank, halting...\n\r", __func__); +- FWU_ASSERT(0); +- } +- } else { +- FWU_ASSERT(0); +- } +- +- priv_metadata.boot_index = boot_index; +- if (private_metadata_write(&priv_metadata) < 0) { +- FWU_ASSERT(0); +- } +- +- if (boot_index == BANK_0) { +- *offset = SE_BL2_BANK_0_OFFSET; +- } else if (boot_index == BANK_1) { +- *offset = SE_BL2_BANK_1_OFFSET; +- } else { +- FWU_ASSERT(0); +- } +- +- FWU_LOG_MSG("%s: exit: booting from bank = %u, offset = 0x%x\n\r", __func__, +- boot_index, *offset); +- +- return; +-} +- +-uint8_t bl2_get_boot_bank(void) +-{ +- uint8_t boot_index; +- struct fwu_private_metadata priv_metadata; +- FWU_LOG_MSG("%s: enter", __func__); +- if (fwu_metadata_init()) { +- FWU_ASSERT(0); +- } +- if (private_metadata_read(&priv_metadata)) { +- FWU_ASSERT(0); +- } +- boot_index = priv_metadata.boot_index; +- FWU_LOG_MSG("%s: exit: booting from bank = %u", __func__, boot_index); +- return boot_index; +-} +- +-static void disable_host_ack_timer(void) +-{ +- FWU_LOG_MSG("%s: timer to reset is disabled\n\r", __func__); +- SysTick->CTRL &= (~SysTick_CTRL_ENABLE_Msk); +-} +- +-static enum fwu_agent_error_t update_nv_counters( +- struct fwu_private_metadata* priv_metadata) +-{ +- enum tfm_plat_err_t err; +- uint32_t security_cnt; +- enum tfm_nv_counter_t tfm_nv_counter_i; +- +- FWU_LOG_MSG("%s: enter\n\r", __func__); +- +- for (int i = 0; i <= FWU_MAX_NV_COUNTER_INDEX; i++) { +- +- switch (i) { +- case FWU_BL2_NV_COUNTER: +- tfm_nv_counter_i = PLAT_NV_COUNTER_BL1_0; +- break; +- case FWU_TFM_NV_COUNTER: +- tfm_nv_counter_i = PLAT_NV_COUNTER_BL2_0; +- break; +- case FWU_TFA_NV_COUNTER: +- tfm_nv_counter_i = PLAT_NV_COUNTER_BL2_1; +- break; +- default: +- FWU_ASSERT(0); +- break; +- } +- +- err = tfm_plat_read_nv_counter(tfm_nv_counter_i, +- sizeof(security_cnt), (uint8_t *)&security_cnt); +- if (err != TFM_PLAT_ERR_SUCCESS) { +- return FWU_AGENT_ERROR; +- } +- +- if (priv_metadata->nv_counter[i] < security_cnt) { +- return FWU_AGENT_ERROR; +- } else if (priv_metadata->nv_counter[i] > security_cnt) { +- FWU_LOG_MSG("%s: updaing index = %u nv counter = %u->%u\n\r", +- __func__, i, security_cnt, +- priv_metadata->nv_counter[FWU_BL2_NV_COUNTER]); +- err = tfm_plat_set_nv_counter(tfm_nv_counter_i, +- priv_metadata->nv_counter[FWU_BL2_NV_COUNTER]); +- if (err != TFM_PLAT_ERR_SUCCESS) { +- return FWU_AGENT_ERROR; +- } +- } +- +- } +- +- FWU_LOG_MSG("%s: exit\n\r", __func__); +- return FWU_AGENT_SUCCESS; +-} +- +-enum fwu_agent_error_t corstone1000_fwu_host_ack(void) +-{ +- enum fwu_agent_error_t ret; +- struct fwu_private_metadata priv_metadata; +- enum fwu_agent_state_t current_state; +- +- FWU_LOG_MSG("%s: enter\n\r", __func__); +- +- if (!is_initialized) { +- return FWU_AGENT_ERROR; +- } +- +- Select_Write_Mode_For_Shared_Flash(); +- +- if (metadata_read(&_metadata)) { +- ret = FWU_AGENT_ERROR; +- goto out; +- } +- +- if (private_metadata_read(&priv_metadata)) { +- ret = FWU_AGENT_ERROR; +- goto out; +- } +- +- current_state = get_fwu_agent_state(&_metadata, &priv_metadata); +- if (current_state == FWU_AGENT_STATE_REGULAR) { +- +- ret = FWU_AGENT_SUCCESS; /* nothing to be done */ +- +- fmp_set_image_info(&full_capsule_image_guid, +- priv_metadata.fmp_version, +- priv_metadata.fmp_last_attempt_version, +- priv_metadata.fmp_last_attempt_status); +- +- goto out; +- +- } else if (current_state != FWU_AGENT_STATE_TRIAL) { +- FWU_ASSERT(0); +- } +- +- if (_metadata.active_index != priv_metadata.boot_index) { +- +- /* firmware update failed, revert back to previous bank */ +- +- priv_metadata.fmp_last_attempt_version = +- _metadata.img_entry[IMAGE_0].img_props[_metadata.active_index].version; +- +- priv_metadata.fmp_last_attempt_status = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL; +- +- ret = fwu_select_previous(&_metadata, &priv_metadata); +- +- } else { +- +- /* firmware update successful */ +- +- priv_metadata.fmp_version = +- _metadata.img_entry[IMAGE_0].img_props[_metadata.active_index].version; +- priv_metadata.fmp_last_attempt_version = +- _metadata.img_entry[IMAGE_0].img_props[_metadata.active_index].version; +- +- priv_metadata.fmp_last_attempt_status = LAST_ATTEMPT_STATUS_SUCCESS; +- +- ret = fwu_accept_image(&full_capsule_image_guid, &_metadata, +- &priv_metadata); +- if (!ret) { +- ret = update_nv_counters(&priv_metadata); +- } +- } +- +- if (ret == FWU_AGENT_SUCCESS) { +- disable_host_ack_timer(); +- fmp_set_image_info(&full_capsule_image_guid, +- priv_metadata.fmp_version, +- priv_metadata.fmp_last_attempt_version, +- priv_metadata.fmp_last_attempt_status); +- } +- +-out: +- Select_XIP_Mode_For_Shared_Flash(); +- +- FWU_LOG_MSG("%s: exit: ret = %d\n\r", __func__, ret); +- return ret; +-} +- +-static int systic_counter = 0; +- +-void SysTick_Handler(void) +-{ +- systic_counter++; +- if (systic_counter % 10 == 0) { +- SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; +- stdio_output_string("*", 1); +- SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; +- } +- if (systic_counter == HOST_ACK_TIMEOUT_SEC) { +- SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; +- stdio_output_string("timer expired!\n\r", +- sizeof("timer expired!\n\r")); +- NVIC_SystemReset(); +- } +-} +- +-/* When in trial state, start the timer for host to respond. +- * Diable timer when host responds back either by calling +- * corstone1000_fwu_accept_image or corstone1000_fwu_select_previous. +- * Otherwise, resets the system. +- */ +-void host_acknowledgement_timer_to_reset(void) +-{ +- struct fwu_private_metadata priv_metadata; +- enum fwu_agent_state_t current_state; +- +- FWU_LOG_MSG("%s: enter\n\r", __func__); +- +- Select_Write_Mode_For_Shared_Flash(); +- +- if (!is_initialized) { +- FWU_ASSERT(0); +- } +- +- if (private_metadata_read(&priv_metadata)) { +- FWU_ASSERT(0); +- } +- +- if (metadata_read(&_metadata)) { +- FWU_ASSERT(0); +- } +- +- Select_XIP_Mode_For_Shared_Flash(); +- +- current_state = get_fwu_agent_state(&_metadata, &priv_metadata); +- +- if (current_state == FWU_AGENT_STATE_TRIAL) { +- FWU_LOG_MSG("%s: in trial state, starting host ack timer\n\r", +- __func__); +- systic_counter = 0; +- if (SysTick_Config(SysTick_LOAD_RELOAD_Msk)) { +- FWU_LOG_MSG("%s: timer init failed\n\r", __func__); +- FWU_ASSERT(0); +- } else { +- FWU_LOG_MSG("%s: timer started: seconds to expire : %u\n\r", +- __func__, HOST_ACK_TIMEOUT_SEC); +- } +- } +- +- FWU_LOG_MSG("%s: exit\n\r", __func__); +- return; +-} +- +-/* stage nv counter into private metadata section of the flash. +- * staged nv counters are written to the otp when firmware update +- * is successful +- * the function assumes that the api is called in the boot loading +- * stage +- */ +-enum fwu_agent_error_t fwu_stage_nv_counter(enum fwu_nv_counter_index_t index, +- uint32_t img_security_cnt) +-{ +- struct fwu_private_metadata priv_metadata; +- +- FWU_LOG_MSG("%s: enter: index = %u, val = %u\n\r", __func__, +- index, img_security_cnt); +- +- if (!is_initialized) { +- FWU_ASSERT(0); +- } +- +- if (index > FWU_MAX_NV_COUNTER_INDEX) { +- return FWU_AGENT_ERROR; +- } +- +- if (private_metadata_read(&priv_metadata)) { +- FWU_ASSERT(0); +- } +- +- if (priv_metadata.nv_counter[index] != img_security_cnt) { +- priv_metadata.nv_counter[index] = img_security_cnt; +- if (private_metadata_write(&priv_metadata)) { +- FWU_ASSERT(0); +- } +- } +- +- FWU_LOG_MSG("%s: exit\n\r", __func__); +- return FWU_AGENT_SUCCESS; +-} +diff --git a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.h b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.h +deleted file mode 100644 +index 701f20558..000000000 +--- a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.h ++++ /dev/null +@@ -1,73 +0,0 @@ +-/* +- * Copyright (c) 2021-2023, Arm Limited. All rights reserved. +- * +- * SPDX-License-Identifier: BSD-3-Clause +- * +- */ +- +-#ifndef FWU_AGENT_H +-#define FWU_AGENT_H +- +-#ifdef ENABLE_FWU_AGENT_DEBUG_LOGS +- #include +- #define FWU_LOG_MSG(f_, ...) printf((f_), ##__VA_ARGS__) +-#else +- #define FWU_LOG_MSG(f_, ...) +-#endif +- +-enum fwu_agent_error_t { +- FWU_AGENT_SUCCESS = 0, +- FWU_AGENT_ERROR = (-1) +-}; +- +-#define FWU_ASSERT(_c_) \ +- if (!(_c_)) { \ +- FWU_LOG_MSG("%s:%d assert hit\n\r", __func__, __LINE__); \ +- while(1) {}; \ +- } \ +- +- +-/* Version used for the very first image of the device. */ +-#define FWU_IMAGE_INITIAL_VERSION 0 +- +-enum fwu_agent_error_t fwu_metadata_provision(void); +-enum fwu_agent_error_t fwu_metadata_init(void); +- +-/* host to secure enclave: +- * firwmare update image is sent accross +- */ +-enum fwu_agent_error_t corstone1000_fwu_flash_image(void); +- +-/* host to secure enclave: +- * host responds with this api to acknowledge its successful +- * boot. +- */ +-enum fwu_agent_error_t corstone1000_fwu_host_ack(void); +- +-void bl1_get_active_bl2_image(uint32_t *bank_offset); +-uint8_t bl2_get_boot_bank(void); +- +-/* When in trial state, start the timer for host to respond. +- * Diable timer when host responds back either by calling +- * corstone1000_fwu_accept_image or corstone1000_fwu_select_previous. +- * Otherwise, resets the system. +- */ +-void host_acknowledgement_timer_to_reset(void); +- +-enum fwu_nv_counter_index_t { +- FWU_BL2_NV_COUNTER = 0, +- FWU_TFM_NV_COUNTER, +- FWU_TFA_NV_COUNTER, +- FWU_MAX_NV_COUNTER_INDEX = FWU_TFA_NV_COUNTER +-}; +- +-/* stage nv counter into private metadata section of the flash. +- * staged nv counters are written to the otp when firmware update +- * is successful +- * the function assumes that the api is called in the boot loading +- * stage +- */ +-enum fwu_agent_error_t fwu_stage_nv_counter(enum fwu_nv_counter_index_t index, +- uint32_t img_security_cnt); +- +-#endif /* FWU_AGENT_H */ +diff --git a/platform/ext/target/arm/corstone1000/fw_update_agent/uefi_capsule_parser.c b/platform/ext/target/arm/corstone1000/fw_update_agent/uefi_capsule_parser.c +deleted file mode 100644 +index c706c040a..000000000 +--- a/platform/ext/target/arm/corstone1000/fw_update_agent/uefi_capsule_parser.c ++++ /dev/null +@@ -1,175 +0,0 @@ +-/* +- * Copyright (c) 2021, Arm Limited. All rights reserved. +- * +- * SPDX-License-Identifier: BSD-3-Clause +- * +- */ +- +-#include "uefi_capsule_parser.h" +-#include "fwu_agent.h" +-#include +- +-/* +-Update Capsule Structure (UEFI spec 2.9 1004) +- EFI_CAPSULE_HEADER +- ... +- ... +- ... +- CAPSULE_BODY +- efi_firmware_management_capsule_header +- Optional Driver 1 (item_offset[0]) +- Optional Driver 2 (item_offset[1]) +- Payload 1 (item_offset[2]) +- efi_firmware_management_capsule_iamge_header +- Binary Update image (Image_length == update_image_size) +- Vendor Code bytes (Data lenght == update_vendorcode_size) +- Payload 2 (item_offset[3]) +- ... +- ... +- Payload n (item_offset[embedded_driver_count + payload_item_count -1]) +-*/ +- +-typedef struct { +- struct efi_guid capsule_guid; +- uint32_t header_size; +- uint32_t flags; +- uint32_t capsule_image_size; +-} efi_capsule_header_t; +- +-typedef struct { +- uint32_t version; +- uint16_t embedded_driver_count; +- uint16_t payload_item_count; +- uint64_t item_offset_list[]; +-} efi_firmware_management_capsule_header_t; +- +-typedef struct { +- uint32_t version; +- struct efi_guid update_image_type_id; +- uint8_t update_image_index; +- uint8_t reserved_bytes[3]; +- uint32_t update_image_size; +- uint32_t update_vendorcode_size; +- uint64_t update_hardware_instance; //introduced in v2 +- uint64_t image_capsule_support; //introduced in v3 +-} efi_firmware_management_capsule_image_header_t; +- +-typedef struct { +- uint32_t signature; +- uint32_t header_size; +- uint32_t fw_version; +- uint32_t lowest_supported_version; +-} fmp_payload_header_t; +- +-#define ANYSIZE_ARRAY 0 +- +-typedef struct { +- uint32_t dwLength; +- uint16_t wRevision; +- uint16_t wCertificateType; +- uint8_t bCertificate[ANYSIZE_ARRAY]; +-} WIN_CERTIFICATE; +- +-typedef struct { +- WIN_CERTIFICATE hdr; +- struct efi_guid cert_type; +- uint8_t cert_data[ANYSIZE_ARRAY]; +-} win_certificate_uefi_guid_t; +- +-typedef struct { +- uint64_t monotonic_count; +- win_certificate_uefi_guid_t auth_info; +-} efi_firmware_image_authentication_t; +- +- +-enum uefi_capsule_error_t uefi_capsule_retrieve_images(void* capsule_ptr, +- capsule_image_info_t* images_info) +-{ +- char *ptr = (char*)capsule_ptr; +- efi_capsule_header_t* capsule_header; +- efi_firmware_management_capsule_header_t* fmp_capsule_header; +- efi_firmware_management_capsule_image_header_t* image_header; +- efi_firmware_image_authentication_t* image_auth; +- fmp_payload_header_t *fmp_payload_header; +- uint32_t total_size; +- uint32_t image_count; +- uint32_t auth_size; +- +- FWU_LOG_MSG("%s: enter, capsule ptr = 0x%p\n\r", __func__, capsule_ptr); +- +- if (!capsule_ptr) { +- return UEFI_CAPSULE_PARSER_ERROR; +- } +- +- capsule_header = (efi_capsule_header_t*)ptr; +- ptr += sizeof(efi_capsule_header_t); +- fmp_capsule_header = (efi_firmware_management_capsule_header_t*)ptr; +- +- total_size = capsule_header->capsule_image_size; +- image_count = fmp_capsule_header->payload_item_count; +- images_info->nr_image = image_count; +- +- FWU_LOG_MSG("%s: capsule size = %u, image count = %u\n\r", __func__, +- total_size, image_count); +- +- if ((image_count == 0) || (image_count > NR_OF_IMAGES_IN_FW_BANK)) { +- return UEFI_CAPSULE_PARSER_ERROR; +- } +- +- for (int i = 0; i < image_count; i++) { +- image_header = (efi_firmware_management_capsule_image_header_t*)(ptr + +- fmp_capsule_header->item_offset_list[i]); +- +- images_info->size[i] = image_header->update_image_size; +- +-#ifdef AUTHENTICATED_CAPSULE +- image_auth = (efi_firmware_image_authentication_t*)( +- (char*)image_header + +- sizeof (efi_firmware_management_capsule_image_header_t) +- ); +- auth_size = sizeof(uint64_t) /* monotonic_count */ + +- image_auth->auth_info.hdr.dwLength/* WIN_CERTIFICATE + cert_data + cert_type */; +- +- fmp_payload_header = (fmp_payload_header_t*)((char*)image_auth + auth_size); +- +- FWU_LOG_MSG("%s: auth size = %u\n\r", __func__, auth_size); +- +- images_info->size[i] -= auth_size; +- +- images_info->image[i] = ( +- (char*)image_header + +- sizeof(efi_firmware_management_capsule_image_header_t) + +- auth_size + +- sizeof(*fmp_payload_header)); +-#else +- images_info->image[i] = ( +- (char*)image_header + +- sizeof(efi_firmware_management_capsule_image_header_t) + +- sizeof(*fmp_payload_header)); +- +- fmp_payload_header = (fmp_payload_header_t*)((char*)image_header + +- sizeof(efi_firmware_management_capsule_image_header_t)); +- +-#endif +- memcpy(&images_info->guid[i], &(image_header->update_image_type_id), +- sizeof(struct efi_guid)); +- +- images_info->version[i] = fmp_payload_header->fw_version; +- FWU_LOG_MSG("%s: image %i version = %d\n\r", __func__, i, +- images_info->version[i]); +- +- FWU_LOG_MSG("%s: image %d at %p, size=%u\n\r", __func__, i, +- images_info->image[i], images_info->size[i]); +- +- if ((fmp_capsule_header->item_offset_list[i] + +- sizeof(efi_firmware_management_capsule_image_header_t) + +- image_header->update_image_size) > total_size) +- { +- return UEFI_CAPSULE_PARSER_ERROR; +- } +- +- } +- +- FWU_LOG_MSG("%s: exit\n\r", __func__); +- return UEFI_CAPSULE_PARSER_SUCCESS; +-} +diff --git a/platform/ext/target/arm/corstone1000/fw_update_agent/uefi_capsule_parser.h b/platform/ext/target/arm/corstone1000/fw_update_agent/uefi_capsule_parser.h +deleted file mode 100644 +index a31cd8a3a..000000000 +--- a/platform/ext/target/arm/corstone1000/fw_update_agent/uefi_capsule_parser.h ++++ /dev/null +@@ -1,33 +0,0 @@ +-/* +- * Copyright (c) 2021, Arm Limited. All rights reserved. +- * +- * SPDX-License-Identifier: BSD-3-Clause +- * +- */ +- +-#ifndef UEFI_CAPSULE_PARSER_H +-#define UEFI_CAPSULE_PARSER_H +- +-#include +-#include "fip_parser/external/uuid.h" +-#include "flash_layout.h" +- +-#define AUTHENTICATED_CAPSULE 1 +- +-enum uefi_capsule_error_t { +- UEFI_CAPSULE_PARSER_SUCCESS = 0, +- UEFI_CAPSULE_PARSER_ERROR = (-1) +-}; +- +-typedef struct capsule_image_info { +- uint32_t nr_image; +- void *image[NR_OF_IMAGES_IN_FW_BANK]; +- struct efi_guid guid[NR_OF_IMAGES_IN_FW_BANK]; +- uint32_t size[NR_OF_IMAGES_IN_FW_BANK]; +- uint32_t version[NR_OF_IMAGES_IN_FW_BANK]; +-} capsule_image_info_t; +- +-enum uefi_capsule_error_t uefi_capsule_retrieve_images(void* capsule_ptr, +- capsule_image_info_t* images_info); +- +-#endif /* UEFI_CAPSULE_PARSER_H */ +diff --git a/platform/ext/target/arm/corstone1000/partition/flash_layout.h b/platform/ext/target/arm/corstone1000/partition/flash_layout.h +index b183d1242..58b02229b 100644 +--- a/platform/ext/target/arm/corstone1000/partition/flash_layout.h ++++ b/platform/ext/target/arm/corstone1000/partition/flash_layout.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2017-2024 Arm Limited. All rights reserved. ++ * Copyright (c) 2017-2025 Arm Limited. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. +@@ -134,8 +134,16 @@ + */ + + /* Bank configurations */ +-#define BANK_PARTITION_SIZE (0xFE0000) /* 15.875 MB */ +-#define TFM_PARTITION_SIZE (0x50000) /* 320 KB */ ++#define BANK_PARTITION_SIZE (0xFE0000) /* 15.875 MB */ ++#define SE_BL2_PARTITION_BANK_OFFSET (0) ++#define TFM_PARTITION_SIZE (0x50000) /* 320 KB */ ++#define TFM_PARTITION_BANK_OFFSET (SE_BL2_PARTITION_SIZE) ++ ++#define FIP_PARTITION_SIZE (0x200000) /* 2 MB */ ++#define FIP_PARTITION_BANK_OFFSET (TFM_PARTITION_BANK_OFFSET + TFM_PARTITION_SIZE) ++ ++#define INITRAMFS_PARTITION_SIZE (0xC00000) /* 12 MB */ ++#define INITRAMFS_PARTITION_BANK_OFFSET (FIP_PARTITION_BANK_OFFSET + FIP_PARTITION_SIZE) + + /************************************************************/ + /* Bank : Images flash offsets are with respect to the bank */ +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-corstone1000.inc b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-corstone1000.inc index f49a4271..87302069 100644 --- a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-corstone1000.inc +++ b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-corstone1000.inc @@ -43,6 +43,9 @@ SRC_URI:append:corstone1000 = " \ file://0022-CC312-alignment-of-cc312-differences.patch \ file://0023-Platform-CS1000-Remove-duplicate-configuration-parameters.patch \ file://0024-Platform-corstone1000-Allow-FWU-calls-in-RSE-COMMS.patch \ + file://0025-FWU-Make-platform-specific-TFM_FWU_BOOTLOADER_LIB-se.patch \ + file://0026-Platform-CS1000-Enable-FWU-partition.patch \ + file://0027-Platform-Corstone1000-Implement-Bootloader-Abstracti.patch \ " FILESEXTRAPATHS:prepend:corstone1000-mps3 := "${THISDIR}/files/corstone1000/psa-adac:" From patchwork Wed Jul 30 11:53:17 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harsimran Singh Tungal X-Patchwork-Id: 67725 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id CC006C87FD6 for ; Wed, 30 Jul 2025 11:54:00 +0000 (UTC) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.web10.33469.1753876432952683973 for ; Wed, 30 Jul 2025 04:53:53 -0700 Authentication-Results: mx.groups.io; dkim=none (message not signed); spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: harsimransingh.tungal@arm.com) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 7DDB82573; Wed, 30 Jul 2025 04:53:44 -0700 (PDT) Received: from e132995.cambridge.arm.com (e132995.arm.com [10.1.25.25]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id EB4623F66E; Wed, 30 Jul 2025 04:53:51 -0700 (PDT) From: Harsimran Singh Tungal To: meta-arm@lists.yoctoproject.org Cc: Harsimran Singh Tungal Subject: [PATCH 03/13] arm-bsp/trusted-firmware-m: corstone-1000: Increase PS_MAX_ASSET_SIZE and CRYPTO_IOVEC_BUFFER_SIZE for EFI variable support Date: Wed, 30 Jul 2025 12:53:17 +0100 Message-Id: <20250730115327.3671160-4-harsimransingh.tungal@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250730115327.3671160-1-harsimransingh.tungal@arm.com> References: <20250730115327.3671160-1-harsimransingh.tungal@arm.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Wed, 30 Jul 2025 11:54:00 -0000 X-Groupsio-URL: https://lists.yoctoproject.org/g/meta-arm/message/6640 Increase `PS_MAX_ASSET_SIZE` and `CRYPTO_IOVEC_BUFFER_SIZE` for the Corstone-1000 platform to support large EFI variable storage required by the UEFI firmware update flow and to pass Arm Architecture Compliance Suite (ACS) tests. Signed-off-by: Harsimran Singh Tungal --- ...m-Corstone1000-Increase-buffer-sizes.patch | 40 +++++++++++++++++++ .../trusted-firmware-m-corstone1000.inc | 1 + 2 files changed, 41 insertions(+) create mode 100644 meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0028-Platform-Corstone1000-Increase-buffer-sizes.patch diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0028-Platform-Corstone1000-Increase-buffer-sizes.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0028-Platform-Corstone1000-Increase-buffer-sizes.patch new file mode 100644 index 00000000..2aaa4fcd --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0028-Platform-Corstone1000-Increase-buffer-sizes.patch @@ -0,0 +1,40 @@ +From e3d94988f14b3004606c247b39bda5ade119545f Mon Sep 17 00:00:00 2001 +From: Harsimran Singh Tungal +Date: Wed, 12 Mar 2025 13:10:47 +0000 +Subject: [PATCH 2/2] Platform: Corstone1000: Increase buffer sizes + +Increase PSA_MAX_ASSET_SIZE and CRYPTO_IOVEC_BUFFER_SIZE +to accommodate large size EFI variables set by new U-Boot version. + +This change is required to pass ACS tests related to Set/Get +EFI variables. These ACS tests started failing after introducing new +version of U-Boot, Trusted-Services and Trusted-Firmware-M while +implementing PSA FWU support. + +Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TF-M/trusted-firmware-m/+/39517/1] +Signed-off-by: Harsimran Singh Tungal +--- + platform/ext/target/arm/corstone1000/config_tfm_target.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/platform/ext/target/arm/corstone1000/config_tfm_target.h b/platform/ext/target/arm/corstone1000/config_tfm_target.h +index 0b410dfd4..a65305bd4 100644 +--- a/platform/ext/target/arm/corstone1000/config_tfm_target.h ++++ b/platform/ext/target/arm/corstone1000/config_tfm_target.h +@@ -24,11 +24,11 @@ + #define ITS_MAX_ASSET_SIZE 2048 + + /* The maximum asset size to be stored in the Protected Storage */ +-#define PS_MAX_ASSET_SIZE 2592 ++#define PS_MAX_ASSET_SIZE 3500 + + /* This is needed to be able to process the EFI variables during PS writes. */ + #define CRYPTO_ENGINE_BUF_SIZE 0x5000 + + /* This is also has to be increased to fit the EFI variables into the iovecs. */ +-#define CRYPTO_IOVEC_BUFFER_SIZE 6000 ++#define CRYPTO_IOVEC_BUFFER_SIZE 7200 + #endif /* __CONFIG_TFM_TARGET_H__ */ +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-corstone1000.inc b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-corstone1000.inc index 87302069..562abb7c 100644 --- a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-corstone1000.inc +++ b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-corstone1000.inc @@ -46,6 +46,7 @@ SRC_URI:append:corstone1000 = " \ file://0025-FWU-Make-platform-specific-TFM_FWU_BOOTLOADER_LIB-se.patch \ file://0026-Platform-CS1000-Enable-FWU-partition.patch \ file://0027-Platform-Corstone1000-Implement-Bootloader-Abstracti.patch \ + file://0028-Platform-Corstone1000-Increase-buffer-sizes.patch \ " FILESEXTRAPATHS:prepend:corstone1000-mps3 := "${THISDIR}/files/corstone1000/psa-adac:" From patchwork Wed Jul 30 11:53:18 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harsimran Singh Tungal X-Patchwork-Id: 67728 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id D8CEDC87FD3 for ; Wed, 30 Jul 2025 11:54:00 +0000 (UTC) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.web10.33472.1753876434135182769 for ; Wed, 30 Jul 2025 04:53:54 -0700 Authentication-Results: mx.groups.io; dkim=none (message not signed); spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: harsimransingh.tungal@arm.com) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id A2D8E2681; Wed, 30 Jul 2025 04:53:45 -0700 (PDT) Received: from e132995.cambridge.arm.com (e132995.arm.com [10.1.25.25]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id BF4943F66E; Wed, 30 Jul 2025 04:53:52 -0700 (PDT) From: Harsimran Singh Tungal To: meta-arm@lists.yoctoproject.org Cc: Harsimran Singh Tungal , Ali Can Ozaslan Subject: [PATCH 04/13] arm-bsp: corstone1000: Add PLATFORM_IS_FVP toggle for FVP/FPGA builds Date: Wed, 30 Jul 2025 12:53:18 +0100 Message-Id: <20250730115327.3671160-5-harsimransingh.tungal@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250730115327.3671160-1-harsimransingh.tungal@arm.com> References: <20250730115327.3671160-1-harsimransingh.tungal@arm.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Wed, 30 Jul 2025 11:54:00 -0000 X-Groupsio-URL: https://lists.yoctoproject.org/g/meta-arm/message/6641 Introduces PLATFORM_IS_FVP to differentiate between FVP and FPGA builds. Adds platform-specific CMake files for corstone1000-fvp and corstone1000-mps3, and updates platform.cmake to use this toggle. This commit also adds the TS_PLATFORM variable to corstone1000-fvp.conf and corstone1000-mps3.conf, explicitly defining platform identifiers for Trusted Services. This ensures a consistent and clear distinction between the FVP and MPS3 builds within the build system. These changes improve maintainability and platform-specific handling by making it easier to reference the correct target platform in configurations and scripts. Signed-off-by: Ali Can Ozaslan Signed-off-by: Harsimran Singh Tungal --- .../conf/machine/corstone1000-fvp.conf | 2 + .../conf/machine/corstone1000-mps3.conf | 2 + ...e1000-Add-PLATFORM_IS_FVP-toggle-for.patch | 77 +++++++++++++++++++ .../trusted-services/ts-arm-platforms.inc | 1 + 4 files changed, 82 insertions(+) create mode 100644 meta-arm-bsp/recipes-security/trusted-services/corstone1000/0017-Platform-Corstone1000-Add-PLATFORM_IS_FVP-toggle-for.patch diff --git a/meta-arm-bsp/conf/machine/corstone1000-fvp.conf b/meta-arm-bsp/conf/machine/corstone1000-fvp.conf index df0275ef..632bd028 100644 --- a/meta-arm-bsp/conf/machine/corstone1000-fvp.conf +++ b/meta-arm-bsp/conf/machine/corstone1000-fvp.conf @@ -7,6 +7,8 @@ TFA_TARGET_PLATFORM = "fvp" TFM_PLATFORM_IS_FVP = "TRUE" +TS_PLATFORM = "arm/corstone1000-fvp" + # testimage config TEST_TARGET = "OEFVPTarget" TEST_TARGET_IP = "127.0.0.1:2222" diff --git a/meta-arm-bsp/conf/machine/corstone1000-mps3.conf b/meta-arm-bsp/conf/machine/corstone1000-mps3.conf index 88f3d9dd..88d01b09 100644 --- a/meta-arm-bsp/conf/machine/corstone1000-mps3.conf +++ b/meta-arm-bsp/conf/machine/corstone1000-mps3.conf @@ -7,3 +7,5 @@ require conf/machine/include/corstone1000.inc TFA_TARGET_PLATFORM = "fpga" PLATFORM_IS_FVP = "FALSE" + +TS_PLATFORM = "arm/corstone1000-mps3" diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0017-Platform-Corstone1000-Add-PLATFORM_IS_FVP-toggle-for.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0017-Platform-Corstone1000-Add-PLATFORM_IS_FVP-toggle-for.patch new file mode 100644 index 00000000..b4c027cc --- /dev/null +++ b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0017-Platform-Corstone1000-Add-PLATFORM_IS_FVP-toggle-for.patch @@ -0,0 +1,77 @@ +From 00cbde17d3e38de385a6f0897cdd6d9bfe8250c7 Mon Sep 17 00:00:00 2001 +From: Ali Can Ozaslan +Date: Thu, 27 Feb 2025 14:06:07 +0000 +Subject: [PATCH 03/10] Platform: Corstone1000: Add PLATFORM_IS_FVP toggle for + FVP/FPGA builds + +Introduces PLATFORM_IS_FVP to differentiate between FVP and FPGA builds. +Adds platform-specific CMake files for corstone1000-fvp and corstone1000-mps3, +and updates platform.cmake to use this toggle. + +Upstream-Status: Pending +Signed-off-by: Ali Can Ozaslan +Signed-off-by: Harsimran Singh Tungal +--- + .../providers/arm/corstone1000-fvp/platform.cmake | 11 +++++++++++ + .../providers/arm/corstone1000-mps3/platform.cmake | 11 +++++++++++ + platform/providers/arm/corstone1000/platform.cmake | 3 ++- + 3 files changed, 24 insertions(+), 1 deletion(-) + create mode 100644 platform/providers/arm/corstone1000-fvp/platform.cmake + create mode 100644 platform/providers/arm/corstone1000-mps3/platform.cmake + +diff --git a/platform/providers/arm/corstone1000-fvp/platform.cmake b/platform/providers/arm/corstone1000-fvp/platform.cmake +new file mode 100644 +index 00000000..9a281e7a +--- /dev/null ++++ b/platform/providers/arm/corstone1000-fvp/platform.cmake +@@ -0,0 +1,11 @@ ++#------------------------------------------------------------------------------- ++# Copyright (c) 2025, Arm Limited and Contributors. All rights reserved. ++# ++# SPDX-License-Identifier: BSD-3-Clause ++# ++# Platform definition for the Corstone-1000-MPS3 platform. ++#------------------------------------------------------------------------------- ++ ++set(PLATFORM_IS_FVP 1 CACHE BOOL "Whether to enable FVP or FPGA build of the platform.") ++ ++include(${TS_PLATFORM_ROOT}/arm/corstone1000/platform.cmake) +diff --git a/platform/providers/arm/corstone1000-mps3/platform.cmake b/platform/providers/arm/corstone1000-mps3/platform.cmake +new file mode 100644 +index 00000000..ec92d1e5 +--- /dev/null ++++ b/platform/providers/arm/corstone1000-mps3/platform.cmake +@@ -0,0 +1,11 @@ ++#------------------------------------------------------------------------------- ++# Copyright (c) 2025, Arm Limited and Contributors. All rights reserved. ++# ++# SPDX-License-Identifier: BSD-3-Clause ++# ++# Platform definition for the Corstone-1000-FVP platform. ++#------------------------------------------------------------------------------- ++ ++set(PLATFORM_IS_FVP 0 CACHE BOOL "Whether to enable FVP or FPGA build of the platform.") ++ ++include(${TS_PLATFORM_ROOT}/arm/corstone1000/platform.cmake) +diff --git a/platform/providers/arm/corstone1000/platform.cmake b/platform/providers/arm/corstone1000/platform.cmake +index 04c8138f..60bc208b 100644 +--- a/platform/providers/arm/corstone1000/platform.cmake ++++ b/platform/providers/arm/corstone1000/platform.cmake +@@ -1,5 +1,5 @@ + #------------------------------------------------------------------------------- +-# Copyright (c) 2021-2024, Arm Limited and Contributors. All rights reserved. ++# Copyright (c) 2021-2025, Arm Limited and Contributors. All rights reserved. + # + # SPDX-License-Identifier: BSD-3-Clause + # +@@ -17,6 +17,7 @@ target_compile_definitions(${TGT} PRIVATE + PLAT_RSE_COMMS_PAYLOAD_MAX_SIZE=${PLAT_RSE_COMMS_PAYLOAD_MAX_SIZE} + COMMS_MHU_MSG_SIZE=${COMMS_MHU_MSG_SIZE} + MBEDTLS_ECP_DP_SECP521R1_ENABLED ++ PLATFORM_IS_FVP=${PLATFORM_IS_FVP} + ) + + get_property(_platform_driver_dependencies TARGET ${TGT} +-- +2.34.1 + diff --git a/meta-arm-bsp/recipes-security/trusted-services/ts-arm-platforms.inc b/meta-arm-bsp/recipes-security/trusted-services/ts-arm-platforms.inc index 543413ea..ed40ca7f 100644 --- a/meta-arm-bsp/recipes-security/trusted-services/ts-arm-platforms.inc +++ b/meta-arm-bsp/recipes-security/trusted-services/ts-arm-platforms.inc @@ -19,6 +19,7 @@ SRC_URI:append:corstone1000 = " \ file://0015-se-proxy-protobuf-change.patch \ file://0021-Align-PSA-Crypto-structs-with-TF-Mv2.1.1.patch \ file://0016-Add-the-com-buffer-address-and-page-count.patch \ + file://0017-Platform-Corstone1000-Add-PLATFORM_IS_FVP-toggle-for.patch \ " # The patches above introduce errors with GCC 14.1, silence them for now CFLAGS:append:corstone1000 = " -Wno-int-conversion -Wno-implicit-function-declaration" From patchwork Wed Jul 30 11:53:19 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harsimran Singh Tungal X-Patchwork-Id: 67730 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id C5D4DC87FD5 for ; Wed, 30 Jul 2025 11:54:00 +0000 (UTC) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.web11.33473.1753876435424064067 for ; Wed, 30 Jul 2025 04:53:55 -0700 Authentication-Results: mx.groups.io; dkim=none (message not signed); spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: harsimransingh.tungal@arm.com) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 04D9E2573; Wed, 30 Jul 2025 04:53:47 -0700 (PDT) Received: from e132995.cambridge.arm.com (e132995.arm.com [10.1.25.25]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 02EF53F66E; Wed, 30 Jul 2025 04:53:53 -0700 (PDT) From: Harsimran Singh Tungal To: meta-arm@lists.yoctoproject.org Cc: Harsimran Singh Tungal , Ali Can Ozaslan , Imre Kis Subject: [PATCH 05/13] arm-bsp/trusted-services: corstone1000: PSA FWU implementation Date: Wed, 30 Jul 2025 12:53:19 +0100 Message-Id: <20250730115327.3671160-6-harsimransingh.tungal@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250730115327.3671160-1-harsimransingh.tungal@arm.com> References: <20250730115327.3671160-1-harsimransingh.tungal@arm.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Wed, 30 Jul 2025 11:54:00 -0000 X-Groupsio-URL: https://lists.yoctoproject.org/g/meta-arm/message/6642 This commit implement the required changes in Trusted-Services in order to incorporate PSA FWU implementation. It involves the following changes: 1. Integrate IPC framework for PSA FWU calls between Cortex-A and Cortex-M subsystems. IPC framework is required to bridge the PSA FWU calls for the platforms which have both Cortex-A and Cortex-M subsystems. Corstone-1000 falls under this category of platforms. In these platforms, the PSA FWU client and PSA FWU provider exist on Cortex-A and all the PSA FWU services are implemented on Cortex-M side. This IPC framework forwards the PSA FWU calls from Cortex-A to Cortex-M subsystem. 2. Load initial image state in PSA FWU M update agent Set initial image state based on the image state returned by psa_fwu_query. This way the update agent has the correct view of images after reboot and it can accept or reject them. 3. Define PSA FWU image mapping structure. Define PSA FWU image mapping structure for Corstone-1000. This structure is responsible to map specific image guid with component number. To enable platform-specific handling, service_proxy_factory.c now conditionally selects the appropriate image mapping based on PLATFORM_IS_FVP. This ensures that both FVP and MPS3 platforms use the correct GUID and firmware update configuration. 4. Fix PSA FWU IPC psa_fwu_install() return value check This change adds support to validate if the return type in psa_fwu_install() is either PSA_SUCCESS or PSA_SUCCESS_REBOOT. Both the return values are expected. Earlier, only PSA_SUCCESS is validated. 5. Add ESRT support Add ESRT support for PSA FWU M agent. ESRT functionality is implemented using unique image dedicated for ESRT data having its own UUID. In PSA FWU M agent's context, this image has read only attributes. The ESRT data can be read using image_read_directory by using ESRT image UUID handle. The ESRT data is queried from Secure Enclave using psa_fwu_query() and ESRT data can be read from psa_fwu_impl_info_t structure object defined in psa_fwu_component_info_t. This commit includes the following changes: 1. Declare ESRT data structures. 2. Modify image_directory_read() to include ESRT data read support 3. Modify psa_fwu_m_update_agent_init to initialize ESRT image attributes 6. Enable ESRT support Enable ESRT support for Corstone-1000. Introduce ESRT image UUID and its component number and set TFM_FWU_MAX_DIGEST_SIZE to ESRT data size. 7. Add event provider proxy Normal world needs to send boot confirmation event to Secure Enclave and Trusted-Services is responsible to transfer the event to Secure Enclave. This commit implements the event handling framework in SE-proxy-SP and develops event provider proxy which forwards the event to Secure Enclave via psa calls. This change is introduced for Corstone-1000 8. Define GUID for each payloads Define GUID's for all the 4 payloads for FVP and MPS3. Signed-off-by: Harsimran Singh Tungal Signed-off-by: Ali Can Ozaslan Signed-off-by: Imre Kis --- ...-FWU-IPC-framework-for-Corstone-1000.patch | 436 ++++++++++++++++++ ...mage-state-in-PSA-FWU-M-update-agent.patch | 188 ++++++++ ...fine-PSA-FWU-image-mapping-structure.patch | 128 +++++ ...C-psa_fwu_install-return-value-check.patch | 31 ++ .../0022-fwu-Add-EFI-ESRT-v1-support.patch | 178 +++++++ ...orm-corstone1000-Enable-ESRT-support.patch | 129 ++++++ ...orstone1000-Add-event-provider-proxy.patch | 268 +++++++++++ ...ne1000-Define-GUID-for-each-payloads.patch | 141 ++++++ .../trusted-services/ts-arm-platforms.inc | 8 + 9 files changed, 1507 insertions(+) create mode 100644 meta-arm-bsp/recipes-security/trusted-services/corstone1000/0018-Integrate-PSA-FWU-IPC-framework-for-Corstone-1000.patch create mode 100644 meta-arm-bsp/recipes-security/trusted-services/corstone1000/0019-Load-initial-image-state-in-PSA-FWU-M-update-agent.patch create mode 100644 meta-arm-bsp/recipes-security/trusted-services/corstone1000/0020-Corstone1000-Define-PSA-FWU-image-mapping-structure.patch create mode 100644 meta-arm-bsp/recipes-security/trusted-services/corstone1000/0021-Fix-PSA-FWU-IPC-psa_fwu_install-return-value-check.patch create mode 100644 meta-arm-bsp/recipes-security/trusted-services/corstone1000/0022-fwu-Add-EFI-ESRT-v1-support.patch create mode 100644 meta-arm-bsp/recipes-security/trusted-services/corstone1000/0023-platform-corstone1000-Enable-ESRT-support.patch create mode 100644 meta-arm-bsp/recipes-security/trusted-services/corstone1000/0024-platform-corstone1000-Add-event-provider-proxy.patch create mode 100644 meta-arm-bsp/recipes-security/trusted-services/corstone1000/0025-platform-corstone1000-Define-GUID-for-each-payloads.patch diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0018-Integrate-PSA-FWU-IPC-framework-for-Corstone-1000.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0018-Integrate-PSA-FWU-IPC-framework-for-Corstone-1000.patch new file mode 100644 index 00000000..2c2bb428 --- /dev/null +++ b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0018-Integrate-PSA-FWU-IPC-framework-for-Corstone-1000.patch @@ -0,0 +1,436 @@ +From fcc7701baf4246e5ceebe4d50db223cb70a0c00f Mon Sep 17 00:00:00 2001 +From: Harsimran Singh Tungal +Date: Thu, 28 Nov 2024 12:02:28 +0000 +Subject: [PATCH 1/8] Integrate PSA FWU IPC framework for Corstone-1000 + +Integrate IPC framework for PSA FWU calls between Cortex-A side and Cortex-M subsystems. + +IPC framework is required to bridge the PSA FWU calls for the platforms which have +both Cortex-A and Cortex-M subsystems. Corstone-1000 falls under this category of +platforms. In these platforms, the PSA FWU client and PSA FWU provider exist on +Cortex-A and all the PSA FWU services are implemented on Cortex-M side. This IPC +framework forwards the PSA FWU calls from Cortex-A to Cortex-M subsystem. + +Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TS/trusted-services/+/33826] +Signed-off-by: Harsimran Singh Tungal +--- + components/service/common/include/psa/sid.h | 6 +- + .../interface/psa_ipc/component.cmake | 13 + + .../psa_fwu_m/interface/psa_ipc/psa_fwu_ipc.c | 253 ++++++++++++++++++ + .../psa_fwu_m/interface/psa_ipc/psa_fwu_ipc.h | 49 ++++ + .../se-proxy/infra/corstone1000/infra.cmake | 2 +- + .../corstone1000/service_proxy_factory.c | 16 ++ + 6 files changed, 337 insertions(+), 2 deletions(-) + create mode 100644 components/service/fwu/psa_fwu_m/interface/psa_ipc/component.cmake + create mode 100644 components/service/fwu/psa_fwu_m/interface/psa_ipc/psa_fwu_ipc.c + create mode 100644 components/service/fwu/psa_fwu_m/interface/psa_ipc/psa_fwu_ipc.h + +diff --git a/components/service/common/include/psa/sid.h b/components/service/common/include/psa/sid.h +index fc3a4fb0..4830f438 100644 +--- a/components/service/common/include/psa/sid.h ++++ b/components/service/common/include/psa/sid.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2019-2023, Arm Limited. All rights reserved. ++ * Copyright (c) 2019-2024, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * +@@ -65,6 +65,10 @@ extern "C" { + #define TFM_ATTEST_GET_TOKEN_SIZE 1002 + + /******** TFM_SP_FWU ********/ ++#define TFM_FIRMWARE_UPDATE_SERVICE_SID (0x000000A0U) ++#define TFM_FIRMWARE_UPDATE_SERVICE_VERSION (1U) ++#define TFM_FIRMWARE_UPDATE_SERVICE_HANDLE (0x40000104U) ++ + #define TFM_FWU_WRITE_SID (0x000000A0U) + #define TFM_FWU_WRITE_VERSION (1U) + #define TFM_FWU_INSTALL_SID (0x000000A1U) +diff --git a/components/service/fwu/psa_fwu_m/interface/psa_ipc/component.cmake b/components/service/fwu/psa_fwu_m/interface/psa_ipc/component.cmake +new file mode 100644 +index 00000000..cdc653a6 +--- /dev/null ++++ b/components/service/fwu/psa_fwu_m/interface/psa_ipc/component.cmake +@@ -0,0 +1,13 @@ ++#------------------------------------------------------------------------------- ++# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. ++# ++# SPDX-License-Identifier: BSD-3-Clause ++# ++#------------------------------------------------------------------------------- ++if (NOT DEFINED TGT) ++ message(FATAL_ERROR "mandatory parameter TGT is not defined.") ++endif() ++ ++target_sources(${TGT} PRIVATE ++ "${CMAKE_CURRENT_LIST_DIR}/psa_fwu_ipc.c" ++) +diff --git a/components/service/fwu/psa_fwu_m/interface/psa_ipc/psa_fwu_ipc.c b/components/service/fwu/psa_fwu_m/interface/psa_ipc/psa_fwu_ipc.c +new file mode 100644 +index 00000000..a47ae539 +--- /dev/null ++++ b/components/service/fwu/psa_fwu_m/interface/psa_ipc/psa_fwu_ipc.c +@@ -0,0 +1,253 @@ ++/* ++ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include "service/fwu/psa_fwu_m/interface/psa_ipc/psa_fwu_ipc.h" ++#include "service/fwu/psa_fwu_m/interface/tfm_fwu_defs.h" ++#include "service/fwu/psa_fwu_m/interface/update.h" ++ ++/** ++ * @brief The singleton psa_fwu_ipc instance ++ * ++ * The psa attestation C API assumes a single backend service provider. ++ */ ++static struct service_client instance; ++ ++psa_status_t psa_fwu_ipc_init(struct rpc_caller_session *session) ++{ ++ return service_client_init(&instance, session); ++} ++ ++void psa_fwu_ipc_deinit(void) ++{ ++ service_client_deinit(&instance); ++} ++ ++int psa_fwu_rpc_status(void) ++{ ++ return instance.rpc_status; ++} ++ ++psa_status_t psa_fwu_query(psa_fwu_component_t component, ++ psa_fwu_component_info_t *info) ++{ ++ if (!instance.session) ++ return PSA_ERROR_BAD_STATE; ++ if (!info) ++ return PSA_ERROR_INVALID_ARGUMENT; ++ ++ psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; ++ struct rpc_caller_interface *caller = instance.session->caller; ++ struct psa_invec in_vec[] = { ++ { .base = psa_ptr_to_u32(&component), .len = sizeof(component) }, ++ }; ++ struct psa_outvec out_vec[] = { ++ { .base = psa_ptr_to_u32(info), .len = sizeof(*info) }, ++ }; ++ ++ status = psa_call(caller, TFM_FIRMWARE_UPDATE_SERVICE_HANDLE, ++ TFM_FWU_QUERY, in_vec, IOVEC_LEN(in_vec), ++ out_vec, IOVEC_LEN(out_vec)); ++ if (status != PSA_SUCCESS) ++ EMSG("failed to psa_call: %d", status); ++ ++ return status; ++} ++ ++psa_status_t psa_fwu_start(psa_fwu_component_t component, ++ const void *manifest, ++ size_t manifest_size) ++{ ++ if(manifest_size > UINT32_MAX) ++ return PSA_ERROR_INVALID_ARGUMENT; ++ if (!instance.session) ++ return PSA_ERROR_BAD_STATE; ++ ++ psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; ++ struct rpc_caller_interface *caller = instance.session->caller; ++ struct psa_invec in_vec[] = { ++ { .base = psa_ptr_to_u32(&component), .len = sizeof(component) }, ++ { .base = psa_ptr_const_to_u32(manifest), .len = manifest_size }, ++ }; ++ ++ status = psa_call(caller, TFM_FIRMWARE_UPDATE_SERVICE_HANDLE, ++ TFM_FWU_START, in_vec, IOVEC_LEN(in_vec), ++ NULL, 0); ++ if (status != PSA_SUCCESS) ++ EMSG("failed to psa_call: %d", status); ++ ++ return status; ++} ++ ++psa_status_t psa_fwu_write(psa_fwu_component_t component, ++ size_t image_offset, ++ const void *block, ++ size_t block_size) ++{ ++ if (!instance.session) ++ return PSA_ERROR_BAD_STATE; ++ if (!block || !block_size) ++ return PSA_ERROR_INVALID_ARGUMENT; ++ if((image_offset > UINT32_MAX) || (block_size > UINT32_MAX)) ++ return PSA_ERROR_INVALID_ARGUMENT; ++ ++ psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; ++ struct rpc_caller_interface *caller = instance.session->caller; ++ struct psa_invec in_vec[] = { ++ { .base = psa_ptr_to_u32(&component), .len = sizeof(component) }, ++ { .base = psa_ptr_to_u32(&image_offset), .len = sizeof(uint32_t) }, ++ { .base = psa_ptr_const_to_u32(block), .len = block_size }, ++ }; ++ ++ status = psa_call(caller, TFM_FIRMWARE_UPDATE_SERVICE_HANDLE, ++ TFM_FWU_WRITE, in_vec, IOVEC_LEN(in_vec), ++ NULL, 0); ++ if (status != PSA_SUCCESS) ++ EMSG("failed to psa_call: %d", status); ++ ++ return status; ++} ++ ++psa_status_t psa_fwu_finish(psa_fwu_component_t component) ++{ ++ if (!instance.session) ++ return PSA_ERROR_BAD_STATE; ++ ++ psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; ++ struct rpc_caller_interface *caller = instance.session->caller; ++ struct psa_invec in_vec[] = { ++ { .base = psa_ptr_to_u32(&component), .len = sizeof(component) }, ++ }; ++ ++ status = psa_call(caller, TFM_FIRMWARE_UPDATE_SERVICE_HANDLE, ++ TFM_FWU_FINISH, in_vec, IOVEC_LEN(in_vec), ++ NULL, 0); ++ if (status != PSA_SUCCESS) ++ EMSG("failed to psa_call: %d", status); ++ ++ return status; ++} ++ ++psa_status_t psa_fwu_cancel(psa_fwu_component_t component) ++{ ++ if (!instance.session) ++ return PSA_ERROR_BAD_STATE; ++ ++ psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; ++ struct rpc_caller_interface *caller = instance.session->caller; ++ struct psa_invec in_vec[] = { ++ { .base = psa_ptr_to_u32(&component), .len = sizeof(component) }, ++ }; ++ ++ status = psa_call(caller, TFM_FIRMWARE_UPDATE_SERVICE_HANDLE, ++ TFM_FWU_CANCEL, in_vec, IOVEC_LEN(in_vec), ++ NULL, 0); ++ if (status != PSA_SUCCESS) ++ EMSG("failed to psa_call: %d", status); ++ ++ return status; ++} ++ ++psa_status_t psa_fwu_clean(psa_fwu_component_t component) ++{ ++ if (!instance.session) ++ return PSA_ERROR_BAD_STATE; ++ ++ psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; ++ struct rpc_caller_interface *caller = instance.session->caller; ++ struct psa_invec in_vec[] = { ++ { .base = psa_ptr_to_u32(&component), .len = sizeof(component) }, ++ }; ++ ++ status = psa_call(caller, TFM_FIRMWARE_UPDATE_SERVICE_HANDLE, ++ TFM_FWU_CLEAN, in_vec, IOVEC_LEN(in_vec), ++ NULL, 0); ++ if (status != PSA_SUCCESS) ++ EMSG("failed to psa_call: %d", status); ++ ++ return status; ++} ++ ++psa_status_t psa_fwu_install(void) ++{ ++ if (!instance.session) ++ return PSA_ERROR_BAD_STATE; ++ ++ psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; ++ struct rpc_caller_interface *caller = instance.session->caller; ++ struct psa_invec in_vec[] = {}; ++ ++ status = psa_call(caller, TFM_FIRMWARE_UPDATE_SERVICE_HANDLE, ++ TFM_FWU_INSTALL, in_vec, 0, ++ NULL, 0); ++ if (status != PSA_SUCCESS) ++ EMSG("failed to psa_call: %d", status); ++ ++ return status; ++} ++ ++psa_status_t psa_fwu_request_reboot(void) ++{ ++ if (!instance.session) ++ return PSA_ERROR_BAD_STATE; ++ ++ psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; ++ struct rpc_caller_interface *caller = instance.session->caller; ++ struct psa_invec in_vec[] = {}; ++ ++ status = psa_call(caller, TFM_FIRMWARE_UPDATE_SERVICE_HANDLE, ++ TFM_FWU_REQUEST_REBOOT, in_vec, 0, ++ NULL, 0); ++ if (status != PSA_SUCCESS) ++ EMSG("failed to psa_call: %d", status); ++ ++ return status; ++} ++ ++psa_status_t psa_fwu_reject(psa_status_t error) ++{ ++ if (!instance.session) ++ return PSA_ERROR_BAD_STATE; ++ ++ psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; ++ struct rpc_caller_interface *caller = instance.session->caller; ++ struct psa_invec in_vec[] = { ++ { .base = psa_ptr_to_u32(&error), .len = sizeof(error) }, ++ }; ++ ++ status = psa_call(caller, TFM_FIRMWARE_UPDATE_SERVICE_HANDLE, ++ TFM_FWU_REJECT, in_vec, IOVEC_LEN(in_vec), ++ NULL, 0); ++ if (status != PSA_SUCCESS) ++ EMSG("failed to psa_call: %d", status); ++ ++ return status; ++} ++ ++psa_status_t psa_fwu_accept(void) ++{ ++ if (!instance.session) ++ return PSA_ERROR_BAD_STATE; ++ ++ psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; ++ struct rpc_caller_interface *caller = instance.session->caller; ++ struct psa_invec in_vec[] = {}; ++ ++ status = psa_call(caller, TFM_FIRMWARE_UPDATE_SERVICE_HANDLE, ++ TFM_FWU_ACCEPT, in_vec, 0, ++ NULL, 0); ++ if (status != PSA_SUCCESS) ++ EMSG("failed to psa_call: %d", status); ++ ++ return status; ++} +diff --git a/components/service/fwu/psa_fwu_m/interface/psa_ipc/psa_fwu_ipc.h b/components/service/fwu/psa_fwu_m/interface/psa_ipc/psa_fwu_ipc.h +new file mode 100644 +index 00000000..867a1c9c +--- /dev/null ++++ b/components/service/fwu/psa_fwu_m/interface/psa_ipc/psa_fwu_ipc.h +@@ -0,0 +1,49 @@ ++/* ++ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef PSA_FWU_IPC_H ++#define PSA_FWU_IPC_H ++ ++#include ++#include "rpc_caller_session.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * @brief Initialize a PSA FWU ipc client ++ * ++ * A PSA FWU ipc client makes RPC calls to a remote FWU service. ++ * ++ * @param[in] rpc_caller RPC caller instance ++ * ++ * @return A status indicating the success/failure of the operation ++ */ ++psa_status_t psa_fwu_ipc_init(struct rpc_caller_session *session); ++ ++/** ++ * @brief Deinitialize a PSA FWU ipc client ++ * ++ */ ++void psa_fwu_ipc_deinit(void); ++ ++/** ++ * @brief Return the most recent RPC status ++ * ++ * May be used to obtain information about an RPC error that resulted ++ * in an API operation failure ++ * ++ * @return Most recent RPC operation status ++ */ ++int psa_fwu_rpc_status(void); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* PSA_FWU_IPC_H */ ++ +diff --git a/deployments/se-proxy/infra/corstone1000/infra.cmake b/deployments/se-proxy/infra/corstone1000/infra.cmake +index 27af8a33..0b04149a 100644 +--- a/deployments/se-proxy/infra/corstone1000/infra.cmake ++++ b/deployments/se-proxy/infra/corstone1000/infra.cmake +@@ -26,7 +26,7 @@ add_components(TARGET "se-proxy" + "components/service/fwu/provider" + "components/service/fwu/provider/serializer" + "components/service/fwu/psa_fwu_m/agent" +- "components/service/fwu/psa_fwu_m/interface/stub" ++ "components/service/fwu/psa_fwu_m/interface/psa_ipc" + "components/service/capsule_update/provider" + "components/service/secure_storage/backend/secure_storage_ipc" + ) +diff --git a/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c b/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c +index 8872abcb..ef91efe0 100644 +--- a/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c ++++ b/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c +@@ -15,6 +15,7 @@ + #include + #include "service/fwu/psa_fwu_m/agent/psa_fwu_m_update_agent.h" + #include "service/fwu/provider/fwu_provider.h" ++#include "service/fwu/psa_fwu_m/interface/psa_ipc/psa_fwu_ipc.h" + #include + #include "service/secure_storage/frontend/secure_storage_provider/secure_storage_uuid.h" + #include +@@ -135,10 +136,25 @@ struct rpc_service_interface *its_proxy_create(void) + + struct rpc_service_interface *fwu_proxy_create(void) + { ++ rpc_status_t rpc_status = RPC_ERROR_INTERNAL; + static struct update_agent *agent; + static struct fwu_provider fwu_provider = { 0 }; + ++ /* Static objects for proxy instance */ ++ static struct rpc_caller_interface rss_comms = { 0 }; ++ static struct rpc_caller_session rpc_session = { 0 }; ++ ++ rpc_status = rss_comms_caller_init(&rss_comms); ++ if (rpc_status != RPC_SUCCESS) ++ return NULL; ++ ++ rpc_status = rpc_caller_session_open(&rpc_session, &rss_comms, &dummy_uuid, 0, 0); ++ if (rpc_status != RPC_SUCCESS) ++ return NULL; ++ + agent = psa_fwu_m_update_agent_init(NULL, 0, 4096); ++ if (psa_fwu_ipc_init(&rpc_session) != PSA_SUCCESS) ++ return NULL; + + return fwu_provider_init(&fwu_provider, agent); + } +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0019-Load-initial-image-state-in-PSA-FWU-M-update-agent.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0019-Load-initial-image-state-in-PSA-FWU-M-update-agent.patch new file mode 100644 index 00000000..2f43369f --- /dev/null +++ b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0019-Load-initial-image-state-in-PSA-FWU-M-update-agent.patch @@ -0,0 +1,188 @@ +From 6fb3bead9e0eea3640ad1209347691c2b40512a2 Mon Sep 17 00:00:00 2001 +From: Imre Kis +Date: Wed, 5 Feb 2025 14:27:45 +0100 +Subject: [PATCH 2/8] Load initial image state in PSA FWU M update agent + +Set initial image state based on the image state returned by +psa_fwu_query. This way the update agent has the correct view of images +after reboot and it can accept or reject them. + +Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TS/trusted-services/+/35155] +Signed-off-by: Imre Kis +Change-Id: I150e4fdb4584c8d07f5f1f642ee88197f9cff49b +Signed-off-by: Harsimran Singh Tungal +--- + .../psa_fwu_m/agent/psa_fwu_m_update_agent.c | 23 +++++++-- + .../test/test_psa_fwu_m_update_agent.cpp | 49 ++++++++++++++++++- + docs/services/fwu/psa-fwu-m.rst | 14 +++++- + 3 files changed, 80 insertions(+), 6 deletions(-) + +diff --git a/components/service/fwu/psa_fwu_m/agent/psa_fwu_m_update_agent.c b/components/service/fwu/psa_fwu_m/agent/psa_fwu_m_update_agent.c +index 6de9ba71..48b86f6e 100644 +--- a/components/service/fwu/psa_fwu_m/agent/psa_fwu_m_update_agent.c ++++ b/components/service/fwu/psa_fwu_m/agent/psa_fwu_m_update_agent.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2024, Arm Limited. All rights reserved. ++ * Copyright (c) 2024-2025, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * +@@ -609,8 +609,11 @@ struct update_agent *psa_fwu_m_update_agent_init( + const struct psa_fwu_m_image_mapping image_mapping[], size_t image_count, + uint32_t max_payload_size) + { ++ psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; + struct psa_fwu_m_update_agent *context = NULL; ++ struct psa_fwu_component_info_t info = { 0 }; + struct psa_fwu_m_image *images = NULL; ++ enum psa_fwu_m_state state = regular; + struct update_agent *agent = NULL; + size_t i = 0; + +@@ -637,9 +640,23 @@ struct update_agent *psa_fwu_m_update_agent_init( + } + + for (i = 0; i < image_count; i++) { ++ psa_status = psa_fwu_query(image_mapping[i].component, &info); ++ if (psa_status != PSA_SUCCESS) { ++ free(images); ++ free(context); ++ free(agent); ++ return NULL; ++ } ++ + images[i].uuid = image_mapping[i].uuid; + images[i].component = image_mapping[i].component; +- images[i].selected_for_staging = false; ++ if (info.state == PSA_FWU_TRIAL) { ++ images[i].selected_for_staging = true; ++ state = trial; ++ } else { ++ images[i].selected_for_staging = false; ++ } ++ + images[i].read = NULL; /* Cannot read images */ + images[i].write = image_write; + } +@@ -654,7 +671,7 @@ struct update_agent *psa_fwu_m_update_agent_init( + context->images = images; + context->image_count = image_count + 1; + context->max_payload_size = max_payload_size; +- context->state = regular; ++ context->state = state; + + agent->context = context; + agent->interface = &interface; +diff --git a/components/service/fwu/psa_fwu_m/agent/test/test_psa_fwu_m_update_agent.cpp b/components/service/fwu/psa_fwu_m/agent/test/test_psa_fwu_m_update_agent.cpp +index de289fff..3805d182 100644 +--- a/components/service/fwu/psa_fwu_m/agent/test/test_psa_fwu_m_update_agent.cpp ++++ b/components/service/fwu/psa_fwu_m/agent/test/test_psa_fwu_m_update_agent.cpp +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2024, Arm Limited. All rights reserved. ++ * Copyright (c) 2024-2025, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * +@@ -14,6 +14,9 @@ + + TEST_GROUP(psa_fwu_m_update_agent) { + TEST_SETUP() { ++ psa_fwu_component_info_t info = {0}; ++ expect_mock_psa_fwu_query(mapping[0].component, &info, PSA_SUCCESS); ++ expect_mock_psa_fwu_query(mapping[1].component, &info, PSA_SUCCESS); + agent = psa_fwu_m_update_agent_init(mapping, 2, 4096); + handle = 0; + progress = 0; +@@ -667,4 +670,46 @@ TEST(psa_fwu_m_update_agent, select_previous) + + expect_mock_psa_fwu_reject(0, PSA_SUCCESS); + LONGS_EQUAL(FWU_STATUS_SUCCESS, update_agent_select_previous(agent)); +-} +\ No newline at end of file ++} ++ ++TEST(psa_fwu_m_update_agent, boot_in_trial_mode_query_fail) { ++ psa_fwu_component_info_t info = {0}; ++ ++ expect_mock_psa_fwu_query(mapping[0].component, &info, PSA_ERROR_GENERIC_ERROR); ++ POINTERS_EQUAL(NULL, psa_fwu_m_update_agent_init(mapping, 2, 4096)); ++} ++ ++TEST(psa_fwu_m_update_agent, boot_in_trial_mode_select_previous) { ++ psa_fwu_component_info_t info0 = {0}; ++ psa_fwu_component_info_t info1 = {0}; ++ ++ info1.state = PSA_FWU_TRIAL; ++ ++ expect_mock_psa_fwu_query(mapping[0].component, &info0, PSA_SUCCESS); ++ expect_mock_psa_fwu_query(mapping[1].component, &info1, PSA_SUCCESS); ++ ++ update_agent *agent = psa_fwu_m_update_agent_init(mapping, 2, 4096); ++ ++ expect_mock_psa_fwu_reject(0, PSA_SUCCESS); ++ LONGS_EQUAL(FWU_STATUS_SUCCESS, update_agent_select_previous(agent)); ++ ++ psa_fwu_m_update_agent_deinit(agent); ++} ++ ++TEST(psa_fwu_m_update_agent, boot_in_trial_mode_accept) { ++ psa_fwu_component_info_t info0 = {0}; ++ psa_fwu_component_info_t info1 = {0}; ++ ++ info1.state = PSA_FWU_TRIAL; ++ ++ expect_mock_psa_fwu_query(mapping[0].component, &info0, PSA_SUCCESS); ++ expect_mock_psa_fwu_query(mapping[1].component, &info1, PSA_SUCCESS); ++ ++ update_agent *agent = psa_fwu_m_update_agent_init(mapping, 2, 4096); ++ ++ expect_mock_psa_fwu_accept(PSA_SUCCESS); ++ LONGS_EQUAL(FWU_STATUS_DENIED, update_agent_accept_image(agent, &mapping[0].uuid)); ++ LONGS_EQUAL(FWU_STATUS_SUCCESS, update_agent_accept_image(agent, &mapping[1].uuid)); ++ ++ psa_fwu_m_update_agent_deinit(agent); ++} +diff --git a/docs/services/fwu/psa-fwu-m.rst b/docs/services/fwu/psa-fwu-m.rst +index 26ffed09..1358015f 100644 +--- a/docs/services/fwu/psa-fwu-m.rst ++++ b/docs/services/fwu/psa-fwu-m.rst +@@ -44,6 +44,11 @@ The solutions to these differences: + * Convert the image query result returned by FWU-M to FWU-A format. There are similar field, but this imposes some + limitations. + ++Initialization ++``````````````` ++ ++The initial image and agent state is determined based on the image state returned by ``psa_fwu_query()``. ++ + + ``fwu_discover()`` + `````````````````` +@@ -71,6 +76,10 @@ agent switches to trial state, so the client can validate the new set of images + + On calling ``fwu_end_staging()`` the agent calls ``psa_fwu_finish()`` on each selected image, then calls + ``psa_fwu_install()``. If all images have been accepted (see ``fwu_commit()``) it also calls ``psa_fwu_accept()``. ++The implementation treats ``PSA_SUCCESS_REBOOT`` and ``PSA_SUCCESS_RESTART`` status values as error. In an A+M system the M ++class side shouldn't restart the system, so calling ``psa_fwu_request_reboot()`` does not fit the system. There's also no ++PSA FWU A return code for inidicating the restart request to the normal world. If the normal world has to restart the ++system after ending the staging phase, it has to do it in an implementation defined way. + + .. uml:: ../uml/psa_fwu_m_update_agent/fwu_end_staging.puml + +@@ -136,7 +145,10 @@ calls ``psa_fwu_accept()`` when all images have been accepted. This results in a + ````````````````````````` + + Selects previous working state (i.e. rejects the firmware update) and transitions back to regular state after calling +-``psa_fwu_reject()``. ++``psa_fwu_reject()``. The implementation treats ``PSA_SUCCESS_REBOOT`` and ``PSA_SUCCESS_RESTART`` status values as error. ++In an A+M system the M class side shouldn't restart the system, so calling ``psa_fwu_request_reboot()`` does not fit the ++system. There's also no PSA FWU A return code for inidicating the restart request to the normal world. If the normal ++world has to restart the system when rejecting the installed firmware, it has to do it in an implementation defined way. + + .. uml:: ../uml/psa_fwu_m_update_agent/fwu_select_previous.puml + +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0020-Corstone1000-Define-PSA-FWU-image-mapping-structure.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0020-Corstone1000-Define-PSA-FWU-image-mapping-structure.patch new file mode 100644 index 00000000..17b1f87e --- /dev/null +++ b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0020-Corstone1000-Define-PSA-FWU-image-mapping-structure.patch @@ -0,0 +1,128 @@ +From 5344d7d0580ca7f2f2569f388dd6e3cd17a372f2 Mon Sep 17 00:00:00 2001 +From: Harsimran Singh Tungal +Date: Thu, 6 Feb 2025 10:26:04 +0000 +Subject: [PATCH 3/8] Corstone1000: Define PSA FWU image mapping structure + +This commit involves following changes + +1. Define PSA FWU image mapping structure for Corstone-1000. +This structure is responsible to map specific image guid with +component number. +To enable platform-specific handling, service_proxy_factory.c now +conditionally selects the appropriate image mapping +based on PLATFORM_IS_FVP. This ensures that both FVP and MPS3 +platforms use the correct GUID and firmware update configuration. + +2. Rename RSS to RSE + +Upstream-Status: Pending +Signed-off-by: Harsimran Singh Tungal +Signed-off-by: Ali Can Ozaslan +--- + .../infra/corstone1000/corstone1000_config.h | 28 +++++++++++++++++++ + .../corstone1000/service_proxy_factory.c | 25 +++++++++++++---- + 2 files changed, 48 insertions(+), 5 deletions(-) + create mode 100644 deployments/se-proxy/infra/corstone1000/corstone1000_config.h + +diff --git a/deployments/se-proxy/infra/corstone1000/corstone1000_config.h b/deployments/se-proxy/infra/corstone1000/corstone1000_config.h +new file mode 100644 +index 00000000..319401f3 +--- /dev/null ++++ b/deployments/se-proxy/infra/corstone1000/corstone1000_config.h +@@ -0,0 +1,28 @@ ++/* ++ * Copyright (c) 2025, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ * ++ */ ++ ++#ifndef CORSTONE1000_CONFIG_H ++#define CORSTONE1000_CONFIG_H ++ ++#define FWU_IMAGE_COUNT 1 ++ ++/* Maximum payload size to be transferred at once to Secure Enclave */ ++#define MAX_PAYLOAD_SIZE 4096 ++ ++#define CORSTONE1000_FVP_FULL_CAPSULE_UUID \ ++{ 0x4e, 0x3a, 0x9f, 0x98, 0xe0, 0x46, 0xd0, 0x4c, 0x98, 0x77, 0xa2, 0x5c, 0x70, 0xc0, 0x13, 0x29, } ++ ++#define CORSTONE1000_MPS3_FULL_CAPSULE_UUID \ ++{ 0xd1, 0x65, 0x18, 0xdf, 0xfb, 0x90, 0x59, 0x4d, 0x9c, 0x38, 0xc9, 0xf2, 0xc1, 0xbb, 0xa8, 0xcc, } ++ ++/* Image indexes in the UEFI capsule */ ++enum fwu_image_index ++{ ++ FWU_IMAGE_INDEX_FULL_CAPSULE = 1, ++}; ++ ++#endif /* CORSTONE1000_CONFIG_H */ +diff --git a/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c b/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c +index ef91efe0..6e5f1221 100644 +--- a/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c ++++ b/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2021-2024, Arm Limited and Contributors. All rights reserved. ++ * Copyright (c) 2021-2025, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2021-2023, Linaro Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause +@@ -19,6 +19,7 @@ + #include + #include "service/secure_storage/frontend/secure_storage_provider/secure_storage_uuid.h" + #include ++#include "corstone1000_config.h" + + /* backends */ + #include +@@ -27,6 +28,20 @@ + + static const struct rpc_uuid dummy_uuid = { 0 }; + ++static const struct psa_fwu_m_image_mapping img_mapping[FWU_IMAGE_COUNT] = { ++#if PLATFORM_IS_FVP ++ { ++ .uuid = CORSTONE1000_FVP_FULL_CAPSULE_UUID, ++ .component = FWU_IMAGE_INDEX_FULL_CAPSULE ++ }, ++#else ++ { ++ .uuid = CORSTONE1000_MPS3_FULL_CAPSULE_UUID, ++ .component = FWU_IMAGE_INDEX_FULL_CAPSULE ++ }, ++#endif ++}; ++ + struct rpc_service_interface *attest_proxy_create(void) + { + struct rpc_service_interface *attest_iface = NULL; +@@ -141,20 +156,20 @@ struct rpc_service_interface *fwu_proxy_create(void) + static struct fwu_provider fwu_provider = { 0 }; + + /* Static objects for proxy instance */ +- static struct rpc_caller_interface rss_comms = { 0 }; ++ static struct rpc_caller_interface rse_comms = { 0 }; + static struct rpc_caller_session rpc_session = { 0 }; + +- rpc_status = rss_comms_caller_init(&rss_comms); ++ rpc_status = rse_comms_caller_init(&rse_comms); + if (rpc_status != RPC_SUCCESS) + return NULL; + +- rpc_status = rpc_caller_session_open(&rpc_session, &rss_comms, &dummy_uuid, 0, 0); ++ rpc_status = rpc_caller_session_open(&rpc_session, &rse_comms, &dummy_uuid, 0, 0); + if (rpc_status != RPC_SUCCESS) + return NULL; + +- agent = psa_fwu_m_update_agent_init(NULL, 0, 4096); + if (psa_fwu_ipc_init(&rpc_session) != PSA_SUCCESS) + return NULL; ++ agent = psa_fwu_m_update_agent_init(img_mapping, FWU_IMAGE_COUNT, MAX_PAYLOAD_SIZE); + + return fwu_provider_init(&fwu_provider, agent); + } +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0021-Fix-PSA-FWU-IPC-psa_fwu_install-return-value-check.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0021-Fix-PSA-FWU-IPC-psa_fwu_install-return-value-check.patch new file mode 100644 index 00000000..da948bd0 --- /dev/null +++ b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0021-Fix-PSA-FWU-IPC-psa_fwu_install-return-value-check.patch @@ -0,0 +1,31 @@ +From d43ec82f7e419e6f1e9f5bd002c324b788ee901f Mon Sep 17 00:00:00 2001 +From: Harsimran Singh Tungal +Date: Thu, 6 Feb 2025 11:32:04 +0000 +Subject: [PATCH 4/8] Fix PSA FWU IPC psa_fwu_install() return value check + +This change adds support to validate if the return type in psa_fwu_install() +is either PSA_SUCCESS or PSA_SUCCESS_REBOOT. Both the return values are expected. +Earlier, only PSA_SUCCESS is validated. + +Upstream-Status: Pending +Signed-off-by: Harsimran Singh Tungal +--- + .../service/fwu/psa_fwu_m/interface/psa_ipc/psa_fwu_ipc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/components/service/fwu/psa_fwu_m/interface/psa_ipc/psa_fwu_ipc.c b/components/service/fwu/psa_fwu_m/interface/psa_ipc/psa_fwu_ipc.c +index a47ae539..3947a809 100644 +--- a/components/service/fwu/psa_fwu_m/interface/psa_ipc/psa_fwu_ipc.c ++++ b/components/service/fwu/psa_fwu_m/interface/psa_ipc/psa_fwu_ipc.c +@@ -190,7 +190,7 @@ psa_status_t psa_fwu_install(void) + status = psa_call(caller, TFM_FIRMWARE_UPDATE_SERVICE_HANDLE, + TFM_FWU_INSTALL, in_vec, 0, + NULL, 0); +- if (status != PSA_SUCCESS) ++ if (status != PSA_SUCCESS && status != PSA_SUCCESS_REBOOT) + EMSG("failed to psa_call: %d", status); + + return status; +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0022-fwu-Add-EFI-ESRT-v1-support.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0022-fwu-Add-EFI-ESRT-v1-support.patch new file mode 100644 index 00000000..ce810a35 --- /dev/null +++ b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0022-fwu-Add-EFI-ESRT-v1-support.patch @@ -0,0 +1,178 @@ +From 740359ba2a73f5ce0015c9023cc1aa69506f99bf Mon Sep 17 00:00:00 2001 +From: Harsimran Singh Tungal +Date: Fri, 28 Feb 2025 21:12:25 +0000 +Subject: [PATCH 5/8] fwu: Add EFI ESRT v1 support + +Add EFI ESRT v1 support for PSA FWU M agent. +ESRT functionality is implemented using unique image dedicated +for ESRT data having its own UUID. In PSA FWU M agent's context, +this image has read only attributes. The ESRT data can be read +using image_read_directory by using ESRT image UUID handle. The +ESRT data is queried from Secure Enclave using psa_fwu_query() +and ESRT data can be read from psa_fwu_impl_info_t structure +object defined in psa_fwu_component_info_t. + +This commit includes the following changes: +1. Declare EFI ESRT v1 data structures. +2. Modify image_directory_read() to include EFI ESRT data read support +3. Modify psa_fwu_m_update_agent_init to initialize ESRT image +attributes + +The ESRT v1 details can be found here : +https://uefi.org/specs/UEFI/2.9_A/23_Firmware_Update_and_Reporting.html#efi-system-resource-table + +Upstream-Status: Pending +Signed-off-by: Harsimran Singh Tungal +--- + .../psa_fwu_m/agent/psa_fwu_m_update_agent.c | 50 +++++++++++++++++-- + protocols/service/fwu/fwu_proto.h | 29 +++++++++-- + 2 files changed, 71 insertions(+), 8 deletions(-) + +diff --git a/components/service/fwu/psa_fwu_m/agent/psa_fwu_m_update_agent.c b/components/service/fwu/psa_fwu_m/agent/psa_fwu_m_update_agent.c +index 48b86f6e..d0464bf5 100644 +--- a/components/service/fwu/psa_fwu_m/agent/psa_fwu_m_update_agent.c ++++ b/components/service/fwu/psa_fwu_m/agent/psa_fwu_m_update_agent.c +@@ -115,13 +115,22 @@ uint32_t image_version_to_uint(psa_fwu_image_version_t version) + return result; + } + ++/* image_directory_read ++ * This function is used for two purposes: ++ * -> Send the details of firmware images to update client when read request is made for FWU_DIRECTORY_CANONICAL_UUID ++ * -> Send ESRT data to update client when read request is made for EFI_SYSTEM_RESOURCE_TABLE_CANONICAL_UUID ++ */ + int image_directory_read(struct psa_fwu_m_update_agent *agent, struct psa_fwu_m_image *image, + uint8_t *buf, size_t buf_size, size_t *read_len, size_t *total_len) + { + psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR; + psa_fwu_component_info_t component_info = { 0 }; + struct fwu_image_directory *directory = NULL; +- size_t image_count = agent->image_count - 1; /* Do not return Image directory */ ++ uint8_t esrt_image_uuid[OSF_UUID_OCTET_LEN]; ++ size_t image_count = agent->image_count - 1; /* Do not return Image directory ++ * If update client uses ESRT UUID for ESRT data, then ESRT image UUID ++ * is considered as a separate image included in this count ++ */ + size_t image_info_size = 0; + size_t i = 0; + +@@ -136,12 +145,36 @@ int image_directory_read(struct psa_fwu_m_update_agent *agent, struct psa_fwu_m_ + return FWU_STATUS_DENIED; /* LCOV_EXCL_LINE */ + + /* +- * If the directory structure doesn't fit into the buffer return SUCCESS with total_len set ++ * If the data to be read doesn't fit into the buffer return SUCCESS with total_len set + * and read_len = 0. + */ + if (*total_len > buf_size) + return FWU_STATUS_SUCCESS; + ++ /* Query ESRT data from Secure Enclave and Copy the ESRT entries from component_info.impl.candidate_digest ++ * to buf in case of ESRT image UUID. ++ * This is needed because Secure Enclave fills component_info.impl.candidate_digest with ESRT data ++ * which needs to be transferred to normal world buffer ++ */ ++ uuid_octets_from_canonical((struct uuid_octets *)&esrt_image_uuid, EFI_SYSTEM_RESOURCE_TABLE_CANONICAL_UUID); ++ if (!memcmp(&esrt_image_uuid, &image->uuid, sizeof(esrt_image_uuid))) { ++ /* Query ESRT data */ ++ psa_status = psa_fwu_query(image->component, &component_info); ++ if (psa_status != PSA_SUCCESS) ++ return psa_status_to_fwu_status(psa_status); ++ ++ struct efi_system_resource_table *esrt = (struct efi_system_resource_table *)component_info.impl.candidate_digest; ++ size_t esrt_size_recv = (esrt->fw_resource_count * sizeof(struct efi_system_resource_entry) ) + sizeof(struct efi_system_resource_table); ++ if(esrt_size_recv > TFM_FWU_MAX_DIGEST_SIZE) ++ return FWU_STATUS_OUT_OF_BOUNDS; ++ ++ /* Copy the ESRT entries to the buf */ ++ memcpy(buf, &component_info.impl.candidate_digest, esrt_size_recv); ++ *total_len = esrt_size_recv; ++ *read_len = *total_len; ++ return FWU_STATUS_SUCCESS; ++ } ++ + directory = (struct fwu_image_directory *)buf; + directory->directory_version = FWU_IMAGE_DIRECTORY_VERSION; + directory->img_info_offset = offsetof(struct fwu_image_directory, img_info_entry); +@@ -615,6 +648,7 @@ struct update_agent *psa_fwu_m_update_agent_init( + struct psa_fwu_m_image *images = NULL; + enum psa_fwu_m_state state = regular; + struct update_agent *agent = NULL; ++ uint8_t esrt_image_uuid[OSF_UUID_OCTET_LEN]; + size_t i = 0; + + /* Allocate +1 image for the Image directory */ +@@ -657,8 +691,16 @@ struct update_agent *psa_fwu_m_update_agent_init( + images[i].selected_for_staging = false; + } + +- images[i].read = NULL; /* Cannot read images */ +- images[i].write = image_write; ++ uuid_octets_from_canonical((struct uuid_octets *)&esrt_image_uuid, EFI_SYSTEM_RESOURCE_TABLE_CANONICAL_UUID); ++ if (!memcmp(&esrt_image_uuid, &images[i].uuid, sizeof(esrt_image_uuid))) { ++ images[i].read = image_directory_read; ++ images[i].write = NULL; ++ images[i].selected_for_staging = false; ++ } ++ else { ++ images[i].read = NULL; /* Cannot read images */ ++ images[i].write = image_write; ++ } + } + + /* Insert Image directory as the last image */ +diff --git a/protocols/service/fwu/fwu_proto.h b/protocols/service/fwu/fwu_proto.h +index 4bcacb1f..aa5d2561 100644 +--- a/protocols/service/fwu/fwu_proto.h ++++ b/protocols/service/fwu/fwu_proto.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2022-2024, Arm Limited and Contributors. All rights reserved. ++ * Copyright (c) 2022-2025, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +@@ -28,9 +28,10 @@ + /** + * Protocol GUIDs defined in FWU-A specification + */ +-#define FWU_UPDATE_AGENT_CANONICAL_UUID "6823a838-1b06-470e-9774-0cce8bfb53fd" +-#define FWU_DIRECTORY_CANONICAL_UUID "deee58d9-5147-4ad3-a290-77666e2341a5" +-#define FWU_METADATA_CANONICAL_UUID "8a7a84a0-8387-40f6-ab41-a8b9a5a60d23" ++#define FWU_UPDATE_AGENT_CANONICAL_UUID "6823a838-1b06-470e-9774-0cce8bfb53fd" ++#define FWU_DIRECTORY_CANONICAL_UUID "deee58d9-5147-4ad3-a290-77666e2341a5" ++#define FWU_METADATA_CANONICAL_UUID "8a7a84a0-8387-40f6-ab41-a8b9a5a60d23" ++#define EFI_SYSTEM_RESOURCE_TABLE_CANONICAL_UUID "63a222b1-6136-684f-9929-78f8b0d62180" + + #define FWU_OPEN_OP_TYPE_READ (0) + #define FWU_OPEN_OP_TYPE_WRITE (1) +@@ -40,6 +41,26 @@ + */ + #define FWU_IMAGE_DIRECTORY_VERSION (2) + ++/** ++ * @brief Information about the ESRT v1. ++ */ ++struct __attribute__((__packed__)) efi_system_resource_entry { ++ uint8_t fw_class[OSF_UUID_OCTET_LEN]; ++ uint32_t fw_type; ++ uint32_t fw_version; ++ uint32_t lowest_supported_fw_version; ++ uint32_t capsule_flags; ++ uint32_t last_attempt_version; ++ uint32_t last_attempt_status; ++}; ++ ++struct __attribute__((__packed__)) efi_system_resource_table { ++ uint32_t fw_resource_count; ++ uint32_t fw_resource_count_max; ++ uint64_t fw_resource_version; ++ struct efi_system_resource_entry entries[]; ++}; ++ + struct __attribute__((__packed__)) fwu_image_info_entry { + uint8_t img_type_uuid[OSF_UUID_OCTET_LEN]; + uint32_t client_permissions; +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0023-platform-corstone1000-Enable-ESRT-support.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0023-platform-corstone1000-Enable-ESRT-support.patch new file mode 100644 index 00000000..18581440 --- /dev/null +++ b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0023-platform-corstone1000-Enable-ESRT-support.patch @@ -0,0 +1,129 @@ +From 27d3ce79128478cd163a2db113326c873bda8d08 Mon Sep 17 00:00:00 2001 +From: Harsimran Singh Tungal +Date: Fri, 28 Feb 2025 21:12:56 +0000 +Subject: [PATCH 6/8] platform: corstone1000: Enable ESRT support + +Enable ESRT support for Corstone-1000. +Introduce ESRT image UUID and its component number and +set TFM_FWU_MAX_DIGEST_SIZE to ESRT data size. + +Upstream-Status: Pending +Signed-off-by: Harsimran Singh Tungal +--- + .../infra/corstone1000/corstone1000_config.h | 3 +-- + .../corstone1000/service_proxy_factory.c | 22 +++++++++++++++++-- + .../providers/arm/corstone1000/platform.cmake | 9 ++++++++ + 3 files changed, 30 insertions(+), 4 deletions(-) + +diff --git a/deployments/se-proxy/infra/corstone1000/corstone1000_config.h b/deployments/se-proxy/infra/corstone1000/corstone1000_config.h +index 319401f3..4a68c2fa 100644 +--- a/deployments/se-proxy/infra/corstone1000/corstone1000_config.h ++++ b/deployments/se-proxy/infra/corstone1000/corstone1000_config.h +@@ -8,8 +8,6 @@ + #ifndef CORSTONE1000_CONFIG_H + #define CORSTONE1000_CONFIG_H + +-#define FWU_IMAGE_COUNT 1 +- + /* Maximum payload size to be transferred at once to Secure Enclave */ + #define MAX_PAYLOAD_SIZE 4096 + +@@ -23,6 +21,7 @@ + enum fwu_image_index + { + FWU_IMAGE_INDEX_FULL_CAPSULE = 1, ++ FWU_IMAGE_INDEX_ESRT, + }; + + #endif /* CORSTONE1000_CONFIG_H */ +diff --git a/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c b/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c +index 6e5f1221..f0a4853e 100644 +--- a/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c ++++ b/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c +@@ -18,6 +18,7 @@ + #include "service/fwu/psa_fwu_m/interface/psa_ipc/psa_fwu_ipc.h" + #include + #include "service/secure_storage/frontend/secure_storage_provider/secure_storage_uuid.h" ++#include + #include + #include "corstone1000_config.h" + +@@ -26,9 +27,17 @@ + #include + #include + ++/* IMAGE_MAPPING_ELEMENT_COUNT includes the number of images to be updated and ESRT image */ ++#define IMAGE_MAPPING_ELEMENT_COUNT (FWU_IMAGE_CAPSULE_COUNT + 1) ++ ++/* The index to access the ESRT image in the psa_fwu_m_image_mapping structure ++ * collection. The ESRT image is always accessed at the end of the collection. ++ */ ++#define IMAGE_MAPPING_ESRT_INDEX (IMAGE_MAPPING_ELEMENT_COUNT - 1) ++ + static const struct rpc_uuid dummy_uuid = { 0 }; + +-static const struct psa_fwu_m_image_mapping img_mapping[FWU_IMAGE_COUNT] = { ++static struct psa_fwu_m_image_mapping img_mapping[IMAGE_MAPPING_ELEMENT_COUNT] = { + #if PLATFORM_IS_FVP + { + .uuid = CORSTONE1000_FVP_FULL_CAPSULE_UUID, +@@ -42,6 +51,13 @@ static const struct psa_fwu_m_image_mapping img_mapping[FWU_IMAGE_COUNT] = { + #endif + }; + ++/* Every platform needs to define esrt image mapping, if ESRT image UUID is to be used to extract ESRT data */ ++static void define_esrt_image_mapping() ++{ ++ uuid_octets_from_canonical(&img_mapping[IMAGE_MAPPING_ESRT_INDEX].uuid, EFI_SYSTEM_RESOURCE_TABLE_CANONICAL_UUID); ++ img_mapping[IMAGE_MAPPING_ESRT_INDEX].component = FWU_IMAGE_INDEX_ESRT; ++} ++ + struct rpc_service_interface *attest_proxy_create(void) + { + struct rpc_service_interface *attest_iface = NULL; +@@ -169,7 +185,9 @@ struct rpc_service_interface *fwu_proxy_create(void) + + if (psa_fwu_ipc_init(&rpc_session) != PSA_SUCCESS) + return NULL; +- agent = psa_fwu_m_update_agent_init(img_mapping, FWU_IMAGE_COUNT, MAX_PAYLOAD_SIZE); ++ ++ define_esrt_image_mapping(); ++ agent = psa_fwu_m_update_agent_init(img_mapping, IMAGE_MAPPING_ELEMENT_COUNT, MAX_PAYLOAD_SIZE); + + return fwu_provider_init(&fwu_provider, agent); + } +diff --git a/platform/providers/arm/corstone1000/platform.cmake b/platform/providers/arm/corstone1000/platform.cmake +index 60bc208b..db1e9743 100644 +--- a/platform/providers/arm/corstone1000/platform.cmake ++++ b/platform/providers/arm/corstone1000/platform.cmake +@@ -6,11 +6,18 @@ + # Platform definition for the Corstone-1000 platform. + #------------------------------------------------------------------------------- + ++# For ESRT v1 details : https://uefi.org/specs/UEFI/2.9_A/23_Firmware_Update_and_Reporting.html#efi-system-resource-table ++set(FWU_IMAGE_CAPSULE_COUNT 4 CACHE STRING "Maximum number of FWU Images in a capsule to be updated") ++set(ESRT_IMAGE_ENTRY_SIZE 40 CACHE STRING "Size of one ESRT v1 Image entry structure object") ++set(ESRT_REMAINING_FIELDS_SIZE 16 CACHE STRING "Size of remaining fields of ESRT v1 table structure") ++math(EXPR TOTAL_ESRT_SIZE "${FWU_IMAGE_CAPSULE_COUNT} * ${ESRT_IMAGE_ENTRY_SIZE} + ${ESRT_REMAINING_FIELDS_SIZE}" OUTPUT_FORMAT DECIMAL) ++ + set(SMM_GATEWAY_MAX_UEFI_VARIABLES 80 CACHE STRING "Maximum UEFI variable count") + set(SMM_RPC_CALLER_SESSION_SHARED_MEMORY_SIZE 4*4096 CACHE STRING "RPC caller buffer size in SMMGW") + set(SMM_SP_HEAP_SIZE 80*1024 CACHE STRING "SMM gateway SP heap size") + set(PLAT_RSE_COMMS_PAYLOAD_MAX_SIZE 0x43C0 CACHE STRING "Size of the RSE_COMMS_PAYLOAD buffer") + set(COMMS_MHU_MSG_SIZE 0x4500 CACHE STRING "Max message size that can be transfered via MHU") ++set(TFM_FWU_MAX_DIGEST_SIZE ${TOTAL_ESRT_SIZE} CACHE STRING "Maximum size of ESRT entries of all the images in a bank") + + target_compile_definitions(${TGT} PRIVATE + SMM_VARIABLE_INDEX_STORAGE_UID=0x787 +@@ -18,6 +25,8 @@ target_compile_definitions(${TGT} PRIVATE + COMMS_MHU_MSG_SIZE=${COMMS_MHU_MSG_SIZE} + MBEDTLS_ECP_DP_SECP521R1_ENABLED + PLATFORM_IS_FVP=${PLATFORM_IS_FVP} ++ TFM_FWU_MAX_DIGEST_SIZE=${TFM_FWU_MAX_DIGEST_SIZE} ++ FWU_IMAGE_CAPSULE_COUNT=${FWU_IMAGE_CAPSULE_COUNT} + ) + + get_property(_platform_driver_dependencies TARGET ${TGT} +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0024-platform-corstone1000-Add-event-provider-proxy.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0024-platform-corstone1000-Add-event-provider-proxy.patch new file mode 100644 index 00000000..8de9f081 --- /dev/null +++ b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0024-platform-corstone1000-Add-event-provider-proxy.patch @@ -0,0 +1,268 @@ +From dde0ca3260ae3b7e7c3390ef03f9f484e9189626 Mon Sep 17 00:00:00 2001 +From: Harsimran Singh Tungal +Date: Tue, 11 Mar 2025 13:33:36 +0000 +Subject: [PATCH 7/8] platform: corstone1000: Add event provider proxy + +Normal world needs to send boot confirmation event +to Secure Enclave and Trusted-Services is responsible +to transfer the event to Secure Enclave. +This commit implements the event handling framework in +SE-proxy-SP and develops event provider proxy which +forwards the event to Secure Enclave via psa calls. +This change is introduced for Corstone-1000 + +Upstream-Status: Pending +Signed-off-by: Harsimran Singh Tungal +--- + .../se-proxy/env/commonsp/se_proxy_sp.c | 16 +++- + .../corstone1000_event_handling.c | 91 +++++++++++++++++++ + .../corstone1000_event_handling.h | 42 +++++++++ + .../se-proxy/infra/corstone1000/infra.cmake | 1 + + .../corstone1000/service_proxy_factory.c | 27 ++++++ + 5 files changed, 175 insertions(+), 2 deletions(-) + create mode 100644 deployments/se-proxy/infra/corstone1000/corstone1000_event_handling.c + create mode 100644 deployments/se-proxy/infra/corstone1000/corstone1000_event_handling.h + +diff --git a/deployments/se-proxy/env/commonsp/se_proxy_sp.c b/deployments/se-proxy/env/commonsp/se_proxy_sp.c +index 7da489ca..7d2ade5e 100644 +--- a/deployments/se-proxy/env/commonsp/se_proxy_sp.c ++++ b/deployments/se-proxy/env/commonsp/se_proxy_sp.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: BSD-3-Clause + /* +- * Copyright (c) 2021-2024, Arm Limited and Contributors. All rights reserved. ++ * Copyright (c) 2021-2025, Arm Limited and Contributors. All rights reserved. + */ + + #include "components/rpc/common/endpoint/rpc_service_interface.h" +@@ -40,7 +40,7 @@ void __noreturn sp_main(union ffa_boot_info *boot_info) + goto fatal_error; + } + +- rpc_status = ts_rpc_endpoint_sp_init(&rpc_endpoint, 7, 16); ++ rpc_status = ts_rpc_endpoint_sp_init(&rpc_endpoint, 8, 16); + if (rpc_status != RPC_SUCCESS) { + EMSG("Failed to initialize RPC endpoint: %d", rpc_status); + goto fatal_error; +@@ -95,6 +95,18 @@ void __noreturn sp_main(union ffa_boot_info *boot_info) + goto fatal_error; + } + ++ rpc_iface = event_handler_proxy_create(); ++ if (!rpc_iface) { ++ EMSG("Failed to create Capsule Update proxy"); ++ goto fatal_error; ++ } ++ ++ rpc_status = ts_rpc_endpoint_sp_add_service(&rpc_endpoint, rpc_iface); ++ if (rpc_status != RPC_SUCCESS) { ++ EMSG("Failed to add service to RPC endpoint: %d", rpc_status); ++ goto fatal_error; ++ } ++ + rpc_iface = capsule_update_proxy_create(); + if (!rpc_iface) { + EMSG("Failed to create Capsule Update proxy"); +diff --git a/deployments/se-proxy/infra/corstone1000/corstone1000_event_handling.c b/deployments/se-proxy/infra/corstone1000/corstone1000_event_handling.c +new file mode 100644 +index 00000000..faf450f2 +--- /dev/null ++++ b/deployments/se-proxy/infra/corstone1000/corstone1000_event_handling.c +@@ -0,0 +1,91 @@ ++/* ++ * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++ ++#include ++#include "corstone1000_event_handling.h" ++ ++#define BOOT_CONFIRMED_EVENT (0x3) ++#define OPCODE_BOOT_CONFIRMED BOOT_CONFIRMED_EVENT ++ ++enum corstone1000_ioctl_id { ++ IOCTL_CORSTONE1000_FWU_HOST_ACK = 1, ++}; ++ ++/* Service request handlers */ ++static rpc_status_t boot_confirmed_handler(void *context, struct rpc_request *req); ++ ++/* Handler mapping table for service */ ++static const struct service_handler handler_table[] = { ++ {OPCODE_BOOT_CONFIRMED, boot_confirmed_handler} ++}; ++ ++struct rpc_service_interface *corstone1000_event_provider_init( ++ struct event_provider *context) ++{ ++ struct rpc_service_interface *rpc_interface = NULL; ++ const struct rpc_uuid dummy_uuid = { .uuid = { 0 }}; ++ if (!context) ++ return NULL; ++ ++ service_provider_init( ++ &context->base_provider, ++ context, ++ &dummy_uuid, ++ handler_table, ++ sizeof(handler_table)/sizeof(struct service_handler)); ++ ++ rpc_interface = service_provider_get_rpc_interface(&context->base_provider); ++ ++ return rpc_interface; ++} ++ ++static rpc_status_t event_handler(uint32_t opcode, struct rpc_caller_interface *caller) ++{ ++ uint32_t ioctl_id; ++ rpc_status_t rpc_status = TS_RPC_CALL_ACCEPTED; ++ ++ struct psa_invec in_vec[] = { ++ { .base = &ioctl_id, .len = sizeof(ioctl_id) } ++ }; ++ ++ if(!caller) { ++ EMSG("event_handler rpc_caller is NULL"); ++ rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE; ++ return rpc_status; ++ } ++ ++ IMSG("event handler opcode %x", opcode); ++ switch(opcode) { ++ case OPCODE_BOOT_CONFIRMED: ++ ioctl_id = IOCTL_CORSTONE1000_FWU_HOST_ACK; ++ /* Boot Confirmed event from Normal World */ ++ ++ psa_call(caller,TFM_PLATFORM_SERVICE_HANDLE, TFM_PLATFORM_API_ID_IOCTL, ++ in_vec,IOVEC_LEN(in_vec), NULL, 0); ++ break; ++ default: ++ EMSG("%s unsupported opcode", __func__); ++ rpc_status = TS_RPC_ERROR_INVALID_PARAMETER; ++ } ++ return rpc_status; ++ ++} ++ ++static rpc_status_t boot_confirmed_handler(void *context, struct rpc_request *req) ++{ ++ struct event_provider *this_instance = (struct event_provider*)context; ++ struct rpc_caller_interface *caller = this_instance->client.session->caller; ++ uint32_t opcode = req->opcode; ++ rpc_status_t rpc_status; ++ ++ rpc_status = event_handler(opcode, caller); ++ ++ return rpc_status; ++} +diff --git a/deployments/se-proxy/infra/corstone1000/corstone1000_event_handling.h b/deployments/se-proxy/infra/corstone1000/corstone1000_event_handling.h +new file mode 100644 +index 00000000..e8e60dae +--- /dev/null ++++ b/deployments/se-proxy/infra/corstone1000/corstone1000_event_handling.h +@@ -0,0 +1,42 @@ ++/* ++ * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef CORSTONE1000_EVENT_HANDLING_H ++#define CORSTONE1000_EVENT_HANDLING_H ++ ++#include ++#include ++#include ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * The event_provider is a service provider that accepts events ++ * and delegates them to a suitable backend. ++ */ ++struct event_provider ++{ ++ struct service_provider base_provider; ++ struct service_client client; ++}; ++ ++/** ++ * \brief Initialize an instance of the event handler ++ * ++ * @param[in] context The instance to initialize ++ * ++ * \return An rpc_service_interface or NULL on failure ++ */ ++struct rpc_service_interface *corstone1000_event_provider_init( ++ struct event_provider *context); ++ ++#ifdef __cplusplus ++} /* extern "C" */ ++#endif ++ ++#endif /* CORSTONE1000_EVENT_HANDLING_H */ +diff --git a/deployments/se-proxy/infra/corstone1000/infra.cmake b/deployments/se-proxy/infra/corstone1000/infra.cmake +index 0b04149a..b95801de 100644 +--- a/deployments/se-proxy/infra/corstone1000/infra.cmake ++++ b/deployments/se-proxy/infra/corstone1000/infra.cmake +@@ -34,4 +34,5 @@ add_components(TARGET "se-proxy" + target_sources(se-proxy PRIVATE + + ${CMAKE_CURRENT_LIST_DIR}/service_proxy_factory.c ++ ${CMAKE_CURRENT_LIST_DIR}/corstone1000_event_handling.c + ) +diff --git a/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c b/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c +index f0a4853e..ed42e2cb 100644 +--- a/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c ++++ b/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c +@@ -21,6 +21,7 @@ + #include + #include + #include "corstone1000_config.h" ++#include "corstone1000_event_handling.h" + + /* backends */ + #include +@@ -165,6 +166,32 @@ struct rpc_service_interface *its_proxy_create(void) + return secure_storage_provider_init(&its_provider, backend, &its_uuid); + } + ++struct rpc_service_interface *event_handler_proxy_create(void) ++{ ++ static struct event_provider event_provider = {0}; ++ rpc_status_t rpc_status = RPC_ERROR_INTERNAL; ++ ++ /* Static objects for proxy instance */ ++ static struct rpc_caller_interface rse_comms = { 0 }; ++ static struct rpc_caller_session rpc_session = { 0 }; ++ ++ rpc_status = rse_comms_caller_init(&rse_comms); ++ if (rpc_status != RPC_SUCCESS) ++ return NULL; ++ ++ rpc_status = rpc_caller_session_open(&rpc_session, &rse_comms, &dummy_uuid, 0, 0); ++ if (rpc_status != RPC_SUCCESS) ++ return NULL; ++ ++ ++ event_provider.client.session = &rpc_session; ++ event_provider.client.rpc_status = RPC_SUCCESS; ++ event_provider.client.service_info.supported_encodings = 0; ++ event_provider.client.service_info.max_payload = 4096; ++ ++ return corstone1000_event_provider_init(&event_provider); ++} ++ + struct rpc_service_interface *fwu_proxy_create(void) + { + rpc_status_t rpc_status = RPC_ERROR_INTERNAL; +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0025-platform-corstone1000-Define-GUID-for-each-payloads.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0025-platform-corstone1000-Define-GUID-for-each-payloads.patch new file mode 100644 index 00000000..61ab4680 --- /dev/null +++ b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0025-platform-corstone1000-Define-GUID-for-each-payloads.patch @@ -0,0 +1,141 @@ +From 6a26d67c0b531af07537aefcbe7a46fc71471d4f Mon Sep 17 00:00:00 2001 +From: Ali Can Ozaslan +Date: Thu, 27 Mar 2025 13:42:03 +0000 +Subject: [PATCH 8/8] platform: corstone1000: Define GUID for FWU payloads + +Specify the Global Unique Identifiers (GUIDs) for firmware update (FWU) +payloads, which include BL2, TFM_S, FIP, and INITRAMFS. +Note that the GUIDs differ between FVP and MPS3 platforms. + +Upstream-Status: Pending +Signed-off-by: Ali Can Ozaslan +Signed-off-by: Harsimran Singh Tungal +--- + .../infra/corstone1000/corstone1000_config.h | 43 ++++++++++++++++--- + .../corstone1000/service_proxy_factory.c | 41 +++++++++++++++--- + 2 files changed, 73 insertions(+), 11 deletions(-) + +diff --git a/deployments/se-proxy/infra/corstone1000/corstone1000_config.h b/deployments/se-proxy/infra/corstone1000/corstone1000_config.h +index 4a68c2fa..c4bd9c2c 100644 +--- a/deployments/se-proxy/infra/corstone1000/corstone1000_config.h ++++ b/deployments/se-proxy/infra/corstone1000/corstone1000_config.h +@@ -11,17 +11,48 @@ + /* Maximum payload size to be transferred at once to Secure Enclave */ + #define MAX_PAYLOAD_SIZE 4096 + +-#define CORSTONE1000_FVP_FULL_CAPSULE_UUID \ +-{ 0x4e, 0x3a, 0x9f, 0x98, 0xe0, 0x46, 0xd0, 0x4c, 0x98, 0x77, 0xa2, 0x5c, 0x70, 0xc0, 0x13, 0x29, } ++/* ++ * GUIDs for capsule updatable firmware images ++ * ++ * The GUIDs are generated with the UUIDv5 format with the following configurations: ++ * Namespace (for FVP GUIDs): 989f3a4e-46e0-4cd0-9877-a25c70c01329 ++ * Namespace (for MPS3 GUIDs): df1865d1-90fb-4d59-9c38-c9f2c1bba8cc ++ * Names: in the `fw_name` field: `BL2`, `TFM_S`, `FIP`, `INITRAMFS` ++ * Note: Using the same namespace and `fw_name` values should generate the same GUIDs. ++ */ ++ ++#define FWU_FVP_BL2_CAPSULE_UUID \ ++{ 0xf9, 0x83, 0xd8, 0xf1, 0xeb, 0xdf, 0x63, 0x53, 0x98, 0xd8, 0x68, 0x6e, 0xe3, 0xb6, 0x9f, 0x4f, } ++ ++#define FWU_FVP_TFM_S_CAPSULE_UUID \ ++{ 0x0e, 0x47, 0xad, 0x7f, 0xc5, 0x5e, 0x03, 0x5c, 0xa2, 0xc1, 0x47, 0x56, 0xb4, 0x95, 0xde, 0x61, } ++ ++#define FWU_FVP_FIP_CAPSULE_UUID \ ++{ 0x75, 0x36, 0x93, 0xf1, 0x8c, 0x5a, 0x6d, 0x5b, 0x9e, 0xf4, 0x84, 0x67, 0x39, 0xe8, 0x9b, 0xc8, } ++ ++#define FWU_FVP_INITRAMFS_CAPSULE_UUID \ ++{ 0xf9, 0xaf, 0x71, 0xf7, 0xe9, 0xc7, 0x99, 0x5f, 0x9e, 0xda, 0x23, 0x69, 0xdd, 0x69, 0x4f, 0x61, } ++ ++#define FWU_MPS3_BL2_CAPSULE_UUID \ ++{ 0xaa, 0xef, 0xfb, 0xfb, 0x56, 0x0a, 0xd5, 0x50, 0xb6, 0x51, 0x74, 0x09, 0x1d, 0x3d, 0x62, 0xcf, } ++ ++#define FWU_MPS3_TFM_S_CAPSULE_UUID \ ++{ 0xad, 0xc7, 0x4c, 0xaf, 0x2e, 0xee, 0x39, 0x5a, 0xaa, 0xd5, 0xfa, 0xc8, 0xa1, 0xe6, 0x17, 0x3c, } ++ ++#define FWU_MPS3_FIP_CAPSULE_UUID \ ++{ 0x96, 0x2f, 0x30, 0x55, 0xf0, 0xc4, 0xf9, 0x5c, 0x86, 0x24, 0xe7, 0xcc, 0x38, 0x8f, 0x2b, 0x68, } + +-#define CORSTONE1000_MPS3_FULL_CAPSULE_UUID \ +-{ 0xd1, 0x65, 0x18, 0xdf, 0xfb, 0x90, 0x59, 0x4d, 0x9c, 0x38, 0xc9, 0xf2, 0xc1, 0xbb, 0xa8, 0xcc, } ++#define FWU_MPS3_INITRAMFS_CAPSULE_UUID \ ++{ 0x72, 0xc9, 0x8a, 0x3e, 0x3c, 0xc3, 0xc9, 0x5c, 0x90, 0xa0, 0xcd, 0xd3, 0x15, 0x96, 0x83, 0xea, } + + /* Image indexes in the UEFI capsule */ + enum fwu_image_index + { +- FWU_IMAGE_INDEX_FULL_CAPSULE = 1, +- FWU_IMAGE_INDEX_ESRT, ++ FWU_IMAGE_INDEX_CAPSULE_BL2 = 1, ++ FWU_IMAGE_INDEX_CAPSULE_TFM_S, ++ FWU_IMAGE_INDEX_CAPSULE_FIP, ++ FWU_IMAGE_INDEX_CAPSULE_INITRAMFS, ++ FWU_IMAGE_INDEX_ESRT , + }; + + #endif /* CORSTONE1000_CONFIG_H */ +diff --git a/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c b/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c +index ed42e2cb..43a9ac37 100644 +--- a/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c ++++ b/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c +@@ -28,7 +28,14 @@ + #include + #include + +-/* IMAGE_MAPPING_ELEMENT_COUNT includes the number of images to be updated and ESRT image */ ++/* IMAGE_MAPPING_ELEMENT_COUNT includes the number of images to be updated and ESRT image. ++ * It includes: ++ * - BL2 ++ * - TFM_S ++ * - FIP ++ * - INITRAMFS ++ * - ESRT ++ */ + #define IMAGE_MAPPING_ELEMENT_COUNT (FWU_IMAGE_CAPSULE_COUNT + 1) + + /* The index to access the ESRT image in the psa_fwu_m_image_mapping structure +@@ -41,13 +48,37 @@ static const struct rpc_uuid dummy_uuid = { 0 }; + static struct psa_fwu_m_image_mapping img_mapping[IMAGE_MAPPING_ELEMENT_COUNT] = { + #if PLATFORM_IS_FVP + { +- .uuid = CORSTONE1000_FVP_FULL_CAPSULE_UUID, +- .component = FWU_IMAGE_INDEX_FULL_CAPSULE ++ .uuid = FWU_FVP_BL2_CAPSULE_UUID, ++ .component = FWU_IMAGE_INDEX_CAPSULE_BL2 ++ }, ++ { ++ .uuid = FWU_FVP_TFM_S_CAPSULE_UUID, ++ .component = FWU_IMAGE_INDEX_CAPSULE_TFM_S ++ }, ++ { ++ .uuid = FWU_FVP_FIP_CAPSULE_UUID, ++ .component = FWU_IMAGE_INDEX_CAPSULE_FIP ++ }, ++ { ++ .uuid = FWU_FVP_INITRAMFS_CAPSULE_UUID, ++ .component = FWU_IMAGE_INDEX_CAPSULE_INITRAMFS + }, + #else + { +- .uuid = CORSTONE1000_MPS3_FULL_CAPSULE_UUID, +- .component = FWU_IMAGE_INDEX_FULL_CAPSULE ++ .uuid = FWU_MPS3_BL2_CAPSULE_UUID, ++ .component = FWU_IMAGE_INDEX_CAPSULE_BL2 ++ }, ++ { ++ .uuid = FWU_MPS3_TFM_S_CAPSULE_UUID, ++ .component = FWU_IMAGE_INDEX_CAPSULE_TFM_S ++ }, ++ { ++ .uuid = FWU_MPS3_FIP_CAPSULE_UUID, ++ .component = FWU_IMAGE_INDEX_CAPSULE_FIP ++ }, ++ { ++ .uuid = FWU_MPS3_INITRAMFS_CAPSULE_UUID, ++ .component = FWU_IMAGE_INDEX_CAPSULE_INITRAMFS + }, + #endif + }; +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-security/trusted-services/ts-arm-platforms.inc b/meta-arm-bsp/recipes-security/trusted-services/ts-arm-platforms.inc index ed40ca7f..060725f1 100644 --- a/meta-arm-bsp/recipes-security/trusted-services/ts-arm-platforms.inc +++ b/meta-arm-bsp/recipes-security/trusted-services/ts-arm-platforms.inc @@ -20,6 +20,14 @@ SRC_URI:append:corstone1000 = " \ file://0021-Align-PSA-Crypto-structs-with-TF-Mv2.1.1.patch \ file://0016-Add-the-com-buffer-address-and-page-count.patch \ file://0017-Platform-Corstone1000-Add-PLATFORM_IS_FVP-toggle-for.patch \ + file://0018-Integrate-PSA-FWU-IPC-framework-for-Corstone-1000.patch \ + file://0019-Load-initial-image-state-in-PSA-FWU-M-update-agent.patch \ + file://0020-Corstone1000-Define-PSA-FWU-image-mapping-structure.patch \ + file://0021-Fix-PSA-FWU-IPC-psa_fwu_install-return-value-check.patch \ + file://0022-fwu-Add-EFI-ESRT-v1-support.patch \ + file://0023-platform-corstone1000-Enable-ESRT-support.patch \ + file://0024-platform-corstone1000-Add-event-provider-proxy.patch \ + file://0025-platform-corstone1000-Define-GUID-for-each-payloads.patch \ " # The patches above introduce errors with GCC 14.1, silence them for now CFLAGS:append:corstone1000 = " -Wno-int-conversion -Wno-implicit-function-declaration" From patchwork Wed Jul 30 11:53:20 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harsimran Singh Tungal X-Patchwork-Id: 67729 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id B6AD3C87FD4 for ; Wed, 30 Jul 2025 11:54:00 +0000 (UTC) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.web10.33473.1753876436695492286 for ; Wed, 30 Jul 2025 04:53:56 -0700 Authentication-Results: mx.groups.io; dkim=none (message not signed); spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: harsimransingh.tungal@arm.com) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 444BA2573; Wed, 30 Jul 2025 04:53:48 -0700 (PDT) Received: from e132995.cambridge.arm.com (e132995.arm.com [10.1.25.25]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 53AC73F66E; Wed, 30 Jul 2025 04:53:55 -0700 (PDT) From: Harsimran Singh Tungal To: meta-arm@lists.yoctoproject.org Cc: Ali Can Ozaslan , Harsimran Singh Tungal Subject: [PATCH 06/13] arm/uefi_capsule: Switch Capsule generation tool from U-Boot to EDK2 Date: Wed, 30 Jul 2025 12:53:20 +0100 Message-Id: <20250730115327.3671160-7-harsimransingh.tungal@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250730115327.3671160-1-harsimransingh.tungal@arm.com> References: <20250730115327.3671160-1-harsimransingh.tungal@arm.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Wed, 30 Jul 2025 11:54:00 -0000 X-Groupsio-URL: https://lists.yoctoproject.org/g/meta-arm/message/6643 From: Ali Can Ozaslan This commit updates the uefi_capsule.bbclass to use the EDK2 GenerateCapsule tool instead of the mkeficapsule utility from U-Boot. The switch was necessary because the mkeficapsule utility from U-Boot does not support generating capsules with multiple payloads, whereas the EDK2 GenerateCapsule tool provides native support for multi-image capsule creation. These changes allow building UEFI capsules with multiple firmware binaries in one step, making the firmware update process more flexible. - Switching dependency from u-boot-tools-native to edk2-basetools-native - Updating the actual capsule creation command to GenerateCapsule with the appropriate flags (including hardware instance, lowest supported version, and monotonic count) * CAPSULE_HARDWARE_INSTANCE defines which hardware instance the capsule update is intended for. This can be set to "1" or "0" indicating the first hardware module or SoC. For systems with multiple modules, subsequent instances could be numbered 2, 3, etc. * CAPSULE_LOWEST_SUPPORTED_VERSION enables roll-back protection by specifying the minimum firmware version that the platform accepts. Any firmware update below this version will be rejected.It should be set 0, 1, 2, etc according to your firmware security and versioning requirements. - Combining certificates into the private key file as required by GenerateCapsule - Add support for multiple firmware payloads This update refactors the capsule generation process to support multiple firmware binaries instead of a single payload. Key changes include: - Integration of a JSON generator script to define multiple payloads - Add default path for JSON config generator and prepare test infrastructure. - Introduction of new variables * CAPSULE_ALL_COMPONENTS: of all available components to be included in the capsule generation process. * CAPSULE_SELECTED_COMPONENTS: Subset of components from CAPSULE_ALL_COMPONENTS that should actually be included in the final capsule image. - Replacement of direct GenerateCapsule arguments with JSON input - Allow passing custom arguments to GenerateCapsule via `CAPSULE_EXTRA_ARGS` variable - Cleanup of temporary files used in the capsule generation process These changes align with EDK2's flexible capsule format and enable component level filtering for more advanced firmware update scenarios. Signed-off-by: Ali Can Ozaslan Signed-off-by: Harsimran Singh Tungal --- meta-arm/classes/uefi_capsule.bbclass | 93 +++++++++--- meta-arm/conf/layer.conf | 3 + .../scripts/generate_capsule_json_multiple.py | 142 ++++++++++++++++++ 3 files changed, 213 insertions(+), 25 deletions(-) create mode 100644 meta-arm/scripts/generate_capsule_json_multiple.py diff --git a/meta-arm/classes/uefi_capsule.bbclass b/meta-arm/classes/uefi_capsule.bbclass index a0709c0f..9d98959d 100644 --- a/meta-arm/classes/uefi_capsule.bbclass +++ b/meta-arm/classes/uefi_capsule.bbclass @@ -1,51 +1,94 @@ # This class generates UEFI capsules -# The current class supports generating a capsule with single firmware binary +# The current class supports generating a capsule with multiple firmware binaries IMAGE_TYPES += "uefi_capsule" -# u-boot-tools should be installed in the native sysroot directory -do_image_uefi_capsule[depends] += "u-boot-tools-native:do_populate_sysroot" +# edk2-basetools should be installed in the native sysroot directory +do_image_uefi_capsule[depends] += "edk2-basetools-native:do_populate_sysroot" # By default the wic image is used to create a capsule CAPSULE_IMGTYPE ?= "wic" # IMGDEPLOYDIR is used as the default location of firmware binary for which the capsule needs to be created -CAPSULE_IMGLOCATION ?= "${IMGDEPLOYDIR}" +CAPSULE_IMG_LOCATION ?= "${IMGDEPLOYDIR}" # The generated capsule by default has uefi.capsule extension CAPSULE_EXTENSION ?= "uefi.capsule" # The generated capsule's name by default is the same as UEFI_FIRMWARE_BINARY -CAPSULE_NAME ?= "${UEFI_FIRMWARE_BINARY}" +CAPSULE_NAME ??= "${UEFI_FIRMWARE_BINARY}" + +# The generated capsule configuration file extension +CAPSULE_CONFIG_FILE_EXTENSION ?= "json" + +# The generated capsule configuration file +CAPSULE_CONFIG_FILE ?= "${IMGDEPLOYDIR}/${CAPSULE_NAME}.${CAPSULE_CONFIG_FILE_EXTENSION}" + +# Path to the script that generates the UEFI capsule payloads JSON +UEFI_CAPSULE_CONFIG_GENERATOR_SCRIPT ?= "${META_ARM_LAYER_DIR}/scripts/generate_capsule_json_multiple.py" + +# Additional variables for capsule component filtering +CAPSULE_ALL_COMPONENTS ?= "" +CAPSULE_SELECTED_COMPONENTS ??= "" + +# Variables required by the EDK2 GenerateCapsule tool. +CAPSULE_CERTIFICATE_PATHS ?= "" +CAPSULE_FW_VERSIONS ?= "" +CAPSULE_GUIDS ?= "" +CAPSULE_INDEXES ?= "" +CAPSULE_HARDWARE_INSTANCES ?= "" +CAPSULE_LOWEST_SUPPORTED_VERSIONS ?= "" +CAPSULE_MONOTONIC_COUNTS ?= "" +CAPSULE_PRIVATE_KEY_PATHS ?= "" +UEFI_FIRMWARE_BINARIES ?= "" +PAYLOAD_CERTIFICATE_PATH ?= "" +PAYLOAD_PRIVATE_KEY_PATH ?= "" -# The following variables must be set to be able to generate a capsule update -CAPSULE_CERTIFICATE_PATH ?= "" -CAPSULE_FW_VERSION ?= "" -CAPSULE_GUID ?= "" -CAPSULE_INDEX ?= "" -CAPSULE_MONOTONIC_COUNT ?= "" -CAPSULE_PRIVATE_KEY_PATH ?= "" -UEFI_FIRMWARE_BINARY ?= "" # Check if the required variables are set python() { - for var in ["CAPSULE_CERTIFICATE_PATH", "CAPSULE_FW_VERSION", \ - "CAPSULE_GUID", "CAPSULE_INDEX", \ - "CAPSULE_MONOTONIC_COUNT", "CAPSULE_PRIVATE_KEY_PATH", \ - "UEFI_FIRMWARE_BINARY"]: + for var in ["CAPSULE_CERTIFICATE_PATHS", "CAPSULE_FW_VERSIONS", \ + "CAPSULE_GUIDS", "CAPSULE_INDEXES", \ + "CAPSULE_HARDWARE_INSTANCES", \ + "CAPSULE_LOWEST_SUPPORTED_VERSIONS", \ + "CAPSULE_MONOTONIC_COUNTS", "CAPSULE_PRIVATE_KEY_PATHS", \ + "UEFI_FIRMWARE_BINARIES", \ + "UEFI_CAPSULE_CONFIG_GENERATOR_SCRIPT", \ + "CAPSULE_ALL_COMPONENTS", \ + "CAPSULE_SELECTED_COMPONENTS", \ + "PAYLOAD_CERTIFICATE_PATH", \ + "PAYLOAD_PRIVATE_KEY_PATH"]: if not d.getVar(var): raise bb.parse.SkipRecipe(f"{var} not set") } IMAGE_CMD:uefi_capsule(){ - mkeficapsule --certificate ${CAPSULE_CERTIFICATE_PATH} \ - --fw-version ${CAPSULE_FW_VERSION} \ - --guid ${CAPSULE_GUID} \ - --index ${CAPSULE_INDEX} \ - --monotonic-count ${CAPSULE_MONOTONIC_COUNT} \ - --private-key ${CAPSULE_PRIVATE_KEY_PATH} \ - ${UEFI_FIRMWARE_BINARY} \ - ${CAPSULE_IMGLOCATION}/${CAPSULE_NAME}.${CAPSULE_EXTENSION} + # Generates the UEFI capsule payloads JSON + ${PYTHON} ${UEFI_CAPSULE_CONFIG_GENERATOR_SCRIPT} \ + --selected_components ${CAPSULE_SELECTED_COMPONENTS}\ + --components ${CAPSULE_ALL_COMPONENTS}\ + --fw_versions ${CAPSULE_FW_VERSIONS} \ + --guids ${CAPSULE_GUIDS} \ + --hardware_instances ${CAPSULE_HARDWARE_INSTANCES} \ + --lowest_supported_versions ${CAPSULE_LOWEST_SUPPORTED_VERSIONS} \ + --monotonic_counts ${CAPSULE_MONOTONIC_COUNTS} \ + --payloads ${UEFI_FIRMWARE_BINARIES} \ + --update_image_indexes ${CAPSULE_INDEXES} \ + --private_keys ${CAPSULE_PRIVATE_KEY_PATHS} \ + --certificates ${CAPSULE_CERTIFICATE_PATHS} \ + --output ${CAPSULE_CONFIG_FILE} + + # Force the GenerateCapsule script to use python3 + export PYTHON_COMMAND=${PYTHON} + + # Append the certificate to the private key to create a PEM bundle compatible with EDK2 tools + cat ${PAYLOAD_CERTIFICATE_PATH} >> ${PAYLOAD_PRIVATE_KEY_PATH} + + # Generate the UEFI capsule image using the EDK2 GenerateCapsule tool + ${STAGING_BINDIR_NATIVE}/edk2-BaseTools/BinWrappers/PosixLike/GenerateCapsule \ + -e -j ${CAPSULE_CONFIG_FILE} \ + ${CAPSULE_EXTRA_ARGS} \ + -o ${CAPSULE_IMG_LOCATION}/${CAPSULE_NAME}.${CAPSULE_EXTENSION} } # The firmware binary should be created before generating the capsule diff --git a/meta-arm/conf/layer.conf b/meta-arm/conf/layer.conf index 753f5259..8f7e1a43 100644 --- a/meta-arm/conf/layer.conf +++ b/meta-arm/conf/layer.conf @@ -21,3 +21,6 @@ HOSTTOOLS_NONFATAL += "telnet" addpylib ${LAYERDIR}/lib oeqa WARN_QA:append:layer-meta-arm = " patch-status" + +# Define base directory for meta-arm +META_ARM_LAYER_DIR := "${LAYERDIR}" diff --git a/meta-arm/scripts/generate_capsule_json_multiple.py b/meta-arm/scripts/generate_capsule_json_multiple.py new file mode 100644 index 00000000..13425748 --- /dev/null +++ b/meta-arm/scripts/generate_capsule_json_multiple.py @@ -0,0 +1,142 @@ +# SPDX-FileCopyrightText: Copyright 2025 Arm Limited and/or its +# affiliates +# +# SPDX-License-Identifier: MIT + +""" +Capsule Payload JSON Generator + +This script creates a JSON file that defines multiple capsule payloads. +Each payload is constructed using command-line input and includes key +metadata like firmware version, GUID, hardware instance, and more. + +Usage: + python generate_capsule_json_multiple.py \ + --fw_versions 1 1 2 \ + --guids guid1 guid2 guid3 \ + --hardware_instances 1 1 1 \ + --lowest_supported_versions 0 0 0 \ + --monotonic_counts 1 1 1 \ + --payloads bl2.bin initramfs.bin tfm_s.bin \ + --update_image_indexes 1 4 2 \ + --private_keys key.key key.key key.key \ + --certificates cert.crt cert.crt cert.crt \ + --components bl2 initramfs tfm_s \ + --selected_components bl2 \ + --output capsule_generation_config.json +""" + +import json +import argparse +from typing import List + + +def parse_arguments() -> argparse.Namespace: + """Parses command-line arguments.""" + parser = argparse.ArgumentParser( + description="Generate a JSON file for multiple Capsule Payloads." + ) + + parser.add_argument( + "--selected_components", default=[], nargs="*", required=False, + help=( + "Filters the payloads to include only those for the selected " + "components (e.g., bl2, initramfs)." + "All components are included when not specified." + ) + ) + + parser.add_argument( + "--output", default="capsule_payloads.json", help="Output JSON file name" + ) + + # Required arguments for each payload entry + required_args = { + "components": "List of components", + "fw_versions": "List of firmware versions", + "guids": "List of GUIDs", + "hardware_instances": "List of hardware instances", + "lowest_supported_versions": "List of lowest supported firmware versions", + "monotonic_counts": "List of monotonic counts", + "payloads": "List of payload file paths", + "update_image_indexes": "List of update image indexes", + "private_keys": "List of private key file paths", + "certificates": "List of certificate file paths", + } + + for arg, desc in required_args.items(): + parser.add_argument(f"--{arg}", nargs="+", required=True, help=desc) + + return parser.parse_args() + + +def validate_input_lengths(args: argparse.Namespace) -> None: + """Ensures all required input lists have the same length (excluding output and selected_components).""" + list_lengths = { + attr: len(getattr(args, attr)) + for attr in vars(args) + if attr not in {"output", "selected_components"} # Ignore optional fields + } + + for attr, length in list_lengths.items(): + if length == 0: + raise ValueError(f"Input list '{attr}' cannot be empty!") + + if len(set(list_lengths.values())) != 1: + raise ValueError("All input lists must have the same length!") + +def create_payloads(args: argparse.Namespace) -> List[dict]: + """Generates the list of payload dictionaries to include in the final JSON.""" + num_payloads = len(args.components) + selected_payloads = [] + + for i in range(num_payloads): + + # If filtering is enabled, skip if not in the allowed components list + if args.components[i] not in args.selected_components: + continue + + payload = { + "Component": args.components[i], + "FwVersion": args.fw_versions[i], + "Guid": args.guids[i], + "HardwareInstance": args.hardware_instances[i], + "LowestSupportedVersion": args.lowest_supported_versions[i], + "MonotonicCount": args.monotonic_counts[i], + "Payload": args.payloads[i], + "UpdateImageIndex": args.update_image_indexes[i], + "OpenSslSignerPrivateCertFile": args.private_keys[i], + "OpenSslTrustedPublicCertFile": args.certificates[i], + "OpenSslOtherPublicCertFile": args.certificates[i], + } + + selected_payloads.append(payload) + + if not selected_payloads: + raise ValueError("None of the provided components match the selected_components list!") + + return selected_payloads + + +def write_json_file(output_path: str, payloads: List[dict]) -> None: + """Writes the list of payloads to a JSON file with basic error handling.""" + try: + with open(output_path, "w", encoding="utf-8") as file: + json.dump({"Payloads": payloads}, file, indent=4) + print(f"JSON file created: {output_path}") + except (OSError) as e: + print(f"Failed to write JSON file to {output_path}: {e}") + except TypeError as e: + print(f"Invalid data format in payloads: {e}") + + +def main() -> None: + """Main script entry point.""" + args = parse_arguments() + validate_input_lengths(args) + payloads = create_payloads(args) + write_json_file(args.output, payloads) + + +if __name__ == "__main__": + main() From patchwork Wed Jul 30 11:53:21 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harsimran Singh Tungal X-Patchwork-Id: 67726 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id A4D11C87FCC for ; Wed, 30 Jul 2025 11:54:00 +0000 (UTC) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.web11.33476.1753876437992477888 for ; Wed, 30 Jul 2025 04:53:58 -0700 Authentication-Results: mx.groups.io; dkim=none (message not signed); spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: harsimransingh.tungal@arm.com) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 7EFDA2681; Wed, 30 Jul 2025 04:53:49 -0700 (PDT) Received: from e132995.cambridge.arm.com (e132995.arm.com [10.1.25.25]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 8B9213F66E; Wed, 30 Jul 2025 04:53:56 -0700 (PDT) From: Harsimran Singh Tungal To: meta-arm@lists.yoctoproject.org Cc: Ali Can Ozaslan , Harsimran Singh Tungal Subject: [PATCH 07/13] arm-bsp/corstone1000: Support multi-payload capsule generation Date: Wed, 30 Jul 2025 12:53:21 +0100 Message-Id: <20250730115327.3671160-8-harsimransingh.tungal@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250730115327.3671160-1-harsimransingh.tungal@arm.com> References: <20250730115327.3671160-1-harsimransingh.tungal@arm.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Wed, 30 Jul 2025 11:54:00 -0000 X-Groupsio-URL: https://lists.yoctoproject.org/g/meta-arm/message/6644 From: Ali Can Ozaslan - Add 'CAPSULE_SELECTED_COMPONENTS' to enable filtering of firmware components during capsule generation. Only components listed in 'CAPSULE_SELECTED_COMPONENTS' will be included in the final capsule image. - Introduce CAPSULE_EXTRA_ARGS to allow passing additional arguments. '--capflag PersistAcrossReset' to retain capsule across reboots. - Payload selection is now controlled via the KAS YAML configuration (corstone1000-image-configuration.yml), allowing per-image control over which firmware components are included. - With the introduction of multiple payload support, 'CAPSULE_VERSION' no longer represents the firmware version itself but is instead used for naming the capsule and assigning a common version to all payloads to simplify testing. - Use EDK2 tool to switch from single FMP capsule generation to multiple FMP capsules using a JSON-based configuration. This removes the need for manually combining firmware images into a .nopt image. - Remove legacy nopt image creation logic, as each firmware binary is now handled individually. Components no longer need to be merged. Deploy task was removed with nopt logic. - Generate dummy.bin for EDK2 tool compatibility. EDK2 requires at least one input file for each payload. - Added dependency on to to ensure images are signed before capsule generation. - Add CAPSULE_LOWEST_SUPPORTED_VERSION to corstone1000-image-configuration.yml.It in the same file where the firmware version (FW_VERSION) is defined, ensuring a unified location for version-related metadata. This value was chosen to be equal to the firmware version to represent a downgrade scenario (from version 6 to version 5) during testing. - CAPSULE_HARDWARE_INSTANCE is set to "1" by default (instead of 0), indicating the first hardware. Signed-off-by: Ali Can Ozaslan Signed-off-by: Harsimran Singh Tungal --- kas/corstone1000-image-configuration.yml | 5 +- .../corstone1000-flash-firmware-image.bb | 165 ++++++++++++++---- 2 files changed, 133 insertions(+), 37 deletions(-) diff --git a/kas/corstone1000-image-configuration.yml b/kas/corstone1000-image-configuration.yml index f955d7ab..b5e17200 100644 --- a/kas/corstone1000-image-configuration.yml +++ b/kas/corstone1000-image-configuration.yml @@ -41,6 +41,7 @@ local_conf_header: CORE_IMAGE_EXTRA_INSTALL:firmware += "packagegroup-ts-tests-psa" capsule: | + # These variables are set here since they are not defined in the arm-systemready-firmware recipe or under multiconfig mode. CAPSULE_EXTENSION = "uefi.capsule" - CAPSULE_FW_VERSION = "6" - CAPSULE_NAME = "${MACHINE}-v${CAPSULE_FW_VERSION}" + CAPSULE_VERSION = "6" + CAPSULE_NAME = "${MACHINE}-v${CAPSULE_VERSION}" diff --git a/meta-arm-bsp/recipes-bsp/images/corstone1000-flash-firmware-image.bb b/meta-arm-bsp/recipes-bsp/images/corstone1000-flash-firmware-image.bb index 5d313c7b..2b9a180d 100644 --- a/meta-arm-bsp/recipes-bsp/images/corstone1000-flash-firmware-image.bb +++ b/meta-arm-bsp/recipes-bsp/images/corstone1000-flash-firmware-image.bb @@ -26,21 +26,133 @@ IMAGE_LINGUAS = "" PACKAGE_INSTALL = "" -# The generated ${MACHINE}_image.nopt is used instead of the default wic image -# for the capsule generation. The uefi.capsule image type doesn't have to -# depend on the wic because of this. -# # The corstone1000_capsule_cert.crt and corstone1000_capsule_key.key are installed # by the U-Boot recipe so this recipe has to depend on that. + CAPSULE_IMGTYPE = "" -CAPSULE_CERTIFICATE_PATH = "${DEPLOY_DIR_IMAGE}/corstone1000_capsule_cert.crt" -CAPSULE_GUID:corstone1000-fvp ?= "989f3a4e-46e0-4cd0-9877-a25c70c01329" -CAPSULE_GUID:corstone1000-mps3 ?= "df1865d1-90fb-4d59-9c38-c9f2c1bba8cc" -CAPSULE_IMGLOCATION = "${DEPLOY_DIR_IMAGE}" -CAPSULE_INDEX = "1" -CAPSULE_MONOTONIC_COUNT = "1" -CAPSULE_PRIVATE_KEY_PATH = "${DEPLOY_DIR_IMAGE}/corstone1000_capsule_key.key" -UEFI_FIRMWARE_BINARY = "${B}/${MACHINE}_image.nopt" +CAPSULE_IMG_LOCATION = "${DEPLOY_DIR_IMAGE}" + +# User-configurable common capsule settings +CAPSULE_EXTENSION ?= "uefi.capsule" +CAPSULE_VERSION ?= "6" +CAPSULE_LOWEST_SUPPORTED_VERSION ?= "6" +CAPSULE_NAME ?= "${MACHINE}-v${CAPSULE_VERSION}" +CAPSULE_SELECTED_COMPONENTS ?= "BL2 TFM_S FIP INITRAMFS" +CAPSULE_EXTRA_ARGS ?= "--capflag PersistAcrossReset" + +# Non-configurable common payloads settings +PAYLOAD_CERTIFICATE_PATH = "${DEPLOY_DIR_IMAGE}/corstone1000_capsule_cert.crt" +PAYLOAD_HARDWARE_INSTANCE = "1" +PAYLOAD_MONOTONIC_COUNT = "1" +PAYLOAD_PRIVATE_KEY_PATH = "${DEPLOY_DIR_IMAGE}/corstone1000_capsule_key.key" +CAPSULE_SELECTED_COMPONENTS += " DUMMY_START DUMMY_END" + +# All capsule fields are reset and initialized with DUMMY_START since it is the first payload +# DUMMY_START +PAYLOAD_DUMMY_START_INDEX ?= "5" +PAYLOAD_DUMMY_START_VERSION ?= "${CAPSULE_VERSION}" +PAYLOAD_DUMMY_START_LOWEST_SUPPORTED_VERSION ?= "${CAPSULE_LOWEST_SUPPORTED_VERSION}" +PAYLOAD_DUMMY_START_GUID ?= "6f784cbf-7938-5c23-8d6e-24d2f1410fa9" + +CAPSULE_ALL_COMPONENTS = "DUMMY_START " +CAPSULE_CERTIFICATE_PATHS = "${PAYLOAD_CERTIFICATE_PATH} " +CAPSULE_GUIDS = "${PAYLOAD_DUMMY_START_GUID} " +CAPSULE_INDEXES = "${PAYLOAD_DUMMY_START_INDEX} " +CAPSULE_HARDWARE_INSTANCES = "${PAYLOAD_HARDWARE_INSTANCE} " +CAPSULE_MONOTONIC_COUNTS = "${PAYLOAD_MONOTONIC_COUNT} " +CAPSULE_PRIVATE_KEY_PATHS = "${PAYLOAD_PRIVATE_KEY_PATH} " +UEFI_FIRMWARE_BINARIES = "${B}/dummy.bin " +CAPSULE_FW_VERSIONS = "${PAYLOAD_DUMMY_START_VERSION} " +CAPSULE_LOWEST_SUPPORTED_VERSIONS = "${PAYLOAD_DUMMY_START_LOWEST_SUPPORTED_VERSION} " + +# BL2 +PAYLOAD_BL2_INDEX ?= "1" +PAYLOAD_BL2_VERSION ?= "${CAPSULE_VERSION}" +PAYLOAD_BL2_LOWEST_SUPPORTED_VERSION ?= "${CAPSULE_LOWEST_SUPPORTED_VERSION}" +PAYLOAD_BL2_GUID:corstone1000-fvp ?= "f1d883f9-dfeb-5363-98d8-686ee3b69f4f" +PAYLOAD_BL2_GUID:corstone1000-mps3 ?= "fbfbefaa-0a56-50d5-b651-74091d3d62cf" + +CAPSULE_ALL_COMPONENTS += "BL2 " +CAPSULE_CERTIFICATE_PATHS += "${PAYLOAD_CERTIFICATE_PATH} " +CAPSULE_GUIDS += "${PAYLOAD_BL2_GUID} " +CAPSULE_INDEXES += "${PAYLOAD_BL2_INDEX} " +CAPSULE_HARDWARE_INSTANCES += "${PAYLOAD_HARDWARE_INSTANCE} " +CAPSULE_MONOTONIC_COUNTS += "${PAYLOAD_MONOTONIC_COUNT} " +CAPSULE_PRIVATE_KEY_PATHS += "${PAYLOAD_PRIVATE_KEY_PATH} " +UEFI_FIRMWARE_BINARIES += "${DEPLOY_DIR_IMAGE}/bl2_signed.bin " +CAPSULE_FW_VERSIONS += "${PAYLOAD_BL2_VERSION} " +CAPSULE_LOWEST_SUPPORTED_VERSIONS += "${PAYLOAD_BL2_LOWEST_SUPPORTED_VERSION} " + +# TFM_S +PAYLOAD_TFM_S_INDEX ?= "2" +PAYLOAD_TFM_S_VERSION ?= "${CAPSULE_VERSION}" +PAYLOAD_TFM_S_LOWEST_SUPPORTED_VERSION ?= "${CAPSULE_LOWEST_SUPPORTED_VERSION}" +PAYLOAD_TFM_S_GUID:corstone1000-fvp ?= "7fad470e-5ec5-5c03-a2c1-4756b495de61" +PAYLOAD_TFM_S_GUID:corstone1000-mps3 ?= "af4cc7ad-ee2e-5a39-aad5-fac8a1e6173c" + +CAPSULE_ALL_COMPONENTS += "TFM_S " +CAPSULE_CERTIFICATE_PATHS += "${PAYLOAD_CERTIFICATE_PATH} " +CAPSULE_GUIDS += "${PAYLOAD_TFM_S_GUID} " +CAPSULE_INDEXES += "${PAYLOAD_TFM_S_INDEX} " +CAPSULE_HARDWARE_INSTANCES += "${PAYLOAD_HARDWARE_INSTANCE} " +CAPSULE_MONOTONIC_COUNTS += "${PAYLOAD_MONOTONIC_COUNT} " +CAPSULE_PRIVATE_KEY_PATHS += "${PAYLOAD_PRIVATE_KEY_PATH} " +UEFI_FIRMWARE_BINARIES += "${DEPLOY_DIR_IMAGE}/tfm_s_signed.bin " +CAPSULE_FW_VERSIONS += "${PAYLOAD_TFM_S_VERSION} " +CAPSULE_LOWEST_SUPPORTED_VERSIONS += "${PAYLOAD_TFM_S_LOWEST_SUPPORTED_VERSION} " + +# FIP +PAYLOAD_FIP_INDEX ?= "3" +PAYLOAD_FIP_VERSION ?= "${CAPSULE_VERSION}" +PAYLOAD_FIP_LOWEST_SUPPORTED_VERSION ?= "${CAPSULE_LOWEST_SUPPORTED_VERSION}" +PAYLOAD_FIP_GUID:corstone1000-fvp ?= "f1933675-5a8c-5b6d-9ef4-846739e89bc8" +PAYLOAD_FIP_GUID:corstone1000-mps3 ?= "55302f96-c4f0-5cf9-8624-e7cc388f2b68" + +CAPSULE_ALL_COMPONENTS += "FIP " +CAPSULE_CERTIFICATE_PATHS += "${PAYLOAD_CERTIFICATE_PATH} " +CAPSULE_GUIDS += "${PAYLOAD_FIP_GUID} " +CAPSULE_INDEXES += "${PAYLOAD_FIP_INDEX} " +CAPSULE_HARDWARE_INSTANCES += "${PAYLOAD_HARDWARE_INSTANCE} " +CAPSULE_MONOTONIC_COUNTS += "${PAYLOAD_MONOTONIC_COUNT} " +CAPSULE_PRIVATE_KEY_PATHS += "${PAYLOAD_PRIVATE_KEY_PATH} " +UEFI_FIRMWARE_BINARIES += "${DEPLOY_DIR_IMAGE}/signed_fip-corstone1000.bin " +CAPSULE_FW_VERSIONS += "${PAYLOAD_FIP_VERSION} " +CAPSULE_LOWEST_SUPPORTED_VERSIONS += "${PAYLOAD_FIP_LOWEST_SUPPORTED_VERSION} " + +# INITRAMFS +PAYLOAD_INITRAMFS_INDEX ?= "4" +PAYLOAD_INITRAMFS_VERSION ?= "${CAPSULE_VERSION}" +PAYLOAD_INITRAMFS_LOWEST_SUPPORTED_VERSION ?= "${CAPSULE_LOWEST_SUPPORTED_VERSION}" +PAYLOAD_INITRAMFS_GUID:corstone1000-fvp ?= "f771aff9-c7e9-5f99-9eda-2369dd694f61" +PAYLOAD_INITRAMFS_GUID:corstone1000-mps3 ?= "3e8ac972-c33c-5cc9-90a0-cdd3159683ea" + +CAPSULE_ALL_COMPONENTS += "INITRAMFS " +CAPSULE_CERTIFICATE_PATHS += "${PAYLOAD_CERTIFICATE_PATH} " +CAPSULE_GUIDS += "${PAYLOAD_INITRAMFS_GUID} " +CAPSULE_INDEXES += "${PAYLOAD_INITRAMFS_INDEX} " +CAPSULE_HARDWARE_INSTANCES += "${PAYLOAD_HARDWARE_INSTANCE} " +CAPSULE_MONOTONIC_COUNTS += "${PAYLOAD_MONOTONIC_COUNT} " +CAPSULE_PRIVATE_KEY_PATHS += "${PAYLOAD_PRIVATE_KEY_PATH} " +UEFI_FIRMWARE_BINARIES += "${DEPLOY_DIR_IMAGE}/Image.gz-initramfs-${MACHINE}.bin " +CAPSULE_FW_VERSIONS += "${PAYLOAD_INITRAMFS_VERSION} " +CAPSULE_LOWEST_SUPPORTED_VERSIONS += "${PAYLOAD_INITRAMFS_LOWEST_SUPPORTED_VERSION} " + +# DUMMY_END +PAYLOAD_DUMMY_END_INDEX ?= "6" +PAYLOAD_DUMMY_END_VERSION ?= "${CAPSULE_VERSION}" +PAYLOAD_DUMMY_END_LOWEST_SUPPORTED_VERSION ?= "${CAPSULE_LOWEST_SUPPORTED_VERSION}" +PAYLOAD_DUMMY_END_GUID ?= "b57e432b-a250-5c73-93e3-90205e64baba" + +CAPSULE_ALL_COMPONENTS += "DUMMY_END" +CAPSULE_CERTIFICATE_PATHS += "${PAYLOAD_CERTIFICATE_PATH}" +CAPSULE_GUIDS += "${PAYLOAD_DUMMY_END_GUID}" +CAPSULE_INDEXES += "${PAYLOAD_DUMMY_END_INDEX}" +CAPSULE_HARDWARE_INSTANCES += "${PAYLOAD_HARDWARE_INSTANCE}" +CAPSULE_MONOTONIC_COUNTS += "${PAYLOAD_MONOTONIC_COUNT}" +CAPSULE_PRIVATE_KEY_PATHS += "${PAYLOAD_PRIVATE_KEY_PATH}" +UEFI_FIRMWARE_BINARIES += "${B}/dummy.bin" +CAPSULE_FW_VERSIONS += "${PAYLOAD_DUMMY_END_VERSION}" +CAPSULE_LOWEST_SUPPORTED_VERSIONS += "${PAYLOAD_DUMMY_END_LOWEST_SUPPORTED_VERSION}" # TF-A settings for signing host images TFA_BL2_BINARY = "bl2-corstone1000.bin" @@ -53,13 +165,6 @@ RE_LAYOUT_WRAPPER_VERSION = "0.0.7" TFM_SIGN_PRIVATE_KEY = "${libdir}/tfm-scripts/root-RSA-3072_1.pem" RE_IMAGE_OFFSET = "0x1000" -# Offsets for the .nopt image generation -# These offset values have to be aligned with those in -# meta-arm/meta-arm-bsp/wic/corstone1000-flash-firmware.wks.in -TFM_OFFSET = "147456" -FIP_OFFSET = "475136" -KERNEL_OFFSET = "2572288" - do_sign_images() { # Sign TF-A BL2 sign_host_image ${RECIPE_SYSROOT}/firmware/${TFA_BL2_BINARY} \ @@ -79,21 +184,11 @@ do_sign_images[depends] = "\ fiptool-native:do_populate_sysroot \ " -# This .nopt image is not the same as the one which is generated by meta-arm/meta-arm/classes/wic_nopt.bbclass. -# The meta-arm/meta-arm/classes/wic_nopt.bbclass removes the partition table from the wic image, but keeps the -# second bank. This function creates a no-partition image with only the first bank. -create_nopt_image() { - dd conv=notrunc bs=1 if=${DEPLOY_DIR_IMAGE}/bl2_signed.bin of=${B}/${MACHINE}_image.nopt - dd conv=notrunc bs=1 if=${DEPLOY_DIR_IMAGE}/tfm_s_signed.bin of=${B}/${MACHINE}_image.nopt seek=${TFM_OFFSET} - dd conv=notrunc bs=1 if=${DEPLOY_DIR_IMAGE}/signed_fip-corstone1000.bin of=${B}/${MACHINE}_image.nopt seek=${FIP_OFFSET} - dd conv=notrunc bs=1 if=${DEPLOY_DIR_IMAGE}/Image.gz-initramfs-${MACHINE}.bin of=${B}/${MACHINE}_image.nopt seek=${KERNEL_OFFSET} -} -do_image_uefi_capsule[depends] += " linux-yocto:do_deploy" -do_image_uefi_capsule[mcdepends] += " ${@bb.utils.contains('BBMULTICONFIG', 'firmware', 'mc::firmware:linux-yocto:do_deploy', '', d)}" -do_image_uefi_capsule[prefuncs] += "create_nopt_image" - -do_deploy() { - install -m 0755 ${B}/${MACHINE}_image.nopt ${DEPLOYDIR} +# Create an empty dummy payload file required for capsule generation +create_dummy_image() { + touch ${B}/dummy.bin } -addtask deploy after do_image_uefi_capsule +do_image_uefi_capsule[depends] += " linux-yocto:do_deploy corstone1000-flash-firmware-image:do_sign_images" +do_image_uefi_capsule[mcdepends] += " ${@bb.utils.contains('BBMULTICONFIG', 'firmware', 'mc::firmware:linux-yocto:do_deploy mc::firmware:corstone1000-flash-firmware-image:do_sign_images', '', d)}" +do_image_uefi_capsule[prefuncs] += "create_dummy_image" From patchwork Wed Jul 30 11:53:22 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harsimran Singh Tungal X-Patchwork-Id: 67732 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id A5C5CC87FD2 for ; Wed, 30 Jul 2025 11:54:00 +0000 (UTC) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.web10.33475.1753876438590313520 for ; Wed, 30 Jul 2025 04:53:58 -0700 Authentication-Results: mx.groups.io; dkim=none (message not signed); spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: harsimransingh.tungal@arm.com) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 4EC6A2573; Wed, 30 Jul 2025 04:53:50 -0700 (PDT) Received: from e132995.cambridge.arm.com (e132995.arm.com [10.1.25.25]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id C1B4C3F66E; Wed, 30 Jul 2025 04:53:57 -0700 (PDT) From: Harsimran Singh Tungal To: meta-arm@lists.yoctoproject.org Cc: Harsimran Singh Tungal Subject: [PATCH 08/13] arm-bsp/trusted-services: corstone-1000: Remove old capsule update implementation Date: Wed, 30 Jul 2025 12:53:22 +0100 Message-Id: <20250730115327.3671160-9-harsimransingh.tungal@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250730115327.3671160-1-harsimransingh.tungal@arm.com> References: <20250730115327.3671160-1-harsimransingh.tungal@arm.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Wed, 30 Jul 2025 11:54:00 -0000 X-Groupsio-URL: https://lists.yoctoproject.org/g/meta-arm/message/6645 This change removes the obsolete out-of-tree patches and legacy support related to the old capsule update mechanism for the Corstone-1000 platform. The Trusted-Services components are now aligned with the upstream implementation, and outdated patches have been dropped or rebased as necessary. - Removed deprecated patches targeting old capsule update logic - Rebasing of remaining patches to ensure compatibility with updated TS interface This prepares the platform for the new PSA FWU-based capsule update path and reduces technical debt in Trusted-Services integration. Signed-off-by: Harsimran Singh Tungal --- ...ub-capsule-update-service-components.patch | 378 --------- ...1-Fix-in-AEAD-for-psa-arch-test-254.patch} | 0 ...0002-Fix-psa-api-crypto-test-no-243.patch} | 0 .../0003-FMP-Support-in-Corstone1000.patch | 418 ---------- ...ag.patch => 0003-Remove-Werror-flag.patch} | 0 ..._HAS_ATTEST_PK-define-from-IAT-test.patch} | 0 ...sizes-compile-time-definitions-user.patch} | 0 ...0-Use-the-stateless-platform-service.patch | 141 ---- ...0006-Align-PSA-Crypto-with-TF-Mv2.1.patch} | 0 ...0-Initialize-capsule-update-provider.patch | 106 --- ...store-UEFI-variable-index-in-chunks.patch} | 140 ++-- ...ne1000-add-client_id-for-FMP-service.patch | 49 -- .../0008-se-proxy-protobuf-change.patch | 71 ++ ...1000-Add-PLATFORM_IS_FVP-toggle-for.patch} | 0 ...FWU-IPC-framework-for-Corstone-1000.patch} | 20 +- ...age-state-in-PSA-FWU-M-update-agent.patch} | 0 ...ine-PSA-FWU-image-mapping-structure.patch} | 0 ...able-index-usage-robust-with-redunda.patch | 716 ------------------ ...-psa_fwu_install-return-value-check.patch} | 0 ...traints-of-NV-UEFI-variables-persist.patch | 387 ---------- ...=> 0014-fwu-Add-EFI-ESRT-v1-support.patch} | 0 ...rm-corstone1000-Enable-ESRT-support.patch} | 0 .../0015-se-proxy-protobuf-change.patch | 64 -- ...rstone1000-Add-event-provider-proxy.patch} | 53 +- ...e1000-Define-GUID-for-each-payloads.patch} | 0 ...e-com-buffer-address-and-page-count.patch} | 27 +- .../trusted-services/ts-arm-platforms.inc | 43 +- 27 files changed, 232 insertions(+), 2381 deletions(-) delete mode 100644 meta-arm-bsp/recipes-security/trusted-services/corstone1000/0001-Add-stub-capsule-update-service-components.patch rename meta-arm-bsp/recipes-security/trusted-services/corstone1000/{0002-Fix-in-AEAD-for-psa-arch-test-254.patch => 0001-Fix-in-AEAD-for-psa-arch-test-254.patch} (100%) rename meta-arm-bsp/recipes-security/trusted-services/corstone1000/{0004-Fix-psa-api-crypto-test-no-243.patch => 0002-Fix-psa-api-crypto-test-no-243.patch} (100%) delete mode 100644 meta-arm-bsp/recipes-security/trusted-services/corstone1000/0003-FMP-Support-in-Corstone1000.patch rename meta-arm-bsp/recipes-security/trusted-services/corstone1000/{0008-Remove-Werror-flag.patch => 0003-Remove-Werror-flag.patch} (100%) rename meta-arm-bsp/recipes-security/trusted-services/corstone1000/{0009-Remove-PLATFORM_HAS_ATTEST_PK-define-from-IAT-test.patch => 0004-Remove-PLATFORM_HAS_ATTEST_PK-define-from-IAT-test.patch} (100%) rename meta-arm-bsp/recipes-security/trusted-services/corstone1000/{0010-Make-RSS-and-MHU-sizes-compile-time-definitions-user.patch => 0005-Make-RSS-and-MHU-sizes-compile-time-definitions-user.patch} (100%) delete mode 100644 meta-arm-bsp/recipes-security/trusted-services/corstone1000/0005-plat-corstone1000-Use-the-stateless-platform-service.patch rename meta-arm-bsp/recipes-security/trusted-services/corstone1000/{0011-Align-PSA-Crypto-with-TF-Mv2.1.patch => 0006-Align-PSA-Crypto-with-TF-Mv2.1.patch} (100%) delete mode 100644 meta-arm-bsp/recipes-security/trusted-services/corstone1000/0006-plat-corstone1000-Initialize-capsule-update-provider.patch rename meta-arm-bsp/recipes-security/trusted-services/corstone1000/{0013-Revert-Load-and-store-UEFI-variable-index-in-chunks.patch => 0007-Revert-Load-and-store-UEFI-variable-index-in-chunks.patch} (74%) delete mode 100644 meta-arm-bsp/recipes-security/trusted-services/corstone1000/0007-plat-corstone1000-add-client_id-for-FMP-service.patch create mode 100644 meta-arm-bsp/recipes-security/trusted-services/corstone1000/0008-se-proxy-protobuf-change.patch rename meta-arm-bsp/recipes-security/trusted-services/corstone1000/{0017-Platform-Corstone1000-Add-PLATFORM_IS_FVP-toggle-for.patch => 0009-Platform-Corstone1000-Add-PLATFORM_IS_FVP-toggle-for.patch} (100%) rename meta-arm-bsp/recipes-security/trusted-services/corstone1000/{0018-Integrate-PSA-FWU-IPC-framework-for-Corstone-1000.patch => 0010-Integrate-PSA-FWU-IPC-framework-for-Corstone-1000.patch} (97%) rename meta-arm-bsp/recipes-security/trusted-services/corstone1000/{0019-Load-initial-image-state-in-PSA-FWU-M-update-agent.patch => 0011-Load-initial-image-state-in-PSA-FWU-M-update-agent.patch} (100%) rename meta-arm-bsp/recipes-security/trusted-services/corstone1000/{0020-Corstone1000-Define-PSA-FWU-image-mapping-structure.patch => 0012-Corstone1000-Define-PSA-FWU-image-mapping-structure.patch} (100%) delete mode 100644 meta-arm-bsp/recipes-security/trusted-services/corstone1000/0012-Revert-Make-variable-index-usage-robust-with-redunda.patch rename meta-arm-bsp/recipes-security/trusted-services/corstone1000/{0021-Fix-PSA-FWU-IPC-psa_fwu_install-return-value-check.patch => 0013-Fix-PSA-FWU-IPC-psa_fwu_install-return-value-check.patch} (100%) delete mode 100644 meta-arm-bsp/recipes-security/trusted-services/corstone1000/0014-Revert-Make-constraints-of-NV-UEFI-variables-persist.patch rename meta-arm-bsp/recipes-security/trusted-services/corstone1000/{0022-fwu-Add-EFI-ESRT-v1-support.patch => 0014-fwu-Add-EFI-ESRT-v1-support.patch} (100%) rename meta-arm-bsp/recipes-security/trusted-services/corstone1000/{0023-platform-corstone1000-Enable-ESRT-support.patch => 0015-platform-corstone1000-Enable-ESRT-support.patch} (100%) delete mode 100644 meta-arm-bsp/recipes-security/trusted-services/corstone1000/0015-se-proxy-protobuf-change.patch rename meta-arm-bsp/recipes-security/trusted-services/corstone1000/{0024-platform-corstone1000-Add-event-provider-proxy.patch => 0016-platform-corstone1000-Add-event-provider-proxy.patch} (82%) rename meta-arm-bsp/recipes-security/trusted-services/corstone1000/{0025-platform-corstone1000-Define-GUID-for-each-payloads.patch => 0017-platform-corstone1000-Define-GUID-for-each-payloads.patch} (100%) rename meta-arm-bsp/recipes-security/trusted-services/corstone1000/{0016-Add-the-com-buffer-address-and-page-count.patch => 0018-Add-the-com-buffer-address-and-page-count.patch} (60%) diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0001-Add-stub-capsule-update-service-components.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0001-Add-stub-capsule-update-service-components.patch deleted file mode 100644 index 8910364a..00000000 --- a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0001-Add-stub-capsule-update-service-components.patch +++ /dev/null @@ -1,378 +0,0 @@ -From fd171007b073a4cff7c3deabfdff233c0a9ed507 Mon Sep 17 00:00:00 2001 -From: Julian Hall -Date: Tue, 12 Oct 2021 15:45:41 +0100 -Subject: [PATCH 01/12] Add stub capsule update service components - -To facilitate development of a capsule update service provider, -stub components are added to provide a starting point for an -implementation. The capsule update service provider is integrated -into the se-proxy/common deployment. - -Upstream-Status: Inappropriate [Trusted-Services Design needs to be followed] -Signed-off-by: Vishnu Banavath -Signed-off-by: Julian Hall -Change-Id: I0d4049bb4de5af7ca80806403301692507085d28 -Signed-off-by: Rui Miguel Silva ---- - .../backend/capsule_update_backend.h | 24 ++++ - .../provider/capsule_update_provider.c | 135 ++++++++++++++++++ - .../provider/capsule_update_provider.h | 51 +++++++ - .../capsule_update/provider/component.cmake | 13 ++ - .../se-proxy/infra/corstone1000/infra.cmake | 1 + - deployments/se-proxy/se_proxy_interfaces.h | 9 +- - .../capsule_update/capsule_update_proto.h | 13 ++ - protocols/service/capsule_update/opcodes.h | 17 +++ - protocols/service/capsule_update/parameters.h | 15 ++ - 9 files changed, 274 insertions(+), 4 deletions(-) - create mode 100644 components/service/capsule_update/backend/capsule_update_backend.h - create mode 100644 components/service/capsule_update/provider/capsule_update_provider.c - create mode 100644 components/service/capsule_update/provider/capsule_update_provider.h - create mode 100644 components/service/capsule_update/provider/component.cmake - create mode 100644 protocols/service/capsule_update/capsule_update_proto.h - create mode 100644 protocols/service/capsule_update/opcodes.h - create mode 100644 protocols/service/capsule_update/parameters.h - -diff --git a/components/service/capsule_update/backend/capsule_update_backend.h b/components/service/capsule_update/backend/capsule_update_backend.h -new file mode 100644 -index 000000000..f3144ff1d ---- /dev/null -+++ b/components/service/capsule_update/backend/capsule_update_backend.h -@@ -0,0 +1,24 @@ -+/* -+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef CAPSULE_UPDATE_BACKEND_H -+#define CAPSULE_UPDATE_BACKEND_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** -+ * Defines the common capsule update backend interface. Concrete backends -+ * implement this interface for different types of platform. -+ */ -+ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* CAPSULE_UPDATE_BACKEND_H */ -diff --git a/components/service/capsule_update/provider/capsule_update_provider.c b/components/service/capsule_update/provider/capsule_update_provider.c -new file mode 100644 -index 000000000..f35c272d2 ---- /dev/null -+++ b/components/service/capsule_update/provider/capsule_update_provider.c -@@ -0,0 +1,135 @@ -+/* -+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include "capsule_update_provider.h" -+ -+ -+#define CAPSULE_UPDATE_REQUEST (0x1) -+#define KERNEL_STARTED_EVENT (0x2) -+ -+enum corstone1000_ioctl_id_t { -+ IOCTL_CORSTONE1000_FWU_FLASH_IMAGES = 0, -+ IOCTL_CORSTONE1000_FWU_HOST_ACK, -+}; -+ -+/* Service request handlers */ -+static rpc_status_t update_capsule_handler(void *context, struct rpc_request *req); -+static rpc_status_t boot_confirmed_handler(void *context, struct rpc_request *req); -+ -+/* Handler mapping table for service */ -+static const struct service_handler handler_table[] = { -+ {CAPSULE_UPDATE_OPCODE_UPDATE_CAPSULE, update_capsule_handler}, -+ {CAPSULE_UPDATE_OPCODE_BOOT_CONFIRMED, boot_confirmed_handler} -+}; -+ -+struct rpc_service_interface *capsule_update_provider_init( -+ struct capsule_update_provider *context) -+{ -+ struct rpc_service_interface *rpc_interface = NULL; -+ const struct rpc_uuid dummy_uuid = { .uuid = { 0 }}; -+ if (!context) -+ return NULL; -+ -+ service_provider_init( -+ &context->base_provider, -+ context, -+ &dummy_uuid, -+ handler_table, -+ sizeof(handler_table)/sizeof(struct service_handler)); -+ -+ rpc_interface = service_provider_get_rpc_interface(&context->base_provider); -+ -+ -+ return rpc_interface; -+} -+ -+void capsule_update_provider_deinit(struct capsule_update_provider *context) -+{ -+ (void)context; -+} -+ -+static rpc_status_t event_handler(uint32_t opcode, struct rpc_caller_interface *caller) -+{ -+ uint32_t ioctl_id; -+ psa_handle_t handle; -+ rpc_status_t rpc_status = TS_RPC_CALL_ACCEPTED; -+ -+ struct psa_invec in_vec[] = { -+ { .base = &ioctl_id, .len = sizeof(ioctl_id) } -+ }; -+ -+ if(!caller) { -+ EMSG("event_handler rpc_caller is NULL"); -+ rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE; -+ return rpc_status; -+ } -+ -+ IMSG("event handler opcode %x", opcode); -+ switch(opcode) { -+ case CAPSULE_UPDATE_REQUEST: -+ /* Openamp call with IOCTL for firmware update*/ -+ ioctl_id = IOCTL_CORSTONE1000_FWU_FLASH_IMAGES; -+ handle = psa_connect(caller, TFM_SP_PLATFORM_IOCTL_SID, -+ TFM_SP_PLATFORM_IOCTL_VERSION); -+ if (handle <= 0) { -+ EMSG("%s Invalid handle", __func__); -+ rpc_status = TS_RPC_ERROR_INVALID_PARAMETER; -+ return rpc_status; -+ } -+ psa_call(caller,handle, PSA_IPC_CALL, -+ in_vec,IOVEC_LEN(in_vec), NULL, 0); -+ break; -+ -+ case KERNEL_STARTED_EVENT: -+ ioctl_id = IOCTL_CORSTONE1000_FWU_HOST_ACK; -+ /*openamp call with IOCTL for kernel start*/ -+ handle = psa_connect(caller, TFM_SP_PLATFORM_IOCTL_SID, -+ TFM_SP_PLATFORM_IOCTL_VERSION); -+ if (handle <= 0) { -+ EMSG("%s Invalid handle", __func__); -+ rpc_status = TS_RPC_ERROR_INVALID_PARAMETER; -+ return rpc_status; -+ } -+ psa_call(caller,handle, PSA_IPC_CALL, -+ in_vec,IOVEC_LEN(in_vec), NULL, 0); -+ break; -+ default: -+ EMSG("%s unsupported opcode", __func__); -+ rpc_status = TS_RPC_ERROR_INVALID_PARAMETER; -+ return rpc_status; -+ } -+ return rpc_status; -+ -+} -+ -+static rpc_status_t update_capsule_handler(void *context, struct rpc_request *req) -+{ -+ struct capsule_update_provider *this_instance = (struct capsule_update_provider*)context; -+ struct rpc_caller_interface *caller = this_instance->client.session->caller; -+ uint32_t opcode = req->opcode; -+ rpc_status_t rpc_status = TS_RPC_ERROR_NOT_READY; -+ -+ rpc_status = event_handler(opcode, caller); -+ return rpc_status; -+} -+ -+static rpc_status_t boot_confirmed_handler(void *context, struct rpc_request *req) -+{ -+ struct capsule_update_provider *this_instance = (struct capsule_update_provider*)context; -+ struct rpc_caller_interface *caller = this_instance->client.session->caller; -+ uint32_t opcode = req->opcode; -+ rpc_status_t rpc_status = TS_RPC_ERROR_NOT_READY; -+ -+ rpc_status = event_handler(opcode, caller); -+ -+ return rpc_status; -+} -diff --git a/components/service/capsule_update/provider/capsule_update_provider.h b/components/service/capsule_update/provider/capsule_update_provider.h -new file mode 100644 -index 000000000..5dc5535d6 ---- /dev/null -+++ b/components/service/capsule_update/provider/capsule_update_provider.h -@@ -0,0 +1,51 @@ -+/* -+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef CAPSULE_UPDATE_PROVIDER_H -+#define CAPSULE_UPDATE_PROVIDER_H -+ -+#include -+#include -+#include -+#include -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** -+ * The capsule_update_provider is a service provider that accepts update capsule -+ * requests and delegates them to a suitable backend that applies the update. -+ */ -+struct capsule_update_provider -+{ -+ struct service_provider base_provider; -+ struct service_client client; -+}; -+ -+/** -+ * \brief Initialize an instance of the capsule update service provider -+ * -+ * @param[in] context The instance to initialize -+ * -+ * \return An rpc_service_interface or NULL on failure -+ */ -+struct rpc_service_interface *capsule_update_provider_init( -+ struct capsule_update_provider *context); -+ -+/** -+ * \brief Cleans up when the instance is no longer needed -+ * -+ * \param[in] context The instance to de-initialize -+ */ -+void capsule_update_provider_deinit( -+ struct capsule_update_provider *context); -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* CAPSULE_UPDATE_PROVIDER_H */ -diff --git a/components/service/capsule_update/provider/component.cmake b/components/service/capsule_update/provider/component.cmake -new file mode 100644 -index 000000000..1d412eb23 ---- /dev/null -+++ b/components/service/capsule_update/provider/component.cmake -@@ -0,0 +1,13 @@ -+#------------------------------------------------------------------------------- -+# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. -+# -+# SPDX-License-Identifier: BSD-3-Clause -+# -+#------------------------------------------------------------------------------- -+if (NOT DEFINED TGT) -+ message(FATAL_ERROR "mandatory parameter TGT is not defined.") -+endif() -+ -+target_sources(${TGT} PRIVATE -+ "${CMAKE_CURRENT_LIST_DIR}/capsule_update_provider.c" -+ ) -diff --git a/deployments/se-proxy/infra/corstone1000/infra.cmake b/deployments/se-proxy/infra/corstone1000/infra.cmake -index 3830f9d61..27af8a333 100644 ---- a/deployments/se-proxy/infra/corstone1000/infra.cmake -+++ b/deployments/se-proxy/infra/corstone1000/infra.cmake -@@ -27,6 +27,7 @@ add_components(TARGET "se-proxy" - "components/service/fwu/provider/serializer" - "components/service/fwu/psa_fwu_m/agent" - "components/service/fwu/psa_fwu_m/interface/stub" -+ "components/service/capsule_update/provider" - "components/service/secure_storage/backend/secure_storage_ipc" - ) - -diff --git a/deployments/se-proxy/se_proxy_interfaces.h b/deployments/se-proxy/se_proxy_interfaces.h -index 48908f846..3d4a7c204 100644 ---- a/deployments/se-proxy/se_proxy_interfaces.h -+++ b/deployments/se-proxy/se_proxy_interfaces.h -@@ -8,9 +8,10 @@ - #define SE_PROXY_INTERFACES_H - - /* Interface IDs from service endpoints available from an se-proxy deployment */ --#define SE_PROXY_INTERFACE_ID_ITS (0) --#define SE_PROXY_INTERFACE_ID_PS (1) --#define SE_PROXY_INTERFACE_ID_CRYPTO (2) --#define SE_PROXY_INTERFACE_ID_ATTEST (3) -+#define SE_PROXY_INTERFACE_ID_ITS (0) -+#define SE_PROXY_INTERFACE_ID_PS (1) -+#define SE_PROXY_INTERFACE_ID_CRYPTO (2) -+#define SE_PROXY_INTERFACE_ID_ATTEST (3) -+#define SE_PROXY_INTERFACE_ID_CAPSULE_UPDATE (4) - - #endif /* SE_PROXY_INTERFACES_H */ -diff --git a/protocols/service/capsule_update/capsule_update_proto.h b/protocols/service/capsule_update/capsule_update_proto.h -new file mode 100644 -index 000000000..8f326cd38 ---- /dev/null -+++ b/protocols/service/capsule_update/capsule_update_proto.h -@@ -0,0 +1,13 @@ -+/* -+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef CAPSULE_UPDATE_PROTO_H -+#define CAPSULE_UPDATE_PROTO_H -+ -+#include -+#include -+ -+#endif /* CAPSULE_UPDATE_PROTO_H */ -diff --git a/protocols/service/capsule_update/opcodes.h b/protocols/service/capsule_update/opcodes.h -new file mode 100644 -index 000000000..8185a0902 ---- /dev/null -+++ b/protocols/service/capsule_update/opcodes.h -@@ -0,0 +1,17 @@ -+/* -+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef CAPSULE_UPDATE_OPCODES_H -+#define CAPSULE_UPDATE_OPCODES_H -+ -+/** -+ * Opcode definitions for the capsule update service -+ */ -+ -+#define CAPSULE_UPDATE_OPCODE_UPDATE_CAPSULE 1 -+#define CAPSULE_UPDATE_OPCODE_BOOT_CONFIRMED 2 -+ -+#endif /* CAPSULE_UPDATE_OPCODES_H */ -diff --git a/protocols/service/capsule_update/parameters.h b/protocols/service/capsule_update/parameters.h -new file mode 100644 -index 000000000..285d92418 ---- /dev/null -+++ b/protocols/service/capsule_update/parameters.h -@@ -0,0 +1,15 @@ -+/* -+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef CAPSULE_UPDATE_PARAMETERS_H -+#define CAPSULE_UPDATE_PARAMETERS_H -+ -+/** -+ * Operation parameter definitions for the capsule update service access protocol. -+ */ -+ -+ -+#endif /* CAPSULE_UPDATE_PARAMETERS_H */ --- -2.25.1 - diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0002-Fix-in-AEAD-for-psa-arch-test-254.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0001-Fix-in-AEAD-for-psa-arch-test-254.patch similarity index 100% rename from meta-arm-bsp/recipes-security/trusted-services/corstone1000/0002-Fix-in-AEAD-for-psa-arch-test-254.patch rename to meta-arm-bsp/recipes-security/trusted-services/corstone1000/0001-Fix-in-AEAD-for-psa-arch-test-254.patch diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0004-Fix-psa-api-crypto-test-no-243.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0002-Fix-psa-api-crypto-test-no-243.patch similarity index 100% rename from meta-arm-bsp/recipes-security/trusted-services/corstone1000/0004-Fix-psa-api-crypto-test-no-243.patch rename to meta-arm-bsp/recipes-security/trusted-services/corstone1000/0002-Fix-psa-api-crypto-test-no-243.patch diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0003-FMP-Support-in-Corstone1000.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0003-FMP-Support-in-Corstone1000.patch deleted file mode 100644 index cd2cf5fc..00000000 --- a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0003-FMP-Support-in-Corstone1000.patch +++ /dev/null @@ -1,418 +0,0 @@ -From fea499f48d07638417511f194c2977133fd75b4d Mon Sep 17 00:00:00 2001 -From: Satish Kumar -Date: Fri, 8 Jul 2022 09:48:06 +0100 -Subject: [PATCH 03/12] FMP Support in Corstone1000. - -The FMP support is used by u-boot to pupolate ESRT information -for the kernel. - -The solution is platform specific and needs to be revisted. - -Signed-off-by: Satish Kumar - -Upstream-Status: Inappropriate [The solution is platform specific and needs to be revisted] -Signed-off-by: Rui Miguel Silva ---- - .../provider/capsule_update_provider.c | 5 + - .../capsule_update/provider/component.cmake | 1 + - .../provider/corstone1000_fmp_service.c | 307 ++++++++++++++++++ - .../provider/corstone1000_fmp_service.h | 26 ++ - 4 files changed, 339 insertions(+) - create mode 100644 components/service/capsule_update/provider/corstone1000_fmp_service.c - create mode 100644 components/service/capsule_update/provider/corstone1000_fmp_service.h - -diff --git a/components/service/capsule_update/provider/capsule_update_provider.c b/components/service/capsule_update/provider/capsule_update_provider.c -index f35c272d2..bfeb7301a 100644 ---- a/components/service/capsule_update/provider/capsule_update_provider.c -+++ b/components/service/capsule_update/provider/capsule_update_provider.c -@@ -11,6 +11,7 @@ - #include - #include - #include "capsule_update_provider.h" -+#include "corstone1000_fmp_service.h" - - - #define CAPSULE_UPDATE_REQUEST (0x1) -@@ -49,6 +50,8 @@ struct rpc_service_interface *capsule_update_provider_init( - rpc_interface = service_provider_get_rpc_interface(&context->base_provider); - - -+ provision_fmp_variables_metadata(context->client.session->caller); -+ - return rpc_interface; - } - -@@ -87,6 +90,7 @@ static rpc_status_t event_handler(uint32_t opcode, struct rpc_caller_interface * - } - psa_call(caller,handle, PSA_IPC_CALL, - in_vec,IOVEC_LEN(in_vec), NULL, 0); -+ set_fmp_image_info(caller, handle); - break; - - case KERNEL_STARTED_EVENT: -@@ -101,6 +105,7 @@ static rpc_status_t event_handler(uint32_t opcode, struct rpc_caller_interface * - } - psa_call(caller,handle, PSA_IPC_CALL, - in_vec,IOVEC_LEN(in_vec), NULL, 0); -+ set_fmp_image_info(caller, handle); - break; - default: - EMSG("%s unsupported opcode", __func__); -diff --git a/components/service/capsule_update/provider/component.cmake b/components/service/capsule_update/provider/component.cmake -index 1d412eb23..6b0601494 100644 ---- a/components/service/capsule_update/provider/component.cmake -+++ b/components/service/capsule_update/provider/component.cmake -@@ -10,4 +10,5 @@ endif() - - target_sources(${TGT} PRIVATE - "${CMAKE_CURRENT_LIST_DIR}/capsule_update_provider.c" -+ "${CMAKE_CURRENT_LIST_DIR}/corstone1000_fmp_service.c" - ) -diff --git a/components/service/capsule_update/provider/corstone1000_fmp_service.c b/components/service/capsule_update/provider/corstone1000_fmp_service.c -new file mode 100644 -index 000000000..2222251a7 ---- /dev/null -+++ b/components/service/capsule_update/provider/corstone1000_fmp_service.c -@@ -0,0 +1,307 @@ -+/* -+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#include "corstone1000_fmp_service.h" -+#include -+#include -+#include -+#include -+ -+#include -+ -+#define VARIABLE_INDEX_STORAGE_UID (0x787) -+ -+/** -+ * Variable attributes -+ */ -+#define EFI_VARIABLE_NON_VOLATILE (0x00000001) -+#define EFI_VARIABLE_BOOTSERVICE_ACCESS (0x00000002) -+#define EFI_VARIABLE_RUNTIME_ACCESS (0x00000004) -+#define EFI_VARIABLE_HARDWARE_ERROR_RECORD (0x00000008) -+#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS (0x00000010) -+#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS (0x00000020) -+#define EFI_VARIABLE_APPEND_WRITE (0x00000040) -+#define EFI_VARIABLE_MASK \ -+ (EFI_VARIABLE_NON_VOLATILE | \ -+ EFI_VARIABLE_BOOTSERVICE_ACCESS | \ -+ EFI_VARIABLE_RUNTIME_ACCESS | \ -+ EFI_VARIABLE_HARDWARE_ERROR_RECORD | \ -+ EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | \ -+ EFI_VARIABLE_APPEND_WRITE) -+ -+#define FMP_VARIABLES_COUNT 6 -+ -+static struct variable_metadata fmp_variables_metadata[FMP_VARIABLES_COUNT] = { -+ { -+ { 0x86c77a67, 0x0b97, 0x4633, \ -+ { 0xa1, 0x87, 0x49, 0x10, 0x4d, 0x06, 0x85, 0xc7} }, -+ /* name size = (variable_name + \0) * sizeof(u16) */ -+ .name_size = 42, { 'F', 'm', 'p', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'V', 'e', 'r', 's', 'i', 'o', 'n' }, -+ .attributes = EFI_VARIABLE_NON_VOLATILE, .uid = 0 -+ }, -+ { -+ { 0x86c77a67, 0x0b97, 0x4633, \ -+ { 0xa1, 0x87, 0x49, 0x10, 0x4d, 0x06, 0x85, 0xc7} }, -+ /* name size = (variable_name + \0) * sizeof(u16) */ -+ .name_size = 34, { 'F', 'm', 'p', 'I', 'm', 'a', 'g', 'e', 'I', 'n', 'f', 'o', 'S', 'i', 'z', 'e' }, -+ .attributes = EFI_VARIABLE_NON_VOLATILE, .uid = 0 -+ }, -+ { -+ { 0x86c77a67, 0x0b97, 0x4633, \ -+ { 0xa1, 0x87, 0x49, 0x10, 0x4d, 0x06, 0x85, 0xc7} }, -+ /* name size = (variable_name + \0) * sizeof(u16) */ -+ .name_size = 38, { 'F', 'm', 'p', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'C', 'o', 'u', 'n', 't' }, -+ .attributes = EFI_VARIABLE_NON_VOLATILE, .uid = 0 -+ }, -+ { -+ { 0x86c77a67, 0x0b97, 0x4633, \ -+ { 0xa1, 0x87, 0x49, 0x10, 0x4d, 0x06, 0x85, 0xc7} }, -+ /* name size = (variable_name + \0) * sizeof(u16) */ -+ .name_size = 26, { 'F', 'm', 'p', 'I', 'm', 'a', 'g', 'e', 'I', 'n', 'f', 'o' }, -+ .attributes = EFI_VARIABLE_NON_VOLATILE, .uid = 0 -+ }, -+ { -+ { 0x86c77a67, 0x0b97, 0x4633, \ -+ { 0xa1, 0x87, 0x49, 0x10, 0x4d, 0x06, 0x85, 0xc7} }, -+ /* name size = (variable_name + \0) * sizeof(u16) */ -+ .name_size = 28, { 'F', 'm', 'p', 'I', 'm', 'a', 'g', 'e', 'N', 'a', 'm', 'e', '1' }, -+ .attributes = EFI_VARIABLE_NON_VOLATILE, .uid = 0 -+ }, -+ { -+ { 0x86c77a67, 0x0b97, 0x4633, \ -+ { 0xa1, 0x87, 0x49, 0x10, 0x4d, 0x06, 0x85, 0xc7} }, -+ /* name size = (variable_name + \0) * sizeof(u16) */ -+ .name_size = 32, { 'F', 'm', 'p', 'V', 'e', 'r', 's', 'i', 'o', 'n', 'N', 'a', 'm', 'e', '1' }, -+ .attributes = EFI_VARIABLE_NON_VOLATILE, .uid = 0 -+ }, -+}; -+ -+static psa_status_t protected_storage_set(struct rpc_caller_interface *caller, -+ psa_storage_uid_t uid, size_t data_length, const void *p_data) -+{ -+ psa_status_t psa_status; -+ psa_storage_create_flags_t create_flags = PSA_STORAGE_FLAG_NONE; -+ -+ struct psa_invec in_vec[] = { -+ { .base = psa_ptr_to_u32(&uid), .len = sizeof(uid) }, -+ { .base = psa_ptr_const_to_u32(p_data), .len = data_length }, -+ { .base = psa_ptr_to_u32(&create_flags), .len = sizeof(create_flags) }, -+ }; -+ -+ psa_status = psa_call(caller, TFM_PROTECTED_STORAGE_SERVICE_HANDLE, TFM_PS_ITS_SET, -+ in_vec, IOVEC_LEN(in_vec), NULL, 0); -+ if (psa_status < 0) -+ EMSG("ipc_set: psa_call failed: %d", psa_status); -+ -+ return psa_status; -+} -+ -+static psa_status_t protected_storage_get(struct rpc_caller_interface *caller, -+ psa_storage_uid_t uid, size_t data_size, void *p_data) -+{ -+ psa_status_t psa_status; -+ uint32_t offset = 0; -+ -+ struct psa_invec in_vec[] = { -+ { .base = psa_ptr_to_u32(&uid), .len = sizeof(uid) }, -+ { .base = psa_ptr_to_u32(&offset), .len = sizeof(offset) }, -+ }; -+ -+ struct psa_outvec out_vec[] = { -+ { .base = psa_ptr_to_u32(p_data), .len = data_size }, -+ }; -+ -+ psa_status = psa_call(caller, TFM_PROTECTED_STORAGE_SERVICE_HANDLE, -+ TFM_PS_ITS_GET, in_vec, IOVEC_LEN(in_vec), -+ out_vec, IOVEC_LEN(out_vec)); -+ -+ if (psa_status == PSA_SUCCESS && out_vec[0].len != data_size) { -+ EMSG("Return size does not match with expected size."); -+ return PSA_ERROR_BUFFER_TOO_SMALL; -+ } -+ -+ return psa_status; -+} -+ -+static uint64_t name_hash(EFI_GUID *guid, size_t name_size, -+ const int16_t *name) -+{ -+ /* Using djb2 hash by Dan Bernstein */ -+ uint64_t hash = 5381; -+ -+ /* Calculate hash over GUID */ -+ hash = ((hash << 5) + hash) + guid->Data1; -+ hash = ((hash << 5) + hash) + guid->Data2; -+ hash = ((hash << 5) + hash) + guid->Data3; -+ -+ for (int i = 0; i < 8; ++i) { -+ -+ hash = ((hash << 5) + hash) + guid->Data4[i]; -+ } -+ -+ /* Extend to cover name up to but not including null terminator */ -+ for (int i = 0; i < name_size / sizeof(int16_t); ++i) { -+ -+ if (!name[i]) break; -+ hash = ((hash << 5) + hash) + name[i]; -+ } -+ -+ return hash; -+} -+ -+ -+static void initialize_metadata(void) -+{ -+ for (int i = 0; i < FMP_VARIABLES_COUNT; i++) { -+ -+ fmp_variables_metadata[i].uid = name_hash( -+ &fmp_variables_metadata[i].guid, -+ fmp_variables_metadata[i].name_size, -+ fmp_variables_metadata[i].name); -+ } -+} -+ -+ -+void provision_fmp_variables_metadata(struct rpc_caller_interface *caller) -+{ -+ struct variable_metadata metadata; -+ psa_status_t status; -+ uint32_t dummy_values = 0xDEAD; -+ -+ EMSG("Provisioning FMP metadata."); -+ -+ initialize_metadata(); -+ -+ status = protected_storage_get(caller, VARIABLE_INDEX_STORAGE_UID, -+ sizeof(struct variable_metadata), &metadata); -+ -+ if (status == PSA_SUCCESS) { -+ EMSG("UEFI variables store is already provisioned."); -+ return; -+ } -+ -+ /* Provision FMP variables with dummy values. */ -+ for (int i = 0; i < FMP_VARIABLES_COUNT; i++) { -+ protected_storage_set(caller, fmp_variables_metadata[i].uid, -+ sizeof(dummy_values), &dummy_values); -+ } -+ -+ status = protected_storage_set(caller, VARIABLE_INDEX_STORAGE_UID, -+ sizeof(struct variable_metadata) * FMP_VARIABLES_COUNT, -+ fmp_variables_metadata); -+ -+ if (status != EFI_SUCCESS) { -+ return; -+ } -+ -+ EMSG("FMP metadata is provisioned"); -+} -+ -+typedef struct { -+ void *base; -+ int len; -+} variable_data_t; -+ -+static variable_data_t fmp_variables_data[FMP_VARIABLES_COUNT]; -+ -+#define IMAGE_INFO_BUFFER_SIZE 256 -+static char image_info_buffer[IMAGE_INFO_BUFFER_SIZE]; -+#define IOCTL_CORSTONE1000_FMP_IMAGE_INFO 2 -+ -+static psa_status_t unpack_image_info(void *buffer, uint32_t size) -+{ -+ typedef struct __attribute__ ((__packed__)) { -+ uint32_t variable_count; -+ uint32_t variable_size[FMP_VARIABLES_COUNT]; -+ uint8_t variable[]; -+ } packed_buffer_t; -+ -+ packed_buffer_t *packed_buffer = buffer; -+ int runner = 0; -+ -+ if (packed_buffer->variable_count != FMP_VARIABLES_COUNT) { -+ EMSG("Expected fmp varaibles = %u, but received = %u", -+ FMP_VARIABLES_COUNT, packed_buffer->variable_count); -+ return PSA_ERROR_PROGRAMMER_ERROR; -+ } -+ -+ for (int i = 0; i < packed_buffer->variable_count; i++) { -+ EMSG("FMP variable %d : size %u", i, packed_buffer->variable_size[i]); -+ fmp_variables_data[i].base = &packed_buffer->variable[runner]; -+ fmp_variables_data[i].len= packed_buffer->variable_size[i]; -+ runner += packed_buffer->variable_size[i]; -+ } -+ -+ return PSA_SUCCESS; -+} -+ -+static psa_status_t get_image_info(struct rpc_caller_interface *caller, -+ psa_handle_t platform_service_handle) -+{ -+ psa_status_t status; -+ psa_handle_t handle; -+ uint32_t ioctl_id = IOCTL_CORSTONE1000_FMP_IMAGE_INFO; -+ -+ struct psa_invec in_vec[] = { -+ { .base = &ioctl_id, .len = sizeof(ioctl_id) }, -+ }; -+ -+ struct psa_outvec out_vec[] = { -+ { .base = image_info_buffer, .len = IMAGE_INFO_BUFFER_SIZE }, -+ }; -+ -+ memset(image_info_buffer, 0, IMAGE_INFO_BUFFER_SIZE); -+ -+ psa_call(caller, platform_service_handle, PSA_IPC_CALL, -+ in_vec, IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec)); -+ -+ status = unpack_image_info(image_info_buffer, IMAGE_INFO_BUFFER_SIZE); -+ if (status != PSA_SUCCESS) { -+ return status; -+ } -+ -+ return PSA_SUCCESS; -+} -+ -+static psa_status_t set_image_info(struct rpc_caller_interface *caller) -+{ -+ psa_status_t status; -+ -+ for (int i = 0; i < FMP_VARIABLES_COUNT; i++) { -+ -+ status = protected_storage_set(caller, -+ fmp_variables_metadata[i].uid, -+ fmp_variables_data[i].len, fmp_variables_data[i].base); -+ -+ if (status != PSA_SUCCESS) { -+ -+ EMSG("FMP variable %d set unsuccessful", i); -+ return status; -+ } -+ -+ EMSG("FMP variable %d set success", i); -+ } -+ -+ return PSA_SUCCESS; -+} -+ -+void set_fmp_image_info(struct rpc_caller_interface *caller, -+ psa_handle_t platform_service_handle) -+{ -+ psa_status_t status; -+ -+ status = get_image_info(caller, platform_service_handle); -+ if (status != PSA_SUCCESS) { -+ return; -+ } -+ -+ status = set_image_info(caller); -+ if (status != PSA_SUCCESS) { -+ return; -+ } -+ -+ return; -+} -diff --git a/components/service/capsule_update/provider/corstone1000_fmp_service.h b/components/service/capsule_update/provider/corstone1000_fmp_service.h -new file mode 100644 -index 000000000..d0023dc07 ---- /dev/null -+++ b/components/service/capsule_update/provider/corstone1000_fmp_service.h -@@ -0,0 +1,26 @@ -+/* -+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved. -+ * -+ * SPDX-License-Identifier: BSD-3-Clause -+ */ -+ -+#ifndef CORSTONE1000_FMP_SERVICE_H -+#define CORSTONE1000_FMP_SERVICE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+void provision_fmp_variables_metadata(struct rpc_caller_interface *caller); -+ -+void set_fmp_image_info(struct rpc_caller_interface *caller, -+ psa_handle_t platform_service_handle); -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* CORSTONE1000_FMP_SERVICE_H */ --- -2.25.1 - diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0008-Remove-Werror-flag.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0003-Remove-Werror-flag.patch similarity index 100% rename from meta-arm-bsp/recipes-security/trusted-services/corstone1000/0008-Remove-Werror-flag.patch rename to meta-arm-bsp/recipes-security/trusted-services/corstone1000/0003-Remove-Werror-flag.patch diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0009-Remove-PLATFORM_HAS_ATTEST_PK-define-from-IAT-test.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0004-Remove-PLATFORM_HAS_ATTEST_PK-define-from-IAT-test.patch similarity index 100% rename from meta-arm-bsp/recipes-security/trusted-services/corstone1000/0009-Remove-PLATFORM_HAS_ATTEST_PK-define-from-IAT-test.patch rename to meta-arm-bsp/recipes-security/trusted-services/corstone1000/0004-Remove-PLATFORM_HAS_ATTEST_PK-define-from-IAT-test.patch diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0010-Make-RSS-and-MHU-sizes-compile-time-definitions-user.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0005-Make-RSS-and-MHU-sizes-compile-time-definitions-user.patch similarity index 100% rename from meta-arm-bsp/recipes-security/trusted-services/corstone1000/0010-Make-RSS-and-MHU-sizes-compile-time-definitions-user.patch rename to meta-arm-bsp/recipes-security/trusted-services/corstone1000/0005-Make-RSS-and-MHU-sizes-compile-time-definitions-user.patch diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0005-plat-corstone1000-Use-the-stateless-platform-service.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0005-plat-corstone1000-Use-the-stateless-platform-service.patch deleted file mode 100644 index 8324e9e0..00000000 --- a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0005-plat-corstone1000-Use-the-stateless-platform-service.patch +++ /dev/null @@ -1,141 +0,0 @@ -From 81d1dbe3f04195c0ad26790e127d61149e4f5b78 Mon Sep 17 00:00:00 2001 -From: Emekcan Aras -Date: Sun, 18 Jun 2023 14:38:42 +0100 -Subject: [PATCH 05/12] plat: corstone1000: Use the stateless platform service - calls Calls to psa_connect is not needed and psa_call can be called directly - with a pre defined handle. - -Signed-off-by: Satish Kumar -Signed-off-by: Mohamed Omar Asaker -Signed-off-by: Emekcan Aras - -Upstream-Status: Inappropriate [Design is to revisted] ---- - .../provider/capsule_update_provider.c | 24 ++++--------------- - .../provider/corstone1000_fmp_service.c | 10 ++++---- - .../provider/corstone1000_fmp_service.h | 3 +-- - components/service/common/include/psa/sid.h | 7 ++++++ - 4 files changed, 17 insertions(+), 27 deletions(-) - -diff --git a/components/service/capsule_update/provider/capsule_update_provider.c b/components/service/capsule_update/provider/capsule_update_provider.c -index bfeb7301a..12c552dae 100644 ---- a/components/service/capsule_update/provider/capsule_update_provider.c -+++ b/components/service/capsule_update/provider/capsule_update_provider.c -@@ -63,7 +63,6 @@ void capsule_update_provider_deinit(struct capsule_update_provider *context) - static rpc_status_t event_handler(uint32_t opcode, struct rpc_caller_interface *caller) - { - uint32_t ioctl_id; -- psa_handle_t handle; - rpc_status_t rpc_status = TS_RPC_CALL_ACCEPTED; - - struct psa_invec in_vec[] = { -@@ -81,31 +80,18 @@ static rpc_status_t event_handler(uint32_t opcode, struct rpc_caller_interface * - case CAPSULE_UPDATE_REQUEST: - /* Openamp call with IOCTL for firmware update*/ - ioctl_id = IOCTL_CORSTONE1000_FWU_FLASH_IMAGES; -- handle = psa_connect(caller, TFM_SP_PLATFORM_IOCTL_SID, -- TFM_SP_PLATFORM_IOCTL_VERSION); -- if (handle <= 0) { -- EMSG("%s Invalid handle", __func__); -- rpc_status = TS_RPC_ERROR_INVALID_PARAMETER; -- return rpc_status; -- } -- psa_call(caller,handle, PSA_IPC_CALL, -+ psa_call(caller,TFM_PLATFORM_SERVICE_HANDLE, TFM_PLATFORM_API_ID_IOCTL, - in_vec,IOVEC_LEN(in_vec), NULL, 0); -- set_fmp_image_info(caller, handle); -+ set_fmp_image_info(caller); - break; - - case KERNEL_STARTED_EVENT: - ioctl_id = IOCTL_CORSTONE1000_FWU_HOST_ACK; - /*openamp call with IOCTL for kernel start*/ -- handle = psa_connect(caller, TFM_SP_PLATFORM_IOCTL_SID, -- TFM_SP_PLATFORM_IOCTL_VERSION); -- if (handle <= 0) { -- EMSG("%s Invalid handle", __func__); -- rpc_status = TS_RPC_ERROR_INVALID_PARAMETER; -- return rpc_status; -- } -- psa_call(caller,handle, PSA_IPC_CALL, -+ -+ psa_call(caller,TFM_PLATFORM_SERVICE_HANDLE, TFM_PLATFORM_API_ID_IOCTL, - in_vec,IOVEC_LEN(in_vec), NULL, 0); -- set_fmp_image_info(caller, handle); -+ set_fmp_image_info(caller); - break; - default: - EMSG("%s unsupported opcode", __func__); -diff --git a/components/service/capsule_update/provider/corstone1000_fmp_service.c b/components/service/capsule_update/provider/corstone1000_fmp_service.c -index 2222251a7..2ed0f33c5 100644 ---- a/components/service/capsule_update/provider/corstone1000_fmp_service.c -+++ b/components/service/capsule_update/provider/corstone1000_fmp_service.c -@@ -238,8 +238,7 @@ static psa_status_t unpack_image_info(void *buffer, uint32_t size) - return PSA_SUCCESS; - } - --static psa_status_t get_image_info(struct rpc_caller_interface *caller, -- psa_handle_t platform_service_handle) -+static psa_status_t get_image_info(struct rpc_caller_interface *caller) - { - psa_status_t status; - psa_handle_t handle; -@@ -255,7 +254,7 @@ static psa_status_t get_image_info(struct rpc_caller_interface *caller, - - memset(image_info_buffer, 0, IMAGE_INFO_BUFFER_SIZE); - -- psa_call(caller, platform_service_handle, PSA_IPC_CALL, -+ psa_call(caller, TFM_PLATFORM_SERVICE_HANDLE, TFM_PLATFORM_API_ID_IOCTL, - in_vec, IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec)); - - status = unpack_image_info(image_info_buffer, IMAGE_INFO_BUFFER_SIZE); -@@ -288,12 +287,11 @@ static psa_status_t set_image_info(struct rpc_caller_interface *caller) - return PSA_SUCCESS; - } - --void set_fmp_image_info(struct rpc_caller_interface *caller, -- psa_handle_t platform_service_handle) -+void set_fmp_image_info(struct rpc_caller_interface *caller) - { - psa_status_t status; - -- status = get_image_info(caller, platform_service_handle); -+ status = get_image_info(caller); - if (status != PSA_SUCCESS) { - return; - } -diff --git a/components/service/capsule_update/provider/corstone1000_fmp_service.h b/components/service/capsule_update/provider/corstone1000_fmp_service.h -index d0023dc07..486fa10b4 100644 ---- a/components/service/capsule_update/provider/corstone1000_fmp_service.h -+++ b/components/service/capsule_update/provider/corstone1000_fmp_service.h -@@ -16,8 +16,7 @@ extern "C" { - - void provision_fmp_variables_metadata(struct rpc_caller_interface *caller); - --void set_fmp_image_info(struct rpc_caller_interface *caller, -- psa_handle_t platform_service_handle); -+void set_fmp_image_info(struct rpc_caller_interface *caller); - - #ifdef __cplusplus - } /* extern "C" */ -diff --git a/components/service/common/include/psa/sid.h b/components/service/common/include/psa/sid.h -index 5aaa659d4..fc3a4fb06 100644 ---- a/components/service/common/include/psa/sid.h -+++ b/components/service/common/include/psa/sid.h -@@ -40,6 +40,13 @@ extern "C" { - #define TFM_CRYPTO_VERSION (1U) - #define TFM_CRYPTO_HANDLE (0x40000100U) - -+/******** TFM_PLATFORM_SERVICE *******/ -+#define TFM_PLATFORM_API_ID_IOCTL (1013) -+#define TFM_PLATFORM_SERVICE_HANDLE (0x40000105U) -+ -+/** -+ * \brief Define a progressive numerical value for each SID which can be used -+ * when dispatching the requests to the service - /******** TFM_SP_PLATFORM ********/ - #define TFM_SP_PLATFORM_SYSTEM_RESET_SID (0x00000040U) - #define TFM_SP_PLATFORM_SYSTEM_RESET_VERSION (1U) --- -2.25.1 - diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0011-Align-PSA-Crypto-with-TF-Mv2.1.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0006-Align-PSA-Crypto-with-TF-Mv2.1.patch similarity index 100% rename from meta-arm-bsp/recipes-security/trusted-services/corstone1000/0011-Align-PSA-Crypto-with-TF-Mv2.1.patch rename to meta-arm-bsp/recipes-security/trusted-services/corstone1000/0006-Align-PSA-Crypto-with-TF-Mv2.1.patch diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0006-plat-corstone1000-Initialize-capsule-update-provider.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0006-plat-corstone1000-Initialize-capsule-update-provider.patch deleted file mode 100644 index 8b1e44ba..00000000 --- a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0006-plat-corstone1000-Initialize-capsule-update-provider.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 8a6542231613d5f1b60bc209a7ad8f8cf72bc95a Mon Sep 17 00:00:00 2001 -From: Bence Balogh -Date: Wed, 29 Nov 2023 15:40:21 +0100 -Subject: [PATCH 06/12] plat: corstone1000: Initialize capsule update provider - -Initializes the capsule update service provider in se-proxy-sp.c deployment -for corstone1000. - -Signed-off-by: Emekcan Aras -Upstream-Status: Inappropriate [Design is to revisted] ---- - .../se-proxy/env/commonsp/se_proxy_sp.c | 14 +++++++++- - .../corstone1000/service_proxy_factory.c | 28 +++++++++++++++++++ - .../se-proxy/infra/service_proxy_factory.h | 1 + - 3 files changed, 42 insertions(+), 1 deletion(-) - -diff --git a/deployments/se-proxy/env/commonsp/se_proxy_sp.c b/deployments/se-proxy/env/commonsp/se_proxy_sp.c -index 485d76493..88e4cf17e 100644 ---- a/deployments/se-proxy/env/commonsp/se_proxy_sp.c -+++ b/deployments/se-proxy/env/commonsp/se_proxy_sp.c -@@ -39,7 +39,7 @@ void __noreturn sp_main(union ffa_boot_info *boot_info) - goto fatal_error; - } - -- rpc_status = ts_rpc_endpoint_sp_init(&rpc_endpoint, 5, 16); -+ rpc_status = ts_rpc_endpoint_sp_init(&rpc_endpoint, 6, 16); - if (rpc_status != RPC_SUCCESS) { - EMSG("Failed to initialize RPC endpoint: %d", rpc_status); - goto fatal_error; -@@ -94,6 +94,18 @@ void __noreturn sp_main(union ffa_boot_info *boot_info) - goto fatal_error; - } - -+ rpc_iface = capsule_update_proxy_create(); -+ if (!rpc_iface) { -+ EMSG("Failed to create Capsule Update proxy"); -+ goto fatal_error; -+ } -+ -+ rpc_status = ts_rpc_endpoint_sp_add_service(&rpc_endpoint, rpc_iface); -+ if (rpc_status != RPC_SUCCESS) { -+ EMSG("Failed to add service to RPC endpoint: %d", rpc_status); -+ goto fatal_error; -+ } -+ - rpc_iface = fwu_proxy_create(); - if (!rpc_iface) { - EMSG("Failed to create FWU proxy"); -diff --git a/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c b/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c -index 759983b46..185a6cd97 100644 ---- a/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c -+++ b/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - #include - #include "service/fwu/psa_fwu_m/agent/psa_fwu_m_update_agent.h" - #include "service/fwu/provider/fwu_provider.h" -@@ -141,3 +142,30 @@ struct rpc_service_interface *fwu_proxy_create(void) - - return fwu_provider_init(&fwu_provider, agent); - } -+ -+struct rpc_service_interface *capsule_update_proxy_create(void) -+{ -+ static struct capsule_update_provider capsule_update_provider; -+ static struct secure_storage_ipc capsule_update_backend; -+ rpc_status_t rpc_status = RPC_ERROR_INTERNAL; -+ -+ /* Static objects for proxy instance */ -+ static struct rpc_caller_interface rse_comms = { 0 }; -+ static struct rpc_caller_session rpc_session = { 0 }; -+ -+ rpc_status = rse_comms_caller_init(&rse_comms); -+ if (rpc_status != RPC_SUCCESS) -+ return NULL; -+ -+ rpc_status = rpc_caller_session_open(&rpc_session, &rse_comms, &dummy_uuid, 0, 0); -+ if (rpc_status != RPC_SUCCESS) -+ return NULL; -+ -+ -+ capsule_update_provider.client.session = &rpc_session; -+ capsule_update_provider.client.rpc_status = RPC_SUCCESS; -+ capsule_update_provider.client.service_info.supported_encodings = 0; -+ capsule_update_provider.client.service_info.max_payload = 4096; -+ -+ return capsule_update_provider_init(&capsule_update_provider); -+} -diff --git a/deployments/se-proxy/infra/service_proxy_factory.h b/deployments/se-proxy/infra/service_proxy_factory.h -index be83319b8..88b377063 100644 ---- a/deployments/se-proxy/infra/service_proxy_factory.h -+++ b/deployments/se-proxy/infra/service_proxy_factory.h -@@ -18,6 +18,7 @@ struct rpc_service_interface *crypto_proxy_create(void); - struct rpc_service_interface *ps_proxy_create(void); - struct rpc_service_interface *its_proxy_create(void); - struct rpc_service_interface *fwu_proxy_create(void); -+struct rpc_service_interface *capsule_update_proxy_create(void); - - #ifdef __cplusplus - } --- -2.25.1 - diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0013-Revert-Load-and-store-UEFI-variable-index-in-chunks.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0007-Revert-Load-and-store-UEFI-variable-index-in-chunks.patch similarity index 74% rename from meta-arm-bsp/recipes-security/trusted-services/corstone1000/0013-Revert-Load-and-store-UEFI-variable-index-in-chunks.patch rename to meta-arm-bsp/recipes-security/trusted-services/corstone1000/0007-Revert-Load-and-store-UEFI-variable-index-in-chunks.patch index 09fa94fc..176900b5 100644 --- a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0013-Revert-Load-and-store-UEFI-variable-index-in-chunks.patch +++ b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0007-Revert-Load-and-store-UEFI-variable-index-in-chunks.patch @@ -1,28 +1,29 @@ -From c490956e50e721c8f2db5934ae5af365ba92e55a Mon Sep 17 00:00:00 2001 +From a986e751f6d4ef34bdc3847cfb02e6f24fbb0702 Mon Sep 17 00:00:00 2001 From: Bence Balogh Date: Mon, 25 Nov 2024 22:13:15 +0100 -Subject: [PATCH 2/3] Revert "Load and store UEFI variable index in chunks" +Subject: [PATCH 01/12] Revert "Load and store UEFI variable index in chunks" This reverts commit a0a08571084238af2a24d4e6e580308f86ab59a2. The PSA IPC backend for the Protected Storage doesn't support the optional -create() and set_extended() APIs. This feature has to be reverted because +create() and set_extended() APIs. This feature has to be reverted because of this. -Keep this inappropriate patch until the usage of create() and set_extended() +Keep this inappropriate patch until the usage of create() and set_extended() APIs are not optional in the SMM-Gateway. Upstream-Status: Inappropriate [To be redesigned] Signed-off-by: Bence Balogh +Signed-off-by: Harsimran Singh Tungal --- - .../backend/test/variable_store_tests.cpp | 100 +----------------- - .../backend/uefi_variable_store.c | 84 +++------------ + .../backend/test/variable_store_tests.cpp | 100 +-------------- + .../backend/uefi_variable_store.c | 115 ++++-------------- deployments/smm-gateway/common/smm_gateway.c | 4 + - 3 files changed, 22 insertions(+), 166 deletions(-) + 3 files changed, 28 insertions(+), 191 deletions(-) diff --git a/components/service/uefi/smm_variable/backend/test/variable_store_tests.cpp b/components/service/uefi/smm_variable/backend/test/variable_store_tests.cpp -index e0f21f77a..2a8c8eb94 100644 +index 0f962f20..7c7435fb 100644 --- a/components/service/uefi/smm_variable/backend/test/variable_store_tests.cpp +++ b/components/service/uefi/smm_variable/backend/test/variable_store_tests.cpp -@@ -56,12 +56,6 @@ TEST_GROUP(UefiVariableStoreTests) +@@ -57,12 +57,6 @@ TEST_GROUP(UefiVariableStoreTests) return var_name; } @@ -35,7 +36,7 @@ index e0f21f77a..2a8c8eb94 100644 size_t string_get_size_in_bytes(const std::u16string &string) { return string.size() * sizeof(uint16_t); -@@ -266,9 +260,9 @@ TEST_GROUP(UefiVariableStoreTests) +@@ -267,9 +261,9 @@ TEST_GROUP(UefiVariableStoreTests) MAX_VARIABLE_SIZE); } @@ -44,14 +45,13 @@ index e0f21f77a..2a8c8eb94 100644 static const size_t MAX_VARIABLE_SIZE = 3000; - static const size_t STORE_CAPACITY = MAX_VARIABLES * MAX_VARIABLE_SIZE; + static const size_t STORE_CAPACITY = 10000; - - static const uint32_t OWNER_ID = 100; - /* -@@ -773,93 +767,3 @@ TEST(UefiVariableStoreTests, noRemoveCheck) - EFI_VARIABLE_NON_VOLATILE); + static const size_t VARIABLE_INDEX_MAX_SIZE = + sizeof(uint32_t) + + MAX_VARIABLES * (sizeof(struct variable_metadata) + +@@ -784,96 +778,6 @@ TEST(UefiVariableStoreTests, noRemoveCheck) UNSIGNED_LONGLONGS_EQUAL(EFI_INVALID_PARAMETER, status); } -- + -TEST(UefiVariableStoreTests, fillStore) -{ - efi_status_t status = EFI_SUCCESS; @@ -141,50 +141,77 @@ index e0f21f77a..2a8c8eb94 100644 - LONGS_EQUAL(0, input_data.compare(output_data)); - } -} +- + TEST(UefiVariableStoreTests, variableIndexCounterOverflow) + { + efi_status_t efi_status = EFI_SUCCESS; diff --git a/components/service/uefi/smm_variable/backend/uefi_variable_store.c b/components/service/uefi/smm_variable/backend/uefi_variable_store.c -index 459ca4566..e5fc32864 100644 +index 48b81ff3..e90ed172 100644 --- a/components/service/uefi/smm_variable/backend/uefi_variable_store.c +++ b/components/service/uefi/smm_variable/backend/uefi_variable_store.c -@@ -615,41 +615,26 @@ static efi_status_t load_variable_index(struct uefi_variable_store *context) +@@ -716,59 +716,29 @@ static psa_status_t get_active_variable_uid(struct uefi_variable_store *context, + static efi_status_t load_variable_index(struct uefi_variable_store *context) + { + struct storage_backend *persistent_store = context->persistent_store.storage_backend; +- psa_status_t psa_status = PSA_SUCCESS; if (persistent_store) { size_t data_len = 0; - size_t data_offset = 0; +- struct psa_storage_info_t variable_index_info = { 0 }; +- +- psa_status = get_active_variable_uid(context, &context->active_variable_index_uid, +- &context->variable_index.counter); +- switch (psa_status) { +- case PSA_SUCCESS: +- break; -- do { -- psa_status_t psa_status = persistent_store->interface->get( -- persistent_store->context, context->owner_id, -- SMM_VARIABLE_INDEX_STORAGE_UID, data_offset, -- RPC_CALLER_SESSION_SHARED_MEMORY_SIZE, -- context->index_sync_buffer + data_offset, &data_len); +- case PSA_ERROR_DOES_NOT_EXIST: +- IMSG("Variable index does not exist in NV store, continuing with empty index"); +- return EFI_SUCCESS; + psa_status_t psa_status = persistent_store->interface->get( + persistent_store->context, context->owner_id, + SMM_VARIABLE_INDEX_STORAGE_UID, 0, context->index_sync_buffer_size, + context->index_sync_buffer, &data_len); -- switch (psa_status) { -+ switch(psa_status) { - case PSA_SUCCESS: -- data_offset += data_len; +- default: +- EMSG("Loading variable index failed: %d", psa_status); +- return EFI_LOAD_ERROR; +- } - -- if (data_offset > context->index_sync_buffer_size) { -- EMSG("Variable index cannot fit the sync buffer"); -- return EFI_LOAD_ERROR; -- } +- /* Make sure the variable index fits the buffer */ +- persistent_store->interface->get_info(persistent_store->context, context->owner_id, +- context->active_variable_index_uid, +- &variable_index_info); - +- if (variable_index_info.size > context->index_sync_buffer_size) { +- EMSG("Variable index cannot fit the sync buffer"); +- return EFI_LOAD_ERROR; +- } ++ switch(psa_status) { ++ case PSA_SUCCESS: + (void) variable_index_restore(&context->variable_index, data_len, + context->index_sync_buffer); - break; ++ break; - case PSA_ERROR_DOES_NOT_EXIST: - IMSG("Index variable does not exist in NV store, continuing with empty index"); -- return EFI_SUCCESS; +- do { +- psa_status = persistent_store->interface->get( +- persistent_store->context, context->owner_id, +- context->active_variable_index_uid, data_offset, +- RPC_CALLER_SESSION_SHARED_MEMORY_SIZE, +- context->index_sync_buffer + data_offset, &data_len); ++ case PSA_ERROR_DOES_NOT_EXIST: ++ IMSG("Index variable does not exist in NV store, continuing with empty index"); + break; - default: +- if (psa_status != PSA_SUCCESS) { ++ default: EMSG("Loading variable index failed: %d", psa_status); return EFI_LOAD_ERROR; - } +- +- data_offset += data_len; +- - } while (data_len == RPC_CALLER_SESSION_SHARED_MEMORY_SIZE); - - variable_index_restore(&context->variable_index, data_offset, @@ -196,8 +223,8 @@ index 459ca4566..e5fc32864 100644 } return EFI_SUCCESS; -@@ -658,14 +643,13 @@ static efi_status_t load_variable_index(struct uefi_variable_store *context) - static efi_status_t sync_variable_index(const struct uefi_variable_store *context) +@@ -777,14 +747,13 @@ static efi_status_t load_variable_index(struct uefi_variable_store *context) + static efi_status_t sync_variable_index(struct uefi_variable_store *context) { efi_status_t status = EFI_SUCCESS; - psa_status_t psa_status = PSA_SUCCESS; @@ -213,27 +240,29 @@ index 459ca4566..e5fc32864 100644 if (status != EFI_SUCCESS) return status; -@@ -674,52 +658,16 @@ static efi_status_t sync_variable_index(const struct uefi_variable_store *contex +@@ -793,56 +762,16 @@ static efi_status_t sync_variable_index(struct uefi_variable_store *context) context->persistent_store.storage_backend; if (persistent_store) { - size_t data_offset = 0; +- uint64_t next_index_uid = 0; +- +- /* Write the older one */ +- next_index_uid = (context->active_variable_index_uid == +- SMM_VARIABLE_INDEX_STORAGE_A_UID ? +- SMM_VARIABLE_INDEX_STORAGE_B_UID : +- SMM_VARIABLE_INDEX_STORAGE_A_UID); - - psa_status = persistent_store->interface->remove( -+ psa_status_t psa_status = persistent_store->interface->set( - persistent_store->context, context->owner_id, -- SMM_VARIABLE_INDEX_STORAGE_UID); +- persistent_store->context, context->owner_id, next_index_uid); - - if (psa_status != PSA_SUCCESS && psa_status != PSA_ERROR_DOES_NOT_EXIST) - goto end; -+ SMM_VARIABLE_INDEX_STORAGE_UID, data_len, -+ context->index_sync_buffer, PSA_STORAGE_FLAG_NONE); - +- - /* Check if the index exists and create if not yet */ - psa_status = persistent_store->interface->create( -- persistent_store->context, context->owner_id, -- SMM_VARIABLE_INDEX_STORAGE_UID, remaining_data_len, -- PSA_STORAGE_FLAG_NONE); +- persistent_store->context, context->owner_id, next_index_uid, +- remaining_data_len, PSA_STORAGE_FLAG_NONE); - - if (psa_status != PSA_SUCCESS) - goto end; @@ -244,8 +273,7 @@ index 459ca4566..e5fc32864 100644 - - psa_status = persistent_store->interface->set_extended( - persistent_store->context, context->owner_id, -- SMM_VARIABLE_INDEX_STORAGE_UID, data_offset, -- data_of_this_iteration, +- next_index_uid, data_offset, data_of_this_iteration, - context->index_sync_buffer + data_offset); - - if (psa_status != PSA_SUCCESS) @@ -255,7 +283,11 @@ index 459ca4566..e5fc32864 100644 - remaining_data_len -= data_of_this_iteration; - - } while (remaining_data_len); -- ++ psa_status_t psa_status = persistent_store->interface->set( ++ persistent_store->context, context->owner_id, ++ SMM_VARIABLE_INDEX_STORAGE_UID, data_len, ++ context->index_sync_buffer, PSA_STORAGE_FLAG_NONE); + - variable_index_confirm_write(&context->variable_index); - context->active_variable_index_uid = next_index_uid; - } else { @@ -272,7 +304,7 @@ index 459ca4566..e5fc32864 100644 /* Check attribute usage rules */ diff --git a/deployments/smm-gateway/common/smm_gateway.c b/deployments/smm-gateway/common/smm_gateway.c -index 3ab45ccf5..eaa861370 100644 +index 3ab45ccf..eaa86137 100644 --- a/deployments/smm-gateway/common/smm_gateway.c +++ b/deployments/smm-gateway/common/smm_gateway.c @@ -40,6 +40,10 @@ @@ -287,5 +319,5 @@ index 3ab45ccf5..eaa861370 100644 * The SP heap must be large enough for storing the UEFI variable index, the RPC shared memory and * ~16kB of miscellaneous data. -- -2.25.1 +2.34.1 diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0007-plat-corstone1000-add-client_id-for-FMP-service.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0007-plat-corstone1000-add-client_id-for-FMP-service.patch deleted file mode 100644 index f56c3578..00000000 --- a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0007-plat-corstone1000-add-client_id-for-FMP-service.patch +++ /dev/null @@ -1,49 +0,0 @@ -From eddadb001463495307fb33f99e8cb41b9722ace1 Mon Sep 17 00:00:00 2001 -From: Bence Balogh -Date: Fri, 5 Apr 2024 17:31:03 +0200 -Subject: [PATCH 07/12] plat: corstone1000: add client_id for FMP service - -Corstone1000 uses trusted-firmware-m as secure enclave software component. Due -to the changes in TF-M 2.0, psa services requires a seperate client_id now. -This commit adds smm-gateway-sp client id to the FMP services since FMP structure -accessed by u-boot via smm-gateway-sp. - -Signed-off-by: emeara01 -Upstream-Status: Inappropriate [Design is to revisted] ---- - .../capsule_update/provider/corstone1000_fmp_service.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/components/service/capsule_update/provider/corstone1000_fmp_service.c b/components/service/capsule_update/provider/corstone1000_fmp_service.c -index 2ed0f33c5..58c2cceaf 100644 ---- a/components/service/capsule_update/provider/corstone1000_fmp_service.c -+++ b/components/service/capsule_update/provider/corstone1000_fmp_service.c -@@ -33,6 +33,7 @@ - EFI_VARIABLE_APPEND_WRITE) - - #define FMP_VARIABLES_COUNT 6 -+#define SMM_GW_SP_ID 0x8003 - - static struct variable_metadata fmp_variables_metadata[FMP_VARIABLES_COUNT] = { - { -@@ -91,7 +92,7 @@ static psa_status_t protected_storage_set(struct rpc_caller_interface *caller, - { .base = psa_ptr_to_u32(&create_flags), .len = sizeof(create_flags) }, - }; - -- psa_status = psa_call(caller, TFM_PROTECTED_STORAGE_SERVICE_HANDLE, TFM_PS_ITS_SET, -+ psa_status = psa_call_client_id(caller, TFM_PROTECTED_STORAGE_SERVICE_HANDLE, SMM_GW_SP_ID,TFM_PS_ITS_SET, - in_vec, IOVEC_LEN(in_vec), NULL, 0); - if (psa_status < 0) - EMSG("ipc_set: psa_call failed: %d", psa_status); -@@ -114,7 +115,7 @@ static psa_status_t protected_storage_get(struct rpc_caller_interface *caller, - { .base = psa_ptr_to_u32(p_data), .len = data_size }, - }; - -- psa_status = psa_call(caller, TFM_PROTECTED_STORAGE_SERVICE_HANDLE, -+ psa_status = psa_call_client_id(caller, TFM_PROTECTED_STORAGE_SERVICE_HANDLE, SMM_GW_SP_ID, - TFM_PS_ITS_GET, in_vec, IOVEC_LEN(in_vec), - out_vec, IOVEC_LEN(out_vec)); - --- -2.25.1 - diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0008-se-proxy-protobuf-change.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0008-se-proxy-protobuf-change.patch new file mode 100644 index 00000000..c7ac1614 --- /dev/null +++ b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0008-se-proxy-protobuf-change.patch @@ -0,0 +1,71 @@ +From 77dbb98428b0661f0ceee54208d226fc7fb27130 Mon Sep 17 00:00:00 2001 +From: Harsimran Singh Tungal +Date: Sun, 1 Jun 2025 11:06:00 +0000 +Subject: [PATCH 02/11] se proxy protobuf change + +Upstream-Status: Pending (not yet submitted to upstream) +Signed-off-by: Emekcan Aras +Signed-off-by: Harsimran Singh Tungal +--- + .../se-proxy/env/commonsp/se_proxy_sp.c | 24 ++++++++++++++++++- + 1 file changed, 23 insertions(+), 1 deletion(-) + +diff --git a/deployments/se-proxy/env/commonsp/se_proxy_sp.c b/deployments/se-proxy/env/commonsp/se_proxy_sp.c +index 485d7649..9f94092b 100644 +--- a/deployments/se-proxy/env/commonsp/se_proxy_sp.c ++++ b/deployments/se-proxy/env/commonsp/se_proxy_sp.c +@@ -13,6 +13,7 @@ + #include "trace.h" + #include "deployments/se-proxy/infra/service_proxy_factory.h" + #include "deployments/se-proxy/se_proxy_interfaces.h" ++#include + + static bool sp_init(uint16_t *own_sp_id); + +@@ -25,6 +26,8 @@ void __noreturn sp_main(union ffa_boot_info *boot_info) + uint16_t own_id = 0; + sp_result result = SP_RESULT_INTERNAL_ERROR; + rpc_status_t rpc_status = RPC_ERROR_INTERNAL; ++ struct rpc_service_interface *crypto_iface_protobuf = NULL; ++ struct crypto_provider *crypto_protobuf_provider = NULL; + + /* Boot phase */ + if (!sp_init(&own_id)) { +@@ -39,7 +42,7 @@ void __noreturn sp_main(union ffa_boot_info *boot_info) + goto fatal_error; + } + +- rpc_status = ts_rpc_endpoint_sp_init(&rpc_endpoint, 5, 16); ++ rpc_status = ts_rpc_endpoint_sp_init(&rpc_endpoint, 6, 16); + if (rpc_status != RPC_SUCCESS) { + EMSG("Failed to initialize RPC endpoint: %d", rpc_status); + goto fatal_error; +@@ -106,6 +109,25 @@ void __noreturn sp_main(union ffa_boot_info *boot_info) + goto fatal_error; + } + ++ crypto_protobuf_provider = crypto_protobuf_provider_factory_create(); ++ if (!crypto_protobuf_provider) { ++ EMSG("Failed to create crypto protobuf provider factory"); ++ goto fatal_error; ++ } ++ ++ crypto_iface_protobuf = service_provider_get_rpc_interface( ++ &crypto_protobuf_provider->base_provider); ++ if (!crypto_iface_protobuf) { ++ EMSG("Failed to create service provider RPC interface"); ++ goto fatal_error; ++ } ++ ++ rpc_status = ts_rpc_endpoint_sp_add_service(&rpc_endpoint, crypto_iface_protobuf); ++ if (rpc_status != RPC_SUCCESS) { ++ EMSG("Failed to add service to RPC endpoint: %d", rpc_status); ++ goto fatal_error; ++ } ++ + /* End of boot phase */ + result = sp_msg_wait(&req_msg); + if (result != SP_RESULT_OK) { +-- +2.34.1 + diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0017-Platform-Corstone1000-Add-PLATFORM_IS_FVP-toggle-for.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0009-Platform-Corstone1000-Add-PLATFORM_IS_FVP-toggle-for.patch similarity index 100% rename from meta-arm-bsp/recipes-security/trusted-services/corstone1000/0017-Platform-Corstone1000-Add-PLATFORM_IS_FVP-toggle-for.patch rename to meta-arm-bsp/recipes-security/trusted-services/corstone1000/0009-Platform-Corstone1000-Add-PLATFORM_IS_FVP-toggle-for.patch diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0018-Integrate-PSA-FWU-IPC-framework-for-Corstone-1000.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0010-Integrate-PSA-FWU-IPC-framework-for-Corstone-1000.patch similarity index 97% rename from meta-arm-bsp/recipes-security/trusted-services/corstone1000/0018-Integrate-PSA-FWU-IPC-framework-for-Corstone-1000.patch rename to meta-arm-bsp/recipes-security/trusted-services/corstone1000/0010-Integrate-PSA-FWU-IPC-framework-for-Corstone-1000.patch index 2c2bb428..4a80e6b3 100644 --- a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0018-Integrate-PSA-FWU-IPC-framework-for-Corstone-1000.patch +++ b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0010-Integrate-PSA-FWU-IPC-framework-for-Corstone-1000.patch @@ -1,7 +1,7 @@ -From fcc7701baf4246e5ceebe4d50db223cb70a0c00f Mon Sep 17 00:00:00 2001 +From f385ddacc8cc62842f7c9c91622d59959c41e718 Mon Sep 17 00:00:00 2001 From: Harsimran Singh Tungal Date: Thu, 28 Nov 2024 12:02:28 +0000 -Subject: [PATCH 1/8] Integrate PSA FWU IPC framework for Corstone-1000 +Subject: [PATCH 04/11] Integrate PSA FWU IPC framework for Corstone-1000 Integrate IPC framework for PSA FWU calls between Cortex-A side and Cortex-M subsystems. @@ -26,7 +26,7 @@ Signed-off-by: Harsimran Singh Tungal create mode 100644 components/service/fwu/psa_fwu_m/interface/psa_ipc/psa_fwu_ipc.h diff --git a/components/service/common/include/psa/sid.h b/components/service/common/include/psa/sid.h -index fc3a4fb0..4830f438 100644 +index 5aaa659d..0235764d 100644 --- a/components/service/common/include/psa/sid.h +++ b/components/service/common/include/psa/sid.h @@ -1,5 +1,5 @@ @@ -36,7 +36,7 @@ index fc3a4fb0..4830f438 100644 * * SPDX-License-Identifier: BSD-3-Clause * -@@ -65,6 +65,10 @@ extern "C" { +@@ -58,6 +58,10 @@ extern "C" { #define TFM_ATTEST_GET_TOKEN_SIZE 1002 /******** TFM_SP_FWU ********/ @@ -381,7 +381,7 @@ index 00000000..867a1c9c +#endif /* PSA_FWU_IPC_H */ + diff --git a/deployments/se-proxy/infra/corstone1000/infra.cmake b/deployments/se-proxy/infra/corstone1000/infra.cmake -index 27af8a33..0b04149a 100644 +index 3830f9d6..2bf6b36e 100644 --- a/deployments/se-proxy/infra/corstone1000/infra.cmake +++ b/deployments/se-proxy/infra/corstone1000/infra.cmake @@ -26,7 +26,7 @@ add_components(TARGET "se-proxy" @@ -390,14 +390,14 @@ index 27af8a33..0b04149a 100644 "components/service/fwu/psa_fwu_m/agent" - "components/service/fwu/psa_fwu_m/interface/stub" + "components/service/fwu/psa_fwu_m/interface/psa_ipc" - "components/service/capsule_update/provider" "components/service/secure_storage/backend/secure_storage_ipc" ) + diff --git a/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c b/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c -index 8872abcb..ef91efe0 100644 +index 759983b4..547e84bc 100644 --- a/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c +++ b/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c -@@ -15,6 +15,7 @@ +@@ -14,6 +14,7 @@ #include #include "service/fwu/psa_fwu_m/agent/psa_fwu_m_update_agent.h" #include "service/fwu/provider/fwu_provider.h" @@ -405,7 +405,7 @@ index 8872abcb..ef91efe0 100644 #include #include "service/secure_storage/frontend/secure_storage_provider/secure_storage_uuid.h" #include -@@ -135,10 +136,25 @@ struct rpc_service_interface *its_proxy_create(void) +@@ -134,10 +135,25 @@ struct rpc_service_interface *its_proxy_create(void) struct rpc_service_interface *fwu_proxy_create(void) { @@ -432,5 +432,5 @@ index 8872abcb..ef91efe0 100644 return fwu_provider_init(&fwu_provider, agent); } -- -2.25.1 +2.34.1 diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0019-Load-initial-image-state-in-PSA-FWU-M-update-agent.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0011-Load-initial-image-state-in-PSA-FWU-M-update-agent.patch similarity index 100% rename from meta-arm-bsp/recipes-security/trusted-services/corstone1000/0019-Load-initial-image-state-in-PSA-FWU-M-update-agent.patch rename to meta-arm-bsp/recipes-security/trusted-services/corstone1000/0011-Load-initial-image-state-in-PSA-FWU-M-update-agent.patch diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0020-Corstone1000-Define-PSA-FWU-image-mapping-structure.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0012-Corstone1000-Define-PSA-FWU-image-mapping-structure.patch similarity index 100% rename from meta-arm-bsp/recipes-security/trusted-services/corstone1000/0020-Corstone1000-Define-PSA-FWU-image-mapping-structure.patch rename to meta-arm-bsp/recipes-security/trusted-services/corstone1000/0012-Corstone1000-Define-PSA-FWU-image-mapping-structure.patch diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0012-Revert-Make-variable-index-usage-robust-with-redunda.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0012-Revert-Make-variable-index-usage-robust-with-redunda.patch deleted file mode 100644 index 8b5f062f..00000000 --- a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0012-Revert-Make-variable-index-usage-robust-with-redunda.patch +++ /dev/null @@ -1,716 +0,0 @@ -From f0c1c15fc8886349f7aeb04e1328472894b674d7 Mon Sep 17 00:00:00 2001 -From: Bence Balogh -Date: Mon, 25 Nov 2024 22:11:33 +0100 -Subject: [PATCH 1/3] Revert "Make variable index usage robust with redundancy" - -This reverts commit 8e394bbfae1dccf86a6a5428471e1b10fdaa74ec. -This revert is needed because the FMP support added for Corstone-1000 only -works if the SMM_VARIABLE_INDEX_STORAGE_UID is 0x787. See the implementation -in the 0003-FMP-Support-in-Corstone1000.patch file. - -The 0003-FMP-Support-in-Corstone1000.patch is also inappropriate and will be -redesigned. Instead of fixing that patch, revert this redundancy feature until -the FMP support is redesigned. - -Upstream-Status: Inappropriate [To be removed after new FWU design] -Signed-off-by: Bence Balogh ---- - .../backend/test/variable_index_tests.cpp | 50 ++--- - .../backend/test/variable_store_tests.cpp | 166 ---------------- - .../backend/uefi_variable_store.c | 181 +++--------------- - .../backend/uefi_variable_store.h | 1 - - .../smm_variable/backend/variable_index.c | 29 +-- - .../smm_variable/backend/variable_index.h | 3 +- - 6 files changed, 46 insertions(+), 384 deletions(-) - -diff --git a/components/service/uefi/smm_variable/backend/test/variable_index_tests.cpp b/components/service/uefi/smm_variable/backend/test/variable_index_tests.cpp -index cf0f6a12e..a52cfbf76 100644 ---- a/components/service/uefi/smm_variable/backend/test/variable_index_tests.cpp -+++ b/components/service/uefi/smm_variable/backend/test/variable_index_tests.cpp -@@ -208,8 +208,7 @@ TEST(UefiVariableIndexTests, enumerateStore) - - TEST(UefiVariableIndexTests, dumpLoadRoadtrip) - { -- uint8_t buffer[sizeof(uint32_t) + -- MAX_VARIABLES * (sizeof(struct variable_metadata) + sizeof(bool))]; -+ uint8_t buffer[MAX_VARIABLES * sizeof(struct variable_metadata)]; - - create_variables(); - -@@ -223,13 +222,7 @@ TEST(UefiVariableIndexTests, dumpLoadRoadtrip) - - CHECK_TRUE(is_dirty); - UNSIGNED_LONGS_EQUAL(EFI_SUCCESS, status); -- /* -- * Variable index counter is at the beginning, which is followed by metadata and -- * constraint status byte of both NV variables -- */ -- UNSIGNED_LONGS_EQUAL(sizeof(uint32_t) + -- ((sizeof(struct variable_metadata) + sizeof(bool)) * 2), -- dump_len); -+ UNSIGNED_LONGS_EQUAL(((sizeof(struct variable_metadata) + sizeof(bool)) * 2), dump_len); - - /* Expect no records to be dirty when the dump is repeated */ - dump_len = 0; -@@ -238,9 +231,7 @@ TEST(UefiVariableIndexTests, dumpLoadRoadtrip) - - UNSIGNED_LONGS_EQUAL(EFI_SUCCESS, status); - CHECK_FALSE(is_dirty); -- UNSIGNED_LONGS_EQUAL(sizeof(uint32_t) + -- ((sizeof(struct variable_metadata) + sizeof(bool)) * 2), -- dump_len); -+ UNSIGNED_LONGS_EQUAL(((sizeof(struct variable_metadata) + sizeof(bool)) * 2), dump_len); - - /* Tear down and reinitialize to simulate a reboot */ - variable_index_deinit(&m_variable_index); -@@ -279,8 +270,7 @@ TEST(UefiVariableIndexTests, dumpLoadRoadtrip) - - TEST(UefiVariableIndexTests, dumpLoadConstrainedVariable) - { -- uint8_t buffer[sizeof(uint32_t) + -- MAX_VARIABLES * (sizeof(struct variable_metadata) + sizeof(bool))]; -+ uint8_t buffer[MAX_VARIABLES * sizeof(struct variable_metadata)]; - - create_variables(); - -@@ -314,13 +304,8 @@ TEST(UefiVariableIndexTests, dumpLoadConstrainedVariable) - UNSIGNED_LONGS_EQUAL(EFI_SUCCESS, status); - CHECK_TRUE(is_dirty); - -- /* -- * Variable index counter is at the beginning, which is followed by metadata and -- * constraint status byte of both NV variables, but only one of them has -- * constraints -- */ -- UNSIGNED_LONGS_EQUAL(sizeof(uint32_t) + -- (sizeof(struct variable_metadata) + sizeof(bool)) * 2 + -+ /* metadata and constraint status byte are stored for both NV variables, but only one of them has constraints */ -+ UNSIGNED_LONGS_EQUAL((sizeof(struct variable_metadata) + sizeof(bool)) * 2 + - sizeof(struct variable_constraints), - dump_len); - -@@ -331,11 +316,7 @@ TEST(UefiVariableIndexTests, dumpLoadConstrainedVariable) - - TEST(UefiVariableIndexTests, dumpBufferTooSmall) - { -- /* -- * Enough to fit the variable index counter and the metadata and constraint -- * status of a single variable -- */ -- uint8_t buffer[sizeof(uint32_t) + sizeof(struct variable_metadata) + sizeof(bool)]; -+ uint8_t buffer[1 * sizeof(struct variable_metadata) + 1]; - - create_variables(); - -@@ -357,8 +338,7 @@ TEST(UefiVariableIndexTests, dumpBufferTooSmall) - - TEST(UefiVariableIndexTests, removeVariable) - { -- uint8_t buffer[sizeof(uint32_t) + -- MAX_VARIABLES * (sizeof(struct variable_metadata) + sizeof(bool))]; -+ uint8_t buffer[MAX_VARIABLES * sizeof(struct variable_metadata)]; - struct variable_info *info = NULL; - - create_variables(); -@@ -378,12 +358,7 @@ TEST(UefiVariableIndexTests, removeVariable) - - CHECK_TRUE(is_dirty); - UNSIGNED_LONGS_EQUAL(EFI_SUCCESS, status); -- /* -- * Dump to now contains the variable index counter and metadata, -- * constraint status data of a variable -- */ -- UNSIGNED_LONGS_EQUAL(sizeof(uint32_t) + sizeof(struct variable_metadata) + sizeof(bool), -- dump_len); -+ UNSIGNED_LONGS_EQUAL(sizeof(struct variable_metadata) + sizeof(bool), dump_len); - - /* Remove the volatile variable */ - info = variable_index_find(&m_variable_index, &guid_1, string_get_size_in_bytes(name_1), -@@ -398,8 +373,7 @@ TEST(UefiVariableIndexTests, removeVariable) - - CHECK_FALSE(is_dirty); - UNSIGNED_LONGS_EQUAL(EFI_SUCCESS, status); -- UNSIGNED_LONGS_EQUAL(sizeof(uint32_t) + sizeof(struct variable_metadata) + sizeof(bool), -- dump_len); -+ UNSIGNED_LONGS_EQUAL(sizeof(struct variable_metadata) + sizeof(bool), dump_len); - - /* Remove the remaining NV variable */ - info = variable_index_find(&m_variable_index, &guid_1, string_get_size_in_bytes(name_3), -@@ -407,14 +381,14 @@ TEST(UefiVariableIndexTests, removeVariable) - - variable_index_clear_variable(&m_variable_index, info); - -- /* Expect index to be dirty and dump to now contains only the variable index counter */ -+ /* Expect index to be dirty and dump to now be empty */ - dump_len = 0; - status = variable_index_dump(&m_variable_index, sizeof(buffer), buffer, &dump_len, - &is_dirty); - - CHECK_TRUE(is_dirty); - UNSIGNED_LONGS_EQUAL(EFI_SUCCESS, status); -- UNSIGNED_LONGS_EQUAL(sizeof(uint32_t), dump_len); -+ UNSIGNED_LONGS_EQUAL(0, dump_len); - - /* Enumerate and now expect an empty index */ - info = NULL; -diff --git a/components/service/uefi/smm_variable/backend/test/variable_store_tests.cpp b/components/service/uefi/smm_variable/backend/test/variable_store_tests.cpp -index 0f962f206..e0f21f77a 100644 ---- a/components/service/uefi/smm_variable/backend/test/variable_store_tests.cpp -+++ b/components/service/uefi/smm_variable/backend/test/variable_store_tests.cpp -@@ -5,7 +5,6 @@ - */ - - #include --#include - #include - #include - #include -@@ -270,17 +269,8 @@ TEST_GROUP(UefiVariableStoreTests) - static const size_t MAX_VARIABLES = 5; - static const size_t MAX_VARIABLE_SIZE = 3000; - static const size_t STORE_CAPACITY = MAX_VARIABLES * MAX_VARIABLE_SIZE; -- static const size_t VARIABLE_INDEX_MAX_SIZE = -- sizeof(uint32_t) + -- MAX_VARIABLES * (sizeof(struct variable_metadata) + -- sizeof(struct variable_constraints) + sizeof(bool)); - - static const uint32_t OWNER_ID = 100; -- -- /* Synchronize these with the variables with the store */ -- uint64_t DEFAULT_VARIABLE_INDEX_STORAGE_A_UID = 0x8000000000000001; -- uint64_t DEFAULT_VARIABLE_INDEX_STORAGE_B_UID = 0x8000000000000002; -- - /* - * Make sure the variable buffer in the test is way above the limit - * so the buffer problems will be handled by the component -@@ -873,159 +863,3 @@ TEST(UefiVariableStoreTests, fillIndex) - LONGS_EQUAL(0, input_data.compare(output_data)); - } - } -- --TEST(UefiVariableStoreTests, variableIndexCounterOverflow) --{ -- efi_status_t efi_status = EFI_SUCCESS; -- psa_status_t psa_status = PSA_SUCCESS; -- std::u16string var_name = u"var"; -- std::string input_data = "a"; -- uint32_t attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | -- EFI_VARIABLE_RUNTIME_ACCESS; -- /* There are no variables set in the index, only the counter is there */ -- uint8_t buffer[sizeof(uint32_t)] = { 0 }; -- -- mock_store_reset(&m_persistent_store); -- -- /* Counter of index A is 0 */ -- psa_status = m_persistent_store.backend.interface->set( -- m_persistent_store.backend.context, OWNER_ID, DEFAULT_VARIABLE_INDEX_STORAGE_A_UID, -- sizeof(buffer), &buffer, PSA_STORAGE_FLAG_NONE); -- UNSIGNED_LONGLONGS_EQUAL(PSA_SUCCESS, psa_status); -- -- /* Set max counter value */ -- buffer[0] = 0xFF; -- buffer[1] = 0xFF; -- buffer[2] = 0xFF; -- buffer[3] = 0xFF; -- -- /* Counter of index B is max value */ -- psa_status = m_persistent_store.backend.interface->set( -- m_persistent_store.backend.context, OWNER_ID, DEFAULT_VARIABLE_INDEX_STORAGE_B_UID, -- sizeof(buffer), &buffer, PSA_STORAGE_FLAG_NONE); -- UNSIGNED_LONGLONGS_EQUAL(PSA_SUCCESS, psa_status); -- -- /* At next initialization of the store index A should be the latest index with counter value 0 */ -- uefi_variable_store_deinit(&m_uefi_variable_store); -- -- efi_status = uefi_variable_store_init(&m_uefi_variable_store, OWNER_ID, MAX_VARIABLES, -- m_persistent_backend, m_volatile_backend); -- UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, efi_status); -- -- UNSIGNED_LONGLONGS_EQUAL(m_uefi_variable_store.active_variable_index_uid, -- DEFAULT_VARIABLE_INDEX_STORAGE_A_UID); -- UNSIGNED_LONGLONGS_EQUAL(m_uefi_variable_store.variable_index.counter, 0); -- -- /* After setting a variable to trigger sync and rebooting index B should be the latest index with counter value 1*/ -- efi_status = set_variable(var_name, input_data, attributes); -- UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, efi_status); -- -- power_cycle(); -- -- UNSIGNED_LONGLONGS_EQUAL(m_uefi_variable_store.active_variable_index_uid, -- DEFAULT_VARIABLE_INDEX_STORAGE_B_UID); -- UNSIGNED_LONGLONGS_EQUAL(m_uefi_variable_store.variable_index.counter, 1); --} -- --TEST(UefiVariableStoreTests, oneEmptyVariableIndexExists) --{ -- psa_status_t status = PSA_SUCCESS; -- -- /* Only, variable index A exists, but it is empty */ -- mock_store_reset(&m_persistent_store); -- -- status = m_persistent_store.backend.interface->create(m_persistent_store.backend.context, -- OWNER_ID, -- DEFAULT_VARIABLE_INDEX_STORAGE_A_UID, -- 100, PSA_STORAGE_FLAG_NONE); -- UNSIGNED_LONGLONGS_EQUAL(PSA_SUCCESS, status); -- -- power_cycle(); -- -- /* Empty index is considered non-existing so default index (A) is selected */ -- UNSIGNED_LONGLONGS_EQUAL(m_uefi_variable_store.active_variable_index_uid, -- DEFAULT_VARIABLE_INDEX_STORAGE_A_UID); -- UNSIGNED_LONGLONGS_EQUAL(m_uefi_variable_store.variable_index.counter, 0); -- -- /* Only, variable index B exists, but it is empty*/ -- mock_store_reset(&m_persistent_store); -- -- status = m_persistent_store.backend.interface->create(m_persistent_store.backend.context, -- OWNER_ID, -- DEFAULT_VARIABLE_INDEX_STORAGE_B_UID, -- 100, PSA_STORAGE_FLAG_NONE); -- UNSIGNED_LONGLONGS_EQUAL(PSA_SUCCESS, status); -- -- power_cycle(); -- -- /* Empty index is considered non-existing so default index (A) is selected */ -- UNSIGNED_LONGLONGS_EQUAL(m_uefi_variable_store.active_variable_index_uid, -- DEFAULT_VARIABLE_INDEX_STORAGE_A_UID); -- UNSIGNED_LONGLONGS_EQUAL(m_uefi_variable_store.variable_index.counter, 0); --} -- --TEST(UefiVariableStoreTests, oneVariableIndexAlreadySet) --{ -- efi_status_t status = EFI_SUCCESS; -- /* Empty variable index with zero counter value */ -- uint8_t buffer[VARIABLE_INDEX_MAX_SIZE] = { 0 }; -- -- /* Set index A in the store with some data, so it will be found as the currently active index */ -- mock_store_reset(&m_persistent_store); -- -- status = m_persistent_store.backend.interface->set( -- m_persistent_store.backend.context, OWNER_ID, DEFAULT_VARIABLE_INDEX_STORAGE_A_UID, -- sizeof(buffer), &buffer, PSA_STORAGE_FLAG_NONE); -- UNSIGNED_LONGLONGS_EQUAL(PSA_SUCCESS, status); -- -- power_cycle(); -- -- UNSIGNED_LONGLONGS_EQUAL(m_uefi_variable_store.active_variable_index_uid, -- DEFAULT_VARIABLE_INDEX_STORAGE_A_UID); -- UNSIGNED_LONGLONGS_EQUAL(m_uefi_variable_store.variable_index.counter, 0); -- -- /* Set index B in the store with some data, so it will be found as the currently active index */ -- mock_store_reset(&m_persistent_store); -- -- status = m_persistent_store.backend.interface->set( -- m_persistent_store.backend.context, OWNER_ID, DEFAULT_VARIABLE_INDEX_STORAGE_B_UID, -- sizeof(buffer), &buffer, PSA_STORAGE_FLAG_NONE); -- UNSIGNED_LONGLONGS_EQUAL(PSA_SUCCESS, status); -- -- power_cycle(); -- -- UNSIGNED_LONGLONGS_EQUAL(m_uefi_variable_store.active_variable_index_uid, -- DEFAULT_VARIABLE_INDEX_STORAGE_B_UID); -- UNSIGNED_LONGLONGS_EQUAL(m_uefi_variable_store.variable_index.counter, 0); --} -- --TEST(UefiVariableStoreTests, variableIndexesWithSameData) --{ -- psa_status_t psa_status = PSA_SUCCESS; -- efi_status_t efi_status = EFI_SUCCESS; -- /* Empty variable index with zero counter value */ -- uint8_t buffer[VARIABLE_INDEX_MAX_SIZE] = { 0 }; -- -- /* Set both indexes to the same data and counter value */ -- mock_store_reset(&m_persistent_store); -- -- psa_status = m_persistent_store.backend.interface->set( -- m_persistent_store.backend.context, OWNER_ID, DEFAULT_VARIABLE_INDEX_STORAGE_A_UID, -- sizeof(buffer), &buffer, PSA_STORAGE_FLAG_NONE); -- UNSIGNED_LONGLONGS_EQUAL(PSA_SUCCESS, psa_status); -- -- psa_status = m_persistent_store.backend.interface->set( -- m_persistent_store.backend.context, OWNER_ID, DEFAULT_VARIABLE_INDEX_STORAGE_B_UID, -- sizeof(buffer), &buffer, PSA_STORAGE_FLAG_NONE); -- UNSIGNED_LONGLONGS_EQUAL(PSA_SUCCESS, psa_status); -- -- /* -- * Initializing the store should fail, because if there are two indexes with the same counter it cannot be decided -- * which has the valid data. -- */ -- uefi_variable_store_deinit(&m_uefi_variable_store); -- -- efi_status = uefi_variable_store_init(&m_uefi_variable_store, OWNER_ID, MAX_VARIABLES, -- m_persistent_backend, m_volatile_backend); -- UNSIGNED_LONGLONGS_EQUAL(EFI_LOAD_ERROR, efi_status); --} -diff --git a/components/service/uefi/smm_variable/backend/uefi_variable_store.c b/components/service/uefi/smm_variable/backend/uefi_variable_store.c -index 48b81ff37..459ca4566 100644 ---- a/components/service/uefi/smm_variable/backend/uefi_variable_store.c -+++ b/components/service/uefi/smm_variable/backend/uefi_variable_store.c -@@ -28,12 +28,9 @@ - #include "service/crypto/client/psa/crypto_client.h" - #endif - --static psa_status_t get_active_variable_uid(struct uefi_variable_store *context, -- uint64_t *active_index_uid, uint32_t *counter); -- - static efi_status_t load_variable_index(struct uefi_variable_store *context); - --static efi_status_t sync_variable_index(struct uefi_variable_store *context); -+static efi_status_t sync_variable_index(const struct uefi_variable_store *context); - - static efi_status_t check_capabilities(const SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *var); - -@@ -138,14 +135,6 @@ static bool compare_name_to_key_store_name(const int16_t *name1, size_t size1, - const uint16_t *name2, size_t size2); - #endif - --/* Private UID for storing the variable index */ --#define SMM_VARIABLE_INDEX_STORAGE_A_UID UINT64_C(0x8000000000000001) --#define SMM_VARIABLE_INDEX_STORAGE_B_UID UINT64_C(0x8000000000000002) -- --_Static_assert(SMM_VARIABLE_INDEX_STORAGE_A_UID != SMM_VARIABLE_INDEX_STORAGE_B_UID, -- "SMM_VARIABLE_INDEX_STORAGE_A_UID must not be the same value as " -- "SMM_VARIABLE_INDEX_STORAGE_B_UID"); -- - /* Default maximum variable size - - * may be overridden using uefi_variable_store_set_storage_limits() - */ -@@ -398,7 +387,7 @@ efi_status_t uefi_variable_store_set_variable(const struct uefi_variable_store * - * index entry. - */ - if (should_sync_index) -- status = sync_variable_index((struct uefi_variable_store *)context); -+ status = sync_variable_index(context); - - /* Store any variable data to the storage backend with the updated metadata */ - if (info->is_variable_set && (status == EFI_SUCCESS)) { -@@ -620,148 +609,40 @@ efi_status_t uefi_variable_store_get_var_check_property( - return status; - } - --/* Checks which index contains the latest data, which shall be loaded */ --static psa_status_t get_active_variable_uid(struct uefi_variable_store *context, -- uint64_t *active_index_uid, uint32_t *counter) --{ -- uint32_t counter_A = 0; -- uint32_t counter_B = 0; -- size_t data_len = 0; -- psa_status_t psa_status_A = PSA_SUCCESS; -- psa_status_t psa_status_B = PSA_SUCCESS; -- struct storage_backend *persistent_store = context->persistent_store.storage_backend; -- -- /* Set default value for the case when the index does not exist yet */ -- *active_index_uid = SMM_VARIABLE_INDEX_STORAGE_A_UID; -- *counter = 0; -- -- if (persistent_store) { -- psa_status_A = persistent_store->interface->get(persistent_store->context, -- context->owner_id, -- SMM_VARIABLE_INDEX_STORAGE_A_UID, 0, -- sizeof(counter_A), &counter_A, -- &data_len); -- -- if (psa_status_A == PSA_SUCCESS && data_len == 0) { -- psa_status_A = persistent_store->interface->remove( -- persistent_store->context, context->owner_id, -- SMM_VARIABLE_INDEX_STORAGE_A_UID); -- -- if (psa_status_A == PSA_SUCCESS) -- psa_status_A = PSA_ERROR_DOES_NOT_EXIST; -- else { -- EMSG("Erronous state of variable index"); -- return PSA_ERROR_STORAGE_FAILURE; -- } -- } -- -- psa_status_B = persistent_store->interface->get(persistent_store->context, -- context->owner_id, -- SMM_VARIABLE_INDEX_STORAGE_B_UID, 0, -- sizeof(counter_B), &counter_B, -- &data_len); -- -- if (psa_status_B == PSA_SUCCESS && data_len == 0) { -- psa_status_B = persistent_store->interface->remove( -- persistent_store->context, context->owner_id, -- SMM_VARIABLE_INDEX_STORAGE_B_UID); -- -- if (psa_status_B == PSA_SUCCESS) -- psa_status_B = PSA_ERROR_DOES_NOT_EXIST; -- else { -- EMSG("Erronous state of variable index"); -- return PSA_ERROR_STORAGE_FAILURE; -- } -- } -- -- if ((psa_status_A != PSA_SUCCESS && psa_status_A != PSA_ERROR_DOES_NOT_EXIST) || -- (psa_status_B != PSA_SUCCESS && psa_status_B != PSA_ERROR_DOES_NOT_EXIST)) -- return PSA_ERROR_STORAGE_FAILURE; -- -- if (psa_status_A == PSA_ERROR_DOES_NOT_EXIST) { -- if (psa_status_B == PSA_ERROR_DOES_NOT_EXIST) -- return PSA_ERROR_DOES_NOT_EXIST; -- -- *active_index_uid = SMM_VARIABLE_INDEX_STORAGE_B_UID; -- *counter = counter_B; -- -- return PSA_SUCCESS; -- } else if (psa_status_B == PSA_ERROR_DOES_NOT_EXIST) { -- *active_index_uid = SMM_VARIABLE_INDEX_STORAGE_A_UID; -- *counter = counter_A; -- -- return PSA_SUCCESS; -- } -- -- if (counter_A + 1 == counter_B) { -- *active_index_uid = SMM_VARIABLE_INDEX_STORAGE_B_UID; -- *counter = counter_B; -- return PSA_SUCCESS; -- } else if (counter_B + 1 == counter_A) { -- *active_index_uid = SMM_VARIABLE_INDEX_STORAGE_A_UID; -- *counter = counter_A; -- return PSA_SUCCESS; -- } else { -- EMSG("UEFI metadata variable index is invalid."); -- return PSA_ERROR_STORAGE_FAILURE; -- } -- } else { -- EMSG("Store backend is not accessible"); -- return PSA_ERROR_STORAGE_FAILURE; -- } -- -- return PSA_ERROR_STORAGE_FAILURE; --} -- - static efi_status_t load_variable_index(struct uefi_variable_store *context) - { - struct storage_backend *persistent_store = context->persistent_store.storage_backend; -- psa_status_t psa_status = PSA_SUCCESS; - - if (persistent_store) { - size_t data_len = 0; - size_t data_offset = 0; -- struct psa_storage_info_t variable_index_info = { 0 }; -- -- psa_status = get_active_variable_uid(context, &context->active_variable_index_uid, -- &context->variable_index.counter); -- switch (psa_status) { -- case PSA_SUCCESS: -- break; -- -- case PSA_ERROR_DOES_NOT_EXIST: -- IMSG("Variable index does not exist in NV store, continuing with empty index"); -- return EFI_SUCCESS; -- -- default: -- EMSG("Loading variable index failed: %d", psa_status); -- return EFI_LOAD_ERROR; -- } -- -- /* Make sure the variable index fits the buffer */ -- persistent_store->interface->get_info(persistent_store->context, context->owner_id, -- context->active_variable_index_uid, -- &variable_index_info); -- -- if (variable_index_info.size > context->index_sync_buffer_size) { -- EMSG("Variable index cannot fit the sync buffer"); -- return EFI_LOAD_ERROR; -- } - - do { -- psa_status = persistent_store->interface->get( -+ psa_status_t psa_status = persistent_store->interface->get( - persistent_store->context, context->owner_id, -- context->active_variable_index_uid, data_offset, -+ SMM_VARIABLE_INDEX_STORAGE_UID, data_offset, - RPC_CALLER_SESSION_SHARED_MEMORY_SIZE, - context->index_sync_buffer + data_offset, &data_len); - -- if (psa_status != PSA_SUCCESS) { -+ switch (psa_status) { -+ case PSA_SUCCESS: -+ data_offset += data_len; -+ -+ if (data_offset > context->index_sync_buffer_size) { -+ EMSG("Variable index cannot fit the sync buffer"); -+ return EFI_LOAD_ERROR; -+ } -+ -+ break; -+ -+ case PSA_ERROR_DOES_NOT_EXIST: -+ IMSG("Index variable does not exist in NV store, continuing with empty index"); -+ return EFI_SUCCESS; -+ -+ default: - EMSG("Loading variable index failed: %d", psa_status); - return EFI_LOAD_ERROR; - } -- -- data_offset += data_len; -- - } while (data_len == RPC_CALLER_SESSION_SHARED_MEMORY_SIZE); - - variable_index_restore(&context->variable_index, data_offset, -@@ -774,7 +655,7 @@ static efi_status_t load_variable_index(struct uefi_variable_store *context) - return EFI_SUCCESS; - } - --static efi_status_t sync_variable_index(struct uefi_variable_store *context) -+static efi_status_t sync_variable_index(const struct uefi_variable_store *context) - { - efi_status_t status = EFI_SUCCESS; - psa_status_t psa_status = PSA_SUCCESS; -@@ -794,24 +675,19 @@ static efi_status_t sync_variable_index(struct uefi_variable_store *context) - - if (persistent_store) { - size_t data_offset = 0; -- uint64_t next_index_uid = 0; -- -- /* Write the older one */ -- next_index_uid = (context->active_variable_index_uid == -- SMM_VARIABLE_INDEX_STORAGE_A_UID ? -- SMM_VARIABLE_INDEX_STORAGE_B_UID : -- SMM_VARIABLE_INDEX_STORAGE_A_UID); - - psa_status = persistent_store->interface->remove( -- persistent_store->context, context->owner_id, next_index_uid); -+ persistent_store->context, context->owner_id, -+ SMM_VARIABLE_INDEX_STORAGE_UID); - - if (psa_status != PSA_SUCCESS && psa_status != PSA_ERROR_DOES_NOT_EXIST) - goto end; - - /* Check if the index exists and create if not yet */ - psa_status = persistent_store->interface->create( -- persistent_store->context, context->owner_id, next_index_uid, -- remaining_data_len, PSA_STORAGE_FLAG_NONE); -+ persistent_store->context, context->owner_id, -+ SMM_VARIABLE_INDEX_STORAGE_UID, remaining_data_len, -+ PSA_STORAGE_FLAG_NONE); - - if (psa_status != PSA_SUCCESS) - goto end; -@@ -822,7 +698,8 @@ static efi_status_t sync_variable_index(struct uefi_variable_store *context) - - psa_status = persistent_store->interface->set_extended( - persistent_store->context, context->owner_id, -- next_index_uid, data_offset, data_of_this_iteration, -+ SMM_VARIABLE_INDEX_STORAGE_UID, data_offset, -+ data_of_this_iteration, - context->index_sync_buffer + data_offset); - - if (psa_status != PSA_SUCCESS) -@@ -1827,7 +1704,7 @@ static void purge_orphan_index_entries(const struct uefi_variable_store *context - } - - if (any_orphans) -- sync_variable_index((struct uefi_variable_store *)context); -+ sync_variable_index(context); - } - - static struct delegate_variable_store * -diff --git a/components/service/uefi/smm_variable/backend/uefi_variable_store.h b/components/service/uefi/smm_variable/backend/uefi_variable_store.h -index 9f2c4a00c..2493ff6b4 100644 ---- a/components/service/uefi/smm_variable/backend/uefi_variable_store.h -+++ b/components/service/uefi/smm_variable/backend/uefi_variable_store.h -@@ -52,7 +52,6 @@ struct uefi_variable_store { - uint32_t owner_id; - uint8_t *index_sync_buffer; - size_t index_sync_buffer_size; -- uint64_t active_variable_index_uid; - struct variable_index variable_index; - struct delegate_variable_store persistent_store; - struct delegate_variable_store volatile_store; -diff --git a/components/service/uefi/smm_variable/backend/variable_index.c b/components/service/uefi/smm_variable/backend/variable_index.c -index 90230426f..5fb6d08c5 100644 ---- a/components/service/uefi/smm_variable/backend/variable_index.c -+++ b/components/service/uefi/smm_variable/backend/variable_index.c -@@ -91,7 +91,6 @@ static struct variable_entry *containing_entry(const struct variable_info *info) - efi_status_t variable_index_init(struct variable_index *context, size_t max_variables) - { - context->max_variables = max_variables; -- context->counter = 0; - context->entries = - (struct variable_entry *)malloc(sizeof(struct variable_entry) * max_variables); - -@@ -109,9 +108,9 @@ void variable_index_deinit(struct variable_index *context) - - size_t variable_index_max_dump_size(struct variable_index *context) - { -- return sizeof(context->counter) + (sizeof(struct variable_metadata) + sizeof(bool) + -- sizeof(struct variable_constraints)) * -- context->max_variables; -+ return (sizeof(struct variable_metadata) + sizeof(bool) + -+ sizeof(struct variable_constraints)) * -+ context->max_variables; - } - - struct variable_info *variable_index_find(const struct variable_index *context, -@@ -288,16 +287,6 @@ efi_status_t variable_index_dump(const struct variable_index *context, size_t bu - *data_len = 0; - *any_dirty = false; - -- /* -- * Intentionally letting the counter overflow. -- * The buffer (index_sync_buffer) is provided by malloc, which allocates memory to a boundary -- * suitable for any default data type of the system (e.g uint32_t) -- */ -- *((uint32_t *)dump_pos) = context->counter + 1; -- bytes_dumped += sizeof(context->counter); -- dump_pos += sizeof(context->counter); -- -- /* Store variables */ - for (size_t pos = 0; pos < context->max_variables; pos++) { - struct variable_entry *entry = &context->entries[pos]; - struct variable_metadata *metadata = &entry->info.metadata; -@@ -344,24 +333,14 @@ efi_status_t variable_index_dump(const struct variable_index *context, size_t bu - return EFI_SUCCESS; - } - --void variable_index_confirm_write(struct variable_index *context) --{ -- context->counter++; --} - --size_t variable_index_restore(struct variable_index *context, size_t data_len, -+size_t variable_index_restore(const struct variable_index *context, size_t data_len, - const uint8_t *buffer) - { - size_t bytes_loaded = 0; - const uint8_t *load_pos = buffer; - int pos = 0; - -- if (data_len >= sizeof(context->counter)) { -- context->counter = *((uint32_t *)load_pos); -- bytes_loaded += sizeof(context->counter); -- load_pos += sizeof(context->counter); -- } -- - while (bytes_loaded < data_len) { - struct variable_entry *entry = &context->entries[pos]; - -diff --git a/components/service/uefi/smm_variable/backend/variable_index.h b/components/service/uefi/smm_variable/backend/variable_index.h -index 592dddc83..0151d636a 100644 ---- a/components/service/uefi/smm_variable/backend/variable_index.h -+++ b/components/service/uefi/smm_variable/backend/variable_index.h -@@ -75,7 +75,6 @@ struct variable_entry { - */ - struct variable_index { - size_t max_variables; -- uint32_t counter; - struct variable_entry *entries; - }; - -@@ -229,7 +228,7 @@ void variable_index_confirm_write(struct variable_index *context); - * - * @return Number of bytes loaded - */ --size_t variable_index_restore(struct variable_index *context, size_t data_len, -+size_t variable_index_restore(const struct variable_index *context, size_t data_len, - const uint8_t *buffer); - - #ifdef __cplusplus --- -2.25.1 - diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0021-Fix-PSA-FWU-IPC-psa_fwu_install-return-value-check.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0013-Fix-PSA-FWU-IPC-psa_fwu_install-return-value-check.patch similarity index 100% rename from meta-arm-bsp/recipes-security/trusted-services/corstone1000/0021-Fix-PSA-FWU-IPC-psa_fwu_install-return-value-check.patch rename to meta-arm-bsp/recipes-security/trusted-services/corstone1000/0013-Fix-PSA-FWU-IPC-psa_fwu_install-return-value-check.patch diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0014-Revert-Make-constraints-of-NV-UEFI-variables-persist.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0014-Revert-Make-constraints-of-NV-UEFI-variables-persist.patch deleted file mode 100644 index 3f0ae436..00000000 --- a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0014-Revert-Make-constraints-of-NV-UEFI-variables-persist.patch +++ /dev/null @@ -1,387 +0,0 @@ -From c0ffa57e7628f23747d7ee947358f8a538fa5d4c Mon Sep 17 00:00:00 2001 -From: Bence Balogh -Date: Mon, 25 Nov 2024 22:17:51 +0100 -Subject: [PATCH 3/3] Revert "Make constraints of NV UEFI variables persistent" - -This reverts commit 64bbde5d9950413cf724ffb792d4d1637892fa8b. -The FMP support didn't work with this commit. See the implementation in the -0003-FMP-Support-in-Corstone1000.patch file. The -0003-FMP-Support-in-Corstone1000.patch will be redesigned but until that, this -commit has to be reverted. - -Upstream-Status: Inappropriate [To be removed after new FWU design] -Signed-off-by: Bence Balogh ---- - .../backend/test/variable_index_tests.cpp | 93 +++---------------- - .../backend/uefi_variable_store.c | 12 +-- - .../smm_variable/backend/variable_index.c | 90 +++--------------- - .../smm_variable/backend/variable_index.h | 7 +- - 4 files changed, 36 insertions(+), 166 deletions(-) - -diff --git a/components/service/uefi/smm_variable/backend/test/variable_index_tests.cpp b/components/service/uefi/smm_variable/backend/test/variable_index_tests.cpp -index a52cfbf76..1b7a6b879 100644 ---- a/components/service/uefi/smm_variable/backend/test/variable_index_tests.cpp -+++ b/components/service/uefi/smm_variable/backend/test/variable_index_tests.cpp -@@ -214,28 +214,21 @@ TEST(UefiVariableIndexTests, dumpLoadRoadtrip) - - /* Expect the info for two NV variables to have been dumped */ - size_t dump_len = 0; -- bool is_dirty = false; -- efi_status_t status = EFI_SUCCESS; -- -- status = variable_index_dump(&m_variable_index, sizeof(buffer), buffer, &dump_len, -- &is_dirty); -+ bool is_dirty = variable_index_dump(&m_variable_index, sizeof(buffer), buffer, &dump_len); - - CHECK_TRUE(is_dirty); -- UNSIGNED_LONGS_EQUAL(EFI_SUCCESS, status); -- UNSIGNED_LONGS_EQUAL(((sizeof(struct variable_metadata) + sizeof(bool)) * 2), dump_len); -+ UNSIGNED_LONGS_EQUAL((sizeof(struct variable_metadata) * 2), dump_len); - - /* Expect no records to be dirty when the dump is repeated */ - dump_len = 0; -- status = variable_index_dump(&m_variable_index, sizeof(buffer), buffer, &dump_len, -- &is_dirty); -+ is_dirty = variable_index_dump(&m_variable_index, sizeof(buffer), buffer, &dump_len); - -- UNSIGNED_LONGS_EQUAL(EFI_SUCCESS, status); - CHECK_FALSE(is_dirty); -- UNSIGNED_LONGS_EQUAL(((sizeof(struct variable_metadata) + sizeof(bool)) * 2), dump_len); -+ UNSIGNED_LONGS_EQUAL((sizeof(struct variable_metadata) * 2), dump_len); - - /* Tear down and reinitialize to simulate a reboot */ - variable_index_deinit(&m_variable_index); -- status = variable_index_init(&m_variable_index, MAX_VARIABLES); -+ efi_status_t status = variable_index_init(&m_variable_index, MAX_VARIABLES); - UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, status); - - /* Load the dumped contents */ -@@ -268,52 +261,6 @@ TEST(UefiVariableIndexTests, dumpLoadRoadtrip) - UNSIGNED_LONGLONGS_EQUAL(EFI_NOT_FOUND, status); - } - --TEST(UefiVariableIndexTests, dumpLoadConstrainedVariable) --{ -- uint8_t buffer[MAX_VARIABLES * sizeof(struct variable_metadata)]; -- -- create_variables(); -- -- struct variable_constraints constraints; -- constraints.revision = 10; -- constraints.property = VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY; -- constraints.attributes = 0; -- constraints.min_size = 1; -- constraints.max_size = 100; -- -- /* Set check constraints on one of the variables */ -- struct variable_info *info = variable_index_find(&m_variable_index, &guid_2, -- string_get_size_in_bytes(name_2), -- (const int16_t *)name_2.data()); -- -- CHECK_TRUE(info); -- CHECK_TRUE(info->is_variable_set); -- CHECK_FALSE(info->is_constraints_set); -- -- variable_index_set_constraints(info, &constraints); -- -- CHECK_TRUE(info->is_constraints_set); -- CHECK_TRUE(info->is_variable_set); -- -- size_t dump_len = 0; -- bool is_dirty = false; -- efi_status_t status = EFI_SUCCESS; -- status = variable_index_dump(&m_variable_index, sizeof(buffer), buffer, &dump_len, -- &is_dirty); -- -- UNSIGNED_LONGS_EQUAL(EFI_SUCCESS, status); -- CHECK_TRUE(is_dirty); -- -- /* metadata and constraint status byte are stored for both NV variables, but only one of them has constraints */ -- UNSIGNED_LONGS_EQUAL((sizeof(struct variable_metadata) + sizeof(bool)) * 2 + -- sizeof(struct variable_constraints), -- dump_len); -- -- /* Load the dumped contents */ -- size_t load_len = variable_index_restore(&m_variable_index, dump_len, buffer); -- UNSIGNED_LONGS_EQUAL(dump_len, load_len); --} -- - TEST(UefiVariableIndexTests, dumpBufferTooSmall) - { - uint8_t buffer[1 * sizeof(struct variable_metadata) + 1]; -@@ -325,15 +272,10 @@ TEST(UefiVariableIndexTests, dumpBufferTooSmall) - * exceed the length of the buffer. - */ - size_t dump_len = 0; -- bool is_dirty = false; -- efi_status_t status = EFI_SUCCESS; -- -- status = variable_index_dump(&m_variable_index, sizeof(buffer), buffer, &dump_len, -- &is_dirty); -+ bool is_dirty = variable_index_dump(&m_variable_index, sizeof(buffer), buffer, &dump_len); - - CHECK_TRUE(is_dirty); -- UNSIGNED_LONGS_EQUAL(EFI_BUFFER_TOO_SMALL, status); -- UNSIGNED_LONGS_EQUAL(0, dump_len); -+ UNSIGNED_LONGS_EQUAL(sizeof(struct variable_metadata) * 1, dump_len); - } - - TEST(UefiVariableIndexTests, removeVariable) -@@ -351,14 +293,10 @@ TEST(UefiVariableIndexTests, removeVariable) - - /* Expect index to be dirty and for only one NV variable to be left */ - size_t dump_len = 0; -- bool is_dirty = false; -- efi_status_t status = EFI_SUCCESS; -- status = variable_index_dump(&m_variable_index, sizeof(buffer), buffer, &dump_len, -- &is_dirty); -+ bool is_dirty = variable_index_dump(&m_variable_index, sizeof(buffer), buffer, &dump_len); - - CHECK_TRUE(is_dirty); -- UNSIGNED_LONGS_EQUAL(EFI_SUCCESS, status); -- UNSIGNED_LONGS_EQUAL(sizeof(struct variable_metadata) + sizeof(bool), dump_len); -+ UNSIGNED_LONGS_EQUAL((sizeof(struct variable_metadata) * 1), dump_len); - - /* Remove the volatile variable */ - info = variable_index_find(&m_variable_index, &guid_1, string_get_size_in_bytes(name_1), -@@ -368,12 +306,10 @@ TEST(UefiVariableIndexTests, removeVariable) - - /* Expect index not to be dirty because there was no change to any NV variable */ - dump_len = 0; -- status = variable_index_dump(&m_variable_index, sizeof(buffer), buffer, &dump_len, -- &is_dirty); -+ is_dirty = variable_index_dump(&m_variable_index, sizeof(buffer), buffer, &dump_len); - - CHECK_FALSE(is_dirty); -- UNSIGNED_LONGS_EQUAL(EFI_SUCCESS, status); -- UNSIGNED_LONGS_EQUAL(sizeof(struct variable_metadata) + sizeof(bool), dump_len); -+ UNSIGNED_LONGS_EQUAL((sizeof(struct variable_metadata) * 1), dump_len); - - /* Remove the remaining NV variable */ - info = variable_index_find(&m_variable_index, &guid_1, string_get_size_in_bytes(name_3), -@@ -383,15 +319,14 @@ TEST(UefiVariableIndexTests, removeVariable) - - /* Expect index to be dirty and dump to now be empty */ - dump_len = 0; -- status = variable_index_dump(&m_variable_index, sizeof(buffer), buffer, &dump_len, -- &is_dirty); -+ is_dirty = variable_index_dump(&m_variable_index, sizeof(buffer), buffer, &dump_len); - - CHECK_TRUE(is_dirty); -- UNSIGNED_LONGS_EQUAL(EFI_SUCCESS, status); -- UNSIGNED_LONGS_EQUAL(0, dump_len); -+ UNSIGNED_LONGS_EQUAL((sizeof(struct variable_metadata) * 0), dump_len); - - /* Enumerate and now expect an empty index */ - info = NULL; -+ efi_status_t status = EFI_SUCCESS; - - info = variable_index_find_next(&m_variable_index, &guid_1, - string_get_size_in_bytes(null_name), (const int16_t *) null_name.data(), -diff --git a/components/service/uefi/smm_variable/backend/uefi_variable_store.c b/components/service/uefi/smm_variable/backend/uefi_variable_store.c -index e5fc32864..7da2d1e71 100644 ---- a/components/service/uefi/smm_variable/backend/uefi_variable_store.c -+++ b/components/service/uefi/smm_variable/backend/uefi_variable_store.c -@@ -575,10 +575,8 @@ efi_status_t uefi_variable_store_set_var_check_property( - status = variable_checker_set_constraints(&constraints, info->is_constraints_set, - &property->VariableProperty); - -- if (status == EFI_SUCCESS) { -+ if (status == EFI_SUCCESS) - variable_index_set_constraints(info, &constraints); -- status = sync_variable_index(context); -- } - - variable_index_remove_unused_entry(&context->variable_index, info); - -@@ -643,15 +641,13 @@ static efi_status_t load_variable_index(struct uefi_variable_store *context) - static efi_status_t sync_variable_index(const struct uefi_variable_store *context) - { - efi_status_t status = EFI_SUCCESS; -- bool is_dirty = false; - - /* Sync the variable index to storage if anything is dirty */ - size_t data_len = 0; - -- status = variable_index_dump(&context->variable_index, context->index_sync_buffer_size, -- context->index_sync_buffer, &data_len, &is_dirty); -- if (status != EFI_SUCCESS) -- return status; -+ bool is_dirty = variable_index_dump(&context->variable_index, -+ context->index_sync_buffer_size, -+ context->index_sync_buffer, &data_len); - - if (is_dirty) { - struct storage_backend *persistent_store = -diff --git a/components/service/uefi/smm_variable/backend/variable_index.c b/components/service/uefi/smm_variable/backend/variable_index.c -index 5fb6d08c5..c39f7394b 100644 ---- a/components/service/uefi/smm_variable/backend/variable_index.c -+++ b/components/service/uefi/smm_variable/backend/variable_index.c -@@ -108,9 +108,7 @@ void variable_index_deinit(struct variable_index *context) - - size_t variable_index_max_dump_size(struct variable_index *context) - { -- return (sizeof(struct variable_metadata) + sizeof(bool) + -- sizeof(struct variable_constraints)) * -- context->max_variables; -+ return sizeof(struct variable_metadata) * context->max_variables; - } - - struct variable_info *variable_index_find(const struct variable_index *context, -@@ -269,68 +267,37 @@ void variable_index_set_constraints(struct variable_info *info, - const struct variable_constraints *constraints) - { - if (info) { -- struct variable_entry *entry = containing_entry(info); -- - info->check_constraints = *constraints; - info->is_constraints_set = true; -- -- mark_dirty(entry); - } - } - --efi_status_t variable_index_dump(const struct variable_index *context, size_t buffer_size, -- uint8_t *buffer, size_t *data_len, bool *any_dirty) -+bool variable_index_dump(const struct variable_index *context, size_t buffer_size, uint8_t *buffer, -+ size_t *data_len) - { -+ bool any_dirty = false; - uint8_t *dump_pos = buffer; - size_t bytes_dumped = 0; - -- *data_len = 0; -- *any_dirty = false; -- - for (size_t pos = 0; pos < context->max_variables; pos++) { - struct variable_entry *entry = &context->entries[pos]; - struct variable_metadata *metadata = &entry->info.metadata; -- struct variable_constraints *constraints = &entry->info.check_constraints; - - if (entry->in_use && entry->info.is_variable_set && -- (metadata->attributes & EFI_VARIABLE_NON_VOLATILE)) { -- /* Store metadata */ -- if (bytes_dumped + sizeof(struct variable_metadata) > buffer_size) -- return EFI_BUFFER_TOO_SMALL; -- -+ (metadata->attributes & EFI_VARIABLE_NON_VOLATILE) && -+ ((bytes_dumped + sizeof(struct variable_metadata)) <= buffer_size)) { - memcpy(dump_pos, metadata, sizeof(struct variable_metadata)); - bytes_dumped += sizeof(struct variable_metadata); - dump_pos += sizeof(struct variable_metadata); -- -- /* Store constraints' status */ -- if (bytes_dumped + sizeof(entry->info.is_constraints_set) > buffer_size) -- return EFI_BUFFER_TOO_SMALL; -- -- memcpy(dump_pos, &entry->info.is_constraints_set, -- sizeof(entry->info.is_constraints_set)); -- bytes_dumped += sizeof(entry->info.is_constraints_set); -- dump_pos += sizeof(entry->info.is_constraints_set); -- -- /* Store constraints, if they are set */ -- if (entry->info.is_constraints_set) { -- if (bytes_dumped + sizeof(entry->info.check_constraints) > -- buffer_size) -- return EFI_BUFFER_TOO_SMALL; -- -- memcpy(dump_pos, constraints, -- sizeof(entry->info.check_constraints)); -- bytes_dumped += sizeof(entry->info.check_constraints); -- dump_pos += sizeof(entry->info.check_constraints); -- } - } - -- *any_dirty |= entry->dirty; -+ any_dirty |= entry->dirty; - entry->dirty = false; - } - - *data_len = bytes_dumped; - -- return EFI_SUCCESS; -+ return any_dirty; - } - - -@@ -342,50 +309,23 @@ size_t variable_index_restore(const struct variable_index *context, size_t data_ - int pos = 0; - - while (bytes_loaded < data_len) { -- struct variable_entry *entry = &context->entries[pos]; -- - if ((data_len - bytes_loaded) >= sizeof(struct variable_metadata)) { -+ struct variable_entry *entry = &context->entries[pos]; - struct variable_metadata *metadata = &entry->info.metadata; - -- /* Load metadata */ - memcpy(metadata, load_pos, sizeof(struct variable_metadata)); -+ -+ entry->info.is_variable_set = true; -+ entry->in_use = true; -+ - bytes_loaded += sizeof(struct variable_metadata); - load_pos += sizeof(struct variable_metadata); -- } else { -- /* Not a whole number of variable_metadata structs! */ -- break; -- } - -- if ((data_len - bytes_loaded) >= sizeof(entry->info.is_constraints_set)) { -- /* Load constraints' status */ -- memcpy(&entry->info.is_constraints_set, load_pos, -- sizeof(entry->info.is_constraints_set)); -- bytes_loaded += sizeof(entry->info.is_constraints_set); -- load_pos += sizeof(entry->info.is_constraints_set); -+ ++pos; - } else { -- /* Not enough space for constraints' status! */ -+ /* Not a whole number of variable_metadata structs! */ - break; - } -- -- if (entry->info.is_constraints_set) { -- if ((data_len - bytes_loaded) >= sizeof(struct variable_constraints)) { -- struct variable_constraints *constraints = -- &entry->info.check_constraints; -- -- /* Load constraints if they are set */ -- memcpy(constraints, load_pos, sizeof(struct variable_constraints)); -- bytes_loaded += sizeof(struct variable_constraints); -- load_pos += sizeof(struct variable_constraints); -- } else { -- /* Not a whole number of variable_constraints structs! */ -- break; -- } -- } -- -- entry->info.is_variable_set = true; -- entry->in_use = true; -- -- ++pos; - } - - return bytes_loaded; -diff --git a/components/service/uefi/smm_variable/backend/variable_index.h b/components/service/uefi/smm_variable/backend/variable_index.h -index 0151d636a..da6ed2476 100644 ---- a/components/service/uefi/smm_variable/backend/variable_index.h -+++ b/components/service/uefi/smm_variable/backend/variable_index.h -@@ -201,12 +201,11 @@ void variable_index_set_constraints(struct variable_info *info, - * @param[in] buffer_size Size of destination buffer - * @param[in] buffer Dump to this buffer - * @param[out] data_len Length of serialized data -- * @param[out] any_dirty True if there is unsaved data - * -- * @return EFI_SUCCESS if all the changes are dumped successfully -+ * @return True if there is unsaved data - */ --efi_status_t variable_index_dump(const struct variable_index *context, size_t buffer_size, -- uint8_t *buffer, size_t *data_len, bool *any_dirty); -+bool variable_index_dump(const struct variable_index *context, size_t buffer_size, uint8_t *buffer, -+ size_t *data_len); - - /** - * @brief Confirms the successful write of the variable index into the storage --- -2.25.1 - diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0022-fwu-Add-EFI-ESRT-v1-support.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0014-fwu-Add-EFI-ESRT-v1-support.patch similarity index 100% rename from meta-arm-bsp/recipes-security/trusted-services/corstone1000/0022-fwu-Add-EFI-ESRT-v1-support.patch rename to meta-arm-bsp/recipes-security/trusted-services/corstone1000/0014-fwu-Add-EFI-ESRT-v1-support.patch diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0023-platform-corstone1000-Enable-ESRT-support.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0015-platform-corstone1000-Enable-ESRT-support.patch similarity index 100% rename from meta-arm-bsp/recipes-security/trusted-services/corstone1000/0023-platform-corstone1000-Enable-ESRT-support.patch rename to meta-arm-bsp/recipes-security/trusted-services/corstone1000/0015-platform-corstone1000-Enable-ESRT-support.patch diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0015-se-proxy-protobuf-change.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0015-se-proxy-protobuf-change.patch deleted file mode 100644 index 11896556..00000000 --- a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0015-se-proxy-protobuf-change.patch +++ /dev/null @@ -1,64 +0,0 @@ -From dd9a51bde0608989e01de5369eaa0eef2bab7c43 Mon Sep 17 00:00:00 2001 -From: Emekcan Aras -Date: Wed, 22 Jan 2025 00:54:30 +0000 -Subject: [PATCH] protobuf fix - -Upstream-Status: Pending (not yet submitted to upstream) -Signed-off-by: Emekcan Aras ---- - .../se-proxy/env/commonsp/se_proxy_sp.c | 25 ++++++++++++++++++- - 1 file changed, 24 insertions(+), 1 deletion(-) - -diff --git a/deployments/se-proxy/env/commonsp/se_proxy_sp.c b/deployments/se-proxy/env/commonsp/se_proxy_sp.c -index 88e4cf17e..7da489ca8 100644 ---- a/deployments/se-proxy/env/commonsp/se_proxy_sp.c -+++ b/deployments/se-proxy/env/commonsp/se_proxy_sp.c -@@ -13,6 +13,7 @@ - #include "trace.h" - #include "deployments/se-proxy/infra/service_proxy_factory.h" - #include "deployments/se-proxy/se_proxy_interfaces.h" -+#include - - static bool sp_init(uint16_t *own_sp_id); - -@@ -39,7 +40,7 @@ void __noreturn sp_main(union ffa_boot_info *boot_info) - goto fatal_error; - } - -- rpc_status = ts_rpc_endpoint_sp_init(&rpc_endpoint, 6, 16); -+ rpc_status = ts_rpc_endpoint_sp_init(&rpc_endpoint, 7, 16); - if (rpc_status != RPC_SUCCESS) { - EMSG("Failed to initialize RPC endpoint: %d", rpc_status); - goto fatal_error; -@@ -118,6 +119,28 @@ void __noreturn sp_main(union ffa_boot_info *boot_info) - goto fatal_error; - } - -+ struct rpc_service_interface *crypto_iface_protobuf = NULL; -+ struct crypto_provider *crypto_protobuf_provider = NULL; -+ -+ crypto_protobuf_provider = crypto_protobuf_provider_factory_create(); -+ if (!crypto_protobuf_provider) { -+ EMSG("Failed to create crypto protobuf provider factory"); -+ goto fatal_error; -+ } -+ -+ crypto_iface_protobuf = service_provider_get_rpc_interface( -+ &crypto_protobuf_provider->base_provider); -+ if (!crypto_iface_protobuf) { -+ EMSG("Failed to create service provider RPC interface"); -+ goto fatal_error; -+ } -+ -+ rpc_status = ts_rpc_endpoint_sp_add_service(&rpc_endpoint, crypto_iface_protobuf); -+ if (rpc_status != RPC_SUCCESS) { -+ EMSG("Failed to add service to RPC endpoint: %d", rpc_status); -+ goto fatal_error; -+ } -+ - /* End of boot phase */ - result = sp_msg_wait(&req_msg); - if (result != SP_RESULT_OK) { --- -2.43.0 - diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0024-platform-corstone1000-Add-event-provider-proxy.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0016-platform-corstone1000-Add-event-provider-proxy.patch similarity index 82% rename from meta-arm-bsp/recipes-security/trusted-services/corstone1000/0024-platform-corstone1000-Add-event-provider-proxy.patch rename to meta-arm-bsp/recipes-security/trusted-services/corstone1000/0016-platform-corstone1000-Add-event-provider-proxy.patch index 8de9f081..e92b80ef 100644 --- a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0024-platform-corstone1000-Add-event-provider-proxy.patch +++ b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0016-platform-corstone1000-Add-event-provider-proxy.patch @@ -1,7 +1,7 @@ -From dde0ca3260ae3b7e7c3390ef03f9f484e9189626 Mon Sep 17 00:00:00 2001 +From 7953806fd3fdb743c40b76e363b917fac786c636 Mon Sep 17 00:00:00 2001 From: Harsimran Singh Tungal Date: Tue, 11 Mar 2025 13:33:36 +0000 -Subject: [PATCH 7/8] platform: corstone1000: Add event provider proxy +Subject: [PATCH 10/11] platform: corstone1000: Add event provider proxy Normal world needs to send boot confirmation event to Secure Enclave and Trusted-Services is responsible @@ -14,17 +14,38 @@ This change is introduced for Corstone-1000 Upstream-Status: Pending Signed-off-by: Harsimran Singh Tungal --- + components/service/common/include/psa/sid.h | 9 ++ .../se-proxy/env/commonsp/se_proxy_sp.c | 16 +++- .../corstone1000_event_handling.c | 91 +++++++++++++++++++ .../corstone1000_event_handling.h | 42 +++++++++ .../se-proxy/infra/corstone1000/infra.cmake | 1 + .../corstone1000/service_proxy_factory.c | 27 ++++++ - 5 files changed, 175 insertions(+), 2 deletions(-) + 6 files changed, 184 insertions(+), 2 deletions(-) create mode 100644 deployments/se-proxy/infra/corstone1000/corstone1000_event_handling.c create mode 100644 deployments/se-proxy/infra/corstone1000/corstone1000_event_handling.h +diff --git a/components/service/common/include/psa/sid.h b/components/service/common/include/psa/sid.h +index 0235764d..9f5ea05e 100644 +--- a/components/service/common/include/psa/sid.h ++++ b/components/service/common/include/psa/sid.h +@@ -40,6 +40,15 @@ extern "C" { + #define TFM_CRYPTO_VERSION (1U) + #define TFM_CRYPTO_HANDLE (0x40000100U) + ++/******** TFM_PLATFORM_SERVICE *******/ ++#define TFM_PLATFORM_API_ID_IOCTL (1013) ++#define TFM_PLATFORM_SERVICE_HANDLE (0x40000105U) ++ ++/** ++ * \brief Define a progressive numerical value for each SID which can be used ++ * when dispatching the requests to the service ++*/ ++ + /******** TFM_SP_PLATFORM ********/ + #define TFM_SP_PLATFORM_SYSTEM_RESET_SID (0x00000040U) + #define TFM_SP_PLATFORM_SYSTEM_RESET_VERSION (1U) diff --git a/deployments/se-proxy/env/commonsp/se_proxy_sp.c b/deployments/se-proxy/env/commonsp/se_proxy_sp.c -index 7da489ca..7d2ade5e 100644 +index 9f94092b..ce1410b2 100644 --- a/deployments/se-proxy/env/commonsp/se_proxy_sp.c +++ b/deployments/se-proxy/env/commonsp/se_proxy_sp.c @@ -1,6 +1,6 @@ @@ -35,16 +56,16 @@ index 7da489ca..7d2ade5e 100644 */ #include "components/rpc/common/endpoint/rpc_service_interface.h" -@@ -40,7 +40,7 @@ void __noreturn sp_main(union ffa_boot_info *boot_info) +@@ -42,7 +42,7 @@ void __noreturn sp_main(union ffa_boot_info *boot_info) goto fatal_error; } -- rpc_status = ts_rpc_endpoint_sp_init(&rpc_endpoint, 7, 16); -+ rpc_status = ts_rpc_endpoint_sp_init(&rpc_endpoint, 8, 16); +- rpc_status = ts_rpc_endpoint_sp_init(&rpc_endpoint, 6, 16); ++ rpc_status = ts_rpc_endpoint_sp_init(&rpc_endpoint, 7, 16); if (rpc_status != RPC_SUCCESS) { EMSG("Failed to initialize RPC endpoint: %d", rpc_status); goto fatal_error; -@@ -95,6 +95,18 @@ void __noreturn sp_main(union ffa_boot_info *boot_info) +@@ -97,6 +97,18 @@ void __noreturn sp_main(union ffa_boot_info *boot_info) goto fatal_error; } @@ -60,9 +81,9 @@ index 7da489ca..7d2ade5e 100644 + goto fatal_error; + } + - rpc_iface = capsule_update_proxy_create(); + rpc_iface = fwu_proxy_create(); if (!rpc_iface) { - EMSG("Failed to create Capsule Update proxy"); + EMSG("Failed to create FWU proxy"); diff --git a/deployments/se-proxy/infra/corstone1000/corstone1000_event_handling.c b/deployments/se-proxy/infra/corstone1000/corstone1000_event_handling.c new file mode 100644 index 00000000..faf450f2 @@ -209,20 +230,20 @@ index 00000000..e8e60dae + +#endif /* CORSTONE1000_EVENT_HANDLING_H */ diff --git a/deployments/se-proxy/infra/corstone1000/infra.cmake b/deployments/se-proxy/infra/corstone1000/infra.cmake -index 0b04149a..b95801de 100644 +index 2bf6b36e..1ec43700 100644 --- a/deployments/se-proxy/infra/corstone1000/infra.cmake +++ b/deployments/se-proxy/infra/corstone1000/infra.cmake -@@ -34,4 +34,5 @@ add_components(TARGET "se-proxy" +@@ -33,4 +33,5 @@ add_components(TARGET "se-proxy" target_sources(se-proxy PRIVATE ${CMAKE_CURRENT_LIST_DIR}/service_proxy_factory.c + ${CMAKE_CURRENT_LIST_DIR}/corstone1000_event_handling.c ) diff --git a/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c b/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c -index f0a4853e..ed42e2cb 100644 +index a754ace7..6d8c3855 100644 --- a/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c +++ b/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c -@@ -21,6 +21,7 @@ +@@ -20,6 +20,7 @@ #include #include #include "corstone1000_config.h" @@ -230,7 +251,7 @@ index f0a4853e..ed42e2cb 100644 /* backends */ #include -@@ -165,6 +166,32 @@ struct rpc_service_interface *its_proxy_create(void) +@@ -164,6 +165,32 @@ struct rpc_service_interface *its_proxy_create(void) return secure_storage_provider_init(&its_provider, backend, &its_uuid); } @@ -264,5 +285,5 @@ index f0a4853e..ed42e2cb 100644 { rpc_status_t rpc_status = RPC_ERROR_INTERNAL; -- -2.25.1 +2.34.1 diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0025-platform-corstone1000-Define-GUID-for-each-payloads.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0017-platform-corstone1000-Define-GUID-for-each-payloads.patch similarity index 100% rename from meta-arm-bsp/recipes-security/trusted-services/corstone1000/0025-platform-corstone1000-Define-GUID-for-each-payloads.patch rename to meta-arm-bsp/recipes-security/trusted-services/corstone1000/0017-platform-corstone1000-Define-GUID-for-each-payloads.patch diff --git a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0016-Add-the-com-buffer-address-and-page-count.patch b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0018-Add-the-com-buffer-address-and-page-count.patch similarity index 60% rename from meta-arm-bsp/recipes-security/trusted-services/corstone1000/0016-Add-the-com-buffer-address-and-page-count.patch rename to meta-arm-bsp/recipes-security/trusted-services/corstone1000/0018-Add-the-com-buffer-address-and-page-count.patch index 77efb6bc..ffca2adb 100644 --- a/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0016-Add-the-com-buffer-address-and-page-count.patch +++ b/meta-arm-bsp/recipes-security/trusted-services/corstone1000/0018-Add-the-com-buffer-address-and-page-count.patch @@ -1,38 +1,31 @@ -From 0423349ec142bd1c4a6cc452eed9a0f5e43c8539 Mon Sep 17 00:00:00 2001 -From: Michael Safwat -Date: Mon, 23 Jun 2025 13:06:10 +0000 +From 2eef8097c6411fb54b2d0203159e120d192315c7 Mon Sep 17 00:00:00 2001 +From: Harsimran Singh Tungal +Date: Thu, 24 Jul 2025 10:33:41 +0000 Subject: [PATCH] Plat: Corstone-1000: Add MM communication buffer configs to CMake -Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TS/trusted-services/+/40893] Two variables are added into the Corstone-1000 platform CMake file so the MM communication buffer address and the page count can be configured. +Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TS/trusted-services/+/40893] Change-Id: I6bbdc90231b0417d4318d6709568113ab1f2c8ce Signed-off-by: Michael Safwat +Signed-off-by: Harsimran Singh Tungal --- - platform/providers/arm/corstone1000/platform.cmake | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) + platform/providers/arm/corstone1000/platform.cmake | 2 ++ + 1 file changed, 2 insertions(+) diff --git a/platform/providers/arm/corstone1000/platform.cmake b/platform/providers/arm/corstone1000/platform.cmake -index 2afcdea8..37c6accf 100644 +index db1e9743..88113c9d 100644 --- a/platform/providers/arm/corstone1000/platform.cmake +++ b/platform/providers/arm/corstone1000/platform.cmake -@@ -1,5 +1,5 @@ - #------------------------------------------------------------------------------- --# Copyright (c) 2021-2024, Arm Limited and Contributors. All rights reserved. -+# Copyright (c) 2021-2025, Arm Limited and Contributors. All rights reserved. - # - # SPDX-License-Identifier: BSD-3-Clause - # -@@ -11,6 +11,9 @@ set(SMM_RPC_CALLER_SESSION_SHARED_MEMORY_SIZE 4*4096 CACHE STRING "RPC caller bu - set(SMM_SP_HEAP_SIZE 80*1024 CACHE STRING "SMM gateway SP heap size") +@@ -18,6 +18,8 @@ set(SMM_SP_HEAP_SIZE 80*1024 CACHE STRING "SMM gateway SP heap size") set(PLAT_RSE_COMMS_PAYLOAD_MAX_SIZE 0x43C0 CACHE STRING "Size of the RSE_COMMS_PAYLOAD buffer") set(COMMS_MHU_MSG_SIZE 0x4500 CACHE STRING "Max message size that can be transfered via MHU") + set(TFM_FWU_MAX_DIGEST_SIZE ${TOTAL_ESRT_SIZE} CACHE STRING "Maximum size of ESRT entries of all the images in a bank") +set(MM_COMM_BUFFER_ADDRESS "0x00000000 0x81FFF000" CACHE STRING "MM Communication buffer start address") +set(MM_COMM_BUFFER_PAGE_COUNT 0x1 CACHE STRING "MM Communication buffer page count") -+ target_compile_definitions(${TGT} PRIVATE SMM_VARIABLE_INDEX_STORAGE_UID=0x787 diff --git a/meta-arm-bsp/recipes-security/trusted-services/ts-arm-platforms.inc b/meta-arm-bsp/recipes-security/trusted-services/ts-arm-platforms.inc index 060725f1..a17beeee 100644 --- a/meta-arm-bsp/recipes-security/trusted-services/ts-arm-platforms.inc +++ b/meta-arm-bsp/recipes-security/trusted-services/ts-arm-platforms.inc @@ -2,32 +2,25 @@ FILESEXTRAPATHS:prepend:corstone1000 := "${THISDIR}/corstone1000:" COMPATIBLE_MACHINE:corstone1000 = "corstone1000" SRC_URI:append:corstone1000 = " \ - file://0001-Add-stub-capsule-update-service-components.patch \ - file://0002-Fix-in-AEAD-for-psa-arch-test-254.patch \ - file://0003-FMP-Support-in-Corstone1000.patch \ - file://0004-Fix-psa-api-crypto-test-no-243.patch \ - file://0005-plat-corstone1000-Use-the-stateless-platform-service.patch \ - file://0006-plat-corstone1000-Initialize-capsule-update-provider.patch \ - file://0007-plat-corstone1000-add-client_id-for-FMP-service.patch \ - file://0008-Remove-Werror-flag.patch \ - file://0009-Remove-PLATFORM_HAS_ATTEST_PK-define-from-IAT-test.patch \ - file://0010-Make-RSS-and-MHU-sizes-compile-time-definitions-user.patch \ - file://0011-Align-PSA-Crypto-with-TF-Mv2.1.patch \ - file://0012-Revert-Make-variable-index-usage-robust-with-redunda.patch \ - file://0013-Revert-Load-and-store-UEFI-variable-index-in-chunks.patch \ - file://0014-Revert-Make-constraints-of-NV-UEFI-variables-persist.patch \ - file://0015-se-proxy-protobuf-change.patch \ + file://0001-Fix-in-AEAD-for-psa-arch-test-254.patch \ + file://0002-Fix-psa-api-crypto-test-no-243.patch \ + file://0003-Remove-Werror-flag.patch \ + file://0004-Remove-PLATFORM_HAS_ATTEST_PK-define-from-IAT-test.patch \ + file://0005-Make-RSS-and-MHU-sizes-compile-time-definitions-user.patch \ + file://0006-Align-PSA-Crypto-with-TF-Mv2.1.patch \ + file://0007-Revert-Load-and-store-UEFI-variable-index-in-chunks.patch \ + file://0008-se-proxy-protobuf-change.patch \ + file://0009-Platform-Corstone1000-Add-PLATFORM_IS_FVP-toggle-for.patch \ + file://0010-Integrate-PSA-FWU-IPC-framework-for-Corstone-1000.patch \ + file://0011-Load-initial-image-state-in-PSA-FWU-M-update-agent.patch \ + file://0012-Corstone1000-Define-PSA-FWU-image-mapping-structure.patch \ + file://0013-Fix-PSA-FWU-IPC-psa_fwu_install-return-value-check.patch \ + file://0014-fwu-Add-EFI-ESRT-v1-support.patch \ + file://0015-platform-corstone1000-Enable-ESRT-support.patch \ + file://0016-platform-corstone1000-Add-event-provider-proxy.patch \ + file://0017-platform-corstone1000-Define-GUID-for-each-payloads.patch \ + file://0018-Add-the-com-buffer-address-and-page-count.patch \ file://0021-Align-PSA-Crypto-structs-with-TF-Mv2.1.1.patch \ - file://0016-Add-the-com-buffer-address-and-page-count.patch \ - file://0017-Platform-Corstone1000-Add-PLATFORM_IS_FVP-toggle-for.patch \ - file://0018-Integrate-PSA-FWU-IPC-framework-for-Corstone-1000.patch \ - file://0019-Load-initial-image-state-in-PSA-FWU-M-update-agent.patch \ - file://0020-Corstone1000-Define-PSA-FWU-image-mapping-structure.patch \ - file://0021-Fix-PSA-FWU-IPC-psa_fwu_install-return-value-check.patch \ - file://0022-fwu-Add-EFI-ESRT-v1-support.patch \ - file://0023-platform-corstone1000-Enable-ESRT-support.patch \ - file://0024-platform-corstone1000-Add-event-provider-proxy.patch \ - file://0025-platform-corstone1000-Define-GUID-for-each-payloads.patch \ " # The patches above introduce errors with GCC 14.1, silence them for now CFLAGS:append:corstone1000 = " -Wno-int-conversion -Wno-implicit-function-declaration" From patchwork Wed Jul 30 11:53:23 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harsimran Singh Tungal X-Patchwork-Id: 67727 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 92858C87FC9 for ; Wed, 30 Jul 2025 11:54:00 +0000 (UTC) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.web11.33477.1753876439382808333 for ; Wed, 30 Jul 2025 04:53:59 -0700 Authentication-Results: mx.groups.io; dkim=none (message not signed); spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: harsimransingh.tungal@arm.com) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 1D5E72936; Wed, 30 Jul 2025 04:53:51 -0700 (PDT) Received: from e132995.cambridge.arm.com (e132995.arm.com [10.1.25.25]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 8E2073F66E; Wed, 30 Jul 2025 04:53:58 -0700 (PDT) From: Harsimran Singh Tungal To: meta-arm@lists.yoctoproject.org Cc: Harsimran Singh Tungal Subject: [PATCH 09/13] arm-bsp/trusted-firmware-m: corstone1000: Remove patches for old capsule update implementation Date: Wed, 30 Jul 2025 12:53:23 +0100 Message-Id: <20250730115327.3671160-10-harsimransingh.tungal@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250730115327.3671160-1-harsimransingh.tungal@arm.com> References: <20250730115327.3671160-1-harsimransingh.tungal@arm.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Wed, 30 Jul 2025 11:54:00 -0000 X-Groupsio-URL: https://lists.yoctoproject.org/g/meta-arm/message/6646 This commit removes the outdated patches of capsule update implementation for the Corstone-1000 platform targeting Trusted-Firmware-M (TF-M). The changes include the removal of obsolete out-of-tree patches and the rebase of retained patches to align with the latest upstream TF-M integration. Key changes: - Dropped legacy TF-M patches related to old capsule update flow - Rebasing of remaining TF-M patches for compatibility with current TF-M baseline This cleanup streamlines the TF-M integration for Corstone-1000 in preparation for the updated PSA Firmware Update (FWU) aligned capsule update support. Signed-off-by: Harsimran Singh Tungal --- ...stone1000-Align-capsule-UEFI-structs.patch | 97 ----- ...Corstone1000-Enable-firewall-in-FVP.patch} | 0 ...-CS1000-Increase-ITS-max-asset-size.patch} | 0 ...-Corstone1000-Fix-NV-counter-writing.patch | 69 ---- ...1000-Increase-RSE_COMMS-buffer-size.patch} | 0 ...S1000-Increase-buffers-for-EFI-vars.patch} | 0 ...-CS1000-Increase-flash-PS-area-size.patch} | 0 ...S1000-Add-multicore-support-for-FVP.patch} | 0 ...m-Corstone1000-Switch-to-metadata-v2.patch | 202 ---------- ...07-Platform-CS1000-Fix-Bank-offsets.patch} | 0 ...-CS1000-Increase-BL2-partition-size.patch} | 0 ...Add-PSA_WANT_ALG_SHA_256-definition.patch} | 0 ...00-Remove-reset-after-capsule-update.patch | 28 -- ...-CS1000-Add-crypto-configs-for-ADAC.patch} | 0 ...rm-CS1000-Fix-platform-name-in-logs.patch} | 0 ...form-CS1000-Remove-unused-BL1-files.patch} | 0 ...m-CS1000-Fix-compiler-switch-in-BL1.patch} | 0 ...C312-alignment-of-cc312-differences.patch} | 0 ...ne1000-Allow-FWU-calls-in-RSE-COMMS.patch} | 0 ...-specific-TFM_FWU_BOOTLOADER_LIB-se.patch} | 0 ...latform-CS1000-Enable-FWU-partition.patch} | 0 ...000-Remove-duplicated-metadata-write.patch | 61 --- ...1000-Implement-Bootloader-Abstracti.patch} | 0 ...-Corstone1000-Increase-buffer-sizes.patch} | 0 ...1000-Validate-both-metadata-replicas.patch | 370 ------------------ ...orstone1000-add-unique-guid-for-mps3.patch | 41 -- .../trusted-firmware-m-corstone1000.inc | 45 +-- 27 files changed, 19 insertions(+), 894 deletions(-) delete mode 100644 meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0001-Platform-Corstone1000-Align-capsule-UEFI-structs.patch rename meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/{0003-Platform-Corstone1000-Enable-firewall-in-FVP.patch => 0001-Platform-Corstone1000-Enable-firewall-in-FVP.patch} (100%) rename meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/{0004-Platform-CS1000-Increase-ITS-max-asset-size.patch => 0002-Platform-CS1000-Increase-ITS-max-asset-size.patch} (100%) delete mode 100644 meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0002-Platform-Corstone1000-Fix-NV-counter-writing.patch rename meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/{0005-Platform-CS1000-Increase-RSE_COMMS-buffer-size.patch => 0003-Platform-CS1000-Increase-RSE_COMMS-buffer-size.patch} (100%) rename meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/{0006-Platform-CS1000-Increase-buffers-for-EFI-vars.patch => 0004-Platform-CS1000-Increase-buffers-for-EFI-vars.patch} (100%) rename meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/{0008-Platform-CS1000-Increase-flash-PS-area-size.patch => 0005-Platform-CS1000-Increase-flash-PS-area-size.patch} (100%) rename meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/{0010-platform-CS1000-Add-multicore-support-for-FVP.patch => 0006-platform-CS1000-Add-multicore-support-for-FVP.patch} (100%) delete mode 100644 meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0007-Plaform-Corstone1000-Switch-to-metadata-v2.patch rename meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/{0011-Platform-CS1000-Fix-Bank-offsets.patch => 0007-Platform-CS1000-Fix-Bank-offsets.patch} (100%) rename meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/{0012-Platform-CS1000-Increase-BL2-partition-size.patch => 0008-Platform-CS1000-Increase-BL2-partition-size.patch} (100%) rename meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/{0013-CC312-ADAC-Add-PSA_WANT_ALG_SHA_256-definition.patch => 0009-CC312-ADAC-Add-PSA_WANT_ALG_SHA_256-definition.patch} (100%) delete mode 100644 meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0009-corstone1000-Remove-reset-after-capsule-update.patch rename meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/{0014-Platform-CS1000-Add-crypto-configs-for-ADAC.patch => 0010-Platform-CS1000-Add-crypto-configs-for-ADAC.patch} (100%) rename meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/{0015-Platform-CS1000-Fix-platform-name-in-logs.patch => 0011-Platform-CS1000-Fix-platform-name-in-logs.patch} (100%) rename meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/{0017-Platform-CS1000-Remove-unused-BL1-files.patch => 0012-Platform-CS1000-Remove-unused-BL1-files.patch} (100%) rename meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/{0019-Platform-CS1000-Fix-compiler-switch-in-BL1.patch => 0013-Platform-CS1000-Fix-compiler-switch-in-BL1.patch} (100%) rename meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/{0022-CC312-alignment-of-cc312-differences.patch => 0014-CC312-alignment-of-cc312-differences.patch} (100%) rename meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/{0024-Platform-corstone1000-Allow-FWU-calls-in-RSE-COMMS.patch => 0015-Platform-corstone1000-Allow-FWU-calls-in-RSE-COMMS.patch} (100%) rename meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/{0025-FWU-Make-platform-specific-TFM_FWU_BOOTLOADER_LIB-se.patch => 0016-FWU-Make-platform-specific-TFM_FWU_BOOTLOADER_LIB-se.patch} (100%) rename meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/{0026-Platform-CS1000-Enable-FWU-partition.patch => 0017-Platform-CS1000-Enable-FWU-partition.patch} (100%) delete mode 100644 meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0018-Platform-CS1000-Remove-duplicated-metadata-write.patch rename meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/{0027-Platform-Corstone1000-Implement-Bootloader-Abstracti.patch => 0018-Platform-Corstone1000-Implement-Bootloader-Abstracti.patch} (100%) rename meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/{0028-Platform-Corstone1000-Increase-buffer-sizes.patch => 0019-Platform-Corstone1000-Increase-buffer-sizes.patch} (100%) delete mode 100644 meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0020-Platform-CS1000-Validate-both-metadata-replicas.patch delete mode 100644 meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0021-platform-corstone1000-add-unique-guid-for-mps3.patch diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0001-Platform-Corstone1000-Align-capsule-UEFI-structs.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0001-Platform-Corstone1000-Align-capsule-UEFI-structs.patch deleted file mode 100644 index fbeb1540..00000000 --- a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0001-Platform-Corstone1000-Align-capsule-UEFI-structs.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 6ac0d4ce58c1a957c5f086e8c32268fdfc3ea531 Mon Sep 17 00:00:00 2001 -From: Emekcan Aras -Date: Thu, 26 Oct 2023 11:46:04 +0100 -Subject: [PATCH 1/9] Platform: Corstone1000: Align capsule UEFI structs - -The UEFI capsules are generated using the U-Boot mkeficapsule tool. -U-Boot uses packed struct for the UEFI and FMP structures, see [1]. -The structs have to be aligned in the TF-M side parser to avoid -crashes. - -[1] https://github.com/u-boot/u-boot/blob/u-boot-2023.07.y/include/efi_api.h#L245 - -Signed-off-by: Emekcan Aras -Signed-off-by: Bence Balogh -Upstream-Status: Backport [6ac0d4ce58c1a957c5f086e8c32268fdfc3ea531] ---- - .../fw_update_agent/uefi_capsule_parser.c | 17 +++++++++-------- - 1 file changed, 9 insertions(+), 8 deletions(-) - -diff --git a/platform/ext/target/arm/corstone1000/fw_update_agent/uefi_capsule_parser.c b/platform/ext/target/arm/corstone1000/fw_update_agent/uefi_capsule_parser.c -index c706c040a..44566e08d 100644 ---- a/platform/ext/target/arm/corstone1000/fw_update_agent/uefi_capsule_parser.c -+++ b/platform/ext/target/arm/corstone1000/fw_update_agent/uefi_capsule_parser.c -@@ -1,10 +1,11 @@ - /* -- * Copyright (c) 2021, Arm Limited. All rights reserved. -+ * Copyright (c) 2021-2024, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -+#include "cmsis_compiler.h" - #include "uefi_capsule_parser.h" - #include "fwu_agent.h" - #include -@@ -29,21 +30,21 @@ Update Capsule Structure (UEFI spec 2.9 1004) - Payload n (item_offset[embedded_driver_count + payload_item_count -1]) - */ - --typedef struct { -+typedef __PACKED_STRUCT { - struct efi_guid capsule_guid; - uint32_t header_size; - uint32_t flags; - uint32_t capsule_image_size; - } efi_capsule_header_t; - --typedef struct { -+typedef __PACKED_STRUCT { - uint32_t version; - uint16_t embedded_driver_count; - uint16_t payload_item_count; - uint64_t item_offset_list[]; - } efi_firmware_management_capsule_header_t; - --typedef struct { -+typedef __PACKED_STRUCT { - uint32_t version; - struct efi_guid update_image_type_id; - uint8_t update_image_index; -@@ -54,7 +55,7 @@ typedef struct { - uint64_t image_capsule_support; //introduced in v3 - } efi_firmware_management_capsule_image_header_t; - --typedef struct { -+typedef __PACKED_STRUCT { - uint32_t signature; - uint32_t header_size; - uint32_t fw_version; -@@ -63,20 +64,20 @@ typedef struct { - - #define ANYSIZE_ARRAY 0 - --typedef struct { -+typedef __PACKED_STRUCT { - uint32_t dwLength; - uint16_t wRevision; - uint16_t wCertificateType; - uint8_t bCertificate[ANYSIZE_ARRAY]; - } WIN_CERTIFICATE; - --typedef struct { -+typedef __PACKED_STRUCT { - WIN_CERTIFICATE hdr; - struct efi_guid cert_type; - uint8_t cert_data[ANYSIZE_ARRAY]; - } win_certificate_uefi_guid_t; - --typedef struct { -+typedef __PACKED_STRUCT { - uint64_t monotonic_count; - win_certificate_uefi_guid_t auth_info; - } efi_firmware_image_authentication_t; --- -2.25.1 - diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0003-Platform-Corstone1000-Enable-firewall-in-FVP.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0001-Platform-Corstone1000-Enable-firewall-in-FVP.patch similarity index 100% rename from meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0003-Platform-Corstone1000-Enable-firewall-in-FVP.patch rename to meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0001-Platform-Corstone1000-Enable-firewall-in-FVP.patch diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0004-Platform-CS1000-Increase-ITS-max-asset-size.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0002-Platform-CS1000-Increase-ITS-max-asset-size.patch similarity index 100% rename from meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0004-Platform-CS1000-Increase-ITS-max-asset-size.patch rename to meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0002-Platform-CS1000-Increase-ITS-max-asset-size.patch diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0002-Platform-Corstone1000-Fix-NV-counter-writing.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0002-Platform-Corstone1000-Fix-NV-counter-writing.patch deleted file mode 100644 index cf598824..00000000 --- a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0002-Platform-Corstone1000-Fix-NV-counter-writing.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 47c54e8e79df52f40057c3d4be9411447d2787c2 Mon Sep 17 00:00:00 2001 -From: Emekcan Aras -Date: Wed, 21 Feb 2024 07:44:25 +0000 -Subject: [PATCH 2/9] Platform: Corstone1000: Fix NV counter writing - -The BL1 writes the PLAT_NV_COUNTER_BL1_0 NV counter directly without -updating the private metadata. Because of this the update_nv_counters() -function should not update the PLAT_NV_COUNTER_BL1_0 from the metadata. - -The tfm_plat_set_nv_counter() had a typo and wrote the -priv_metadata->nv_counter[FWU_BL2_NV_COUNTER] to every NV counter. - -Signed-off-by: Emekcan Aras -Signed-off-by: Bence Balogh -Upstream-Status: Backport [47c54e8e79df52f40057c3d4be9411447d2787c2] ---- - .../corstone1000/fw_update_agent/fwu_agent.c | 18 +++++++++++------- - 1 file changed, 11 insertions(+), 7 deletions(-) - -diff --git a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c -index 9a9926a3d..b2f31e166 100644 ---- a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c -+++ b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c -@@ -1120,12 +1120,13 @@ static enum fwu_agent_error_t update_nv_counters( - - FWU_LOG_MSG("%s: enter\n\r", __func__); - -- for (int i = 0; i <= FWU_MAX_NV_COUNTER_INDEX; i++) { -+ /* The FWU_BL2_NV_COUNTER (0) is not mirrored in the private metadata. It is -+ * directly updated in the bl1_2_validate_image_at_addr() function, in -+ * tfm/bl1/bl1_2/main.c. -+ * Because of this, the index starts from FWU_TFM_NV_COUNTER (1). */ -+ for (int i = FWU_TFM_NV_COUNTER; i <= FWU_MAX_NV_COUNTER_INDEX; i++) { - - switch (i) { -- case FWU_BL2_NV_COUNTER: -- tfm_nv_counter_i = PLAT_NV_COUNTER_BL1_0; -- break; - case FWU_TFM_NV_COUNTER: - tfm_nv_counter_i = PLAT_NV_COUNTER_BL2_0; - break; -@@ -1140,18 +1141,21 @@ static enum fwu_agent_error_t update_nv_counters( - err = tfm_plat_read_nv_counter(tfm_nv_counter_i, - sizeof(security_cnt), (uint8_t *)&security_cnt); - if (err != TFM_PLAT_ERR_SUCCESS) { -+ FWU_LOG_MSG("%s: couldn't read NV counter\n\r", __func__); - return FWU_AGENT_ERROR; - } - - if (priv_metadata->nv_counter[i] < security_cnt) { -+ FWU_LOG_MSG("%s: staged NV counter is smaller than current value\n\r", __func__); - return FWU_AGENT_ERROR; - } else if (priv_metadata->nv_counter[i] > security_cnt) { -- FWU_LOG_MSG("%s: updaing index = %u nv counter = %u->%u\n\r", -+ FWU_LOG_MSG("%s: updating index = %u nv counter = %u->%u\n\r", - __func__, i, security_cnt, -- priv_metadata->nv_counter[FWU_BL2_NV_COUNTER]); -+ priv_metadata->nv_counter[i]); - err = tfm_plat_set_nv_counter(tfm_nv_counter_i, -- priv_metadata->nv_counter[FWU_BL2_NV_COUNTER]); -+ priv_metadata->nv_counter[i]); - if (err != TFM_PLAT_ERR_SUCCESS) { -+ FWU_LOG_MSG("%s: couldn't write NV counter\n\r", __func__); - return FWU_AGENT_ERROR; - } - } --- -2.25.1 - diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0005-Platform-CS1000-Increase-RSE_COMMS-buffer-size.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0003-Platform-CS1000-Increase-RSE_COMMS-buffer-size.patch similarity index 100% rename from meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0005-Platform-CS1000-Increase-RSE_COMMS-buffer-size.patch rename to meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0003-Platform-CS1000-Increase-RSE_COMMS-buffer-size.patch diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0006-Platform-CS1000-Increase-buffers-for-EFI-vars.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0004-Platform-CS1000-Increase-buffers-for-EFI-vars.patch similarity index 100% rename from meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0006-Platform-CS1000-Increase-buffers-for-EFI-vars.patch rename to meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0004-Platform-CS1000-Increase-buffers-for-EFI-vars.patch diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0008-Platform-CS1000-Increase-flash-PS-area-size.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0005-Platform-CS1000-Increase-flash-PS-area-size.patch similarity index 100% rename from meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0008-Platform-CS1000-Increase-flash-PS-area-size.patch rename to meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0005-Platform-CS1000-Increase-flash-PS-area-size.patch diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0010-platform-CS1000-Add-multicore-support-for-FVP.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0006-platform-CS1000-Add-multicore-support-for-FVP.patch similarity index 100% rename from meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0010-platform-CS1000-Add-multicore-support-for-FVP.patch rename to meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0006-platform-CS1000-Add-multicore-support-for-FVP.patch diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0007-Plaform-Corstone1000-Switch-to-metadata-v2.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0007-Plaform-Corstone1000-Switch-to-metadata-v2.patch deleted file mode 100644 index 2e14dfd6..00000000 --- a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0007-Plaform-Corstone1000-Switch-to-metadata-v2.patch +++ /dev/null @@ -1,202 +0,0 @@ -From c731d187fbe9fc1e10ad8ecfb3d04bb480bc86b6 Mon Sep 17 00:00:00 2001 -From: Emekcan Aras -Date: Mon, 8 Apr 2024 16:04:45 +0100 -Subject: [PATCH 7/9] Plaform: Corstone1000: Switch to metadata v2 - -This upgrades metadata data structs from v1 to v2 as described in PSA -FWU Specification: -https://developer.arm.com/documentation/den0118/latest/ - -The TrustedFirmware-A v2.11 release supports only the metadata v2. The -structs in TF-M side had to be aligned to keep the compatibility. - -Signed-off-by: Emekcan Aras -Signed-off-by: Bence Balogh -Upstream-Status: Backport [c731d187fbe9fc1e10ad8ecfb3d04bb480bc86b6] ---- - .../corstone1000/fw_update_agent/fwu_agent.c | 86 +++++++++++++++---- - 1 file changed, 69 insertions(+), 17 deletions(-) - -diff --git a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c -index b2f31e166..5fddd3238 100644 ---- a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c -+++ b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c -@@ -26,6 +26,15 @@ - #include "platform.h" - #endif - -+#define FWU_METADATA_VERSION 2 -+#define FWU_FW_STORE_DESC_OFFSET 0x20 -+#define NR_OF_MAX_FW_BANKS 4 -+ -+/* -+ * Metadata version 2 data structures defined by PSA_FW update specification -+ * at https://developer.arm.com/documentation/den0118/latest/ -+ */ -+ - /* Properties of image in a bank */ - struct fwu_image_properties { - -@@ -58,6 +67,28 @@ struct fwu_image_entry { - - } __packed; - -+struct fwu_fw_store_descriptor { -+ -+ /* Number of Banks */ -+ uint8_t num_banks; -+ -+ /* Reserved */ -+ uint8_t reserved; -+ -+ /* Number of images per bank */ -+ uint16_t num_images; -+ -+ /* Size of image_entry(all banks) in bytes */ -+ uint16_t img_entry_size; -+ -+ /* Size of image bank info structure in bytes */ -+ uint16_t bank_info_entry_size; -+ -+ /* Array of fwu_image_entry structs */ -+ struct fwu_image_entry img_entry[NR_OF_IMAGES_IN_FW_BANK]; -+ -+} __packed; -+ - struct fwu_metadata { - - /* Metadata CRC value */ -@@ -72,8 +103,23 @@ struct fwu_metadata { - /* Previous bank index with which device booted successfully */ - uint32_t previous_active_index; - -- /* Image entry information */ -- struct fwu_image_entry img_entry[NR_OF_IMAGES_IN_FW_BANK]; -+ /* Size of the entire metadata in bytes */ -+ uint32_t metadata_size; -+ -+ /* Offset of the image descriptor structure */ -+ uint16_t desc_offset; -+ -+ /* Reserved */ -+ uint16_t reserved1; -+ -+ /* Bank state: It's not used in corstone1000 at the moment.Currently -+ * not used by any sw componenets such as u-boot and TF-A */ -+ uint8_t bank_state[NR_OF_MAX_FW_BANKS]; -+ -+ /* Reserved */ -+ uint32_t reserved2; -+ -+ struct fwu_fw_store_descriptor fw_desc; - - } __packed; - -@@ -607,23 +653,29 @@ enum fwu_agent_error_t fwu_metadata_provision(void) - - memset(&_metadata, 0, sizeof(struct fwu_metadata)); - -- _metadata.version = 1; -+ _metadata.version = FWU_METADATA_VERSION; - _metadata.active_index = BANK_0; - _metadata.previous_active_index = BANK_1; -+ _metadata.desc_offset= FWU_FW_STORE_DESC_OFFSET; - -+ _metadata.fw_desc.num_banks = NR_OF_FW_BANKS; -+ _metadata.fw_desc.num_images = NR_OF_IMAGES_IN_FW_BANK; -+ _metadata.fw_desc.img_entry_size = sizeof(struct fwu_image_entry) * NR_OF_IMAGES_IN_FW_BANK; -+ _metadata.fw_desc.bank_info_entry_size = sizeof(struct fwu_image_properties) * NR_OF_FW_BANKS; - /* bank 0 is the place where images are located at the - * start of device lifecycle */ - - for (int i = 0; i < NR_OF_IMAGES_IN_FW_BANK; i++) { - -- _metadata.img_entry[i].img_props[BANK_0].accepted = IMAGE_ACCEPTED; -- _metadata.img_entry[i].img_props[BANK_0].version = image_version; -+ _metadata.fw_desc.img_entry[i].img_props[BANK_0].accepted = IMAGE_ACCEPTED; -+ _metadata.fw_desc.img_entry[i].img_props[BANK_0].version = image_version; - -- _metadata.img_entry[i].img_props[BANK_1].accepted = IMAGE_NOT_ACCEPTED; -- _metadata.img_entry[i].img_props[BANK_1].version = INVALID_VERSION; -+ _metadata.fw_desc.img_entry[i].img_props[BANK_1].accepted = IMAGE_NOT_ACCEPTED; -+ _metadata.fw_desc.img_entry[i].img_props[BANK_1].version = INVALID_VERSION; - } - -- /* Calculate CRC32 for fwu metadata */ -+ /* Calculate CRC32 for fwu metadata. The first filed in the _metadata has to be the crc_32. -+ * This should be omited from the calculation. */ - _metadata.crc_32 = crc32((uint8_t *)&_metadata.version, - sizeof(struct fwu_metadata) - sizeof(uint32_t)); - -@@ -685,7 +737,7 @@ static enum fwu_agent_state_t get_fwu_agent_state( - } - - for (int i = 0; i < NR_OF_IMAGES_IN_FW_BANK; i++) { -- if ((metadata_ptr->img_entry[i].img_props[boot_index].accepted) -+ if ((metadata_ptr->fw_desc.img_entry[i].img_props[boot_index].accepted) - == (IMAGE_NOT_ACCEPTED)) { - return FWU_AGENT_STATE_TRIAL; - } -@@ -760,7 +812,7 @@ static enum fwu_agent_error_t flash_full_capsule( - } - - if (version <= -- (metadata->img_entry[IMAGE_0].img_props[active_index].version)) { -+ (metadata->fw_desc.img_entry[IMAGE_0].img_props[active_index].version)) { - FWU_LOG_MSG("ERROR: %s: version error\n\r",__func__); - return FWU_AGENT_ERROR; - } -@@ -791,9 +843,9 @@ static enum fwu_agent_error_t flash_full_capsule( - - /* Change system state to trial bank state */ - for (int i = 0; i < NR_OF_IMAGES_IN_FW_BANK; i++) { -- metadata->img_entry[i].img_props[previous_active_index].accepted = -+ metadata->fw_desc.img_entry[i].img_props[previous_active_index].accepted = - IMAGE_NOT_ACCEPTED; -- metadata->img_entry[i].img_props[previous_active_index].version = version; -+ metadata->fw_desc.img_entry[i].img_props[previous_active_index].version = version; - } - metadata->active_index = previous_active_index; - metadata->previous_active_index = active_index; -@@ -900,7 +952,7 @@ static enum fwu_agent_error_t accept_full_capsule( - FWU_LOG_MSG("%s: enter\n\r", __func__); - - for (int i = 0; i < NR_OF_IMAGES_IN_FW_BANK; i++) { -- metadata->img_entry[i].img_props[active_index].accepted = -+ metadata->fw_desc.img_entry[i].img_props[active_index].accepted = - IMAGE_ACCEPTED; - } - -@@ -990,7 +1042,7 @@ static enum fwu_agent_error_t fwu_select_previous( - - index = metadata->previous_active_index; - for (int i = 0; i < NR_OF_IMAGES_IN_FW_BANK; i++) { -- if (metadata->img_entry[i].img_props[index].accepted != IMAGE_ACCEPTED) -+ if (metadata->fw_desc.img_entry[i].img_props[index].accepted != IMAGE_ACCEPTED) - { - FWU_ASSERT(0); - } -@@ -1211,7 +1263,7 @@ enum fwu_agent_error_t corstone1000_fwu_host_ack(void) - /* firmware update failed, revert back to previous bank */ - - priv_metadata.fmp_last_attempt_version = -- _metadata.img_entry[IMAGE_0].img_props[_metadata.active_index].version; -+ _metadata.fw_desc.img_entry[IMAGE_0].img_props[_metadata.active_index].version; - - priv_metadata.fmp_last_attempt_status = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL; - -@@ -1222,9 +1274,9 @@ enum fwu_agent_error_t corstone1000_fwu_host_ack(void) - /* firmware update successful */ - - priv_metadata.fmp_version = -- _metadata.img_entry[IMAGE_0].img_props[_metadata.active_index].version; -+ _metadata.fw_desc.img_entry[IMAGE_0].img_props[_metadata.active_index].version; - priv_metadata.fmp_last_attempt_version = -- _metadata.img_entry[IMAGE_0].img_props[_metadata.active_index].version; -+ _metadata.fw_desc.img_entry[IMAGE_0].img_props[_metadata.active_index].version; - - priv_metadata.fmp_last_attempt_status = LAST_ATTEMPT_STATUS_SUCCESS; - --- -2.25.1 - diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0011-Platform-CS1000-Fix-Bank-offsets.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0007-Platform-CS1000-Fix-Bank-offsets.patch similarity index 100% rename from meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0011-Platform-CS1000-Fix-Bank-offsets.patch rename to meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0007-Platform-CS1000-Fix-Bank-offsets.patch diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0012-Platform-CS1000-Increase-BL2-partition-size.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0008-Platform-CS1000-Increase-BL2-partition-size.patch similarity index 100% rename from meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0012-Platform-CS1000-Increase-BL2-partition-size.patch rename to meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0008-Platform-CS1000-Increase-BL2-partition-size.patch diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0013-CC312-ADAC-Add-PSA_WANT_ALG_SHA_256-definition.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0009-CC312-ADAC-Add-PSA_WANT_ALG_SHA_256-definition.patch similarity index 100% rename from meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0013-CC312-ADAC-Add-PSA_WANT_ALG_SHA_256-definition.patch rename to meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0009-CC312-ADAC-Add-PSA_WANT_ALG_SHA_256-definition.patch diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0009-corstone1000-Remove-reset-after-capsule-update.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0009-corstone1000-Remove-reset-after-capsule-update.patch deleted file mode 100644 index e3333c53..00000000 --- a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0009-corstone1000-Remove-reset-after-capsule-update.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 898d3c148521b331302c587e658d7e0a4f645c77 Mon Sep 17 00:00:00 2001 -From: Bence Balogh -Date: Mon, 27 May 2024 17:11:31 +0200 -Subject: [PATCH 09/10] corstone1000: Remove reset after capsule update - -Signed-off-by: Bence Balogh -Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TF-M/trusted-firmware-m/+/29065] ---- - .../target/arm/corstone1000/services/src/tfm_platform_system.c | 3 --- - 1 file changed, 3 deletions(-) - -diff --git a/platform/ext/target/arm/corstone1000/services/src/tfm_platform_system.c b/platform/ext/target/arm/corstone1000/services/src/tfm_platform_system.c -index 41305ed966..1e837ce3b5 100644 ---- a/platform/ext/target/arm/corstone1000/services/src/tfm_platform_system.c -+++ b/platform/ext/target/arm/corstone1000/services/src/tfm_platform_system.c -@@ -28,9 +28,6 @@ enum tfm_platform_err_t tfm_platform_hal_ioctl(tfm_platform_ioctl_req_t request, - - case IOCTL_CORSTONE1000_FWU_FLASH_IMAGES: - result = corstone1000_fwu_flash_image(); -- if (!result) { -- NVIC_SystemReset(); -- } - break; - - case IOCTL_CORSTONE1000_FWU_HOST_ACK: --- -2.25.1 - diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0014-Platform-CS1000-Add-crypto-configs-for-ADAC.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0010-Platform-CS1000-Add-crypto-configs-for-ADAC.patch similarity index 100% rename from meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0014-Platform-CS1000-Add-crypto-configs-for-ADAC.patch rename to meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0010-Platform-CS1000-Add-crypto-configs-for-ADAC.patch diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0015-Platform-CS1000-Fix-platform-name-in-logs.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0011-Platform-CS1000-Fix-platform-name-in-logs.patch similarity index 100% rename from meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0015-Platform-CS1000-Fix-platform-name-in-logs.patch rename to meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0011-Platform-CS1000-Fix-platform-name-in-logs.patch diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0017-Platform-CS1000-Remove-unused-BL1-files.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0012-Platform-CS1000-Remove-unused-BL1-files.patch similarity index 100% rename from meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0017-Platform-CS1000-Remove-unused-BL1-files.patch rename to meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0012-Platform-CS1000-Remove-unused-BL1-files.patch diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0019-Platform-CS1000-Fix-compiler-switch-in-BL1.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0013-Platform-CS1000-Fix-compiler-switch-in-BL1.patch similarity index 100% rename from meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0019-Platform-CS1000-Fix-compiler-switch-in-BL1.patch rename to meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0013-Platform-CS1000-Fix-compiler-switch-in-BL1.patch diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0022-CC312-alignment-of-cc312-differences.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0014-CC312-alignment-of-cc312-differences.patch similarity index 100% rename from meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0022-CC312-alignment-of-cc312-differences.patch rename to meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0014-CC312-alignment-of-cc312-differences.patch diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0024-Platform-corstone1000-Allow-FWU-calls-in-RSE-COMMS.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0015-Platform-corstone1000-Allow-FWU-calls-in-RSE-COMMS.patch similarity index 100% rename from meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0024-Platform-corstone1000-Allow-FWU-calls-in-RSE-COMMS.patch rename to meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0015-Platform-corstone1000-Allow-FWU-calls-in-RSE-COMMS.patch diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0025-FWU-Make-platform-specific-TFM_FWU_BOOTLOADER_LIB-se.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0016-FWU-Make-platform-specific-TFM_FWU_BOOTLOADER_LIB-se.patch similarity index 100% rename from meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0025-FWU-Make-platform-specific-TFM_FWU_BOOTLOADER_LIB-se.patch rename to meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0016-FWU-Make-platform-specific-TFM_FWU_BOOTLOADER_LIB-se.patch diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0026-Platform-CS1000-Enable-FWU-partition.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0017-Platform-CS1000-Enable-FWU-partition.patch similarity index 100% rename from meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0026-Platform-CS1000-Enable-FWU-partition.patch rename to meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0017-Platform-CS1000-Enable-FWU-partition.patch diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0018-Platform-CS1000-Remove-duplicated-metadata-write.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0018-Platform-CS1000-Remove-duplicated-metadata-write.patch deleted file mode 100644 index e468916e..00000000 --- a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0018-Platform-CS1000-Remove-duplicated-metadata-write.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 60793058794f0ac8ea35a69b2dddf97ccba1acdb Mon Sep 17 00:00:00 2001 -From: Bence Balogh -Date: Thu, 5 Sep 2024 21:29:07 +0200 -Subject: [PATCH 2/5] Platform: CS1000: Remove duplicated metadata write - -The metadata replica_2 was written twice which is not needed. -Signed-off-by: Bence Balogh -Upstream-Status: Pending [Not submitted to upstream yet] ---- - .../corstone1000/fw_update_agent/fwu_agent.c | 28 ------------------- - 1 file changed, 28 deletions(-) - -diff --git a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c -index d0028a56d8..2b69447dc5 100644 ---- a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c -+++ b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c -@@ -499,20 +499,6 @@ static enum fwu_agent_error_t metadata_write( - return FWU_AGENT_ERROR; - } - -- FWU_LOG_MSG("%s: enter: flash addr = %u, size = %d\n\r", __func__, -- FWU_METADATA_REPLICA_2_OFFSET, sizeof(struct fwu_metadata)); -- -- ret = FWU_METADATA_FLASH_DEV.EraseSector(FWU_METADATA_REPLICA_2_OFFSET); -- if (ret != ARM_DRIVER_OK) { -- return FWU_AGENT_ERROR; -- } -- -- ret = FWU_METADATA_FLASH_DEV.ProgramData(FWU_METADATA_REPLICA_2_OFFSET, -- p_metadata, sizeof(struct fwu_metadata)); -- if (ret < 0 || ret != sizeof(struct fwu_metadata)) { -- return FWU_AGENT_ERROR; -- } -- - FWU_LOG_MSG("%s: success: active = %u, previous = %d\n\r", __func__, - p_metadata->active_index, p_metadata->previous_active_index); - return FWU_AGENT_SUCCESS; -@@ -569,20 +555,6 @@ static enum fwu_agent_error_t metadata_write( - return FWU_AGENT_ERROR; - } - -- FWU_LOG_MSG("%s: enter: flash addr = %u, size = %d\n\r", __func__, -- FWU_METADATA_REPLICA_2_OFFSET, sizeof(struct fwu_metadata)); -- -- ret = FWU_METADATA_FLASH_DEV.EraseSector(FWU_METADATA_REPLICA_2_OFFSET); -- if (ret != ARM_DRIVER_OK) { -- return FWU_AGENT_ERROR; -- } -- -- ret = FWU_METADATA_FLASH_DEV.ProgramData(FWU_METADATA_REPLICA_2_OFFSET, -- p_metadata, sizeof(struct fwu_metadata)); -- if (ret < 0 || ret != sizeof(struct fwu_metadata)) { -- return FWU_AGENT_ERROR; -- } -- - FWU_LOG_MSG("%s: success: active = %u, previous = %d\n\r", __func__, - p_metadata->active_index, p_metadata->previous_active_index); - return FWU_AGENT_SUCCESS; --- -2.25.1 - diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0027-Platform-Corstone1000-Implement-Bootloader-Abstracti.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0018-Platform-Corstone1000-Implement-Bootloader-Abstracti.patch similarity index 100% rename from meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0027-Platform-Corstone1000-Implement-Bootloader-Abstracti.patch rename to meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0018-Platform-Corstone1000-Implement-Bootloader-Abstracti.patch diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0028-Platform-Corstone1000-Increase-buffer-sizes.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0019-Platform-Corstone1000-Increase-buffer-sizes.patch similarity index 100% rename from meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0028-Platform-Corstone1000-Increase-buffer-sizes.patch rename to meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0019-Platform-Corstone1000-Increase-buffer-sizes.patch diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0020-Platform-CS1000-Validate-both-metadata-replicas.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0020-Platform-CS1000-Validate-both-metadata-replicas.patch deleted file mode 100644 index e38c8651..00000000 --- a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0020-Platform-CS1000-Validate-both-metadata-replicas.patch +++ /dev/null @@ -1,370 +0,0 @@ -From 5fd2662e1f20b5c645ff0755e84424bae303fa45 Mon Sep 17 00:00:00 2001 -From: Bence Balogh -Date: Mon, 9 Sep 2024 09:42:58 +0200 -Subject: [PATCH] Platform: CS1000: Validate both metadata replicas - -According to the [1] both metadata replica integrity should be checked -during the update agent initialization, and if one of the replica is -corrupted then it should be fixed by copying the other replica. - -This commit: -- Adds the integrity check and correction to the - corstone1000_fwu_host_ack() function. This function is called when - the Host core has booted. -- Updates the metadata_read() function so both replica can be read. -- Adds metadata_write_replica() function to write metadata replicas - separately. - -[1] https://developer.arm.com/documentation/den0118/a/?lang=en - -Signed-off-by: Bence Balogh -Upstream-Status: Pending [Not submitted to upstream yet] ---- - .../corstone1000/fw_update_agent/fwu_agent.c | 167 ++++++++++++------ - .../corstone1000/fw_update_agent/fwu_agent.h | 7 + - 2 files changed, 119 insertions(+), 55 deletions(-) - -diff --git a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c -index 92b918c67..aad6208e0 100644 ---- a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c -+++ b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c -@@ -395,20 +395,33 @@ static enum fwu_agent_error_t metadata_read_without_validation(struct fwu_metada - #endif - - #ifdef BL1_BUILD --static enum fwu_agent_error_t metadata_read(struct fwu_metadata *p_metadata) -+static enum fwu_agent_error_t metadata_read(struct fwu_metadata *p_metadata, uint8_t replica_num) - { - int ret; -+ uint32_t replica_offset = 0; - -- FWU_LOG_MSG("%s: enter: flash addr = %u, size = %d\n\r", __func__, -- FWU_METADATA_REPLICA_1_OFFSET, sizeof(struct fwu_metadata)); -+ FWU_LOG_MSG("%s: enter\n\r", __func__); - - if (!p_metadata) { - return FWU_AGENT_ERROR; - } - -- ret = FWU_METADATA_FLASH_DEV.ReadData(FWU_METADATA_REPLICA_1_OFFSET, -- p_metadata, sizeof(struct fwu_metadata)); -- if (ret < 0 || ret != sizeof(struct fwu_metadata)) { -+ if (replica_num == 1) { -+ replica_offset = FWU_METADATA_REPLICA_1_OFFSET; -+ } else if (replica_num == 2) { -+ replica_offset = FWU_METADATA_REPLICA_2_OFFSET; -+ } else { -+ FWU_LOG_MSG("%s: replica_num must be 1 or 2\n\r", __func__); -+ return FWU_AGENT_ERROR; -+ } -+ -+ FWU_LOG_MSG("%s: flash addr = %u, size = %d\n\r", __func__, -+ replica_offset, sizeof(*p_metadata)); -+ -+ -+ ret = FWU_METADATA_FLASH_DEV.ReadData(replica_offset, -+ p_metadata, sizeof(*p_metadata)); -+ if (ret < 0 || ret != sizeof(*p_metadata)) { - return FWU_AGENT_ERROR; - } - -@@ -422,17 +435,27 @@ static enum fwu_agent_error_t metadata_read(struct fwu_metadata *p_metadata) - return FWU_AGENT_SUCCESS; - } - #else --static enum fwu_agent_error_t metadata_read(struct fwu_metadata *p_metadata) -+static enum fwu_agent_error_t metadata_read(struct fwu_metadata *p_metadata, uint8_t replica_num) - { - uuid_t metadata_uuid = FWU_METADATA_TYPE_UUID; - partition_entry_t *part; - int ret; - -+ FWU_LOG_MSG("%s: enter\n\r", __func__); -+ - if (!p_metadata) { - return FWU_AGENT_ERROR; - } - -- part = get_partition_entry_by_type(&metadata_uuid); -+ if (replica_num == 1) { -+ part = get_partition_entry_by_type(&metadata_uuid); -+ } else if (replica_num == 2) { -+ part = get_partition_replica_by_type(&metadata_uuid); -+ } else { -+ FWU_LOG_MSG("%s: replica_num must be 1 or 2\n\r", __func__); -+ return FWU_AGENT_ERROR; -+ } -+ - if (!part) { - FWU_LOG_MSG("%s: FWU metadata partition not found\n\r", __func__); - return FWU_AGENT_ERROR; -@@ -461,39 +484,38 @@ static enum fwu_agent_error_t metadata_read(struct fwu_metadata *p_metadata) - - #ifdef BL1_BUILD - static enum fwu_agent_error_t metadata_write( -- struct fwu_metadata *p_metadata) -+ struct fwu_metadata *p_metadata, uint8_t replica_num) - { - int ret; -+ uint32_t replica_offset = 0; - -- FWU_LOG_MSG("%s: enter: flash addr = %u, size = %d\n\r", __func__, -- FWU_METADATA_REPLICA_1_OFFSET, sizeof(struct fwu_metadata)); -+ FWU_LOG_MSG("%s: enter\n\r", __func__); - - if (!p_metadata) { - return FWU_AGENT_ERROR; - } - -- ret = FWU_METADATA_FLASH_DEV.EraseSector(FWU_METADATA_REPLICA_1_OFFSET); -- if (ret != ARM_DRIVER_OK) { -- return FWU_AGENT_ERROR; -- } -- -- ret = FWU_METADATA_FLASH_DEV.ProgramData(FWU_METADATA_REPLICA_1_OFFSET, -- p_metadata, sizeof(struct fwu_metadata)); -- if (ret < 0 || ret != sizeof(struct fwu_metadata)) { -+ if (replica_num == 1) { -+ replica_offset = FWU_METADATA_REPLICA_1_OFFSET; -+ } else if (replica_num == 2) { -+ replica_offset = FWU_METADATA_REPLICA_2_OFFSET; -+ } else { -+ FWU_LOG_MSG("%s: replica_num must be 1 or 2\n\r", __func__); - return FWU_AGENT_ERROR; - } - - FWU_LOG_MSG("%s: enter: flash addr = %u, size = %d\n\r", __func__, -- FWU_METADATA_REPLICA_2_OFFSET, sizeof(struct fwu_metadata)); -+ replica_offset, sizeof(*p_metadata)); - -- ret = FWU_METADATA_FLASH_DEV.EraseSector(FWU_METADATA_REPLICA_2_OFFSET); -+ -+ ret = FWU_METADATA_FLASH_DEV.EraseSector(replica_offset); - if (ret != ARM_DRIVER_OK) { - return FWU_AGENT_ERROR; - } - -- ret = FWU_METADATA_FLASH_DEV.ProgramData(FWU_METADATA_REPLICA_2_OFFSET, -- p_metadata, sizeof(struct fwu_metadata)); -- if (ret < 0 || ret != sizeof(struct fwu_metadata)) { -+ ret = FWU_METADATA_FLASH_DEV.ProgramData(replica_offset, -+ p_metadata, sizeof(*p_metadata)); -+ if (ret < 0 || ret != sizeof(*p_metadata)) { - return FWU_AGENT_ERROR; - } - -@@ -503,7 +525,7 @@ static enum fwu_agent_error_t metadata_write( - } - #else - static enum fwu_agent_error_t metadata_write( -- struct fwu_metadata *p_metadata) -+ struct fwu_metadata *p_metadata, uint8_t replica_num) - { - uuid_t metadata_uuid = FWU_METADATA_TYPE_UUID; - partition_entry_t *part; -@@ -513,7 +535,15 @@ static enum fwu_agent_error_t metadata_write( - return FWU_AGENT_ERROR; - } - -- part = get_partition_entry_by_type(&metadata_uuid); -+ if (replica_num == 1) { -+ part = get_partition_entry_by_type(&metadata_uuid); -+ } else if (replica_num == 2) { -+ part = get_partition_replica_by_type(&metadata_uuid); -+ } else { -+ FWU_LOG_MSG("%s: replica_num must be 1 or 2\n\r", __func__); -+ return FWU_AGENT_ERROR; -+ } -+ - if (!part) { - FWU_LOG_MSG("%s: FWU metadata partition not found\n\r", __func__); - return FWU_AGENT_ERROR; -@@ -533,32 +563,51 @@ static enum fwu_agent_error_t metadata_write( - return FWU_AGENT_ERROR; - } - -- part = get_partition_replica_by_type(&metadata_uuid); -- if (!part) { -- FWU_LOG_MSG("%s: FWU metadata replica partition not found\n\r", __func__); -- return FWU_AGENT_ERROR; -- } -+ FWU_LOG_MSG("%s: success: active = %u, previous = %d\n\r", __func__, -+ p_metadata->active_index, p_metadata->previous_active_index); -+ return FWU_AGENT_SUCCESS; -+} -+#endif - -- FWU_LOG_MSG("%s: enter: flash addr = %u, size = %d\n\r", __func__, -- part->start, sizeof(struct fwu_metadata)); -+static enum fwu_agent_error_t metadata_write_both_replica( -+ struct fwu_metadata *p_metadata) -+{ -+ enum fwu_agent_error_t ret = FWU_AGENT_ERROR; - -- ret = FWU_METADATA_FLASH_DEV.EraseSector(part->start); -- if (ret != ARM_DRIVER_OK) { -- return FWU_AGENT_ERROR; -+ ret = metadata_write(&_metadata, 1); -+ if (ret) { -+ return ret; - } - -- ret = FWU_METADATA_FLASH_DEV.ProgramData(part->start, -- p_metadata, sizeof(struct fwu_metadata)); -- if (ret < 0 || ret != sizeof(struct fwu_metadata)) { -- return FWU_AGENT_ERROR; -+ ret = metadata_write(&_metadata, 2); -+ if (ret) { -+ return ret; - } - -- FWU_LOG_MSG("%s: success: active = %u, previous = %d\n\r", __func__, -- p_metadata->active_index, p_metadata->previous_active_index); - return FWU_AGENT_SUCCESS; - } --#endif - -+enum fwu_agent_error_t fwu_metadata_check_and_correct_integrity(void) -+{ -+ enum fwu_agent_error_t ret_replica_1 = FWU_AGENT_ERROR; -+ enum fwu_agent_error_t ret_replica_2 = FWU_AGENT_ERROR; -+ -+ /* Check integrity of both metadata replica */ -+ ret_replica_1 = metadata_read(&_metadata, 1); -+ ret_replica_2 = metadata_read(&_metadata, 2); -+ -+ if (ret_replica_1 != FWU_AGENT_SUCCESS && ret_replica_2 != FWU_AGENT_SUCCESS) { -+ return FWU_AGENT_ERROR; -+ } else if (ret_replica_1 == FWU_AGENT_SUCCESS && ret_replica_2 != FWU_AGENT_SUCCESS) { -+ metadata_read(&_metadata, 1); -+ metadata_write(&_metadata, 2); -+ } else if (ret_replica_1 != FWU_AGENT_SUCCESS && ret_replica_2 == FWU_AGENT_SUCCESS) { -+ metadata_read(&_metadata, 2); -+ metadata_write(&_metadata, 1); -+ } -+ -+ return FWU_AGENT_SUCCESS; -+} - - enum fwu_agent_error_t fwu_metadata_init(void) - { -@@ -617,8 +666,8 @@ enum fwu_agent_error_t fwu_metadata_provision(void) - * had a firmware data?. If yes, then don't initialize - * metadata - */ -- metadata_read(&_metadata); -- if(_metadata.active_index < 2 || _metadata.previous_active_index <2){ -+ metadata_read(&_metadata, 1); -+ if(_metadata.active_index < 2 || _metadata.previous_active_index < 2){ - if(_metadata.active_index ^ _metadata.previous_active_index) - return FWU_AGENT_SUCCESS; - } -@@ -652,13 +701,13 @@ enum fwu_agent_error_t fwu_metadata_provision(void) - _metadata.crc_32 = crc32((uint8_t *)&_metadata.version, - sizeof(struct fwu_metadata) - sizeof(uint32_t)); - -- ret = metadata_write(&_metadata); -+ ret = metadata_write_both_replica(&_metadata); - if (ret) { - return ret; - } - -- memset(&_metadata, 0, sizeof(struct fwu_metadata)); -- ret = metadata_read(&_metadata); -+ memset(&_metadata, 0, sizeof(_metadata)); -+ ret = metadata_read(&_metadata, 1); - if (ret) { - return ret; - } -@@ -825,7 +874,7 @@ static enum fwu_agent_error_t flash_full_capsule( - metadata->crc_32 = crc32((uint8_t *)&metadata->version, - sizeof(struct fwu_metadata) - sizeof(uint32_t)); - -- ret = metadata_write(metadata); -+ ret = metadata_write_both_replica(metadata); - if (ret) { - return ret; - } -@@ -852,7 +901,7 @@ enum fwu_agent_error_t corstone1000_fwu_flash_image(void) - - Select_Write_Mode_For_Shared_Flash(); - -- if (metadata_read(&_metadata)) { -+ if (metadata_read(&_metadata, 1)) { - ret = FWU_AGENT_ERROR; - goto out; - } -@@ -938,7 +987,7 @@ static enum fwu_agent_error_t accept_full_capsule( - metadata->crc_32 = crc32((uint8_t *)&metadata->version, - sizeof(struct fwu_metadata) - sizeof(uint32_t)); - -- ret = metadata_write(metadata); -+ ret = metadata_write_both_replica(metadata); - if (ret) { - return ret; - } -@@ -1034,7 +1083,7 @@ static enum fwu_agent_error_t fwu_select_previous( - metadata->crc_32 = crc32((uint8_t *)&metadata->version, - sizeof(struct fwu_metadata) - sizeof(uint32_t)); - -- ret = metadata_write(metadata); -+ ret = metadata_write_both_replica(metadata); - if (ret) { - return ret; - } -@@ -1064,7 +1113,7 @@ void bl1_get_active_bl2_image(uint32_t *offset) - FWU_ASSERT(0); - } - -- if (metadata_read(&_metadata)) { -+ if (metadata_read(&_metadata, 1)) { - FWU_ASSERT(0); - } - -@@ -1203,9 +1252,17 @@ enum fwu_agent_error_t corstone1000_fwu_host_ack(void) - return FWU_AGENT_ERROR; - } - -+ /* This cannot be added to the fwu_metadata_init() because that function is -+ * called before the logging is enabled by TF-M. */ -+ ret = fwu_metadata_check_and_correct_integrity(); -+ if (ret = FWU_AGENT_SUCCESS) { -+ FWU_LOG_MSG("fwu_metadata_check_and_correct_integrity failed\r\n"); -+ return ret; -+ } -+ - Select_Write_Mode_For_Shared_Flash(); - -- if (metadata_read(&_metadata)) { -+ if (metadata_read(&_metadata, 1)) { - ret = FWU_AGENT_ERROR; - goto out; - } -@@ -1315,7 +1372,7 @@ void host_acknowledgement_timer_to_reset(void) - FWU_ASSERT(0); - } - -- if (metadata_read(&_metadata)) { -+ if (metadata_read(&_metadata, 1)) { - FWU_ASSERT(0); - } - -diff --git a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.h b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.h -index 701f20558..78e104277 100644 ---- a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.h -+++ b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.h -@@ -70,4 +70,11 @@ enum fwu_nv_counter_index_t { - enum fwu_agent_error_t fwu_stage_nv_counter(enum fwu_nv_counter_index_t index, - uint32_t img_security_cnt); - -+/* -+ * Check if both metadata replica is valid by calculating and comparing crc32. -+ * If one of the replica is corrupted then update it with the valid replica. -+ * If both of the replicas are corrupted then the correction is not possible. -+ */ -+enum fwu_agent_error_t fwu_metadata_check_and_correct_integrity(void); -+ - #endif /* FWU_AGENT_H */ --- -2.25.1 - diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0021-platform-corstone1000-add-unique-guid-for-mps3.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0021-platform-corstone1000-add-unique-guid-for-mps3.patch deleted file mode 100644 index b153b8da..00000000 --- a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0021-platform-corstone1000-add-unique-guid-for-mps3.patch +++ /dev/null @@ -1,41 +0,0 @@ -From a32e7195a4fc1c9d890f9e22a795443d01dc1e8f Mon Sep 17 00:00:00 2001 -From: Anusmita Dutta Mazumder -Date: Tue, 2 Apr 2024 13:04:56 +0000 -Subject: [PATCH 03/10] platform: corstone1000: add unique guid for mps3 - -This patch sets unique GUID for Corstone1000 FVP and MPS3 - -Upstream-Status: Inappropriate [Redesign of Capsule update interface is required] -Signed-off-by: Anusmita Dutta Mazumder ---- - .../target/arm/corstone1000/fw_update_agent/fwu_agent.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c -index 003ab9faf8..5768df19b8 100644 ---- a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c -+++ b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c -@@ -113,13 +113,19 @@ enum fwu_agent_state_t { - }; - - struct efi_guid full_capsule_image_guid = { -+#if PLATFORM_IS_FVP - .time_low = 0x989f3a4e, - .time_mid = 0x46e0, - .time_hi_and_version = 0x4cd0, - .clock_seq_and_node = {0x98, 0x77, 0xa2, 0x5c, 0x70, 0xc0, 0x13, 0x29} -+#else -+ .time_low = 0xdf1865d1, -+ .time_mid = 0x90fb, -+ .time_hi_and_version = 0x4d59, -+ .clock_seq_and_node = {0x9c, 0x38, 0xc9, 0xf2, 0xc1, 0xbb, 0xa8, 0xcc} -+#endif - }; - -- - #define IMAGE_ACCEPTED (1) - #define IMAGE_NOT_ACCEPTED (0) - #define BANK_0 (0) --- -2.25.1 - diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-corstone1000.inc b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-corstone1000.inc index 562abb7c..a6a261e9 100644 --- a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-corstone1000.inc +++ b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-corstone1000.inc @@ -20,33 +20,26 @@ SRC_URI += " \ FILESEXTRAPATHS:prepend := "${THISDIR}/files:" SRC_URI:append:corstone1000 = " \ - file://0001-Platform-Corstone1000-Align-capsule-UEFI-structs.patch \ - file://0002-Platform-Corstone1000-Fix-NV-counter-writing.patch \ - file://0003-Platform-Corstone1000-Enable-firewall-in-FVP.patch \ - file://0004-Platform-CS1000-Increase-ITS-max-asset-size.patch \ - file://0005-Platform-CS1000-Increase-RSE_COMMS-buffer-size.patch \ - file://0006-Platform-CS1000-Increase-buffers-for-EFI-vars.patch \ - file://0007-Plaform-Corstone1000-Switch-to-metadata-v2.patch \ - file://0008-Platform-CS1000-Increase-flash-PS-area-size.patch \ - file://0009-corstone1000-Remove-reset-after-capsule-update.patch \ - file://0010-platform-CS1000-Add-multicore-support-for-FVP.patch \ - file://0011-Platform-CS1000-Fix-Bank-offsets.patch \ - file://0012-Platform-CS1000-Increase-BL2-partition-size.patch \ - file://0013-CC312-ADAC-Add-PSA_WANT_ALG_SHA_256-definition.patch \ - file://0014-Platform-CS1000-Add-crypto-configs-for-ADAC.patch \ - file://0015-Platform-CS1000-Fix-platform-name-in-logs.patch \ - file://0017-Platform-CS1000-Remove-unused-BL1-files.patch \ - file://0018-Platform-CS1000-Remove-duplicated-metadata-write.patch \ - file://0019-Platform-CS1000-Fix-compiler-switch-in-BL1.patch \ - file://0020-Platform-CS1000-Validate-both-metadata-replicas.patch \ - file://0021-platform-corstone1000-add-unique-guid-for-mps3.patch \ - file://0022-CC312-alignment-of-cc312-differences.patch \ + file://0001-Platform-Corstone1000-Enable-firewall-in-FVP.patch \ + file://0002-Platform-CS1000-Increase-ITS-max-asset-size.patch \ + file://0003-Platform-CS1000-Increase-RSE_COMMS-buffer-size.patch \ + file://0004-Platform-CS1000-Increase-buffers-for-EFI-vars.patch \ + file://0005-Platform-CS1000-Increase-flash-PS-area-size.patch \ + file://0006-platform-CS1000-Add-multicore-support-for-FVP.patch \ + file://0007-Platform-CS1000-Fix-Bank-offsets.patch \ + file://0008-Platform-CS1000-Increase-BL2-partition-size.patch \ + file://0009-CC312-ADAC-Add-PSA_WANT_ALG_SHA_256-definition.patch \ + file://0010-Platform-CS1000-Add-crypto-configs-for-ADAC.patch \ + file://0011-Platform-CS1000-Fix-platform-name-in-logs.patch \ + file://0012-Platform-CS1000-Remove-unused-BL1-files.patch \ + file://0013-Platform-CS1000-Fix-compiler-switch-in-BL1.patch \ + file://0014-CC312-alignment-of-cc312-differences.patch \ + file://0015-Platform-corstone1000-Allow-FWU-calls-in-RSE-COMMS.patch \ + file://0016-FWU-Make-platform-specific-TFM_FWU_BOOTLOADER_LIB-se.patch \ + file://0017-Platform-CS1000-Enable-FWU-partition.patch \ + file://0018-Platform-Corstone1000-Implement-Bootloader-Abstracti.patch \ + file://0019-Platform-Corstone1000-Increase-buffer-sizes.patch \ file://0023-Platform-CS1000-Remove-duplicate-configuration-parameters.patch \ - file://0024-Platform-corstone1000-Allow-FWU-calls-in-RSE-COMMS.patch \ - file://0025-FWU-Make-platform-specific-TFM_FWU_BOOTLOADER_LIB-se.patch \ - file://0026-Platform-CS1000-Enable-FWU-partition.patch \ - file://0027-Platform-Corstone1000-Implement-Bootloader-Abstracti.patch \ - file://0028-Platform-Corstone1000-Increase-buffer-sizes.patch \ " FILESEXTRAPATHS:prepend:corstone1000-mps3 := "${THISDIR}/files/corstone1000/psa-adac:" From patchwork Wed Jul 30 11:53:24 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harsimran Singh Tungal X-Patchwork-Id: 67736 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1FE7FC87FD3 for ; Wed, 30 Jul 2025 11:54:11 +0000 (UTC) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.web11.33478.1753876440759178432 for ; Wed, 30 Jul 2025 04:54:01 -0700 Authentication-Results: mx.groups.io; dkim=none (message not signed); spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: harsimransingh.tungal@arm.com) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 54FDE2573; Wed, 30 Jul 2025 04:53:52 -0700 (PDT) Received: from e132995.cambridge.arm.com (e132995.arm.com [10.1.25.25]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 6B8D83F66E; Wed, 30 Jul 2025 04:53:59 -0700 (PDT) From: Harsimran Singh Tungal To: meta-arm@lists.yoctoproject.org Cc: Abdellatif El Khlifi , Harsimran Singh Tungal Subject: [PATCH 10/13] arm-bsp/u-boot: corstone1000: Add PSA Firmware Update support (DEN0118 v1.0A) Date: Wed, 30 Jul 2025 12:53:24 +0100 Message-Id: <20250730115327.3671160-11-harsimransingh.tungal@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250730115327.3671160-1-harsimransingh.tungal@arm.com> References: <20250730115327.3671160-1-harsimransingh.tungal@arm.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Wed, 30 Jul 2025 11:54:11 -0000 X-Groupsio-URL: https://lists.yoctoproject.org/g/meta-arm/message/6647 From: Abdellatif El Khlifi Add PSA FWU support on U-Boot v2025.04 Introduce Platform Security Architecture (PSA) Firmware Update (FWU) support to U-Boot v2025.04 on the Corstone-1000 reference design. This implements the Arm DEN0118 v1.0A specification and provides a generic, upstreamable FWU framework for reuse across other Arm platforms. Design overview: Client/Runner: U-Boot parses the capsule and executes the FWU state machine. Update agent: Secure world handles flash writes and metadata updates. Key features: - Capsule-based firmware updates with support for multiple payloads - On-disk capsule handling (ESP-based update) - Optional image acceptance at ExitBootServices() - ESRT (EFI System Resource Table) support - FFA_MEM_SHARE and FFA_MEM_RECLAIM ABI support - FWU enabled for the Corstone-1000 platform [1]: Platform Security Firmware Update for the A-profile Arm Architecture, https://developer.arm.com/documentation/den0118/latest/ Signed-off-by: Abdellatif El Khlifi Signed-off-by: Harsimran Singh Tungal --- .../conf/machine/include/corstone1000.inc | 4 +- .../u-boot/u-boot-corstone1000.inc | 83 +- ...mccc-add-support-for-SMCCCv1.2-x0-x1.patch | 198 -- ...-pointer-check-to-the-uclass-driver-.patch | 64 + ...d-introduce-uuid_str_to_le_bin-funct.patch | 115 - ...02-arm_ffa-Add-FFA_MEM_SHARE-support.patch | 598 +++++ ...d-introduce-testcase-for-uuid_str_to.patch | 91 - ...-arm_ffa-Add-FFA_MEM_RECLAIM-support.patch | 232 ++ ...5-arm_ffa-introduce-Arm-FF-A-support.patch | 2129 ----------------- ...Replace-the-emulator-error-log-with-.patch | 43 + ...v15-arm_ffa-introduce-armffa-command.patch | 433 ---- ...Improve-the-readability-of-clearing-.patch | 128 + ...m_ffa-introduce-sandbox-FF-A-support.patch | 1311 ---------- ...-sandbox-Add-FFA_MEM_SHARE-emulation.patch | 129 + ...-introduce-sandbox-test-cases-for-UC.patch | 338 --- ..._ffa-sandbox-Add-FFA_MEM_SHARE-tests.patch | 101 + ...-introduce-armffa-command-Sandbox-te.patch | 91 - ...andbox-Add-FFA_MEM_RECLAIM-emulation.patch | 89 + ...-efi-introduce-FF-A-MM-communication.patch | 446 ---- ...fa-sandbox-Add-FFA_MEM_RECLAIM-tests.patch | 68 + ...-efi-corstone1000-enable-MM-communic.patch | 29 - ..._arm_psa-Initialize-the-update-agent.patch | 439 ++++ ...000-fwu-introduce-EFI-capsule-update.patch | 406 ---- ...-the-FWU-directory-through-get_image.patch | 894 +++++++ ...000-fix-unrecognized-filesystem-type.patch | 28 - .../0012-fwu_arm_psa-Add-staging-ABIs.patch | 722 ++++++ ...one1000-remove-guid-check-from-corst.patch | 50 - ...rm_psa-Add-set_image-and-get_image_i.patch | 111 + ..._arm_psa-Keep-the-FMP-payload-header.patch | 34 + ...ate-ESRT-table-if-EFI_ESRT-config-op.patch | 34 - ...-add-get_image_info-for-corstone1000.patch | 120 - ...rm_psa-Skip-accepting-the-payload-af.patch | 46 + ...ull-pointer-exception-with-get_image.patch | 59 - ...wu_arm_psa-Disable-trial-state-handl.patch | 71 + ...017-arm-corstone1000-add-mmc-for-fvp.patch | 97 - ...arm_psa-Add-FWU-acceptance-mechanism.patch | 310 +++ ...ne1000-add-compressed-kernel-support.patch | 31 - .../0018-fwu_arm_psa-Add-ESRT-support.patch | 219 ++ .../0019-arm-corstone1000-esrt-support.patch | 222 -- ...ExitBootService-notification-handler.patch | 54 + ...ne1000-enable-distro-booting-command.patch | 25 - ...ule-Add-runtime-capsule-flags-checks.patch | 67 + ...tone1000-add-fwu-metadata-store-info.patch | 39 - ..._psa-corstone1000-Enable-FWU-support.patch | 228 ++ ...tone1000-Perform-bank-logic-when-rea.patch | 143 ++ ...data-make-sure-structures-are-packed.patch | 47 - .../0023-corstone1000-add-boot-index.patch | 39 - ...tone1000-Notify-SE-Proxy-SP-on-ExitB.patch | 104 + ...adjust-boot-bank-and-kernel-location.patch | 33 - ...tone1000-Set-Boot0001-for-on-disk-FW.patch | 59 + ...add-nvmxip-fwu-mdata-and-gpt-options.patch | 72 - .../0026-nvmxip-move-header-to-include.patch | 39 - ...00-set-kernel_addr-based-on-boot_idx.patch | 132 - ...-corstone1000-boot-index-from-active.patch | 38 - .../0029-corstone1000-enable-PSCI-reset.patch | 28 - ...030-Enable-EFI-set-get-time-services.patch | 30 - ...tone1000-detect-inflated-kernel-size.patch | 26 - ...ne1000-ESRT-add-unique-firmware-GUID.patch | 44 - ...-to-remove-non-compliant-nodes-and-p.patch | 134 -- ...-Call-the-EVT_FT_FIXUP-event-handler.patch | 53 - ...e1000-purge-U-Boot-specific-DT-nodes.patch | 48 - ...00-add-signature-device-tree-overlay.patch | 28 - ...-enable-authenticated-capsule-config.patch | 25 - ...roduce-EFI-authenticated-capsule-upd.patch | 73 - ...nables-ondisk-capsule-update-feature.patch | 33 - ...-runtime-capsule-update-flags-checks.patch | 56 - .../0041-scatter-gather-flag-workaround.patch | 39 - ...rstone1000-enable-virtio-net-support.patch | 94 - ...i-Fix-bind_smccc_features-psci-check.patch | 57 - ...000-set-unique-GUID-for-fvp-and-mps3.patch | 57 - ...-efi-corstone1000-fwu-update-RPC-ABI.patch | 75 - ...ne1000-Change-MMCOMM-buffer-location.patch | 47 - ...one1000-dts-add-external-system-node.patch | 34 - ...corstone1000-Enable-UEFI-Secure-boot.patch | 28 - ...dd-secondary-cores-cpu-nodes-for-FVP.patch | 63 - .../0050-fwu-Use-metadata-v2.patch | 105 - ...rstone1000-purge-remoteproc-dts-node.patch | 34 - .../0052-reserve-memory-for-se-comm.patch | 46 - 78 files changed, 4982 insertions(+), 8007 deletions(-) delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0001-FF-A-v15-arm64-smccc-add-support-for-SMCCCv1.2-x0-x1.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0001-arm_ffa-Add-NULL-pointer-check-to-the-uclass-driver-.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0002-FF-A-v15-lib-uuid-introduce-uuid_str_to_le_bin-funct.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0002-arm_ffa-Add-FFA_MEM_SHARE-support.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0003-FF-A-v15-lib-uuid-introduce-testcase-for-uuid_str_to.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0003-arm_ffa-Add-FFA_MEM_RECLAIM-support.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0004-FF-A-v15-arm_ffa-introduce-Arm-FF-A-support.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0004-arm_ffa-sandbox-Replace-the-emulator-error-log-with-.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0005-FF-A-v15-arm_ffa-introduce-armffa-command.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0005-arm_ffa-sandbox-Improve-the-readability-of-clearing-.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0006-FF-A-v15-arm_ffa-introduce-sandbox-FF-A-support.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0006-arm_ffa-sandbox-Add-FFA_MEM_SHARE-emulation.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0007-FF-A-v15-arm_ffa-introduce-sandbox-test-cases-for-UC.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0007-arm_ffa-sandbox-Add-FFA_MEM_SHARE-tests.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0008-FF-A-v15-arm_ffa-introduce-armffa-command-Sandbox-te.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0008-arm_ffa-sandbox-Add-FFA_MEM_RECLAIM-emulation.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0009-FF-A-v15-arm_ffa-efi-introduce-FF-A-MM-communication.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0009-arm_ffa-sandbox-Add-FFA_MEM_RECLAIM-tests.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0010-FF-A-v15-arm_ffa-efi-corstone1000-enable-MM-communic.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0010-fwu_arm_psa-Initialize-the-update-agent.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0011-efi-corstone1000-fwu-introduce-EFI-capsule-update.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0011-fwu_arm_psa-Read-the-FWU-directory-through-get_image.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0012-arm-corstone1000-fix-unrecognized-filesystem-type.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0012-fwu_arm_psa-Add-staging-ABIs.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0013-efi_loader-corstone1000-remove-guid-check-from-corst.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0013-efi_loader-fwu_arm_psa-Add-set_image-and-get_image_i.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0014-efi_loader-fwu_arm_psa-Keep-the-FMP-payload-header.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0014-efi_loader-populate-ESRT-table-if-EFI_ESRT-config-op.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0015-efi_firmware-add-get_image_info-for-corstone1000.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0015-efi_loader-fwu_arm_psa-Skip-accepting-the-payload-af.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0016-efi_loader-fix-null-pointer-exception-with-get_image.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0016-efi_loader-fwu-fwu_arm_psa-Disable-trial-state-handl.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0017-arm-corstone1000-add-mmc-for-fvp.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0017-fwu_arm_psa-Add-FWU-acceptance-mechanism.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0018-corstone1000-add-compressed-kernel-support.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0018-fwu_arm_psa-Add-ESRT-support.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0019-arm-corstone1000-esrt-support.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0019-fwu_arm_psa-Add-ExitBootService-notification-handler.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0020-corstone1000-enable-distro-booting-command.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0020-efi_loader-capsule-Add-runtime-capsule-flags-checks.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0021-corstone1000-add-fwu-metadata-store-info.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0021-fwu_arm_psa-corstone1000-Enable-FWU-support.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0022-fwu_arm_psa-corstone1000-Perform-bank-logic-when-rea.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0022-fwu_metadata-make-sure-structures-are-packed.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0023-corstone1000-add-boot-index.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0023-fwu_arm_psa-corstone1000-Notify-SE-Proxy-SP-on-ExitB.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0024-corstone1000-adjust-boot-bank-and-kernel-location.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0024-fwu_arm_psa-corstone1000-Set-Boot0001-for-on-disk-FW.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0025-corstone1000-add-nvmxip-fwu-mdata-and-gpt-options.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0026-nvmxip-move-header-to-include.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0027-corstone1000-set-kernel_addr-based-on-boot_idx.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0028-corstone1000-boot-index-from-active.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0029-corstone1000-enable-PSCI-reset.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0030-Enable-EFI-set-get-time-services.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0031-corstone1000-detect-inflated-kernel-size.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0032-corstone1000-ESRT-add-unique-firmware-GUID.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0033-dt-Provide-a-way-to-remove-non-compliant-nodes-and-p.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0034-bootefi-Call-the-EVT_FT_FIXUP-event-handler.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0035-corstone1000-purge-U-Boot-specific-DT-nodes.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0036-corstone1000-add-signature-device-tree-overlay.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0037-corstone1000-enable-authenticated-capsule-config.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0038-corstone1000-introduce-EFI-authenticated-capsule-upd.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0039-enables-ondisk-capsule-update-feature.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0040-fix-runtime-capsule-update-flags-checks.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0041-scatter-gather-flag-workaround.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0042-corstone1000-enable-virtio-net-support.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0043-firmware-psci-Fix-bind_smccc_features-psci-check.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0044-corstone1000-set-unique-GUID-for-fvp-and-mps3.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0045-efi-corstone1000-fwu-update-RPC-ABI.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0046-Corstone1000-Change-MMCOMM-buffer-location.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0047-corstone1000-dts-add-external-system-node.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0048-corstone1000-Enable-UEFI-Secure-boot.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0049-corstone1000-Add-secondary-cores-cpu-nodes-for-FVP.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0050-fwu-Use-metadata-v2.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0051-corstone1000-purge-remoteproc-dts-node.patch delete mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0052-reserve-memory-for-se-comm.patch diff --git a/meta-arm-bsp/conf/machine/include/corstone1000.inc b/meta-arm-bsp/conf/machine/include/corstone1000.inc index ecaea64d..af077083 100644 --- a/meta-arm-bsp/conf/machine/include/corstone1000.inc +++ b/meta-arm-bsp/conf/machine/include/corstone1000.inc @@ -23,8 +23,8 @@ TS_SP_SE_PROXY_CONFIG = "corstone1000" # Include smm-gateway and se-proxy SPs into optee-os binary MACHINE_FEATURES += "ts-smm-gateway ts-se-proxy" -# u-boot -PREFERRED_VERSION_u-boot ?= "2023.07%" +# U-Boot +PREFERRED_VERSION_u-boot ?= "2025.04%" MACHINE_FEATURES += "efi" EFI_PROVIDER ?= "grub-efi" diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot-corstone1000.inc b/meta-arm-bsp/recipes-bsp/u-boot/u-boot-corstone1000.inc index bb9da10d..e19034f7 100644 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot-corstone1000.inc +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot-corstone1000.inc @@ -15,70 +15,41 @@ UBOOT_EXTLINUX = "0" SYSROOT_DIRS:append = " /boot" +# FWU patches SRC_URI:append = " \ - file://0001-FF-A-v15-arm64-smccc-add-support-for-SMCCCv1.2-x0-x1.patch \ - file://0002-FF-A-v15-lib-uuid-introduce-uuid_str_to_le_bin-funct.patch \ - file://0003-FF-A-v15-lib-uuid-introduce-testcase-for-uuid_str_to.patch \ - file://0004-FF-A-v15-arm_ffa-introduce-Arm-FF-A-support.patch \ - file://0005-FF-A-v15-arm_ffa-introduce-armffa-command.patch \ - file://0006-FF-A-v15-arm_ffa-introduce-sandbox-FF-A-support.patch \ - file://0007-FF-A-v15-arm_ffa-introduce-sandbox-test-cases-for-UC.patch \ - file://0008-FF-A-v15-arm_ffa-introduce-armffa-command-Sandbox-te.patch \ - file://0009-FF-A-v15-arm_ffa-efi-introduce-FF-A-MM-communication.patch \ - file://0010-FF-A-v15-arm_ffa-efi-corstone1000-enable-MM-communic.patch \ - file://0011-efi-corstone1000-fwu-introduce-EFI-capsule-update.patch \ - file://0012-arm-corstone1000-fix-unrecognized-filesystem-type.patch \ - file://0013-efi_loader-corstone1000-remove-guid-check-from-corst.patch \ - file://0014-efi_loader-populate-ESRT-table-if-EFI_ESRT-config-op.patch \ - file://0015-efi_firmware-add-get_image_info-for-corstone1000.patch \ - file://0016-efi_loader-fix-null-pointer-exception-with-get_image.patch \ - file://0017-arm-corstone1000-add-mmc-for-fvp.patch \ - file://0018-corstone1000-add-compressed-kernel-support.patch \ - file://0019-arm-corstone1000-esrt-support.patch \ - file://0020-corstone1000-enable-distro-booting-command.patch \ - file://0021-corstone1000-add-fwu-metadata-store-info.patch \ - file://0022-fwu_metadata-make-sure-structures-are-packed.patch \ - file://0023-corstone1000-add-boot-index.patch \ - file://0024-corstone1000-adjust-boot-bank-and-kernel-location.patch \ - file://0025-corstone1000-add-nvmxip-fwu-mdata-and-gpt-options.patch \ - file://0026-nvmxip-move-header-to-include.patch \ - file://0027-corstone1000-set-kernel_addr-based-on-boot_idx.patch \ - file://0028-corstone1000-boot-index-from-active.patch \ - file://0029-corstone1000-enable-PSCI-reset.patch \ - file://0030-Enable-EFI-set-get-time-services.patch \ - file://0031-corstone1000-detect-inflated-kernel-size.patch \ - file://0032-corstone1000-ESRT-add-unique-firmware-GUID.patch \ - file://0033-dt-Provide-a-way-to-remove-non-compliant-nodes-and-p.patch \ - file://0034-bootefi-Call-the-EVT_FT_FIXUP-event-handler.patch \ - file://0035-corstone1000-purge-U-Boot-specific-DT-nodes.patch \ - file://0036-corstone1000-add-signature-device-tree-overlay.patch \ - file://0037-corstone1000-enable-authenticated-capsule-config.patch \ - file://0038-corstone1000-introduce-EFI-authenticated-capsule-upd.patch \ - file://0039-enables-ondisk-capsule-update-feature.patch \ - file://0040-fix-runtime-capsule-update-flags-checks.patch \ - file://0041-scatter-gather-flag-workaround.patch \ - file://0042-corstone1000-enable-virtio-net-support.patch \ - file://0043-firmware-psci-Fix-bind_smccc_features-psci-check.patch \ - file://0044-corstone1000-set-unique-GUID-for-fvp-and-mps3.patch \ - file://0045-efi-corstone1000-fwu-update-RPC-ABI.patch \ - file://0046-Corstone1000-Change-MMCOMM-buffer-location.patch \ - file://0047-corstone1000-dts-add-external-system-node.patch \ - file://0048-corstone1000-Enable-UEFI-Secure-boot.patch \ - file://0049-corstone1000-Add-secondary-cores-cpu-nodes-for-FVP.patch \ - file://0050-fwu-Use-metadata-v2.patch \ - ${@bb.utils.contains('MACHINE_FEATURES', 'corstone1000-extsys', \ - '', 'file://0051-corstone1000-purge-remoteproc-dts-node.patch' , d)} \ - file://0052-reserve-memory-for-se-comm.patch \ + file://0001-arm_ffa-Add-NULL-pointer-check-to-the-uclass-driver-.patch \ + file://0002-arm_ffa-Add-FFA_MEM_SHARE-support.patch \ + file://0003-arm_ffa-Add-FFA_MEM_RECLAIM-support.patch \ + file://0004-arm_ffa-sandbox-Replace-the-emulator-error-log-with-.patch \ + file://0005-arm_ffa-sandbox-Improve-the-readability-of-clearing-.patch \ + file://0006-arm_ffa-sandbox-Add-FFA_MEM_SHARE-emulation.patch \ + file://0007-arm_ffa-sandbox-Add-FFA_MEM_SHARE-tests.patch \ + file://0008-arm_ffa-sandbox-Add-FFA_MEM_RECLAIM-emulation.patch \ + file://0009-arm_ffa-sandbox-Add-FFA_MEM_RECLAIM-tests.patch \ + file://0010-fwu_arm_psa-Initialize-the-update-agent.patch \ + file://0011-fwu_arm_psa-Read-the-FWU-directory-through-get_image.patch \ + file://0012-fwu_arm_psa-Add-staging-ABIs.patch \ + file://0013-efi_loader-fwu_arm_psa-Add-set_image-and-get_image_i.patch \ + file://0014-efi_loader-fwu_arm_psa-Keep-the-FMP-payload-header.patch \ + file://0015-efi_loader-fwu_arm_psa-Skip-accepting-the-payload-af.patch \ + file://0016-efi_loader-fwu-fwu_arm_psa-Disable-trial-state-handl.patch \ + file://0017-fwu_arm_psa-Add-FWU-acceptance-mechanism.patch \ + file://0018-fwu_arm_psa-Add-ESRT-support.patch \ + file://0019-fwu_arm_psa-Add-ExitBootService-notification-handler.patch \ + file://0020-efi_loader-capsule-Add-runtime-capsule-flags-checks.patch \ + file://0021-fwu_arm_psa-corstone1000-Enable-FWU-support.patch \ + file://0022-fwu_arm_psa-corstone1000-Perform-bank-logic-when-rea.patch \ + file://0023-fwu_arm_psa-corstone1000-Notify-SE-Proxy-SP-on-ExitB.patch \ + file://0024-fwu_arm_psa-corstone1000-Set-Boot0001-for-on-disk-FW.patch \ " do_configure:append() { - openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=CRT/ -keyout ${B}/CRT.key -out ${B}/CRT.crt -nodes -days 365 - cert-to-efi-sig-list ${B}/CRT.crt ${B}/corstone1000_defconfig/CRT.esl + openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=CRT/ -keyout ${B}/CRT.key -out ${B}/corstone1000_defconfig/CRT.crt -nodes -days 365 } FILES:${PN} += "/corstone1000_capsule_*" do_install:append() { - install -D -p -m 0644 ${B}/CRT.crt ${D}/corstone1000_capsule_cert.crt + install -D -p -m 0644 ${B}/corstone1000_defconfig/CRT.crt ${D}/corstone1000_capsule_cert.crt install -D -p -m 0644 ${B}/CRT.key ${D}/corstone1000_capsule_key.key } diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0001-FF-A-v15-arm64-smccc-add-support-for-SMCCCv1.2-x0-x1.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0001-FF-A-v15-arm64-smccc-add-support-for-SMCCCv1.2-x0-x1.patch deleted file mode 100644 index 0e467a85..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0001-FF-A-v15-arm64-smccc-add-support-for-SMCCCv1.2-x0-x1.patch +++ /dev/null @@ -1,198 +0,0 @@ -From cc651db9a1370e697fd2525ce58b81ff7e112474 Mon Sep 17 00:00:00 2001 -From: Abdellatif El Khlifi -Date: Fri, 29 Jul 2022 13:06:19 +0100 -Subject: [PATCH] FF-A v15: arm64: smccc: add support for SMCCCv1.2 x0-x17 - registers - -add support for x0-x17 registers used by the SMC calls - -In SMCCC v1.2 [1] arguments are passed in registers x1-x17. -Results are returned in x0-x17. - -This work is inspired from the following kernel commit: - -arm64: smccc: Add support for SMCCCv1.2 extended input/output registers - -[1]: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token= - -Signed-off-by: Abdellatif El Khlifi -Reviewed-by: Ilias Apalodimas -Reviewed-by: Jens Wiklander -Reviewed-by: Simon Glass -Cc: Tom Rini -Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20230713132847.176000-1-abdellatif.elkhlifi@arm.com/] ---- - arch/arm/cpu/armv8/smccc-call.S | 57 ++++++++++++++++++++++++++++++++- - arch/arm/lib/asm-offsets.c | 16 +++++++++ - include/linux/arm-smccc.h | 45 ++++++++++++++++++++++++++ - 3 files changed, 117 insertions(+), 1 deletion(-) - -diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S -index dc92b28777..93f66d3366 100644 ---- a/arch/arm/cpu/armv8/smccc-call.S -+++ b/arch/arm/cpu/armv8/smccc-call.S -@@ -1,7 +1,11 @@ - /* SPDX-License-Identifier: GPL-2.0 */ - /* - * Copyright (c) 2015, Linaro Limited -- */ -+ * Copyright 2022-2023 Arm Limited and/or its affiliates -+ * -+ * Authors: -+ * Abdellatif El Khlifi -+*/ - #include - #include - #include -@@ -45,3 +49,54 @@ ENDPROC(__arm_smccc_smc) - ENTRY(__arm_smccc_hvc) - SMCCC hvc - ENDPROC(__arm_smccc_hvc) -+ -+#ifdef CONFIG_ARM64 -+ -+ .macro SMCCC_1_2 instr -+ /* Save `res` and free a GPR that won't be clobbered */ -+ stp x1, x19, [sp, #-16]! -+ -+ /* Ensure `args` won't be clobbered while loading regs in next step */ -+ mov x19, x0 -+ -+ /* Load the registers x0 - x17 from the struct arm_smccc_1_2_regs */ -+ ldp x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS] -+ ldp x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS] -+ ldp x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS] -+ ldp x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS] -+ ldp x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS] -+ ldp x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS] -+ ldp x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS] -+ ldp x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS] -+ ldp x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS] -+ -+ \instr #0 -+ -+ /* Load the `res` from the stack */ -+ ldr x19, [sp] -+ -+ /* Store the registers x0 - x17 into the result structure */ -+ stp x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS] -+ stp x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS] -+ stp x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS] -+ stp x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS] -+ stp x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS] -+ stp x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS] -+ stp x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS] -+ stp x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS] -+ stp x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS] -+ -+ /* Restore original x19 */ -+ ldp xzr, x19, [sp], #16 -+ ret -+ .endm -+ -+/* -+ * void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args, -+ * struct arm_smccc_1_2_regs *res); -+ */ -+ENTRY(arm_smccc_1_2_smc) -+ SMCCC_1_2 smc -+ENDPROC(arm_smccc_1_2_smc) -+ -+#endif -diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c -index 6de0ce9152..181a8ac4c2 100644 ---- a/arch/arm/lib/asm-offsets.c -+++ b/arch/arm/lib/asm-offsets.c -@@ -9,6 +9,11 @@ - * generate asm statements containing #defines, - * compile this file to assembler, and then extract the - * #defines from the assembly-language output. -+ * -+ * Copyright 2022-2023 Arm Limited and/or its affiliates -+ * -+ * Authors: -+ * Abdellatif El Khlifi - */ - - #include -@@ -90,6 +95,17 @@ int main(void) - DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2)); - DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id)); - DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state)); -+#ifdef CONFIG_ARM64 -+ DEFINE(ARM_SMCCC_1_2_REGS_X0_OFFS, offsetof(struct arm_smccc_1_2_regs, a0)); -+ DEFINE(ARM_SMCCC_1_2_REGS_X2_OFFS, offsetof(struct arm_smccc_1_2_regs, a2)); -+ DEFINE(ARM_SMCCC_1_2_REGS_X4_OFFS, offsetof(struct arm_smccc_1_2_regs, a4)); -+ DEFINE(ARM_SMCCC_1_2_REGS_X6_OFFS, offsetof(struct arm_smccc_1_2_regs, a6)); -+ DEFINE(ARM_SMCCC_1_2_REGS_X8_OFFS, offsetof(struct arm_smccc_1_2_regs, a8)); -+ DEFINE(ARM_SMCCC_1_2_REGS_X10_OFFS, offsetof(struct arm_smccc_1_2_regs, a10)); -+ DEFINE(ARM_SMCCC_1_2_REGS_X12_OFFS, offsetof(struct arm_smccc_1_2_regs, a12)); -+ DEFINE(ARM_SMCCC_1_2_REGS_X14_OFFS, offsetof(struct arm_smccc_1_2_regs, a14)); -+ DEFINE(ARM_SMCCC_1_2_REGS_X16_OFFS, offsetof(struct arm_smccc_1_2_regs, a16)); -+#endif - #endif - - return 0; -diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h -index e1d09884a1..f44e9e8f93 100644 ---- a/include/linux/arm-smccc.h -+++ b/include/linux/arm-smccc.h -@@ -1,6 +1,10 @@ - /* SPDX-License-Identifier: GPL-2.0 */ - /* - * Copyright (c) 2015, Linaro Limited -+ * Copyright 2022-2023 Arm Limited and/or its affiliates -+ * -+ * Authors: -+ * Abdellatif El Khlifi - */ - #ifndef __LINUX_ARM_SMCCC_H - #define __LINUX_ARM_SMCCC_H -@@ -70,6 +74,47 @@ struct arm_smccc_res { - unsigned long a3; - }; - -+#ifdef CONFIG_ARM64 -+/** -+ * struct arm_smccc_1_2_regs - Arguments for or Results from SMC call -+ * @a0-a17 argument values from registers 0 to 17 -+ */ -+struct arm_smccc_1_2_regs { -+ unsigned long a0; -+ unsigned long a1; -+ unsigned long a2; -+ unsigned long a3; -+ unsigned long a4; -+ unsigned long a5; -+ unsigned long a6; -+ unsigned long a7; -+ unsigned long a8; -+ unsigned long a9; -+ unsigned long a10; -+ unsigned long a11; -+ unsigned long a12; -+ unsigned long a13; -+ unsigned long a14; -+ unsigned long a15; -+ unsigned long a16; -+ unsigned long a17; -+}; -+ -+/** -+ * arm_smccc_1_2_smc() - make SMC calls -+ * @args: arguments passed via struct arm_smccc_1_2_regs -+ * @res: result values via struct arm_smccc_1_2_regs -+ * -+ * This function is used to make SMC calls following SMC Calling Convention -+ * v1.2 or above. The content of the supplied param are copied from the -+ * structure to registers prior to the SMC instruction. The return values -+ * are updated with the content from registers on return from the SMC -+ * instruction. -+ */ -+asmlinkage void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args, -+ struct arm_smccc_1_2_regs *res); -+#endif -+ - /** - * struct arm_smccc_quirk - Contains quirk information - * @id: quirk identification diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0001-arm_ffa-Add-NULL-pointer-check-to-the-uclass-driver-.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0001-arm_ffa-Add-NULL-pointer-check-to-the-uclass-driver-.patch new file mode 100644 index 00000000..a2a6f348 --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0001-arm_ffa-Add-NULL-pointer-check-to-the-uclass-driver-.patch @@ -0,0 +1,64 @@ +From 9b001c37347aa8fa5ecbd68f12714a12c74b6ea5 Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Wed, 30 Oct 2024 14:10:43 +0000 +Subject: [PATCH 01/36] arm_ffa: Add NULL pointer check to the uclass driver + operations + +Add NULL pointer check for ops + +The device driver can miss defining an operations structure. +So, ffa_get_ops() can return NULL. +This commit adds checks for ops in the uclass driver operations +and an error is returned when ops is NULL. + +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20250702152528.1180414-1-abdellatif.elkhlifi@arm.com/] +--- + drivers/firmware/arm-ffa/arm-ffa-uclass.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c +index 96c64964bb7..f8d231204db 100644 +--- a/drivers/firmware/arm-ffa/arm-ffa-uclass.c ++++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0+ + /* +- * Copyright 2022-2023 Arm Limited and/or its affiliates ++ * Copyright 2022-2023, 2025 Arm Limited and/or its affiliates + * + * Authors: + * Abdellatif El Khlifi +@@ -954,6 +954,9 @@ int ffa_partition_info_get(struct udevice *dev, const char *uuid_str, + { + struct ffa_bus_ops *ops = ffa_get_ops(dev); + ++ if (!ops) ++ return -EINVAL; ++ + if (!ops->partition_info_get) + return -ENOSYS; + +@@ -979,6 +982,9 @@ int ffa_sync_send_receive(struct udevice *dev, u16 dst_part_id, + { + struct ffa_bus_ops *ops = ffa_get_ops(dev); + ++ if (!ops) ++ return -EINVAL; ++ + if (!ops->sync_send_receive) + return -ENOSYS; + +@@ -1000,6 +1006,9 @@ int ffa_rxtx_unmap(struct udevice *dev) + { + struct ffa_bus_ops *ops = ffa_get_ops(dev); + ++ if (!ops) ++ return -EINVAL; ++ + if (!ops->rxtx_unmap) + return -ENOSYS; + +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0002-FF-A-v15-lib-uuid-introduce-uuid_str_to_le_bin-funct.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0002-FF-A-v15-lib-uuid-introduce-uuid_str_to_le_bin-funct.patch deleted file mode 100644 index 2fc5caaf..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0002-FF-A-v15-lib-uuid-introduce-uuid_str_to_le_bin-funct.patch +++ /dev/null @@ -1,115 +0,0 @@ -From 4c1eaa36a882f9f921c3bc3b1352bbb04a939c4f Mon Sep 17 00:00:00 2001 -From: Abdellatif El Khlifi -Date: Thu, 4 Aug 2022 16:46:47 +0100 -Subject: [PATCH] FF-A v15: lib: uuid: introduce uuid_str_to_le_bin function - -convert UUID string to little endian binary data - -Signed-off-by: Abdellatif El Khlifi -Reviewed-by: Simon Glass -Cc: Tom Rini -Cc: Ilias Apalodimas -Cc: Jens Wiklander -Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20230713132847.176000-1-abdellatif.elkhlifi@arm.com/] ---- - include/uuid.h | 15 +++++++++++++++ - lib/uuid.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 63 insertions(+) - -diff --git a/include/uuid.h b/include/uuid.h -index 4a4883d3b5..89b93e642b 100644 ---- a/include/uuid.h -+++ b/include/uuid.h -@@ -2,6 +2,10 @@ - /* - * Copyright (C) 2014 Samsung Electronics - * Przemyslaw Marczak -+ * Copyright 2022-2023 Arm Limited and/or its affiliates -+ * -+ * Authors: -+ * Abdellatif El Khlifi - */ - #ifndef __UUID_H__ - #define __UUID_H__ -@@ -44,4 +48,15 @@ int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin); - const char *uuid_guid_get_str(const unsigned char *guid_bin); - void gen_rand_uuid(unsigned char *uuid_bin); - void gen_rand_uuid_str(char *uuid_str, int str_format); -+ -+/** -+ * uuid_str_to_le_bin() - Convert string UUID to little endian binary data. -+ * @uuid_str: pointer to UUID string -+ * @uuid_bin: pointer to allocated array for little endian output [16B] -+ * Return: -+ * uuid_bin filled with little endian UUID data -+ * On success 0 is returned. Otherwise, failure code. -+ */ -+int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin); -+ - #endif -diff --git a/lib/uuid.c b/lib/uuid.c -index 96e1af3c8b..45f325d964 100644 ---- a/lib/uuid.c -+++ b/lib/uuid.c -@@ -1,6 +1,10 @@ - // SPDX-License-Identifier: GPL-2.0+ - /* - * Copyright 2011 Calxeda, Inc. -+ * Copyright 2022-2023 Arm Limited and/or its affiliates -+ * -+ * Authors: -+ * Abdellatif El Khlifi - */ - - #include -@@ -354,6 +358,50 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin, - return 0; - } - -+/** -+ * uuid_str_to_le_bin() - Convert string UUID to little endian binary data. -+ * @uuid_str: pointer to UUID string -+ * @uuid_bin: pointer to allocated array for little endian output [16B] -+ * -+ * UUID string is 36 characters (36 bytes): -+ * -+ * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -+ * -+ * where x is a hexadecimal character. Fields are separated by '-'s. -+ * When converting to a little endian binary UUID, the string fields are reversed. -+ * -+ * Return: -+ * -+ * uuid_bin filled with little endian UUID data -+ * On success 0 is returned. Otherwise, failure code. -+ */ -+int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin) -+{ -+ u16 tmp16; -+ u32 tmp32; -+ u64 tmp64; -+ -+ if (!uuid_str_valid(uuid_str) || !uuid_bin) -+ return -EINVAL; -+ -+ tmp32 = cpu_to_le32(hextoul(uuid_str, NULL)); -+ memcpy(uuid_bin, &tmp32, 4); -+ -+ tmp16 = cpu_to_le16(hextoul(uuid_str + 9, NULL)); -+ memcpy(uuid_bin + 4, &tmp16, 2); -+ -+ tmp16 = cpu_to_le16(hextoul(uuid_str + 14, NULL)); -+ memcpy(uuid_bin + 6, &tmp16, 2); -+ -+ tmp16 = cpu_to_le16(hextoul(uuid_str + 19, NULL)); -+ memcpy(uuid_bin + 8, &tmp16, 2); -+ -+ tmp64 = cpu_to_le64(simple_strtoull(uuid_str + 24, NULL, 16)); -+ memcpy(uuid_bin + 10, &tmp64, 6); -+ -+ return 0; -+} -+ - /* - * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID. - * diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0002-arm_ffa-Add-FFA_MEM_SHARE-support.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0002-arm_ffa-Add-FFA_MEM_SHARE-support.patch new file mode 100644 index 00000000..68578e32 --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0002-arm_ffa-Add-FFA_MEM_SHARE-support.patch @@ -0,0 +1,598 @@ +From 7d4fbdc82bb004a4a7852016f94b56a82a9c3e7e Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Tue, 29 Oct 2024 17:22:35 +0000 +Subject: [PATCH 02/36] arm_ffa: Add FFA_MEM_SHARE support + +Add to the FF-A bus FFA_MEM_SHARE ABI + +The FFA_MEM_SHARE is a memory management ABI described in the FF-A v1.0 +specification [1]. + +This ABI starts a transaction to grant access to a memory region +to one or more Borrowers (aka Secure Partitions or endpoints). + +This work is based on the implementation in Linux kernel [2]. + +[1]: https://developer.arm.com/documentation/den0077/a/?lang=en +[2]: commit cc2195fe536c28e192df5d07e6dd277af36814b4 + Files: drivers/firmware/arm_ffa/driver.c , include/linux/arm_ffa.h + +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20250702152528.1180414-1-abdellatif.elkhlifi@arm.com/] +--- + doc/arch/arm64.ffa.rst | 2 + + drivers/firmware/arm-ffa/arm-ffa-uclass.c | 210 ++++++++++++++++++++++ + drivers/firmware/arm-ffa/arm-ffa.c | 3 +- + include/arm_ffa.h | 86 ++++++++- + include/arm_ffa_priv.h | 142 ++++++++++++++- + 5 files changed, 439 insertions(+), 4 deletions(-) + +diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst +index f966f8ba6af..3eec735d741 100644 +--- a/doc/arch/arm64.ffa.rst ++++ b/doc/arch/arm64.ffa.rst +@@ -185,6 +185,7 @@ The following features are provided: + - FFA_INTERRUPT + - FFA_MSG_SEND_DIRECT_REQ + - FFA_MSG_SEND_DIRECT_RESP ++ - FFA_MEM_SHARE + + - Support for the 64-bit version of the following ABIs: + +@@ -203,6 +204,7 @@ The following features are provided: + - ffa_partition_info_get + - ffa_sync_send_receive + - ffa_rxtx_unmap ++ - ffa_memory_share + + - FF-A bus discovery makes sure FF-A framework is responsive and compatible + with the driver +diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c +index f8d231204db..2ba0b925fa6 100644 +--- a/drivers/firmware/arm-ffa/arm-ffa-uclass.c ++++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c +@@ -95,6 +95,20 @@ static struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = { + "DENIED: Buffer pair already registered", + }, + }, ++ [FFA_ID_TO_ERRMAP_ID(FFA_MEM_SHARE)] = { ++ { ++ [ABORTED] = ++ "ABORTED: Failure in the transmission of fragments or in time slicing", ++ [INVALID_PARAMETERS] = ++ "INVALID_PARAMETERS: Validation failed for the Memory Transaction or the Endpoint memory access descriptor", ++ [NO_MEMORY] = ++ "NO_MEMORY: Insufficient memory to complete this operation", ++ [BUSY] = ++ "BUSY: The TX buffer is busy", ++ [DENIED] = ++ "DENIED: Memory region ownership, permission, access or attributes error", ++ }, ++ }, + }; + + /** +@@ -929,6 +943,177 @@ int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id, + return ffa_to_std_errno(ffa_errno); + } + ++/** ++ * ffa_mem_desc_offset() - helper for descriptors offset calculation ++ * @count: An integer defining the number of Endpoint memory access descriptors ++ * ++ * Calculate the offset of the Endpoint memory access descriptor and ++ * the Composite memory region descriptor. ++ * ++ * Return: ++ * ++ * The descriptor offset. ++ */ ++static inline u32 ffa_mem_desc_offset(int count) ++{ ++ u32 offset = count * sizeof(struct ffa_mem_region_attributes); ++ ++ offset += sizeof(struct ffa_mem_region); ++ ++ return offset; ++} ++ ++/** ++ * ffa_setup_and_transmit() - set up the memory and transmit data using FF-A ++ * @dev: The FF-A bus device ++ * @func_id: An integer identifying the function ++ * @buffer: A pointer to the data to be transmitted (FF-A TX buffer) ++ * @args: A pointer to a structure containing additional user arguments ++ * ++ * Setup the memory transaction related to the access to a specified ++ * memory region. ++ * Currently we support FFA_MEM_SHARE only. ++ * ++ * Return: ++ * ++ * 0 on success. . Otherwise, failure ++ */ ++static int ffa_setup_and_transmit(struct udevice *dev, u32 func_id, ++ void *buffer, struct ffa_mem_ops_args *args) ++{ ++ ffa_value_t res = {0}; ++ int ffa_errno; ++ u32 composite_offset; ++ u32 total_length; ++ struct ffa_mem_region *mem_region = buffer; ++ struct ffa_composite_mem_region *composite; ++ struct ffa_mem_region_addr_range *constituent; ++ struct ffa_mem_region_attributes *ep_mem_access; ++ u32 idx; ++ struct ffa_priv *uc_priv; ++ ++ uc_priv = dev_get_uclass_priv(dev); ++ ++ mem_region->tag = args->tag; ++ mem_region->flags = args->flags; ++ mem_region->sender_id = uc_priv->id; ++ ++ /* ++ * These attributes are only valid for FFA_MEM_SHARE. ++ * They are not valid for FFA_MEM_LEND (no implemented). ++ */ ++ if (func_id == FFA_MEM_SHARE) ++ mem_region->attributes = FFA_MEM_NORMAL | FFA_MEM_WRITE_BACK ++ | FFA_MEM_INNER_SHAREABLE; ++ else ++ mem_region->attributes = 0; ++ ++ mem_region->handle = 0; ++ mem_region->ep_count = args->nattrs; ++ mem_region->reserved1 = 0; ++ mem_region->reserved2 = 0; ++ ++ ep_mem_access = buffer + ffa_mem_desc_offset(0); ++ ++ composite_offset = ffa_mem_desc_offset(args->nattrs); ++ ++ /* Multiple borrowers supported */ ++ for (idx = 0; idx < args->nattrs; idx++, ep_mem_access++) { ++ ep_mem_access->receiver = args->attrs[idx].receiver; ++ ep_mem_access->attrs = args->attrs[idx].attrs; ++ ep_mem_access->composite_off = composite_offset; ++ ep_mem_access->flag = 0; ++ ep_mem_access->reserved = 0; ++ } ++ ++ /* Only one Composite and one Constituent memory region supported */ ++ composite = buffer + composite_offset; ++ composite->total_pg_cnt = args->pg_cnt; ++ composite->addr_range_cnt = FFA_MEM_CONSTITUENTS; ++ composite->reserved = 0; ++ ++ constituent = &composite->constituents[0]; ++ constituent->address = map_to_sysmem(args->address); ++ constituent->pg_cnt = args->pg_cnt; ++ constituent->reserved = 0; ++ ++ total_length = composite_offset + sizeof(*composite) + ++ sizeof(*constituent); ++ ++ /* ++ * Note: Time slicing is not supported. ++ * It's only available to EL1 and S-EL1 endpoints. ++ */ ++ ++ invoke_ffa_fn((ffa_value_t){ ++ .a0 = FFA_SMC_32(func_id), ++ .a1 = total_length, ++ .a2 = total_length, ++ .a3 = 0, /* the TX buffer is used */ ++ .a4 = 0, /* the TX buffer is used */ ++ }, ++ &res ++ ); ++ ++ if (res.a0 != FFA_SMC_32(FFA_SUCCESS)) { ++ ffa_errno = res.a2; ++ ffa_print_error_log(func_id, ffa_errno); ++ return ffa_to_std_errno(ffa_errno); ++ } ++ ++ args->g_handle = PACK_HANDLE(res.a2, res.a3); ++ return 0; ++} ++ ++/** ++ * ffa_memory_ops() - wrapper for the memory management ABIs ++ * @dev: The FF-A bus device ++ * @func_id: An integer identifying the function ++ * @args: A pointer to a structure containing additional user arguments ++ * ++ * Verify the use of the TX buffer then call ffa_setup_and_transmit(). ++ * Currently we support FFA_MEM_SHARE only. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++static int ffa_memory_ops(struct udevice *dev, u32 func_id, ++ struct ffa_mem_ops_args *args) ++{ ++ void *buffer; ++ struct ffa_priv *uc_priv = dev_get_uclass_priv(dev); ++ ++ if (!args->use_txbuf) { ++ log_err("only TX buffer supported\n"); ++ return -EPROTONOSUPPORT; ++ } ++ ++ buffer = uc_priv->pair.txbuf; ++ ++ if (!buffer || !args->attrs || !args->address) ++ return -EINVAL; ++ ++ return ffa_setup_and_transmit(dev, func_id, buffer, args); ++} ++ ++/** ++ * ffa_memory_share_hdlr() - FFA_MEM_SHARE handler function ++ * @dev: The FF-A bus device ++ * @args: A pointer to a structure containing additional user arguments ++ * ++ * Implement FFA_MEM_SHARE FF-A function ++ * to grant access to a memory region to one or more Borrowers. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++int ffa_memory_share_hdlr(struct udevice *dev, struct ffa_mem_ops_args *args) ++{ ++ return ffa_memory_ops(dev, FFA_MEM_SHARE, args); ++} ++ + /* FF-A driver operations (used by clients for communicating with FF-A)*/ + + /** +@@ -1015,6 +1200,31 @@ int ffa_rxtx_unmap(struct udevice *dev) + return ops->rxtx_unmap(dev); + } + ++/** ++ * ffa_memory_share() - FFA_MEM_SHARE driver operation ++ * @dev: The FF-A bus device ++ * @args: A pointer to a structure containing additional user arguments ++ * ++ * Driver operation for FFA_MEM_SHARE. ++ * Please see ffa_memory_share_hdlr() description for more details. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++int ffa_memory_share(struct udevice *dev, struct ffa_mem_ops_args *args) ++{ ++ struct ffa_bus_ops *ops = ffa_get_ops(dev); ++ ++ if (!ops || !args) ++ return -EINVAL; ++ ++ if (!ops->memory_share) ++ return -ENOSYS; ++ ++ return ops->memory_share(dev, args); ++} ++ + /** + * ffa_do_probe() - probing FF-A framework + * @dev: the FF-A bus device (arm_ffa) +diff --git a/drivers/firmware/arm-ffa/arm-ffa.c b/drivers/firmware/arm-ffa/arm-ffa.c +index 94e6105cb38..df904cae412 100644 +--- a/drivers/firmware/arm-ffa/arm-ffa.c ++++ b/drivers/firmware/arm-ffa/arm-ffa.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0+ + /* +- * Copyright 2022-2023 Arm Limited and/or its affiliates ++ * Copyright 2022-2023, 2025 Arm Limited and/or its affiliates + * + * Authors: + * Abdellatif El Khlifi +@@ -84,6 +84,7 @@ static const struct ffa_bus_ops ffa_ops = { + .partition_info_get = ffa_get_partitions_info_hdlr, + .sync_send_receive = ffa_msg_send_direct_req_hdlr, + .rxtx_unmap = ffa_unmap_rxtx_buffers_hdlr, ++ .memory_share = ffa_memory_share_hdlr, + }; + + /* Registering the FF-A driver as an SMCCC feature driver */ +diff --git a/include/arm_ffa.h b/include/arm_ffa.h +index db9b1be995e..4d2ea7fd1a6 100644 +--- a/include/arm_ffa.h ++++ b/include/arm_ffa.h +@@ -1,6 +1,6 @@ + /* SPDX-License-Identifier: GPL-2.0+ */ + /* +- * Copyright 2022-2023 Arm Limited and/or its affiliates ++ * Copyright 2022-2023, 2025 Arm Limited and/or its affiliates + * + * Authors: + * Abdellatif El Khlifi +@@ -81,11 +81,74 @@ struct ffa_send_direct_data { + + struct udevice; + ++/** ++ * struct ffa_mem_region_attributes - Endpoint memory access descriptor ++ * ++ * The data structure used in memory management transactions to create an ++ * association between an endpoint, memory access permissions and a composite ++ * memory region description. ++ * ++ * For more details, please refer to Table 5.16 and Table 5.15 in the FF-A ++ * specification v1.0. ++ * ++ * This structure was taken from Linux. ++ */ ++struct ffa_mem_region_attributes { ++ /* The ID of the VM to which the memory is being given or shared. */ ++ u16 receiver; ++ /* ++ * The permissions with which the memory region should be mapped in the ++ * receiver's page table. ++ */ ++#define FFA_MEM_EXEC BIT(3) ++#define FFA_MEM_NO_EXEC BIT(2) ++#define FFA_MEM_RW BIT(1) ++#define FFA_MEM_RO BIT(0) ++ u8 attrs; ++ /* ++ * Flags used during FFA_MEM_RETRIEVE_REQ and FFA_MEM_RETRIEVE_RESP ++ * for memory regions with multiple borrowers. ++ */ ++#define FFA_MEM_RETRIEVE_SELF_BORROWER BIT(0) ++ u8 flag; ++ /* ++ * Offset in bytes from the start of the outer `ffa_memory_region` to ++ * an `struct ffa_mem_region_addr_range`. ++ */ ++ u32 composite_off; ++ u64 reserved; ++}; ++ ++/** ++ * struct ffa_mem_ops_args - User arguments to the memory management ABIs ++ * @use_txbuf: Whether to use the TX buffer for the memory transaction ++ * @nattrs: Number of the borrowers ++ * @flags: Memory transaction flags ++ * @tag: The tag associated with the transaction ++ * @g_handle: Globally unique Handle to identify the memory region (out) ++ * @address: Virtual address of the memory region ++ * @attrs: Memory access permissions of each borrower ++ * ++ * The structured filled by the user and passed to the memory ++ * management ABIs (e.g: FFA_MEM_SHARE) ++ */ ++struct ffa_mem_ops_args { ++ bool use_txbuf; ++ u32 nattrs; ++ u32 flags; ++ u64 tag; ++ u64 g_handle; ++ void *address; ++ u32 pg_cnt; ++ struct ffa_mem_region_attributes *attrs; ++}; ++ + /** + * struct ffa_bus_ops - Operations for FF-A + * @partition_info_get: callback for the FFA_PARTITION_INFO_GET + * @sync_send_receive: callback for the FFA_MSG_SEND_DIRECT_REQ + * @rxtx_unmap: callback for the FFA_RXTX_UNMAP ++ * @memory_share: callback for the FFA_MEM_SHARE + * + * The data structure providing all the operations supported by the driver. + * This structure is EFI runtime resident. +@@ -97,6 +160,7 @@ struct ffa_bus_ops { + struct ffa_send_direct_data *msg, + bool is_smc64); + int (*rxtx_unmap)(struct udevice *dev); ++ int (*memory_share)(struct udevice *dev, struct ffa_mem_ops_args *args); + }; + + #define ffa_get_ops(dev) ((struct ffa_bus_ops *)(dev)->driver->ops) +@@ -196,6 +260,26 @@ int ffa_partition_info_get(struct udevice *dev, const char *uuid_str, + int ffa_get_partitions_info_hdlr(struct udevice *dev, const char *uuid_str, + u32 *sp_count, struct ffa_partition_desc **sp_descs); + ++/** ++ * ffa_memory_share() - FFA_MEM_SHARE driver operation ++ * Please see ffa_memory_share_hdlr() description for more details. ++ */ ++int ffa_memory_share(struct udevice *dev, struct ffa_mem_ops_args *args); ++ ++/** ++ * ffa_memory_share_hdlr() - FFA_MEM_SHARE handler function ++ * @dev: The FF-A bus device ++ * @args: A pointer to a structure containing additional user arguments ++ * ++ * Implement FFA_MEM_SHARE FF-A function ++ * to grant access to a memory region to one or more Borrowers. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++int ffa_memory_share_hdlr(struct udevice *dev, struct ffa_mem_ops_args *args); ++ + struct ffa_priv; + + /** +diff --git a/include/arm_ffa_priv.h b/include/arm_ffa_priv.h +index d564c33c647..a259911d5b9 100644 +--- a/include/arm_ffa_priv.h ++++ b/include/arm_ffa_priv.h +@@ -1,6 +1,6 @@ + /* SPDX-License-Identifier: GPL-2.0+ */ + /* +- * Copyright 2022-2023 Arm Limited and/or its affiliates ++ * Copyright 2022-2023, 2025 Arm Limited and/or its affiliates + * + * Authors: + * Abdellatif El Khlifi +@@ -132,10 +132,11 @@ enum ffa_abis { + FFA_RUN = 0x6d, + FFA_MSG_SEND_DIRECT_REQ = 0x6f, + FFA_MSG_SEND_DIRECT_RESP = 0x70, ++ FFA_MEM_SHARE = 0x73, + + /* To be updated when adding new FFA IDs */ + FFA_FIRST_ID = FFA_ERROR, /* Lowest number ID */ +- FFA_LAST_ID = FFA_MSG_SEND_DIRECT_RESP, /* Highest number ID */ ++ FFA_LAST_ID = FFA_MEM_SHARE, /* Highest number ID */ + }; + + enum ffa_abi_errcode { +@@ -219,6 +220,143 @@ struct ffa_priv { + struct ffa_rxtxpair pair; + }; + ++/* FF-A memory management ABIs data structures */ ++ ++/** ++ * struct ffa_mem_region - Lend, donate or share memory transaction descriptor ++ * ++ * Specifies the data structure that must be used by the Owner/Lender and a ++ * Borrower/Receiver in a transaction to donate, lend or share a memory region. ++ * It specifies the memory region description, properties and other transaction ++ * attributes in an invocation of the following ABIs. ++ * ++ * FFA_MEM_DONATE. ++ * FFA_MEM_LEND. ++ * FFA_MEM_SHARE. ++ * FFA_MEM_RETRIEVE_REQ. ++ * FFA_MEM_RETRIEVE_RESP. ++ * ++ * For more details, please refer to the Table 5.19 in the FF-A specification ++ * v1.0. ++ * ++ * The interpretation of some fields depends on the ABI this structure is used ++ * with. This variance in behavior is also specified in the Table 5.19. ++ * ++ * This structure was taken from Linux and adapted to FF-A v1.0. ++ */ ++struct ffa_mem_region { ++ /* The ID of the VM/owner which originally sent the memory region */ ++ u16 sender_id; ++#define FFA_MEM_NORMAL BIT(5) ++#define FFA_MEM_DEVICE BIT(4) ++ ++#define FFA_MEM_WRITE_BACK (3 << 2) ++#define FFA_MEM_NON_CACHEABLE BIT(2) ++ ++#define FFA_DEV_nGnRnE (0 << 2) ++#define FFA_DEV_nGnRE BIT(2) ++#define FFA_DEV_nGRE (2 << 2) ++#define FFA_DEV_GRE (3 << 2) ++ ++#define FFA_MEM_NON_SHAREABLE (0) ++#define FFA_MEM_OUTER_SHAREABLE (2) ++#define FFA_MEM_INNER_SHAREABLE (3) ++ /* Memory region attributes */ ++ u8 attributes; ++ ++ u8 reserved1; ++ ++/* ++ * Clear memory region contents after unmapping it from the sender and ++ * before mapping it for any receiver. ++ */ ++#define FFA_MEM_CLEAR BIT(0) ++/* ++ * Whether the hypervisor may time slice the memory sharing or retrieval ++ * operation. ++ */ ++#define FFA_TIME_SLICE_ENABLE BIT(1) ++ ++#define FFA_MEM_RETRIEVE_TYPE_IN_RESP (0 << 3) ++#define FFA_MEM_RETRIEVE_TYPE_SHARE BIT(3) ++#define FFA_MEM_RETRIEVE_TYPE_LEND (2 << 3) ++#define FFA_MEM_RETRIEVE_TYPE_DONATE (3 << 3) ++ ++#define FFA_MEM_RETRIEVE_ADDR_ALIGN_HINT BIT(9) ++#define FFA_MEM_RETRIEVE_ADDR_ALIGN(x) ((x) << 5) ++ /* Flags to control behaviour of the transaction. */ ++ u32 flags; ++#define HANDLE_LOW_MASK GENMASK_ULL(31, 0) ++#define HANDLE_HIGH_MASK GENMASK_ULL(63, 32) ++#define HANDLE_LOW(x) ((u32)(FIELD_GET(HANDLE_LOW_MASK, (x)))) ++#define HANDLE_HIGH(x) ((u32)(FIELD_GET(HANDLE_HIGH_MASK, (x)))) ++ ++#define PACK_HANDLE(l, h) \ ++ (FIELD_PREP(HANDLE_LOW_MASK, (l)) | FIELD_PREP(HANDLE_HIGH_MASK, (h))) ++ /* ++ * A globally-unique ID assigned by the hypervisor for a region ++ * of memory being sent between VMs. ++ */ ++ u64 handle; ++ /* ++ * An implementation defined value associated with the receiver and the ++ * memory region. ++ */ ++ u64 tag; ++ ++ u32 reserved2; ++ ++ /* ++ * The number of `ffa_mem_region_attributes` entries included in this ++ * transaction. ++ */ ++ u32 ep_count; ++}; ++ ++/** ++ * struct ffa_mem_region_addr_range - Constituent memory region descriptor ++ * ++ * Each descriptor specifies the base address and size of a virtually or ++ * physically contiguous memory region. ++ * ++ * For more details, please refer to Table 5.14 in the FF-A ++ * specification v1.0. ++ * ++ * This structure was taken from Linux. ++ */ ++struct ffa_mem_region_addr_range { ++ /* The base IPA of the constituent memory region, aligned to 4 kiB */ ++ u64 address; ++ /* The number of 4 kiB pages in the constituent memory region. */ ++ u32 pg_cnt; ++ u32 reserved; ++}; ++ ++/** ++ * struct ffa_composite_mem_region - Composite memory region descriptor ++ * ++ * For more details, please refer to Table 5.13 in the FF-A ++ * specification v1.0. ++ * ++ * This structure was taken from Linux. ++ */ ++struct ffa_composite_mem_region { ++ /* ++ * The total number of 4 kiB pages included in this memory region. This ++ * must be equal to the sum of page counts specified in each ++ * `struct ffa_mem_region_addr_range`. ++ */ ++ u32 total_pg_cnt; ++ /* The number of constituents included in this memory region range */ ++#define FFA_MEM_CONSTITUENTS (1) ++ u32 addr_range_cnt; ++ u64 reserved; ++ /** An array of `addr_range_cnt` memory region constituents. */ ++ struct ffa_mem_region_addr_range constituents[]; ++}; ++ ++/* Functions prototypes */ ++ + /** + * ffa_get_version_hdlr() - FFA_VERSION handler function + * @dev: The FF-A bus device +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0003-FF-A-v15-lib-uuid-introduce-testcase-for-uuid_str_to.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0003-FF-A-v15-lib-uuid-introduce-testcase-for-uuid_str_to.patch deleted file mode 100644 index bec856e1..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0003-FF-A-v15-lib-uuid-introduce-testcase-for-uuid_str_to.patch +++ /dev/null @@ -1,91 +0,0 @@ -From fe51e27e4f0033e9737a1099d0dd06f976a60705 Mon Sep 17 00:00:00 2001 -From: Abdellatif El Khlifi -Date: Mon, 27 Mar 2023 16:24:29 +0100 -Subject: [PATCH] FF-A v15: lib: uuid: introduce testcase for - uuid_str_to_le_bin - -provide a test case - -Signed-off-by: Abdellatif El Khlifi -Reviewed-by: Simon Glass -Cc: Tom Rini -Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20230713132847.176000-1-abdellatif.elkhlifi@arm.com/] ---- - MAINTAINERS | 5 +++++ - test/lib/Makefile | 1 + - test/lib/uuid.c | 41 +++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 47 insertions(+) - create mode 100644 test/lib/uuid.c - -diff --git a/MAINTAINERS b/MAINTAINERS -index 3bf60c4643..a1122afb01 100644 ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -1632,3 +1632,8 @@ S: Maintained - F: arch/arm/dts/ls1021a-twr-u-boot.dtsi - F: drivers/crypto/fsl/ - F: include/fsl_sec.h -+ -+UUID testing -+M: Abdellatif El Khlifi -+S: Maintained -+F: test/lib/uuid.c -diff --git a/test/lib/Makefile b/test/lib/Makefile -index e0bd9e04e8..e75a263e6a 100644 ---- a/test/lib/Makefile -+++ b/test/lib/Makefile -@@ -22,6 +22,7 @@ obj-$(CONFIG_AES) += test_aes.o - obj-$(CONFIG_GETOPT) += getopt.o - obj-$(CONFIG_CRC8) += test_crc8.o - obj-$(CONFIG_UT_LIB_CRYPT) += test_crypt.o -+obj-$(CONFIG_LIB_UUID) += uuid.o - else - obj-$(CONFIG_SANDBOX) += kconfig_spl.o - endif -diff --git a/test/lib/uuid.c b/test/lib/uuid.c -new file mode 100644 -index 0000000000..e24331a136 ---- /dev/null -+++ b/test/lib/uuid.c -@@ -0,0 +1,41 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Functional tests for UCLASS_FFA class -+ * -+ * Copyright 2022-2023 Arm Limited and/or its affiliates -+ * -+ * Authors: -+ * Abdellatif El Khlifi -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+/* test UUID */ -+#define TEST_SVC_UUID "ed32d533-4209-99e6-2d72-cdd998a79cc0" -+ -+#define UUID_SIZE 16 -+ -+/* The UUID binary data (little-endian format) */ -+static const u8 ref_uuid_bin[UUID_SIZE] = { -+ 0x33, 0xd5, 0x32, 0xed, -+ 0x09, 0x42, 0xe6, 0x99, -+ 0x72, 0x2d, 0xc0, 0x9c, -+ 0xa7, 0x98, 0xd9, 0xcd -+}; -+ -+static int lib_test_uuid_to_le(struct unit_test_state *uts) -+{ -+ const char *uuid_str = TEST_SVC_UUID; -+ u8 ret_uuid_bin[UUID_SIZE] = {0}; -+ -+ ut_assertok(uuid_str_to_le_bin(uuid_str, ret_uuid_bin)); -+ ut_asserteq_mem(ref_uuid_bin, ret_uuid_bin, UUID_SIZE); -+ -+ return 0; -+} -+ -+LIB_TEST(lib_test_uuid_to_le, 0); diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0003-arm_ffa-Add-FFA_MEM_RECLAIM-support.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0003-arm_ffa-Add-FFA_MEM_RECLAIM-support.patch new file mode 100644 index 00000000..a1d3e812 --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0003-arm_ffa-Add-FFA_MEM_RECLAIM-support.patch @@ -0,0 +1,232 @@ +From 09d9e3d05845de1c18672e3bcfabb3ef78092653 Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Tue, 29 Oct 2024 17:24:43 +0000 +Subject: [PATCH 03/36] arm_ffa: Add FFA_MEM_RECLAIM support + +Add to the FF-A bus FFA_MEM_RECLAIM ABI + +The FFA_MEM_RECLAIM is a memory management ABI described in the FF-A +v1.0 specification [1]. + +This ABI restores exclusive access to a memory region back to its Owner. + +This work is based on the implementation in Linux [2]. + +[1]: https://developer.arm.com/documentation/den0077/a/?lang=en +[2]: commit cc2195fe536c28e192df5d07e6dd277af36814b4 + File: drivers/firmware/arm_ffa/driver.c + +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20250702152528.1180414-1-abdellatif.elkhlifi@arm.com/] +--- + doc/arch/arm64.ffa.rst | 2 + + drivers/firmware/arm-ffa/arm-ffa-uclass.c | 76 +++++++++++++++++++++++ + drivers/firmware/arm-ffa/arm-ffa.c | 1 + + include/arm_ffa.h | 25 +++++++- + include/arm_ffa_priv.h | 3 +- + 5 files changed, 105 insertions(+), 2 deletions(-) + +diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst +index 3eec735d741..d2c4fb49f79 100644 +--- a/doc/arch/arm64.ffa.rst ++++ b/doc/arch/arm64.ffa.rst +@@ -186,6 +186,7 @@ The following features are provided: + - FFA_MSG_SEND_DIRECT_REQ + - FFA_MSG_SEND_DIRECT_RESP + - FFA_MEM_SHARE ++ - FFA_MEM_RECLAIM + + - Support for the 64-bit version of the following ABIs: + +@@ -205,6 +206,7 @@ The following features are provided: + - ffa_sync_send_receive + - ffa_rxtx_unmap + - ffa_memory_share ++ - ffa_memory_reclaim + + - FF-A bus discovery makes sure FF-A framework is responsive and compatible + with the driver +diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c +index 2ba0b925fa6..597b4e994b4 100644 +--- a/drivers/firmware/arm-ffa/arm-ffa-uclass.c ++++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c +@@ -109,6 +109,18 @@ static struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = { + "DENIED: Memory region ownership, permission, access or attributes error", + }, + }, ++ [FFA_ID_TO_ERRMAP_ID(FFA_MEM_RECLAIM)] = { ++ { ++ [ABORTED] = ++ "ABORTED: ABI invocation failure", ++ [INVALID_PARAMETERS] = ++ "INVALID_PARAMETERS: Invalid handle or flags", ++ [NO_MEMORY] = ++ "NO_MEMORY: Failure to create the Owner's mapping", ++ [DENIED] = ++ "DENIED: Memory region state issue", ++ }, ++ }, + }; + + /** +@@ -1114,6 +1126,44 @@ int ffa_memory_share_hdlr(struct udevice *dev, struct ffa_mem_ops_args *args) + return ffa_memory_ops(dev, FFA_MEM_SHARE, args); + } + ++/** ++ * ffa_memory_reclaim_hdlr() - FFA_MEM_RECLAIM handler function ++ * @dev: The FF-A bus device ++ * @g_handle: The memory region globally unique Handle ++ * @flags: Zero memory and time slicing flags ++ * ++ * Implement FFA_MEM_RECLAIM FF-A function ++ * to restore exclusive access to a memory region back to its Owner. ++ * Note: FFA_MEM_RECLAIM can not be used at EFI runtime because memory that was ++ * lent as per the memory map during boot time can not be reclaimed into the ++ * memory map during runtime. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++int ffa_memory_reclaim_hdlr(struct udevice *dev, u64 g_handle, u32 flags) ++{ ++ ffa_value_t res; ++ int ffa_errno; ++ ++ invoke_ffa_fn((ffa_value_t){ ++ .a0 = FFA_SMC_32(FFA_MEM_RECLAIM), ++ .a1 = HANDLE_LOW(g_handle), .a2 = HANDLE_HIGH(g_handle), ++ .a3 = flags, ++ }, ++ &res ++ ); ++ ++ if (res.a0 != FFA_SMC_32(FFA_SUCCESS)) { ++ ffa_errno = res.a2; ++ ffa_print_error_log(FFA_MEM_RECLAIM, ffa_errno); ++ return ffa_to_std_errno(ffa_errno); ++ } ++ ++ return 0; ++} ++ + /* FF-A driver operations (used by clients for communicating with FF-A)*/ + + /** +@@ -1225,6 +1275,32 @@ int ffa_memory_share(struct udevice *dev, struct ffa_mem_ops_args *args) + return ops->memory_share(dev, args); + } + ++/** ++ * ffa_memory_reclaim() - FFA_MEM_RECLAIM driver operation ++ * @dev: The FF-A bus device ++ * @g_handle: The memory region globally unique Handle ++ * @flags: Zero memory and time slicing flags ++ * ++ * Driver operation for FFA_MEM_RECLAIM. ++ * Please see ffa_memory_reclaim_hdlr() description for more details. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++int ffa_memory_reclaim(struct udevice *dev, u64 g_handle, u32 flags) ++{ ++ struct ffa_bus_ops *ops = ffa_get_ops(dev); ++ ++ if (!ops) ++ return -EINVAL; ++ ++ if (!ops->memory_reclaim) ++ return -ENOSYS; ++ ++ return ops->memory_reclaim(dev, g_handle, flags); ++} ++ + /** + * ffa_do_probe() - probing FF-A framework + * @dev: the FF-A bus device (arm_ffa) +diff --git a/drivers/firmware/arm-ffa/arm-ffa.c b/drivers/firmware/arm-ffa/arm-ffa.c +index df904cae412..de36f5647d2 100644 +--- a/drivers/firmware/arm-ffa/arm-ffa.c ++++ b/drivers/firmware/arm-ffa/arm-ffa.c +@@ -85,6 +85,7 @@ static const struct ffa_bus_ops ffa_ops = { + .sync_send_receive = ffa_msg_send_direct_req_hdlr, + .rxtx_unmap = ffa_unmap_rxtx_buffers_hdlr, + .memory_share = ffa_memory_share_hdlr, ++ .memory_reclaim = ffa_memory_reclaim_hdlr, + }; + + /* Registering the FF-A driver as an SMCCC feature driver */ +diff --git a/include/arm_ffa.h b/include/arm_ffa.h +index 4d2ea7fd1a6..a36f461662c 100644 +--- a/include/arm_ffa.h ++++ b/include/arm_ffa.h +@@ -147,8 +147,9 @@ struct ffa_mem_ops_args { + * struct ffa_bus_ops - Operations for FF-A + * @partition_info_get: callback for the FFA_PARTITION_INFO_GET + * @sync_send_receive: callback for the FFA_MSG_SEND_DIRECT_REQ +- * @rxtx_unmap: callback for the FFA_RXTX_UNMAP ++ * @rxtx_unmap: callback for the FFA_RXTX_UNMAP + * @memory_share: callback for the FFA_MEM_SHARE ++ * @memory_reclaim: callback for the FFA_MEM_RECLAIM + * + * The data structure providing all the operations supported by the driver. + * This structure is EFI runtime resident. +@@ -161,6 +162,7 @@ struct ffa_bus_ops { + bool is_smc64); + int (*rxtx_unmap)(struct udevice *dev); + int (*memory_share)(struct udevice *dev, struct ffa_mem_ops_args *args); ++ int (*memory_reclaim)(struct udevice *dev, u64 g_handle, u32 flags); + }; + + #define ffa_get_ops(dev) ((struct ffa_bus_ops *)(dev)->driver->ops) +@@ -280,6 +282,27 @@ int ffa_memory_share(struct udevice *dev, struct ffa_mem_ops_args *args); + */ + int ffa_memory_share_hdlr(struct udevice *dev, struct ffa_mem_ops_args *args); + ++/** ++ * ffa_memory_reclaim() - FFA_MEM_RECLAIM driver operation ++ * Please see ffa_memory_reclaim_hdlr() description for more details. ++ */ ++int ffa_memory_reclaim(struct udevice *dev, u64 g_handle, u32 flags); ++ ++/** ++ * ffa_memory_reclaim_hdlr() - FFA_MEM_RECLAIM handler function ++ * @dev: The FF-A bus device ++ * @g_handle: The memory region globally unique Handle ++ * @flags: Zero memory and time slicing flags ++ * ++ * Implement FFA_MEM_RECLAIM FF-A function ++ * to restore exclusive access to a memory region back to its Owner. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++int ffa_memory_reclaim_hdlr(struct udevice *dev, u64 g_handle, u32 flags); ++ + struct ffa_priv; + + /** +diff --git a/include/arm_ffa_priv.h b/include/arm_ffa_priv.h +index a259911d5b9..54196199ce3 100644 +--- a/include/arm_ffa_priv.h ++++ b/include/arm_ffa_priv.h +@@ -133,10 +133,11 @@ enum ffa_abis { + FFA_MSG_SEND_DIRECT_REQ = 0x6f, + FFA_MSG_SEND_DIRECT_RESP = 0x70, + FFA_MEM_SHARE = 0x73, ++ FFA_MEM_RECLAIM = 0x77, + + /* To be updated when adding new FFA IDs */ + FFA_FIRST_ID = FFA_ERROR, /* Lowest number ID */ +- FFA_LAST_ID = FFA_MEM_SHARE, /* Highest number ID */ ++ FFA_LAST_ID = FFA_MEM_RECLAIM, /* Highest number ID */ + }; + + enum ffa_abi_errcode { +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0004-FF-A-v15-arm_ffa-introduce-Arm-FF-A-support.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0004-FF-A-v15-arm_ffa-introduce-Arm-FF-A-support.patch deleted file mode 100644 index dcbc5744..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0004-FF-A-v15-arm_ffa-introduce-Arm-FF-A-support.patch +++ /dev/null @@ -1,2129 +0,0 @@ -From d1f0d01f1d863c2b98cc181dfc752f6c71faefaf Mon Sep 17 00:00:00 2001 -From: Abdellatif El Khlifi -Date: Mon, 17 Jul 2023 15:11:43 +0100 -Subject: [PATCH] FF-A v15: arm_ffa: introduce Arm FF-A support - -Add Arm FF-A support implementing Arm Firmware Framework for Armv8-A v1.0 - -The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1] -describes interfaces (ABIs) that standardize communication -between the Secure World and Normal World leveraging TrustZone -technology. - -This driver uses 64-bit registers as per SMCCCv1.2 spec and comes -on top of the SMCCC layer. The driver provides the FF-A ABIs needed for -querying the FF-A framework from the secure world. - -The driver uses SMC32 calling convention which means using the first -32-bit data of the Xn registers. - -All supported ABIs come with their 32-bit version except FFA_RXTX_MAP -which has 64-bit version supported. - -Both 32-bit and 64-bit direct messaging are supported which allows both -32-bit and 64-bit clients to use the FF-A bus. - -FF-A is a discoverable bus and similar to architecture features. -FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed -by the PSCI driver. - -Clients are able to probe then use the FF-A bus by calling the DM class -searching APIs (e.g: uclass_first_device). - -The Secure World is considered as one entity to communicate with -using the FF-A bus. FF-A communication is handled by one device and -one instance (the bus). This FF-A driver takes care of all the -interactions between Normal world and Secure World. - -The driver exports its operations to be used by upper layers. - -Exported operations: - -- ffa_partition_info_get -- ffa_sync_send_receive -- ffa_rxtx_unmap - -Generic FF-A methods are implemented in the Uclass (arm-ffa-uclass.c). -Arm specific methods are implemented in the Arm driver (arm-ffa.c). - -For more details please refer to the driver documentation [2]. - -[1]: https://developer.arm.com/documentation/den0077/latest/ -[2]: doc/arch/arm64.ffa.rst - -Signed-off-by: Abdellatif El Khlifi -Reviewed-by: Simon Glass -Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20230713132847.176000-1-abdellatif.elkhlifi@arm.com/] ---- - MAINTAINERS | 8 + - doc/arch/arm64.ffa.rst | 238 ++++ - doc/arch/index.rst | 1 + - drivers/Makefile | 1 + - drivers/firmware/Kconfig | 1 + - drivers/firmware/arm-ffa/Kconfig | 36 + - drivers/firmware/arm-ffa/Makefile | 8 + - drivers/firmware/arm-ffa/arm-ffa-uclass.c | 1065 +++++++++++++++++ - drivers/firmware/arm-ffa/arm-ffa.c | 104 ++ - .../firmware/arm-ffa/sandbox_arm_ffa_priv.h | 14 + - include/arm_ffa.h | 213 ++++ - include/arm_ffa_priv.h | 246 ++++ - include/dm/uclass-id.h | 6 + - 13 files changed, 1941 insertions(+) - create mode 100644 doc/arch/arm64.ffa.rst - create mode 100644 drivers/firmware/arm-ffa/Kconfig - create mode 100644 drivers/firmware/arm-ffa/Makefile - create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c - create mode 100644 drivers/firmware/arm-ffa/arm-ffa.c - create mode 100644 drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h - create mode 100644 include/arm_ffa.h - create mode 100644 include/arm_ffa_priv.h - -diff --git a/MAINTAINERS b/MAINTAINERS -index a1122afb01..9c5ebf312c 100644 ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -266,6 +266,14 @@ F: drivers/net/cortina_ni.h - F: drivers/net/phy/ca_phy.c - F: configs/cortina_presidio-asic-pnand_defconfig - -+ARM FF-A -+M: Abdellatif El Khlifi -+S: Maintained -+F: doc/arch/arm64.ffa.rst -+F: drivers/firmware/arm-ffa/ -+F: include/arm_ffa.h -+F: include/sandbox_arm_ffa.h -+ - ARM FREESCALE IMX - M: Stefano Babic - M: Fabio Estevam -diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst -new file mode 100644 -index 0000000000..4f817f053c ---- /dev/null -+++ b/doc/arch/arm64.ffa.rst -@@ -0,0 +1,238 @@ -+.. SPDX-License-Identifier: GPL-2.0+ -+ -+Arm FF-A Support -+================ -+ -+Summary -+------- -+ -+FF-A stands for Firmware Framework for Arm A-profile processors. -+ -+FF-A specifies interfaces that enable a pair of software execution environments aka partitions to -+communicate with each other. A partition could be a VM in the Normal or Secure world, an -+application in S-EL0, or a Trusted OS in S-EL1. -+ -+The U-Boot FF-A support (the bus) implements the interfaces to communicate -+with partitions in the Secure world aka Secure partitions (SPs). -+ -+The FF-A support specifically focuses on communicating with SPs that -+isolate portions of EFI runtime services that must run in a protected -+environment which is inaccessible by the Host OS or Hypervisor. -+Examples of such services are set/get variables. -+ -+The FF-A support uses the SMC ABIs defined by the FF-A specification to: -+ -+- Discover the presence of SPs of interest -+- Access an SP's service through communication protocols -+ e.g. EFI MM communication protocol -+ -+At this stage of development only EFI boot-time services are supported. -+Runtime support will be added in future developments. -+ -+The U-Boot FF-A support provides the following parts: -+ -+- A Uclass driver providing generic FF-A methods. -+- An Arm FF-A device driver providing Arm-specific methods and reusing the Uclass methods. -+ -+FF-A and SMC specifications -+------------------------------------------- -+ -+The current implementation of the U-Boot FF-A support relies on -+`FF-A v1.0 specification`_ and uses SMC32 calling convention which -+means using the first 32-bit data of the Xn registers. -+ -+At this stage we only need the FF-A v1.0 features. -+ -+The FF-A support has been tested with OP-TEE which supports SMC32 calling -+convention. -+ -+Hypervisors are supported if they are configured to trap SMC calls. -+ -+The FF-A support uses 64-bit registers as per `SMC Calling Convention v1.2 specification`_. -+ -+Supported hardware -+-------------------------------- -+ -+Aarch64 plaforms -+ -+Configuration -+---------------------- -+ -+CONFIG_ARM_FFA_TRANSPORT -+ Enables the FF-A support. Turn this on if you want to use FF-A -+ communication. -+ When using an Arm 64-bit platform, the Arm FF-A driver will be used. -+ -+FF-A ABIs under the hood -+--------------------------------------- -+ -+Invoking an FF-A ABI involves providing to the secure world/hypervisor the -+expected arguments from the ABI. -+ -+On an Arm 64-bit platform, the ABI arguments are stored in x0 to x7 registers. -+Then, an SMC instruction is executed. -+ -+At the secure side level or hypervisor the ABI is handled at a higher exception -+level and the arguments are read and processed. -+ -+The response is put back through x0 to x7 registers and control is given back -+to the U-Boot Arm FF-A driver (non-secure world). -+ -+The driver reads the response and processes it accordingly. -+ -+This methodology applies to all the FF-A ABIs. -+ -+FF-A bus discovery on Arm 64-bit platforms -+--------------------------------------------- -+ -+When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is considered as -+an architecture feature and discovered using ARM_SMCCC_FEATURES mechanism. -+This discovery mechanism is performed by the PSCI driver. -+ -+The PSCI driver comes with a PSCI device tree node which is the root node for all -+architecture features including FF-A bus. -+ -+:: -+ -+ => dm tree -+ -+ Class Index Probed Driver Name -+ ----------------------------------------------------------- -+ ... -+ firmware 0 [ + ] psci |-- psci -+ ffa 0 [ ] arm_ffa | `-- arm_ffa -+ ... -+ -+The PSCI driver is bound to the PSCI device and when probed it tries to discover -+the architecture features by calling a callback the features drivers provide. -+ -+In case of FF-A, the callback is arm_ffa_is_supported() which tries to discover the -+FF-A framework by querying the FF-A framework version from secure world using -+FFA_VERSION ABI. When discovery is successful, the ARM_SMCCC_FEATURES -+mechanism creates a U-Boot device for the FF-A bus and binds the Arm FF-A driver -+with the device using device_bind_driver(). -+ -+At this stage the FF-A bus is registered with the DM and can be interacted with using -+the DM APIs. -+ -+Clients are able to probe then use the FF-A bus by calling uclass_first_device(). -+Please refer to the armffa command implementation as an example of how to probe -+and interact with the FF-A bus. -+ -+When calling uclass_first_device(), the FF-A driver is probed and ends up calling -+ffa_do_probe() provided by the Uclass which does the following: -+ -+ - saving the FF-A framework version in uc_priv -+ - querying from secure world the u-boot endpoint ID -+ - querying from secure world the supported features of FFA_RXTX_MAP -+ - mapping the RX/TX buffers -+ - querying from secure world all the partitions information -+ -+When one of the above actions fails, probing fails and the driver stays not active -+and can be probed again if needed. -+ -+Requirements for clients -+------------------------------------- -+ -+When using the FF-A bus with EFI, clients must query the SPs they are looking for -+during EFI boot-time mode using the service UUID. -+ -+The RX/TX buffers are only available at EFI boot-time. Querying partitions is -+done at boot time and data is cached for future use. -+ -+RX/TX buffers should be unmapped before EFI runtime mode starts. -+The driver provides a bus operation for that called ffa_rxtx_unmap(). -+ -+The user should call ffa_rxtx_unmap() to unmap the RX/TX buffers when required -+(e.g: at efi_exit_boot_services()). -+ -+The Linux kernel allocates its own RX/TX buffers. To be able to register these kernel buffers -+with secure world, the U-Boot's RX/TX buffers should be unmapped before EFI runtime starts. -+ -+When invoking FF-A direct messaging, clients should specify which ABI protocol -+they want to use (32-bit vs 64-bit). Selecting the protocol means using -+the 32-bit or 64-bit version of FFA_MSG_SEND_DIRECT_{REQ, RESP}. -+The calling convention between U-Boot and the secure world stays the same: SMC32. -+ -+Requirements for user drivers -+------------------------------------- -+ -+Users who want to implement their custom FF-A device driver while reusing the FF-A Uclass can do so -+by implementing their own invoke_ffa_fn() in the user driver. -+ -+The bus driver layer -+------------------------------ -+ -+FF-A support comes on top of the SMCCC layer and is implemented by the FF-A Uclass drivers/firmware/arm-ffa/arm-ffa-uclass.c -+ -+The following features are provided: -+ -+- Support for the 32-bit version of the following ABIs: -+ -+ - FFA_VERSION -+ - FFA_ID_GET -+ - FFA_FEATURES -+ - FFA_PARTITION_INFO_GET -+ - FFA_RXTX_UNMAP -+ - FFA_RX_RELEASE -+ - FFA_RUN -+ - FFA_ERROR -+ - FFA_SUCCESS -+ - FFA_INTERRUPT -+ - FFA_MSG_SEND_DIRECT_REQ -+ - FFA_MSG_SEND_DIRECT_RESP -+ -+- Support for the 64-bit version of the following ABIs: -+ -+ - FFA_RXTX_MAP -+ - FFA_MSG_SEND_DIRECT_REQ -+ - FFA_MSG_SEND_DIRECT_RESP -+ -+- Processing the received data from the secure world/hypervisor and caching it -+ -+- Hiding from upper layers the FF-A protocol and registers details. Upper -+ layers focus on exchanged data, FF-A support takes care of how to transport -+ that to the secure world/hypervisor using FF-A -+ -+- FF-A support provides driver operations to be used by upper layers: -+ -+ - ffa_partition_info_get -+ - ffa_sync_send_receive -+ - ffa_rxtx_unmap -+ -+- FF-A bus discovery makes sure FF-A framework is responsive and compatible -+ with the driver -+ -+- FF-A bus can be compiled and used without EFI -+ -+Example of boot logs with FF-A enabled -+-------------------------------------- -+ -+For example, when using FF-A with Corstone-1000 the logs are as follows: -+ -+:: -+ -+ U-Boot 2023.01 (May 10 2023 - 11:08:07 +0000) corstone1000 aarch64 -+ -+ DRAM: 2 GiB -+ Arm FF-A framework discovery -+ FF-A driver 1.0 -+ FF-A framework 1.0 -+ FF-A versions are compatible -+ ... -+ FF-A driver 1.0 -+ FF-A framework 1.0 -+ FF-A versions are compatible -+ EFI: MM partition ID 0x8003 -+ ... -+ EFI stub: Booting Linux Kernel... -+ ... -+ Linux version 6.1.9-yocto-standard (oe-user@oe-host) (aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.40.202301193 -+ Machine model: ARM Corstone1000 FPGA MPS3 board -+ -+Contributors -+------------ -+ * Abdellatif El Khlifi -+ -+.. _`FF-A v1.0 specification`: https://documentation-service.arm.com/static/5fb7e8a6ca04df4095c1d65e -+.. _`SMC Calling Convention v1.2 specification`: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6 -diff --git a/doc/arch/index.rst b/doc/arch/index.rst -index b8da4b8c8e..2f916f4026 100644 ---- a/doc/arch/index.rst -+++ b/doc/arch/index.rst -@@ -8,6 +8,7 @@ Architecture-specific doc - - arc - arm64 -+ arm64.ffa - m68k - mips - nios2 -diff --git a/drivers/Makefile b/drivers/Makefile -index 29be78a3f2..6094fac50d 100644 ---- a/drivers/Makefile -+++ b/drivers/Makefile -@@ -114,6 +114,7 @@ obj-y += iommu/ - obj-y += smem/ - obj-y += thermal/ - obj-$(CONFIG_TEE) += tee/ -+obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/ - obj-y += axi/ - obj-y += ufs/ - obj-$(CONFIG_W1) += w1/ -diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig -index eae1c8ddc9..8789b1ea14 100644 ---- a/drivers/firmware/Kconfig -+++ b/drivers/firmware/Kconfig -@@ -45,4 +45,5 @@ config ARM_SMCCC_FEATURES - the PSCI driver is always probed and binds dirvers registered to the Arm SMCCC - services if any and reported as supported by the SMCCC firmware. - -+source "drivers/firmware/arm-ffa/Kconfig" - source "drivers/firmware/scmi/Kconfig" -diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig -new file mode 100644 -index 0000000000..9200c8028b ---- /dev/null -+++ b/drivers/firmware/arm-ffa/Kconfig -@@ -0,0 +1,36 @@ -+# SPDX-License-Identifier: GPL-2.0 -+ -+config ARM_FFA_TRANSPORT -+ bool "Enable Arm Firmware Framework for Armv8-A driver" -+ depends on DM && ARM64 -+ select ARM_SMCCC -+ select ARM_SMCCC_FEATURES -+ select LIB_UUID -+ select DEVRES -+ help -+ The Firmware Framework for Arm A-profile processors (FF-A) -+ describes interfaces (ABIs) that standardize communication -+ between the Secure World and Normal World leveraging TrustZone -+ technology. -+ -+ The FF-A support in U-Boot is based on FF-A specification v1.0 and uses SMC32 -+ calling convention. -+ -+ FF-A specification: -+ -+ https://developer.arm.com/documentation/den0077/a/?lang=en -+ -+ In U-Boot FF-A design, FF-A is considered as a discoverable bus. -+ FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed -+ by the PSCI driver. -+ The Secure World is considered as one entity to communicate with -+ using the FF-A bus. -+ FF-A communication is handled by one device and one instance (the bus). -+ The FF-A support on U-Boot takes care of all the interactions between Normal -+ world and Secure World. -+ -+ Generic FF-A methods are implemented in the Uclass (arm-ffa-uclass.c). -+ Arm specific methods are implemented in the Arm driver (arm-ffa.c). -+ -+ For more details about the FF-A support, please refer to doc/arch/arm64.ffa.rst -+ -diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile -new file mode 100644 -index 0000000000..11b1766285 ---- /dev/null -+++ b/drivers/firmware/arm-ffa/Makefile -@@ -0,0 +1,8 @@ -+# SPDX-License-Identifier: GPL-2.0+ -+# -+# Copyright 2022-2023 Arm Limited and/or its affiliates -+# -+# Authors: -+# Abdellatif El Khlifi -+ -+obj-y += arm-ffa-uclass.o arm-ffa.o -diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c -new file mode 100644 -index 0000000000..ffa9d81fa7 ---- /dev/null -+++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c -@@ -0,0 +1,1065 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Copyright 2022-2023 Arm Limited and/or its affiliates -+ * -+ * Authors: -+ * Abdellatif El Khlifi -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+DECLARE_GLOBAL_DATA_PTR; -+ -+/* Error mapping declarations */ -+ -+int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = { -+ [NOT_SUPPORTED] = -EOPNOTSUPP, -+ [INVALID_PARAMETERS] = -EINVAL, -+ [NO_MEMORY] = -ENOMEM, -+ [BUSY] = -EBUSY, -+ [INTERRUPTED] = -EINTR, -+ [DENIED] = -EACCES, -+ [RETRY] = -EAGAIN, -+ [ABORTED] = -ECANCELED, -+}; -+ -+static struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = { -+ [FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = { -+ { -+ [NOT_SUPPORTED] = -+ "NOT_SUPPORTED: A Firmware Framework implementation does not exist", -+ }, -+ }, -+ [FFA_ID_TO_ERRMAP_ID(FFA_ID_GET)] = { -+ { -+ [NOT_SUPPORTED] = -+ "NOT_SUPPORTED: This function is not implemented at this FF-A instance", -+ }, -+ }, -+ [FFA_ID_TO_ERRMAP_ID(FFA_FEATURES)] = { -+ { -+ [NOT_SUPPORTED] = -+ "NOT_SUPPORTED: FFA_RXTX_MAP is not implemented at this FF-A instance", -+ }, -+ }, -+ [FFA_ID_TO_ERRMAP_ID(FFA_PARTITION_INFO_GET)] = { -+ { -+ [NOT_SUPPORTED] = -+ "NOT_SUPPORTED: This function is not implemented at this FF-A instance", -+ [INVALID_PARAMETERS] = -+ "INVALID_PARAMETERS: Unrecognized UUID", -+ [NO_MEMORY] = -+ "NO_MEMORY: Results cannot fit in RX buffer of the caller", -+ [BUSY] = -+ "BUSY: RX buffer of the caller is not free", -+ [DENIED] = -+ "DENIED: Callee is not in a state to handle this request", -+ }, -+ }, -+ [FFA_ID_TO_ERRMAP_ID(FFA_RXTX_UNMAP)] = { -+ { -+ [NOT_SUPPORTED] = -+ "NOT_SUPPORTED: FFA_RXTX_UNMAP is not implemented at this FF-A instance", -+ [INVALID_PARAMETERS] = -+ "INVALID_PARAMETERS: No buffer pair registered on behalf of the caller", -+ }, -+ }, -+ [FFA_ID_TO_ERRMAP_ID(FFA_RX_RELEASE)] = { -+ { -+ [NOT_SUPPORTED] = -+ "NOT_SUPPORTED: FFA_RX_RELEASE is not implemented at this FF-A instance", -+ [DENIED] = -+ "DENIED: Caller did not have ownership of the RX buffer", -+ }, -+ }, -+ [FFA_ID_TO_ERRMAP_ID(FFA_RXTX_MAP)] = { -+ { -+ [NOT_SUPPORTED] = -+ "NOT_SUPPORTED: This function is not implemented at this FF-A instance", -+ [INVALID_PARAMETERS] = -+ "INVALID_PARAMETERS: Field(s) in input parameters incorrectly encoded", -+ [NO_MEMORY] = -+ "NO_MEMORY: Not enough memory", -+ [DENIED] = -+ "DENIED: Buffer pair already registered", -+ }, -+ }, -+}; -+ -+/** -+ * ffa_to_std_errno() - convert FF-A error code to standard error code -+ * @ffa_errno: Error code returned by the FF-A ABI -+ * -+ * Map the given FF-A error code as specified -+ * by the spec to a u-boot standard error code. -+ * -+ * Return: -+ * -+ * The standard error code on success. . Otherwise, failure -+ */ -+static int ffa_to_std_errno(int ffa_errno) -+{ -+ int err_idx = -ffa_errno; -+ -+ /* Map the FF-A error code to the standard u-boot error code */ -+ if (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR) -+ return ffa_to_std_errmap[err_idx]; -+ return -EINVAL; -+} -+ -+/** -+ * ffa_print_error_log() - print the error log corresponding to the selected FF-A ABI -+ * @ffa_id: FF-A ABI ID -+ * @ffa_errno: Error code returned by the FF-A ABI -+ * -+ * Map the FF-A error code to the error log relevant to the -+ * selected FF-A ABI. Then the error log is printed. -+ * -+ * Return: -+ * -+ * 0 on success. . Otherwise, failure -+ */ -+static int ffa_print_error_log(u32 ffa_id, int ffa_errno) -+{ -+ int err_idx = -ffa_errno, abi_idx = 0; -+ -+ /* Map the FF-A error code to the corresponding error log */ -+ -+ if (err_idx <= 0 || err_idx >= MAX_NUMBER_FFA_ERR) -+ return -EINVAL; -+ -+ if (ffa_id < FFA_FIRST_ID || ffa_id > FFA_LAST_ID) -+ return -EINVAL; -+ -+ abi_idx = FFA_ID_TO_ERRMAP_ID(ffa_id); -+ if (abi_idx < 0 || abi_idx >= FFA_ERRMAP_COUNT) -+ return -EINVAL; -+ -+ if (!err_msg_map[abi_idx].err_str[err_idx]) -+ return -EINVAL; -+ -+ log_err("%s\n", err_msg_map[abi_idx].err_str[err_idx]); -+ -+ return 0; -+} -+ -+/* FF-A ABIs implementation (U-Boot side) */ -+ -+/** -+ * invoke_ffa_fn() - SMC wrapper -+ * @args: FF-A ABI arguments to be copied to Xn registers -+ * @res: FF-A ABI return data to be copied from Xn registers -+ * -+ * Calls low level SMC implementation. -+ * This function should be implemented by the user driver. -+ */ -+void __weak invoke_ffa_fn(ffa_value_t args, ffa_value_t *res) -+{ -+} -+ -+/** -+ * ffa_get_version_hdlr() - FFA_VERSION handler function -+ * @dev: The FF-A bus device -+ * -+ * Implement FFA_VERSION FF-A function -+ * to get from the secure world the FF-A framework version -+ * FFA_VERSION is used to discover the FF-A framework. -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+int ffa_get_version_hdlr(struct udevice *dev) -+{ -+ u16 major, minor; -+ ffa_value_t res = {0}; -+ int ffa_errno; -+ struct ffa_priv *uc_priv; -+ -+ invoke_ffa_fn((ffa_value_t){ -+ .a0 = FFA_SMC_32(FFA_VERSION), .a1 = FFA_VERSION_1_0, -+ }, &res); -+ -+ ffa_errno = res.a0; -+ if (ffa_errno < 0) { -+ ffa_print_error_log(FFA_VERSION, ffa_errno); -+ return ffa_to_std_errno(ffa_errno); -+ } -+ -+ major = GET_FFA_MAJOR_VERSION(res.a0); -+ minor = GET_FFA_MINOR_VERSION(res.a0); -+ -+ log_info("FF-A driver %d.%d\nFF-A framework %d.%d\n", -+ FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor); -+ -+ if (major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION) { -+ log_info("FF-A versions are compatible\n"); -+ -+ if (dev) { -+ uc_priv = dev_get_uclass_priv(dev); -+ if (uc_priv) -+ uc_priv->fwk_version = res.a0; -+ } -+ -+ return 0; -+ } -+ -+ log_err("versions are incompatible\nExpected: %d.%d , Found: %d.%d\n", -+ FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor); -+ -+ return -EPROTONOSUPPORT; -+} -+ -+/** -+ * ffa_get_endpoint_id() - FFA_ID_GET handler function -+ * @dev: The FF-A bus device -+ * -+ * Implement FFA_ID_GET FF-A function -+ * to get from the secure world u-boot endpoint ID -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+static int ffa_get_endpoint_id(struct udevice *dev) -+{ -+ ffa_value_t res = {0}; -+ int ffa_errno; -+ struct ffa_priv *uc_priv = dev_get_uclass_priv(dev); -+ -+ invoke_ffa_fn((ffa_value_t){ -+ .a0 = FFA_SMC_32(FFA_ID_GET), -+ }, &res); -+ -+ if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) { -+ uc_priv->id = GET_SELF_ENDPOINT_ID((u32)res.a2); -+ log_debug("FF-A endpoint ID is %u\n", uc_priv->id); -+ -+ return 0; -+ } -+ -+ ffa_errno = res.a2; -+ -+ ffa_print_error_log(FFA_ID_GET, ffa_errno); -+ -+ return ffa_to_std_errno(ffa_errno); -+} -+ -+/** -+ * ffa_set_rxtx_buffers_pages_cnt() - set the minimum number of pages in each of the RX/TX buffers -+ * @dev: The FF-A bus device -+ * @prop_field: properties field obtained from FFA_FEATURES ABI -+ * -+ * Set the minimum number of pages in each of the RX/TX buffers in uc_priv -+ * -+ * Return: -+ * -+ * rxtx_min_pages field contains the returned number of pages -+ * 0 on success. Otherwise, failure -+ */ -+static int ffa_set_rxtx_buffers_pages_cnt(struct udevice *dev, u32 prop_field) -+{ -+ struct ffa_priv *uc_priv = dev_get_uclass_priv(dev); -+ -+ switch (prop_field) { -+ case RXTX_4K: -+ uc_priv->pair.rxtx_min_pages = 1; -+ break; -+ case RXTX_16K: -+ uc_priv->pair.rxtx_min_pages = 4; -+ break; -+ case RXTX_64K: -+ uc_priv->pair.rxtx_min_pages = 16; -+ break; -+ default: -+ log_err("RX/TX buffer size not supported\n"); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/** -+ * ffa_get_rxtx_map_features_hdlr() - FFA_FEATURES handler function with FFA_RXTX_MAP argument -+ * @dev: The FF-A bus device -+ * -+ * Implement FFA_FEATURES FF-A function to retrieve the FFA_RXTX_MAP features -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+static int ffa_get_rxtx_map_features_hdlr(struct udevice *dev) -+{ -+ ffa_value_t res = {0}; -+ int ffa_errno; -+ -+ invoke_ffa_fn((ffa_value_t){ -+ .a0 = FFA_SMC_32(FFA_FEATURES), -+ .a1 = FFA_SMC_64(FFA_RXTX_MAP), -+ }, &res); -+ -+ if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) -+ return ffa_set_rxtx_buffers_pages_cnt(dev, res.a2); -+ -+ ffa_errno = res.a2; -+ ffa_print_error_log(FFA_FEATURES, ffa_errno); -+ -+ return ffa_to_std_errno(ffa_errno); -+} -+ -+/** -+ * ffa_free_rxtx_buffers() - free the RX/TX buffers -+ * @dev: The FF-A bus device -+ * -+ * Free the RX/TX buffers -+ */ -+static void ffa_free_rxtx_buffers(struct udevice *dev) -+{ -+ struct ffa_priv *uc_priv = dev_get_uclass_priv(dev); -+ -+ log_debug("Freeing FF-A RX/TX buffers\n"); -+ -+ if (uc_priv->pair.rxbuf) { -+ free(uc_priv->pair.rxbuf); -+ uc_priv->pair.rxbuf = NULL; -+ } -+ -+ if (uc_priv->pair.txbuf) { -+ free(uc_priv->pair.txbuf); -+ uc_priv->pair.txbuf = NULL; -+ } -+} -+ -+/** -+ * ffa_alloc_rxtx_buffers() - allocate the RX/TX buffers -+ * @dev: The FF-A bus device -+ * -+ * Used by ffa_map_rxtx_buffers to allocate -+ * the RX/TX buffers before mapping them. The allocated memory is physically -+ * contiguous since memalign ends up calling malloc which allocates -+ * contiguous memory in u-boot. -+ * The size of the memory allocated is the minimum allowed. -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+static int ffa_alloc_rxtx_buffers(struct udevice *dev) -+{ -+ u64 bytes; -+ struct ffa_priv *uc_priv = dev_get_uclass_priv(dev); -+ -+ log_debug("Using %lu 4KB page(s) for FF-A RX/TX buffers size\n", -+ uc_priv->pair.rxtx_min_pages); -+ -+ bytes = uc_priv->pair.rxtx_min_pages * SZ_4K; -+ -+ /* -+ * The alignment of the RX and TX buffers must be equal -+ * to the larger translation granule size -+ * Assumption: Memory allocated with memalign is always physically contiguous -+ */ -+ -+ uc_priv->pair.rxbuf = memalign(bytes, bytes); -+ if (!uc_priv->pair.rxbuf) { -+ log_err("failure to allocate RX buffer\n"); -+ return -ENOBUFS; -+ } -+ -+ log_debug("FF-A RX buffer at virtual address %p\n", uc_priv->pair.rxbuf); -+ -+ uc_priv->pair.txbuf = memalign(bytes, bytes); -+ if (!uc_priv->pair.txbuf) { -+ free(uc_priv->pair.rxbuf); -+ uc_priv->pair.rxbuf = NULL; -+ log_err("failure to allocate the TX buffer\n"); -+ return -ENOBUFS; -+ } -+ -+ log_debug("FF-A TX buffer at virtual address %p\n", uc_priv->pair.txbuf); -+ -+ /* Make sure the buffers are cleared before use */ -+ memset(uc_priv->pair.rxbuf, 0, bytes); -+ memset(uc_priv->pair.txbuf, 0, bytes); -+ -+ return 0; -+} -+ -+/** -+ * ffa_map_rxtx_buffers_hdlr() - FFA_RXTX_MAP handler function -+ * @dev: The FF-A bus device -+ * -+ * Implement FFA_RXTX_MAP FF-A function to map the RX/TX buffers -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+static int ffa_map_rxtx_buffers_hdlr(struct udevice *dev) -+{ -+ int ret; -+ ffa_value_t res = {0}; -+ int ffa_errno; -+ struct ffa_priv *uc_priv = dev_get_uclass_priv(dev); -+ -+ ret = ffa_alloc_rxtx_buffers(dev); -+ if (ret) -+ return ret; -+ -+ /* -+ * we need to pass the physical addresses of the RX/TX buffers -+ * in u-boot physical/virtual mapping is 1:1 -+ * no need to convert from virtual to physical -+ */ -+ -+ invoke_ffa_fn((ffa_value_t){ -+ .a0 = FFA_SMC_64(FFA_RXTX_MAP), -+ .a1 = map_to_sysmem(uc_priv->pair.txbuf), -+ .a2 = map_to_sysmem(uc_priv->pair.rxbuf), -+ .a3 = uc_priv->pair.rxtx_min_pages, -+ }, &res); -+ -+ if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) { -+ log_debug("FF-A RX/TX buffers mapped\n"); -+ return 0; -+ } -+ -+ ffa_errno = res.a2; -+ ffa_print_error_log(FFA_RXTX_MAP, ffa_errno); -+ -+ ffa_free_rxtx_buffers(dev); -+ -+ return ffa_to_std_errno(ffa_errno); -+} -+ -+/** -+ * ffa_unmap_rxtx_buffers_hdlr() - FFA_RXTX_UNMAP handler function -+ * @dev: The FF-A bus device -+ * -+ * Implement FFA_RXTX_UNMAP FF-A function to unmap the RX/TX buffers -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+int ffa_unmap_rxtx_buffers_hdlr(struct udevice *dev) -+{ -+ ffa_value_t res = {0}; -+ int ffa_errno; -+ struct ffa_priv *uc_priv; -+ -+ log_debug("unmapping FF-A RX/TX buffers\n"); -+ -+ uc_priv = dev_get_uclass_priv(dev); -+ -+ invoke_ffa_fn((ffa_value_t){ -+ .a0 = FFA_SMC_32(FFA_RXTX_UNMAP), -+ .a1 = PREP_SELF_ENDPOINT_ID(uc_priv->id), -+ }, &res); -+ -+ if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) { -+ ffa_free_rxtx_buffers(dev); -+ return 0; -+ } -+ -+ ffa_errno = res.a2; -+ ffa_print_error_log(FFA_RXTX_UNMAP, ffa_errno); -+ -+ return ffa_to_std_errno(ffa_errno); -+} -+ -+/** -+ * ffa_release_rx_buffer_hdlr() - FFA_RX_RELEASE handler function -+ * @dev: The FF-A bus device -+ * -+ * Invoke FFA_RX_RELEASE FF-A function to release the ownership of the RX buffer -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+static int ffa_release_rx_buffer_hdlr(struct udevice *dev) -+{ -+ ffa_value_t res = {0}; -+ int ffa_errno; -+ -+ invoke_ffa_fn((ffa_value_t){ -+ .a0 = FFA_SMC_32(FFA_RX_RELEASE), -+ }, &res); -+ -+ if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) -+ return 0; -+ -+ ffa_errno = res.a2; -+ ffa_print_error_log(FFA_RX_RELEASE, ffa_errno); -+ -+ return ffa_to_std_errno(ffa_errno); -+} -+ -+/** -+ * ffa_uuid_are_identical() - check whether two given UUIDs are identical -+ * @uuid1: first UUID -+ * @uuid2: second UUID -+ * -+ * Used by ffa_read_partitions_info to search for a UUID in the partitions descriptors table -+ * -+ * Return: -+ * -+ * 1 when UUIDs match. Otherwise, 0 -+ */ -+static bool ffa_uuid_are_identical(const struct ffa_partition_uuid *uuid1, -+ const struct ffa_partition_uuid *uuid2) -+{ -+ if (!uuid1 || !uuid2) -+ return 0; -+ -+ return !memcmp(uuid1, uuid2, sizeof(struct ffa_partition_uuid)); -+} -+ -+/** -+ * ffa_read_partitions_info() - read queried partition data -+ * @dev: The FF-A bus device -+ * @count: The number of partitions queried -+ * @part_uuid: Pointer to the partition(s) UUID -+ * -+ * Read the partitions information returned by the FFA_PARTITION_INFO_GET and saves it in uc_priv -+ * -+ * Return: -+ * -+ * uc_priv is updated with the partition(s) information -+ * 0 is returned on success. Otherwise, failure -+ */ -+static int ffa_read_partitions_info(struct udevice *dev, u32 count, -+ struct ffa_partition_uuid *part_uuid) -+{ -+ struct ffa_priv *uc_priv = dev_get_uclass_priv(dev); -+ -+ if (!count) { -+ log_err("no partition detected\n"); -+ return -ENODATA; -+ } -+ -+ log_debug("Reading FF-A partitions data from the RX buffer\n"); -+ -+ if (!part_uuid) { -+ /* Querying information of all partitions */ -+ u64 buf_bytes; -+ u64 data_bytes; -+ u32 desc_idx; -+ struct ffa_partition_info *parts_info; -+ -+ data_bytes = count * sizeof(struct ffa_partition_desc); -+ -+ buf_bytes = uc_priv->pair.rxtx_min_pages * SZ_4K; -+ -+ if (data_bytes > buf_bytes) { -+ log_err("partitions data size exceeds the RX buffer size:\n"); -+ log_err(" sizes in bytes: data %llu , RX buffer %llu\n", -+ data_bytes, -+ buf_bytes); -+ -+ return -ENOMEM; -+ } -+ -+ uc_priv->partitions.descs = devm_kmalloc(dev, data_bytes, __GFP_ZERO); -+ if (!uc_priv->partitions.descs) { -+ log_err("cannot allocate partitions data buffer\n"); -+ return -ENOMEM; -+ } -+ -+ parts_info = uc_priv->pair.rxbuf; -+ -+ for (desc_idx = 0 ; desc_idx < count ; desc_idx++) { -+ uc_priv->partitions.descs[desc_idx].info = -+ parts_info[desc_idx]; -+ -+ log_debug("FF-A partition ID %x : info cached\n", -+ uc_priv->partitions.descs[desc_idx].info.id); -+ } -+ -+ uc_priv->partitions.count = count; -+ -+ log_debug("%d FF-A partition(s) found and cached\n", count); -+ -+ } else { -+ u32 rx_desc_idx, cached_desc_idx; -+ struct ffa_partition_info *parts_info; -+ u8 desc_found; -+ -+ parts_info = uc_priv->pair.rxbuf; -+ -+ /* -+ * Search for the SP IDs read from the RX buffer -+ * in the already cached SPs. -+ * Update the UUID when ID found. -+ */ -+ for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) { -+ desc_found = 0; -+ -+ /* Search the current ID in the cached partitions */ -+ for (cached_desc_idx = 0; -+ cached_desc_idx < uc_priv->partitions.count; -+ cached_desc_idx++) { -+ /* Save the UUID */ -+ if (uc_priv->partitions.descs[cached_desc_idx].info.id == -+ parts_info[rx_desc_idx].id) { -+ uc_priv->partitions.descs[cached_desc_idx].sp_uuid = -+ *part_uuid; -+ -+ desc_found = 1; -+ break; -+ } -+ } -+ -+ if (!desc_found) -+ return -ENODATA; -+ } -+ } -+ -+ return 0; -+} -+ -+/** -+ * ffa_query_partitions_info() - invoke FFA_PARTITION_INFO_GET and save partitions data -+ * @dev: The FF-A bus device -+ * @part_uuid: Pointer to the partition(s) UUID -+ * @pcount: Pointer to the number of partitions variable filled when querying -+ * -+ * Execute the FFA_PARTITION_INFO_GET to query the partitions data. -+ * Then, call ffa_read_partitions_info to save the data in uc_priv. -+ * -+ * After reading the data the RX buffer is released using ffa_release_rx_buffer -+ * -+ * Return: -+ * -+ * When part_uuid is NULL, all partitions data are retrieved from secure world -+ * When part_uuid is non NULL, data for partitions matching the given UUID are -+ * retrieved and the number of partitions is returned -+ * 0 is returned on success. Otherwise, failure -+ */ -+static int ffa_query_partitions_info(struct udevice *dev, struct ffa_partition_uuid *part_uuid, -+ u32 *pcount) -+{ -+ struct ffa_partition_uuid query_uuid = {0}; -+ ffa_value_t res = {0}; -+ int ffa_errno; -+ -+ /* -+ * If a UUID is specified. Information for one or more -+ * partitions in the system is queried. Otherwise, information -+ * for all installed partitions is queried -+ */ -+ -+ if (part_uuid) { -+ if (!pcount) -+ return -EINVAL; -+ -+ query_uuid = *part_uuid; -+ } else if (pcount) { -+ return -EINVAL; -+ } -+ -+ invoke_ffa_fn((ffa_value_t){ -+ .a0 = FFA_SMC_32(FFA_PARTITION_INFO_GET), -+ .a1 = query_uuid.a1, -+ .a2 = query_uuid.a2, -+ .a3 = query_uuid.a3, -+ .a4 = query_uuid.a4, -+ }, &res); -+ -+ if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) { -+ int ret; -+ -+ /* -+ * res.a2 contains the count of partition information descriptors -+ * populated in the RX buffer -+ */ -+ if (res.a2) { -+ ret = ffa_read_partitions_info(dev, (u32)res.a2, part_uuid); -+ if (ret) { -+ log_err("failed reading SP(s) data , err (%d)\n", ret); -+ ffa_release_rx_buffer_hdlr(dev); -+ return -EINVAL; -+ } -+ } -+ -+ /* Return the SP count (when querying using a UUID) */ -+ if (pcount) -+ *pcount = (u32)res.a2; -+ -+ /* -+ * After calling FFA_PARTITION_INFO_GET the buffer ownership -+ * is assigned to the consumer (u-boot). So, we need to give -+ * the ownership back to the SPM or hypervisor -+ */ -+ ret = ffa_release_rx_buffer_hdlr(dev); -+ -+ return ret; -+ } -+ -+ ffa_errno = res.a2; -+ ffa_print_error_log(FFA_PARTITION_INFO_GET, ffa_errno); -+ -+ return ffa_to_std_errno(ffa_errno); -+} -+ -+/** -+ * ffa_get_partitions_info_hdlr() - FFA_PARTITION_INFO_GET handler function -+ * @uuid_str: pointer to the UUID string -+ * @sp_count: address of the variable containing the number of partitions matching the UUID -+ * The variable is set by the driver -+ * @sp_descs: address of the descriptors of the partitions matching the UUID -+ * The address is set by the driver -+ * -+ * Return the number of partitions and their descriptors matching the UUID -+ * -+ * Query the secure partition data from uc_priv. -+ * If not found, invoke FFA_PARTITION_INFO_GET FF-A function to query the partition information -+ * from secure world. -+ * -+ * A client of the FF-A driver should know the UUID of the service it wants to -+ * access. It should use the UUID to request the FF-A driver to provide the -+ * partition(s) information of the service. The FF-A driver uses -+ * PARTITION_INFO_GET to obtain this information. This is implemented through -+ * ffa_get_partitions_info_hdlr() function. -+ * If the partition(s) matching the UUID found, the partition(s) information and the -+ * number are returned. -+ * If no partition matching the UUID is found in the cached area, a new FFA_PARTITION_INFO_GET -+ * call is issued. -+ * If not done yet, the UUID is updated in the cached area. -+ * This assumes that partitions data does not change in the secure world. -+ * Otherwise u-boot will have an outdated partition data. The benefit of caching -+ * the information in the FF-A driver is to accommodate discovery after -+ * ExitBootServices(). -+ * -+ * Return: -+ * -+ * @sp_count: the number of partitions -+ * @sp_descs: address of the partitions descriptors -+ * -+ * On success 0 is returned. Otherwise, failure -+ */ -+int ffa_get_partitions_info_hdlr(struct udevice *dev, const char *uuid_str, -+ u32 *sp_count, struct ffa_partition_desc **sp_descs) -+{ -+ u32 i; -+ struct ffa_partition_uuid part_uuid = {0}; -+ struct ffa_priv *uc_priv; -+ struct ffa_partition_desc *rx_descs; -+ -+ uc_priv = dev_get_uclass_priv(dev); -+ -+ if (!uc_priv->partitions.count || !uc_priv->partitions.descs) { -+ log_err("no partition installed\n"); -+ return -EINVAL; -+ } -+ -+ if (!uuid_str) { -+ log_err("no UUID provided\n"); -+ return -EINVAL; -+ } -+ -+ if (!sp_count) { -+ log_err("no count argument provided\n"); -+ return -EINVAL; -+ } -+ -+ if (!sp_descs) { -+ log_err("no info argument provided\n"); -+ return -EINVAL; -+ } -+ -+ if (uuid_str_to_le_bin(uuid_str, (unsigned char *)&part_uuid)) { -+ log_err("invalid UUID\n"); -+ return -EINVAL; -+ } -+ -+ log_debug("Searching FF-A partitions using the provided UUID\n"); -+ -+ *sp_count = 0; -+ *sp_descs = uc_priv->pair.rxbuf; -+ rx_descs = *sp_descs; -+ -+ /* Search in the cached partitions */ -+ for (i = 0; i < uc_priv->partitions.count; i++) -+ if (ffa_uuid_are_identical(&uc_priv->partitions.descs[i].sp_uuid, -+ &part_uuid)) { -+ log_debug("FF-A partition ID %x matches the provided UUID\n", -+ uc_priv->partitions.descs[i].info.id); -+ -+ (*sp_count)++; -+ *rx_descs++ = uc_priv->partitions.descs[i]; -+ } -+ -+ if (!(*sp_count)) { -+ int ret; -+ -+ log_debug("No FF-A partition found. Querying framework ...\n"); -+ -+ ret = ffa_query_partitions_info(dev, &part_uuid, sp_count); -+ -+ if (!ret) { -+ log_debug("Number of FF-A partition(s) matching the UUID: %d\n", *sp_count); -+ -+ if (*sp_count) -+ ret = ffa_get_partitions_info_hdlr(dev, uuid_str, sp_count, -+ sp_descs); -+ else -+ ret = -ENODATA; -+ } -+ -+ return ret; -+ } -+ -+ return 0; -+} -+ -+/** -+ * ffa_cache_partitions_info() - Query and saves all secure partitions data -+ * @dev: The FF-A bus device -+ * -+ * Invoke FFA_PARTITION_INFO_GET FF-A function to query from secure world -+ * all partitions information. -+ * -+ * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument. -+ * All installed partitions information are returned. We cache them in uc_priv -+ * and we keep the UUID field empty (in FF-A 1.0 UUID is not provided by the partition descriptor) -+ * -+ * Called at the device probing level. -+ * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+static int ffa_cache_partitions_info(struct udevice *dev) -+{ -+ return ffa_query_partitions_info(dev, NULL, NULL); -+} -+ -+/** -+ * ffa_msg_send_direct_req_hdlr() - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function -+ * @dev: The FF-A bus device -+ * @dst_part_id: destination partition ID -+ * @msg: pointer to the message data preallocated by the client (in/out) -+ * @is_smc64: select 64-bit or 32-bit FF-A ABI -+ * -+ * Implement FFA_MSG_SEND_DIRECT_{REQ,RESP} -+ * FF-A functions. -+ * -+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition. -+ * The response from the secure partition is handled by reading the -+ * FFA_MSG_SEND_DIRECT_RESP arguments. -+ * -+ * The maximum size of the data that can be exchanged is 40 bytes which is -+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0 -+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP} -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id, -+ struct ffa_send_direct_data *msg, bool is_smc64) -+{ -+ ffa_value_t res = {0}; -+ int ffa_errno; -+ u64 req_mode, resp_mode; -+ struct ffa_priv *uc_priv; -+ -+ uc_priv = dev_get_uclass_priv(dev); -+ -+ /* No partition installed */ -+ if (!uc_priv->partitions.count || !uc_priv->partitions.descs) -+ return -ENODEV; -+ -+ if (is_smc64) { -+ req_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ); -+ resp_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP); -+ } else { -+ req_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_REQ); -+ resp_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_RESP); -+ } -+ -+ invoke_ffa_fn((ffa_value_t){ -+ .a0 = req_mode, -+ .a1 = PREP_SELF_ENDPOINT_ID(uc_priv->id) | -+ PREP_PART_ENDPOINT_ID(dst_part_id), -+ .a2 = 0, -+ .a3 = msg->data0, -+ .a4 = msg->data1, -+ .a5 = msg->data2, -+ .a6 = msg->data3, -+ .a7 = msg->data4, -+ }, &res); -+ -+ while (res.a0 == FFA_SMC_32(FFA_INTERRUPT)) -+ invoke_ffa_fn((ffa_value_t){ -+ .a0 = FFA_SMC_32(FFA_RUN), -+ .a1 = res.a1, -+ }, &res); -+ -+ if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) { -+ /* Message sent with no response */ -+ return 0; -+ } -+ -+ if (res.a0 == resp_mode) { -+ /* Message sent with response extract the return data */ -+ msg->data0 = res.a3; -+ msg->data1 = res.a4; -+ msg->data2 = res.a5; -+ msg->data3 = res.a6; -+ msg->data4 = res.a7; -+ -+ return 0; -+ } -+ -+ ffa_errno = res.a2; -+ return ffa_to_std_errno(ffa_errno); -+} -+ -+/* FF-A driver operations (used by clients for communicating with FF-A)*/ -+ -+/** -+ * ffa_partition_info_get() - FFA_PARTITION_INFO_GET driver operation -+ * @uuid_str: pointer to the UUID string -+ * @sp_count: address of the variable containing the number of partitions matching the UUID -+ * The variable is set by the driver -+ * @sp_descs: address of the descriptors of the partitions matching the UUID -+ * The address is set by the driver -+ * -+ * Driver operation for FFA_PARTITION_INFO_GET. -+ * Please see ffa_get_partitions_info_hdlr() description for more details. -+ * -+ * Return: -+ * -+ * @sp_count: the number of partitions -+ * @sp_descs: address of the partitions descriptors -+ * -+ * On success 0 is returned. Otherwise, failure -+ */ -+int ffa_partition_info_get(struct udevice *dev, const char *uuid_str, -+ u32 *sp_count, struct ffa_partition_desc **sp_descs) -+{ -+ struct ffa_bus_ops *ops = ffa_get_ops(dev); -+ -+ if (!ops->partition_info_get) -+ return -ENOSYS; -+ -+ return ops->partition_info_get(dev, uuid_str, sp_count, sp_descs); -+} -+ -+/** -+ * ffa_sync_send_receive() - FFA_MSG_SEND_DIRECT_{REQ,RESP} driver operation -+ * @dev: The FF-A bus device -+ * @dst_part_id: destination partition ID -+ * @msg: pointer to the message data preallocated by the client (in/out) -+ * @is_smc64: select 64-bit or 32-bit FF-A ABI -+ * -+ * Driver operation for FFA_MSG_SEND_DIRECT_{REQ,RESP}. -+ * Please see ffa_msg_send_direct_req_hdlr() description for more details. -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+int ffa_sync_send_receive(struct udevice *dev, u16 dst_part_id, -+ struct ffa_send_direct_data *msg, bool is_smc64) -+{ -+ struct ffa_bus_ops *ops = ffa_get_ops(dev); -+ -+ if (!ops->sync_send_receive) -+ return -ENOSYS; -+ -+ return ops->sync_send_receive(dev, dst_part_id, msg, is_smc64); -+} -+ -+/** -+ * ffa_rxtx_unmap() - FFA_RXTX_UNMAP driver operation -+ * @dev: The FF-A bus device -+ * -+ * Driver operation for FFA_RXTX_UNMAP. -+ * Please see ffa_unmap_rxtx_buffers_hdlr() description for more details. -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+int ffa_rxtx_unmap(struct udevice *dev) -+{ -+ struct ffa_bus_ops *ops = ffa_get_ops(dev); -+ -+ if (!ops->rxtx_unmap) -+ return -ENOSYS; -+ -+ return ops->rxtx_unmap(dev); -+} -+ -+/** -+ * ffa_do_probe() - probing FF-A framework -+ * @dev: the FF-A bus device (arm_ffa) -+ * -+ * Probing is triggered on demand by clients searching for the uclass. -+ * At probe level the following actions are done: -+ * - saving the FF-A framework version in uc_priv -+ * - querying from secure world the u-boot endpoint ID -+ * - querying from secure world the supported features of FFA_RXTX_MAP -+ * - mapping the RX/TX buffers -+ * - querying from secure world all the partitions information -+ * -+ * All data queried from secure world is saved in uc_priv. -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+static int ffa_do_probe(struct udevice *dev) -+{ -+ int ret; -+ -+ ret = ffa_get_version_hdlr(dev); -+ if (ret) -+ return ret; -+ -+ ret = ffa_get_endpoint_id(dev); -+ if (ret) -+ return ret; -+ -+ ret = ffa_get_rxtx_map_features_hdlr(dev); -+ if (ret) -+ return ret; -+ -+ ret = ffa_map_rxtx_buffers_hdlr(dev); -+ if (ret) -+ return ret; -+ -+ ret = ffa_cache_partitions_info(dev); -+ if (ret) { -+ ffa_unmap_rxtx_buffers_hdlr(dev); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+UCLASS_DRIVER(ffa) = { -+ .name = "ffa", -+ .id = UCLASS_FFA, -+ .pre_probe = ffa_do_probe, -+ .pre_remove = ffa_unmap_rxtx_buffers_hdlr, -+ .per_device_auto = sizeof(struct ffa_priv) -+}; -diff --git a/drivers/firmware/arm-ffa/arm-ffa.c b/drivers/firmware/arm-ffa/arm-ffa.c -new file mode 100644 -index 0000000000..68df75bd9e ---- /dev/null -+++ b/drivers/firmware/arm-ffa/arm-ffa.c -@@ -0,0 +1,104 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Copyright 2022-2023 Arm Limited and/or its affiliates -+ * -+ * Authors: -+ * Abdellatif El Khlifi -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+DECLARE_GLOBAL_DATA_PTR; -+ -+/** -+ * invoke_ffa_fn() - SMC wrapper -+ * @args: FF-A ABI arguments to be copied to Xn registers -+ * @res: FF-A ABI return data to be copied from Xn registers -+ * -+ * Calls low level SMC assembly function -+ */ -+void invoke_ffa_fn(ffa_value_t args, ffa_value_t *res) -+{ -+ arm_smccc_1_2_smc(&args, res); -+} -+ -+/** -+ * arm_ffa_discover() - perform FF-A discovery -+ * @dev: The Arm FF-A bus device (arm_ffa) -+ * Try to discover the FF-A framework. Discovery is performed by -+ * querying the FF-A framework version from secure world using the FFA_VERSION ABI. -+ * Return: -+ * -+ * true on success. Otherwise, false. -+ */ -+static bool arm_ffa_discover(struct udevice *dev) -+{ -+ int ret; -+ -+ log_info("Arm FF-A framework discovery\n"); -+ -+ ret = ffa_get_version_hdlr(dev); -+ if (ret) -+ return false; -+ -+ return true; -+} -+ -+/** -+ * arm_ffa_is_supported() - FF-A bus discovery callback -+ * @invoke_fn: legacy SMC invoke function (not used) -+ * -+ * Perform FF-A discovery by calling arm_ffa_discover(). -+ * Discovery is performed by querying the FF-A framework version from -+ * secure world using the FFA_VERSION ABI. -+ * -+ * The FF-A driver is registered as an SMCCC feature driver. So, features discovery -+ * callbacks are called by the PSCI driver (PSCI device is the SMCCC features -+ * root device). -+ * -+ * The FF-A driver supports the SMCCCv1.2 extended input/output registers. -+ * So, the legacy SMC invocation is not used. -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+static bool arm_ffa_is_supported(void (*invoke_fn)(ulong a0, ulong a1, -+ ulong a2, ulong a3, -+ ulong a4, ulong a5, -+ ulong a6, ulong a7, -+ struct arm_smccc_res *res)) -+{ -+ return arm_ffa_discover(NULL); -+} -+ -+/* Arm FF-A driver operations */ -+ -+static const struct ffa_bus_ops ffa_ops = { -+ .partition_info_get = ffa_get_partitions_info_hdlr, -+ .sync_send_receive = ffa_msg_send_direct_req_hdlr, -+ .rxtx_unmap = ffa_unmap_rxtx_buffers_hdlr, -+}; -+ -+/* Registering the FF-A driver as an SMCCC feature driver */ -+ -+ARM_SMCCC_FEATURE_DRIVER(arm_ffa) = { -+ .driver_name = FFA_DRV_NAME, -+ .is_supported = arm_ffa_is_supported, -+}; -+ -+/* Declaring the FF-A driver under UCLASS_FFA */ -+ -+U_BOOT_DRIVER(arm_ffa) = { -+ .name = FFA_DRV_NAME, -+ .id = UCLASS_FFA, -+ .flags = DM_REMOVE_OS_PREPARE, -+ .ops = &ffa_ops, -+}; -diff --git a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h -new file mode 100644 -index 0000000000..4338f9c9b1 ---- /dev/null -+++ b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h -@@ -0,0 +1,14 @@ -+/* SPDX-License-Identifier: GPL-2.0+ */ -+/* -+ * Copyright 2022-2023 Arm Limited and/or its affiliates -+ * -+ * Authors: -+ * Abdellatif El Khlifi -+ */ -+ -+#ifndef __SANDBOX_ARM_FFA_PRV_H -+#define __SANDBOX_ARM_FFA_PRV_H -+ -+/* Future sandbox support private declarations */ -+ -+#endif -diff --git a/include/arm_ffa.h b/include/arm_ffa.h -new file mode 100644 -index 0000000000..db9b1be995 ---- /dev/null -+++ b/include/arm_ffa.h -@@ -0,0 +1,213 @@ -+/* SPDX-License-Identifier: GPL-2.0+ */ -+/* -+ * Copyright 2022-2023 Arm Limited and/or its affiliates -+ * -+ * Authors: -+ * Abdellatif El Khlifi -+ */ -+ -+#ifndef __ARM_FFA_H -+#define __ARM_FFA_H -+ -+#include -+ -+/* -+ * This header is public. It can be used by clients to access -+ * data structures and definitions they need -+ */ -+ -+/* -+ * struct ffa_partition_info - Partition information descriptor -+ * @id: Partition ID -+ * @exec_ctxt: Execution context count -+ * @properties: Partition properties -+ * -+ * Data structure containing information about partitions instantiated in the system -+ * This structure is filled with the data queried by FFA_PARTITION_INFO_GET -+ */ -+struct ffa_partition_info { -+ u16 id; -+ u16 exec_ctxt; -+/* partition supports receipt of direct requests */ -+#define FFA_PARTITION_DIRECT_RECV BIT(0) -+/* partition can send direct requests. */ -+#define FFA_PARTITION_DIRECT_SEND BIT(1) -+/* partition can send and receive indirect messages. */ -+#define FFA_PARTITION_INDIRECT_MSG BIT(2) -+ u32 properties; -+}; -+ -+/* -+ * struct ffa_partition_uuid - 16 bytes UUID transmitted by FFA_PARTITION_INFO_GET -+ * @a1-4: 32-bit words access to the UUID data -+ * -+ */ -+struct ffa_partition_uuid { -+ u32 a1; /* w1 */ -+ u32 a2; /* w2 */ -+ u32 a3; /* w3 */ -+ u32 a4; /* w4 */ -+}; -+ -+/** -+ * struct ffa_partition_desc - the secure partition descriptor -+ * @info: partition information -+ * @sp_uuid: the secure partition UUID -+ * -+ * Each partition has its descriptor containing the partitions information and the UUID -+ */ -+struct ffa_partition_desc { -+ struct ffa_partition_info info; -+ struct ffa_partition_uuid sp_uuid; -+}; -+ -+/* -+ * struct ffa_send_direct_data - Data structure hosting the data -+ * used by FFA_MSG_SEND_DIRECT_{REQ,RESP} -+ * @data0-4: Data read/written from/to x3-x7 registers -+ * -+ * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ -+ * or read from FFA_MSG_SEND_DIRECT_RESP -+ */ -+ -+/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */ -+struct ffa_send_direct_data { -+ ulong data0; /* w3/x3 */ -+ ulong data1; /* w4/x4 */ -+ ulong data2; /* w5/x5 */ -+ ulong data3; /* w6/x6 */ -+ ulong data4; /* w7/x7 */ -+}; -+ -+struct udevice; -+ -+/** -+ * struct ffa_bus_ops - Operations for FF-A -+ * @partition_info_get: callback for the FFA_PARTITION_INFO_GET -+ * @sync_send_receive: callback for the FFA_MSG_SEND_DIRECT_REQ -+ * @rxtx_unmap: callback for the FFA_RXTX_UNMAP -+ * -+ * The data structure providing all the operations supported by the driver. -+ * This structure is EFI runtime resident. -+ */ -+struct ffa_bus_ops { -+ int (*partition_info_get)(struct udevice *dev, const char *uuid_str, -+ u32 *sp_count, struct ffa_partition_desc **sp_descs); -+ int (*sync_send_receive)(struct udevice *dev, u16 dst_part_id, -+ struct ffa_send_direct_data *msg, -+ bool is_smc64); -+ int (*rxtx_unmap)(struct udevice *dev); -+}; -+ -+#define ffa_get_ops(dev) ((struct ffa_bus_ops *)(dev)->driver->ops) -+ -+/** -+ * ffa_rxtx_unmap() - FFA_RXTX_UNMAP driver operation -+ * Please see ffa_unmap_rxtx_buffers_hdlr() description for more details. -+ */ -+int ffa_rxtx_unmap(struct udevice *dev); -+ -+/** -+ * ffa_unmap_rxtx_buffers_hdlr() - FFA_RXTX_UNMAP handler function -+ * @dev: The arm_ffa bus device -+ * -+ * This function implements FFA_RXTX_UNMAP FF-A function -+ * to unmap the RX/TX buffers -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+int ffa_unmap_rxtx_buffers_hdlr(struct udevice *dev); -+ -+/** -+ * ffa_sync_send_receive() - FFA_MSG_SEND_DIRECT_{REQ,RESP} driver operation -+ * Please see ffa_msg_send_direct_req_hdlr() description for more details. -+ */ -+int ffa_sync_send_receive(struct udevice *dev, u16 dst_part_id, -+ struct ffa_send_direct_data *msg, bool is_smc64); -+ -+/** -+ * ffa_msg_send_direct_req_hdlr() - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function -+ * @dev: The arm_ffa bus device -+ * @dst_part_id: destination partition ID -+ * @msg: pointer to the message data preallocated by the client (in/out) -+ * @is_smc64: select 64-bit or 32-bit FF-A ABI -+ * -+ * This function implements FFA_MSG_SEND_DIRECT_{REQ,RESP} -+ * FF-A functions. -+ * -+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition. -+ * The response from the secure partition is handled by reading the -+ * FFA_MSG_SEND_DIRECT_RESP arguments. -+ * -+ * The maximum size of the data that can be exchanged is 40 bytes which is -+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0 -+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP} -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id, -+ struct ffa_send_direct_data *msg, bool is_smc64); -+ -+/** -+ * ffa_partition_info_get() - FFA_PARTITION_INFO_GET driver operation -+ * Please see ffa_get_partitions_info_hdlr() description for more details. -+ */ -+int ffa_partition_info_get(struct udevice *dev, const char *uuid_str, -+ u32 *sp_count, struct ffa_partition_desc **sp_descs); -+ -+/** -+ * ffa_get_partitions_info_hdlr() - FFA_PARTITION_INFO_GET handler function -+ * @uuid_str: pointer to the UUID string -+ * @sp_count: address of the variable containing the number of partitions matching the UUID -+ * The variable is set by the driver -+ * @sp_descs: address of the descriptors of the partitions matching the UUID -+ * The address is set by the driver -+ * -+ * Return the number of partitions and their descriptors matching the UUID -+ * -+ * Query the secure partition data from uc_priv. -+ * If not found, invoke FFA_PARTITION_INFO_GET -+ * FF-A function to query the partition information from secure world. -+ * -+ * A client of the FF-A driver should know the UUID of the service it wants to -+ * access. It should use the UUID to request the FF-A driver to provide the -+ * partition(s) information of the service. The FF-A driver uses -+ * PARTITION_INFO_GET to obtain this information. This is implemented through -+ * ffa_get_partitions_info_hdlr() function. -+ * A new FFA_PARTITION_INFO_GET call is issued (first one performed through -+ * ffa_cache_partitions_info) allowing to retrieve the partition(s) information. -+ * They are not saved (already done). We only update the UUID in the cached area. -+ * This assumes that partitions data does not change in the secure world. -+ * Otherwise u-boot will have an outdated partition data. The benefit of caching -+ * the information in the FF-A driver is to accommodate discovery after -+ * ExitBootServices(). -+ * -+ * Return: -+ * -+ * @sp_count: the number of partitions -+ * @sp_descs: address of the partitions descriptors -+ * -+ * On success 0 is returned. Otherwise, failure -+ */ -+int ffa_get_partitions_info_hdlr(struct udevice *dev, const char *uuid_str, -+ u32 *sp_count, struct ffa_partition_desc **sp_descs); -+ -+struct ffa_priv; -+ -+/** -+ * ffa_set_smc_conduit() - Set the SMC conduit -+ * @dev: The FF-A bus device -+ * -+ * Selects the SMC conduit by setting the FF-A ABI invoke function. -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+int ffa_set_smc_conduit(struct udevice *dev); -+ -+#endif -diff --git a/include/arm_ffa_priv.h b/include/arm_ffa_priv.h -new file mode 100644 -index 0000000000..d564c33c64 ---- /dev/null -+++ b/include/arm_ffa_priv.h -@@ -0,0 +1,246 @@ -+/* SPDX-License-Identifier: GPL-2.0+ */ -+/* -+ * Copyright 2022-2023 Arm Limited and/or its affiliates -+ * -+ * Authors: -+ * Abdellatif El Khlifi -+ */ -+ -+#ifndef __ARM_FFA_PRV_H -+#define __ARM_FFA_PRV_H -+ -+#include -+#include -+#include -+ -+/* This header is exclusively used by the FF-A Uclass and FF-A driver(s) */ -+ -+/* Arm FF-A driver name */ -+#define FFA_DRV_NAME "arm_ffa" -+ -+/* The FF-A SMC function definitions */ -+ -+#if CONFIG_IS_ENABLED(SANDBOX) -+ -+/* Providing Arm SMCCC declarations to sandbox */ -+ -+/** -+ * struct sandbox_smccc_1_2_regs - emulated SMC call arguments or results -+ * @a0-a17 argument values from registers 0 to 17 -+ */ -+struct sandbox_smccc_1_2_regs { -+ ulong a0; -+ ulong a1; -+ ulong a2; -+ ulong a3; -+ ulong a4; -+ ulong a5; -+ ulong a6; -+ ulong a7; -+ ulong a8; -+ ulong a9; -+ ulong a10; -+ ulong a11; -+ ulong a12; -+ ulong a13; -+ ulong a14; -+ ulong a15; -+ ulong a16; -+ ulong a17; -+}; -+ -+typedef struct sandbox_smccc_1_2_regs ffa_value_t; -+ -+#define ARM_SMCCC_FAST_CALL 1UL -+#define ARM_SMCCC_OWNER_STANDARD 4 -+#define ARM_SMCCC_SMC_32 0 -+#define ARM_SMCCC_SMC_64 1 -+#define ARM_SMCCC_TYPE_SHIFT 31 -+#define ARM_SMCCC_CALL_CONV_SHIFT 30 -+#define ARM_SMCCC_OWNER_MASK 0x3f -+#define ARM_SMCCC_OWNER_SHIFT 24 -+#define ARM_SMCCC_FUNC_MASK 0xffff -+ -+#define ARM_SMCCC_CALL_VAL(type, calling_convention, owner, func_num) \ -+ (((type) << ARM_SMCCC_TYPE_SHIFT) | \ -+ ((calling_convention) << ARM_SMCCC_CALL_CONV_SHIFT) | \ -+ (((owner) & ARM_SMCCC_OWNER_MASK) << ARM_SMCCC_OWNER_SHIFT) | \ -+ ((func_num) & ARM_SMCCC_FUNC_MASK)) -+ -+#else -+/* CONFIG_ARM64 */ -+#include -+typedef struct arm_smccc_1_2_regs ffa_value_t; -+#endif -+ -+/* Defining the function pointer type for the function executing the FF-A ABIs */ -+typedef void (*invoke_ffa_fn_t)(ffa_value_t args, ffa_value_t *res); -+ -+/* FF-A driver version definitions */ -+ -+#define MAJOR_VERSION_MASK GENMASK(30, 16) -+#define MINOR_VERSION_MASK GENMASK(15, 0) -+#define GET_FFA_MAJOR_VERSION(x) \ -+ ((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x)))) -+#define GET_FFA_MINOR_VERSION(x) \ -+ ((u16)(FIELD_GET(MINOR_VERSION_MASK, (x)))) -+#define PACK_VERSION_INFO(major, minor) \ -+ (FIELD_PREP(MAJOR_VERSION_MASK, (major)) | \ -+ FIELD_PREP(MINOR_VERSION_MASK, (minor))) -+ -+#define FFA_MAJOR_VERSION (1) -+#define FFA_MINOR_VERSION (0) -+#define FFA_VERSION_1_0 \ -+ PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION) -+ -+/* Endpoint ID mask (u-boot endpoint ID) */ -+ -+#define GET_SELF_ENDPOINT_ID_MASK GENMASK(15, 0) -+#define GET_SELF_ENDPOINT_ID(x) \ -+ ((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x)))) -+ -+#define PREP_SELF_ENDPOINT_ID_MASK GENMASK(31, 16) -+#define PREP_SELF_ENDPOINT_ID(x) \ -+ (FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x))) -+ -+/* Partition endpoint ID mask (partition with which u-boot communicates with) */ -+ -+#define PREP_PART_ENDPOINT_ID_MASK GENMASK(15, 0) -+#define PREP_PART_ENDPOINT_ID(x) \ -+ (FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x))) -+ -+/* Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver */ -+ -+#define FFA_SMC(calling_convention, func_num) \ -+ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention), \ -+ ARM_SMCCC_OWNER_STANDARD, (func_num)) -+ -+#define FFA_SMC_32(func_num) FFA_SMC(ARM_SMCCC_SMC_32, (func_num)) -+#define FFA_SMC_64(func_num) FFA_SMC(ARM_SMCCC_SMC_64, (func_num)) -+ -+enum ffa_abis { -+ FFA_ERROR = 0x60, -+ FFA_SUCCESS = 0x61, -+ FFA_INTERRUPT = 0x62, -+ FFA_VERSION = 0x63, -+ FFA_FEATURES = 0x64, -+ FFA_RX_RELEASE = 0x65, -+ FFA_RXTX_MAP = 0x66, -+ FFA_RXTX_UNMAP = 0x67, -+ FFA_PARTITION_INFO_GET = 0x68, -+ FFA_ID_GET = 0x69, -+ FFA_RUN = 0x6d, -+ FFA_MSG_SEND_DIRECT_REQ = 0x6f, -+ FFA_MSG_SEND_DIRECT_RESP = 0x70, -+ -+ /* To be updated when adding new FFA IDs */ -+ FFA_FIRST_ID = FFA_ERROR, /* Lowest number ID */ -+ FFA_LAST_ID = FFA_MSG_SEND_DIRECT_RESP, /* Highest number ID */ -+}; -+ -+enum ffa_abi_errcode { -+ NOT_SUPPORTED = 1, -+ INVALID_PARAMETERS, -+ NO_MEMORY, -+ BUSY, -+ INTERRUPTED, -+ DENIED, -+ RETRY, -+ ABORTED, -+ MAX_NUMBER_FFA_ERR -+}; -+ -+extern int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR]; -+ -+/* Container structure and helper macros to map between an FF-A error and relevant error log */ -+struct ffa_abi_errmap { -+ char *err_str[MAX_NUMBER_FFA_ERR]; -+}; -+ -+#define FFA_ERRMAP_COUNT (FFA_LAST_ID - FFA_FIRST_ID + 1) -+#define FFA_ID_TO_ERRMAP_ID(ffa_id) ((ffa_id) - FFA_FIRST_ID) -+ -+/** -+ * enum ffa_rxtx_buf_sizes - minimum sizes supported -+ * for the RX/TX buffers -+ */ -+enum ffa_rxtx_buf_sizes { -+ RXTX_4K, -+ RXTX_64K, -+ RXTX_16K -+}; -+ -+/** -+ * struct ffa_rxtxpair - Hosts the RX/TX buffers virtual addresses -+ * @rxbuf: virtual address of the RX buffer -+ * @txbuf: virtual address of the TX buffer -+ * @rxtx_min_pages: RX/TX buffers minimum size in pages -+ * -+ * Hosts the virtual addresses of the mapped RX/TX buffers -+ * These addresses are used by the FF-A functions that use the RX/TX buffers -+ */ -+struct ffa_rxtxpair { -+ void *rxbuf; /* Virtual address returned by memalign */ -+ void *txbuf; /* Virtual address returned by memalign */ -+ size_t rxtx_min_pages; /* Minimum number of pages in each of the RX/TX buffers */ -+}; -+ -+struct ffa_partition_desc; -+ -+/** -+ * struct ffa_partitions - descriptors for all secure partitions -+ * @count: The number of partitions descriptors -+ * @descs The partitions descriptors table -+ * -+ * Contains the partitions descriptors table -+ */ -+struct ffa_partitions { -+ u32 count; -+ struct ffa_partition_desc *descs; /* Virtual address */ -+}; -+ -+/** -+ * struct ffa_priv - the driver private data structure -+ * -+ * @fwk_version: FF-A framework version -+ * @emul: FF-A sandbox emulator -+ * @id: u-boot endpoint ID -+ * @partitions: The partitions descriptors structure -+ * @pair: The RX/TX buffers pair -+ * -+ * The device private data structure containing all the -+ * data read from secure world. -+ */ -+struct ffa_priv { -+ u32 fwk_version; -+ struct udevice *emul; -+ u16 id; -+ struct ffa_partitions partitions; -+ struct ffa_rxtxpair pair; -+}; -+ -+/** -+ * ffa_get_version_hdlr() - FFA_VERSION handler function -+ * @dev: The FF-A bus device -+ * -+ * Implement FFA_VERSION FF-A function -+ * to get from the secure world the FF-A framework version -+ * FFA_VERSION is used to discover the FF-A framework. -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+int ffa_get_version_hdlr(struct udevice *dev); -+ -+/** -+ * invoke_ffa_fn() - SMC wrapper -+ * @args: FF-A ABI arguments to be copied to Xn registers -+ * @res: FF-A ABI return data to be copied from Xn registers -+ * -+ * Calls low level SMC implementation. -+ * This function should be implemented by the user driver. -+ */ -+void invoke_ffa_fn(ffa_value_t args, ffa_value_t *res); -+ -+#endif -diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h -index 307ad6931c..3c6af2e3d2 100644 ---- a/include/dm/uclass-id.h -+++ b/include/dm/uclass-id.h -@@ -4,6 +4,11 @@ - * - * (C) Copyright 2012 - * Pavel Herrmann -+ * -+ * Copyright 2022-2023 Arm Limited and/or its affiliates -+ * -+ * Authors: -+ * Abdellatif El Khlifi - */ - - #ifndef _DM_UCLASS_ID_H -@@ -57,6 +62,7 @@ enum uclass_id { - UCLASS_ETH, /* Ethernet device */ - UCLASS_ETH_PHY, /* Ethernet PHY device */ - UCLASS_EXTCON, /* External Connector Class */ -+ UCLASS_FFA, /* Arm Firmware Framework for Armv8-A */ - UCLASS_FIRMWARE, /* Firmware */ - UCLASS_FPGA, /* FPGA device */ - UCLASS_FUZZING_ENGINE, /* Fuzzing engine */ diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0004-arm_ffa-sandbox-Replace-the-emulator-error-log-with-.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0004-arm_ffa-sandbox-Replace-the-emulator-error-log-with-.patch new file mode 100644 index 00000000..5ffb7a06 --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0004-arm_ffa-sandbox-Replace-the-emulator-error-log-with-.patch @@ -0,0 +1,43 @@ +From 939406ee3612ad261a51c002655e90431741aa78 Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Thu, 17 Oct 2024 22:11:22 +0100 +Subject: [PATCH 04/36] arm_ffa: sandbox: Replace the emulator error log with + debug log + +Set the log to a debug log and reformulate the message + +The message is about showing what the emulated FF-A ABI decided +based on the user arguments. The log is just for information purposes +and helpful when debugging. + +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20250702152528.1180414-1-abdellatif.elkhlifi@arm.com/] +--- + drivers/firmware/arm-ffa/ffa-emul-uclass.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/firmware/arm-ffa/ffa-emul-uclass.c b/drivers/firmware/arm-ffa/ffa-emul-uclass.c +index 1521d9b66ac..d2f051f7e2a 100644 +--- a/drivers/firmware/arm-ffa/ffa-emul-uclass.c ++++ b/drivers/firmware/arm-ffa/ffa-emul-uclass.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0+ + /* +- * Copyright 2022-2023 Arm Limited and/or its affiliates ++ * Copyright 2022-2023, 2025 Arm Limited and/or its affiliates + * + * Authors: + * Abdellatif El Khlifi +@@ -658,8 +658,7 @@ void sandbox_arm_ffa_smccc_smc(ffa_value_t *args, ffa_value_t *res) + args->a0); + } + +- if (ret != 0) +- log_err("FF-A ABI internal failure (%d)\n", ret); ++ log_debug("Emulated FF-A ABI feedback (%d)\n", ret); + } + + /** +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0005-FF-A-v15-arm_ffa-introduce-armffa-command.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0005-FF-A-v15-arm_ffa-introduce-armffa-command.patch deleted file mode 100644 index 8672652b..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0005-FF-A-v15-arm_ffa-introduce-armffa-command.patch +++ /dev/null @@ -1,433 +0,0 @@ -From 57e4d6e9c5fc174a96366268150bc85de75baa79 Mon Sep 17 00:00:00 2001 -From: Abdellatif El Khlifi -Date: Wed, 10 May 2023 17:27:01 +0100 -Subject: [PATCH] FF-A v15: arm_ffa: introduce armffa command - -Provide armffa command showcasing the use of the U-Boot FF-A support - -armffa is a command showcasing how to invoke FF-A operations. -This provides a guidance to the client developers on how to -call the FF-A bus interfaces. The command also allows to gather secure -partitions information and ping these partitions. The command is also -helpful in testing the communication with secure partitions. - -For more details please refer to the command documentation [1]. - -[1]: doc/usage/cmd/armffa.rst - -Signed-off-by: Abdellatif El Khlifi -Reviewed-by: Simon Glass -Cc: Tom Rini -Cc: Ilias Apalodimas -Cc: Jens Wiklander -Cc: Heinrich Schuchardt -Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20230713132847.176000-1-abdellatif.elkhlifi@arm.com/] ---- - MAINTAINERS | 2 + - cmd/Kconfig | 10 ++ - cmd/Makefile | 1 + - cmd/armffa.c | 202 +++++++++++++++++++++++++++++++ - doc/arch/arm64.ffa.rst | 7 ++ - doc/usage/cmd/armffa.rst | 93 ++++++++++++++ - doc/usage/index.rst | 1 + - drivers/firmware/arm-ffa/Kconfig | 1 + - 8 files changed, 317 insertions(+) - create mode 100644 cmd/armffa.c - create mode 100644 doc/usage/cmd/armffa.rst - -diff --git a/MAINTAINERS b/MAINTAINERS -index 9c5ebf312c..4ae82229fc 100644 ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -269,7 +269,9 @@ F: configs/cortina_presidio-asic-pnand_defconfig - ARM FF-A - M: Abdellatif El Khlifi - S: Maintained -+F: cmd/armffa.c - F: doc/arch/arm64.ffa.rst -+F: doc/usage/cmd/armffa.rst - F: drivers/firmware/arm-ffa/ - F: include/arm_ffa.h - F: include/sandbox_arm_ffa.h -diff --git a/cmd/Kconfig b/cmd/Kconfig -index 02e54f1e50..79b4f8367a 100644 ---- a/cmd/Kconfig -+++ b/cmd/Kconfig -@@ -935,6 +935,16 @@ endmenu - - menu "Device access commands" - -+config CMD_ARMFFA -+ bool "Arm FF-A test command" -+ depends on ARM_FFA_TRANSPORT -+ help -+ Provides a test command for the FF-A support -+ supported options: -+ - Listing the partition(s) info -+ - Sending a data pattern to the specified partition -+ - Displaying the arm_ffa device info -+ - config CMD_ARMFLASH - #depends on FLASH_CFI_DRIVER - bool "armflash" -diff --git a/cmd/Makefile b/cmd/Makefile -index 6c37521b4e..7d20a85a46 100644 ---- a/cmd/Makefile -+++ b/cmd/Makefile -@@ -12,6 +12,7 @@ obj-y += panic.o - obj-y += version.o - - # command -+obj-$(CONFIG_CMD_ARMFFA) += armffa.o - obj-$(CONFIG_CMD_2048) += 2048.o - obj-$(CONFIG_CMD_ACPI) += acpi.o - obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o -diff --git a/cmd/armffa.c b/cmd/armffa.c -new file mode 100644 -index 0000000000..7e6eafc03a ---- /dev/null -+++ b/cmd/armffa.c -@@ -0,0 +1,202 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Copyright 2022-2023 Arm Limited and/or its affiliates -+ * -+ * Authors: -+ * Abdellatif El Khlifi -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* Select the right physical address formatting according to the platform */ -+#ifdef CONFIG_PHYS_64BIT -+#define PhysAddrLength "ll" -+#else -+#define PhysAddrLength "" -+#endif -+#define PHYS_ADDR_LN "%" PhysAddrLength "x" -+ -+/** -+ * ffa_get_dev() - Return the FF-A device -+ * @devp: pointer to the FF-A device -+ * -+ * Search for the FF-A device. -+ * -+ * Return: -+ * 0 on success. Otherwise, failure -+ */ -+static int ffa_get_dev(struct udevice **devp) -+{ -+ int ret; -+ -+ ret = uclass_first_device_err(UCLASS_FFA, devp); -+ if (ret) { -+ log_err("Cannot find FF-A bus device\n"); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+/** -+ * do_ffa_getpart() - implementation of the getpart subcommand -+ * @cmdtp: Command Table -+ * @flag: flags -+ * @argc: number of arguments -+ * @argv: arguments -+ * -+ * Query a secure partition information. The secure partition UUID is provided -+ * as an argument. The function uses the arm_ffa driver -+ * partition_info_get operation which implements FFA_PARTITION_INFO_GET -+ * ABI to retrieve the data. The input UUID string is expected to be in big -+ * endian format. -+ * -+ * Return: -+ * -+ * CMD_RET_SUCCESS: on success, otherwise failure -+ */ -+static int do_ffa_getpart(struct cmd_tbl *cmdtp, int flag, int argc, -+ char *const argv[]) -+{ -+ u32 count = 0; -+ int ret; -+ struct ffa_partition_desc *descs; -+ u32 i; -+ struct udevice *dev; -+ -+ if (argc != 2) { -+ log_err("Missing argument\n"); -+ return CMD_RET_USAGE; -+ } -+ -+ ret = ffa_get_dev(&dev); -+ if (ret) -+ return CMD_RET_FAILURE; -+ -+ /* Ask the driver to fill the buffer with the SPs info */ -+ -+ ret = ffa_partition_info_get(dev, argv[1], &count, &descs); -+ if (ret) { -+ log_err("Failure in querying partition(s) info (error code: %d)\n", ret); -+ return CMD_RET_FAILURE; -+ } -+ -+ /* SPs found , show the partition information */ -+ for (i = 0; i < count ; i++) { -+ log_info("Partition: id = %x , exec_ctxt %x , properties %x\n", -+ descs[i].info.id, -+ descs[i].info.exec_ctxt, -+ descs[i].info.properties); -+ } -+ -+ return CMD_RET_SUCCESS; -+} -+ -+/** -+ * do_ffa_ping() - implementation of the ping subcommand -+ * @cmdtp: Command Table -+ * @flag: flags -+ * @argc: number of arguments -+ * @argv: arguments -+ * -+ * Send data to a secure partition. The secure partition UUID is provided -+ * as an argument. Use the arm_ffa driver sync_send_receive operation -+ * which implements FFA_MSG_SEND_DIRECT_{REQ,RESP} ABIs to send/receive data. -+ * -+ * Return: -+ * -+ * CMD_RET_SUCCESS: on success, otherwise failure -+ */ -+static int do_ffa_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) -+{ -+ struct ffa_send_direct_data msg = { -+ .data0 = 0xaaaaaaaa, -+ .data1 = 0xbbbbbbbb, -+ .data2 = 0xcccccccc, -+ .data3 = 0xdddddddd, -+ .data4 = 0xeeeeeeee, -+ }; -+ u16 part_id; -+ int ret; -+ struct udevice *dev; -+ -+ if (argc != 2) { -+ log_err("Missing argument\n"); -+ return CMD_RET_USAGE; -+ } -+ -+ part_id = strtoul(argv[1], NULL, 16); -+ if (!part_id) { -+ log_err("Partition ID can not be 0\n"); -+ return CMD_RET_USAGE; -+ } -+ -+ ret = ffa_get_dev(&dev); -+ if (ret) -+ return CMD_RET_FAILURE; -+ -+ ret = ffa_sync_send_receive(dev, part_id, &msg, 1); -+ if (!ret) { -+ u8 cnt; -+ -+ log_info("SP response:\n[LSB]\n"); -+ for (cnt = 0; -+ cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64); -+ cnt++) -+ log_info("%llx\n", ((u64 *)&msg)[cnt]); -+ return CMD_RET_SUCCESS; -+ } -+ -+ log_err("Sending direct request error (%d)\n", ret); -+ return CMD_RET_FAILURE; -+} -+ -+/** -+ *do_ffa_devlist() - implementation of the devlist subcommand -+ * @cmdtp: [in] Command Table -+ * @flag: flags -+ * @argc: number of arguments -+ * @argv: arguments -+ * -+ * Query the device belonging to the UCLASS_FFA -+ * class. -+ * -+ * Return: -+ * -+ * CMD_RET_SUCCESS: on success, otherwise failure -+ */ -+static int do_ffa_devlist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) -+{ -+ struct udevice *dev; -+ int ret; -+ -+ ret = ffa_get_dev(&dev); -+ if (ret) -+ return CMD_RET_FAILURE; -+ -+ log_info("device %s, addr " PHYS_ADDR_LN ", driver %s, ops " PHYS_ADDR_LN "\n", -+ dev->name, -+ map_to_sysmem(dev), -+ dev->driver->name, -+ map_to_sysmem(dev->driver->ops)); -+ -+ return CMD_RET_SUCCESS; -+} -+ -+static char armffa_help_text[] = -+ "getpart \n" -+ " - lists the partition(s) info\n" -+ "ping \n" -+ " - sends a data pattern to the specified partition\n" -+ "devlist\n" -+ " - displays information about the FF-A device/driver\n"; -+ -+U_BOOT_CMD_WITH_SUBCMDS(armffa, "Arm FF-A test command", armffa_help_text, -+ U_BOOT_SUBCMD_MKENT(getpart, 2, 1, do_ffa_getpart), -+ U_BOOT_SUBCMD_MKENT(ping, 2, 1, do_ffa_ping), -+ U_BOOT_SUBCMD_MKENT(devlist, 1, 1, do_ffa_devlist)); -diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst -index 4f817f053c..aefd527447 100644 ---- a/doc/arch/arm64.ffa.rst -+++ b/doc/arch/arm64.ffa.rst -@@ -205,6 +205,13 @@ The following features are provided: - - - FF-A bus can be compiled and used without EFI - -+The armffa command -+----------------------------------- -+ -+armffa is a command showcasing how to use the FF-A bus and how to invoke the driver operations. -+ -+Please refer the command documentation at :doc:`../usage/cmd/armffa` -+ - Example of boot logs with FF-A enabled - -------------------------------------- - -diff --git a/doc/usage/cmd/armffa.rst b/doc/usage/cmd/armffa.rst -new file mode 100644 -index 0000000000..3d422686c1 ---- /dev/null -+++ b/doc/usage/cmd/armffa.rst -@@ -0,0 +1,93 @@ -+.. SPDX-License-Identifier: GPL-2.0+: -+ -+armffa command -+============== -+ -+Synopsis -+-------- -+ -+:: -+ -+ armffa [sub-command] [arguments] -+ -+ sub-commands: -+ -+ getpart [partition UUID] -+ -+ lists the partition(s) info -+ -+ ping [partition ID] -+ -+ sends a data pattern to the specified partition -+ -+ devlist -+ -+ displays information about the FF-A device/driver -+ -+Description -+----------- -+ -+armffa is a command showcasing how to use the FF-A bus and how to invoke its operations. -+ -+This provides a guidance to the client developers on how to call the FF-A bus interfaces. -+ -+The command also allows to gather secure partitions information and ping these partitions. -+ -+The command is also helpful in testing the communication with secure partitions. -+ -+Example -+------- -+ -+The following examples are run on Corstone-1000 platform. -+ -+* ping -+ -+:: -+ -+ corstone1000# armffa ping 0x8003 -+ SP response: -+ [LSB] -+ fffffffe -+ 0 -+ 0 -+ 0 -+ 0 -+ -+* ping (failure case) -+ -+:: -+ -+ corstone1000# armffa ping 0 -+ Sending direct request error (-22) -+ -+* getpart -+ -+:: -+ -+ corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd722d -+ Partition: id = 8003 , exec_ctxt 1 , properties 3 -+ -+* getpart (failure case) -+ -+:: -+ -+ corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd7221 -+ INVALID_PARAMETERS: Unrecognized UUID -+ Failure in querying partitions count (error code: -22) -+ -+* devlist -+ -+:: -+ -+ corstone1000# armffa devlist -+ device name arm_ffa, dev 00000000fdf41c30, driver name arm_ffa, ops 00000000fffc0e98 -+ -+Configuration -+------------- -+ -+The command is available if CONFIG_CMD_ARMFFA=y and CONFIG_ARM_FFA_TRANSPORT=y. -+ -+Return value -+------------ -+ -+The return value $? is 0 (true) on success, 1 (false) on failure. -diff --git a/doc/usage/index.rst b/doc/usage/index.rst -index 388e59f173..e462de2806 100644 ---- a/doc/usage/index.rst -+++ b/doc/usage/index.rst -@@ -22,6 +22,7 @@ Shell commands - - cmd/acpi - cmd/addrmap -+ cmd/armffa - cmd/askenv - cmd/base - cmd/bdinfo -diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig -index 9200c8028b..a7d5392859 100644 ---- a/drivers/firmware/arm-ffa/Kconfig -+++ b/drivers/firmware/arm-ffa/Kconfig -@@ -5,6 +5,7 @@ config ARM_FFA_TRANSPORT - depends on DM && ARM64 - select ARM_SMCCC - select ARM_SMCCC_FEATURES -+ imply CMD_ARMFFA - select LIB_UUID - select DEVRES - help diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0005-arm_ffa-sandbox-Improve-the-readability-of-clearing-.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0005-arm_ffa-sandbox-Improve-the-readability-of-clearing-.patch new file mode 100644 index 00000000..f3d4eefa --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0005-arm_ffa-sandbox-Improve-the-readability-of-clearing-.patch @@ -0,0 +1,128 @@ +From 20f7e4fcd4aec29729c7c3ab2e9dbfe69a04d167 Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Tue, 11 Feb 2025 17:54:45 +0000 +Subject: [PATCH 05/36] arm_ffa: sandbox: Improve the readability of clearing + the X registers + +Make clearing the must be zero registers more readable in the emulator + +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20250702152528.1180414-1-abdellatif.elkhlifi@arm.com/] +--- + .../sandbox/include/asm/sandbox_arm_ffa_priv.h | 15 ++------------- + drivers/firmware/arm-ffa/ffa-emul-uclass.c | 18 +++++++++--------- + 2 files changed, 11 insertions(+), 22 deletions(-) + +diff --git a/arch/sandbox/include/asm/sandbox_arm_ffa_priv.h b/arch/sandbox/include/asm/sandbox_arm_ffa_priv.h +index b0881822d78..5c46547beab 100644 +--- a/arch/sandbox/include/asm/sandbox_arm_ffa_priv.h ++++ b/arch/sandbox/include/asm/sandbox_arm_ffa_priv.h +@@ -39,19 +39,8 @@ + #define RXTX_BUFFERS_MIN_SIZE (RXTX_4K) + #define RXTX_BUFFERS_MIN_PAGES (1) + +-/* MBZ registers info */ +- +-/* x1-x7 MBZ */ +-#define FFA_X1X7_MBZ_CNT (7) +-#define FFA_X1X7_MBZ_REG_START (&res->a1) +- +-/* x4-x7 MBZ */ +-#define FFA_X4X7_MBZ_CNT (4) +-#define FFA_X4X7_MBZ_REG_START (&res->a4) +- +-/* x3-x7 MBZ */ +-#define FFA_X3X7_MBZ_CNT (5) +-#define FFA_X3_MBZ_REG_START (&res->a3) ++/* A helper macro used for clearing registers that Must Be Zero (MBZ) */ ++#define FFA_X_REG_SIZE_IN_BYTE sizeof((((ffa_value_t *)0)->a0)) + + /* number of emulated FF-A secure partitions (SPs) */ + #define SANDBOX_PARTITIONS_CNT (4) +diff --git a/drivers/firmware/arm-ffa/ffa-emul-uclass.c b/drivers/firmware/arm-ffa/ffa-emul-uclass.c +index d2f051f7e2a..dcf5bce9435 100644 +--- a/drivers/firmware/arm-ffa/ffa-emul-uclass.c ++++ b/drivers/firmware/arm-ffa/ffa-emul-uclass.c +@@ -83,7 +83,7 @@ static int sandbox_ffa_version(struct udevice *emul, ffa_value_t *pargs, ffa_val + res->a0 = priv->fwk_version; + + /* x1-x7 MBZ */ +- memset(FFA_X1X7_MBZ_REG_START, 0, FFA_X1X7_MBZ_CNT * sizeof(ulong)); ++ memset(&res->a1, 0, 7 * FFA_X_REG_SIZE_IN_BYTE); + + return 0; + } +@@ -111,7 +111,7 @@ static int sandbox_ffa_id_get(struct udevice *emul, ffa_value_t *pargs, ffa_valu + res->a2 = priv->id; + + /* x3-x7 MBZ */ +- memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong)); ++ memset(&res->a3, 0, 5 * FFA_X_REG_SIZE_IN_BYTE); + + return 0; + } +@@ -136,14 +136,14 @@ static int sandbox_ffa_features(ffa_value_t *pargs, ffa_value_t *res) + res->a2 = RXTX_BUFFERS_MIN_SIZE; + res->a3 = 0; + /* x4-x7 MBZ */ +- memset(FFA_X4X7_MBZ_REG_START, 0, FFA_X4X7_MBZ_CNT * sizeof(ulong)); ++ memset(&res->a4, 0, 4 * FFA_X_REG_SIZE_IN_BYTE); + return 0; + } + + res->a0 = FFA_SMC_32(FFA_ERROR); + res->a2 = -NOT_SUPPORTED; + /* x3-x7 MBZ */ +- memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong)); ++ memset(&res->a3, 0, 5 * FFA_X_REG_SIZE_IN_BYTE); + log_err("FF-A interface %lx not implemented\n", pargs->a1); + + return ffa_to_std_errmap[NOT_SUPPORTED]; +@@ -248,7 +248,7 @@ cleanup: + res->a1 = 0; + + /* x3-x7 MBZ */ +- memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong)); ++ memset(&res->a3, 0, 5 * FFA_X_REG_SIZE_IN_BYTE); + + return ret; + } +@@ -305,7 +305,7 @@ feedback: + res->a1 = 0; + + /* x3-x7 MBZ */ +- memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong)); ++ memset(&res->a3, 0, 5 * FFA_X_REG_SIZE_IN_BYTE); + + return ret; + } +@@ -352,7 +352,7 @@ feedback: + res->a1 = 0; + + /* x3-x7 MBZ */ +- memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong)); ++ memset(&res->a3, 0, 5 * FFA_X_REG_SIZE_IN_BYTE); + + return ret; + } +@@ -388,7 +388,7 @@ static int sandbox_ffa_rx_release(struct udevice *emul, ffa_value_t *pargs, ffa_ + res->a1 = 0; + + /* x3-x7 MBZ */ +- memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong)); ++ memset(&res->a3, 0, 5 * FFA_X_REG_SIZE_IN_BYTE); + + return ret; + } +@@ -448,7 +448,7 @@ static int sandbox_ffa_msg_send_direct_req(struct udevice *emul, + res->a2 = -INVALID_PARAMETERS; + + /* x3-x7 MBZ */ +- memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong)); ++ memset(&res->a3, 0, 5 * FFA_X_REG_SIZE_IN_BYTE); + + return ffa_to_std_errmap[INVALID_PARAMETERS]; + } +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0006-FF-A-v15-arm_ffa-introduce-sandbox-FF-A-support.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0006-FF-A-v15-arm_ffa-introduce-sandbox-FF-A-support.patch deleted file mode 100644 index c0078b80..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0006-FF-A-v15-arm_ffa-introduce-sandbox-FF-A-support.patch +++ /dev/null @@ -1,1311 +0,0 @@ -From b05ab0973850069d819872e26fae2aecbbf75f0e Mon Sep 17 00:00:00 2001 -From: Abdellatif El Khlifi -Date: Mon, 17 Jul 2023 15:18:58 +0100 -Subject: [PATCH] FF-A v15: arm_ffa: introduce sandbox FF-A support - -Emulate Secure World's FF-A ABIs and allow testing U-Boot FF-A support - -Features of the sandbox FF-A support: - -- Introduce an FF-A emulator -- Introduce an FF-A device driver for FF-A comms with emulated Secure World -- Provides test methods allowing to read the status of the inspected ABIs - -The sandbox FF-A emulator supports only 64-bit direct messaging. - -Signed-off-by: Abdellatif El Khlifi -Reviewed-by: Simon Glass -Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20230713132847.176000-1-abdellatif.elkhlifi@arm.com/] ---- - MAINTAINERS | 3 +- - arch/sandbox/dts/sandbox.dtsi | 9 + - arch/sandbox/dts/test.dts | 9 + - arch/sandbox/include/asm/sandbox_arm_ffa.h | 72 ++ - .../include/asm/sandbox_arm_ffa_priv.h | 121 +++ - configs/sandbox64_defconfig | 2 + - configs/sandbox_defconfig | 2 + - doc/arch/arm64.ffa.rst | 19 +- - doc/arch/sandbox/sandbox.rst | 1 + - drivers/firmware/arm-ffa/Kconfig | 13 +- - drivers/firmware/arm-ffa/Makefile | 10 +- - drivers/firmware/arm-ffa/ffa-emul-uclass.c | 720 ++++++++++++++++++ - .../firmware/arm-ffa/sandbox_arm_ffa_priv.h | 14 - - drivers/firmware/arm-ffa/sandbox_ffa.c | 110 +++ - include/dm/uclass-id.h | 1 + - 15 files changed, 1084 insertions(+), 22 deletions(-) - create mode 100644 arch/sandbox/include/asm/sandbox_arm_ffa.h - create mode 100644 arch/sandbox/include/asm/sandbox_arm_ffa_priv.h - create mode 100644 drivers/firmware/arm-ffa/ffa-emul-uclass.c - delete mode 100644 drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h - create mode 100644 drivers/firmware/arm-ffa/sandbox_ffa.c - -diff --git a/MAINTAINERS b/MAINTAINERS -index 4ae82229fc..679a3acdd8 100644 ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -269,12 +269,13 @@ F: configs/cortina_presidio-asic-pnand_defconfig - ARM FF-A - M: Abdellatif El Khlifi - S: Maintained -+F: arch/sandbox/include/asm/sandbox_arm_ffa.h -+F: arch/sandbox/include/asm/sandbox_arm_ffa_priv.h - F: cmd/armffa.c - F: doc/arch/arm64.ffa.rst - F: doc/usage/cmd/armffa.rst - F: drivers/firmware/arm-ffa/ - F: include/arm_ffa.h --F: include/sandbox_arm_ffa.h - - ARM FREESCALE IMX - M: Stefano Babic -diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi -index 30a305c4d2..94a08814b8 100644 ---- a/arch/sandbox/dts/sandbox.dtsi -+++ b/arch/sandbox/dts/sandbox.dtsi -@@ -445,6 +445,15 @@ - thermal { - compatible = "sandbox,thermal"; - }; -+ -+ arm-ffa-emul { -+ compatible = "sandbox,arm-ffa-emul"; -+ -+ sandbox-arm-ffa { -+ compatible = "sandbox,arm-ffa"; -+ }; -+ }; -+ - }; - - &cros_ec { -diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts -index ff9f9222e6..c6807ee031 100644 ---- a/arch/sandbox/dts/test.dts -+++ b/arch/sandbox/dts/test.dts -@@ -1820,6 +1820,15 @@ - extcon { - compatible = "sandbox,extcon"; - }; -+ -+ arm-ffa-emul { -+ compatible = "sandbox,arm-ffa-emul"; -+ -+ sandbox-arm-ffa { -+ compatible = "sandbox,arm-ffa"; -+ }; -+ }; -+ - }; - - #include "sandbox_pmic.dtsi" -diff --git a/arch/sandbox/include/asm/sandbox_arm_ffa.h b/arch/sandbox/include/asm/sandbox_arm_ffa.h -new file mode 100644 -index 0000000000..be2790f496 ---- /dev/null -+++ b/arch/sandbox/include/asm/sandbox_arm_ffa.h -@@ -0,0 +1,72 @@ -+/* SPDX-License-Identifier: GPL-2.0+ */ -+/* -+ * Copyright 2022-2023 Arm Limited and/or its affiliates -+ * -+ * Authors: -+ * Abdellatif El Khlifi -+ */ -+ -+#ifndef __SANDBOX_ARM_FFA_H -+#define __SANDBOX_ARM_FFA_H -+ -+#include -+ -+/* -+ * This header provides public sandbox FF-A emulator declarations -+ * and declarations needed by FF-A sandbox clients -+ */ -+ -+/* UUIDs strings of the emulated services */ -+#define SANDBOX_SERVICE1_UUID "ed32d533-4209-99e6-2d72-cdd998a79cc0" -+#define SANDBOX_SERVICE2_UUID "ed32d544-4209-99e6-2d72-cdd998a79cc0" -+ -+/* IDs of the emulated secure partitions (SPs) */ -+#define SANDBOX_SP1_ID 0x1245 -+#define SANDBOX_SP2_ID 0x9836 -+#define SANDBOX_SP3_ID 0x6452 -+#define SANDBOX_SP4_ID 0x7814 -+ -+/* Invalid service UUID (no matching SP) */ -+#define SANDBOX_SERVICE3_UUID "55d532ed-0942-e699-722d-c09ca798d9cd" -+ -+/* Invalid service UUID (invalid UUID string format) */ -+#define SANDBOX_SERVICE4_UUID "32ed-0942-e699-722d-c09ca798d9cd" -+ -+/* Number of valid services */ -+#define SANDBOX_SP_COUNT_PER_VALID_SERVICE 2 -+ -+/** -+ * struct ffa_sandbox_data - query ABI state data structure -+ * @data0_size: size of the first argument -+ * @data0: pointer to the first argument -+ * @data1_size>: size of the second argument -+ * @data1: pointer to the second argument -+ * -+ * Used to pass various types of data with different sizes between -+ * the test cases and the sandbox emulator. -+ * The data is for querying FF-A ABIs state. -+ */ -+struct ffa_sandbox_data { -+ u32 data0_size; /* size of the first argument */ -+ void *data0; /* pointer to the first argument */ -+ u32 data1_size; /* size of the second argument */ -+ void *data1; /* pointer to the second argument */ -+}; -+ -+/* The sandbox FF-A emulator public functions */ -+ -+/** -+ * sandbox_query_ffa_emul_state() - Inspect the FF-A ABIs -+ * @queried_func_id: The FF-A function to be queried -+ * @func_data: Pointer to the FF-A function arguments container structure -+ * -+ * Query the status of FF-A ABI specified in the input argument. -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+int sandbox_query_ffa_emul_state(u32 queried_func_id, -+ struct ffa_sandbox_data *func_data); -+ -+#endif -diff --git a/arch/sandbox/include/asm/sandbox_arm_ffa_priv.h b/arch/sandbox/include/asm/sandbox_arm_ffa_priv.h -new file mode 100644 -index 0000000000..b0881822d7 ---- /dev/null -+++ b/arch/sandbox/include/asm/sandbox_arm_ffa_priv.h -@@ -0,0 +1,121 @@ -+/* SPDX-License-Identifier: GPL-2.0+ */ -+/* -+ * Copyright 2022-2023 Arm Limited and/or its affiliates -+ * -+ * Authors: -+ * Abdellatif El Khlifi -+ */ -+ -+#ifndef __SANDBOX_ARM_FFA_PRV_H -+#define __SANDBOX_ARM_FFA_PRV_H -+ -+#include -+ -+/* This header is exclusively used by the Sandbox FF-A driver and emulator */ -+ -+/* Non-secure physical FF-A instance */ -+#define NS_PHYS_ENDPOINT_ID (0) -+ -+#define GET_NS_PHYS_ENDPOINT_ID_MASK GENMASK(31, 16) -+#define GET_NS_PHYS_ENDPOINT_ID(x) \ -+ ((u16)(FIELD_GET(GET_NS_PHYS_ENDPOINT_ID_MASK, (x)))) -+ -+/* Helper macro for reading the destination partition ID */ -+#define GET_DST_SP_ID_MASK GENMASK(15, 0) -+#define GET_DST_SP_ID(x) \ -+ ((u16)(FIELD_GET(GET_DST_SP_ID_MASK, (x)))) -+ -+/* Helper macro for setting the source partition ID */ -+#define PREP_SRC_SP_ID_MASK GENMASK(31, 16) -+#define PREP_SRC_SP_ID(x) \ -+ (FIELD_PREP(PREP_SRC_SP_ID_MASK, (x))) -+ -+/* Helper macro for setting the destination endpoint ID */ -+#define PREP_NS_PHYS_ENDPOINT_ID_MASK GENMASK(15, 0) -+#define PREP_NS_PHYS_ENDPOINT_ID(x) \ -+ (FIELD_PREP(PREP_NS_PHYS_ENDPOINT_ID_MASK, (x))) -+ -+/* RX/TX buffers minimum size */ -+#define RXTX_BUFFERS_MIN_SIZE (RXTX_4K) -+#define RXTX_BUFFERS_MIN_PAGES (1) -+ -+/* MBZ registers info */ -+ -+/* x1-x7 MBZ */ -+#define FFA_X1X7_MBZ_CNT (7) -+#define FFA_X1X7_MBZ_REG_START (&res->a1) -+ -+/* x4-x7 MBZ */ -+#define FFA_X4X7_MBZ_CNT (4) -+#define FFA_X4X7_MBZ_REG_START (&res->a4) -+ -+/* x3-x7 MBZ */ -+#define FFA_X3X7_MBZ_CNT (5) -+#define FFA_X3_MBZ_REG_START (&res->a3) -+ -+/* number of emulated FF-A secure partitions (SPs) */ -+#define SANDBOX_PARTITIONS_CNT (4) -+ -+/* Binary data of the emulated services UUIDs */ -+ -+/* service 1 UUID binary data (little-endian format) */ -+#define SANDBOX_SERVICE1_UUID_A1 0xed32d533 -+#define SANDBOX_SERVICE1_UUID_A2 0x99e64209 -+#define SANDBOX_SERVICE1_UUID_A3 0x9cc02d72 -+#define SANDBOX_SERVICE1_UUID_A4 0xcdd998a7 -+ -+/* service 2 UUID binary data (little-endian format) */ -+#define SANDBOX_SERVICE2_UUID_A1 0xed32d544 -+#define SANDBOX_SERVICE2_UUID_A2 0x99e64209 -+#define SANDBOX_SERVICE2_UUID_A3 0x9cc02d72 -+#define SANDBOX_SERVICE2_UUID_A4 0xcdd998a7 -+ -+/** -+ * struct ffa_rxtxpair_info - structure hosting the RX/TX buffers flags -+ * @rxbuf_owned: RX buffer ownership flag (the owner is non secure world) -+ * @rxbuf_mapped: RX buffer mapping flag -+ * @txbuf_owned TX buffer ownership flag -+ * @txbuf_mapped: TX buffer mapping flag -+ * @rxtx_buf_size: RX/TX buffers size -+ * -+ * Hosts the ownership/mapping flags of the RX/TX buffers -+ * When a buffer is owned/mapped its corresponding flag is set to 1 otherwise 0. -+ */ -+struct ffa_rxtxpair_info { -+ u8 rxbuf_owned; -+ u8 rxbuf_mapped; -+ u8 txbuf_owned; -+ u8 txbuf_mapped; -+ u32 rxtx_buf_size; -+}; -+ -+/** -+ * struct sandbox_ffa_emul - emulator data -+ * -+ * @fwk_version: FF-A framework version -+ * @id: u-boot endpoint ID -+ * @partitions: The partitions descriptors structure -+ * @pair: The RX/TX buffers pair -+ * @pair_info: The RX/TX buffers pair flags and size -+ * @test_ffa_data: The data of the FF-A bus under test -+ * -+ * Hosts all the emulated secure world data. -+ */ -+struct sandbox_ffa_emul { -+ u32 fwk_version; -+ u16 id; -+ struct ffa_partitions partitions; -+ struct ffa_rxtxpair pair; -+ struct ffa_rxtxpair_info pair_info; -+}; -+ -+/** -+ * ffa_emul_find() - Finds the FF-A emulator -+ * @dev: the sandbox FF-A device (sandbox-arm-ffa) -+ * @emulp: the FF-A emulator device (sandbox-ffa-emul) -+ * Return: -+ * 0 on success. Otherwise, failure -+ */ -+int ffa_emul_find(struct udevice *dev, struct udevice **emulp); -+ -+#endif -diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig -index 98b3e0cda4..2db69b8e52 100644 ---- a/configs/sandbox64_defconfig -+++ b/configs/sandbox64_defconfig -@@ -260,3 +260,5 @@ CONFIG_FWU_MULTI_BANK_UPDATE=y - CONFIG_UNIT_TEST=y - CONFIG_UT_TIME=y - CONFIG_UT_DM=y -+CONFIG_NVMXIP_QSPI=y -+CONFIG_ARM_FFA_TRANSPORT=y -diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig -index 1ec44d5b33..f77733377d 100644 ---- a/configs/sandbox_defconfig -+++ b/configs/sandbox_defconfig -@@ -344,3 +344,5 @@ CONFIG_TEST_FDTDEC=y - CONFIG_UNIT_TEST=y - CONFIG_UT_TIME=y - CONFIG_UT_DM=y -+CONFIG_CMD_2048=y -+CONFIG_ARM_FFA_TRANSPORT=y -diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst -index aefd527447..b7c754fa3d 100644 ---- a/doc/arch/arm64.ffa.rst -+++ b/doc/arch/arm64.ffa.rst -@@ -33,6 +33,10 @@ The U-Boot FF-A support provides the following parts: - - - A Uclass driver providing generic FF-A methods. - - An Arm FF-A device driver providing Arm-specific methods and reusing the Uclass methods. -+- A sandbox emulator for Arm FF-A, emulates the FF-A side of the Secure World and provides -+ FF-A ABIs inspection methods. -+- An FF-A sandbox device driver for FF-A communication with the emulated Secure World. -+ The driver leverages the FF-A Uclass to establish FF-A communication. - - FF-A and SMC specifications - ------------------------------------------- -@@ -62,6 +66,7 @@ CONFIG_ARM_FFA_TRANSPORT - Enables the FF-A support. Turn this on if you want to use FF-A - communication. - When using an Arm 64-bit platform, the Arm FF-A driver will be used. -+ When using sandbox, the sandbox FF-A emulator and FF-A sandbox driver will be used. - - FF-A ABIs under the hood - --------------------------------------- -@@ -98,10 +103,8 @@ architecture features including FF-A bus. - - Class Index Probed Driver Name - ----------------------------------------------------------- -- ... - firmware 0 [ + ] psci |-- psci - ffa 0 [ ] arm_ffa | `-- arm_ffa -- ... - - The PSCI driver is bound to the PSCI device and when probed it tries to discover - the architecture features by calling a callback the features drivers provide. -@@ -205,6 +208,18 @@ The following features are provided: - - - FF-A bus can be compiled and used without EFI - -+Relationship between the sandbox emulator and the FF-A device -+--------------------------------------------------------------- -+ -+:: -+ -+ => dm tree -+ -+ Class Index Probed Driver Name -+ ----------------------------------------------------------- -+ ffa_emul 0 [ + ] sandbox_ffa_emul `-- arm-ffa-emul -+ ffa 0 [ ] sandbox_arm_ffa `-- sandbox-arm-ffa -+ - The armffa command - ----------------------------------- - -diff --git a/doc/arch/sandbox/sandbox.rst b/doc/arch/sandbox/sandbox.rst -index 77ca6bc4cc..a3631de749 100644 ---- a/doc/arch/sandbox/sandbox.rst -+++ b/doc/arch/sandbox/sandbox.rst -@@ -200,6 +200,7 @@ Supported Drivers - - U-Boot sandbox supports these emulations: - -+- Arm FF-A - - Block devices - - Chrome OS EC - - GPIO -diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig -index a7d5392859..d75f8b53fd 100644 ---- a/drivers/firmware/arm-ffa/Kconfig -+++ b/drivers/firmware/arm-ffa/Kconfig -@@ -2,9 +2,9 @@ - - config ARM_FFA_TRANSPORT - bool "Enable Arm Firmware Framework for Armv8-A driver" -- depends on DM && ARM64 -- select ARM_SMCCC -- select ARM_SMCCC_FEATURES -+ depends on DM && (ARM64 || SANDBOX) -+ select ARM_SMCCC if !SANDBOX -+ select ARM_SMCCC_FEATURES if !SANDBOX - imply CMD_ARMFFA - select LIB_UUID - select DEVRES -@@ -33,5 +33,10 @@ config ARM_FFA_TRANSPORT - Generic FF-A methods are implemented in the Uclass (arm-ffa-uclass.c). - Arm specific methods are implemented in the Arm driver (arm-ffa.c). - -- For more details about the FF-A support, please refer to doc/arch/arm64.ffa.rst -+ FF-A sandbox is provided to run FF-A under sandbox and allows to test the FF-A Uclass. -+ Sandbox support includes an emulator for Arm FF-A which emulates the FF-A side of -+ the Secure World and provides FF-A ABIs inspection methods (ffa-emul-uclass.c). -+ An FF-A sandbox driver is also provided for FF-A communication with the emulated -+ Secure World (sandbox_ffa.c). - -+ For more details about the FF-A support, please refer to doc/arch/arm64.ffa.rst -diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile -index 11b1766285..318123a7f4 100644 ---- a/drivers/firmware/arm-ffa/Makefile -+++ b/drivers/firmware/arm-ffa/Makefile -@@ -5,4 +5,12 @@ - # Authors: - # Abdellatif El Khlifi - --obj-y += arm-ffa-uclass.o arm-ffa.o -+# build the generic FF-A methods -+obj-y += arm-ffa-uclass.o -+ifeq ($(CONFIG_SANDBOX),y) -+# build the FF-A sandbox emulator and driver -+obj-y += ffa-emul-uclass.o sandbox_ffa.o -+else -+# build the Arm64 FF-A driver -+obj-y += arm-ffa.o -+endif -diff --git a/drivers/firmware/arm-ffa/ffa-emul-uclass.c b/drivers/firmware/arm-ffa/ffa-emul-uclass.c -new file mode 100644 -index 0000000000..5562bbaac3 ---- /dev/null -+++ b/drivers/firmware/arm-ffa/ffa-emul-uclass.c -@@ -0,0 +1,720 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Copyright 2022-2023 Arm Limited and/or its affiliates -+ * -+ * Authors: -+ * Abdellatif El Khlifi -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+DECLARE_GLOBAL_DATA_PTR; -+ -+/* The partitions (SPs) table */ -+static struct ffa_partition_desc sandbox_partitions[SANDBOX_PARTITIONS_CNT] = { -+ { -+ .info = { .id = SANDBOX_SP1_ID, .exec_ctxt = 0x5687, .properties = 0x89325621 }, -+ .sp_uuid = { -+ .a1 = SANDBOX_SERVICE1_UUID_A1, -+ .a2 = SANDBOX_SERVICE1_UUID_A2, -+ .a3 = SANDBOX_SERVICE1_UUID_A3, -+ .a4 = SANDBOX_SERVICE1_UUID_A4, -+ } -+ }, -+ { -+ .info = { .id = SANDBOX_SP3_ID, .exec_ctxt = 0x7687, .properties = 0x23325621 }, -+ .sp_uuid = { -+ .a1 = SANDBOX_SERVICE2_UUID_A1, -+ .a2 = SANDBOX_SERVICE2_UUID_A2, -+ .a3 = SANDBOX_SERVICE2_UUID_A3, -+ .a4 = SANDBOX_SERVICE2_UUID_A4, -+ } -+ }, -+ { -+ .info = { .id = SANDBOX_SP2_ID, .exec_ctxt = 0x9587, .properties = 0x45325621 }, -+ .sp_uuid = { -+ .a1 = SANDBOX_SERVICE1_UUID_A1, -+ .a2 = SANDBOX_SERVICE1_UUID_A2, -+ .a3 = SANDBOX_SERVICE1_UUID_A3, -+ .a4 = SANDBOX_SERVICE1_UUID_A4, -+ } -+ }, -+ { -+ .info = { .id = SANDBOX_SP4_ID, .exec_ctxt = 0x1487, .properties = 0x70325621 }, -+ .sp_uuid = { -+ .a1 = SANDBOX_SERVICE2_UUID_A1, -+ .a2 = SANDBOX_SERVICE2_UUID_A2, -+ .a3 = SANDBOX_SERVICE2_UUID_A3, -+ .a4 = SANDBOX_SERVICE2_UUID_A4, -+ } -+ } -+ -+}; -+ -+/* The emulator functions */ -+ -+/** -+ * sandbox_ffa_version() - Emulated FFA_VERSION handler function -+ * @emul: The sandbox FF-A emulator device -+ * @pargs: The SMC call input arguments a0-a7 -+ * @res: The SMC return data -+ * -+ * Emulate FFA_VERSION FF-A function. -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+ -+static int sandbox_ffa_version(struct udevice *emul, ffa_value_t *pargs, ffa_value_t *res) -+{ -+ struct sandbox_ffa_emul *priv = dev_get_priv(emul); -+ -+ priv->fwk_version = FFA_VERSION_1_0; -+ res->a0 = priv->fwk_version; -+ -+ /* x1-x7 MBZ */ -+ memset(FFA_X1X7_MBZ_REG_START, 0, FFA_X1X7_MBZ_CNT * sizeof(ulong)); -+ -+ return 0; -+} -+ -+/** -+ * sandbox_ffa_id_get() - Emulated FFA_ID_GET handler function -+ * @emul: The sandbox FF-A emulator device -+ * @pargs: The SMC call input arguments a0-a7 -+ * @res: The SMC return data -+ * -+ * Emulate FFA_ID_GET FF-A function. -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+static int sandbox_ffa_id_get(struct udevice *emul, ffa_value_t *pargs, ffa_value_t *res) -+{ -+ struct sandbox_ffa_emul *priv = dev_get_priv(emul); -+ -+ res->a0 = FFA_SMC_32(FFA_SUCCESS); -+ res->a1 = 0; -+ -+ priv->id = NS_PHYS_ENDPOINT_ID; -+ res->a2 = priv->id; -+ -+ /* x3-x7 MBZ */ -+ memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong)); -+ -+ return 0; -+} -+ -+/** -+ * sandbox_ffa_features() - Emulated FFA_FEATURES handler function -+ * @pargs: The SMC call input arguments a0-a7 -+ * @res: The SMC return data -+ * -+ * Emulate FFA_FEATURES FF-A function. -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+static int sandbox_ffa_features(ffa_value_t *pargs, ffa_value_t *res) -+{ -+ res->a1 = 0; -+ -+ if (pargs->a1 == FFA_SMC_64(FFA_RXTX_MAP)) { -+ res->a0 = FFA_SMC_32(FFA_SUCCESS); -+ res->a2 = RXTX_BUFFERS_MIN_SIZE; -+ res->a3 = 0; -+ /* x4-x7 MBZ */ -+ memset(FFA_X4X7_MBZ_REG_START, 0, FFA_X4X7_MBZ_CNT * sizeof(ulong)); -+ return 0; -+ } -+ -+ res->a0 = FFA_SMC_32(FFA_ERROR); -+ res->a2 = -NOT_SUPPORTED; -+ /* x3-x7 MBZ */ -+ memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong)); -+ log_err("FF-A interface %lx not implemented\n", pargs->a1); -+ -+ return ffa_to_std_errmap[NOT_SUPPORTED]; -+} -+ -+/** -+ * sandbox_ffa_partition_info_get() - Emulated FFA_PARTITION_INFO_GET handler -+ * @emul: The sandbox FF-A emulator device -+ * @pargs: The SMC call input arguments a0-a7 -+ * @res: The SMC return data -+ * -+ * Emulate FFA_PARTITION_INFO_GET FF-A function. -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+static int sandbox_ffa_partition_info_get(struct udevice *emul, ffa_value_t *pargs, -+ ffa_value_t *res) -+{ -+ struct ffa_partition_info *rxbuf_desc_info = NULL; -+ u32 descs_cnt; -+ u32 descs_size_bytes; -+ int ret; -+ struct sandbox_ffa_emul *priv = dev_get_priv(emul); -+ -+ res->a0 = FFA_SMC_32(FFA_ERROR); -+ -+ if (!priv->pair.rxbuf) { -+ res->a2 = -DENIED; -+ ret = ffa_to_std_errmap[DENIED]; -+ goto cleanup; -+ } -+ -+ if (priv->pair_info.rxbuf_owned) { -+ res->a2 = -BUSY; -+ ret = ffa_to_std_errmap[BUSY]; -+ goto cleanup; -+ } -+ -+ if (!priv->partitions.descs) { -+ priv->partitions.descs = sandbox_partitions; -+ priv->partitions.count = SANDBOX_PARTITIONS_CNT; -+ } -+ -+ descs_size_bytes = SANDBOX_PARTITIONS_CNT * -+ sizeof(struct ffa_partition_desc); -+ -+ /* Abort if the RX buffer size is smaller than the descs buffer size */ -+ if ((priv->pair_info.rxtx_buf_size * SZ_4K) < descs_size_bytes) { -+ res->a2 = -NO_MEMORY; -+ ret = ffa_to_std_errmap[NO_MEMORY]; -+ goto cleanup; -+ } -+ -+ rxbuf_desc_info = priv->pair.rxbuf; -+ -+ /* No UUID specified. Return the information of all partitions */ -+ if (!pargs->a1 && !pargs->a2 && !pargs->a3 && !pargs->a4) { -+ for (descs_cnt = 0; descs_cnt < SANDBOX_PARTITIONS_CNT; descs_cnt++) -+ *(rxbuf_desc_info++) = priv->partitions.descs[descs_cnt].info; -+ -+ res->a0 = FFA_SMC_32(FFA_SUCCESS); -+ res->a2 = SANDBOX_PARTITIONS_CNT; -+ /* Transfer ownership to the consumer: the non secure world */ -+ priv->pair_info.rxbuf_owned = 1; -+ ret = 0; -+ -+ goto cleanup; -+ } -+ -+ /* A UUID specified. Return the info of all SPs matching the UUID */ -+ -+ for (descs_cnt = 0 ; descs_cnt < SANDBOX_PARTITIONS_CNT ; descs_cnt++) -+ if (pargs->a1 == priv->partitions.descs[descs_cnt].sp_uuid.a1 && -+ pargs->a2 == priv->partitions.descs[descs_cnt].sp_uuid.a2 && -+ pargs->a3 == priv->partitions.descs[descs_cnt].sp_uuid.a3 && -+ pargs->a4 == priv->partitions.descs[descs_cnt].sp_uuid.a4) { -+ *(rxbuf_desc_info++) = priv->partitions.descs[descs_cnt].info; -+ } -+ -+ if (rxbuf_desc_info != priv->pair.rxbuf) { -+ res->a0 = FFA_SMC_32(FFA_SUCCESS); -+ /* Store the partitions count */ -+ res->a2 = (ulong) -+ (rxbuf_desc_info - (struct ffa_partition_info *) -+ priv->pair.rxbuf); -+ ret = 0; -+ -+ /* Transfer ownership to the consumer: the non secure world */ -+ priv->pair_info.rxbuf_owned = 1; -+ } else { -+ /* Unrecognized UUID */ -+ res->a2 = -INVALID_PARAMETERS; -+ ret = ffa_to_std_errmap[INVALID_PARAMETERS]; -+ } -+ -+cleanup: -+ -+ log_err("FFA_PARTITION_INFO_GET (%ld)\n", res->a2); -+ -+ res->a1 = 0; -+ -+ /* x3-x7 MBZ */ -+ memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong)); -+ -+ return ret; -+} -+ -+/** -+ * sandbox_ffa_rxtx_map() - Emulated FFA_RXTX_MAP handler -+ * @emul: The sandbox FF-A emulator device -+ * @pargs: The SMC call input arguments a0-a7 -+ * @res: The SMC return data -+ * -+ * Emulate FFA_RXTX_MAP FF-A function. -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+static int sandbox_ffa_rxtx_map(struct udevice *emul, ffa_value_t *pargs, ffa_value_t *res) -+{ -+ int ret; -+ struct sandbox_ffa_emul *priv = dev_get_priv(emul); -+ -+ res->a0 = FFA_SMC_32(FFA_ERROR); -+ -+ if (priv->pair.txbuf && priv->pair.rxbuf) { -+ res->a2 = -DENIED; -+ ret = ffa_to_std_errmap[DENIED]; -+ goto feedback; -+ } -+ -+ if (pargs->a3 >= RXTX_BUFFERS_MIN_PAGES && pargs->a1 && pargs->a2) { -+ priv->pair.txbuf = map_sysmem(pargs->a1, 0); -+ priv->pair.rxbuf = map_sysmem(pargs->a2, 0); -+ priv->pair_info.rxtx_buf_size = pargs->a3; -+ priv->pair_info.rxbuf_mapped = 1; -+ res->a0 = FFA_SMC_32(FFA_SUCCESS); -+ res->a2 = 0; -+ ret = 0; -+ goto feedback; -+ } -+ -+ if (!pargs->a1 || !pargs->a2) { -+ res->a2 = -INVALID_PARAMETERS; -+ ret = ffa_to_std_errmap[INVALID_PARAMETERS]; -+ } else { -+ res->a2 = -NO_MEMORY; -+ ret = ffa_to_std_errmap[NO_MEMORY]; -+ } -+ -+ log_err("Error in FFA_RXTX_MAP arguments (%d)\n", -+ (int)res->a2); -+ -+feedback: -+ -+ res->a1 = 0; -+ -+ /* x3-x7 MBZ */ -+ memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong)); -+ -+ return ret; -+} -+ -+/** -+ * sandbox_ffa_rxtx_unmap() - Emulated FFA_RXTX_UNMAP handler -+ * @emul: The sandbox FF-A emulator device -+ * @pargs: The SMC call input arguments a0-a7 -+ * @res: The SMC return data -+ * -+ * Emulate FFA_RXTX_UNMAP FF-A function. -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+static int sandbox_ffa_rxtx_unmap(struct udevice *emul, ffa_value_t *pargs, ffa_value_t *res) -+{ -+ int ret; -+ struct sandbox_ffa_emul *priv = dev_get_priv(emul); -+ -+ res->a0 = FFA_SMC_32(FFA_ERROR); -+ res->a2 = -INVALID_PARAMETERS; -+ ret = ffa_to_std_errmap[INVALID_PARAMETERS]; -+ -+ if (GET_NS_PHYS_ENDPOINT_ID(pargs->a1) != priv->id) -+ goto feedback; -+ -+ if (priv->pair.txbuf && priv->pair.rxbuf) { -+ priv->pair.txbuf = 0; -+ priv->pair.rxbuf = 0; -+ priv->pair_info.rxtx_buf_size = 0; -+ priv->pair_info.rxbuf_mapped = 0; -+ res->a0 = FFA_SMC_32(FFA_SUCCESS); -+ res->a2 = 0; -+ ret = 0; -+ goto feedback; -+ } -+ -+ log_err("No buffer pair registered on behalf of the caller\n"); -+ -+feedback: -+ -+ res->a1 = 0; -+ -+ /* x3-x7 MBZ */ -+ memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong)); -+ -+ return ret; -+} -+ -+/** -+ * sandbox_ffa_rx_release() - Emulated FFA_RX_RELEASE handler -+ * @emul: The sandbox FF-A emulator device -+ * @pargs: The SMC call input arguments a0-a7 -+ * @res: The SMC return data -+ * -+ * Emulate FFA_RX_RELEASE FF-A function. -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+static int sandbox_ffa_rx_release(struct udevice *emul, ffa_value_t *pargs, ffa_value_t *res) -+{ -+ int ret; -+ struct sandbox_ffa_emul *priv = dev_get_priv(emul); -+ -+ if (!priv->pair_info.rxbuf_owned) { -+ res->a0 = FFA_SMC_32(FFA_ERROR); -+ res->a2 = -DENIED; -+ ret = ffa_to_std_errmap[DENIED]; -+ } else { -+ priv->pair_info.rxbuf_owned = 0; -+ res->a0 = FFA_SMC_32(FFA_SUCCESS); -+ res->a2 = 0; -+ ret = 0; -+ } -+ -+ res->a1 = 0; -+ -+ /* x3-x7 MBZ */ -+ memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong)); -+ -+ return ret; -+} -+ -+/** -+ * sandbox_ffa_sp_valid() - Check SP validity -+ * @emul: The sandbox FF-A emulator device -+ * @part_id: partition ID to check -+ * -+ * Search the input ID in the descriptors table. -+ * -+ * Return: -+ * -+ * 1 on success (Partition found). Otherwise, failure -+ */ -+static int sandbox_ffa_sp_valid(struct udevice *emul, u16 part_id) -+{ -+ u32 descs_cnt; -+ struct sandbox_ffa_emul *priv = dev_get_priv(emul); -+ -+ for (descs_cnt = 0 ; descs_cnt < SANDBOX_PARTITIONS_CNT ; descs_cnt++) -+ if (priv->partitions.descs[descs_cnt].info.id == part_id) -+ return 1; -+ -+ return 0; -+} -+ -+/** -+ * sandbox_ffa_msg_send_direct_req() - Emulated FFA_MSG_SEND_DIRECT_{REQ,RESP} handler -+ * @emul: The sandbox FF-A emulator device -+ * @pargs: The SMC call input arguments a0-a7 -+ * @res: The SMC return data -+ * -+ * Emulate FFA_MSG_SEND_DIRECT_{REQ,RESP} FF-A ABIs. -+ * Only SMC 64-bit is supported in Sandbox. -+ * -+ * Emulating interrupts is not supported. So, FFA_RUN and FFA_INTERRUPT are not -+ * supported. In case of success FFA_MSG_SEND_DIRECT_RESP is returned with -+ * default pattern data (0xff). -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+static int sandbox_ffa_msg_send_direct_req(struct udevice *emul, -+ ffa_value_t *pargs, ffa_value_t *res) -+{ -+ u16 part_id; -+ struct sandbox_ffa_emul *priv = dev_get_priv(emul); -+ -+ part_id = GET_DST_SP_ID(pargs->a1); -+ -+ if (GET_NS_PHYS_ENDPOINT_ID(pargs->a1) != priv->id || -+ !sandbox_ffa_sp_valid(emul, part_id) || pargs->a2) { -+ res->a0 = FFA_SMC_32(FFA_ERROR); -+ res->a1 = 0; -+ res->a2 = -INVALID_PARAMETERS; -+ -+ /* x3-x7 MBZ */ -+ memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong)); -+ -+ return ffa_to_std_errmap[INVALID_PARAMETERS]; -+ } -+ -+ res->a0 = FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP); -+ -+ res->a1 = PREP_SRC_SP_ID(part_id) | -+ PREP_NS_PHYS_ENDPOINT_ID(priv->id); -+ -+ res->a2 = 0; -+ -+ /* Return 0xff bytes as a response */ -+ res->a3 = -1UL; -+ res->a4 = -1UL; -+ res->a5 = -1UL; -+ res->a6 = -1UL; -+ res->a7 = -1UL; -+ -+ return 0; -+} -+ -+/** -+ * sandbox_ffa_get_rxbuf_flags() - Read the mapping/ownership flags -+ * @emul: The sandbox FF-A emulator device -+ * @queried_func_id: The FF-A function to be queried -+ * @func_data: Pointer to the FF-A function arguments container structure -+ * -+ * Query the status flags of the following emulated -+ * ABIs: FFA_RXTX_MAP, FFA_RXTX_UNMAP, FFA_RX_RELEASE. -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+static int sandbox_ffa_get_rxbuf_flags(struct udevice *emul, u32 queried_func_id, -+ struct ffa_sandbox_data *func_data) -+{ -+ struct sandbox_ffa_emul *priv = dev_get_priv(emul); -+ -+ if (!func_data) -+ return -EINVAL; -+ -+ if (!func_data->data0 || func_data->data0_size != sizeof(u8)) -+ return -EINVAL; -+ -+ switch (queried_func_id) { -+ case FFA_RXTX_MAP: -+ case FFA_RXTX_UNMAP: -+ *((u8 *)func_data->data0) = priv->pair_info.rxbuf_mapped; -+ return 0; -+ case FFA_RX_RELEASE: -+ *((u8 *)func_data->data0) = priv->pair_info.rxbuf_owned; -+ return 0; -+ default: -+ log_err("The querried FF-A interface flag (%d) undefined\n", -+ queried_func_id); -+ return -EINVAL; -+ } -+} -+ -+/** -+ * sandbox_ffa_get_fwk_version() - Return the FFA framework version -+ * @emul: The sandbox FF-A emulator device -+ * @func_data: Pointer to the FF-A function arguments container structure -+ * -+ * Return the FFA framework version read from the FF-A emulator data. -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+static int sandbox_ffa_get_fwk_version(struct udevice *emul, struct ffa_sandbox_data *func_data) -+{ -+ struct sandbox_ffa_emul *priv = dev_get_priv(emul); -+ -+ if (!func_data) -+ return -EINVAL; -+ -+ if (!func_data->data0 || -+ func_data->data0_size != sizeof(priv->fwk_version)) -+ return -EINVAL; -+ -+ *((u32 *)func_data->data0) = priv->fwk_version; -+ -+ return 0; -+} -+ -+/** -+ * sandbox_ffa_get_parts() - Return the address of partitions data -+ * @emul: The sandbox FF-A emulator device -+ * @func_data: Pointer to the FF-A function arguments container structure -+ * -+ * Return the address of partitions data read from the FF-A emulator data. -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+static int sandbox_ffa_get_parts(struct udevice *emul, struct ffa_sandbox_data *func_data) -+{ -+ struct sandbox_ffa_emul *priv = dev_get_priv(emul); -+ -+ if (!func_data) -+ return -EINVAL; -+ -+ if (!func_data->data0 || -+ func_data->data0_size != sizeof(struct ffa_partitions *)) -+ return -EINVAL; -+ -+ *((struct ffa_partitions **)func_data->data0) = &priv->partitions; -+ -+ return 0; -+} -+ -+/** -+ * sandbox_query_ffa_emul_state() - Inspect the FF-A ABIs -+ * @queried_func_id: The FF-A function to be queried -+ * @func_data: Pointer to the FF-A function arguments container structure -+ * -+ * Query the status of FF-A ABI specified in the input argument. -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+int sandbox_query_ffa_emul_state(u32 queried_func_id, -+ struct ffa_sandbox_data *func_data) -+{ -+ struct udevice *emul; -+ int ret; -+ -+ ret = uclass_first_device_err(UCLASS_FFA_EMUL, &emul); -+ if (ret) { -+ log_err("Cannot find FF-A emulator during querying state\n"); -+ return ret; -+ } -+ -+ switch (queried_func_id) { -+ case FFA_RXTX_MAP: -+ case FFA_RXTX_UNMAP: -+ case FFA_RX_RELEASE: -+ return sandbox_ffa_get_rxbuf_flags(emul, queried_func_id, func_data); -+ case FFA_VERSION: -+ return sandbox_ffa_get_fwk_version(emul, func_data); -+ case FFA_PARTITION_INFO_GET: -+ return sandbox_ffa_get_parts(emul, func_data); -+ default: -+ log_err("Undefined FF-A interface (%d)\n", -+ queried_func_id); -+ return -EINVAL; -+ } -+} -+ -+/** -+ * sandbox_arm_ffa_smccc_smc() - FF-A SMC call emulation -+ * @args: the SMC call arguments -+ * @res: the SMC call returned data -+ * -+ * Emulate the FF-A ABIs SMC call. -+ * The emulated FF-A ABI is identified and invoked. -+ * FF-A emulation is based on the FF-A specification 1.0 -+ * -+ * Return: -+ * -+ * 0 on success. Otherwise, failure. -+ * FF-A protocol error codes are returned using the registers arguments as -+ * described by the specification -+ */ -+void sandbox_arm_ffa_smccc_smc(ffa_value_t *args, ffa_value_t *res) -+{ -+ int ret = 0; -+ struct udevice *emul; -+ -+ ret = uclass_first_device_err(UCLASS_FFA_EMUL, &emul); -+ if (ret) { -+ log_err("Cannot find FF-A emulator during SMC emulation\n"); -+ return; -+ } -+ -+ switch (args->a0) { -+ case FFA_SMC_32(FFA_VERSION): -+ ret = sandbox_ffa_version(emul, args, res); -+ break; -+ case FFA_SMC_32(FFA_PARTITION_INFO_GET): -+ ret = sandbox_ffa_partition_info_get(emul, args, res); -+ break; -+ case FFA_SMC_32(FFA_RXTX_UNMAP): -+ ret = sandbox_ffa_rxtx_unmap(emul, args, res); -+ break; -+ case FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ): -+ ret = sandbox_ffa_msg_send_direct_req(emul, args, res); -+ break; -+ case FFA_SMC_32(FFA_ID_GET): -+ ret = sandbox_ffa_id_get(emul, args, res); -+ break; -+ case FFA_SMC_32(FFA_FEATURES): -+ ret = sandbox_ffa_features(args, res); -+ break; -+ case FFA_SMC_64(FFA_RXTX_MAP): -+ ret = sandbox_ffa_rxtx_map(emul, args, res); -+ break; -+ case FFA_SMC_32(FFA_RX_RELEASE): -+ ret = sandbox_ffa_rx_release(emul, args, res); -+ break; -+ default: -+ log_err("Undefined FF-A interface (%lx)\n", -+ args->a0); -+ } -+ -+ if (ret != 0) -+ log_err("FF-A ABI internal failure (%d)\n", ret); -+} -+ -+/** -+ * invoke_ffa_fn() - SMC wrapper -+ * @args: FF-A ABI arguments to be copied to Xn registers -+ * @res: FF-A ABI return data to be copied from Xn registers -+ * -+ * Calls the emulated SMC call. -+ */ -+void invoke_ffa_fn(ffa_value_t args, ffa_value_t *res) -+{ -+ sandbox_arm_ffa_smccc_smc(&args, res); -+} -+ -+/** -+ * ffa_emul_find() - Find the FF-A emulator -+ * @dev: the sandbox FF-A device (sandbox-arm-ffa) -+ * @emulp: the FF-A emulator device (sandbox-ffa-emul) -+ * -+ * Search for the FF-A emulator and returns its device pointer. -+ * -+ * Return: -+ * 0 on success. Otherwise, failure -+ */ -+int ffa_emul_find(struct udevice *dev, struct udevice **emulp) -+{ -+ int ret; -+ -+ ret = uclass_first_device_err(UCLASS_FFA_EMUL, emulp); -+ if (ret) { -+ log_err("Cannot find FF-A emulator\n"); -+ return ret; -+ } -+ -+ log_info("FF-A emulator ready to use\n"); -+ -+ return 0; -+} -+ -+UCLASS_DRIVER(ffa_emul) = { -+ .name = "ffa_emul", -+ .id = UCLASS_FFA_EMUL, -+ .post_bind = dm_scan_fdt_dev, -+}; -+ -+static const struct udevice_id sandbox_ffa_emul_ids[] = { -+ { .compatible = "sandbox,arm-ffa-emul" }, -+ { } -+}; -+ -+/* Declaring the sandbox FF-A emulator under UCLASS_FFA_EMUL */ -+U_BOOT_DRIVER(sandbox_ffa_emul) = { -+ .name = "sandbox_ffa_emul", -+ .id = UCLASS_FFA_EMUL, -+ .of_match = sandbox_ffa_emul_ids, -+ .priv_auto = sizeof(struct sandbox_ffa_emul), -+}; -diff --git a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h -deleted file mode 100644 -index 4338f9c9b1..0000000000 ---- a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h -+++ /dev/null -@@ -1,14 +0,0 @@ --/* SPDX-License-Identifier: GPL-2.0+ */ --/* -- * Copyright 2022-2023 Arm Limited and/or its affiliates -- * -- * Authors: -- * Abdellatif El Khlifi -- */ -- --#ifndef __SANDBOX_ARM_FFA_PRV_H --#define __SANDBOX_ARM_FFA_PRV_H -- --/* Future sandbox support private declarations */ -- --#endif -diff --git a/drivers/firmware/arm-ffa/sandbox_ffa.c b/drivers/firmware/arm-ffa/sandbox_ffa.c -new file mode 100644 -index 0000000000..ef9491ccea ---- /dev/null -+++ b/drivers/firmware/arm-ffa/sandbox_ffa.c -@@ -0,0 +1,110 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Copyright 2022-2023 Arm Limited and/or its affiliates -+ * -+ * Authors: -+ * Abdellatif El Khlifi -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+DECLARE_GLOBAL_DATA_PTR; -+ -+/** -+ * sandbox_ffa_discover() - perform sandbox FF-A discovery -+ * @dev: The sandbox FF-A bus device -+ * Try to discover the FF-A framework. Discovery is performed by -+ * querying the FF-A framework version from secure world using the FFA_VERSION ABI. -+ * Return: -+ * -+ * 0 on success. Otherwise, failure -+ */ -+static int sandbox_ffa_discover(struct udevice *dev) -+{ -+ int ret; -+ struct udevice *emul; -+ -+ log_info("Emulated FF-A framework discovery\n"); -+ -+ ret = ffa_emul_find(dev, &emul); -+ if (ret) { -+ log_err("Cannot find FF-A emulator\n"); -+ return ret; -+ } -+ -+ ret = ffa_get_version_hdlr(dev); -+ if (ret) -+ return ret; -+ -+ return 0; -+} -+ -+/** -+ * sandbox_ffa_probe() - The sandbox FF-A driver probe function -+ * @dev: the sandbox-arm-ffa device -+ * Save the emulator device in uc_priv. -+ * Return: -+ * -+ * 0 on success. -+ */ -+static int sandbox_ffa_probe(struct udevice *dev) -+{ -+ int ret; -+ struct ffa_priv *uc_priv = dev_get_uclass_priv(dev); -+ -+ ret = uclass_first_device_err(UCLASS_FFA_EMUL, &uc_priv->emul); -+ if (ret) { -+ log_err("Cannot find FF-A emulator\n"); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+/** -+ * sandbox_ffa_bind() - The sandbox FF-A driver bind function -+ * @dev: the sandbox-arm-ffa device -+ * Try to discover the emulated FF-A bus. -+ * Return: -+ * -+ * 0 on success. -+ */ -+static int sandbox_ffa_bind(struct udevice *dev) -+{ -+ int ret; -+ -+ ret = sandbox_ffa_discover(dev); -+ if (ret) -+ return ret; -+ -+ return 0; -+} -+ -+/* Sandbox Arm FF-A emulator operations */ -+ -+static const struct ffa_bus_ops sandbox_ffa_ops = { -+ .partition_info_get = ffa_get_partitions_info_hdlr, -+ .sync_send_receive = ffa_msg_send_direct_req_hdlr, -+ .rxtx_unmap = ffa_unmap_rxtx_buffers_hdlr, -+}; -+ -+static const struct udevice_id sandbox_ffa_id[] = { -+ { "sandbox,arm-ffa", 0 }, -+ { }, -+}; -+ -+/* Declaring the sandbox FF-A driver under UCLASS_FFA */ -+U_BOOT_DRIVER(sandbox_arm_ffa) = { -+ .name = "sandbox_arm_ffa", -+ .of_match = sandbox_ffa_id, -+ .id = UCLASS_FFA, -+ .bind = sandbox_ffa_bind, -+ .probe = sandbox_ffa_probe, -+ .ops = &sandbox_ffa_ops, -+}; -diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h -index 3c6af2e3d2..0432c95c9e 100644 ---- a/include/dm/uclass-id.h -+++ b/include/dm/uclass-id.h -@@ -63,6 +63,7 @@ enum uclass_id { - UCLASS_ETH_PHY, /* Ethernet PHY device */ - UCLASS_EXTCON, /* External Connector Class */ - UCLASS_FFA, /* Arm Firmware Framework for Armv8-A */ -+ UCLASS_FFA_EMUL, /* sandbox FF-A device emulator */ - UCLASS_FIRMWARE, /* Firmware */ - UCLASS_FPGA, /* FPGA device */ - UCLASS_FUZZING_ENGINE, /* Fuzzing engine */ diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0006-arm_ffa-sandbox-Add-FFA_MEM_SHARE-emulation.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0006-arm_ffa-sandbox-Add-FFA_MEM_SHARE-emulation.patch new file mode 100644 index 00000000..1b42c684 --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0006-arm_ffa-sandbox-Add-FFA_MEM_SHARE-emulation.patch @@ -0,0 +1,129 @@ +From 8ba17011b310fee0741ef5c7ddd1a5b019428e4e Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Wed, 16 Oct 2024 18:41:16 +0100 +Subject: [PATCH 06/36] arm_ffa: sandbox: Add FFA_MEM_SHARE emulation + +Add FFA_MEM_SHARE support to the FF-A emulator + +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20250702152528.1180414-1-abdellatif.elkhlifi@arm.com/] +--- + .../include/asm/sandbox_arm_ffa_priv.h | 6 ++- + drivers/firmware/arm-ffa/ffa-emul-uclass.c | 43 +++++++++++++++++++ + drivers/firmware/arm-ffa/sandbox_ffa.c | 3 +- + 3 files changed, 50 insertions(+), 2 deletions(-) + +diff --git a/arch/sandbox/include/asm/sandbox_arm_ffa_priv.h b/arch/sandbox/include/asm/sandbox_arm_ffa_priv.h +index 5c46547beab..fa09f9598ee 100644 +--- a/arch/sandbox/include/asm/sandbox_arm_ffa_priv.h ++++ b/arch/sandbox/include/asm/sandbox_arm_ffa_priv.h +@@ -1,6 +1,6 @@ + /* SPDX-License-Identifier: GPL-2.0+ */ + /* +- * Copyright 2022-2023 Arm Limited and/or its affiliates ++ * Copyright 2022-2023, 2025 Arm Limited and/or its affiliates + * + * Authors: + * Abdellatif El Khlifi +@@ -38,6 +38,7 @@ + /* RX/TX buffers minimum size */ + #define RXTX_BUFFERS_MIN_SIZE (RXTX_4K) + #define RXTX_BUFFERS_MIN_PAGES (1) ++#define RXTX_BUFFERS_MIN_PAGES_SIZE (RXTX_BUFFERS_MIN_PAGES * SZ_4K) + + /* A helper macro used for clearing registers that Must Be Zero (MBZ) */ + #define FFA_X_REG_SIZE_IN_BYTE sizeof((((ffa_value_t *)0)->a0)) +@@ -59,6 +60,9 @@ + #define SANDBOX_SERVICE2_UUID_A3 0x9cc02d72 + #define SANDBOX_SERVICE2_UUID_A4 0xcdd998a7 + ++/* Globally unique Handle to identify the shared memory region */ ++#define SANDBOX_MEM_HANDLE 0xffffffff ++ + /** + * struct ffa_rxtxpair_info - structure hosting the RX/TX buffers flags + * @rxbuf_owned: RX buffer ownership flag (the owner is non secure world) +diff --git a/drivers/firmware/arm-ffa/ffa-emul-uclass.c b/drivers/firmware/arm-ffa/ffa-emul-uclass.c +index dcf5bce9435..4918404fb6d 100644 +--- a/drivers/firmware/arm-ffa/ffa-emul-uclass.c ++++ b/drivers/firmware/arm-ffa/ffa-emul-uclass.c +@@ -563,6 +563,46 @@ static int sandbox_ffa_get_parts(struct udevice *emul, struct ffa_sandbox_data * + return 0; + } + ++/** ++ * sandbox_ffa_memory_share() - Emulated FFA_MEM_SHARE handler ++ * @emul: The sandbox FF-A emulator device ++ * @pargs: The SMC call input arguments a0-a7 ++ * @res: The SMC return data ++ * ++ * Emulate FFA_MEM_SHARE FF-A function. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++static int sandbox_ffa_memory_share(struct udevice *emul, ffa_value_t *pargs, ++ ffa_value_t *res) ++{ ++ int ret; ++ ++ res->a1 = 0; ++ ++ if (!pargs->a1 || pargs->a1 > RXTX_BUFFERS_MIN_PAGES_SIZE) { ++ /* FFA_ERROR encoding */ ++ res->a0 = FFA_SMC_32(FFA_ERROR); ++ res->a2 = -INVALID_PARAMETERS; ++ ret = ffa_to_std_errmap[INVALID_PARAMETERS]; ++ /* x3-x7 MBZ */ ++ memset(&res->a3, 0, 5 * FFA_X_REG_SIZE_IN_BYTE); ++ ++ return ret; ++ } ++ ++ /* FFA_SUCCESS encoding */ ++ res->a0 = FFA_SMC_32(FFA_SUCCESS); ++ res->a2 = SANDBOX_MEM_HANDLE; ++ res->a3 = SANDBOX_MEM_HANDLE; ++ /* x4-x7 MBZ */ ++ memset(&res->a4, 0, 4 * FFA_X_REG_SIZE_IN_BYTE); ++ ++ return 0; ++} ++ + /** + * sandbox_query_ffa_emul_state() - Inspect the FF-A ABIs + * @queried_func_id: The FF-A function to be queried +@@ -653,6 +693,9 @@ void sandbox_arm_ffa_smccc_smc(ffa_value_t *args, ffa_value_t *res) + case FFA_SMC_32(FFA_RX_RELEASE): + ret = sandbox_ffa_rx_release(emul, args, res); + break; ++ case FFA_SMC_32(FFA_MEM_SHARE): ++ ret = sandbox_ffa_memory_share(emul, args, res); ++ break; + default: + log_err("Undefined FF-A interface (%lx)\n", + args->a0); +diff --git a/drivers/firmware/arm-ffa/sandbox_ffa.c b/drivers/firmware/arm-ffa/sandbox_ffa.c +index 44b32a829dd..8d85e660e2b 100644 +--- a/drivers/firmware/arm-ffa/sandbox_ffa.c ++++ b/drivers/firmware/arm-ffa/sandbox_ffa.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0+ + /* +- * Copyright 2022-2023 Arm Limited and/or its affiliates ++ * Copyright 2022-2023, 2025 Arm Limited and/or its affiliates + * + * Authors: + * Abdellatif El Khlifi +@@ -91,6 +91,7 @@ static const struct ffa_bus_ops sandbox_ffa_ops = { + .partition_info_get = ffa_get_partitions_info_hdlr, + .sync_send_receive = ffa_msg_send_direct_req_hdlr, + .rxtx_unmap = ffa_unmap_rxtx_buffers_hdlr, ++ .memory_share = ffa_memory_share_hdlr, + }; + + static const struct udevice_id sandbox_ffa_id[] = { +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0007-FF-A-v15-arm_ffa-introduce-sandbox-test-cases-for-UC.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0007-FF-A-v15-arm_ffa-introduce-sandbox-test-cases-for-UC.patch deleted file mode 100644 index c61002d8..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0007-FF-A-v15-arm_ffa-introduce-sandbox-test-cases-for-UC.patch +++ /dev/null @@ -1,338 +0,0 @@ -From effa8444b74e456f724146c2593991281f95762d Mon Sep 17 00:00:00 2001 -From: Abdellatif El Khlifi -Date: Wed, 10 May 2023 17:34:55 +0100 -Subject: [PATCH] FF-A v15: arm_ffa: introduce sandbox test cases for - UCLASS_FFA - -Add functional test cases for the FF-A support - -These tests rely on the FF-A sandbox emulator and FF-A -sandbox driver which help in inspecting the FF-A communication. - -Signed-off-by: Abdellatif El Khlifi -Reviewed-by: Simon Glass -Cc: Tom Rini -Cc: Ilias Apalodimas -Cc: Jens Wiklander -Cc: Heinrich Schuchardt -Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20230713132847.176000-1-abdellatif.elkhlifi@arm.com/] ---- - MAINTAINERS | 1 + - doc/arch/arm64.ffa.rst | 1 + - test/dm/Makefile | 3 +- - test/dm/ffa.c | 261 +++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 265 insertions(+), 1 deletion(-) - create mode 100644 test/dm/ffa.c - -diff --git a/MAINTAINERS b/MAINTAINERS -index 679a3acdd8..ccd7859c88 100644 ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -276,6 +276,7 @@ F: doc/arch/arm64.ffa.rst - F: doc/usage/cmd/armffa.rst - F: drivers/firmware/arm-ffa/ - F: include/arm_ffa.h -+F: test/dm/ffa.c - - ARM FREESCALE IMX - M: Stefano Babic -diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst -index b7c754fa3d..325fb80346 100644 ---- a/doc/arch/arm64.ffa.rst -+++ b/doc/arch/arm64.ffa.rst -@@ -37,6 +37,7 @@ The U-Boot FF-A support provides the following parts: - FF-A ABIs inspection methods. - - An FF-A sandbox device driver for FF-A communication with the emulated Secure World. - The driver leverages the FF-A Uclass to establish FF-A communication. -+- Sandbox FF-A test cases. - - FF-A and SMC specifications - ------------------------------------------- -diff --git a/test/dm/Makefile b/test/dm/Makefile -index 3799b1ae8f..7ed00733c1 100644 ---- a/test/dm/Makefile -+++ b/test/dm/Makefile -@@ -1,7 +1,7 @@ - # SPDX-License-Identifier: GPL-2.0+ - # - # Copyright (c) 2013 Google, Inc --# Copyright 2023 Arm Limited and/or its affiliates -+# Copyright 2022-2023 Arm Limited and/or its affiliates - - obj-$(CONFIG_UT_DM) += test-dm.o - -@@ -92,6 +92,7 @@ obj-$(CONFIG_POWER_DOMAIN) += power-domain.o - obj-$(CONFIG_ACPI_PMC) += pmc.o - obj-$(CONFIG_DM_PMIC) += pmic.o - obj-$(CONFIG_DM_PWM) += pwm.o -+obj-$(CONFIG_ARM_FFA_TRANSPORT) += ffa.o - obj-$(CONFIG_QFW) += qfw.o - obj-$(CONFIG_RAM) += ram.o - obj-y += regmap.o -diff --git a/test/dm/ffa.c b/test/dm/ffa.c -new file mode 100644 -index 0000000000..6912666bb4 ---- /dev/null -+++ b/test/dm/ffa.c -@@ -0,0 +1,261 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Functional tests for UCLASS_FFA class -+ * -+ * Copyright 2022-2023 Arm Limited and/or its affiliates -+ * -+ * Authors: -+ * Abdellatif El Khlifi -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* Functional tests for the UCLASS_FFA */ -+ -+static int check_fwk_version(struct ffa_priv *uc_priv, struct unit_test_state *uts) -+{ -+ struct ffa_sandbox_data func_data; -+ u32 fwk_version = 0; -+ -+ func_data.data0 = &fwk_version; -+ func_data.data0_size = sizeof(fwk_version); -+ ut_assertok(sandbox_query_ffa_emul_state(FFA_VERSION, &func_data)); -+ ut_asserteq(uc_priv->fwk_version, fwk_version); -+ -+ return 0; -+} -+ -+static int check_endpoint_id(struct ffa_priv *uc_priv, struct unit_test_state *uts) -+{ -+ ut_asserteq(0, uc_priv->id); -+ -+ return 0; -+} -+ -+static int check_rxtxbuf(struct ffa_priv *uc_priv, struct unit_test_state *uts) -+{ -+ ut_assertnonnull(uc_priv->pair.rxbuf); -+ ut_assertnonnull(uc_priv->pair.txbuf); -+ -+ return 0; -+} -+ -+static int check_features(struct ffa_priv *uc_priv, struct unit_test_state *uts) -+{ -+ ut_assert(uc_priv->pair.rxtx_min_pages == RXTX_4K || -+ uc_priv->pair.rxtx_min_pages == RXTX_16K || -+ uc_priv->pair.rxtx_min_pages == RXTX_64K); -+ -+ return 0; -+} -+ -+static int check_rxbuf_mapped_flag(u32 queried_func_id, -+ u8 rxbuf_mapped, -+ struct unit_test_state *uts) -+{ -+ switch (queried_func_id) { -+ case FFA_RXTX_MAP: -+ ut_asserteq(1, rxbuf_mapped); -+ break; -+ case FFA_RXTX_UNMAP: -+ ut_asserteq(0, rxbuf_mapped); -+ break; -+ default: -+ ut_assert(false); -+ } -+ -+ return 0; -+} -+ -+static int check_rxbuf_release_flag(u8 rxbuf_owned, struct unit_test_state *uts) -+{ -+ ut_asserteq(0, rxbuf_owned); -+ -+ return 0; -+} -+ -+static int test_ffa_msg_send_direct_req(u16 part_id, struct unit_test_state *uts) -+{ -+ struct ffa_send_direct_data msg; -+ u8 cnt; -+ struct udevice *dev; -+ -+ ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev)); -+ -+ ut_assertok(ffa_sync_send_receive(dev, part_id, &msg, 1)); -+ -+ for (cnt = 0; cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64); cnt++) -+ ut_asserteq_64(-1UL, ((u64 *)&msg)[cnt]); -+ -+ return 0; -+} -+ -+static int test_partitions_and_comms(const char *service_uuid, -+ struct unit_test_state *uts) -+{ -+ struct ffa_partition_desc *descs; -+ u32 count, i, j, valid_sps = 0; -+ struct udevice *dev; -+ struct ffa_sandbox_data func_data; -+ struct ffa_partitions *partitions; -+ -+ ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev)); -+ -+ /* Get from the driver the count and information of the SPs matching the UUID */ -+ ut_assertok(ffa_partition_info_get(dev, service_uuid, &count, &descs)); -+ -+ /* Make sure the count is correct */ -+ ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, count); -+ -+ /* SPs found , verify the partitions information */ -+ -+ func_data.data0 = &partitions; -+ func_data.data0_size = sizeof(struct ffa_partitions *); -+ ut_assertok(sandbox_query_ffa_emul_state(FFA_PARTITION_INFO_GET, &func_data)); -+ -+ for (i = 0; i < count ; i++) { -+ for (j = 0; -+ j < partitions->count; -+ j++) { -+ if (descs[i].info.id == -+ partitions->descs[j].info.id) { -+ valid_sps++; -+ ut_asserteq_mem(&descs[i], -+ &partitions->descs[j], -+ sizeof(struct ffa_partition_desc)); -+ /* Send and receive data from the current partition */ -+ test_ffa_msg_send_direct_req(descs[i].info.id, uts); -+ } -+ } -+ } -+ -+ /* Verify expected partitions found in the emulated secure world */ -+ ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, valid_sps); -+ -+ return 0; -+} -+ -+static int dm_test_ffa_ack(struct unit_test_state *uts) -+{ -+ struct ffa_priv *uc_priv; -+ struct ffa_sandbox_data func_data; -+ u8 rxbuf_flag = 0; -+ const char *svc1_uuid = SANDBOX_SERVICE1_UUID; -+ const char *svc2_uuid = SANDBOX_SERVICE2_UUID; -+ struct udevice *dev; -+ -+ /* Test probing the sandbox FF-A bus */ -+ ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev)); -+ -+ /* Get a pointer to the sandbox FF-A bus private data */ -+ uc_priv = dev_get_uclass_priv(dev); -+ -+ /* Make sure the private data pointer is retrieved */ -+ ut_assertnonnull(uc_priv); -+ -+ /* Test FFA_VERSION */ -+ check_fwk_version(uc_priv, uts); -+ -+ /* Test FFA_ID_GET */ -+ check_endpoint_id(uc_priv, uts); -+ -+ /* Test FFA_FEATURES */ -+ check_features(uc_priv, uts); -+ -+ /* Test RX/TX buffers */ -+ check_rxtxbuf(uc_priv, uts); -+ -+ /* Test FFA_RXTX_MAP */ -+ func_data.data0 = &rxbuf_flag; -+ func_data.data0_size = sizeof(rxbuf_flag); -+ -+ rxbuf_flag = 0; -+ sandbox_query_ffa_emul_state(FFA_RXTX_MAP, &func_data); -+ check_rxbuf_mapped_flag(FFA_RXTX_MAP, rxbuf_flag, uts); -+ -+ /* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */ -+ test_partitions_and_comms(svc1_uuid, uts); -+ -+ /* Test FFA_RX_RELEASE */ -+ rxbuf_flag = 1; -+ sandbox_query_ffa_emul_state(FFA_RX_RELEASE, &func_data); -+ check_rxbuf_release_flag(rxbuf_flag, uts); -+ -+ /* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */ -+ test_partitions_and_comms(svc2_uuid, uts); -+ -+ /* Test FFA_RX_RELEASE */ -+ rxbuf_flag = 1; -+ ut_assertok(sandbox_query_ffa_emul_state(FFA_RX_RELEASE, &func_data)); -+ check_rxbuf_release_flag(rxbuf_flag, uts); -+ -+ return 0; -+} -+ -+DM_TEST(dm_test_ffa_ack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC); -+ -+static int dm_test_ffa_nack(struct unit_test_state *uts) -+{ -+ struct ffa_priv *uc_priv; -+ const char *valid_svc_uuid = SANDBOX_SERVICE1_UUID; -+ const char *unvalid_svc_uuid = SANDBOX_SERVICE3_UUID; -+ const char *unvalid_svc_uuid_str = SANDBOX_SERVICE4_UUID; -+ struct ffa_send_direct_data msg; -+ int ret; -+ u32 count; -+ u16 part_id = 0; -+ struct udevice *dev; -+ struct ffa_partition_desc *descs = NULL; -+ -+ /* Test probing the sandbox FF-A bus */ -+ ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev)); -+ -+ /* Get a pointer to the sandbox FF-A bus private data */ -+ uc_priv = dev_get_uclass_priv(dev); -+ -+ /* Make sure the private data pointer is retrieved */ -+ ut_assertnonnull(uc_priv); -+ -+ /* Query partitions count using invalid arguments */ -+ ret = ffa_partition_info_get(dev, NULL, NULL, NULL); -+ ut_asserteq(-EINVAL, ret); -+ ret = ffa_partition_info_get(dev, unvalid_svc_uuid, NULL, NULL); -+ ut_asserteq(-EINVAL, ret); -+ ret = ffa_partition_info_get(dev, unvalid_svc_uuid, &count, NULL); -+ ut_asserteq(-EINVAL, ret); -+ -+ /* Query partitions count using an invalid UUID string */ -+ ret = ffa_partition_info_get(dev, unvalid_svc_uuid_str, &count, &descs); -+ ut_asserteq(-EINVAL, ret); -+ -+ /* Query partitions count using an invalid UUID (no matching SP) */ -+ count = 0; -+ ret = ffa_partition_info_get(dev, unvalid_svc_uuid, &count, &descs); -+ ut_asserteq(0, count); -+ -+ /* Query partitions data using a valid UUID */ -+ count = 0; -+ ut_assertok(ffa_partition_info_get(dev, valid_svc_uuid, &count, &descs)); -+ /* Make sure partitions are detected */ -+ ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, count); -+ ut_assertnonnull(descs); -+ -+ /* Send data to an invalid partition */ -+ ret = ffa_sync_send_receive(dev, part_id, &msg, 1); -+ ut_asserteq(-EINVAL, ret); -+ -+ /* Send data to a valid partition */ -+ part_id = uc_priv->partitions.descs[0].info.id; -+ ut_assertok(ffa_sync_send_receive(dev, part_id, &msg, 1)); -+ -+ return 0; -+} -+ -+DM_TEST(dm_test_ffa_nack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC); diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0007-arm_ffa-sandbox-Add-FFA_MEM_SHARE-tests.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0007-arm_ffa-sandbox-Add-FFA_MEM_SHARE-tests.patch new file mode 100644 index 00000000..fc425125 --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0007-arm_ffa-sandbox-Add-FFA_MEM_SHARE-tests.patch @@ -0,0 +1,101 @@ +From b5f99e6be813e8bba29f7379ae7395ed51a19967 Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Thu, 17 Oct 2024 15:14:10 +0100 +Subject: [PATCH 07/36] arm_ffa: sandbox: Add FFA_MEM_SHARE tests + +Add positive and negative test cases + +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20250702152528.1180414-1-abdellatif.elkhlifi@arm.com/] +--- + test/dm/ffa.c | 46 +++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 45 insertions(+), 1 deletion(-) + +diff --git a/test/dm/ffa.c b/test/dm/ffa.c +index 593b7177fce..59eea9a57cc 100644 +--- a/test/dm/ffa.c ++++ b/test/dm/ffa.c +@@ -2,7 +2,7 @@ + /* + * Functional tests for UCLASS_FFA class + * +- * Copyright 2022-2023 Arm Limited and/or its affiliates ++ * Copyright 2022-2023, 2025 Arm Limited and/or its affiliates + * + * Authors: + * Abdellatif El Khlifi +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -141,6 +142,43 @@ static int test_partitions_and_comms(const char *service_uuid, + return 0; + } + ++static int test_ffa_memory_share(bool test_ack, struct unit_test_state *uts) ++{ ++ struct ffa_mem_ops_args args = {0}; ++ struct ffa_mem_region_attributes attrs = {0}; ++ static u8 buf[SZ_4K]; ++ int ret; ++ struct udevice *dev; ++ ++ ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev)); ++ ++ args.attrs = &attrs; ++ args.nattrs = 1; ++ args.address = buf; ++ args.pg_cnt = 1; ++ ++ if (test_ack) { ++ args.use_txbuf = true; ++ ++ ut_assertok(ffa_memory_share(dev, &args)); ++ ut_asserteq(HANDLE_LOW(args.g_handle), SANDBOX_MEM_HANDLE); ++ ut_asserteq(HANDLE_HIGH(args.g_handle), SANDBOX_MEM_HANDLE); ++ } else { ++ /* Do not use the TX buffer as a transaction buffer */ ++ args.use_txbuf = false; ++ ret = ffa_memory_share(dev, &args); ++ ut_asserteq(-EPROTONOSUPPORT, ret); ++ ++ /* No memory region address given */ ++ args.use_txbuf = true; ++ args.address = NULL; ++ ret = ffa_memory_share(dev, &args); ++ ut_asserteq(-EINVAL, ret); ++ } ++ ++ return 0; ++} ++ + static int dm_test_ffa_ack(struct unit_test_state *uts) + { + struct ffa_priv *uc_priv; +@@ -195,6 +233,9 @@ static int dm_test_ffa_ack(struct unit_test_state *uts) + ut_assertok(sandbox_query_ffa_emul_state(FFA_RX_RELEASE, &func_data)); + check_rxbuf_release_flag(rxbuf_flag, uts); + ++ /* Test FFA_MEM_SHARE */ ++ test_ffa_memory_share(true, uts); ++ + return 0; + } + DM_TEST(dm_test_ffa_ack, UTF_SCAN_FDT | UTF_CONSOLE); +@@ -253,6 +294,9 @@ static int dm_test_ffa_nack(struct unit_test_state *uts) + part_id = uc_priv->partitions.descs[0].info.id; + ut_assertok(ffa_sync_send_receive(dev, part_id, &msg, 1)); + ++ /* Test FFA_MEM_SHARE */ ++ test_ffa_memory_share(false, uts); ++ + return 0; + } + DM_TEST(dm_test_ffa_nack, UTF_SCAN_FDT | UTF_CONSOLE); +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0008-FF-A-v15-arm_ffa-introduce-armffa-command-Sandbox-te.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0008-FF-A-v15-arm_ffa-introduce-armffa-command-Sandbox-te.patch deleted file mode 100644 index a1dc18ed..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0008-FF-A-v15-arm_ffa-introduce-armffa-command-Sandbox-te.patch +++ /dev/null @@ -1,91 +0,0 @@ -From c95d1bd311b251e5dd6c6e53c2dc7977bdca7870 Mon Sep 17 00:00:00 2001 -From: Abdellatif El Khlifi -Date: Fri, 23 Jun 2023 13:44:10 +0100 -Subject: [PATCH] FF-A v15: arm_ffa: introduce armffa command Sandbox test - -Add Sandbox test for the armffa command - -Signed-off-by: Abdellatif El Khlifi -Reviewed-by: Simon Glass -Cc: Tom Rini -Cc: Ilias Apalodimas -Cc: Jens Wiklander -Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20230713132847.176000-1-abdellatif.elkhlifi@arm.com/] ---- - MAINTAINERS | 1 + - test/cmd/Makefile | 2 ++ - test/cmd/armffa.c | 33 +++++++++++++++++++++++++++++++++ - 3 files changed, 36 insertions(+) - create mode 100644 test/cmd/armffa.c - -diff --git a/MAINTAINERS b/MAINTAINERS -index ccd7859c88..885d91fe5c 100644 ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -276,6 +276,7 @@ F: doc/arch/arm64.ffa.rst - F: doc/usage/cmd/armffa.rst - F: drivers/firmware/arm-ffa/ - F: include/arm_ffa.h -+F: test/cmd/armffa.c - F: test/dm/ffa.c - - ARM FREESCALE IMX -diff --git a/test/cmd/Makefile b/test/cmd/Makefile -index 055adc65a2..1d1dbb4fbc 100644 ---- a/test/cmd/Makefile -+++ b/test/cmd/Makefile -@@ -1,6 +1,7 @@ - # SPDX-License-Identifier: GPL-2.0+ - # - # Copyright (c) 2013 Google, Inc -+# Copyright 2022-2023 Arm Limited and/or its affiliates - - ifdef CONFIG_HUSH_PARSER - obj-$(CONFIG_CONSOLE_RECORD) += test_echo.o -@@ -23,6 +24,7 @@ obj-$(CONFIG_CMD_SEAMA) += seama.o - ifdef CONFIG_SANDBOX - obj-$(CONFIG_CMD_READ) += rw.o - obj-$(CONFIG_CMD_SETEXPR) += setexpr.o -+obj-$(CONFIG_ARM_FFA_TRANSPORT) += armffa.o - endif - obj-$(CONFIG_CMD_TEMPERATURE) += temperature.o - obj-$(CONFIG_CMD_WGET) += wget.o -diff --git a/test/cmd/armffa.c b/test/cmd/armffa.c -new file mode 100644 -index 0000000000..9a44a397e8 ---- /dev/null -+++ b/test/cmd/armffa.c -@@ -0,0 +1,33 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Test for armffa command -+ * -+ * Copyright 2022-2023 Arm Limited and/or its affiliates -+ * -+ * Authors: -+ * Abdellatif El Khlifi -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* Basic test of 'armffa' command */ -+static int dm_test_armffa_cmd(struct unit_test_state *uts) -+{ -+ /* armffa getpart */ -+ ut_assertok(run_command("armffa getpart " SANDBOX_SERVICE1_UUID, 0)); -+ -+ /* armffa ping */ -+ ut_assertok(run_commandf("armffa ping 0x%x", SANDBOX_SP1_ID)); -+ -+ /* armffa devlist */ -+ ut_assertok(run_command("armffa devlist", 0)); -+ -+ return 0; -+} -+ -+DM_TEST(dm_test_armffa_cmd, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC); diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0008-arm_ffa-sandbox-Add-FFA_MEM_RECLAIM-emulation.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0008-arm_ffa-sandbox-Add-FFA_MEM_RECLAIM-emulation.patch new file mode 100644 index 00000000..6b6f100d --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0008-arm_ffa-sandbox-Add-FFA_MEM_RECLAIM-emulation.patch @@ -0,0 +1,89 @@ +From 6c37c2ef7fd844083fddc4c819f3fd37f7f6abc4 Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Thu, 17 Oct 2024 15:50:02 +0100 +Subject: [PATCH 08/36] arm_ffa: sandbox: Add FFA_MEM_RECLAIM emulation + +Add FFA_MEM_RECLAIM support to the FF-A emulator + +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20250702152528.1180414-1-abdellatif.elkhlifi@arm.com/] +--- + drivers/firmware/arm-ffa/ffa-emul-uclass.c | 42 ++++++++++++++++++++++ + drivers/firmware/arm-ffa/sandbox_ffa.c | 1 + + 2 files changed, 43 insertions(+) + +diff --git a/drivers/firmware/arm-ffa/ffa-emul-uclass.c b/drivers/firmware/arm-ffa/ffa-emul-uclass.c +index 4918404fb6d..a630392b6d1 100644 +--- a/drivers/firmware/arm-ffa/ffa-emul-uclass.c ++++ b/drivers/firmware/arm-ffa/ffa-emul-uclass.c +@@ -603,6 +603,45 @@ static int sandbox_ffa_memory_share(struct udevice *emul, ffa_value_t *pargs, + return 0; + } + ++/** ++ * sandbox_ffa_memory_reclaim() - Emulated FFA_MEM_RECLAIM handler ++ * @emul: The sandbox FF-A emulator device ++ * @pargs: The SMC call input arguments a0-a7 ++ * @res: The SMC return data ++ * ++ * Emulate FFA_MEM_RECLAIM FF-A function. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++static int sandbox_ffa_memory_reclaim(struct udevice *emul, ffa_value_t *pargs, ++ ffa_value_t *res) ++{ ++ int ret; ++ ++ res->a1 = 0; ++ ++ if (pargs->a1 != SANDBOX_MEM_HANDLE || ++ pargs->a2 != SANDBOX_MEM_HANDLE) { ++ /* FFA_ERROR encoding */ ++ res->a0 = FFA_SMC_32(FFA_ERROR); ++ res->a2 = -INVALID_PARAMETERS; ++ ret = ffa_to_std_errmap[INVALID_PARAMETERS]; ++ /* x3-x7 MBZ */ ++ memset(&res->a3, 0, 5 * FFA_X_REG_SIZE_IN_BYTE); ++ ++ return ret; ++ } ++ ++ /* FFA_SUCCESS encoding */ ++ res->a0 = FFA_SMC_32(FFA_SUCCESS); ++ /* x2-x7 MBZ */ ++ memset(&res->a2, 0, 6 * FFA_X_REG_SIZE_IN_BYTE); ++ ++ return 0; ++} ++ + /** + * sandbox_query_ffa_emul_state() - Inspect the FF-A ABIs + * @queried_func_id: The FF-A function to be queried +@@ -696,6 +735,9 @@ void sandbox_arm_ffa_smccc_smc(ffa_value_t *args, ffa_value_t *res) + case FFA_SMC_32(FFA_MEM_SHARE): + ret = sandbox_ffa_memory_share(emul, args, res); + break; ++ case FFA_SMC_32(FFA_MEM_RECLAIM): ++ ret = sandbox_ffa_memory_reclaim(emul, args, res); ++ break; + default: + log_err("Undefined FF-A interface (%lx)\n", + args->a0); +diff --git a/drivers/firmware/arm-ffa/sandbox_ffa.c b/drivers/firmware/arm-ffa/sandbox_ffa.c +index 8d85e660e2b..54c81d12f92 100644 +--- a/drivers/firmware/arm-ffa/sandbox_ffa.c ++++ b/drivers/firmware/arm-ffa/sandbox_ffa.c +@@ -92,6 +92,7 @@ static const struct ffa_bus_ops sandbox_ffa_ops = { + .sync_send_receive = ffa_msg_send_direct_req_hdlr, + .rxtx_unmap = ffa_unmap_rxtx_buffers_hdlr, + .memory_share = ffa_memory_share_hdlr, ++ .memory_reclaim = ffa_memory_reclaim_hdlr, + }; + + static const struct udevice_id sandbox_ffa_id[] = { +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0009-FF-A-v15-arm_ffa-efi-introduce-FF-A-MM-communication.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0009-FF-A-v15-arm_ffa-efi-introduce-FF-A-MM-communication.patch deleted file mode 100644 index 4934a903..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0009-FF-A-v15-arm_ffa-efi-introduce-FF-A-MM-communication.patch +++ /dev/null @@ -1,446 +0,0 @@ -From c40964dc6ba6baea0adf8f384e1e57fcd5ca18b0 Mon Sep 17 00:00:00 2001 -From: Abdellatif El Khlifi -Date: Mon, 15 Aug 2022 15:12:49 +0100 -Subject: [PATCH] FF-A v15: arm_ffa: efi: introduce FF-A MM communication - -Add MM communication support using FF-A transport - -This feature allows accessing MM partitions services through -EFI MM communication protocol. MM partitions such as StandAlonneMM -or smm-gateway secure partitions which reside in secure world. - -An MM shared buffer and a door bell event are used to exchange -the data. - -The data is used by EFI services such as GetVariable()/SetVariable() -and copied from the communication buffer to the MM shared buffer. - -The secure partition is notified about availability of data in the -MM shared buffer by an FF-A message (door bell). - -On such event, MM SP can read the data and updates the MM shared -buffer with the response data. - -The response data is copied back to the communication buffer and -consumed by the EFI subsystem. - -MM communication protocol supports FF-A 64-bit direct messaging. - -Signed-off-by: Abdellatif El Khlifi -Tested-by: Gowtham Suresh Kumar -Reviewed-by: Simon Glass -Cc: Tom Rini -Cc: Ilias Apalodimas -Cc: Jens Wiklander -Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20230713132847.176000-1-abdellatif.elkhlifi@arm.com/] ---- - include/mm_communication.h | 13 ++ - lib/efi_loader/Kconfig | 46 +++++- - lib/efi_loader/efi_variable_tee.c | 257 +++++++++++++++++++++++++++++- - 3 files changed, 309 insertions(+), 7 deletions(-) - -diff --git a/include/mm_communication.h b/include/mm_communication.h -index e65fbde60d..f17847583b 100644 ---- a/include/mm_communication.h -+++ b/include/mm_communication.h -@@ -6,6 +6,9 @@ - * Copyright (c) 2017, Intel Corporation. All rights reserved. - * Copyright (C) 2020 Linaro Ltd. - * Copyright (C) 2020 Linaro Ltd. -+ * Copyright 2022-2023 Arm Limited and/or its affiliates -+ * Authors: -+ * Abdellatif El Khlifi - */ - - #ifndef _MM_COMMUNICATION_H_ -@@ -13,6 +16,9 @@ - - #include - -+/* MM service UUID string (big-endian format). This UUID is common across all MM SPs */ -+#define MM_SP_UUID "33d532ed-e699-0942-c09c-a798d9cd722d" -+ - /* - * Interface to the pseudo Trusted Application (TA), which provides a - * communication channel with the Standalone MM (Management Mode) -@@ -248,4 +254,11 @@ struct smm_variable_var_check_property { - u16 name[]; - }; - -+/* supported MM transports */ -+enum mm_comms_select { -+ MM_COMMS_UNDEFINED, -+ MM_COMMS_FFA, -+ MM_COMMS_OPTEE -+}; -+ - #endif /* _MM_COMMUNICATION_H_ */ -diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig -index c5835e6ef6..553e6a30a2 100644 ---- a/lib/efi_loader/Kconfig -+++ b/lib/efi_loader/Kconfig -@@ -55,13 +55,55 @@ config EFI_VARIABLE_FILE_STORE - stored as file /ubootefi.var on the EFI system partition. - - config EFI_MM_COMM_TEE -- bool "UEFI variables storage service via OP-TEE" -- depends on OPTEE -+ bool "UEFI variables storage service via the trusted world" -+ select ARM_FFA_TRANSPORT -+ select TEE -+ select OPTEE - help -+ Allowing access to the MM SP services (SPs such as StandAlonneMM, smm-gateway). -+ When using the u-boot OP-TEE driver, StandAlonneMM is supported. -+ When using the u-boot FF-A driver any MM SP is supported. -+ - If OP-TEE is present and running StandAloneMM, dispatch all UEFI - variable related operations to that. The application will verify, - authenticate and store the variables on an RPMB. - -+ When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related -+ operations to the MM SP running in the secure world. -+ A door bell mechanism is used to notify the SP when there is data in the shared -+ MM buffer. The data is copied by u-boot to the shared buffer before issuing -+ the door bell event. -+ -+config FFA_SHARED_MM_BUF_SIZE -+ int "Memory size of the shared MM communication buffer" -+ default 0 -+ depends on EFI_MM_COMM_TEE -+ help -+ This defines the size in bytes of the memory area reserved for the shared -+ buffer used for communication between the MM feature in U-Boot and -+ the MM SP in secure world. -+ The size of the memory region must be a multiple of the size of the maximum -+ translation granule size that is specified in the ID_AA64MMFR0_EL1 System register. -+ It is assumed that the MM SP knows the size of the shared MM communication buffer. -+ -+config FFA_SHARED_MM_BUF_OFFSET -+ int "Data offset in the shared MM communication buffer" -+ default 0 -+ depends on EFI_MM_COMM_TEE -+ help -+ This defines the offset in bytes of the data read or written to in the shared -+ buffer by the MM SP. -+ -+config FFA_SHARED_MM_BUF_ADDR -+ hex "Define the address of the shared MM communication buffer" -+ default 0x0 -+ depends on EFI_MM_COMM_TEE -+ help -+ This defines the address of the shared MM communication buffer -+ used for communication between the MM feature in U-Boot and -+ the MM SP in secure world. -+ It is assumed that the MM SP knows the address of the shared MM communication buffer. -+ - config EFI_VARIABLE_NO_STORE - bool "Don't persist non-volatile UEFI variables" - help -diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c -index dfef18435d..5137b871ea 100644 ---- a/lib/efi_loader/efi_variable_tee.c -+++ b/lib/efi_loader/efi_variable_tee.c -@@ -4,17 +4,34 @@ - * - * Copyright (C) 2019 Linaro Ltd. - * Copyright (C) 2019 Linaro Ltd. -+ * Copyright 2022-2023 Arm Limited and/or its affiliates -+ * -+ * Authors: -+ * Abdellatif El Khlifi - */ - - #include -+#include -+#include -+#include - #include - #include - #include - #include --#include - #include -+#include - #include -+#include -+ -+/* MM return codes */ -+#define MM_SUCCESS (0) -+#define MM_NOT_SUPPORTED (-1) -+#define MM_INVALID_PARAMETER (-2) -+#define MM_DENIED (-3) -+#define MM_NO_MEMORY (-5) - -+static const char *mm_sp_svc_uuid = MM_SP_UUID; -+static u16 mm_sp_id; - extern struct efi_var_file __efi_runtime_data *efi_var_buf; - static efi_uintn_t max_buffer_size; /* comm + var + func + data */ - static efi_uintn_t max_payload_size; /* func + data */ -@@ -145,16 +162,241 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize) - } - - /** -- * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send -+ * ffa_notify_mm_sp() - Announce there is data in the shared buffer -+ * -+ * Notify the MM partition in the trusted world that -+ * data is available in the shared buffer. -+ * This is a blocking call during which trusted world has exclusive access -+ * to the MM shared buffer. -+ * -+ * Return: -+ * -+ * 0 on success -+ */ -+static int ffa_notify_mm_sp(void) -+{ -+ struct ffa_send_direct_data msg = {0}; -+ int ret; -+ int sp_event_ret; -+ struct udevice *dev; -+ -+ ret = uclass_first_device_err(UCLASS_FFA, &dev); -+ if (ret) { -+ log_err("EFI: Cannot find FF-A bus device, notify MM SP failure\n"); -+ return ret; -+ } -+ -+ msg.data0 = CONFIG_FFA_SHARED_MM_BUF_OFFSET; /* x3 */ -+ -+ ret = ffa_sync_send_receive(dev, mm_sp_id, &msg, 1); -+ if (ret) -+ return ret; -+ -+ sp_event_ret = msg.data0; /* x3 */ -+ -+ switch (sp_event_ret) { -+ case MM_SUCCESS: -+ ret = 0; -+ break; -+ case MM_NOT_SUPPORTED: -+ ret = -EINVAL; -+ break; -+ case MM_INVALID_PARAMETER: -+ ret = -EPERM; -+ break; -+ case MM_DENIED: -+ ret = -EACCES; -+ break; -+ case MM_NO_MEMORY: -+ ret = -EBUSY; -+ break; -+ default: -+ ret = -EACCES; -+ } -+ -+ return ret; -+} -+ -+/** -+ * ffa_discover_mm_sp_id() - Query the MM partition ID -+ * -+ * Use the FF-A driver to get the MM partition ID. -+ * If multiple partitions are found, use the first one. -+ * This is a boot time function. -+ * -+ * Return: -+ * -+ * 0 on success -+ */ -+static int ffa_discover_mm_sp_id(void) -+{ -+ u32 count = 0; -+ int ret; -+ struct ffa_partition_desc *descs; -+ struct udevice *dev; -+ -+ ret = uclass_first_device_err(UCLASS_FFA, &dev); -+ if (ret) { -+ log_err("EFI: Cannot find FF-A bus device, MM SP discovery failure\n"); -+ return ret; -+ } -+ -+ /* Ask the driver to fill the buffer with the SPs info */ -+ ret = ffa_partition_info_get(dev, mm_sp_svc_uuid, &count, &descs); -+ if (ret) { -+ log_err("EFI: Failure in querying SPs info (%d), MM SP discovery failure\n", ret); -+ return ret; -+ } -+ -+ /* MM SPs found , use the first one */ -+ -+ mm_sp_id = descs[0].info.id; -+ -+ log_info("EFI: MM partition ID 0x%x\n", mm_sp_id); -+ -+ return 0; -+} -+ -+/** -+ * ffa_mm_communicate() - Exchange EFI services data with the MM partition using FF-A -+ * @comm_buf: locally allocated communication buffer used for rx/tx -+ * @dsize: communication buffer size -+ * -+ * Issue a door bell event to notify the MM partition (SP) running in OP-TEE -+ * that there is data to read from the shared buffer. -+ * Communication with the MM SP is performed using FF-A transport. -+ * On the event, MM SP can read the data from the buffer and -+ * update the MM shared buffer with response data. -+ * The response data is copied back to the communication buffer. -+ * -+ * Return: -+ * -+ * EFI status code -+ */ -+static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size) -+{ -+ ulong tx_data_size; -+ int ffa_ret; -+ efi_status_t efi_ret; -+ struct efi_mm_communicate_header *mm_hdr; -+ void *virt_shared_buf; -+ -+ if (!comm_buf) -+ return EFI_INVALID_PARAMETER; -+ -+ /* Discover MM partition ID at boot time */ -+ if (!mm_sp_id && ffa_discover_mm_sp_id()) { -+ log_err("EFI: Failure to discover MM SP ID at boot time, FF-A MM comms failure\n"); -+ return EFI_UNSUPPORTED; -+ } -+ -+ mm_hdr = (struct efi_mm_communicate_header *)comm_buf; -+ tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t); -+ -+ if (comm_buf_size != tx_data_size || tx_data_size > CONFIG_FFA_SHARED_MM_BUF_SIZE) -+ return EFI_INVALID_PARAMETER; -+ -+ /* Copy the data to the shared buffer */ -+ -+ virt_shared_buf = map_sysmem((phys_addr_t)CONFIG_FFA_SHARED_MM_BUF_ADDR, 0); -+ memcpy(virt_shared_buf, comm_buf, tx_data_size); -+ -+ /* -+ * The secure world might have cache disabled for -+ * the device region used for shared buffer (which is the case for Optee). -+ * In this case, the secure world reads the data from DRAM. -+ * Let's flush the cache so the DRAM is updated with the latest data. -+ */ -+#ifdef CONFIG_ARM64 -+ invalidate_dcache_all(); -+#endif -+ -+ /* Announce there is data in the shared buffer */ -+ -+ ffa_ret = ffa_notify_mm_sp(); -+ -+ switch (ffa_ret) { -+ case 0: { -+ ulong rx_data_size; -+ /* Copy the MM SP response from the shared buffer to the communication buffer */ -+ rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len + -+ sizeof(efi_guid_t) + -+ sizeof(size_t); -+ -+ if (rx_data_size > comm_buf_size) { -+ efi_ret = EFI_OUT_OF_RESOURCES; -+ break; -+ } -+ -+ memcpy(comm_buf, virt_shared_buf, rx_data_size); -+ efi_ret = EFI_SUCCESS; -+ break; -+ } -+ case -EINVAL: -+ efi_ret = EFI_DEVICE_ERROR; -+ break; -+ case -EPERM: -+ efi_ret = EFI_INVALID_PARAMETER; -+ break; -+ case -EACCES: -+ efi_ret = EFI_ACCESS_DENIED; -+ break; -+ case -EBUSY: -+ efi_ret = EFI_OUT_OF_RESOURCES; -+ break; -+ default: -+ efi_ret = EFI_ACCESS_DENIED; -+ } -+ -+ unmap_sysmem(virt_shared_buf); -+ return efi_ret; -+} -+ -+/** -+ * get_mm_comms() - detect the available MM transport -+ * -+ * Make sure the FF-A bus is probed successfully -+ * which means FF-A communication with secure world works and ready -+ * for use. -+ * -+ * If FF-A bus is not ready, use OPTEE comms. -+ * -+ * Return: -+ * -+ * MM_COMMS_FFA or MM_COMMS_OPTEE -+ */ -+static enum mm_comms_select get_mm_comms(void) -+{ -+ struct udevice *dev; -+ int ret; -+ -+ ret = uclass_first_device_err(UCLASS_FFA, &dev); -+ if (ret) { -+ log_err("EFI: Cannot find FF-A bus device, trying Optee comms\n"); -+ return MM_COMMS_OPTEE; -+ } -+ -+ return MM_COMMS_FFA; -+} -+ -+/** -+ * mm_communicate() - Adjust the communication buffer to the MM SP and send - * it to OP-TEE - * -- * @comm_buf: locally allocted communcation buffer -+ * @comm_buf: locally allocated communication buffer - * @dsize: buffer size -+ * -+ * The SP (also called partition) can be any MM SP such as StandAlonneMM or smm-gateway. -+ * The comm_buf format is the same for both partitions. -+ * When using the u-boot OP-TEE driver, StandAlonneMM is supported. -+ * When using the u-boot FF-A driver, any MM SP is supported. -+ * - * Return: status code - */ - static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize) - { - efi_status_t ret; -+ enum mm_comms_select mm_comms; - struct efi_mm_communicate_header *mm_hdr; - struct smm_variable_communicate_header *var_hdr; - -@@ -162,7 +404,12 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize) - mm_hdr = (struct efi_mm_communicate_header *)comm_buf; - var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data; - -- ret = optee_mm_communicate(comm_buf, dsize); -+ mm_comms = get_mm_comms(); -+ if (mm_comms == MM_COMMS_FFA) -+ ret = ffa_mm_communicate(comm_buf, dsize); -+ else -+ ret = optee_mm_communicate(comm_buf, dsize); -+ - if (ret != EFI_SUCCESS) { - log_err("%s failed!\n", __func__); - return ret; -@@ -697,7 +944,7 @@ void efi_variables_boot_exit_notify(void) - ret = EFI_NOT_FOUND; - - if (ret != EFI_SUCCESS) -- log_err("Unable to notify StMM for ExitBootServices\n"); -+ log_err("Unable to notify the MM partition for ExitBootServices\n"); - free(comm_buf); - - /* diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0009-arm_ffa-sandbox-Add-FFA_MEM_RECLAIM-tests.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0009-arm_ffa-sandbox-Add-FFA_MEM_RECLAIM-tests.patch new file mode 100644 index 00000000..01f63df4 --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0009-arm_ffa-sandbox-Add-FFA_MEM_RECLAIM-tests.patch @@ -0,0 +1,68 @@ +From a1242cf231ef4d0fc1da36420e2db8cb12f7aa26 Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Thu, 17 Oct 2024 15:50:21 +0100 +Subject: [PATCH 09/36] arm_ffa: sandbox: Add FFA_MEM_RECLAIM tests + +Add FFA_MEM_RECLAIM positive and negative test cases + +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20250702152528.1180414-1-abdellatif.elkhlifi@arm.com/] +--- + test/dm/ffa.c | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/test/dm/ffa.c b/test/dm/ffa.c +index 59eea9a57cc..f4a6716cfd8 100644 +--- a/test/dm/ffa.c ++++ b/test/dm/ffa.c +@@ -179,6 +179,27 @@ static int test_ffa_memory_share(bool test_ack, struct unit_test_state *uts) + return 0; + } + ++static int test_ffa_memory_reclaim(bool test_ack, struct unit_test_state *uts) ++{ ++ int ret; ++ u64 g_handle; ++ struct udevice *dev; ++ ++ ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev)); ++ ++ if (test_ack) { ++ g_handle = PACK_HANDLE(SANDBOX_MEM_HANDLE, SANDBOX_MEM_HANDLE); ++ ut_assertok(ffa_memory_reclaim(dev, g_handle, 0)); ++ } else { ++ /* Provide a wrong handle */ ++ g_handle = PACK_HANDLE(SANDBOX_MEM_HANDLE, 0); ++ ret = ffa_memory_reclaim(dev, g_handle, 0); ++ ut_asserteq(-EINVAL, ret); ++ } ++ ++ return 0; ++} ++ + static int dm_test_ffa_ack(struct unit_test_state *uts) + { + struct ffa_priv *uc_priv; +@@ -236,6 +257,9 @@ static int dm_test_ffa_ack(struct unit_test_state *uts) + /* Test FFA_MEM_SHARE */ + test_ffa_memory_share(true, uts); + ++ /* Test FFA_MEM_RECLAIM */ ++ test_ffa_memory_reclaim(true, uts); ++ + return 0; + } + DM_TEST(dm_test_ffa_ack, UTF_SCAN_FDT | UTF_CONSOLE); +@@ -297,6 +321,9 @@ static int dm_test_ffa_nack(struct unit_test_state *uts) + /* Test FFA_MEM_SHARE */ + test_ffa_memory_share(false, uts); + ++ /* Test FFA_MEM_RECLAIM */ ++ test_ffa_memory_reclaim(false, uts); ++ + return 0; + } + DM_TEST(dm_test_ffa_nack, UTF_SCAN_FDT | UTF_CONSOLE); +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0010-FF-A-v15-arm_ffa-efi-corstone1000-enable-MM-communic.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0010-FF-A-v15-arm_ffa-efi-corstone1000-enable-MM-communic.patch deleted file mode 100644 index b01d669e..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0010-FF-A-v15-arm_ffa-efi-corstone1000-enable-MM-communic.patch +++ /dev/null @@ -1,29 +0,0 @@ -From c27f5fe90433f8e1b6eaa84857171ea7fc26593a Mon Sep 17 00:00:00 2001 -From: Abdellatif El Khlifi -Date: Mon, 17 Jul 2023 15:23:33 +0100 -Subject: [PATCH] FF-A v15: arm_ffa: efi: corstone1000: enable MM communication - -turn on EFI MM communication - -On corstone1000 platform MM communication between u-boot -and the secure world (Optee) is done using the FF-A bus. - -Signed-off-by: Abdellatif El Khlifi -Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20230713132847.176000-1-abdellatif.elkhlifi@arm.com/] ---- - configs/corstone1000_defconfig | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig -index 2d391048cd..ee5481b63c 100644 ---- a/configs/corstone1000_defconfig -+++ b/configs/corstone1000_defconfig -@@ -53,3 +53,8 @@ CONFIG_DM_SERIAL=y - CONFIG_USB=y - CONFIG_USB_ISP1760=y - CONFIG_ERRNO_STR=y -+CONFIG_NVMXIP_QSPI=y -+CONFIG_EFI_MM_COMM_TEE=y -+CONFIG_FFA_SHARED_MM_BUF_SIZE=4096 -+CONFIG_FFA_SHARED_MM_BUF_OFFSET=0 -+CONFIG_FFA_SHARED_MM_BUF_ADDR=0x02000000 diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0010-fwu_arm_psa-Initialize-the-update-agent.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0010-fwu_arm_psa-Initialize-the-update-agent.patch new file mode 100644 index 00000000..e81ff633 --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0010-fwu_arm_psa-Initialize-the-update-agent.patch @@ -0,0 +1,439 @@ +From 716b0084511392055c3be8b0bb5f4f90f7c4fcd2 Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Wed, 23 Oct 2024 17:45:32 +0100 +Subject: [PATCH 10/36] fwu_arm_psa: Initialize the update agent + +Add the initializations required for the update agent + +The aim is adding support for the Trusted Services (aka TS) +Firmware Update API. This API allows the interaction with +the FWU services provided by Secure world. +At U-Boot level, we provide the PSA FWU ABI built on top of the +FF-A bus to invoke the FWU services in Secure world. + +The design is based on the Platform Security Firmware Update +for the A-profile Arm Architecture specification [1]. + +In our design, the Secure world is the update agent. U-Boot +is the update client. + +The update agent is initialized as follows: + +- Trusted Services FWU SP discovery +- Setting up the shared buffer between the Normal world (U-Boot) and + Secure world (Trusted Services) +- Notifying FWU SP about the shared buffer + +[1]: DEN0118, 1.0 A: https://developer.arm.com/documentation/den0118/latest/ + +Signed-off-by: Abdellatif El Khlifi +Signed-off-by: Davidson kumaresan +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20250702152528.1180414-1-abdellatif.elkhlifi@arm.com/] +--- + MAINTAINERS | 7 + + include/fwu_arm_psa.h | 58 ++++++++ + lib/fwu_updates/Kconfig | 18 +++ + lib/fwu_updates/Makefile | 1 + + lib/fwu_updates/fwu_arm_psa.c | 271 ++++++++++++++++++++++++++++++++++ + 5 files changed, 355 insertions(+) + create mode 100644 include/fwu_arm_psa.h + create mode 100644 lib/fwu_updates/fwu_arm_psa.c + +diff --git a/MAINTAINERS b/MAINTAINERS +index 042d3f6160a..e7ed894441e 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -1210,6 +1210,13 @@ T: git https://source.denx.de/u-boot/custodians/u-boot-fsl-qoriq.git + F: drivers/watchdog/sp805_wdt.c + F: drivers/watchdog/sbsa_gwdt.c + ++FWU ARM PSA ++M: Abdellatif El Khlifi ++M: Davidson kumaresan ++S: Maintained ++F: include/fwu_arm_psa.h ++F: lib/fwu_updates/fwu_arm_psa.c ++ + FWU Multi Bank Update + M: Sughosh Ganu + S: Maintained +diff --git a/include/fwu_arm_psa.h b/include/fwu_arm_psa.h +new file mode 100644 +index 00000000000..f1d42f9ef24 +--- /dev/null ++++ b/include/fwu_arm_psa.h +@@ -0,0 +1,58 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * Copyright 2025 Arm Limited and/or its affiliates ++ * ++ * Authors: ++ * Abdellatif El Khlifi ++ * Davidson kumaresan ++ */ ++ ++#ifndef __FWU_ARM_PSA_H ++#define __FWU_ARM_PSA_H ++ ++#include ++#include ++ ++#define FWU_BUFFER_PAGES (1024) ++ ++/* 4 MB buffer shared with secure world */ ++#define FWU_BUFFER_SIZE (FWU_BUFFER_PAGES * EFI_PAGE_SIZE) ++ ++/* TS UUID string for detecting all SPs (in big-endian format) */ ++#define ALL_TS_SP_UUID "d776cdbd-5e82-5147-3b96-ac4349f8d486" ++/* In little-endian equivalent to: bdcd76d7-825e-4751-963b-86d4f84943ac */ ++ ++/* TS FWU service UUID string (in big-endian format) */ ++#define TS_FWU_SERVICE_UUID "38a82368-061b-0e47-7497-fd53fb8bce0c" ++/* In little-endian equivalent to: 6823a838-1b06-470e-9774-0cce8bfb53fd */ ++ ++#define TS_RPC_MEM_RETRIEVE (0xff0001) ++#define TS_RPC_SERVICE_INFO_GET (0xff0003) ++#define RPC_SUCCESS (0) ++ ++#define SVC_IFACE_ID_GET_MASK GENMASK(7, 0) ++#define GET_SVC_IFACE_ID(x) \ ++ ((u8)(FIELD_GET(SVC_IFACE_ID_GET_MASK, (x)))) ++ ++#define HANDLE_MSW_MASK GENMASK(63, 32) ++#define HANDLE_LSW_MASK GENMASK(31, 0) ++#define GET_FWU_BUF_MSW(x) \ ++ ((u32)(FIELD_GET(HANDLE_MSW_MASK, (x)))) ++#define GET_FWU_BUF_LSW(x) \ ++ ((u32)(FIELD_GET(HANDLE_LSW_MASK, (x)))) ++ ++/** ++ * fwu_agent_init() - Setup the FWU agent ++ * ++ * Perform the initializations required to communicate ++ * and use the FWU agent in secure world. ++ * The frontend of the FWU agent is the Trusted Services (aka TS) ++ * FWU SP (aka Secure Partition). ++ * ++ * Return: ++ * ++ * 0 is returned on success. Otherwise, failure ++ */ ++int fwu_agent_init(void); ++ ++#endif +diff --git a/lib/fwu_updates/Kconfig b/lib/fwu_updates/Kconfig +index a722107c129..cdc96109f0a 100644 +--- a/lib/fwu_updates/Kconfig ++++ b/lib/fwu_updates/Kconfig +@@ -46,4 +46,22 @@ config FWU_MDATA_V2 + metadata structure. This option enables support for FWU + Metadata version 2 access. + ++config FWU_ARM_PSA ++ bool "FMP driver for Arm PSA FWU specification" ++ depends on EFI_CAPSULE_FIRMWARE_MANAGEMENT && \ ++ EFI_CAPSULE_FIRMWARE_RAW && \ ++ ARM_FFA_TRANSPORT && (ARM64 || SANDBOX) ++ select EFI_CAPSULE_FIRMWARE ++ help ++ Select this option if you want to enable firmware management protocol ++ driver that supports the Arm PSA firmware update specification as ++ mentioned in https://developer.arm.com/documentation/den0118/a/ ++ ++config FWU_BUFFER_PAGES ++ int "Number of 4KB pages in the FWU shared buffer" ++ depends on FWU_ARM_PSA ++ default 1024 ++ help ++ This defines the size of the FWU shared buffer used for communication. ++ + endif +diff --git a/lib/fwu_updates/Makefile b/lib/fwu_updates/Makefile +index 3681bef46cd..498e2411091 100644 +--- a/lib/fwu_updates/Makefile ++++ b/lib/fwu_updates/Makefile +@@ -8,3 +8,4 @@ obj-$(CONFIG_FWU_MDATA_GPT_BLK) += fwu_gpt.o + obj-$(CONFIG_FWU_MDATA_MTD) += fwu_mtd.o + obj-$(CONFIG_FWU_MDATA_V1) += fwu_v1.o + obj-$(CONFIG_FWU_MDATA_V2) += fwu_v2.o ++obj-$(CONFIG_FWU_ARM_PSA) += fwu_arm_psa.o +diff --git a/lib/fwu_updates/fwu_arm_psa.c b/lib/fwu_updates/fwu_arm_psa.c +new file mode 100644 +index 00000000000..4a01c5ac672 +--- /dev/null ++++ b/lib/fwu_updates/fwu_arm_psa.c +@@ -0,0 +1,271 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Copyright 2025 Arm Limited and/or its affiliates ++ * ++ * Authors: ++ * Abdellatif El Khlifi ++ * Davidson kumaresan ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static void *g_fwu_buf; ++static u64 g_fwu_buf_handle; ++static u16 g_fwu_sp_id; ++static struct udevice *g_dev; ++static u16 g_svc_interface_id; ++static bool g_fwu_initialized; ++ ++/** ++ * fwu_discover_ts_sp_id() - Query the FWU partition ID ++ * ++ * Use the FF-A driver to get the FWU partition ID. ++ * If multiple partitions are found, use the first one. ++ * ++ * Return: ++ * ++ * 0 on success ++ */ ++static int fwu_discover_ts_sp_id(void) ++{ ++ u32 count = 0; ++ int ret; ++ u32 i; ++ struct ffa_partition_desc *descs = NULL; ++ struct ffa_send_direct_data msg; ++ struct ffa_partition_uuid fwu_service_uuid = {0}; ++ ++ /* Ask the driver to fill the buffer with the SPs info */ ++ ++ ret = ffa_partition_info_get(g_dev, ALL_TS_SP_UUID, &count, &descs); ++ if (ret) { ++ log_err("FWU: Failure in querying partitions (err: %d)\n", ret); ++ return ret; ++ } ++ ++ if (!count) { ++ log_err("FWU: No Trusted Service partition found\n"); ++ return -ENODATA; ++ } ++ ++ if (!descs) { ++ log_err("FWU: No partitions descriptors filled\n"); ++ return -EINVAL; ++ } ++ ++ if (uuid_str_to_le_bin(TS_FWU_SERVICE_UUID, ++ (unsigned char *)&fwu_service_uuid)) { ++ log_err("FWU: invalid FWU SP UUID\n"); ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < count ; i++) { ++ log_debug("FWU: Enquiring service from SP 0x%x\n", ++ descs[i].info.id); ++ ++ msg.data0 = TS_RPC_SERVICE_INFO_GET; ++ msg.data1 = fwu_service_uuid.a1; ++ msg.data2 = fwu_service_uuid.a2; ++ msg.data3 = fwu_service_uuid.a3; ++ msg.data4 = fwu_service_uuid.a4; ++ ++ ret = ffa_sync_send_receive(g_dev, descs[i].info.id, &msg, 0); ++ if (ret) { ++ log_err("FWU: FF-A error for SERVICE_INFO_GET (err: %d)\n", ++ ret); ++ return ret; ++ } ++ ++ if (msg.data0 != TS_RPC_SERVICE_INFO_GET) { ++ log_err("FWU: Wrong SERVICE_INFO_GET return: (%lx)\n", ++ msg.data0); ++ continue; ++ } ++ ++ if (msg.data1 == RPC_SUCCESS) { ++ g_svc_interface_id = GET_SVC_IFACE_ID(msg.data2); ++ g_fwu_sp_id = descs[i].info.id; ++ log_debug("FWU: Service interface ID 0x%x found\n", ++ g_svc_interface_id); ++ return 0; ++ } ++ ++ log_debug("FWU: service not found\n"); ++ } ++ ++ log_err("FWU: No SP provides the service\n"); ++ ++ return -ENOENT; ++} ++ ++/** ++ * fwu_shared_buf_reclaim() - Reclaim the shared communication buffer ++ * ++ * In case of errors, this function can be called to retrieve ++ * the FWU shared buffer. ++ * ++ * Return: ++ * ++ * 0 is returned on success. Otherwise, failure ++ */ ++static int fwu_shared_buf_reclaim(void) ++{ ++ int reclaim_ret; ++ ++ reclaim_ret = ffa_memory_reclaim(g_dev, g_fwu_buf_handle, 0); ++ if (reclaim_ret) ++ log_err("FWU: FF-A memory reclaim failure (err: %d)\n", ++ reclaim_ret); ++ else ++ log_debug("FWU: Shared buffer reclaimed\n"); ++ ++ free(g_fwu_buf); ++ g_fwu_buf = NULL; ++ ++ return reclaim_ret; ++} ++ ++/** ++ * fwu_shared_buf_init() - Setup the FWU shared communication buffer ++ * ++ * The communication with the TS FWU SP is based on a buffer shared ++ * between U-Boot and TS FWU SP allocated in normal world and accessed ++ * by both sides. The buffer contains the data exchanged between both sides ++ * such as the payloads data. ++ * ++ * Return: ++ * ++ * 0 is returned on success. Otherwise, failure ++ */ ++static int fwu_shared_buf_init(void) ++{ ++ struct ffa_mem_ops_args args = {0}; ++ struct ffa_mem_region_attributes attrs = {0}; ++ struct ffa_send_direct_data msg; ++ int ret; ++ ++ g_fwu_buf = memalign(EFI_PAGE_SIZE, FWU_BUFFER_SIZE); ++ if (!g_fwu_buf) { ++ log_err("FWU: Failure to allocate the shared buffer\n"); ++ return -ENOMEM; ++ } ++ ++ /* Setting up user arguments */ ++ args.use_txbuf = true; ++ args.address = g_fwu_buf; ++ args.pg_cnt = FWU_BUFFER_PAGES; ++ args.nattrs = 1; ++ attrs.receiver = g_fwu_sp_id; ++ attrs.attrs = FFA_MEM_RW; ++ args.attrs = &attrs; ++ ++ /* Registering the shared buffer with secure world (Trusted Services) */ ++ ret = ffa_memory_share(g_dev, &args); ++ if (ret) { ++ free(g_fwu_buf); ++ g_fwu_buf = NULL; ++ log_err("FWU: Failure setting up the shared buffer (err: %d)\n", ++ ret); ++ return ret; ++ } ++ ++ g_fwu_buf_handle = args.g_handle; ++ ++ log_debug("FWU: shared buffer handle 0x%llx\n", g_fwu_buf_handle); ++ ++ /* Inform the FWU SP know about the shared buffer */ ++ ++ msg.data0 = TS_RPC_MEM_RETRIEVE; ++ msg.data1 = GET_FWU_BUF_LSW(g_fwu_buf_handle); ++ msg.data2 = GET_FWU_BUF_MSW(g_fwu_buf_handle); ++ ++ ret = ffa_sync_send_receive(g_dev, g_fwu_sp_id, &msg, 0); ++ if (ret) { ++ log_err("FWU: FF-A message error for MEM_RETRIEVE (err: %d)\n", ++ ret); ++ goto failure; ++ } ++ ++ if (msg.data0 != TS_RPC_MEM_RETRIEVE) { ++ log_err("FWU: Unexpected MEM_RETRIEVE return: (%lx)\n", ++ msg.data0); ++ ret = -EINVAL; ++ goto failure; ++ } ++ ++ if (msg.data1 != RPC_SUCCESS) { ++ log_err("FWU: MEM_RETRIEVE failed\n"); ++ ret = -EOPNOTSUPP; ++ goto failure; ++ } ++ ++ log_debug("FWU: MEM_RETRIEVE success for SP 0x%x\n", g_fwu_sp_id); ++ ++ return 0; ++ ++failure: ++ fwu_shared_buf_reclaim(); ++ return ret; ++} ++ ++/** ++ * fwu_agent_init() - Setup the FWU agent ++ * ++ * Perform the initializations required to communicate ++ * and use the FWU agent in secure world. ++ * The frontend of the FWU agent is the Trusted Services (aka TS) ++ * FWU SP (aka Secure Partition). ++ * ++ * Return: ++ * ++ * 0 is returned on success. Otherwise, failure ++ */ ++int fwu_agent_init(void) ++{ ++ int ret; ++ struct fwu_data *fwu_data; ++ u32 active_idx; ++ ++ fwu_data = fwu_get_data(); ++ if (!fwu_data) { ++ log_err("FWU: Cannot get FWU data\n"); ++ return -EINVAL; ++ } ++ ++ ret = fwu_get_active_index(&active_idx); ++ if (ret) { ++ log_err("FWU: Failed to read boot index, err (%d)\n", ++ ret); ++ return ret; ++ } ++ ++ if (fwu_data->trial_state) ++ log_info("FWU: System booting in Trial State\n"); ++ else ++ log_info("FWU: System booting in Regular State\n"); ++ ++ ret = uclass_first_device_err(UCLASS_FFA, &g_dev); ++ if (ret) { ++ log_err("FWU: Cannot find FF-A bus device, err (%d)\n", ret); ++ return ret; ++ } ++ ++ ret = fwu_discover_ts_sp_id(); ++ if (ret) ++ return ret; ++ ++ ret = fwu_shared_buf_init(); ++ if (ret) ++ return ret; ++ ++ g_fwu_initialized = true; ++ ++ return 0; ++} +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0011-efi-corstone1000-fwu-introduce-EFI-capsule-update.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0011-efi-corstone1000-fwu-introduce-EFI-capsule-update.patch deleted file mode 100644 index 62fd6d5a..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0011-efi-corstone1000-fwu-introduce-EFI-capsule-update.patch +++ /dev/null @@ -1,406 +0,0 @@ -From 2a054e537037bb4f4f9e144ca69438abd9bb38ed Mon Sep 17 00:00:00 2001 -From: Abdellatif El Khlifi -Date: Mon, 17 Jul 2023 15:56:18 +0100 -Subject: [PATCH] efi: corstone1000: fwu: introduce EFI capsule update - -This commit provides capsule update feature for Corstone1000. - -This feature is available before and after ExitBootServices(). - -A platform specific capsule buffer is allocated. This buffer -is physically contiguous and allocated at the start of the DDR -memory after u-boot relocation to the end of DDR. - -The capsule buffer is shared between u-boot and the secure world. - -On UpdateCapsule() , capsule data is copied to the buffer and a buffer ready event is generated using FF-A transport. - -On efi_init_capsule() in U-Boot, an EFI started event is sent to SE Proxy FW update service. This event is generated on each boot. - -Note: The SE proxy SP requires that the interface/event IDs are passed using register w4 for the buffer ready event and the EFI started event. - - interface ID (31:16) - event ID (15:0) - -Signed-off-by: Abdellatif El Khlifi -Signed-off-by: Vishnu Banavath -Signed-off-by: Rui Miguel Silva -Upstream-Status: Pending [Not submitted to upstream yet] ---- - board/armltd/corstone1000/corstone1000.c | 4 + - configs/corstone1000_defconfig | 3 + - include/configs/corstone1000.h | 24 ++++ - include/efi_loader.h | 4 +- - lib/efi_loader/efi_boottime.c | 7 ++ - lib/efi_loader/efi_capsule.c | 136 ++++++++++++++++++++++- - lib/efi_loader/efi_setup.c | 64 +++++++++++ - 7 files changed, 238 insertions(+), 4 deletions(-) - -diff --git a/board/armltd/corstone1000/corstone1000.c b/board/armltd/corstone1000/corstone1000.c -index 6ec8e6144f..c840290885 100644 ---- a/board/armltd/corstone1000/corstone1000.c -+++ b/board/armltd/corstone1000/corstone1000.c -@@ -67,6 +67,10 @@ static struct mm_region corstone1000_mem_map[] = { - - struct mm_region *mem_map = corstone1000_mem_map; - -+void set_dfu_alt_info(char *interface, char *devstr) -+{ -+} -+ - int board_init(void) - { - return 0; -diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig -index ee5481b63c..40ba415ecb 100644 ---- a/configs/corstone1000_defconfig -+++ b/configs/corstone1000_defconfig -@@ -58,3 +58,6 @@ CONFIG_EFI_MM_COMM_TEE=y - CONFIG_FFA_SHARED_MM_BUF_SIZE=4096 - CONFIG_FFA_SHARED_MM_BUF_OFFSET=0 - CONFIG_FFA_SHARED_MM_BUF_ADDR=0x02000000 -+CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y -+CONFIG_EFI_CAPSULE_FIRMWARE_FIT=y -+CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y -diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h -index 3347c11792..8927b09499 100644 ---- a/include/configs/corstone1000.h -+++ b/include/configs/corstone1000.h -@@ -14,6 +14,30 @@ - - #include - -+/* The SE Proxy partition ID*/ -+#define CORSTONE1000_SEPROXY_PART_ID (0x8002) -+ -+/* Update service ID provided by the SE Proxy secure partition*/ -+#define CORSTONE1000_SEPROXY_UPDATE_SVC_ID (0x4) -+ -+/* Notification events used with SE Proxy update service */ -+#define CORSTONE1000_BUFFER_READY_EVT (0x1) -+#define CORSTONE1000_UBOOT_EFI_STARTED_EVT (0x2) -+ -+#define PREP_SEPROXY_SVC_ID_MASK GENMASK(31, 16) -+#define PREP_SEPROXY_SVC_ID(x) (FIELD_PREP(PREP_SEPROXY_SVC_ID_MASK, (x))) -+ -+#define PREP_SEPROXY_EVT_MASK GENMASK(15, 0) -+#define PREP_SEPROXY_EVT(x) (FIELD_PREP(PREP_SEPROXY_EVT_MASK, (x))) -+ -+/* Size in 4KB pages of the EFI capsule buffer */ -+#define CORSTONE1000_CAPSULE_BUFFER_SIZE (8192) /* 32 MB */ -+ -+/* Capsule GUID */ -+#define EFI_CORSTONE1000_CAPSULE_ID_GUID \ -+ EFI_GUID(0x3a770ddc, 0x409b, 0x48b2, 0x81, 0x41, \ -+ 0x93, 0xb7, 0xc6, 0x0b, 0x20, 0x9e) -+ - #define V2M_BASE 0x80000000 - - #define CFG_PL011_CLOCK 50000000 -diff --git a/include/efi_loader.h b/include/efi_loader.h -index 38d7f66bab..0a613ed51e 100644 ---- a/include/efi_loader.h -+++ b/include/efi_loader.h -@@ -1036,11 +1036,11 @@ extern const struct efi_firmware_management_protocol efi_fmp_fit; - extern const struct efi_firmware_management_protocol efi_fmp_raw; - - /* Capsule update */ --efi_status_t EFIAPI efi_update_capsule( -+efi_status_t __efi_runtime EFIAPI efi_update_capsule( - struct efi_capsule_header **capsule_header_array, - efi_uintn_t capsule_count, - u64 scatter_gather_list); --efi_status_t EFIAPI efi_query_capsule_caps( -+efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps( - struct efi_capsule_header **capsule_header_array, - efi_uintn_t capsule_count, - u64 *maximum_capsule_size, -diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c -index d5065f296a..a5da77c36c 100644 ---- a/lib/efi_loader/efi_boottime.c -+++ b/lib/efi_loader/efi_boottime.c -@@ -23,6 +23,13 @@ - #include - #include - -+#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) -+#include -+#include -+#include -+#include -+#endif -+ - DECLARE_GLOBAL_DATA_PTR; - - /* Task priority level */ -diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c -index 7a6f195cbc..ea084e4ed2 100644 ---- a/lib/efi_loader/efi_capsule.c -+++ b/lib/efi_loader/efi_capsule.c -@@ -26,6 +26,17 @@ - #include - #include - -+#ifdef CONFIG_TARGET_CORSTONE1000 -+#include -+#include -+#include -+#include -+#include -+ -+void *__efi_runtime_data corstone1000_capsule_buf; /* capsule shared buffer virtual address */ -+efi_guid_t corstone1000_capsule_guid = EFI_CORSTONE1000_CAPSULE_ID_GUID; -+#endif -+ - DECLARE_GLOBAL_DATA_PTR; - - const efi_guid_t efi_guid_capsule_report = EFI_CAPSULE_REPORT_GUID; -@@ -709,6 +720,87 @@ static efi_status_t efi_capsule_update_firmware( - } - #endif /* CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT */ - -+#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) -+ -+/** -+ * efi_corstone1000_alloc_capsule_shared_buf - allocate capsule shared buffer -+ * @capsule_image_size: The capsule data (header + payload) -+ * -+ * This function allocates the physically contiguous buffer shared between u-boot -+ * and the secure world. On UpdateCapsule() capsule data is copied to the buffer -+ * and a door bell event is generated. -+ * The buffer is allocated at the start of the DDR memory after u-boot has been relocated -+ * to the end of DDR. -+ * -+ * Return: -+ * -+ * 0: on success, otherwise failure -+ */ -+efi_status_t efi_corstone1000_alloc_capsule_shared_buf(void) -+{ -+ efi_status_t efi_ret; -+ u64 ram_base = CFG_SYS_SDRAM_BASE; -+ -+ log_debug("[%s]\n", __func__); -+ -+ efi_ret = efi_allocate_pages(EFI_ALLOCATE_ADDRESS, -+ EFI_RUNTIME_SERVICES_DATA, -+ CORSTONE1000_CAPSULE_BUFFER_SIZE, -+ &ram_base); -+ -+ if (efi_ret != EFI_SUCCESS) { -+ corstone1000_capsule_buf = NULL; -+ log_err("EFI: Corstone1000: Allocating capsule shared buffer error (%d)\n" -+ , (int)efi_ret); -+ return efi_ret; -+ } -+ -+ log_info("EFI: Corstone1000: Capsule shared buffer at 0x%x , size %d pages\n" -+ , (unsigned int)ram_base, -+ CORSTONE1000_CAPSULE_BUFFER_SIZE); -+ -+ corstone1000_capsule_buf = (void *)map_sysmem((phys_addr_t)ram_base, 0); -+ -+ return EFI_SUCCESS; -+} -+ -+/** -+ * efi_corstone1000_buffer_ready_event - issue door bell event -+ * @capsule_image_size: The capsule data (header + payload) -+ * -+ * This function notifies the SE Proxy update service that capsule data is available -+ * in the capsule shared buffer. -+ * -+ * Return: -+ * -+ * 0: on success, otherwise failure -+ */ -+static int __efi_runtime efi_corstone1000_buffer_ready_event(u32 capsule_image_size) -+{ -+ struct ffa_send_direct_data msg = {0}; -+ int ret; -+ struct udevice *dev; -+ -+ log_debug("[%s]\n", __func__); -+ -+ ret = uclass_first_device_err(UCLASS_FFA, &dev); -+ if (ret) { -+ log_err("Cannot find FF-A bus device\n"); -+ return ret; -+ } -+ -+ /* -+ * setting the buffer ready event arguments in register w4: -+ * - capsule update interface ID (31:16) -+ * - the buffer ready event ID (15:0) -+ */ -+ msg.data1 = PREP_SEPROXY_SVC_ID(CORSTONE1000_SEPROXY_UPDATE_SVC_ID) | -+ PREP_SEPROXY_EVT(CORSTONE1000_BUFFER_READY_EVT); /* w4 */ -+ -+ return ffa_sync_send_receive(dev, CORSTONE1000_SEPROXY_PART_ID, &msg, 0); -+} -+#endif -+ - /** - * efi_update_capsule() - process information from operating system - * @capsule_header_array: Array of virtual address pointers -@@ -722,7 +814,7 @@ static efi_status_t efi_capsule_update_firmware( - * - * Return: status code - */ --efi_status_t EFIAPI efi_update_capsule( -+efi_status_t __efi_runtime EFIAPI efi_update_capsule( - struct efi_capsule_header **capsule_header_array, - efi_uintn_t capsule_count, - u64 scatter_gather_list) -@@ -739,6 +831,13 @@ efi_status_t EFIAPI efi_update_capsule( - goto out; - } - -+#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) -+ if (capsule_count != 1 || !corstone1000_capsule_buf) { -+ ret = EFI_INVALID_PARAMETER; -+ goto out; -+ } -+#endif -+ - ret = EFI_SUCCESS; - for (i = 0, capsule = *capsule_header_array; i < capsule_count; - i++, capsule = *(++capsule_header_array)) { -@@ -751,6 +850,39 @@ efi_status_t EFIAPI efi_update_capsule( - - log_debug("Capsule[%d] (guid:%pUs)\n", - i, &capsule->capsule_guid); -+ -+#if CONFIG_IS_ENABLED(TARGET_CORSTONE1000) -+ if (guidcmp(&corstone1000_capsule_guid, &capsule->capsule_guid)) { -+ ret = EFI_INVALID_PARAMETER; -+ log_err("Corstone1000: Invalid capsule GUID\n"); -+ goto out; -+ } -+ -+ if (efi_size_in_pages(capsule->capsule_image_size) > -+ CORSTONE1000_CAPSULE_BUFFER_SIZE) { -+ log_err("Corstone1000: Capsule data size exceeds the shared buffer size\n"); -+ ret = EFI_BUFFER_TOO_SMALL; -+ goto out; -+ } -+ -+ /* copy the data to the contiguous buffer */ -+ efi_memcpy_runtime(corstone1000_capsule_buf, capsule, capsule->capsule_image_size); -+ -+ /* invalidate the data cache */ -+ invalidate_dcache_all(); -+ -+ /* issue buffer ready event */ -+ ret = efi_corstone1000_buffer_ready_event(capsule->capsule_image_size); -+ if (ret) { -+ log_err("EFI: Corstone1000: Buffer ready event error (%d)\n", (int)ret); -+ ret = EFI_DEVICE_ERROR; -+ } else { -+ ret = EFI_SUCCESS; -+ } -+ -+ goto out; -+#endif -+ - if (!guidcmp(&capsule->capsule_guid, - &efi_guid_firmware_management_capsule_id)) { - ret = efi_capsule_update_firmware(capsule); -@@ -789,7 +921,7 @@ out: - * - * Return: status code - */ --efi_status_t EFIAPI efi_query_capsule_caps( -+efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps( - struct efi_capsule_header **capsule_header_array, - efi_uintn_t capsule_count, - u64 *maximum_capsule_size, -diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c -index 58d4e13402..bf90a98b5a 100644 ---- a/lib/efi_loader/efi_setup.c -+++ b/lib/efi_loader/efi_setup.c -@@ -17,6 +17,18 @@ - - efi_status_t efi_obj_list_initialized = OBJ_LIST_NOT_INITIALIZED; - -+#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) -+#include -+#include -+#include -+#include -+ -+/** -+ * efi_corstone1000_alloc_capsule_shared_buf - allocate capsule shared buffer -+ */ -+extern efi_status_t efi_corstone1000_alloc_capsule_shared_buf(void); -+#endif -+ - /* - * Allow unaligned memory access. - * -@@ -120,6 +132,42 @@ static efi_status_t efi_init_secure_boot(void) - } - #endif /* CONFIG_EFI_SECURE_BOOT */ - -+#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) -+/** -+ * efi_corstone1000_uboot-efi_started_event - notifies SE Proxy FW update service -+ * -+ * This function notifies the SE Proxy update service that uboot efi has already started -+ * -+ * Return: -+ * -+ * 0: on success, otherwise failure -+ * */ -+static int efi_corstone1000_uboot_efi_started_event(void) -+{ -+ struct ffa_send_direct_data msg = {0}; -+ int ret; -+ struct udevice *dev; -+ -+ log_debug("[%s]\n", __func__); -+ -+ ret = uclass_first_device_err(UCLASS_FFA, &dev); -+ if (ret) { -+ log_err("Cannot find FF-A bus device\n"); -+ return ret; -+ } -+ -+ /* -+ * setting the kernel started event arguments: -+ * setting capsule update interface ID(31:16) -+ * the kernel started event ID(15:0) -+ */ -+ msg.data1 = PREP_SEPROXY_SVC_ID(CORSTONE1000_SEPROXY_UPDATE_SVC_ID) | -+ PREP_SEPROXY_EVT(CORSTONE1000_UBOOT_EFI_STARTED_EVT); /* w4 */ -+ -+ return ffa_sync_send_receive(dev, CORSTONE1000_SEPROXY_PART_ID, &msg, 0); -+} -+#endif -+ - /** - * efi_init_capsule - initialize capsule update state - * -@@ -129,6 +177,22 @@ static efi_status_t efi_init_capsule(void) - { - efi_status_t ret = EFI_SUCCESS; - -+#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) -+ int ffa_ret; -+ -+ ffa_ret = efi_corstone1000_uboot_efi_started_event(); -+ if (ffa_ret) -+ log_err("Failure to notify SE Proxy FW update service\n"); -+ else -+ debug("SE Proxy FW update service notified\n"); -+ -+ ret = efi_corstone1000_alloc_capsule_shared_buf(); -+ if (ret != EFI_SUCCESS) { -+ printf("EFI: Corstone-1000: cannot allocate caspsule shared buffer\n"); -+ return ret; -+ } -+#endif -+ - if (IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT)) { - u16 var_name16[12]; - diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0011-fwu_arm_psa-Read-the-FWU-directory-through-get_image.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0011-fwu_arm_psa-Read-the-FWU-directory-through-get_image.patch new file mode 100644 index 00000000..36d96652 --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0011-fwu_arm_psa-Read-the-FWU-directory-through-get_image.patch @@ -0,0 +1,894 @@ +From 372b693b0d9778fc5696512f13d39d0090b9b0d9 Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Fri, 15 Nov 2024 19:24:50 +0000 +Subject: [PATCH 11/36] fwu_arm_psa: Read the FWU directory through + get_image_info() + +Implement get_image_info() + +get_image_info() is implemented by fwu_arm_psa_get_image_info() +which reads the images information from the cached directory in Secure +world then populates the images descriptors. + +The FWU Arm PSA setup ABIs have been implemented to allow +reading the directory data. + +The ABIs are specified by the Platform Security Firmware Update for +the A-profile Arm Architecture specification [1]. + +For more details about PSA please see [2]. + +The implemented ABIs are as follows: + +FWU_DISCOVER +FWU_OPEN +FWU_READ_STREAM +FWU_COMMIT + +[1]: DEN0118, 1.0 A: https://developer.arm.com/documentation/den0118/latest/ +[2]: https://www.psacertified.org/ + +Signed-off-by: Abdellatif El Khlifi +Signed-off-by: Davidson kumaresan +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20250702152528.1180414-1-abdellatif.elkhlifi@arm.com/] +--- + include/fwu_arm_psa.h | 206 ++++++++++++ + lib/fwu_updates/fwu_arm_psa.c | 580 +++++++++++++++++++++++++++++++++- + 2 files changed, 785 insertions(+), 1 deletion(-) + +diff --git a/include/fwu_arm_psa.h b/include/fwu_arm_psa.h +index f1d42f9ef24..ba294359b5e 100644 +--- a/include/fwu_arm_psa.h ++++ b/include/fwu_arm_psa.h +@@ -10,9 +10,16 @@ + #ifndef __FWU_ARM_PSA_H + #define __FWU_ARM_PSA_H + ++#include + #include + #include + ++#define DEFAULT_HW_INSTANCE (1) ++ ++/* Default values of the ESRT fields which are not supported at this stage */ ++#define PACKAGE_VERSION_NOT_SUP (0xffffffff) ++#define LAST_ATTEMPT_NOT_SUP (0) ++ + #define FWU_BUFFER_PAGES (1024) + + /* 4 MB buffer shared with secure world */ +@@ -26,6 +33,13 @@ + #define TS_FWU_SERVICE_UUID "38a82368-061b-0e47-7497-fd53fb8bce0c" + /* In little-endian equivalent to: 6823a838-1b06-470e-9774-0cce8bfb53fd */ + ++/* TS FWU directory UUID string (in big-endian format) */ ++#define FWU_DIRECTORY_CANONICAL_UUID "d958eede-4751-d34a-90a2-a541236e6677" ++/* In little-endian equivalent to: deee58d9-5147-4ad3-a290-77666e2341a5 */ ++ ++/* The entries correspond to the payloads in the storage device and the fake ESRT image */ ++#define FWU_DIRECTORY_IMAGE_ENTRIES_COUNT (CONFIG_FWU_NUM_IMAGES_PER_BANK + 1) ++ + #define TS_RPC_MEM_RETRIEVE (0xff0001) + #define TS_RPC_SERVICE_INFO_GET (0xff0003) + #define RPC_SUCCESS (0) +@@ -34,6 +48,11 @@ + #define GET_SVC_IFACE_ID(x) \ + ((u8)(FIELD_GET(SVC_IFACE_ID_GET_MASK, (x)))) + ++#define SVC_ID_MASK GENMASK(15, 0) ++#define SVC_IFACE_ID_SET_MASK GENMASK(23, 16) ++#define PACK_SVC_IFACE_ID(svc, iface) (FIELD_PREP(SVC_ID_MASK, (svc)) | \ ++ FIELD_PREP(SVC_IFACE_ID_SET_MASK, (iface))) ++ + #define HANDLE_MSW_MASK GENMASK(63, 32) + #define HANDLE_LSW_MASK GENMASK(31, 0) + #define GET_FWU_BUF_MSW(x) \ +@@ -41,6 +60,174 @@ + #define GET_FWU_BUF_LSW(x) \ + ((u32)(FIELD_GET(HANDLE_LSW_MASK, (x)))) + ++enum fwu_abis { ++ FWU_DISCOVER = 0, ++ FWU_OPEN = 19, ++ FWU_READ_STREAM = 21, ++ FWU_COMMIT = 22, ++ /* To be updated when adding new FWU IDs */ ++ FWU_FIRST_ID = FWU_DISCOVER, /* Lowest number ID */ ++ FWU_LAST_ID = FWU_COMMIT, /* Highest number ID */ ++}; ++ ++enum fwu_abi_errcode { ++ FWU_UNKNOWN = 1, ++ FWU_BUSY, ++ FWU_OUT_OF_BOUNDS, ++ FWU_AUTH_FAIL, ++ FWU_NO_PERMISSION, ++ FWU_DENIED, ++ FWU_RESUME, ++ FWU_NOT_AVAILABLE, ++ MAX_NUMBER_FWU_ERR ++}; ++ ++/* Container structure and helper macros to map between an FF-A error and relevant error log */ ++struct fwu_abi_errmap { ++ char *err_str[MAX_NUMBER_FWU_ERR]; ++}; ++ ++#define FWU_ERRMAP_COUNT (FWU_LAST_ID - FWU_FIRST_ID + 1) ++#define FWU_ID_TO_ERRMAP_ID(fwu_id) ((fwu_id) - FWU_FIRST_ID) ++ ++/* ++ * struct fwu_open_args - fwu_open ABI arguments ++ * @function_id: fwu_open service ID ++ * @image_type_guid: GUID of the image to be opened ++ * @op_type: The operation that the Client will perform on the image ++ */ ++struct __packed fwu_open_args { ++ u32 function_id; ++ efi_guid_t image_type_guid; ++#define FWU_OP_TYPE_READ 0 ++#define FWU_OP_TYPE_WRITE 1 ++ u8 op_type; ++}; ++ ++/* ++ * struct fwu_open_resp - fwu_open ABI returns ++ * @status: The ABI return status ++ * @handle: Staging context identifier ++ */ ++struct __packed fwu_open_resp { ++ int status; ++ u32 handle; ++}; ++ ++/* ++ * struct fwu_discover_args - fwu_discover ABI arguments ++ * @function_id: fwu_discover service ID ++ */ ++struct __packed fwu_discover_args { ++ u32 function_id; ++}; ++ ++/* ++ * struct fwu_discover_resp - fwu_discover ABI returns ++ * @status: The ABI return status ++ * @service_status: the status of the service provider ++ * @version_major: the ABI major version ++ * @version_minor: the ABI minor version ++ * @off_function_presence: the offset (in bytes) of the function_presence array ++ * relative to the start of this data structure ++ * @num_func: the number of entries in the function_presence array ++ * @max_payload_size: the maximum number of bytes that a payload can contain ++ * @flags: flags listing the update capabilities ++ * @vendor_specific_flags: Vendor specific update capabilities flags ++ * @function_presence: array of bytes indicating functions that are implemented ++ */ ++struct __packed fwu_discover_resp { ++ int status; ++ u16 service_status; ++ u8 version_major; ++ u8 version_minor; ++ u16 off_function_presence; ++ u16 num_func; ++ u64 max_payload_size; ++ u32 flags; ++ u32 vendor_specific_flags; ++ void *function_presence; ++}; ++ ++/* ++ * struct fwu_read_stream_args - fwu_read_stream ABI arguments ++ * @function_id: fwu_read_stream service ID ++ * @handle: The handle of the context being read from ++ */ ++struct __packed fwu_read_stream_args { ++ u32 function_id; ++ u32 handle; ++}; ++ ++/* ++ * struct fwu_read_stream_resp - fwu_read_stream ABI returns ++ * @status: The ABI return status ++ * @read_bytes: Number of bytes read by the current ABI call ++ * @total_bytes: Total number of bytes that can be read ++ * @payload: The read data by the current ABI call ++ */ ++struct __packed fwu_read_stream_resp { ++ int status; ++ u32 read_bytes; ++ u32 total_bytes; ++ u8 payload[]; ++}; ++ ++/* ++ * struct fwu_commit_args - fwu_commit ABI arguments ++ * @function_id: fwu_commit service ID ++ * @handle: The handle of the context being closed ++ * @acceptance_req: If positive, the Client requests the image to be marked as ++ * unaccepted ++ * @max_atomic_len: Hint, maximum time (in ns) that the Update Agent can execute ++ * continuously without yielding back to the Client state ++ */ ++struct __packed fwu_commit_args { ++ u32 function_id; ++ u32 handle; ++#define FWU_IMG_ACCEPTED 0 ++#define FWU_IMG_NOT_ACCEPTED 1 ++ u32 acceptance_req; ++ u32 max_atomic_len; ++}; ++ ++/* ++ * struct fwu_commit_resp - fwu_commit ABI returns ++ * @status: The ABI return status ++ * @progress: Units of work already completed by the Update Agent ++ * @total_work: Units of work the Update Agent must perform until fwu_commit ++ * returns successfully ++ */ ++struct __packed fwu_commit_resp { ++ int status; ++ u32 progress; ++ u32 total_work; ++}; ++ ++/* ++ * FWU directory information structures ++ */ ++ ++struct __packed fwu_image_info_entry { ++ efi_guid_t image_guid; ++ u32 client_permissions; ++ u32 img_max_size; ++ u32 lowest_acceptable_version; ++ u32 img_version; ++ u32 accepted; ++ u32 reserved; ++}; ++ ++struct __packed fwu_image_directory { ++ u32 directory_version; ++ u32 img_info_offset; ++ u32 num_images; ++ u32 correct_boot; ++ u32 img_info_size; ++ u32 reserved; ++ struct fwu_image_info_entry entries[FWU_DIRECTORY_IMAGE_ENTRIES_COUNT]; ++}; ++ + /** + * fwu_agent_init() - Setup the FWU agent + * +@@ -55,4 +242,23 @@ + */ + int fwu_agent_init(void); + ++/** ++ * fwu_arm_psa_get_image_info() - Arm PSA implementation for GetImageInfo() ++ * ++ * Initialize the update agent in secure world if not initialized. ++ * Then, read the FWU directory information including the current ++ * images information. For more details refer to fwu_image_directory structure. ++ * ++ * Return: ++ * ++ * EFI_SUCCESS is returned on success. Otherwise, failure ++ */ ++efi_status_t fwu_arm_psa_get_image_info(efi_uintn_t *image_info_size, ++ struct efi_firmware_image_descriptor *image_info, ++ u32 *descriptor_version, ++ u8 *descriptor_count, ++ efi_uintn_t *descriptor_size, ++ u32 *package_version, ++ u16 **package_version_name); ++ + #endif +diff --git a/lib/fwu_updates/fwu_arm_psa.c b/lib/fwu_updates/fwu_arm_psa.c +index 4a01c5ac672..b42d9f90e1e 100644 +--- a/lib/fwu_updates/fwu_arm_psa.c ++++ b/lib/fwu_updates/fwu_arm_psa.c +@@ -9,7 +9,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -21,7 +20,481 @@ static u64 g_fwu_buf_handle; + static u16 g_fwu_sp_id; + static struct udevice *g_dev; + static u16 g_svc_interface_id; ++static u64 g_max_payload_size; ++static u8 g_fwu_version_major; ++static u8 g_fwu_version_minor; + static bool g_fwu_initialized; ++struct fwu_image_directory g_fwu_cached_directory; ++ ++/* Error mapping declarations */ ++ ++int fwu_to_std_errmap[MAX_NUMBER_FWU_ERR] = { ++ [FWU_UNKNOWN] = -EOPNOTSUPP, ++ [FWU_OUT_OF_BOUNDS] = -ERANGE, ++ [FWU_AUTH_FAIL] = -EFAULT, ++ [FWU_BUSY] = -EBUSY, ++ [FWU_NO_PERMISSION] = -EPERM, ++ [FWU_DENIED] = -EACCES, ++ [FWU_RESUME] = -EAGAIN, ++ [FWU_NOT_AVAILABLE] = -ENAVAIL, ++}; ++ ++static struct fwu_abi_errmap err_msg_map[FWU_ERRMAP_COUNT] = { ++ [FWU_ID_TO_ERRMAP_ID(FWU_OPEN)] = { ++ { ++ [FWU_UNKNOWN] = ++ "FWU_UNKNOWN: Image type with GUID=image_type_guid does not exist", ++ [FWU_DENIED] = ++ "FWU_DENIED: An image cannot be opened for writing outside of this Staging state", ++ [FWU_NOT_AVAILABLE] = ++ "FWU_NOT_AVAILABLE: The Update Agent does not support the op_type for this image", ++ }, ++ }, ++ [FWU_ID_TO_ERRMAP_ID(FWU_READ_STREAM)] = { ++ { ++ [FWU_UNKNOWN] = ++ "FWU_UNKNOWN: Handle is not recognized", ++ [FWU_DENIED] = ++ "FWU_DENIED: The image cannot be temporarily read from", ++ [FWU_NO_PERMISSION] = ++ "FWU_NO_PERMISSION: The image cannot be read from", ++ }, ++ }, ++ [FWU_ID_TO_ERRMAP_ID(FWU_COMMIT)] = { ++ { ++ [FWU_UNKNOWN] = ++ "FWU_UNKNOWN: Handle is not recognized", ++ [FWU_DENIED] = ++ "FWU_DENIED: The image can only be accepted after activation", ++ [FWU_AUTH_FAIL] = ++ "FWU_AUTH_FAIL: Image closed, authentication failed", ++ [FWU_RESUME] = ++ "FWU_RESUME: The Update Agent yielded", ++ }, ++ }, ++}; ++ ++/** ++ * fwu_to_std_errno() - convert FWU error code to standard error code ++ * @fwu_errno: Error code returned by the FWU ABI ++ * ++ * Map the given FWU error code as specified ++ * by the spec to a U-Boot standard error code. ++ * ++ * Return: ++ * ++ * The standard error code on success. . Otherwise, failure ++ */ ++static int fwu_to_std_errno(int fwu_errno) ++{ ++ int err_idx = -fwu_errno; ++ ++ /* Map the FWU error code to the standard u-boot error code */ ++ if (err_idx > 0 && err_idx < MAX_NUMBER_FWU_ERR) ++ return fwu_to_std_errmap[err_idx]; ++ return -EINVAL; ++} ++ ++/** ++ * fwu_print_error_log() - print the error log corresponding to the selected FWU ABI ++ * @fwu_id: FWU ABI ID ++ * @fwu_errno: Error code returned by the FWU ABI ++ * ++ * Map the FWU error code to the error log relevant to the ++ * selected FWU ABI. Then the error log is printed. ++ * ++ * Return: ++ * ++ * 0 on success. . Otherwise, failure ++ */ ++static int fwu_print_error_log(u32 fwu_id, int fwu_errno) ++{ ++ int err_idx = -fwu_errno, abi_idx = 0; ++ ++ /* Map the FWU error code to the corresponding error log */ ++ ++ if (err_idx <= 0 || err_idx >= MAX_NUMBER_FWU_ERR) ++ return -EINVAL; ++ ++ if (fwu_id < FWU_FIRST_ID || fwu_id > FWU_LAST_ID) ++ return -EINVAL; ++ ++ abi_idx = FWU_ID_TO_ERRMAP_ID(fwu_id); ++ ++ if (!err_msg_map[abi_idx].err_str[err_idx]) ++ return -EINVAL; ++ ++ log_err("%s\n", err_msg_map[abi_idx].err_str[err_idx]); ++ ++ return 0; ++} ++ ++/** ++ * fwu_invoke_svc() - FWU service call request ++ * @svc_id: FWU ABI function ID ++ * @svc_name: FWU ABI function name ++ * @req_args_sz: Size in bytes of the arguments of the FWU ABI function ++ * @expect_resp_sz: Size in bytes of the response of the FWU ABI function ++ * @extra_resp_bytes: Size in bytes of the extra response data ++ * ++ * Invoke a FWU ABI by issuing a TS service call request. ++ * ++ * Return: ++ * ++ * 0 on success ++ */ ++static int fwu_invoke_svc(u32 svc_id, const char *svc_name, ++ u32 req_args_sz, u32 expect_resp_sz, ++ u32 *extra_resp_bytes) ++{ ++ struct ffa_send_direct_data msg; ++ int ret; ++ int *svc_status_in_buf = g_fwu_buf, svc_status_in_reg; ++ u32 expect_total_resp_sz; ++ ++ log_debug("FWU: Invoking %s\n", svc_name); ++ ++ if (!expect_resp_sz || !svc_name || !req_args_sz) { ++ log_err("%s: Invalid invoke arguments\n", svc_name); ++ return -EINVAL; ++ } ++ ++ msg.data0 = PACK_SVC_IFACE_ID(svc_id, g_svc_interface_id); ++ msg.data1 = GET_FWU_BUF_LSW(g_fwu_buf_handle); ++ msg.data2 = GET_FWU_BUF_MSW(g_fwu_buf_handle); ++ msg.data3 = req_args_sz; ++ msg.data4 = 0; ++ ++ ret = ffa_sync_send_receive(g_dev, g_fwu_sp_id, &msg, 0); ++ if (ret) { ++ log_err("%s: FF-A error %d\n", svc_name, ret); ++ return ret; ++ } ++ ++ if (msg.data0 != PACK_SVC_IFACE_ID(svc_id, g_svc_interface_id)) { ++ log_err("%s: Unexpected service/interface ID 0x%lx\n", ++ svc_name, msg.data0); ++ return -EINVAL; ++ } ++ ++ if (msg.data1 != RPC_SUCCESS) { ++ log_err("%s: TS RPC error 0x%lx\n", svc_name, msg.data1); ++ return -ECOMM; ++ } ++ ++ svc_status_in_reg = (int)msg.data2; ++ if (*svc_status_in_buf != svc_status_in_reg) { ++ log_err("%s: Status mismatch (reg %d , buf %d)\n", ++ svc_name, svc_status_in_reg, *svc_status_in_buf); ++ return -EINVAL; ++ } ++ ++ if (svc_status_in_reg < 0) { ++ fwu_print_error_log(svc_id, svc_status_in_reg); ++ if (svc_status_in_reg != -FWU_RESUME) ++ return fwu_to_std_errno(svc_status_in_reg); ++ } ++ ++ if (!extra_resp_bytes) ++ expect_total_resp_sz = expect_resp_sz; ++ else ++ expect_total_resp_sz = expect_resp_sz + *extra_resp_bytes; ++ ++ if (msg.data3 != expect_total_resp_sz) { ++ log_err("%s: Unexpected response size (%ld , %d)\n", ++ svc_name, msg.data3, expect_total_resp_sz); ++ return -EINVAL; ++ } ++ ++ if (svc_status_in_reg == -FWU_RESUME) ++ return fwu_to_std_errno(svc_status_in_reg); ++ ++ return 0; ++} ++ ++/** ++ * fwu_discover() - fwu_discover ABI ++ * ++ * This call indicates the version of the ABI alongside a list of the ++ * implemented functions (aka services). ++ * Only max_payload_size is saved for future use. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++static int fwu_discover(void) ++{ ++ int ret; ++ struct fwu_discover_args *args = g_fwu_buf; ++ struct fwu_discover_resp *resp = g_fwu_buf; ++ char *svc_name = "FWU_DISCOVER"; ++ ++ /* Filling the arguments in the shared buffer */ ++ args->function_id = FWU_DISCOVER; ++ ++ /* Executing the FWU ABI through the FF-A bus */ ++ ret = fwu_invoke_svc(args->function_id, svc_name, sizeof(*args), ++ sizeof(int), NULL); ++ if (ret) { ++ log_debug("FWU_DISCOVER: error %d\n", ret); ++ return ret; ++ } ++ ++ g_max_payload_size = resp->max_payload_size; ++ g_fwu_version_major = resp->version_major; ++ g_fwu_version_minor = resp->version_minor; ++ ++ log_debug("FWU: max_payload_size %llu\n", g_max_payload_size); ++ log_info("FWU: ABI version %d.%d detected\n", g_fwu_version_major, ++ g_fwu_version_minor); ++ ++ return 0; ++} ++ ++/** ++ * fwu_open() - fwu_open ABI ++ * @guid: GUID of the image to be opened ++ * @op_type: The operation that the Client will perform on the image ++ * @handle: Staging context identifier ++ * ++ * Returns a handle to the image with a given GUID. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++static int fwu_open(const efi_guid_t *guid, u8 op_type, ++ u32 *handle) ++{ ++ int ret; ++ struct fwu_open_args *args = g_fwu_buf; ++ struct fwu_open_resp *resp = g_fwu_buf; ++ char *svc_name = "FWU_OPEN"; ++ ++ if (!guid || !handle) ++ return -EINVAL; ++ ++ /* Filling the arguments in the shared buffer */ ++ args->function_id = FWU_OPEN; ++ ++ guidcpy(&args->image_type_guid, guid); ++ args->op_type = op_type; ++ ++ /* Executing the FWU ABI through the FF-A bus */ ++ ret = fwu_invoke_svc(args->function_id, svc_name, ++ sizeof(*args), sizeof(*resp), NULL); ++ if (ret) ++ return ret; ++ ++ *handle = resp->handle; ++ ++ return 0; ++} ++ ++/** ++ * fwu_read_stream() - fwu_read_stream ABI ++ * @handle: The handle of the context being read from ++ * @buffer: The destination buffer where the data will be copied to ++ * @buffer_size: The size of the destination buffer ++ * ++ * The call reads at most g_max_payload_size bytes from the Update Agent ++ * context pointed to by handle. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++static int fwu_read_stream(u32 handle, u8 *buffer, u32 buffer_size) ++{ ++ int ret; ++ u32 curr_read_offset = 0, new_read_offset, fwu_buf_bytes_left; ++ struct fwu_read_stream_args *args = g_fwu_buf; ++ struct fwu_read_stream_resp *resp = g_fwu_buf; ++ char *svc_name = "FWU_READ_STREAM"; ++ ++ if (!buffer || !buffer_size) ++ return -EINVAL; ++ ++ do { ++ /* Filling the arguments in the shared buffer */ ++ args->function_id = FWU_READ_STREAM; ++ args->handle = handle; ++ ++ /* Executing the FWU ABI through the FF-A bus */ ++ ret = fwu_invoke_svc(args->function_id, svc_name, sizeof(*args), ++ sizeof(*resp), &resp->read_bytes); ++ if (ret) ++ return ret; ++ ++ if (resp->read_bytes > g_max_payload_size) { ++ log_err("%s: Bytes read > max_payload_size (%d , %llu)\n", ++ svc_name, resp->read_bytes, ++ g_max_payload_size); ++ return -EINVAL; ++ } ++ ++ fwu_buf_bytes_left = FWU_BUFFER_SIZE - sizeof(*resp); ++ ++ if (resp->read_bytes > fwu_buf_bytes_left) { ++ log_err("%s: Bytes read > shared buffer (%d , %d)\n", ++ svc_name, resp->read_bytes, fwu_buf_bytes_left); ++ return -EINVAL; ++ } ++ ++ if (resp->total_bytes > buffer_size) { ++ log_err("%s: Total bytes > dest buffer (%d , %d)\n", ++ svc_name, resp->total_bytes, buffer_size); ++ return -EINVAL; ++ } ++ ++ new_read_offset = resp->read_bytes + curr_read_offset; ++ ++ if (new_read_offset > buffer_size) { ++ log_err("%s: Bytes read > dest buffer (%d , %d)\n", ++ svc_name, new_read_offset, buffer_size); ++ return -EINVAL; ++ } ++ ++ memcpy(buffer + curr_read_offset, resp->payload, ++ resp->read_bytes); ++ ++ curr_read_offset = new_read_offset; ++ ++ if (curr_read_offset > resp->total_bytes) { ++ log_err("%s: Offset bypassed total bytes (%d , %d)\n", ++ svc_name, curr_read_offset, resp->total_bytes); ++ return -EINVAL; ++ } ++ ++ } while (curr_read_offset != resp->total_bytes); ++ ++ return ret; ++} ++ ++/** ++ * fwu_commit() - fwu_commit ABI ++ * @handle: The handle of the context being closed ++ * @acceptance_req: Acceptance status set by the Client ++ * @max_atomic_len: Hint, maximum time (in ns) that the Update Agent can execute ++ * continuously without yielding back to the Client state ++ * ++ * The call closes the image pointed to by handle. The image can be any entity ++ * opened with fwu_open(). ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++static int fwu_commit(u32 handle, u32 acceptance_req, u32 max_atomic_len) ++{ ++ struct fwu_commit_args *args = g_fwu_buf; ++ struct fwu_commit_resp *resp = g_fwu_buf; ++ char *svc_name = "FWU_COMMIT"; ++ int ret; ++ ++ /* Filling the arguments in the shared buffer */ ++ args->function_id = FWU_COMMIT; ++ args->handle = handle; ++ args->acceptance_req = acceptance_req; ++ args->max_atomic_len = max_atomic_len; ++ ++ /* Executing the FWU ABI through the FF-A bus */ ++ ret = fwu_invoke_svc(args->function_id, svc_name, ++ sizeof(*args), sizeof(*resp), NULL); ++ ++ while (resp->status == -FWU_RESUME) ++ ret = fwu_invoke_svc(args->function_id, svc_name, sizeof(*args), ++ sizeof(*resp), NULL); ++ ++ if (ret) ++ return ret; ++ ++ log_debug("%s: Progress %d/%d\n", svc_name, resp->progress, ++ resp->total_work); ++ ++ return 0; ++} ++ ++/** ++ * fwu_read_directory() - Read FWU directory information ++ * ++ * Read FWU directory information. ++ * For more details see fwu_image_directory structure. ++ * ++ * Return: ++ * ++ * 0 on success ++ */ ++static int fwu_read_directory(void) ++{ ++ int ret, close_ret; ++ u32 handle = 0; ++ efi_guid_t dir_guid = {0}; ++ char *uuid_str = FWU_DIRECTORY_CANONICAL_UUID; ++ ++ if (!uuid_str) { ++ log_err("FWU: No directory UUID provided\n"); ++ return -EINVAL; ++ } ++ ++ if (uuid_str_to_le_bin(uuid_str, dir_guid.b)) { ++ log_err("FWU: Invalid directory UUID\n"); ++ return -EINVAL; ++ } ++ ++ ret = fwu_open(&dir_guid, FWU_OP_TYPE_READ, &handle); ++ if (ret) { ++ log_err("FWU: Open image directory failed (err: %d)\n", ++ ret); ++ return ret; ++ } ++ ++ log_debug("FWU: Image directory handle (0x%x)\n", handle); ++ ++ ret = fwu_read_stream(handle, (u8 *)&g_fwu_cached_directory, ++ sizeof(g_fwu_cached_directory)); ++ if (ret) { ++ log_err("FWU: Read image directory failed (err: %d)\n", ++ ret); ++ goto close_handle; ++ } ++ ++ log_debug("FWU: directory_version (%d)\n", ++ g_fwu_cached_directory.directory_version); ++ ++ /* ++ * Note: The expected images in the directory are: ++ * - The images to be updated ++ * - The ESRT image (an image containing ESRT data) ++ * The ESRT image is not involved in the FWU. ++ * It should be removed from the count. ++ */ ++ g_fwu_cached_directory.num_images -= 1; ++ ++ if (g_fwu_cached_directory.num_images != ++ CONFIG_FWU_NUM_IMAGES_PER_BANK) { ++ log_err("FWU: Unexpected image count (%d , %d)\n", ++ g_fwu_cached_directory.num_images, ++ CONFIG_FWU_NUM_IMAGES_PER_BANK); ++ ret = -EINVAL; ++ goto close_handle; ++ } ++ ++ log_debug("FWU: images to be updated (%d)\n", ++ g_fwu_cached_directory.num_images); ++ log_debug("FWU: img_info_size (%d)\n", ++ g_fwu_cached_directory.img_info_size); ++ ++close_handle: ++ /* The Update Agent can execute for an unbounded time */ ++ close_ret = fwu_commit(handle, FWU_IMG_NOT_ACCEPTED, 0); ++ if (close_ret) ++ log_err("FWU: Close image directory handle failed (err: %d)\n", ++ close_ret); ++ ++ return ret; ++} + + /** + * fwu_discover_ts_sp_id() - Query the FWU partition ID +@@ -265,7 +738,112 @@ int fwu_agent_init(void) + if (ret) + return ret; + ++ ret = fwu_discover(); ++ if (ret) ++ goto failure; ++ + g_fwu_initialized = true; + + return 0; ++ ++failure: ++ fwu_shared_buf_reclaim(); ++ return ret; ++} ++ ++/** ++ * fwu_arm_psa_get_image_info() - Arm PSA implementation for GetImageInfo() ++ * ++ * Initialize the update agent in secure world if not initialized. ++ * Then, read the FWU directory information including the current ++ * images information. For more details refer to fwu_image_directory structure. ++ * ++ * Return: ++ * ++ * EFI_SUCCESS is returned on success. Otherwise, failure ++ */ ++efi_status_t fwu_arm_psa_get_image_info(efi_uintn_t *image_info_size, ++ struct efi_firmware_image_descriptor *image_info, ++ u32 *descriptor_version, ++ u8 *descriptor_count, ++ efi_uintn_t *descriptor_size, ++ u32 *package_version, ++ u16 **package_version_name) ++{ ++ int ret; ++ int required_image_info_size; ++ size_t image_info_desc_size = sizeof(*image_info); ++ ++ if (!g_fwu_initialized) { ++ ret = fwu_agent_init(); ++ if (ret) { ++ log_err("FWU: Update agent init failed, ret = %d\n", ++ ret); ++ return EFI_EXIT(EFI_DEVICE_ERROR); ++ } ++ } ++ ++ ret = fwu_read_directory(); ++ if (ret) ++ return EFI_NOT_READY; ++ ++ required_image_info_size = g_fwu_cached_directory.num_images * ++ image_info_desc_size; ++ ++ if (*image_info_size < required_image_info_size) { ++ *image_info_size = required_image_info_size; ++ return EFI_BUFFER_TOO_SMALL; ++ } ++ ++ *descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION; ++ *descriptor_count = g_fwu_cached_directory.num_images; ++ *descriptor_size = image_info_desc_size; ++ *package_version = PACKAGE_VERSION_NOT_SUP; /* Not supported */ ++ *package_version_name = NULL; /* Not supported */ ++ ++ for (int i = 0; i < g_fwu_cached_directory.num_images; i++) { ++ /* Only image indexes starting from 1 are supported */ ++ image_info[i].image_index = i + 1; ++ ++ /* Corresponding ESRT field: FwClass */ ++ guidcpy(&image_info[i].image_type_id, ++ &g_fwu_cached_directory.entries[i].image_guid); ++ ++ image_info[i].image_id = image_info[i].image_index; ++ image_info[i].image_id_name = NULL; /* Not supported */ ++ ++ /* Corresponding ESRT field: FwVersion */ ++ image_info[i].version = ++ g_fwu_cached_directory.entries[i].img_version; ++ ++ image_info[i].version_name = NULL; /* Not supported */ ++ image_info[i].size = ++ g_fwu_cached_directory.entries[i].img_max_size; ++ ++ image_info[i].attributes_supported = ++ IMAGE_ATTRIBUTE_IMAGE_UPDATABLE | ++ IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED; ++ image_info[i].attributes_setting = ++ IMAGE_ATTRIBUTE_IMAGE_UPDATABLE; ++ ++ /* Check if the capsule authentication is enabled */ ++ if (IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE)) ++ image_info[i].attributes_setting |= ++ IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED; ++ ++ /* Corresponding ESRT field: LowestSupportedFwVersion */ ++ image_info[i].lowest_supported_image_version = ++ g_fwu_cached_directory.entries[i].lowest_acceptable_version; ++ ++ /* Corresponding ESRT field: LastAttemptVersion (not supported) */ ++ image_info[i].last_attempt_version = LAST_ATTEMPT_NOT_SUP; ++ ++ /* Corresponding ESRT field: LastAttemptStatus (not supported) */ ++ image_info[i].last_attempt_status = LAST_ATTEMPT_NOT_SUP; ++ ++ image_info[i].hardware_instance = DEFAULT_HW_INSTANCE; ++ image_info[i].dependencies = NULL; /* Not supported */ ++ } ++ ++ return EFI_SUCCESS; + } +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0012-arm-corstone1000-fix-unrecognized-filesystem-type.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0012-arm-corstone1000-fix-unrecognized-filesystem-type.patch deleted file mode 100644 index 8055d88c..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0012-arm-corstone1000-fix-unrecognized-filesystem-type.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 2351cdc3787cd8b06579dcb1986fe80a57dd2d6e Mon Sep 17 00:00:00 2001 -From: Rui Miguel Silva -Date: Fri, 4 Mar 2022 15:56:09 +0000 -Subject: [PATCH] arm: corstone1000: fix unrecognized filesystem type - -Some usb sticks are not recognized by usb, just add a -delay before checking status. - -Signed-off-by: Rui Miguel Silva -Upstream-Status: Pending [Not submitted to upstream yet] ---- - common/usb_storage.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/common/usb_storage.c b/common/usb_storage.c -index ac64275773..1d2680c3cd 100644 ---- a/common/usb_storage.c -+++ b/common/usb_storage.c -@@ -785,6 +785,9 @@ static int usb_stor_BBB_transport(struct scsi_cmd *srb, struct us_data *us) - st: - retry = 0; - again: -+ if (srb->cmd[0] == SCSI_TST_U_RDY) -+ mdelay(100); -+ - debug("STATUS phase\n"); - result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE, - &actlen, USB_CNTL_TIMEOUT*5); diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0012-fwu_arm_psa-Add-staging-ABIs.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0012-fwu_arm_psa-Add-staging-ABIs.patch new file mode 100644 index 00000000..f29e8cc9 --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0012-fwu_arm_psa-Add-staging-ABIs.patch @@ -0,0 +1,722 @@ +From 04274ddd1e05d9aed6130633a4cf712e1e5aafbb Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Thu, 6 Feb 2025 11:37:33 +0000 +Subject: [PATCH 12/36] fwu_arm_psa: Add staging ABIs + +Implement the ABIs and logic for updating images + +The staging process defined by the Platform Security Firmware +Update for the A-profile Arm Architecture specification [1] is +executed through the staging ABIs. + +The capsule should contain at least 3 payloads (2 dummy payloads +to indicate the start and the end of the staging process. In addition, one +or multiple payloads to write in the storage device). + +The implemented ABIs are as follows: + +FWU_BEGIN_STAGING +FWU_END_STAGING +FWU_CANCEL_STAGING +FWU_WRITE_STREAM + +[1]: DEN0118, 1.0 A: https://developer.arm.com/documentation/den0118/latest/ + +Signed-off-by: Abdellatif El Khlifi +Signed-off-by: Davidson kumaresan +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20250702152528.1180414-1-abdellatif.elkhlifi@arm.com/] +--- + include/efi_api.h | 3 + + include/efi_loader.h | 5 + + include/fwu_arm_psa.h | 130 ++++++++++++ + lib/efi_loader/efi_capsule.c | 24 ++- + lib/fwu_updates/fwu_arm_psa.c | 363 ++++++++++++++++++++++++++++++++++ + 5 files changed, 523 insertions(+), 2 deletions(-) + +diff --git a/include/efi_api.h b/include/efi_api.h +index eb61eafa028..1465b98310d 100644 +--- a/include/efi_api.h ++++ b/include/efi_api.h +@@ -25,6 +25,9 @@ + */ + #define EFI_SPECIFICATION_VERSION (2 << 16 | 110) + ++#define EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_VERSION 0x00000001 ++#define EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_VERSION 0x00000003 ++ + /* Types and defines for EFI CreateEvent */ + enum efi_timer_delay { + EFI_TIMER_STOP = 0, +diff --git a/include/efi_loader.h b/include/efi_loader.h +index 1d75d97ebbc..1899639450c 100644 +--- a/include/efi_loader.h ++++ b/include/efi_loader.h +@@ -385,6 +385,11 @@ extern const efi_guid_t smbios3_guid; + extern const efi_guid_t efi_guid_text_input_protocol; + extern const efi_guid_t efi_guid_text_output_protocol; + ++/*The current processed capsule */ ++#if CONFIG_IS_ENABLED(FWU_ARM_PSA) ++extern struct efi_capsule_header *g_capsule_data; ++#endif ++ + /** + * struct efi_open_protocol_info_item - open protocol info item + * +diff --git a/include/fwu_arm_psa.h b/include/fwu_arm_psa.h +index ba294359b5e..a8f0ff93d51 100644 +--- a/include/fwu_arm_psa.h ++++ b/include/fwu_arm_psa.h +@@ -40,6 +40,21 @@ + /* The entries correspond to the payloads in the storage device and the fake ESRT image */ + #define FWU_DIRECTORY_IMAGE_ENTRIES_COUNT (CONFIG_FWU_NUM_IMAGES_PER_BANK + 1) + ++/* ++ * GUIDs for dummy payloads ++ * ++ * The GUIDs are generated with the UUIDv5 format. ++ * Namespace: 7b5c472e-5671-4fb7-a824-36a8e86f05c1 ++ * Names: DUMMY_START, DUMMY_END ++ */ ++#define FWU_DUMMY_START_IMAGE_GUID \ ++ EFI_GUID(0x6f784cbf, 0x7938, 0x5c23, 0x8d, 0x6e, \ ++ 0x24, 0xd2, 0xf1, 0x41, 0x0f, 0xa9) ++ ++#define FWU_DUMMY_END_IMAGE_GUID \ ++ EFI_GUID(0xb57e432b, 0xa250, 0x5c73, 0x93, 0xe3, \ ++ 0x90, 0x20, 0x5e, 0x64, 0xba, 0xba) ++ + #define TS_RPC_MEM_RETRIEVE (0xff0001) + #define TS_RPC_SERVICE_INFO_GET (0xff0003) + #define RPC_SUCCESS (0) +@@ -62,7 +77,11 @@ + + enum fwu_abis { + FWU_DISCOVER = 0, ++ FWU_BEGIN_STAGING = 16, ++ FWU_END_STAGING = 17, ++ FWU_CANCEL_STAGING = 18, + FWU_OPEN = 19, ++ FWU_WRITE_STREAM = 20, + FWU_READ_STREAM = 21, + FWU_COMMIT = 22, + /* To be updated when adding new FWU IDs */ +@@ -82,6 +101,14 @@ enum fwu_abi_errcode { + MAX_NUMBER_FWU_ERR + }; + ++/* Enum to classify the possible type of payloads */ ++typedef enum { ++ FWU_PAYLOAD_TYPE_REAL = 1, ++ FWU_PAYLOAD_TYPE_DUMMY_START, ++ FWU_PAYLOAD_TYPE_DUMMY_END, ++ FWU_PAYLOAD_TYPE_INVALID, ++} fwu_payload_type; ++ + /* Container structure and helper macros to map between an FF-A error and relevant error log */ + struct fwu_abi_errmap { + char *err_str[MAX_NUMBER_FWU_ERR]; +@@ -173,6 +200,64 @@ struct __packed fwu_read_stream_resp { + u8 payload[]; + }; + ++/* ++ * struct fwu_begin_staging_args - fwu_begin_staging ABI arguments ++ * @function_id: fwu_begin_staging service ID ++ * @reserved: Reserved, must be zero ++ * @vendor_flags: Vendor specific staging flags ++ * @partial_update_count: The number of elements in the update_guid ++array ++ * @update_guid: An array of image type GUIDs that the update Client will update ++ * during the Staging state ++ */ ++struct __packed fwu_begin_staging_args { ++ u32 function_id; ++ u32 reserved; ++ u32 vendor_flags; ++ u32 partial_update_count; ++ efi_guid_t update_guid[]; ++}; ++ ++/* ++ * struct fwu_begin_staging_resp - fwu_begin_staging ABI returns ++ * @status: The ABI return status ++ */ ++struct __packed fwu_begin_staging_resp { ++ int status; ++}; ++ ++/* ++ * struct fwu_end_staging_args - fwu_end_staging ABI arguments ++ * @function_id: fwu_end_staging service ID state ++ */ ++struct __packed fwu_end_staging_args { ++ u32 function_id; ++}; ++ ++/* ++ * struct fwu_end_staging_resp - fwu_end_staging ABI returns ++ * @status: The ABI return status ++ */ ++struct __packed fwu_end_staging_resp { ++ int status; ++}; ++ ++/* ++ * struct fwu_cancel_staging_args - fwu_cancel_staging ABI arguments ++ * @function_id: fwu_cancel_staging service ID state ++ */ ++struct __packed fwu_cancel_staging_args { ++ u32 function_id; ++}; ++ ++/* ++ * struct fwu_cancel_staging_resp - fwu_cancel_staging ABI returns ++ * @status: The ABI return status ++ */ ++struct __packed fwu_cancel_staging_resp { ++ int status; ++}; ++ + /* + * struct fwu_commit_args - fwu_commit ABI arguments + * @function_id: fwu_commit service ID +@@ -204,6 +289,28 @@ struct __packed fwu_commit_resp { + u32 total_work; + }; + ++/* ++ * struct fwu_write_stream_args - fwu_write_stream ABI arguments ++ * @function_id: fwu_write_stream service ID ++ * @handle: The handle of the context being written to ++ * @data_len: Size of the data present in the payload ++ * @payload: The data to be transferred ++ */ ++struct __packed fwu_write_stream_args { ++ u32 function_id; ++ u32 handle; ++ u32 data_len; ++ u8 payload[]; ++}; ++ ++/* ++ * struct fwu_write_stream_resp - fwu_write_stream ABI returns ++ * @status: The ABI return status ++ */ ++struct __packed fwu_write_stream_resp { ++ int status; ++}; ++ + /* + * FWU directory information structures + */ +@@ -261,4 +368,27 @@ efi_status_t fwu_arm_psa_get_image_info(efi_uintn_t *image_info_size, + u32 *package_version, + u16 **package_version_name); + ++/** ++ * fwu_update_image() - Update an image ++ * ++ * Perform staging. ++ * ++ * Return: ++ * ++ * 0 on success ++ */ ++int fwu_update_image(const void *image, u8 image_index, u32 image_size); ++ ++/** ++ * fwu_is_dummy_payload() - Identifies a dummy payload ++ * @image_index: The payload index ++ * ++ * Check whether the payload is dummy or not. ++ * ++ * Return: ++ * ++ * An enum value reflecting whether the payload is dummy or not. ++ */ ++fwu_payload_type fwu_get_payload_type(u32 image_index); ++ + #endif +diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c +index f8a4a7c6ef4..66efb24abf2 100644 +--- a/lib/efi_loader/efi_capsule.c ++++ b/lib/efi_loader/efi_capsule.c +@@ -14,6 +14,11 @@ + #include + #include + #include ++ ++#if CONFIG_IS_ENABLED(FWU_ARM_PSA) ++#include ++#endif ++ + #include + #include + #include +@@ -38,6 +43,10 @@ const efi_guid_t fwu_guid_os_request_fw_revert = + const efi_guid_t fwu_guid_os_request_fw_accept = + FWU_OS_REQUEST_FW_ACCEPT_GUID; + ++#if CONFIG_IS_ENABLED(FWU_ARM_PSA) ++ struct efi_capsule_header *g_capsule_data; ++#endif ++ + #define FW_ACCEPT_OS (u32)0x8000 + + #ifdef CONFIG_EFI_CAPSULE_ON_DISK +@@ -194,6 +203,12 @@ efi_fmp_find(efi_guid_t *image_type, u8 image_index, u64 instance, + continue; + fmp = fmp_handler->protocol_interface; + ++#if CONFIG_IS_ENABLED(FWU_ARM_PSA) ++ if (fwu_get_payload_type(image_index) != ++ FWU_PAYLOAD_TYPE_REAL) ++ return fmp; ++#endif ++ + /* get device's image info */ + info_size = 0; + image_info = NULL; +@@ -604,7 +619,7 @@ static efi_status_t efi_capsule_update_firmware( + capsule_size = capsule_data->capsule_image_size + - capsule_data->header_size; + +- if (capsule->version != 0x00000001) ++ if (capsule->version != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_VERSION) + return EFI_UNSUPPORTED; + + handles = NULL; +@@ -615,6 +630,10 @@ static efi_status_t efi_capsule_update_firmware( + if (ret != EFI_SUCCESS) + return EFI_UNSUPPORTED; + ++#if CONFIG_IS_ENABLED(FWU_ARM_PSA) ++ g_capsule_data = capsule_data; ++#endif ++ + /* Payload */ + for (item = capsule->embedded_driver_count; + item < capsule->embedded_driver_count +@@ -629,7 +648,8 @@ static efi_status_t efi_capsule_update_firmware( + + image = (void *)capsule + capsule->item_offset_list[item]; + +- if (image->version != 0x00000003) { ++ if (image->version != ++ EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_VERSION) { + ret = EFI_UNSUPPORTED; + goto out; + } +diff --git a/lib/fwu_updates/fwu_arm_psa.c b/lib/fwu_updates/fwu_arm_psa.c +index b42d9f90e1e..042bf7a0898 100644 +--- a/lib/fwu_updates/fwu_arm_psa.c ++++ b/lib/fwu_updates/fwu_arm_psa.c +@@ -25,6 +25,7 @@ static u8 g_fwu_version_major; + static u8 g_fwu_version_minor; + static bool g_fwu_initialized; + struct fwu_image_directory g_fwu_cached_directory; ++efi_guid_t g_update_guid[CONFIG_FWU_NUM_IMAGES_PER_BANK]; + + /* Error mapping declarations */ + +@@ -60,6 +61,18 @@ static struct fwu_abi_errmap err_msg_map[FWU_ERRMAP_COUNT] = { + "FWU_NO_PERMISSION: The image cannot be read from", + }, + }, ++ [FWU_ID_TO_ERRMAP_ID(FWU_WRITE_STREAM)] = { ++ { ++ [FWU_UNKNOWN] = ++ "FWU_UNKNOWN: Unrecognized handle", ++ [FWU_DENIED] = ++ "FWU_DENIED: The system is not in a Staging state", ++ [FWU_NO_PERMISSION] = ++ "FWU_NO_PERMISSION: The image cannot be written to", ++ [FWU_OUT_OF_BOUNDS] = ++ "FWU_OUT_OF_BOUNDS: less than data_len bytes available in the image", ++ }, ++ }, + [FWU_ID_TO_ERRMAP_ID(FWU_COMMIT)] = { + { + [FWU_UNKNOWN] = +@@ -72,6 +85,34 @@ static struct fwu_abi_errmap err_msg_map[FWU_ERRMAP_COUNT] = { + "FWU_RESUME: The Update Agent yielded", + }, + }, ++ [FWU_ID_TO_ERRMAP_ID(FWU_BEGIN_STAGING)] = { ++ { ++ [FWU_UNKNOWN] = ++ "FWU_UNKNOWN: One of more GUIDs in the update_guid field are unknown to the Update Agent", ++ [FWU_DENIED] = ++ "FWU_DENIED: The Firmware Store is in the Trial state or the platform did not boot correctly", ++ [FWU_BUSY] = ++ "FWU_BUSY: The Client is temporarily prevented from entering the Staging state", ++ }, ++ }, ++ [FWU_ID_TO_ERRMAP_ID(FWU_END_STAGING)] = { ++ { ++ [FWU_BUSY] = ++ "FWU_BUSY: There are open image handles", ++ [FWU_DENIED] = ++ "FWU_DENIED: The system is not in a Staging state", ++ [FWU_AUTH_FAIL] = ++ "FWU_AUTH_FAIL: At least one of the updated images fails to authenticate", ++ [FWU_NOT_AVAILABLE] = ++ "FWU_NOT_AVAILABLE: The Update Agent does not support partial updates", ++ }, ++ }, ++ [FWU_ID_TO_ERRMAP_ID(FWU_CANCEL_STAGING)] = { ++ { ++ [FWU_DENIED] = ++ "FWU_DENIED: The system is not in a Staging state", ++ }, ++ }, + }; + + /** +@@ -129,6 +170,111 @@ static int fwu_print_error_log(u32 fwu_id, int fwu_errno) + return 0; + } + ++/** ++ * fwu_get_payload_type() - Identifies the payload type ++ * @image_index: The payload index ++ * ++ * Identifies the FWU payload type based on the image index. ++ * ++ * Return: ++ * ++ * FWU_PAYLOAD_TYPE_REAL for a real payload ++ * FWU_PAYLOAD_TYPE_DUMMY_START for the start of a dummy payload ++ * FWU_PAYLOAD_TYPE_DUMMY_END for the end of a dummy payload ++ * FWU_PAYLOAD_TYPE_INVALID for an invalid image_index ++ * ++ */ ++fwu_payload_type fwu_get_payload_type(u32 image_index) ++{ ++ efi_guid_t *image_guid = NULL; ++ int i; ++ struct efi_fw_image *fw_array; ++ ++ fw_array = update_info.images; ++ for (i = 0; i < update_info.num_images; i++) { ++ if (fw_array[i].image_index == image_index) { ++ image_guid = &fw_array[i].image_type_id; ++ break; ++ } ++ } ++ ++ if (!image_guid) ++ return FWU_PAYLOAD_TYPE_INVALID; ++ ++ if (!guidcmp(image_guid, ++ &((efi_guid_t)FWU_DUMMY_START_IMAGE_GUID))) ++ return FWU_PAYLOAD_TYPE_DUMMY_START; ++ ++ if (!guidcmp(image_guid, ++ &((efi_guid_t)FWU_DUMMY_END_IMAGE_GUID))) ++ return FWU_PAYLOAD_TYPE_DUMMY_END; ++ ++ return FWU_PAYLOAD_TYPE_REAL; ++} ++ ++/** ++ * fwu_get_capsule_guids() - Detect the payloads GUIDs in the caspsule ++ * @partial_update_count: A pointer to the number of payloads to update ++ * @update_guid: A pointer to a GUIDs array for the payloads to update ++ * ++ * Parse the current capsule and detect the payloads GUIDs. ++ * ++ * Return: ++ * ++ * EFI_SUCCESS is returned on success. Otherwise, failure ++ */ ++static efi_status_t fwu_get_capsule_guids(u32 *partial_update_count, ++ efi_guid_t saved_guids[]) ++{ ++ struct efi_firmware_management_capsule_header *capsule; ++ struct efi_firmware_management_capsule_image_header *image; ++ int item; ++ size_t capsule_size; ++ efi_status_t ret = EFI_SUCCESS; ++ ++ if (!saved_guids || !partial_update_count) ++ return EFI_INVALID_PARAMETER; ++ ++ *partial_update_count = 0; ++ capsule = (void *)g_capsule_data + g_capsule_data->header_size; ++ capsule_size = g_capsule_data->capsule_image_size ++ - g_capsule_data->header_size; ++ ++ /* Payload */ ++ for (item = capsule->embedded_driver_count; ++ item < capsule->embedded_driver_count ++ + capsule->payload_item_count; item++) { ++ /* sanity check */ ++ if ((capsule->item_offset_list[item] + sizeof(*image) ++ >= capsule_size)) { ++ ret = EFI_INVALID_PARAMETER; ++ log_err("FWU: Insufficient data, err (0x%lx)\n", ret); ++ break; ++ } ++ ++ image = (void *)capsule + capsule->item_offset_list[item]; ++ ++ if (image->version != ++ EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_VERSION) { ++ ret = EFI_UNSUPPORTED; ++ log_err("FWU: Version check failed, err (0x%lx)\n", ++ ret); ++ break; ++ } ++ ++ if (fwu_get_payload_type(image->update_image_index) != ++ FWU_PAYLOAD_TYPE_REAL) ++ continue; ++ ++ guidcpy(&saved_guids[*partial_update_count], ++ &image->update_image_type_id); ++ ++ (*partial_update_count)++; ++ } ++ ++ return ret; ++} ++ + /** + * fwu_invoke_svc() - FWU service call request + * @svc_id: FWU ABI function ID +@@ -372,6 +518,92 @@ static int fwu_read_stream(u32 handle, u8 *buffer, u32 buffer_size) + return ret; + } + ++/** ++ * fwu_begin_staging() - fwu_begin_staging ABI ++ * ++ * This call indicates to the Update Agent that a new staging process ++ * will commence. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++static int fwu_begin_staging(void) ++{ ++ struct fwu_begin_staging_args *args = g_fwu_buf; ++ struct fwu_begin_staging_resp *resp = g_fwu_buf; ++ char *svc_name = "FWU_BEGIN_STAGING"; ++ efi_status_t ret; ++ ++ /* Filling the arguments in the shared buffer */ ++ args->function_id = FWU_BEGIN_STAGING; ++ ++ args->reserved = 0; ++ args->vendor_flags = 0; ++ ++ ret = fwu_get_capsule_guids(&args->partial_update_count, ++ args->update_guid); ++ if (ret) { ++ log_err("FWU: Failure to get the payloads GUIDs\n"); ++ return -ENODATA; ++ } ++ ++ log_info("FWU: Updating %d payload(s)\n", args->partial_update_count); ++ ++ /* Executing the FWU ABI through the FF-A bus */ ++ return fwu_invoke_svc(args->function_id, svc_name, ++ sizeof(*args), sizeof(*resp), NULL); ++} ++ ++/** ++ * fwu_end_staging() - fwu_end_staging ABI ++ * ++ * The Client informs the Update Agent that all the images, meant to be updated, ++ * have been transferred to the Update Agent and that the staging has ++ * terminated. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++static int fwu_end_staging(void) ++{ ++ struct fwu_end_staging_args *args = g_fwu_buf; ++ struct fwu_end_staging_resp *resp = g_fwu_buf; ++ char *svc_name = "FWU_END_STAGING"; ++ ++ /* Filling the arguments in the shared buffer */ ++ args->function_id = FWU_END_STAGING; ++ ++ /* Executing the FWU ABI through the FF-A bus */ ++ return fwu_invoke_svc(args->function_id, svc_name, ++ sizeof(*args), sizeof(*resp), NULL); ++} ++ ++/** ++ * fwu_cancel_staging() - fwu_cancel_staging ABI ++ * ++ * The Client cancels the staging procedure and the system transitions back to ++ * the Regular state. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++static int fwu_cancel_staging(void) ++{ ++ struct fwu_cancel_staging_args *args = g_fwu_buf; ++ struct fwu_cancel_staging_resp *resp = g_fwu_buf; ++ char *svc_name = "FWU_CANCEL_STAGING"; ++ ++ /* Filling the arguments in the shared buffer */ ++ args->function_id = FWU_CANCEL_STAGING; ++ ++ /* Executing the FWU ABI through the FF-A bus */ ++ return fwu_invoke_svc(args->function_id, svc_name, ++ sizeof(*args), sizeof(*resp), NULL); ++} ++ + /** + * fwu_commit() - fwu_commit ABI + * @handle: The handle of the context being closed +@@ -416,6 +648,137 @@ static int fwu_commit(u32 handle, u32 acceptance_req, u32 max_atomic_len) + return 0; + } + ++/** ++ * fwu_write_stream() - fwu_write_stream ABI ++ * @handle: The handle of the context being writen to ++ * @payload: The data to be transferred ++ * @payload_size: Size of the data present in the payload ++ * ++ * The call writes at most max_payload_size bytes to the Update Agent context ++ * pointed to by handle. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++static int fwu_write_stream(u32 handle, const u8 *payload, u32 payload_size) ++{ ++ int ret; ++ u32 write_size, max_write_size, curr_write_offset = 0; ++ u32 payload_bytes_left = payload_size, fwu_buf_bytes_left; ++ struct fwu_write_stream_args *args = g_fwu_buf; ++ struct fwu_write_stream_resp *resp = g_fwu_buf; ++ char *svc_name = "FWU_WRITE_STREAM"; ++ ++ if (!payload || !payload_size) ++ return -EINVAL; ++ ++ fwu_buf_bytes_left = FWU_BUFFER_SIZE - sizeof(*args); ++ ++ if (g_max_payload_size <= fwu_buf_bytes_left) ++ max_write_size = g_max_payload_size; ++ else ++ max_write_size = fwu_buf_bytes_left; ++ ++ while (curr_write_offset < payload_size) { ++ if (payload_bytes_left <= max_write_size) ++ write_size = payload_bytes_left; ++ else ++ write_size = max_write_size; ++ ++ /* Filling the arguments in the shared buffer */ ++ args->function_id = FWU_WRITE_STREAM; ++ args->handle = handle; ++ args->data_len = write_size; ++ memcpy(args->payload, payload + curr_write_offset, write_size); ++ ++ /* Executing the FWU ABI through the FF-A bus */ ++ ret = fwu_invoke_svc(args->function_id, svc_name, sizeof(*args), ++ sizeof(*resp), NULL); ++ if (ret) ++ return ret; ++ ++ curr_write_offset += write_size; ++ payload_bytes_left -= write_size; ++ ++ log_debug("%s: %d bytes written, remaining %d bytes\n", ++ svc_name, write_size, payload_bytes_left); ++ } ++ ++ return ret; ++} ++ ++/** ++ * fwu_update_image() - Update an image ++ * ++ * Perform staging with multiple payloads support. ++ * The capsule is expected to: ++ * - Start with a dummy payload to mark the start of the payloads sequence ++ * - One or more payloads to be written to the storage device ++ * - End with a dummy payload to mark the end of the payloads sequence ++ * ++ * The possible payloads in the capsule are described in the board file ++ * through struct efi_fw_image. This includes the dummy payloads. ++ * The dummy payloads image indexes must be >= CONFIG_FWU_NUM_IMAGES_PER_BANK ++ * The dummy payloads are not sent to the Secure world and are not written to ++ * the storage device. ++ * ++ * Return: ++ * ++ * 0 on success ++ */ ++int fwu_update_image(const void *image, u8 image_index, u32 image_size) ++{ ++ int ret; ++ u32 handle; ++ ++ if (!image) ++ return -EINVAL; ++ ++ /* Only image indexes starting from 1 are supported */ ++ if (!image_index || image_index > update_info.num_images) ++ return -EINVAL; ++ ++ if (fwu_get_payload_type(image_index) == ++ FWU_PAYLOAD_TYPE_DUMMY_START) { ++ return fwu_begin_staging(); ++ } ++ ++ if (fwu_get_payload_type(image_index) == ++ FWU_PAYLOAD_TYPE_DUMMY_END) { ++ ret = fwu_end_staging(); ++ if (ret) ++ goto cancel_staging; ++ return 0; ++ } ++ ++ ret = fwu_open(&g_fwu_cached_directory.entries[image_index - 1].image_guid, ++ FWU_OP_TYPE_WRITE, &handle); ++ if (ret) ++ goto cancel_staging; ++ ++ ret = fwu_write_stream(handle, image, image_size); ++ if (ret) ++ goto cancel_staging; ++ ++ /* ++ * The Update Agent can execute for an unbounded time. ++ * The image should be tried before being accepted. ++ * So, we put the acceptance request as 'not accepted'. ++ */ ++ ret = fwu_commit(handle, FWU_IMG_NOT_ACCEPTED, 0); ++ if (ret) ++ goto cancel_staging; ++ ++ log_debug("FWU: Image at index %d updated\n", image_index); ++ ++ return 0; ++ ++cancel_staging: ++ ++ return fwu_cancel_staging(); ++} ++ + /** + * fwu_read_directory() - Read FWU directory information + * +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0013-efi_loader-corstone1000-remove-guid-check-from-corst.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0013-efi_loader-corstone1000-remove-guid-check-from-corst.patch deleted file mode 100644 index fed13c6a..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0013-efi_loader-corstone1000-remove-guid-check-from-corst.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 42d0694494fdc549a989ca5a3924fdc82a4647c1 Mon Sep 17 00:00:00 2001 -From: Vishnu Banavath -Date: Sat, 11 Dec 2021 13:23:55 +0000 -Subject: [PATCH] efi_loader: corstone1000: remove guid check from corstone1000 - config option - -Use generic fmp guid and no separte check is required for -CORSTONE1000 target. - -Signed-off-by: Vishnu Banavath -Signed-off-by: Rui Miguel Silva -Upstream-Status: Pending [Not submitted to upstream yet] ---- - lib/efi_loader/efi_capsule.c | 16 +--------------- - 1 file changed, 1 insertion(+), 15 deletions(-) - -diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c -index ea084e4ed2..5314f529b4 100644 ---- a/lib/efi_loader/efi_capsule.c -+++ b/lib/efi_loader/efi_capsule.c -@@ -852,12 +852,6 @@ efi_status_t __efi_runtime EFIAPI efi_update_capsule( - i, &capsule->capsule_guid); - - #if CONFIG_IS_ENABLED(TARGET_CORSTONE1000) -- if (guidcmp(&corstone1000_capsule_guid, &capsule->capsule_guid)) { -- ret = EFI_INVALID_PARAMETER; -- log_err("Corstone1000: Invalid capsule GUID\n"); -- goto out; -- } -- - if (efi_size_in_pages(capsule->capsule_image_size) > - CORSTONE1000_CAPSULE_BUFFER_SIZE) { - log_err("Corstone1000: Capsule data size exceeds the shared buffer size\n"); -@@ -883,15 +877,7 @@ efi_status_t __efi_runtime EFIAPI efi_update_capsule( - goto out; - #endif - -- if (!guidcmp(&capsule->capsule_guid, -- &efi_guid_firmware_management_capsule_id)) { -- ret = efi_capsule_update_firmware(capsule); -- } else { -- log_err("Unsupported capsule type: %pUs\n", -- &capsule->capsule_guid); -- ret = EFI_UNSUPPORTED; -- } -- -+ ret = efi_capsule_update_firmware(capsule); - if (ret != EFI_SUCCESS) - goto out; - } diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0013-efi_loader-fwu_arm_psa-Add-set_image-and-get_image_i.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0013-efi_loader-fwu_arm_psa-Add-set_image-and-get_image_i.patch new file mode 100644 index 00000000..bb05a5cf --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0013-efi_loader-fwu_arm_psa-Add-set_image-and-get_image_i.patch @@ -0,0 +1,111 @@ +From c4cf3e3a2869502c9ffadaa2121ab5cd05f3712f Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Wed, 18 Dec 2024 15:14:24 +0000 +Subject: [PATCH 13/36] efi_loader: fwu_arm_psa: Add set_image and + get_image_info support + +Implement set_image and get_image_info through RAW functions + +The implementation is done using efi_firmware_raw_set_image() +and efi_firmware_get_image_info() + +Signed-off-by: Abdellatif El Khlifi +Signed-off-by: Davidson kumaresan +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20250702152528.1180414-1-abdellatif.elkhlifi@arm.com/] +--- + lib/efi_loader/efi_firmware.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c +index 5a754c9cd03..de2357acbd7 100644 +--- a/lib/efi_loader/efi_firmware.c ++++ b/lib/efi_loader/efi_firmware.c +@@ -4,6 +4,12 @@ + * + * Copyright (c) 2020 Linaro Limited + * Author: AKASHI Takahiro ++ * ++ * Copyright 2025 Arm Limited and/or its affiliates ++ * ++ * Authors: ++ * Abdellatif El Khlifi ++ * Davidson kumaresan + */ + + #define LOG_CATEGORY LOGC_EFI +@@ -13,6 +19,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -194,6 +201,7 @@ static void efi_firmware_get_lsv_from_dtb(u8 image_index, + } + } + ++#if !CONFIG_IS_ENABLED(FWU_ARM_PSA) + /** + * efi_firmware_fill_version_info - fill the version information + * @image_info: Image information +@@ -375,6 +383,7 @@ static efi_status_t efi_fill_image_desc_array( + + return EFI_SUCCESS; + } ++#endif + + /** + * efi_firmware_capsule_authenticate - authenticate the capsule if enabled +@@ -605,10 +614,17 @@ efi_status_t EFIAPI efi_firmware_get_image_info( + !descriptor_size || !package_version || !package_version_name)) + return EFI_EXIT(EFI_INVALID_PARAMETER); + ++#if CONFIG_IS_ENABLED(FWU_ARM_PSA) ++ ret = fwu_arm_psa_get_image_info(image_info_size, image_info, ++ descriptor_version, descriptor_count, ++ descriptor_size, ++ package_version, package_version_name); ++#else + ret = efi_fill_image_desc_array(image_info_size, image_info, + descriptor_version, descriptor_count, + descriptor_size, package_version, + package_version_name); ++#endif + + return EFI_EXIT(ret); + } +@@ -713,8 +729,10 @@ efi_status_t EFIAPI efi_firmware_raw_set_image( + efi_status_t (*progress)(efi_uintn_t completion), + u16 **abort_reason) + { ++#if !CONFIG_IS_ENABLED(FWU_ARM_PSA) + int ret; + u8 dfu_alt_num; ++#endif + efi_status_t status; + struct fmp_state state = { 0 }; + +@@ -729,6 +747,10 @@ efi_status_t EFIAPI efi_firmware_raw_set_image( + if (status != EFI_SUCCESS) + return EFI_EXIT(status); + ++#if CONFIG_IS_ENABLED(FWU_ARM_PSA) ++ if (fwu_update_image(image, image_index, image_size)) ++ return EFI_EXIT(EFI_DEVICE_ERROR); ++#else + /* + * dfu_alt_num is assigned from 0 while image_index starts from 1. + * dfu_alt_num is calculated by (image_index - 1) when multi bank update +@@ -751,6 +773,8 @@ efi_status_t EFIAPI efi_firmware_raw_set_image( + NULL, NULL)) + return EFI_EXIT(EFI_DEVICE_ERROR); + ++#endif ++ + efi_firmware_set_fmp_state_var(&state, image_index); + + return EFI_EXIT(EFI_SUCCESS); +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0014-efi_loader-fwu_arm_psa-Keep-the-FMP-payload-header.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0014-efi_loader-fwu_arm_psa-Keep-the-FMP-payload-header.patch new file mode 100644 index 00000000..1b7a8297 --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0014-efi_loader-fwu_arm_psa-Keep-the-FMP-payload-header.patch @@ -0,0 +1,34 @@ +From e2b35f2520ba80c55c96b70bcc2a927cb0d20c75 Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Fri, 24 Jan 2025 15:13:39 +0000 +Subject: [PATCH 14/36] efi_loader: fwu_arm_psa: Keep the FMP payload header + +Allow sending the payload with its FMP header + +The Secure world needs the data provided by the payload +FMP header. So, let's keep it in case of FWU_ARM_PSA. + +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20250702152528.1180414-1-abdellatif.elkhlifi@arm.com/] +--- + lib/efi_loader/efi_firmware.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c +index de2357acbd7..d1ec7b9427b 100644 +--- a/lib/efi_loader/efi_firmware.c ++++ b/lib/efi_loader/efi_firmware.c +@@ -523,8 +523,10 @@ static void efi_firmware_get_fw_version(const void **p_image, + /* FMP header is inserted above the capsule payload */ + state->fw_version = header->fw_version; + ++#if !CONFIG_IS_ENABLED(FWU_ARM_PSA) + *p_image += header->header_size; + *p_image_size -= header->header_size; ++#endif + } + } + +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0014-efi_loader-populate-ESRT-table-if-EFI_ESRT-config-op.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0014-efi_loader-populate-ESRT-table-if-EFI_ESRT-config-op.patch deleted file mode 100644 index 31c19e14..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0014-efi_loader-populate-ESRT-table-if-EFI_ESRT-config-op.patch +++ /dev/null @@ -1,34 +0,0 @@ -From a368e6a94382bb88f3603107d14ff3af0fb4eaa2 Mon Sep 17 00:00:00 2001 -From: Vishnu Banavath -Date: Fri, 17 Dec 2021 19:49:02 +0000 -Subject: [PATCH] efi_loader: populate ESRT table if EFI_ESRT config option is - set - -This change is to call efi_esrt_populate function if CONFIG_EFI_ESRT -is set. This will populte esrt table with firmware image info - -Signed-off-by: Vishnu Banavath -Signed-off-by: Rui Miguel Silva -Upstream-Status: Pending [Not submitted to upstream yet] ---- - lib/efi_loader/efi_capsule.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c -index 5314f529b4..6a06605ad9 100644 ---- a/lib/efi_loader/efi_capsule.c -+++ b/lib/efi_loader/efi_capsule.c -@@ -874,6 +874,13 @@ efi_status_t __efi_runtime EFIAPI efi_update_capsule( - ret = EFI_SUCCESS; - } - -+ if (IS_ENABLED(CONFIG_EFI_ESRT)) { -+ /* Rebuild the ESRT to reflect any updated FW images. */ -+ ret = efi_esrt_populate(); -+ if (ret != EFI_SUCCESS) -+ log_warning("EFI Capsule: failed to update ESRT\n"); -+ } -+ - goto out; - #endif - diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0015-efi_firmware-add-get_image_info-for-corstone1000.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0015-efi_firmware-add-get_image_info-for-corstone1000.patch deleted file mode 100644 index c7ecfe89..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0015-efi_firmware-add-get_image_info-for-corstone1000.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 972ed0e27cce6d2822055f31e336213043bcb1f3 Mon Sep 17 00:00:00 2001 -From: Vishnu Banavath -Date: Fri, 17 Dec 2021 19:50:25 +0000 -Subject: [PATCH] efi_firmware: add get_image_info for corstone1000 - -This change is to populate get_image_info which eventually -will be populated in ESRT table - -Signed-off-by: Vishnu Banavath -Signed-off-by: Rui Miguel Silva -Upstream-Status: Pending [Not submitted to upstream yet] ---- - lib/efi_loader/efi_firmware.c | 72 ++++++++++++++++++++++++++++++++++- - 1 file changed, 71 insertions(+), 1 deletion(-) - -diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c -index 93e2b01c07..0a38a96351 100644 ---- a/lib/efi_loader/efi_firmware.c -+++ b/lib/efi_loader/efi_firmware.c -@@ -18,11 +18,69 @@ - - #define FMP_PAYLOAD_HDR_SIGNATURE SIGNATURE_32('M', 'S', 'S', '1') - -+#if CONFIG_IS_ENABLED(TARGET_CORSTONE1000) -+#define EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID \ -+ EFI_GUID(0xe2bb9c06, 0x70e9, 0x4b14, 0x97, 0xa3, \ -+ 0x5a, 0x79, 0x13, 0x17, 0x6e, 0x3f) -+ -+ const efi_guid_t efi_firmware_image_type_uboot_raw = -+ EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID; -+ -+static efi_status_t efi_corstone1000_img_info_get ( -+ efi_uintn_t *image_info_size, -+ struct efi_firmware_image_descriptor *image_info, -+ u32 *descriptor_version, -+ u8 *descriptor_count, -+ efi_uintn_t *descriptor_size, -+ u32 *package_version, -+ u16 **package_version_name, -+ const efi_guid_t *image_type) -+{ -+ int i = 0; -+ -+ *image_info_size = sizeof(*image_info); -+ *descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION; -+ *descriptor_count = 1;//dfu_num; -+ *descriptor_size = sizeof(*image_info); -+ if (package_version) -+ *package_version = 0xffffffff; /* not supported */ -+ if(package_version_name) -+ *package_version_name = NULL; /* not supported */ -+ -+ if(image_info == NULL) { -+ log_warning("image_info is null\n"); -+ return EFI_BUFFER_TOO_SMALL; -+ } -+ -+ image_info[i].image_index = i; -+ image_info[i].image_type_id = *image_type; -+ image_info[i].image_id = 0; -+ image_info[i].image_id_name = "wic"; -+ image_info[i].version = 1; -+ image_info[i].version_name = NULL; -+ image_info[i].size = 0x1000; -+ image_info[i].attributes_supported = IMAGE_ATTRIBUTE_IMAGE_UPDATABLE | -+ IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED; -+ image_info[i].attributes_setting = IMAGE_ATTRIBUTE_IMAGE_UPDATABLE; -+ /* Check if the capsule authentication is enabled */ -+ if (IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE)) -+ image_info[0].attributes_setting |= -+ IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED; -+ image_info[i].lowest_supported_image_version = 0; -+ image_info[i].last_attempt_version = 0; -+ image_info[i].last_attempt_status = LAST_ATTEMPT_STATUS_SUCCESS; -+ image_info[i].hardware_instance = 1; -+ image_info[i].dependencies = NULL; -+ -+ return EFI_SUCCESS; -+} -+#endif -+ - /** - * struct fmp_payload_header - EDK2 header for the FMP payload - * - * This structure describes the header which is preprended to the -- * FMP payload by the edk2 capsule generation scripts. -+ * FMP payload by the edk1 capsule generation scripts. - * - * @signature: Header signature used to identify the header - * @header_size: Size of the structure -@@ -286,10 +344,18 @@ efi_status_t EFIAPI efi_firmware_get_image_info( - !descriptor_size || !package_version || !package_version_name)) - return EFI_EXIT(EFI_INVALID_PARAMETER); - -+#if CONFIG_IS_ENABLED(TARGET_CORSTONE1000) -+ ret = efi_corstone1000_img_info_get(image_info_size, image_info, -+ descriptor_version, descriptor_count, -+ descriptor_size, -+ package_version, package_version_name, -+ &efi_firmware_image_type_uboot_raw); -+#else - ret = efi_fill_image_desc_array(image_info_size, image_info, - descriptor_version, descriptor_count, - descriptor_size, package_version, - package_version_name); -+#endif - - return EFI_EXIT(ret); - } -@@ -415,6 +481,10 @@ efi_status_t EFIAPI efi_firmware_raw_set_image( - } - } - -+#if CONFIG_IS_ENABLED(TARGET_CORSTONE1000) -+ return EFI_EXIT(EFI_SUCCESS); -+#endif -+ - if (dfu_write_by_alt(image_index - 1, (void *)image, image_size, - NULL, NULL)) - return EFI_EXIT(EFI_DEVICE_ERROR); diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0015-efi_loader-fwu_arm_psa-Skip-accepting-the-payload-af.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0015-efi_loader-fwu_arm_psa-Skip-accepting-the-payload-af.patch new file mode 100644 index 00000000..ee7cab83 --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0015-efi_loader-fwu_arm_psa-Skip-accepting-the-payload-af.patch @@ -0,0 +1,46 @@ +From 5b6c64f927e21bd9b77754e16e1976cab63831ff Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Fri, 24 Jan 2025 15:26:57 +0000 +Subject: [PATCH 15/36] efi_loader: fwu_arm_psa: Skip accepting the payload + after set_image() + +Do not update the acceptance metadata bit after updating an image + +The update agent (secure world) is responsible of setting the acceptance +bit in the metadata. + +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20250702152528.1180414-1-abdellatif.elkhlifi@arm.com/] +--- + lib/efi_loader/efi_capsule.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c +index 66efb24abf2..9221cafb844 100644 +--- a/lib/efi_loader/efi_capsule.c ++++ b/lib/efi_loader/efi_capsule.c +@@ -4,6 +4,11 @@ + * + * Copyright (c) 2018 Linaro Limited + * Author: AKASHI Takahiro ++ * ++ * Copyright 2025 Arm Limited and/or its affiliates ++ * ++ * Author: ++ * Abdellatif El Khlifi + */ + + #define LOG_CATEGORY LOGC_EFI +@@ -701,7 +706,8 @@ static efi_status_t efi_capsule_update_firmware( + goto out; + } + +- if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) { ++ if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE) && ++ !IS_ENABLED(CONFIG_FWU_ARM_PSA)) { + image_type_id = &image->update_image_type_id; + if (!fw_accept_os) { + /* +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0016-efi_loader-fix-null-pointer-exception-with-get_image.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0016-efi_loader-fix-null-pointer-exception-with-get_image.patch deleted file mode 100644 index 694d8534..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0016-efi_loader-fix-null-pointer-exception-with-get_image.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 75ace03c24d92a206957a1a2392eab3c892cf960 Mon Sep 17 00:00:00 2001 -From: Vishnu Banavath -Date: Fri, 14 Jan 2022 15:24:18 +0000 -Subject: [PATCH] efi_loader: fix null pointer exception with get_image_info - -get_img_info API implemented for corstone1000 target does not -check the input attributes and as a result uboot crash's with -null pointer access. This change is to fix the null pointer -exception. - -Signed-off-by: Vishnu Banavath -Signed-off-by: Rui Miguel Silva -Upstream-Status: Pending [Not submitted to upstream yet] ---- - lib/efi_loader/efi_firmware.c | 19 +++++++++++-------- - 1 file changed, 11 insertions(+), 8 deletions(-) - -diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c -index 0a38a96351..c883e2ff0a 100644 ---- a/lib/efi_loader/efi_firmware.c -+++ b/lib/efi_loader/efi_firmware.c -@@ -39,26 +39,29 @@ static efi_status_t efi_corstone1000_img_info_get ( - int i = 0; - - *image_info_size = sizeof(*image_info); -- *descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION; -- *descriptor_count = 1;//dfu_num; -- *descriptor_size = sizeof(*image_info); -+ if(descriptor_version) -+ *descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION; -+ if(descriptor_count) -+ *descriptor_count = 1; -+ if(descriptor_size) -+ *descriptor_size = sizeof(*image_info); - if (package_version) - *package_version = 0xffffffff; /* not supported */ - if(package_version_name) - *package_version_name = NULL; /* not supported */ - - if(image_info == NULL) { -- log_warning("image_info is null\n"); -+ log_debug("image_info is null\n"); - return EFI_BUFFER_TOO_SMALL; - } - -- image_info[i].image_index = i; -+ image_info[i].image_index = 1; - image_info[i].image_type_id = *image_type; - image_info[i].image_id = 0; -- image_info[i].image_id_name = "wic"; -- image_info[i].version = 1; -+ image_info[i].image_id_name = L"wic image"; -+ image_info[i].version = 0; - image_info[i].version_name = NULL; -- image_info[i].size = 0x1000; -+ image_info[i].size = 0; - image_info[i].attributes_supported = IMAGE_ATTRIBUTE_IMAGE_UPDATABLE | - IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED; - image_info[i].attributes_setting = IMAGE_ATTRIBUTE_IMAGE_UPDATABLE; diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0016-efi_loader-fwu-fwu_arm_psa-Disable-trial-state-handl.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0016-efi_loader-fwu-fwu_arm_psa-Disable-trial-state-handl.patch new file mode 100644 index 00000000..26263f33 --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0016-efi_loader-fwu-fwu_arm_psa-Disable-trial-state-handl.patch @@ -0,0 +1,71 @@ +From 9b381a19ec3437d4bdc3fd922084a39331f29a3d Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Thu, 20 Mar 2025 15:05:08 +0000 +Subject: [PATCH 16/36] efi_loader: fwu: fwu_arm_psa: Disable trial state + handling + +No need for trial state handling in U-Boot for FWU Arm PSA + +In FWU Arm PSA mode, trial state is handled by Secure world. + +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20250702152528.1180414-1-abdellatif.elkhlifi@arm.com/] +--- + lib/efi_loader/efi_capsule.c | 7 +++++-- + lib/fwu_updates/fwu.c | 8 +++++++- + 2 files changed, 12 insertions(+), 3 deletions(-) + +diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c +index 9221cafb844..e01f2a5f8a8 100644 +--- a/lib/efi_loader/efi_capsule.c ++++ b/lib/efi_loader/efi_capsule.c +@@ -586,7 +586,9 @@ static efi_status_t efi_capsule_update_firmware( + if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) { + if (fwu_empty_capsule(capsule_data)) { + if (fwu_empty_capsule_checks_pass()) { +- return fwu_empty_capsule_process(capsule_data); ++ return !IS_ENABLED(CONFIG_FWU_ARM_PSA) ? ++ fwu_empty_capsule_process(capsule_data) : ++ 0; + } else { + log_err("FWU empty capsule checks failed. Cannot start update\n"); + return EFI_INVALID_PARAMETER; +@@ -1399,7 +1401,8 @@ efi_status_t efi_launch_capsules(void) + + efi_capsule_scan_done(); + +- if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) { ++ if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE) && ++ !IS_ENABLED(CONFIG_FWU_ARM_PSA)) { + if (capsule_update == true && update_status == true) { + ret = fwu_post_update_process(fw_accept_os); + } else if (capsule_update == true && update_status == false) { +diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c +index 7f085a0211f..9e6511b4da0 100644 +--- a/lib/fwu_updates/fwu.c ++++ b/lib/fwu_updates/fwu.c +@@ -340,6 +340,11 @@ int fwu_get_mdata(struct fwu_mdata *mdata) + if (parts_ok[i]) + continue; + ++ if (IS_ENABLED(CONFIG_FWU_ARM_PSA)) { ++ log_err("FWU metadata copy %d invalid\n", i); ++ return -ENOTSYNC; ++ } ++ + memcpy(parts_mdata[i], parts_mdata[1 - i], mdata_size); + err = fwu_sync_mdata(parts_mdata[i], i ? SECONDARY_PART : PRIMARY_PART); + if (err) { +@@ -765,7 +770,8 @@ static int fwu_boottime_checks(void) + + in_trial = in_trial_state(); + +- ret = in_trial ? fwu_trial_count_update() : trial_counter_update(NULL); ++ ret = (in_trial && !IS_ENABLED(CONFIG_FWU_ARM_PSA)) ? ++ fwu_trial_count_update() : trial_counter_update(NULL); + + if (!ret) + boottime_check = 1; +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0017-arm-corstone1000-add-mmc-for-fvp.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0017-arm-corstone1000-add-mmc-for-fvp.patch deleted file mode 100644 index 1326e7c9..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0017-arm-corstone1000-add-mmc-for-fvp.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 7dec0707573062aba859e4cd3be073c24b112efa Mon Sep 17 00:00:00 2001 -From: Rui Miguel Silva -Date: Mon, 17 Jul 2023 16:50:53 +0100 -Subject: [PATCH] arm:corstone1000: add mmc for fvp - -Enable support mmc/sdcard for the corstone1000 FVP. - -Signed-off-by: Vishnu Banavath -Signed-off-by: Rui Miguel Silva -Upstream-Status: Pending [Not submitted to upstream yet] ---- - board/armltd/corstone1000/corstone1000.c | 28 +++++++++++++++++++----- - configs/corstone1000_defconfig | 9 ++++++-- - include/configs/corstone1000.h | 4 +++- - 3 files changed, 32 insertions(+), 9 deletions(-) - -diff --git a/board/armltd/corstone1000/corstone1000.c b/board/armltd/corstone1000/corstone1000.c -index c840290885..ecfd8366df 100644 ---- a/board/armltd/corstone1000/corstone1000.c -+++ b/board/armltd/corstone1000/corstone1000.c -@@ -39,19 +39,35 @@ static struct mm_region corstone1000_mem_map[] = { - }, { - /* USB */ - .virt = 0x40200000UL, -- .phys = 0x40200000UL, -+ .phys = 0x40200000UL, -+ .size = 0x00100000UL, -+ .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | -+ PTE_BLOCK_NON_SHARE | -+ PTE_BLOCK_PXN | PTE_BLOCK_UXN -+ }, { -+ /* MMC0 */ -+ .virt = 0x40300000UL, -+ .phys = 0x40300000UL, - .size = 0x00100000UL, - .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | -- PTE_BLOCK_NON_SHARE | -- PTE_BLOCK_PXN | PTE_BLOCK_UXN -+ PTE_BLOCK_NON_SHARE | -+ PTE_BLOCK_PXN | PTE_BLOCK_UXN - }, { - /* ethernet */ - .virt = 0x40100000UL, -- .phys = 0x40100000UL, -+ .phys = 0x40100000UL, -+ .size = 0x00100000UL, -+ .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | -+ PTE_BLOCK_NON_SHARE | -+ PTE_BLOCK_PXN | PTE_BLOCK_UXN -+ }, { -+ /* MMC1 */ -+ .virt = 0x50000000UL, -+ .phys = 0x50000000UL, - .size = 0x00100000UL, - .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | -- PTE_BLOCK_NON_SHARE | -- PTE_BLOCK_PXN | PTE_BLOCK_UXN -+ PTE_BLOCK_NON_SHARE | -+ PTE_BLOCK_PXN | PTE_BLOCK_UXN - }, { - /* OCVM */ - .virt = 0x80000000UL, -diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig -index 40ba415ecb..76158fc37d 100644 ---- a/configs/corstone1000_defconfig -+++ b/configs/corstone1000_defconfig -@@ -40,8 +40,13 @@ CONFIG_VERSION_VARIABLE=y - CONFIG_NET_RANDOM_ETHADDR=y - CONFIG_REGMAP=y - CONFIG_MISC=y --# CONFIG_MMC is not set --CONFIG_NVMXIP_QSPI=y -+CONFIG_CLK=y -+CONFIG_CMD_MMC=y -+CONFIG_DM_MMC=y -+CONFIG_ARM_PL180_MMCI=y -+CONFIG_MMC_SDHCI_ADMA_HELPERS=y -+CONFIG_MMC_WRITE=y -+CONFIG_DM_GPIO=y - CONFIG_PHYLIB=y - CONFIG_PHY_SMSC=y - CONFIG_SMC911X=y -diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h -index 8927b09499..1466507f80 100644 ---- a/include/configs/corstone1000.h -+++ b/include/configs/corstone1000.h -@@ -49,7 +49,9 @@ - #define CFG_SYS_SDRAM_BASE PHYS_SDRAM_1 - - #define BOOT_TARGET_DEVICES(func) \ -- func(USB, usb, 0) -+ func(USB, usb, 0) \ -+ func(MMC, mmc, 0) \ -+ func(MMC, mmc, 1) - - #include - diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0017-fwu_arm_psa-Add-FWU-acceptance-mechanism.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0017-fwu_arm_psa-Add-FWU-acceptance-mechanism.patch new file mode 100644 index 00000000..9fdcd1a6 --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0017-fwu_arm_psa-Add-FWU-acceptance-mechanism.patch @@ -0,0 +1,310 @@ +From c7df14add690e18645fdfea2c7e8ee5f2b8239c1 Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Thu, 20 Mar 2025 15:09:27 +0000 +Subject: [PATCH 17/36] fwu_arm_psa: Add FWU acceptance mechanism + +Accept the FWU at ExitBootServices() + +Provide the FWU_ACCEPT_IMAGE ABI and setup an event triggered +on ExitBootServices(). +This mechanism notifies Secure world that the system booted +successfully by accepting the images in trial state. + +Also, add FWU_ARM_PSA_ACCEPT_IMAGES config +to allow platforms to switch off image acceptance +in ExitBootServices(). + +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20250702152528.1180414-1-abdellatif.elkhlifi@arm.com/] +--- + include/fwu_arm_psa.h | 22 +++- + lib/fwu_updates/Kconfig | 8 ++ + lib/fwu_updates/fwu_arm_psa.c | 183 ++++++++++++++++++++++++++++++++++ + 3 files changed, 212 insertions(+), 1 deletion(-) + +diff --git a/include/fwu_arm_psa.h b/include/fwu_arm_psa.h +index a8f0ff93d51..451d8b614e3 100644 +--- a/include/fwu_arm_psa.h ++++ b/include/fwu_arm_psa.h +@@ -84,9 +84,10 @@ enum fwu_abis { + FWU_WRITE_STREAM = 20, + FWU_READ_STREAM = 21, + FWU_COMMIT = 22, ++ FWU_ACCEPT_IMAGE = 23, + /* To be updated when adding new FWU IDs */ + FWU_FIRST_ID = FWU_DISCOVER, /* Lowest number ID */ +- FWU_LAST_ID = FWU_COMMIT, /* Highest number ID */ ++ FWU_LAST_ID = FWU_ACCEPT_IMAGE, /* Highest number ID */ + }; + + enum fwu_abi_errcode { +@@ -311,6 +312,25 @@ struct __packed fwu_write_stream_resp { + int status; + }; + ++/* ++ * struct fwu_accept_image_args - fwu_accept_image ABI arguments ++ * @function_id: fwu_accept_image service ID ++ * @image_type_guid: GUID of the image to be accepted ++ */ ++struct __packed fwu_accept_image_args { ++ u32 function_id; ++ u32 reserved; ++ efi_guid_t image_type_guid; ++}; ++ ++/* ++ * struct fwu_accept_image_resp - fwu_accept_image ABI returns ++ * @status: The ABI return status ++ */ ++struct __packed fwu_accept_image_resp { ++ int status; ++}; ++ + /* + * FWU directory information structures + */ +diff --git a/lib/fwu_updates/Kconfig b/lib/fwu_updates/Kconfig +index cdc96109f0a..958e54dec37 100644 +--- a/lib/fwu_updates/Kconfig ++++ b/lib/fwu_updates/Kconfig +@@ -57,6 +57,14 @@ config FWU_ARM_PSA + driver that supports the Arm PSA firmware update specification as + mentioned in https://developer.arm.com/documentation/den0118/a/ + ++config FWU_ARM_PSA_ACCEPT_IMAGES ++ bool "Accept images at EFI ExitBootServices() level" ++ depends on FWU_ARM_PSA ++ default y ++ help ++ Select this option if reaching ExitBootServices() level means the boot succeeded ++ This option will add a callback at ExitBootServices() that accepts all the images. ++ + config FWU_BUFFER_PAGES + int "Number of 4KB pages in the FWU shared buffer" + depends on FWU_ARM_PSA +diff --git a/lib/fwu_updates/fwu_arm_psa.c b/lib/fwu_updates/fwu_arm_psa.c +index 042bf7a0898..40746eee6ce 100644 +--- a/lib/fwu_updates/fwu_arm_psa.c ++++ b/lib/fwu_updates/fwu_arm_psa.c +@@ -8,6 +8,7 @@ + */ + #include + #include ++#include + #include + #include + #include +@@ -113,6 +114,14 @@ static struct fwu_abi_errmap err_msg_map[FWU_ERRMAP_COUNT] = { + "FWU_DENIED: The system is not in a Staging state", + }, + }, ++ [FWU_ID_TO_ERRMAP_ID(FWU_ACCEPT_IMAGE)] = { ++ { ++ [FWU_UNKNOWN] = ++ "FWU_UNKNOWN: Image with type=image_type_guid is not managed by the Update Agent", ++ [FWU_DENIED] = ++ "FWU_DENIED: The system has not booted with the active bank, or the image cannot be accepted before being activated", ++ }, ++ }, + }; + + /** +@@ -708,6 +717,36 @@ static int fwu_write_stream(u32 handle, const u8 *payload, u32 payload_size) + return ret; + } + ++/** ++ * fwu_accept() - fwu_accept_image ABI ++ * @guid: GUID of the image to be accepted ++ * ++ * Sets the status of the firmware image, with a given GUID ++ * to "accepted" in the active firmware bank. ++ * ++ * Return: ++ * ++ * 0 on success. Otherwise, failure ++ */ ++static int fwu_accept(const efi_guid_t *guid) ++{ ++ struct fwu_accept_image_args *args = g_fwu_buf; ++ struct fwu_accept_image_resp *resp = g_fwu_buf; ++ char *svc_name = "FWU_ACCEPT_IMAGE"; ++ ++ if (!guid) ++ return -EINVAL; ++ ++ /* Filling the arguments in the shared buffer */ ++ args->function_id = FWU_ACCEPT_IMAGE; ++ ++ guidcpy(&args->image_type_guid, guid); ++ ++ /* Executing the FWU ABI through the FF-A bus */ ++ return fwu_invoke_svc(args->function_id, svc_name, ++ sizeof(*args), sizeof(*resp), NULL); ++} ++ + /** + * fwu_update_image() - Update an image + * +@@ -1051,6 +1090,144 @@ failure: + return ret; + } + ++/** ++ * fwu_one_image_accepted() - Accept one image in trial state ++ * @img_entry: Pointer to the image entry. ++ * @active_idx: Active bank index. ++ * @image_number: Image number for logging purposes. ++ * ++ * Invoke FWU accept image ABI to accept the image. ++ * ++ * Return: ++ * ++ * true is returned on success, false on failure. ++ */ ++static bool fwu_one_image_accepted(const struct fwu_image_entry *img_entry, ++ u32 active_idx, ++ u32 image_number) ++{ ++ const struct fwu_image_bank_info *bank_info = ++ &img_entry->img_bank_info[active_idx]; ++ int fwu_ret; ++ ++ if (!bank_info->accepted) { ++ fwu_ret = fwu_accept(&bank_info->image_guid); ++ if (fwu_ret) { ++ log_err("FWU: Failed to accept image #%d\n", ++ image_number + 1); ++ return false; ++ } ++ log_debug("FWU: Image #%d accepted\n", image_number + 1); ++ } ++ ++ return true; ++} ++ ++/** ++ * fwu_all_images_accepted() - Accept any pending firmware update images ++ * @fwu_data: Pointer to FWU data structure ++ * ++ * Read from the metadata the acceptance state of each image. ++ * Then, accept the images which are not accepted yet. ++ * ++ * Return: ++ * ++ * true is returned on success, false on failure. ++ */ ++static bool fwu_all_images_accepted(const struct fwu_data *fwu_data) ++{ ++ int fwu_ret; ++ u32 active_idx; ++ u32 i; ++ bool accepted; ++ ++ fwu_ret = fwu_get_active_index(&active_idx); ++ if (fwu_ret) { ++ log_err("FWU: Failed to read boot index, err (%d)\n", ++ fwu_ret); ++ return false; ++ } ++ ++ for (i = 0 ; i < CONFIG_FWU_NUM_IMAGES_PER_BANK ; i++) { ++ accepted = fwu_one_image_accepted(&fwu_data->fwu_images[i], active_idx, i); ++ if (!accepted) ++ return false; ++ } ++ ++ return true; ++} ++ ++/** ++ * fwu_accept_notify_exit_boot_services() - ExitBootServices callback ++ * ++ * @event: callback event ++ * @context: callback context ++ * ++ * Reaching ExitBootServices() level means the boot succeeded. ++ * So, accept all the images. ++ * ++ * Return: ++ * ++ * EFI_SUCCESS on success. Otherwise, failure ++ */ ++static void EFIAPI fwu_accept_notify_exit_boot_services(struct efi_event *event, ++ void *context) ++{ ++ efi_status_t efi_ret = EFI_SUCCESS; ++ bool all_accepted; ++ struct fwu_data *fwu_data; ++ ++ EFI_ENTRY("%p, %p", event, context); ++ ++ fwu_data = fwu_get_data(); ++ if (!fwu_data) { ++ log_err("FWU: Cannot get FWU data\n"); ++ efi_ret = EFI_INVALID_PARAMETER; ++ goto out; ++ } ++ ++ if (fwu_data->trial_state) { ++ all_accepted = fwu_all_images_accepted(fwu_data); ++ if (!all_accepted) { ++ efi_ret = EFI_ACCESS_DENIED; ++ goto out; ++ } ++ ++ } else { ++ log_info("FWU: ExitBootServices: Booting in regular state\n"); ++ } ++ ++out: ++ EFI_EXIT(efi_ret); ++} ++ ++/** ++ * fwu_setup_accept_event() - Setup the FWU accept event ++ * ++ * Create a FWU accept event triggered on ExitBootServices(). ++ * ++ * Return: ++ * ++ * 0 is returned on success. Otherwise, failure ++ */ ++static int fwu_setup_accept_event(void) ++{ ++ efi_status_t efi_ret; ++ struct efi_event *evt = NULL; ++ ++ efi_ret = efi_create_event(EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK, ++ fwu_accept_notify_exit_boot_services, NULL, ++ &efi_guid_event_group_exit_boot_services, ++ &evt); ++ if (efi_ret != EFI_SUCCESS) { ++ log_err("FWU: Cannot install accept event %p, err (%lu)\n", evt, ++ efi_ret); ++ return -EPERM; ++ } ++ ++ return 0; ++} ++ + /** + * fwu_agent_init() - Setup the FWU agent + * +@@ -1105,6 +1282,12 @@ int fwu_agent_init(void) + if (ret) + goto failure; + ++ if (IS_ENABLED(CONFIG_FWU_ARM_PSA_ACCEPT_IMAGES)) { ++ ret = fwu_setup_accept_event(); ++ if (ret) ++ goto failure; ++ } ++ + g_fwu_initialized = true; + + return 0; +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0018-corstone1000-add-compressed-kernel-support.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0018-corstone1000-add-compressed-kernel-support.patch deleted file mode 100644 index af87a4a5..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0018-corstone1000-add-compressed-kernel-support.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 67f9f4dbb58a9213232523a433cd6d7c50eeadc7 Mon Sep 17 00:00:00 2001 -From: Jon Mason -Date: Wed, 30 Nov 2022 18:59:59 +0000 -Subject: [PATCH] corstone1000: add compressed kernel support - -The corstone1000 kernel has become too large to fit in the available -storage. Swtiching to a compressed kernel avoids the problem, but -requires uncompressing it. Add this decompression to the default boot -instructions. - -Signed-off-by: Jon Mason -Signed-off-by: Abdellatif El Khlifi -Upstream-Status: Pending [Not submitted to upstream yet] -Signed-off-by: Rui Miguel Silva ---- - configs/corstone1000_defconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig -index 76158fc37d..a92668389a 100644 ---- a/configs/corstone1000_defconfig -+++ b/configs/corstone1000_defconfig -@@ -15,7 +15,7 @@ CONFIG_DISTRO_DEFAULTS=y - CONFIG_BOOTDELAY=3 - CONFIG_USE_BOOTARGS=y - CONFIG_BOOTARGS="console=ttyAMA0 loglevel=9 ip=dhcp earlyprintk" --CONFIG_BOOTCOMMAND="run retrieve_kernel_load_addr; echo Loading kernel from $kernel_addr to memory ... ; loadm $kernel_addr $kernel_addr_r 0xc00000; usb start; usb reset; run distro_bootcmd; bootefi $kernel_addr_r $fdtcontroladdr;" -+CONFIG_BOOTCOMMAND="run retrieve_kernel_load_addr; echo Loading kernel from $kernel_addr to memory ... ; unzip $kernel_addr 0x90000000; loadm 0x90000000 $kernel_addr_r 0xf00000; usb start; usb reset; run distro_bootcmd; bootefi $kernel_addr_r $fdtcontroladdr;" - CONFIG_CONSOLE_RECORD=y - CONFIG_LOGLEVEL=7 - # CONFIG_DISPLAY_CPUINFO is not set diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0018-fwu_arm_psa-Add-ESRT-support.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0018-fwu_arm_psa-Add-ESRT-support.patch new file mode 100644 index 00000000..40af11ee --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0018-fwu_arm_psa-Add-ESRT-support.patch @@ -0,0 +1,219 @@ +From f248f22667df72143938bd2175f0ac49b98d1c3c Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Thu, 13 Feb 2025 17:31:48 +0000 +Subject: [PATCH 18/36] fwu_arm_psa: Add ESRT support + +Read ESRT data from Secure world in GetImageInfo() + +Use FWU_READ_STREAM ABI to read ESRT data from Secure world. + +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20250702152528.1180414-1-abdellatif.elkhlifi@arm.com/] +--- + include/fwu_arm_psa.h | 13 ++++ + lib/fwu_updates/fwu_arm_psa.c | 116 +++++++++++++++++++++++++++++++--- + 2 files changed, 119 insertions(+), 10 deletions(-) + +diff --git a/include/fwu_arm_psa.h b/include/fwu_arm_psa.h +index 451d8b614e3..e29c0b2c05d 100644 +--- a/include/fwu_arm_psa.h ++++ b/include/fwu_arm_psa.h +@@ -16,6 +16,9 @@ + + #define DEFAULT_HW_INSTANCE (1) + ++/* The minimum supported ESRT version */ ++#define EFI_SYSTEM_RESOURCE_TABLE_FIRMWARE_RESOURCE_VERSION (1) ++ + /* Default values of the ESRT fields which are not supported at this stage */ + #define PACKAGE_VERSION_NOT_SUP (0xffffffff) + #define LAST_ATTEMPT_NOT_SUP (0) +@@ -355,6 +358,16 @@ struct __packed fwu_image_directory { + struct fwu_image_info_entry entries[FWU_DIRECTORY_IMAGE_ENTRIES_COUNT]; + }; + ++/* ++ * struct fwu_esrt_data_wrapper - Wrapper for the ESRT data ++ * @data: The ESRT data read from secure world ++ * @entries: The ESRT entries ++ */ ++struct __packed fwu_esrt_data_wrapper { ++ struct efi_system_resource_table data; ++ struct efi_system_resource_entry entries[CONFIG_FWU_NUM_IMAGES_PER_BANK]; ++}; ++ + /** + * fwu_agent_init() - Setup the FWU agent + * +diff --git a/lib/fwu_updates/fwu_arm_psa.c b/lib/fwu_updates/fwu_arm_psa.c +index 40746eee6ce..7297e724569 100644 +--- a/lib/fwu_updates/fwu_arm_psa.c ++++ b/lib/fwu_updates/fwu_arm_psa.c +@@ -27,6 +27,7 @@ static u8 g_fwu_version_minor; + static bool g_fwu_initialized; + struct fwu_image_directory g_fwu_cached_directory; + efi_guid_t g_update_guid[CONFIG_FWU_NUM_IMAGES_PER_BANK]; ++struct fwu_esrt_data_wrapper g_esrt_data; + + /* Error mapping declarations */ + +@@ -898,6 +899,100 @@ close_handle: + return ret; + } + ++/** ++ * fwu_esrt_sanity_check() - Verify ESRT data ++ * ++ * Make sure the ESRT data matches the directory data. ++ * ++ * Return: ++ * ++ * 0 on success ++ */ ++static int fwu_esrt_sanity_check(void) ++{ ++ int i; ++ ++ log_debug("FWU: ESRT data check ...\n"); ++ ++ if (g_esrt_data.data.fw_resource_count != ++ CONFIG_FWU_NUM_IMAGES_PER_BANK) { ++ log_err("FWU: Unexpected ESRT entries count (%d , %d)\n", ++ g_esrt_data.data.fw_resource_count, ++ CONFIG_FWU_NUM_IMAGES_PER_BANK); ++ return -EINVAL; ++ } ++ ++ if (g_esrt_data.data.fw_resource_version < ++ EFI_SYSTEM_RESOURCE_TABLE_FIRMWARE_RESOURCE_VERSION) { ++ log_err("FWU: Secure world ESRT version %llu not supported\n", ++ g_esrt_data.data.fw_resource_version); ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < g_fwu_cached_directory.num_images; i++) { ++ if (guidcmp(&g_fwu_cached_directory.entries[i].image_guid, ++ &g_esrt_data.data.entries[i].fw_class)) { ++ log_err("FWU: GUID mismatch for image %d\n", i + 1); ++ return -EINVAL; ++ } ++ } ++ ++ log_debug("FWU: ESRT data check passed\n"); ++ ++ return 0; ++} ++ ++/** ++ * fwu_read_esrt() - Read the ESRT data ++ * ++ * Read the ESRT data from the Secure world. ++ * ++ * Return: ++ * ++ * 0 on success ++ */ ++static int fwu_read_esrt(void) ++{ ++ int ret, close_ret; ++ u32 handle = 0; ++ efi_guid_t esrt_guid = EFI_SYSTEM_RESOURCE_TABLE_GUID; ++ u32 esrt_data_size; ++ ++ ret = fwu_open(&esrt_guid, FWU_OP_TYPE_READ, &handle); ++ if (ret) { ++ log_err("FWU: Open ESRT image failed (err: %d)\n", ++ ret); ++ return ret; ++ } ++ ++ log_debug("FWU: ESRT image handle (0x%x)\n", handle); ++ ++ esrt_data_size = sizeof(g_esrt_data); ++ ++ ret = fwu_read_stream(handle, (u8 *)&g_esrt_data, esrt_data_size); ++ if (ret) { ++ log_err("FWU: Read ESRT image failed (err: %d)\n", ++ ret); ++ goto close_handle; ++ } ++ ++ ret = fwu_esrt_sanity_check(); ++ if (ret) ++ goto close_handle; ++ ++ log_debug("FWU: ESRT version supported by Secure world (%llu)\n", ++ g_esrt_data.data.fw_resource_version); ++ ++close_handle: ++ /* The Update Agent can execute for an unbounded time */ ++ close_ret = fwu_commit(handle, FWU_IMG_NOT_ACCEPTED, 0); ++ if (close_ret) ++ log_err("FWU: Close ESRT image handle failed (err: %d)\n", ++ close_ret); ++ ++ return ret; ++} ++ + /** + * fwu_discover_ts_sp_id() - Query the FWU partition ID + * +@@ -1192,7 +1287,6 @@ static void EFIAPI fwu_accept_notify_exit_boot_services(struct efi_event *event, + efi_ret = EFI_ACCESS_DENIED; + goto out; + } +- + } else { + log_info("FWU: ExitBootServices: Booting in regular state\n"); + } +@@ -1333,6 +1427,10 @@ efi_status_t fwu_arm_psa_get_image_info(efi_uintn_t *image_info_size, + if (ret) + return EFI_NOT_READY; + ++ ret = fwu_read_esrt(); ++ if (ret) ++ return EFI_NOT_READY; ++ + required_image_info_size = g_fwu_cached_directory.num_images * + image_info_desc_size; + +@@ -1352,15 +1450,13 @@ efi_status_t fwu_arm_psa_get_image_info(efi_uintn_t *image_info_size, + image_info[i].image_index = i + 1; + + /* Corresponding ESRT field: FwClass */ +- guidcpy(&image_info[i].image_type_id, +- &g_fwu_cached_directory.entries[i].image_guid); ++ guidcpy(&image_info[i].image_type_id, &g_esrt_data.entries[i].fw_class); + + image_info[i].image_id = image_info[i].image_index; + image_info[i].image_id_name = NULL; /* Not supported */ + + /* Corresponding ESRT field: FwVersion */ +- image_info[i].version = +- g_fwu_cached_directory.entries[i].img_version; ++ image_info[i].version = g_esrt_data.entries[i].fw_version; + + image_info[i].version_name = NULL; /* Not supported */ + image_info[i].size = +@@ -1379,13 +1475,13 @@ efi_status_t fwu_arm_psa_get_image_info(efi_uintn_t *image_info_size, + + /* Corresponding ESRT field: LowestSupportedFwVersion */ + image_info[i].lowest_supported_image_version = +- g_fwu_cached_directory.entries[i].lowest_acceptable_version; ++ g_esrt_data.entries[i].lowest_supported_fw_version; + +- /* Corresponding ESRT field: LastAttemptVersion (not supported) */ +- image_info[i].last_attempt_version = LAST_ATTEMPT_NOT_SUP; ++ /* Corresponding ESRT field: LastAttemptVersion */ ++ image_info[i].last_attempt_version = g_esrt_data.entries[i].last_attempt_version; + +- /* Corresponding ESRT field: LastAttemptStatus (not supported) */ +- image_info[i].last_attempt_status = LAST_ATTEMPT_NOT_SUP; ++ /* Corresponding ESRT field: LastAttemptStatus */ ++ image_info[i].last_attempt_status = g_esrt_data.entries[i].last_attempt_status; + + image_info[i].hardware_instance = DEFAULT_HW_INSTANCE; + image_info[i].dependencies = NULL; /* Not supported */ +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0019-arm-corstone1000-esrt-support.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0019-arm-corstone1000-esrt-support.patch deleted file mode 100644 index 0781e374..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0019-arm-corstone1000-esrt-support.patch +++ /dev/null @@ -1,222 +0,0 @@ -From 47479f96cb3b3646d298c39216b2c960940476bd Mon Sep 17 00:00:00 2001 -From: Satish Kumar -Date: Wed, 30 Nov 2022 19:11:43 +0000 -Subject: [PATCH] arm/corstone1000: esrt support - -The implementation is platform specific and would require -change in future. - -The patch should not be upstreamed as it is to the u-boot. -Redesign of FMP protocol for ESRT and Capsule Update interface -is to be considered in the future. - -Signed-off-by: Satish Kumar -Upstream-Status: Inappropriate [Redesign of FMP protocol for ESRT and Capsule update interface is required] -Signed-off-by: Rui Miguel Silva ---- - include/efi_api.h | 2 +- - lib/efi_loader/efi_firmware.c | 133 ++++++++++++++++++++++++++++++++++ - lib/efi_loader/efi_setup.c | 17 +++-- - 3 files changed, 143 insertions(+), 9 deletions(-) - -diff --git a/include/efi_api.h b/include/efi_api.h -index 55a4c989fc..f267ab5110 100644 ---- a/include/efi_api.h -+++ b/include/efi_api.h -@@ -2086,7 +2086,7 @@ struct efi_firmware_image_descriptor { - u32 last_attempt_status; - u64 hardware_instance; - efi_firmware_image_dep_t *dependencies; --}; -+} __packed; - - struct efi_firmware_management_protocol { - efi_status_t (EFIAPI *get_image_info)( -diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c -index c883e2ff0a..c6ab6e2182 100644 ---- a/lib/efi_loader/efi_firmware.c -+++ b/lib/efi_loader/efi_firmware.c -@@ -15,6 +15,7 @@ - #include - - #include -+#include - - #define FMP_PAYLOAD_HDR_SIGNATURE SIGNATURE_32('M', 'S', 'S', '1') - -@@ -417,8 +418,140 @@ efi_status_t EFIAPI efi_firmware_fit_set_image( - return EFI_EXIT(EFI_SUCCESS); - } - -+#if CONFIG_IS_ENABLED(TARGET_CORSTONE1000) -+ -+/** -+ * efi_firmware_corstone1000_get_image_info - return information about the current -+ firmware image -+ * @this: Protocol instance -+ * @image_info_size: Size of @image_info -+ * @image_info: Image information -+ * @descriptor_version: Pointer to version number -+ * @descriptor_count: Pointer to number of descriptors -+ * @descriptor_size: Pointer to descriptor size -+ * package_version: Package version -+ * package_version_name: Package version's name -+ * -+ * Return information bout the current firmware image in @image_info. -+ * @image_info will consist of a number of descriptors. -+ * Each descriptor will be created based on efi fetched variable. -+ * -+ * Return status code -+ */ -+static -+efi_status_t EFIAPI efi_firmware_corstone1000_get_image_info( -+ struct efi_firmware_management_protocol *this, -+ efi_uintn_t *image_info_size, -+ struct efi_firmware_image_descriptor *image_info, -+ u32 *descriptor_version, -+ u8 *descriptor_count, -+ efi_uintn_t *descriptor_size, -+ u32 *package_version, -+ u16 **package_version_name) -+{ -+ efi_uintn_t var_size; -+ efi_status_t ret = EFI_SUCCESS; -+ efi_uintn_t image_info_size_var = 0; -+ efi_uintn_t image_info_name_size_var; -+ efi_uintn_t image_info_version_size_var; -+ u8 *runner = (u8 *)image_info; -+ u16 fmp_image_name[14] = {'F', 'm', 'p', 'I', 'm', 'a', 'g', 'e', 'N', 'a', 'm', 'e', '1', '\0'}; -+ u16 fmp_version_name[16] = {'F', 'm', 'p', 'V', 'e', 'r', 's', 'i', 'o', 'n', 'N', 'a', 'm', 'e', '1', '\0'}; -+ -+ EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this, -+ image_info_size, image_info, -+ descriptor_version, descriptor_count, descriptor_size, -+ package_version, package_version_name); -+ -+ if (!image_info_size) -+ return EFI_EXIT(EFI_INVALID_PARAMETER); -+ -+ if (*image_info_size && -+ (!image_info || !descriptor_version || !descriptor_count || -+ !descriptor_size || !package_version || !package_version_name)) -+ return EFI_EXIT(EFI_INVALID_PARAMETER); -+ -+ var_size = sizeof(*descriptor_version); -+ ret = efi_get_variable(u"FmpDescriptorVersion", -+ &efi_guid_firmware_management_protocol, NULL, -+ &var_size, descriptor_version); -+ if (ret != EFI_SUCCESS) -+ return EFI_EXIT(ret); -+ -+ if (*descriptor_version != EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION) -+ return EFI_EXIT(EFI_UNSUPPORTED); -+ -+ var_size = sizeof(image_info_size_var); -+ ret = efi_get_variable(u"FmpImageInfoSize", -+ &efi_guid_firmware_management_protocol, NULL, -+ &var_size, &image_info_size_var); -+ if (ret != EFI_SUCCESS) -+ return EFI_EXIT(ret); -+ -+ if (*image_info_size < image_info_size_var) { -+ *image_info_size = image_info_size_var; -+ return EFI_EXIT(EFI_BUFFER_TOO_SMALL); -+ } -+ -+ image_info_name_size_var = image_info_size_var; -+ -+ var_size = sizeof(*descriptor_count); -+ ret = efi_get_variable(u"FmpDescriptorCount", -+ &efi_guid_firmware_management_protocol, NULL, -+ &var_size, descriptor_count); -+ if (ret != EFI_SUCCESS) { -+ return EFI_EXIT(ret); -+ } -+ -+ ret = efi_get_variable(u"FmpImageInfo", -+ &efi_guid_firmware_management_protocol, NULL, -+ &image_info_size_var, image_info); -+ if (ret != EFI_SUCCESS) -+ return EFI_EXIT(ret); -+ -+ runner += image_info_size_var; -+ -+ image_info_name_size_var -= image_info_size_var; -+ image_info_version_size_var = image_info_name_size_var; -+ -+ /* Consider changing the string modfication logic */ -+ fmp_image_name[12] = '0' + (u16)image_info->image_id; -+ ret = efi_get_variable(fmp_image_name, -+ &efi_guid_firmware_management_protocol, NULL, -+ &image_info_name_size_var, runner); -+ if (ret != EFI_SUCCESS) -+ return EFI_EXIT(ret); -+ -+ image_info_version_size_var -= image_info_name_size_var; -+ image_info->image_id_name = (u16*)runner; -+ runner += image_info_name_size_var; -+ -+ /* Consider changing the string modfication logic */ -+ fmp_version_name[14] = '0' + (u16)image_info->image_id; -+ ret = efi_get_variable(fmp_version_name, -+ &efi_guid_firmware_management_protocol, NULL, -+ &image_info_version_size_var, runner); -+ if (ret != EFI_SUCCESS) -+ return EFI_EXIT(ret); -+ -+ image_info->version_name = (u16*)runner; -+ -+ *image_info_size = image_info_size_var; -+ -+ *package_version = 0xffffffff; /* not supported */ -+ *package_version_name = NULL; /* not supported */ -+ -+ return EFI_EXIT(ret); -+} -+ -+#endif -+ - const struct efi_firmware_management_protocol efi_fmp_fit = { -+#if CONFIG_IS_ENABLED(TARGET_CORSTONE1000) -+ .get_image_info = efi_firmware_corstone1000_get_image_info, -+#else - .get_image_info = efi_firmware_get_image_info, -+#endif - .get_image = efi_firmware_get_image_unsupported, - .set_image = efi_firmware_fit_set_image, - .check_image = efi_firmware_check_image_unsupported, -diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c -index bf90a98b5a..d20568c1c8 100644 ---- a/lib/efi_loader/efi_setup.c -+++ b/lib/efi_loader/efi_setup.c -@@ -178,14 +178,6 @@ static efi_status_t efi_init_capsule(void) - efi_status_t ret = EFI_SUCCESS; - - #if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) -- int ffa_ret; -- -- ffa_ret = efi_corstone1000_uboot_efi_started_event(); -- if (ffa_ret) -- log_err("Failure to notify SE Proxy FW update service\n"); -- else -- debug("SE Proxy FW update service notified\n"); -- - ret = efi_corstone1000_alloc_capsule_shared_buf(); - if (ret != EFI_SUCCESS) { - printf("EFI: Corstone-1000: cannot allocate caspsule shared buffer\n"); -@@ -304,6 +296,15 @@ efi_status_t efi_init_obj_list(void) - if (ret != EFI_SUCCESS) - goto out; - -+#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) -+ int ffa_ret; -+ ffa_ret = efi_corstone1000_uboot_efi_started_event(); -+ if (ffa_ret) -+ log_err("Failure to notify SE Proxy FW update service\n"); -+ else -+ debug("SE Proxy FW update service notified\n"); -+#endif -+ - /* Initialize variable services */ - ret = efi_init_variables(); - if (ret != EFI_SUCCESS) diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0019-fwu_arm_psa-Add-ExitBootService-notification-handler.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0019-fwu_arm_psa-Add-ExitBootService-notification-handler.patch new file mode 100644 index 00000000..dda06828 --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0019-fwu_arm_psa-Add-ExitBootService-notification-handler.patch @@ -0,0 +1,54 @@ +From bf2211397fc79bcc29cf58389392042f2d0101c4 Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Mon, 10 Mar 2025 16:33:06 +0000 +Subject: [PATCH 19/36] fwu_arm_psa: Add ExitBootService() notification handler + +Provide a weak function that can be overridden + +Some boards need to perform custom actions on ExitBootService() +related to FWU. This function can be overridden by the board. + +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20250702152528.1180414-1-abdellatif.elkhlifi@arm.com/] +--- + lib/fwu_updates/fwu_arm_psa.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/lib/fwu_updates/fwu_arm_psa.c b/lib/fwu_updates/fwu_arm_psa.c +index 7297e724569..6a829c631b0 100644 +--- a/lib/fwu_updates/fwu_arm_psa.c ++++ b/lib/fwu_updates/fwu_arm_psa.c +@@ -1252,6 +1252,21 @@ static bool fwu_all_images_accepted(const struct fwu_data *fwu_data) + return true; + } + ++/** ++ * fwu_notify_exit_boot_services() - FWU notification handler ++ * ++ * Some boards need to perform custom actions on ExitBootService() ++ * related to FWU. This function can be overridden by the board. ++ * ++ * Return: ++ * ++ * EFI_SUCCESS on success. Otherwise, failure ++ */ ++efi_status_t __weak fwu_notify_exit_boot_services(void) ++{ ++ return EFI_SUCCESS; ++} ++ + /** + * fwu_accept_notify_exit_boot_services() - ExitBootServices callback + * +@@ -1292,6 +1307,8 @@ static void EFIAPI fwu_accept_notify_exit_boot_services(struct efi_event *event, + } + + out: ++ fwu_notify_exit_boot_services(); ++ + EFI_EXIT(efi_ret); + } + +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0020-corstone1000-enable-distro-booting-command.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0020-corstone1000-enable-distro-booting-command.patch deleted file mode 100644 index 8ee8343a..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0020-corstone1000-enable-distro-booting-command.patch +++ /dev/null @@ -1,25 +0,0 @@ -From c95dbed049801401ac98afc8ef53e917b69f9a62 Mon Sep 17 00:00:00 2001 -From: Abdellatif El Khlifi -Date: Mon, 5 Dec 2022 17:02:32 +0000 -Subject: [PATCH] corstone1000: enable distro booting command - -enable distro_bootcmd - -Signed-off-by: Abdellatif El Khlifi -Signed-off-by: Rui Miguel Silva -Upstream-Status: Pending [Not submitted to upstream yet] ---- - include/configs/corstone1000.h | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h -index 1466507f80..8622565a87 100644 ---- a/include/configs/corstone1000.h -+++ b/include/configs/corstone1000.h -@@ -55,5 +55,6 @@ - - #include - -+#define CFG_EXTRA_ENV_SETTINGS BOOTENV - - #endif diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0020-efi_loader-capsule-Add-runtime-capsule-flags-checks.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0020-efi_loader-capsule-Add-runtime-capsule-flags-checks.patch new file mode 100644 index 00000000..951607a9 --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0020-efi_loader-capsule-Add-runtime-capsule-flags-checks.patch @@ -0,0 +1,67 @@ +From 898008bd55b0de115f62254be8fbc8a5d43894ba Mon Sep 17 00:00:00 2001 +From: Emekcan Aras +Date: Fri, 21 Mar 2025 15:34:44 +0000 +Subject: [PATCH 20/36] efi_loader: capsule: Add runtime capsule flags checks + +Add missing checks according to the UEFI specification [1] + +checks added for these capsule flags: + +CAPSULE_FLAGS_PERSIST_ACROSS_RESET +CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE +CAPSULE_FLAGS_INITIATE_RESET + +[1]: Table 8.8 Flag Firmware Behavior, + https://uefi.org/specs/UEFI/2.10/08_Services_Runtime_Services.html + +Signed-off-by: Emekcan Aras +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20250702152528.1180414-1-abdellatif.elkhlifi@arm.com/] +--- + lib/efi_loader/efi_capsule.c | 30 ++++++++++++++++++++++++++++++ + 1 file changed, 30 insertions(+) + +diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c +index e01f2a5f8a8..aeb05a00a0f 100644 +--- a/lib/efi_loader/efi_capsule.c ++++ b/lib/efi_loader/efi_capsule.c +@@ -791,6 +791,36 @@ efi_status_t EFIAPI efi_update_capsule( + continue; + } + ++ /* ++ * ScatterGatherList must point to a list when the ++ * CAPSULE_FLAGS_PERSIST_ACROSS_RESET flag is set. ++ */ ++ if ((capsule->flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) && ++ !scatter_gather_list) { ++ ret = EFI_INVALID_PARAMETER; ++ goto out; ++ } ++ ++ /* ++ * The CAPSULE_FLAGS_PERSIST_ACROSS_RESET flag must be set ++ * along with the CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag. ++ */ ++ if ((capsule->flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) && ++ !(capsule->flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET)) { ++ ret = EFI_INVALID_PARAMETER; ++ goto out; ++ } ++ ++ /* ++ * The CAPSULE_FLAGS_PERSIST_ACROSS_RESET flag must be set ++ * along with the CAPSULE_FLAGS_INITIATE_RESET flag. ++ */ ++ if ((capsule->flags & CAPSULE_FLAGS_INITIATE_RESET) && ++ !(capsule->flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET)) { ++ ret = EFI_INVALID_PARAMETER; ++ goto out; ++ } ++ + log_debug("Capsule[%d] (guid:%pUs)\n", + i, &capsule->capsule_guid); + ret = efi_capsule_update_firmware(capsule); +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0021-corstone1000-add-fwu-metadata-store-info.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0021-corstone1000-add-fwu-metadata-store-info.patch deleted file mode 100644 index c58f7b57..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0021-corstone1000-add-fwu-metadata-store-info.patch +++ /dev/null @@ -1,39 +0,0 @@ -From c250b6b896facee9ef42f88f5c76f055dbcfc708 Mon Sep 17 00:00:00 2001 -From: Rui Miguel Silva -Date: Wed, 1 Feb 2023 15:58:07 +0000 -Subject: [PATCH] corstone1000: add fwu-metadata store info - -Add fwu-mdata node and handle for the reference -nvmxip-qspi. - -Upstream-Status: Submitted -Signed-off-by: Rui Miguel Silva ---- - arch/arm/dts/corstone1000.dtsi | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/arch/arm/dts/corstone1000.dtsi b/arch/arm/dts/corstone1000.dtsi -index 533dfdf8e1..1e0ec075e4 100644 ---- a/arch/arm/dts/corstone1000.dtsi -+++ b/arch/arm/dts/corstone1000.dtsi -@@ -38,7 +38,7 @@ - reg = <0x88200000 0x77e00000>; - }; - -- nvmxip-qspi@08000000 { -+ nvmxip: nvmxip-qspi@08000000 { - compatible = "nvmxip,qspi"; - reg = <0x08000000 0x2000000>; - lba_shift = <9>; -@@ -106,6 +106,11 @@ - method = "smc"; - }; - -+ fwu-mdata { -+ compatible = "u-boot,fwu-mdata-gpt"; -+ fwu-mdata-store = <&nvmxip>; -+ }; -+ - soc { - compatible = "simple-bus"; - #address-cells = <1>; diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0021-fwu_arm_psa-corstone1000-Enable-FWU-support.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0021-fwu_arm_psa-corstone1000-Enable-FWU-support.patch new file mode 100644 index 00000000..14424124 --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0021-fwu_arm_psa-corstone1000-Enable-FWU-support.patch @@ -0,0 +1,228 @@ +From 7aa05114f04ec5792d7948153baf0633f5ca8bcb Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Thu, 20 Mar 2025 14:41:41 +0000 +Subject: [PATCH 21/36] fwu_arm_psa: corstone1000: Enable FWU support + +Provide the update_info structure and FWU configs for Corstone-1000 + +update_info defines the image to be used for FWU. +The FWU configs enabled are the FWU Arm PSA configs. + +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20250702152528.1180414-1-abdellatif.elkhlifi@arm.com/] +--- + board/armltd/corstone1000/corstone1000.c | 138 ++++++++++++++++++++++- + configs/corstone1000_defconfig | 10 +- + 2 files changed, 146 insertions(+), 2 deletions(-) + +diff --git a/board/armltd/corstone1000/corstone1000.c b/board/armltd/corstone1000/corstone1000.c +index 3ad77f51949..d2176b9174d 100644 +--- a/board/armltd/corstone1000/corstone1000.c ++++ b/board/armltd/corstone1000/corstone1000.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0+ + /* +- * (C) Copyright 2022 ARM Limited ++ * (C) Copyright 2022, 2025 Arm Limited + * (C) Copyright 2022 Linaro + * Rui Miguel Silva + */ +@@ -8,8 +8,11 @@ + #include + #include + #include ++#include + #include ++#include + #include ++#include + #include + #include + #include +@@ -21,6 +24,133 @@ + #define CORSTONE1000_KERNEL_PRIMARY "kernel_primary" + #define CORSTONE1000_KERNEL_SECONDARY "kernel_secondary" + ++#if IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) ++ ++/* The total number of upgradable images including the start and end dummy payloads */ ++#define CAPSULE_PAYLOADS_MAX_COUNT (CONFIG_FWU_NUM_IMAGES_PER_BANK + 2) ++ ++/* ++ * GUIDs for capsule updatable firmware images ++ * ++ * The GUIDs are generating with the UUIDv5 format. ++ * Namespace used for FVP GUIDs: 989f3a4e-46e0-4cd0-9877-a25c70c01329 ++ * Namespace used for MPS3 GUIDs: df1865d1-90fb-4d59-9c38-c9f2c1bba8cc ++ * Names: the image names stated in the fw_name field ++ */ ++ ++#define FWU_FVP_BL2_IMAGE_GUID \ ++ EFI_GUID(0xf1d883f9, 0xdfeb, 0x5363, 0x98, 0xd8, \ ++ 0x68, 0x6e, 0xe3, 0xb6, 0x9f, 0x4f) ++ ++#define FWU_MPS3_BL2_IMAGE_GUID \ ++ EFI_GUID(0xfbfbefaa, 0x0a56, 0x50d5, 0xb6, 0x51, \ ++ 0x74, 0x09, 0x1d, 0x3d, 0x62, 0xcf) ++ ++#define FWU_FVP_TFM_S_IMAGE_GUID \ ++ EFI_GUID(0x7fad470e, 0x5ec5, 0x5c03, 0xa2, 0xc1, \ ++ 0x47, 0x56, 0xb4, 0x95, 0xde, 0x61) ++ ++#define FWU_MPS3_TFM_S_IMAGE_GUID \ ++ EFI_GUID(0xaf4cc7ad, 0xee2e, 0x5a39, 0xaa, 0xd5, \ ++ 0xfa, 0xc8, 0xa1, 0xe6, 0x17, 0x3c) ++ ++#define FWU_FVP_FIP_IMAGE_GUID \ ++ EFI_GUID(0xf1933675, 0x5a8c, 0x5b6d, 0x9e, 0xf4, \ ++ 0x84, 0x67, 0x39, 0xe8, 0x9b, 0xc8) ++ ++#define FWU_MPS3_FIP_IMAGE_GUID \ ++ EFI_GUID(0x55302f96, 0xc4f0, 0x5cf9, 0x86, 0x24, \ ++ 0xe7, 0xcc, 0x38, 0x8f, 0x2b, 0x68) ++ ++#define FWU_FVP_INITRAMFS_IMAGE_GUID \ ++ EFI_GUID(0xf771aff9, 0xc7e9, 0x5f99, 0x9e, 0xda, \ ++ 0x23, 0x69, 0xdd, 0x69, 0x4f, 0x61) ++ ++#define FWU_MPS3_INITRAMFS_IMAGE_GUID \ ++ EFI_GUID(0x3e8ac972, 0xc33c, 0x5cc9, 0x90, 0xa0, \ ++ 0xcd, 0xd3, 0x15, 0x96, 0x83, 0xea) ++ ++enum fw_image_index { ++ FW_IMAGE_INDEX_BL2 = 1, ++ FW_IMAGE_INDEX_TFM_S, ++ FW_IMAGE_INDEX_FIP, ++ FW_IMAGE_INDEX_INITRAMFS, ++ FW_IMAGE_INDEX_DUMMY_START, ++ FW_IMAGE_INDEX_DUMMY_END ++}; ++ ++struct efi_fw_image fw_mps3_images[] = { ++ { ++ .image_type_id = FWU_MPS3_BL2_IMAGE_GUID, ++ .fw_name = u"BL2", ++ .image_index = FW_IMAGE_INDEX_BL2, ++ }, ++ { ++ .image_type_id = FWU_MPS3_TFM_S_IMAGE_GUID, ++ .fw_name = u"TFM_S", ++ .image_index = FW_IMAGE_INDEX_TFM_S, ++ }, ++ { ++ .image_type_id = FWU_MPS3_FIP_IMAGE_GUID, ++ .fw_name = u"FIP", ++ .image_index = FW_IMAGE_INDEX_FIP, ++ }, ++ { ++ .image_type_id = FWU_MPS3_INITRAMFS_IMAGE_GUID, ++ .fw_name = u"INITRAMFS", ++ .image_index = FW_IMAGE_INDEX_INITRAMFS, ++ }, ++ { ++ .image_type_id = FWU_DUMMY_START_IMAGE_GUID, ++ .fw_name = u"DUMMY_START", ++ .image_index = FW_IMAGE_INDEX_DUMMY_START, ++ }, ++ { ++ .image_type_id = FWU_DUMMY_END_IMAGE_GUID, ++ .fw_name = u"DUMMY_END", ++ .image_index = FW_IMAGE_INDEX_DUMMY_END, ++ }, ++}; ++ ++struct efi_fw_image fw_fvp_images[] = { ++ { ++ .image_type_id = FWU_FVP_BL2_IMAGE_GUID, ++ .fw_name = u"BL2", ++ .image_index = FW_IMAGE_INDEX_BL2, ++ }, ++ { ++ .image_type_id = FWU_FVP_TFM_S_IMAGE_GUID, ++ .fw_name = u"TFM_S", ++ .image_index = FW_IMAGE_INDEX_TFM_S, ++ }, ++ { ++ .image_type_id = FWU_FVP_FIP_IMAGE_GUID, ++ .fw_name = u"FIP", ++ .image_index = FW_IMAGE_INDEX_FIP, ++ }, ++ { ++ .image_type_id = FWU_FVP_INITRAMFS_IMAGE_GUID, ++ .fw_name = u"INITRAMFS", ++ .image_index = FW_IMAGE_INDEX_INITRAMFS, ++ }, ++ { ++ .image_type_id = FWU_DUMMY_START_IMAGE_GUID, ++ .fw_name = u"DUMMY_START", ++ .image_index = FW_IMAGE_INDEX_DUMMY_START, ++ }, ++ { ++ .image_type_id = FWU_DUMMY_END_IMAGE_GUID, ++ .fw_name = u"DUMMY_END", ++ .image_index = FW_IMAGE_INDEX_DUMMY_END, ++ }, ++}; ++ ++struct efi_capsule_update_info update_info = { ++ .num_images = CAPSULE_PAYLOADS_MAX_COUNT, ++}; ++ ++#endif /* EFI_HAVE_CAPSULE_SUPPORT */ ++ + static int corstone1000_boot_idx; + + static struct mm_region corstone1000_mem_map[] = { +@@ -79,6 +209,12 @@ struct mm_region *mem_map = corstone1000_mem_map; + + int board_init(void) + { ++#if IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) ++ if (!strcmp(DEVICE_TREE, "corstone1000-fvp")) ++ update_info.images = fw_fvp_images; ++ else ++ update_info.images = fw_mps3_images; ++#endif + return 0; + } + +diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig +index 80163580f85..5b10e3f7484 100644 +--- a/configs/corstone1000_defconfig ++++ b/configs/corstone1000_defconfig +@@ -10,11 +10,16 @@ CONFIG_DEFAULT_DEVICE_TREE="corstone1000-mps3" + CONFIG_SYS_BOOTM_LEN=0x800000 + CONFIG_SYS_LOAD_ADDR=0x82100000 + CONFIG_IDENT_STRING=" corstone1000 aarch64 " ++CONFIG_FWU_NUM_IMAGES_PER_BANK=4 + CONFIG_EFI_MM_COMM_TEE=y + CONFIG_FFA_SHARED_MM_BUF_SIZE=4096 + CONFIG_FFA_SHARED_MM_BUF_OFFSET=0 + CONFIG_FFA_SHARED_MM_BUF_ADDR=0x02000000 ++CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y + CONFIG_EFI_CAPSULE_ON_DISK=y ++CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y ++CONFIG_EFI_CAPSULE_AUTHENTICATE=y ++CONFIG_EFI_CAPSULE_CRT_FILE="CRT.crt" + CONFIG_FIT=y + CONFIG_DISTRO_DEFAULTS=y + CONFIG_BOOTDELAY=3 +@@ -38,6 +43,7 @@ CONFIG_CMD_LOADM=y + CONFIG_CMD_USB=y + # CONFIG_CMD_SETEXPR is not set + CONFIG_CMD_CACHE=y ++CONFIG_CMD_EFIDEBUG=y + CONFIG_CMD_RTC=y + CONFIG_CMD_TIME=y + CONFIG_CMD_GETTIME=y +@@ -67,4 +73,6 @@ CONFIG_USB_ISP1760=y + # CONFIG_RANDOM_UUID is not set + CONFIG_ERRNO_STR=y + CONFIG_FWU_MULTI_BANK_UPDATE=y +-CONFIG_FWU_MDATA_V1=y ++CONFIG_FWU_MDATA_V2=y ++CONFIG_FWU_ARM_PSA=y ++# CONFIG_TOOLS_MKEFICAPSULE is not set +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0022-fwu_arm_psa-corstone1000-Perform-bank-logic-when-rea.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0022-fwu_arm_psa-corstone1000-Perform-bank-logic-when-rea.patch new file mode 100644 index 00000000..1fe95f11 --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0022-fwu_arm_psa-corstone1000-Perform-bank-logic-when-rea.patch @@ -0,0 +1,143 @@ +From e3e4f4adae7bdf580490bd82013760e4f603022e Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Wed, 5 Mar 2025 19:09:20 +0000 +Subject: [PATCH 22/36] fwu_arm_psa: corstone1000: Perform bank logic when + reading boot index + +Move bank logic from board_late_init to fwu_plat_get_bootidx + +board_late_init is called very early before the FWU subsystem is setup. +So, the metadata is still not initialized at that level. Reading the boot +index at that level returns an invalid value. +Moving the bank logic to fwu_plat_get_bootidx guarantees the returned +boot index is reflecting the value read from the metadata. + +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20250702152528.1180414-1-abdellatif.elkhlifi@arm.com/] +--- + board/armltd/corstone1000/corstone1000.c | 63 +++++++++++------------- + configs/corstone1000_defconfig | 1 - + 2 files changed, 29 insertions(+), 35 deletions(-) + +diff --git a/board/armltd/corstone1000/corstone1000.c b/board/armltd/corstone1000/corstone1000.c +index d2176b9174d..2ccf851e6c5 100644 +--- a/board/armltd/corstone1000/corstone1000.c ++++ b/board/armltd/corstone1000/corstone1000.c +@@ -151,8 +151,6 @@ struct efi_capsule_update_info update_info = { + + #endif /* EFI_HAVE_CAPSULE_SUPPORT */ + +-static int corstone1000_boot_idx; +- + static struct mm_region corstone1000_mem_map[] = { + { + /* CVM */ +@@ -234,45 +232,37 @@ int dram_init_banksize(void) + } + + void fwu_plat_get_bootidx(uint *boot_idx) +-{ +- int ret; +- +- /* +- * in our platform, the Secure Enclave is the one who controls +- * all the boot tries and status, so, every time we get here +- * we know that the we are booting from the active index +- */ +- ret = fwu_get_active_index(boot_idx); +- if (ret < 0) { +- *boot_idx = CONFIG_FWU_NUM_BANKS; +- log_err("corstone1000: failed to read active index\n"); +- } +-} +- +-int board_late_init(void) + { + struct disk_partition part_info; + struct udevice *dev, *bdev; + struct nvmxip_plat *plat; + struct blk_desc *desc; + int ret; ++ bool kernel_addr_set, kernel_size_set; + + ret = uclass_first_device_err(UCLASS_NVMXIP, &dev); + if (ret < 0) { +- log_err("Cannot find kernel device\n"); +- return ret; ++ log_err("Cannot find kernel device, err (%d)\n", ret); ++ return; + } + + plat = dev_get_plat(dev); + device_find_first_child(dev, &bdev); + desc = dev_get_uclass_plat(bdev); +- ret = fwu_get_active_index(&corstone1000_boot_idx); ++ ret = fwu_get_active_index(boot_idx); + if (ret < 0) { ++ *boot_idx = CONFIG_FWU_NUM_BANKS; + log_err("corstone1000: failed to read boot index\n"); +- return ret; ++ return; + } + +- if (!corstone1000_boot_idx) ++ kernel_addr_set = env_get_hex("kernel_addr", 0) ? true : false; ++ kernel_size_set = env_get_hex("kernel_size", 0) ? true : false; ++ ++ if (kernel_addr_set && kernel_size_set) ++ return; ++ ++ if (!(*boot_idx)) + ret = part_get_info_by_name(desc, CORSTONE1000_KERNEL_PRIMARY, + &part_info); + else +@@ -281,18 +271,23 @@ int board_late_init(void) + + if (ret < 0) { + log_err("failed to fetch kernel partition index: %d\n", +- corstone1000_boot_idx); +- return ret; ++ *boot_idx); ++ return; + } + +- ret = 0; +- +- ret |= env_set_hex("kernel_addr", plat->phys_base + +- (part_info.start * part_info.blksz)); +- ret |= env_set_hex("kernel_size", part_info.size * part_info.blksz); +- +- if (ret < 0) +- log_err("failed to setup kernel addr and size\n"); ++ if (!kernel_addr_set) { ++ ret = env_set_hex("kernel_addr", plat->phys_base + ++ (part_info.start * part_info.blksz)); ++ if (ret) ++ log_err("cannot set kernel_addr variable, err (%d)\n", ++ ret); ++ } + +- return ret; ++ if (!kernel_size_set) { ++ ret = env_set_hex("kernel_size", ++ part_info.size * part_info.blksz); ++ if (ret) ++ log_err("cannot set kernel_size variable, err (%d)\n", ++ ret); ++ } + } +diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig +index 5b10e3f7484..d52d39a0b36 100644 +--- a/configs/corstone1000_defconfig ++++ b/configs/corstone1000_defconfig +@@ -31,7 +31,6 @@ CONFIG_SYS_CBSIZE=512 + CONFIG_LOGLEVEL=7 + # CONFIG_DISPLAY_CPUINFO is not set + # CONFIG_DISPLAY_BOARDINFO is not set +-CONFIG_BOARD_LATE_INIT=y + CONFIG_SYS_PROMPT="corstone1000# " + # CONFIG_CMD_CONSOLE is not set + CONFIG_CMD_FWU_METADATA=y +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0022-fwu_metadata-make-sure-structures-are-packed.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0022-fwu_metadata-make-sure-structures-are-packed.patch deleted file mode 100644 index e556cabe..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0022-fwu_metadata-make-sure-structures-are-packed.patch +++ /dev/null @@ -1,47 +0,0 @@ -From b1445e50c1f260e3454bc4946ea1009ff3e0dda6 Mon Sep 17 00:00:00 2001 -From: Rui Miguel Silva -Date: Wed, 1 Feb 2023 16:13:24 +0000 -Subject: [PATCH] fwu_metadata: make sure structures are packed - -The fwu metadata in the metadata partitions -should/are packed to guarantee that the info is -correct in all platforms. Also the size of them -are used to calculate the crc32 and that is important -to get it right. - -Upstream-Status: Pending -Signed-off-by: Rui Miguel Silva ---- - include/fwu_mdata.h | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/include/fwu_mdata.h b/include/fwu_mdata.h -index 8fda4f4ac2..c61221a917 100644 ---- a/include/fwu_mdata.h -+++ b/include/fwu_mdata.h -@@ -22,7 +22,7 @@ struct fwu_image_bank_info { - efi_guid_t image_uuid; - uint32_t accepted; - uint32_t reserved; --}; -+} __packed; - - /** - * struct fwu_image_entry - information for a particular type of image -@@ -38,7 +38,7 @@ struct fwu_image_entry { - efi_guid_t image_type_uuid; - efi_guid_t location_uuid; - struct fwu_image_bank_info img_bank_info[CONFIG_FWU_NUM_BANKS]; --}; -+} __packed; - - /** - * struct fwu_mdata - FWU metadata structure for multi-bank updates -@@ -62,6 +62,6 @@ struct fwu_mdata { - uint32_t previous_active_index; - - struct fwu_image_entry img_entry[CONFIG_FWU_NUM_IMAGES_PER_BANK]; --}; -+} __packed; - - #endif /* _FWU_MDATA_H_ */ diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0023-corstone1000-add-boot-index.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0023-corstone1000-add-boot-index.patch deleted file mode 100644 index 4fc5de73..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0023-corstone1000-add-boot-index.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 7a71000da87c4b48c6c42043924863c2933d8bdf Mon Sep 17 00:00:00 2001 -From: Rui Miguel Silva -Date: Mon, 17 Jul 2023 17:04:10 +0100 -Subject: [PATCH] corstone1000: add boot index - -it is expected that the firmware that runs before -u-boot somehow provide the information of the bank -(index) of it is booting. -We will need to extend tf-a to pass that info, -meanwhile just set it to the default bank. - -Upstream-Status: Pending -Signed-off-by: Rui Miguel Silva -Signed-off-by: Abdellatif El Khlifi ---- - board/armltd/corstone1000/corstone1000.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/board/armltd/corstone1000/corstone1000.c b/board/armltd/corstone1000/corstone1000.c -index ecfd8366df..ba6d024b80 100644 ---- a/board/armltd/corstone1000/corstone1000.c -+++ b/board/armltd/corstone1000/corstone1000.c -@@ -8,6 +8,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -107,6 +108,7 @@ int dram_init_banksize(void) - return 0; - } - --void reset_cpu(void) -+void fwu_plat_get_bootidx(uint *boot_idx) - { -+ *boot_idx = 0; - } diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0023-fwu_arm_psa-corstone1000-Notify-SE-Proxy-SP-on-ExitB.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0023-fwu_arm_psa-corstone1000-Notify-SE-Proxy-SP-on-ExitB.patch new file mode 100644 index 00000000..5317984f --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0023-fwu_arm_psa-corstone1000-Notify-SE-Proxy-SP-on-ExitB.patch @@ -0,0 +1,104 @@ +From fe7e49ae4fdf07aab3d882adcde94097b3dead82 Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Thu, 20 Mar 2025 15:27:27 +0000 +Subject: [PATCH 23/36] fwu_arm_psa: corstone1000: Notify SE Proxy SP on + ExitBootService() + +Implement the notification in fwu_notify_exit_boot_services() + +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20250702152528.1180414-1-abdellatif.elkhlifi@arm.com/] +--- + board/armltd/corstone1000/corstone1000.c | 60 ++++++++++++++++++++++++ + 1 file changed, 60 insertions(+) + +diff --git a/board/armltd/corstone1000/corstone1000.c b/board/armltd/corstone1000/corstone1000.c +index 2ccf851e6c5..2532c5f10fa 100644 +--- a/board/armltd/corstone1000/corstone1000.c ++++ b/board/armltd/corstone1000/corstone1000.c +@@ -5,6 +5,7 @@ + * Rui Miguel Silva + */ + ++#include + #include + #include + #include +@@ -19,11 +20,28 @@ + #include + #include + #include ++#include + + #define CORSTONE1000_KERNEL_PARTS 2 + #define CORSTONE1000_KERNEL_PRIMARY "kernel_primary" + #define CORSTONE1000_KERNEL_SECONDARY "kernel_secondary" + ++/* The SE Proxy partition ID*/ ++#define CORSTONE1000_SEPROXY_PART_ID (0x8002) ++ ++/* Update service ID provided by the SE Proxy SP*/ ++#define CORSTONE1000_SEPROXY_UPDATE_SVC_ID (0x4) ++#define PREP_SEPROXY_SVC_ID_MASK GENMASK(31, 16) ++#define PREP_SEPROXY_SVC_ID(x) (FIELD_PREP(PREP_SEPROXY_SVC_ID_MASK, (x))) ++ ++/* Notification event used with SE Proxy SP */ ++#define CORSTONE1000_UBOOT_EFI_STARTED_EVT (0x3) ++#define PREP_SEPROXY_EVT_MASK GENMASK(15, 0) ++#define PREP_SEPROXY_EVT(x) (FIELD_PREP(PREP_SEPROXY_EVT_MASK, (x))) ++ ++/* Signal that there is no shared memory used when notifying SE Proxy SP */ ++#define FFA_MEM_HANDLE_INVALID (0xffffffff) ++ + #if IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) + + /* The total number of upgradable images including the start and end dummy payloads */ +@@ -291,3 +309,45 @@ void fwu_plat_get_bootidx(uint *boot_idx) + ret); + } + } ++ ++/** ++ * fwu_notify_exit_boot_services() - ExitBootService event handler ++ * ++ * Notify SE Proxy SP when reaching ExitBootService(). ++ * ++ * Return: ++ * ++ * EFI_SUCCESS on success. Otherwise, failure ++ */ ++efi_status_t fwu_notify_exit_boot_services(void) ++{ ++ efi_status_t efi_ret = EFI_SUCCESS; ++ int ffa_ret; ++ struct ffa_send_direct_data msg = {0}; ++ struct udevice *dev; ++ ++ ffa_ret = uclass_first_device_err(UCLASS_FFA, &dev); ++ if (ffa_ret) { ++ log_err("Cannot find FF-A bus device, err (%d)\n", ffa_ret); ++ efi_ret = EFI_DEVICE_ERROR; ++ goto out; ++ } ++ ++ msg.data0 = PREP_SEPROXY_SVC_ID(CORSTONE1000_SEPROXY_UPDATE_SVC_ID) | ++ PREP_SEPROXY_EVT(CORSTONE1000_UBOOT_EFI_STARTED_EVT); ++ ++ msg.data1 = FFA_MEM_HANDLE_INVALID; ++ msg.data2 = FFA_MEM_HANDLE_INVALID; ++ ++ ffa_ret = ffa_sync_send_receive(dev, CORSTONE1000_SEPROXY_PART_ID, &msg, 0); ++ if (ffa_ret) { ++ log_err("Cannot notify SE Proxy SP, err (%d)\n", ffa_ret); ++ efi_ret = EFI_NO_RESPONSE; ++ goto out; ++ } ++ ++ log_debug("SE Proxy SP notified\n"); ++ ++out: ++ return efi_ret; ++} +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0024-corstone1000-adjust-boot-bank-and-kernel-location.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0024-corstone1000-adjust-boot-bank-and-kernel-location.patch deleted file mode 100644 index 66c6c665..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0024-corstone1000-adjust-boot-bank-and-kernel-location.patch +++ /dev/null @@ -1,33 +0,0 @@ -From b15518faa5eba9ffb9da4d6e17d8ab4bb8e69f27 Mon Sep 17 00:00:00 2001 -From: Rui Miguel Silva -Date: Wed, 1 Feb 2023 16:17:21 +0000 -Subject: [PATCH] corstone1000: adjust boot bank and kernel location - -Adjust in the env boot script the address of the -bootbank with the new gpt layout, and also the -kernel partition address. Please be aware that -this is hack and needs a proper fix, since the -offset of the kernel partition is not fixed, -but for the propose of PoC it is enough for testing. - -Upstream-Status: Pending -Signed-off-by: Rui Miguel Silva ---- - board/armltd/corstone1000/corstone1000.env | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/board/armltd/corstone1000/corstone1000.env b/board/armltd/corstone1000/corstone1000.env -index b24ff07fc6..a6ee496221 100644 ---- a/board/armltd/corstone1000/corstone1000.env -+++ b/board/armltd/corstone1000/corstone1000.env -@@ -1,8 +1,8 @@ - /* SPDX-License-Identifier: GPL-2.0+ */ - - usb_pgood_delay=250 --boot_bank_flag=0x08002000 --kernel_addr_bank_0=0x083EE000 -+boot_bank_flag=0x08005006 -+kernel_addr_bank_0=0x08280000 - kernel_addr_bank_1=0x0936E000 - retrieve_kernel_load_addr= - if itest.l *${boot_bank_flag} == 0; then diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0024-fwu_arm_psa-corstone1000-Set-Boot0001-for-on-disk-FW.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0024-fwu_arm_psa-corstone1000-Set-Boot0001-for-on-disk-FW.patch new file mode 100644 index 00000000..2584183a --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0024-fwu_arm_psa-corstone1000-Set-Boot0001-for-on-disk-FW.patch @@ -0,0 +1,59 @@ +From 259e9c11412c89a528a18d7ae34f770914c122a4 Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Fri, 2 May 2025 15:42:56 +0100 +Subject: [PATCH 24/36] fwu_arm_psa: corstone1000: Set Boot0001 for on-disk FWU + +Set Boot0001 to point to the ESP partition path + +On-disk FWU requires setting the boot option to where the +EFI System Partition (ESP) is so U-Boot's capsule driver +can detect the ESP partition and start the FWU. + +Corstone-1000 supports on-disk FWU on FVP. +The ESP partition is at mmc 1:1 and is accessible with boot option 1. + +To avoid setting manually Boot0001 at factory level, Boot0001 is +set in the bootcmd. So, before starting the on-disk FWU, the bootcmd +will be executed and Boot0001 will be set automatically. + +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20250702152528.1180414-1-abdellatif.elkhlifi@arm.com/] +--- + board/armltd/corstone1000/corstone1000.env | 8 ++++++++ + configs/corstone1000_defconfig | 2 +- + 2 files changed, 9 insertions(+), 1 deletion(-) + +diff --git a/board/armltd/corstone1000/corstone1000.env b/board/armltd/corstone1000/corstone1000.env +index ee318b1b1c3..6e631b12bc2 100644 +--- a/board/armltd/corstone1000/corstone1000.env ++++ b/board/armltd/corstone1000/corstone1000.env +@@ -1,5 +1,13 @@ + /* SPDX-License-Identifier: GPL-2.0+ */ + ++/* ++ * Copyright 2023, 2025 Arm Limited and/or its affiliates ++ */ ++ + usb_pgood_delay=250 + boot_bank_flag=0x08005006 + kernel_addr_r=0x88200000 ++prepare_ondisk_fwu= ++ if mmc dev 1; then ++ efidebug boot add -B 1 OnDiskFWU mmc 1:1 / ; ++ fi; +diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig +index d52d39a0b36..e02fb7cca67 100644 +--- a/configs/corstone1000_defconfig ++++ b/configs/corstone1000_defconfig +@@ -25,7 +25,7 @@ CONFIG_DISTRO_DEFAULTS=y + CONFIG_BOOTDELAY=3 + CONFIG_USE_BOOTARGS=y + CONFIG_BOOTARGS="console=ttyAMA0 loglevel=9 ip=dhcp earlyprintk" +-CONFIG_BOOTCOMMAND="echo Loading kernel from $kernel_addr to memory ... ; unzip $kernel_addr 0x90000000; loadm 0x90000000 $kernel_addr_r $filesize; usb start; usb reset; run distro_bootcmd; bootefi $kernel_addr_r $fdtcontroladdr;" ++CONFIG_BOOTCOMMAND="echo Loading kernel from $kernel_addr to memory ... ; unzip $kernel_addr 0x90000000; loadm 0x90000000 $kernel_addr_r $filesize; usb start; usb reset; run prepare_ondisk_fwu ; run distro_bootcmd; bootefi $kernel_addr_r $fdtcontroladdr;" + CONFIG_CONSOLE_RECORD=y + CONFIG_SYS_CBSIZE=512 + CONFIG_LOGLEVEL=7 +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0025-corstone1000-add-nvmxip-fwu-mdata-and-gpt-options.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0025-corstone1000-add-nvmxip-fwu-mdata-and-gpt-options.patch deleted file mode 100644 index c9e050a4..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0025-corstone1000-add-nvmxip-fwu-mdata-and-gpt-options.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 085b51e1545e905b4ba87c529954f31067032eaa Mon Sep 17 00:00:00 2001 -From: Rui Miguel Silva -Date: Mon, 17 Jul 2023 17:33:52 +0100 -Subject: [PATCH] corstone1000: add nvmxip, fwu-mdata and gpt options - -Enable the newest features: nvmxip, fwu-metadata and -gpt. Commands to print the partition info, gpt info -and fwu metadata will be available. - -Upstream-Status: Pending -Signed-off-by: Rui Miguel Silva ---- - configs/corstone1000_defconfig | 21 ++++++++++++++------- - 1 file changed, 14 insertions(+), 7 deletions(-) - -diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig -index a92668389a..4c75a01818 100644 ---- a/configs/corstone1000_defconfig -+++ b/configs/corstone1000_defconfig -@@ -15,7 +15,7 @@ CONFIG_DISTRO_DEFAULTS=y - CONFIG_BOOTDELAY=3 - CONFIG_USE_BOOTARGS=y - CONFIG_BOOTARGS="console=ttyAMA0 loglevel=9 ip=dhcp earlyprintk" --CONFIG_BOOTCOMMAND="run retrieve_kernel_load_addr; echo Loading kernel from $kernel_addr to memory ... ; unzip $kernel_addr 0x90000000; loadm 0x90000000 $kernel_addr_r 0xf00000; usb start; usb reset; run distro_bootcmd; bootefi $kernel_addr_r $fdtcontroladdr;" -+CONFIG_BOOTCOMMAND="echo Loading kernel from $kernel_addr to memory ... ; unzip $kernel_addr 0x90000000; loadm 0x90000000 $kernel_addr_r 0xf00000; usb start; usb reset; run distro_bootcmd; bootefi $kernel_addr_r $fdtcontroladdr;" - CONFIG_CONSOLE_RECORD=y - CONFIG_LOGLEVEL=7 - # CONFIG_DISPLAY_CPUINFO is not set -@@ -23,11 +23,15 @@ CONFIG_LOGLEVEL=7 - CONFIG_SYS_MAXARGS=64 - CONFIG_SYS_CBSIZE=512 - # CONFIG_CMD_CONSOLE is not set -+CONFIG_CMD_FWU_METADATA=y - CONFIG_CMD_BOOTZ=y - CONFIG_SYS_BOOTM_LEN=0x800000 - # CONFIG_CMD_XIMG is not set -+CONFIG_CMD_GPT=y -+# CONFIG_RANDOM_UUID is not set - CONFIG_CMD_LOADM=y - # CONFIG_CMD_LOADS is not set -+CONFIG_CMD_MMC=y - CONFIG_CMD_USB=y - # CONFIG_CMD_SETEXPR is not set - # CONFIG_CMD_NFS is not set -@@ -41,12 +45,7 @@ CONFIG_NET_RANDOM_ETHADDR=y - CONFIG_REGMAP=y - CONFIG_MISC=y - CONFIG_CLK=y --CONFIG_CMD_MMC=y --CONFIG_DM_MMC=y - CONFIG_ARM_PL180_MMCI=y --CONFIG_MMC_SDHCI_ADMA_HELPERS=y --CONFIG_MMC_WRITE=y --CONFIG_DM_GPIO=y - CONFIG_PHYLIB=y - CONFIG_PHY_SMSC=y - CONFIG_SMC911X=y -@@ -65,4 +64,12 @@ CONFIG_FFA_SHARED_MM_BUF_OFFSET=0 - CONFIG_FFA_SHARED_MM_BUF_ADDR=0x02000000 - CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y - CONFIG_EFI_CAPSULE_FIRMWARE_FIT=y --CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y -+CONFIG_FWU_NUM_IMAGES_PER_BANK=4 -+CONFIG_FWU_MDATA=y -+CONFIG_FWU_MDATA_GPT_BLK=y -+CONFIG_SYSRESET=y -+CONFIG_EFI_CAPSULE_ON_DISK=y -+CONFIG_EFI_IGNORE_OSINDICATIONS=y -+CONFIG_FWU_MULTI_BANK_UPDATE=y -+# CONFIG_TOOLS_MKEFICAPSULE is not set -+CONFIG_DM_GPIO=y -\ No newline at end of file diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0026-nvmxip-move-header-to-include.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0026-nvmxip-move-header-to-include.patch deleted file mode 100644 index 46734385..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0026-nvmxip-move-header-to-include.patch +++ /dev/null @@ -1,39 +0,0 @@ -From e7db287eb8bda80465d0c11cbb41acc798bb9fc6 Mon Sep 17 00:00:00 2001 -From: Rui Miguel Silva -Date: Fri, 9 Jun 2023 13:31:53 +0100 -Subject: [PATCH] nvmxip: move header to include - -Move header to include to allow external code -to get the internal bdev structures to access -block device operations. - -as at it, just add the UCLASS_NVMXIP string -so we get the correct output in partitions -listing. - -Upstream-Status: Pending -Signed-off-by: Rui Miguel Silva ---- - disk/part.c | 3 +++ - {drivers/mtd/nvmxip => include}/nvmxip.h | 0 - 2 files changed, 3 insertions(+) - rename {drivers/mtd/nvmxip => include}/nvmxip.h (100%) - -diff --git a/disk/part.c b/disk/part.c -index 35300df590..f57dce7a29 100644 ---- a/disk/part.c -+++ b/disk/part.c -@@ -271,6 +271,9 @@ static void print_part_header(const char *type, struct blk_desc *dev_desc) - case UCLASS_NVME: - puts ("NVMe"); - break; -+ case UCLASS_NVMXIP: -+ puts ("NVMXIP"); -+ break; - case UCLASS_PVBLOCK: - puts("PV BLOCK"); - break; -diff --git a/drivers/mtd/nvmxip/nvmxip.h b/include/nvmxip.h -similarity index 100% -rename from drivers/mtd/nvmxip/nvmxip.h -rename to include/nvmxip.h diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0027-corstone1000-set-kernel_addr-based-on-boot_idx.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0027-corstone1000-set-kernel_addr-based-on-boot_idx.patch deleted file mode 100644 index 352873f9..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0027-corstone1000-set-kernel_addr-based-on-boot_idx.patch +++ /dev/null @@ -1,132 +0,0 @@ -From ae098fd5c47f6d805b356c892558a85d571bed67 Mon Sep 17 00:00:00 2001 -From: Rui Miguel Silva -Date: Tue, 18 Jul 2023 12:14:47 +0100 -Subject: [PATCH] corstone1000: set kernel_addr based on boot_idx - -We need to distinguish between boot banks and from which -partition to load the kernel+initramfs to memory. - -For that, fetch the boot index, fetch the correspondent -partition, calculate the correct kernel address and -then set the env variable kernel_addr with that value. - -Upstream-Status: Pending -Signed-off-by: Rui Miguel Silva ---- - board/armltd/corstone1000/corstone1000.c | 58 +++++++++++++++++++++- - board/armltd/corstone1000/corstone1000.env | 8 --- - configs/corstone1000_defconfig | 1 + - 3 files changed, 58 insertions(+), 9 deletions(-) - -diff --git a/board/armltd/corstone1000/corstone1000.c b/board/armltd/corstone1000/corstone1000.c -index ba6d024b80..a045262ebb 100644 ---- a/board/armltd/corstone1000/corstone1000.c -+++ b/board/armltd/corstone1000/corstone1000.c -@@ -5,15 +5,25 @@ - * Rui Miguel Silva - */ - -+#include - #include - #include - #include -+#include - #include - #include -+#include -+#include - #include - #include - #include - -+#define CORSTONE1000_KERNEL_PARTS 2 -+#define CORSTONE1000_KERNEL_PRIMARY "kernel_primary" -+#define CORSTONE1000_KERNEL_SECONDARY "kernel_secondary" -+ -+static int corstone1000_boot_idx; -+ - static struct mm_region corstone1000_mem_map[] = { - { - /* CVM */ -@@ -110,5 +120,51 @@ int dram_init_banksize(void) - - void fwu_plat_get_bootidx(uint *boot_idx) - { -- *boot_idx = 0; -+ *boot_idx = corstone1000_boot_idx; -+} -+ -+int board_late_init(void) -+{ -+ struct disk_partition part_info; -+ struct udevice *dev, *bdev; -+ struct nvmxip_plat *plat; -+ struct blk_desc *desc; -+ int ret; -+ -+ ret = uclass_first_device_err(UCLASS_NVMXIP, &dev); -+ if (ret < 0) { -+ log_err("Cannot find kernel device\n"); -+ return ret; -+ } -+ -+ plat = dev_get_plat(dev); -+ device_find_first_child(dev, &bdev); -+ desc = dev_get_uclass_plat(bdev); -+ ret = fwu_get_active_index(&corstone1000_boot_idx); -+ if (ret < 0) -+ log_err("corstone1000: failed to read boot index\n"); -+ -+ if (!corstone1000_boot_idx) -+ ret = part_get_info_by_name(desc, CORSTONE1000_KERNEL_PRIMARY, -+ &part_info); -+ else -+ ret = part_get_info_by_name(desc, CORSTONE1000_KERNEL_SECONDARY, -+ &part_info); -+ -+ if (ret < 0) { -+ log_err("failed to fetch kernel partition index: %d\n", -+ corstone1000_boot_idx); -+ return ret; -+ } -+ -+ ret = 0; -+ -+ ret |= env_set_hex("kernel_addr", plat->phys_base + -+ (part_info.start * part_info.blksz)); -+ ret |= env_set_hex("kernel_size", part_info.size * part_info.blksz); -+ -+ if (ret < 0) -+ log_err("failed to setup kernel addr and size\n"); -+ -+ return ret; - } -diff --git a/board/armltd/corstone1000/corstone1000.env b/board/armltd/corstone1000/corstone1000.env -index a6ee496221..ee318b1b1c 100644 ---- a/board/armltd/corstone1000/corstone1000.env -+++ b/board/armltd/corstone1000/corstone1000.env -@@ -2,12 +2,4 @@ - - usb_pgood_delay=250 - boot_bank_flag=0x08005006 --kernel_addr_bank_0=0x08280000 --kernel_addr_bank_1=0x0936E000 --retrieve_kernel_load_addr= -- if itest.l *${boot_bank_flag} == 0; then -- setenv kernel_addr $kernel_addr_bank_0; -- else -- setenv kernel_addr $kernel_addr_bank_1; -- fi; - kernel_addr_r=0x88200000 -diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig -index 4c75a01818..0232131a11 100644 ---- a/configs/corstone1000_defconfig -+++ b/configs/corstone1000_defconfig -@@ -20,6 +20,7 @@ CONFIG_CONSOLE_RECORD=y - CONFIG_LOGLEVEL=7 - # CONFIG_DISPLAY_CPUINFO is not set - # CONFIG_DISPLAY_BOARDINFO is not set -+CONFIG_BOARD_LATE_INIT=y - CONFIG_SYS_MAXARGS=64 - CONFIG_SYS_CBSIZE=512 - # CONFIG_CMD_CONSOLE is not set diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0028-corstone1000-boot-index-from-active.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0028-corstone1000-boot-index-from-active.patch deleted file mode 100644 index fee77974..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0028-corstone1000-boot-index-from-active.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 67c439b974da80208962c1c7f0a1291908e23a30 Mon Sep 17 00:00:00 2001 -From: Rui Miguel Silva -Date: Mon, 27 Feb 2023 14:40:13 +0000 -Subject: [PATCH] corstone1000: boot index from active - -In our platform, the Secure Enclave is the one who control -all the boot tries and status, so, every time we get here -we know that the we are booting from the active index. - -Upstream-Status: Pending -Signed-off-by: Rui Miguel Silva -Signed-off-by: Abdellatif El Khlifi ---- - board/armltd/corstone1000/corstone1000.c | 11 ++++++++++- - 1 file changed, 10 insertions(+), 1 deletion(-) - -diff --git a/board/armltd/corstone1000/corstone1000.c b/board/armltd/corstone1000/corstone1000.c -index a045262ebb..53c65506d5 100644 ---- a/board/armltd/corstone1000/corstone1000.c -+++ b/board/armltd/corstone1000/corstone1000.c -@@ -120,7 +120,16 @@ int dram_init_banksize(void) - - void fwu_plat_get_bootidx(uint *boot_idx) - { -- *boot_idx = corstone1000_boot_idx; -+ int ret; -+ -+ /* -+ * in our platform, the Secure Enclave is the one who control -+ * all the boot tries and status, so, every time we get here -+ * we know that the we are booting from the active index -+ */ -+ ret = fwu_get_active_index(boot_idx); -+ if (ret < 0) -+ log_err("corstone1000: failed to read active index err %d\n", ret); - } - - int board_late_init(void) diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0029-corstone1000-enable-PSCI-reset.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0029-corstone1000-enable-PSCI-reset.patch deleted file mode 100644 index f722f81c..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0029-corstone1000-enable-PSCI-reset.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 8b7260db2b0c560b430657f801dd102fb2b141de Mon Sep 17 00:00:00 2001 -From: Emekcan Aras -Date: Tue, 18 Jul 2023 12:19:17 +0100 -Subject: [PATCH] corstone1000: enable PSCI reset - -Even though corstone1000 does not implement entire PSCI APIs,it relies on -PSCI reset interface for the system reset. U-boot change the config name, so we -need to enable it again. - -Upstream-Status: Pending [Not submitted to upstream yet] -Signed-off-by: Emekcan Aras ---- - configs/corstone1000_defconfig | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig -index 0232131a11..ccd558cfce 100644 ---- a/configs/corstone1000_defconfig -+++ b/configs/corstone1000_defconfig -@@ -73,4 +73,5 @@ CONFIG_EFI_CAPSULE_ON_DISK=y - CONFIG_EFI_IGNORE_OSINDICATIONS=y - CONFIG_FWU_MULTI_BANK_UPDATE=y - # CONFIG_TOOLS_MKEFICAPSULE is not set --CONFIG_DM_GPIO=y -\ No newline at end of file -+CONFIG_DM_GPIO=y -+CONFIG_SYSRESET_PSCI=y -\ No newline at end of file diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0030-Enable-EFI-set-get-time-services.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0030-Enable-EFI-set-get-time-services.patch deleted file mode 100644 index 015ed439..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0030-Enable-EFI-set-get-time-services.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 03f53356a5b8b30b981ab7a16c6f48ca7fffe489 Mon Sep 17 00:00:00 2001 -From: Gowtham Suresh Kumar -Date: Tue, 18 Jul 2023 12:21:39 +0100 -Subject: [PATCH] Enable EFI set/get time services - -SetTime_Conf and SetTime_Func tests in UEFI SCT test suite of ACS -fails with unsupported return value. CONFIG_EFI_SET_TIME and -CONFIG_EFI_GET_TIME config values are added to enable these EFI -services. - -Upstream-Status: Pending [Not submitted to upstream yet] -Signed-off-by: Gowtham Suresh Kumar -Signed-off-by: Abdellatif El Khlifi ---- - configs/corstone1000_defconfig | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig -index ccd558cfce..a0af413de8 100644 ---- a/configs/corstone1000_defconfig -+++ b/configs/corstone1000_defconfig -@@ -74,4 +74,6 @@ CONFIG_EFI_IGNORE_OSINDICATIONS=y - CONFIG_FWU_MULTI_BANK_UPDATE=y - # CONFIG_TOOLS_MKEFICAPSULE is not set - CONFIG_DM_GPIO=y --CONFIG_SYSRESET_PSCI=y -\ No newline at end of file -+CONFIG_SYSRESET_PSCI=y -+CONFIG_EFI_SET_TIME=y -+CONFIG_EFI_GET_TIME=y diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0031-corstone1000-detect-inflated-kernel-size.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0031-corstone1000-detect-inflated-kernel-size.patch deleted file mode 100644 index 8ee20aaa..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0031-corstone1000-detect-inflated-kernel-size.patch +++ /dev/null @@ -1,26 +0,0 @@ -From affde70e4ba728b0ce855f53501bdb5caa8afa6d Mon Sep 17 00:00:00 2001 -From: Abdellatif El Khlifi -Date: Fri, 11 Aug 2023 10:41:19 +0100 -Subject: [PATCH] corstone1000: detect inflated kernel size - -use filesize variable set by unzip command - -Upstream-Status: Pending [Not submitted to upstream yet] -Signed-off-by: Abdellatif El Khlifi ---- - configs/corstone1000_defconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig -index a0af413de8..5b0b2ac3bf 100644 ---- a/configs/corstone1000_defconfig -+++ b/configs/corstone1000_defconfig -@@ -15,7 +15,7 @@ CONFIG_DISTRO_DEFAULTS=y - CONFIG_BOOTDELAY=3 - CONFIG_USE_BOOTARGS=y - CONFIG_BOOTARGS="console=ttyAMA0 loglevel=9 ip=dhcp earlyprintk" --CONFIG_BOOTCOMMAND="echo Loading kernel from $kernel_addr to memory ... ; unzip $kernel_addr 0x90000000; loadm 0x90000000 $kernel_addr_r 0xf00000; usb start; usb reset; run distro_bootcmd; bootefi $kernel_addr_r $fdtcontroladdr;" -+CONFIG_BOOTCOMMAND="echo Loading kernel from $kernel_addr to memory ... ; unzip $kernel_addr 0x90000000; loadm 0x90000000 $kernel_addr_r $filesize; usb start; usb reset; run distro_bootcmd; bootefi $kernel_addr_r $fdtcontroladdr;" - CONFIG_CONSOLE_RECORD=y - CONFIG_LOGLEVEL=7 - # CONFIG_DISPLAY_CPUINFO is not set diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0032-corstone1000-ESRT-add-unique-firmware-GUID.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0032-corstone1000-ESRT-add-unique-firmware-GUID.patch deleted file mode 100644 index 1c34f338..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0032-corstone1000-ESRT-add-unique-firmware-GUID.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 1f1e0c35c9a11e956a8dc10002d17a497de947e3 Mon Sep 17 00:00:00 2001 -From: Anusmita Dutta Mazumder -Date: Tue, 8 Aug 2023 10:24:39 +0000 -Subject: [PATCH] corstone1000: ESRT: add unique firmware GUID - -Add unique Corstone-1000 firmware GUID - -Upstream-Status: Pending [Not submitted to upstream yet] -Signed-off-by: Anusmita Dutta Mazumder ---- - lib/efi_loader/efi_firmware.c | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c -index c6ab6e2182..7792a6aa83 100644 ---- a/lib/efi_loader/efi_firmware.c -+++ b/lib/efi_loader/efi_firmware.c -@@ -20,12 +20,12 @@ - #define FMP_PAYLOAD_HDR_SIGNATURE SIGNATURE_32('M', 'S', 'S', '1') - - #if CONFIG_IS_ENABLED(TARGET_CORSTONE1000) --#define EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID \ -- EFI_GUID(0xe2bb9c06, 0x70e9, 0x4b14, 0x97, 0xa3, \ -- 0x5a, 0x79, 0x13, 0x17, 0x6e, 0x3f) -+/* Firmware GUID */ -+#define EFI_CORSTONE1000_FIRMWARE_GUID \ -+ EFI_GUID(0x989f3a4e, 0x46e0, 0x4cd0, 0x98, 0x77, \ -+ 0xa2, 0x5c, 0x70, 0xc0, 0x13, 0x29) - -- const efi_guid_t efi_firmware_image_type_uboot_raw = -- EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID; -+efi_guid_t corstone1000_firmware_guid = EFI_CORSTONE1000_FIRMWARE_GUID; - - static efi_status_t efi_corstone1000_img_info_get ( - efi_uintn_t *image_info_size, -@@ -353,7 +353,7 @@ efi_status_t EFIAPI efi_firmware_get_image_info( - descriptor_version, descriptor_count, - descriptor_size, - package_version, package_version_name, -- &efi_firmware_image_type_uboot_raw); -+ &corstone1000_firmware_guid); - #else - ret = efi_fill_image_desc_array(image_info_size, image_info, - descriptor_version, descriptor_count, diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0033-dt-Provide-a-way-to-remove-non-compliant-nodes-and-p.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0033-dt-Provide-a-way-to-remove-non-compliant-nodes-and-p.patch deleted file mode 100644 index ecc35675..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0033-dt-Provide-a-way-to-remove-non-compliant-nodes-and-p.patch +++ /dev/null @@ -1,134 +0,0 @@ -From f098724d2a59bf5c265a81c5b8767563c6c2d8de Mon Sep 17 00:00:00 2001 -From: Sughosh Ganu -Date: Thu, 21 Sep 2023 14:13:42 +0100 -Subject: [PATCH] dt: Provide a way to remove non-compliant nodes and - properties - -Add a function which is registered to spy for a EVT_FT_FIXUP event, -and removes the non upstreamed nodes and properties from the -devicetree before it gets passed to the OS. - -This allows removing entire nodes, or specific properties under nodes -from the devicetree. The required nodes and properties can be -registered for removal through the DT_NON_COMPLIANT_PURGE and -DT_NON_COMPLIANT_PURGE_LIST macros. - -Signed-off-by: Sughosh Ganu -Upstream-Status: Submitted [RFC: https://lore.kernel.org/u-boot/aca7e6fa-2dec-a7c5-e47e-84c5ffa6f9b7@gmx.de/T/#m16d14ee960427cc88066bdcdd76f0a26738bb66d] ---- - include/dt-structs.h | 11 +++++++ - lib/Makefile | 1 + - lib/dt_purge.c | 73 ++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 85 insertions(+) - create mode 100644 lib/dt_purge.c - -diff --git a/include/dt-structs.h b/include/dt-structs.h -index fa1622cb1d..f535c60471 100644 ---- a/include/dt-structs.h -+++ b/include/dt-structs.h -@@ -57,3 +57,14 @@ struct phandle_2_arg { - #endif - - #endif -+ -+struct dt_non_compliant_purge { -+ const char *node_path; -+ const char *prop; -+}; -+ -+#define DT_NON_COMPLIANT_PURGE(__name) \ -+ ll_entry_declare(struct dt_non_compliant_purge, __name, dt_purge) -+ -+#define DT_NON_COMPLIANT_PURGE_LIST(__name) \ -+ ll_entry_declare_list(struct dt_non_compliant_purge, __name, dt_purge) -diff --git a/lib/Makefile b/lib/Makefile -index 8d8ccc8bbc..82a906daa0 100644 ---- a/lib/Makefile -+++ b/lib/Makefile -@@ -37,6 +37,7 @@ endif - obj-y += crc8.o - obj-y += crc16.o - obj-y += crc16-ccitt.o -+obj-y += dt_purge.o - obj-$(CONFIG_ERRNO_STR) += errno_str.o - obj-$(CONFIG_FIT) += fdtdec_common.o - obj-$(CONFIG_TEST_FDTDEC) += fdtdec_test.o -diff --git a/lib/dt_purge.c b/lib/dt_purge.c -new file mode 100644 -index 0000000000..f893ba9796 ---- /dev/null -+++ b/lib/dt_purge.c -@@ -0,0 +1,73 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+/* -+ * Copyright (c) 2023, Linaro Limited -+ */ -+ -+#include -+#include -+#include -+ -+#include -+ -+/** -+ * dt_non_compliant_purge() - Remove non-upstreamed nodes and properties -+ * from the DT -+ * @ctx: Context for event -+ * @event: Event to process -+ * -+ * Iterate through an array of DT nodes and properties, and remove them -+ * from the device-tree before the DT gets handed over to the kernel. -+ * These are nodes and properties which do not have upstream bindings -+ * and need to be purged before being handed over to the kernel. -+ * -+ * If both the node and property are specified, delete the property. If -+ * only the node is specified, delete the entire node, including it's -+ * subnodes, if any. -+ * -+ * Return: 0 if OK, -ve on error -+ */ -+static int dt_non_compliant_purge(void *ctx, struct event *event) -+{ -+ int nodeoff = 0; -+ int err = 0; -+ void *fdt; -+ const struct event_ft_fixup *fixup = &event->data.ft_fixup; -+ struct dt_non_compliant_purge *purge_entry; -+ struct dt_non_compliant_purge *purge_start = -+ ll_entry_start(struct dt_non_compliant_purge, dt_purge); -+ int nentries = ll_entry_count(struct dt_non_compliant_purge, dt_purge); -+ -+ if (fixup->images) -+ return 0; -+ -+ fdt = fixup->tree.fdt; -+ for (purge_entry = purge_start; purge_entry != purge_start + nentries; -+ purge_entry++) { -+ nodeoff = fdt_path_offset(fdt, purge_entry->node_path); -+ if (nodeoff < 0) { -+ log_debug("Error (%d) getting node offset for %s\n", -+ nodeoff, purge_entry->node_path); -+ continue; -+ } -+ -+ if (purge_entry->prop) { -+ err = fdt_delprop(fdt, nodeoff, purge_entry->prop); -+ if (err < 0 && err != -FDT_ERR_NOTFOUND) { -+ log_debug("Error (%d) deleting %s\n", -+ err, purge_entry->prop); -+ goto out; -+ } -+ } else { -+ err = fdt_del_node(fdt, nodeoff); -+ if (err) { -+ log_debug("Error (%d) trying to delete node %s\n", -+ err, purge_entry->node_path); -+ goto out; -+ } -+ } -+ } -+ -+out: -+ return err; -+} -+EVENT_SPY(EVT_FT_FIXUP, dt_non_compliant_purge); diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0034-bootefi-Call-the-EVT_FT_FIXUP-event-handler.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0034-bootefi-Call-the-EVT_FT_FIXUP-event-handler.patch deleted file mode 100644 index 54363e99..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0034-bootefi-Call-the-EVT_FT_FIXUP-event-handler.patch +++ /dev/null @@ -1,53 +0,0 @@ -From ff83070da7d1f547fc640e8446251f8e1e4ffc33 Mon Sep 17 00:00:00 2001 -From: Sughosh Ganu -Date: Thu, 21 Sep 2023 14:15:13 +0100 -Subject: [PATCH] bootefi: Call the EVT_FT_FIXUP event handler - -The bootefi command passes the devicetree to the kernel through the -EFI config table. Call the event handlers for fixing the devicetree -before jumping into the kernel. This removes any devicetree nodes -and/or properties that are specific only to U-Boot, and are not to be -passed to the OS. - -Signed-off-by: Sughosh Ganu -Upstream-Status: Submitted [RFC: https://lore.kernel.org/u-boot/aca7e6fa-2dec-a7c5-e47e-84c5ffa6f9b7@gmx.de/T/#m16d14ee960427cc88066bdcdd76f0a26738bb66d] ---- - cmd/bootefi.c | 18 ++++++++++++++++++ - 1 file changed, 18 insertions(+) - -diff --git a/cmd/bootefi.c b/cmd/bootefi.c -index 5c0afec154..f9588b66c7 100644 ---- a/cmd/bootefi.c -+++ b/cmd/bootefi.c -@@ -237,6 +237,23 @@ static void *get_config_table(const efi_guid_t *guid) - return NULL; - } - -+/** -+ * event_notify_dt_fixup() - call ft_fixup event -+ * -+ * @fdt: address of the device tree to be passed to the kernel -+ * through the configuration table -+ * Return: None -+ */ -+static void event_notify_dt_fixup(void *fdt) -+{ -+ int ret; -+ struct event_ft_fixup fixup = {0}; -+ -+ fixup.tree.fdt = fdt; -+ ret = event_notify(EVT_FT_FIXUP, &fixup, sizeof(fixup)); -+ if (ret) -+ printf("Error: %d: FDT Fixup event failed\n", ret); -+} - #endif /* !CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE) */ - - /** -@@ -318,6 +335,7 @@ efi_status_t efi_install_fdt(void *fdt) - efi_carve_out_dt_rsv(fdt); - - efi_try_purge_kaslr_seed(fdt); -+ event_notify_dt_fixup(fdt); - - if (CONFIG_IS_ENABLED(EFI_TCG2_PROTOCOL_MEASURE_DTB)) { - ret = efi_tcg2_measure_dtb(fdt); diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0035-corstone1000-purge-U-Boot-specific-DT-nodes.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0035-corstone1000-purge-U-Boot-specific-DT-nodes.patch deleted file mode 100644 index 090f32c5..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0035-corstone1000-purge-U-Boot-specific-DT-nodes.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 49e3463a397b61e859df5e1a383f82d64c1e4f3f Mon Sep 17 00:00:00 2001 -From: Abdellatif El Khlifi -Date: Thu, 21 Sep 2023 15:24:34 +0100 -Subject: [PATCH] corstone1000: purge U-Boot specific DT nodes - -Remove U-Boot specific DT nodes before passing the DT to Linux - -This is needed to pass SystemReady IR 2.0 dt-schema tests - -Signed-off-by: Abdellatif El Khlifi -Upstream-Status: Pending [RFC: https://lore.kernel.org/u-boot/aca7e6fa-2dec-a7c5-e47e-84c5ffa6f9b7@gmx.de/T/#m16d14ee960427cc88066bdcdd76f0a26738bb66d] ---- - board/armltd/corstone1000/corstone1000.c | 15 +++++++++++++++ - 1 file changed, 15 insertions(+) - -diff --git a/board/armltd/corstone1000/corstone1000.c b/board/armltd/corstone1000/corstone1000.c -index 53c65506d5..e3c0e5bf50 100644 ---- a/board/armltd/corstone1000/corstone1000.c -+++ b/board/armltd/corstone1000/corstone1000.c -@@ -9,6 +9,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -18,6 +19,20 @@ - #include - #include - -+/* remove the DT nodes not needed in Linux */ -+DT_NON_COMPLIANT_PURGE_LIST(foo) = { -+ { .node_path = "/fwu-mdata" }, -+ { .node_path = "/nvmxip-qspi@08000000" }, -+ { .node_path = "/soc/mailbox@1b820000" }, -+ { .node_path = "/soc/mailbox@1b830000" }, -+ { .node_path = "/soc/mhu@1b000000" }, -+ { .node_path = "/soc/mhu@1b010000" }, -+ { .node_path = "/soc/mhu@1b020000" }, -+ { .node_path = "/soc/mhu@1b030000" }, -+ { .node_path = "/soc/client" }, -+ { .node_path = "/soc/extsys@1A010310" }, -+}; -+ - #define CORSTONE1000_KERNEL_PARTS 2 - #define CORSTONE1000_KERNEL_PRIMARY "kernel_primary" - #define CORSTONE1000_KERNEL_SECONDARY "kernel_secondary" diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0036-corstone1000-add-signature-device-tree-overlay.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0036-corstone1000-add-signature-device-tree-overlay.patch deleted file mode 100644 index 62713abf..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0036-corstone1000-add-signature-device-tree-overlay.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 57e2230470c32bf2c6206813bcdfc9ce30b70c1d Mon Sep 17 00:00:00 2001 -From: Emekcan Aras -Date: Wed, 13 Sep 2023 13:20:15 +0100 -Subject: [PATCH] corstone1000: add signature device tree overlay - -Adds signature device tree overlay. - -Signed-off-by: Emekcan Aras -Upstream-Status: Pending [Not submitted to upstream yet] ---- - arch/arm/dts/corstone1000.dtsi | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/arch/arm/dts/corstone1000.dtsi b/arch/arm/dts/corstone1000.dtsi -index 1e0ec075e4..077673dd44 100644 ---- a/arch/arm/dts/corstone1000.dtsi -+++ b/arch/arm/dts/corstone1000.dtsi -@@ -111,6 +111,10 @@ - fwu-mdata-store = <&nvmxip>; - }; - -+ signature { -+ capsule-key = /incbin/("../../../CRT.esl"); -+ }; -+ - soc { - compatible = "simple-bus"; - #address-cells = <1>; diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0037-corstone1000-enable-authenticated-capsule-config.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0037-corstone1000-enable-authenticated-capsule-config.patch deleted file mode 100644 index 65d5e151..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0037-corstone1000-enable-authenticated-capsule-config.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 509645079f3dbb6b14e920102bea75c2f408d195 Mon Sep 17 00:00:00 2001 -From: Emekcan Aras -Date: Wed, 13 Sep 2023 13:52:02 +0100 -Subject: [PATCH] corstone1000: enable authenticated capsule config - -Enables authenticated capsule update config for corstone1000. - -Signed-off-by: Emekcan Aras -Upstream-Status: Pending [Not submitted to upstream yet] ---- - configs/corstone1000_defconfig | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig -index 5b0b2ac3bf..2de3f5d7b3 100644 ---- a/configs/corstone1000_defconfig -+++ b/configs/corstone1000_defconfig -@@ -70,6 +70,7 @@ CONFIG_FWU_MDATA=y - CONFIG_FWU_MDATA_GPT_BLK=y - CONFIG_SYSRESET=y - CONFIG_EFI_CAPSULE_ON_DISK=y -+CONFIG_EFI_CAPSULE_AUTHENTICATE=y - CONFIG_EFI_IGNORE_OSINDICATIONS=y - CONFIG_FWU_MULTI_BANK_UPDATE=y - # CONFIG_TOOLS_MKEFICAPSULE is not set diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0038-corstone1000-introduce-EFI-authenticated-capsule-upd.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0038-corstone1000-introduce-EFI-authenticated-capsule-upd.patch deleted file mode 100644 index ae409321..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0038-corstone1000-introduce-EFI-authenticated-capsule-upd.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 3f06f148656fbe238ed8bd93f9631a95668f9406 Mon Sep 17 00:00:00 2001 -From: Emekcan Aras -Date: Wed, 13 Sep 2023 13:55:08 +0100 -Subject: [PATCH] corstone1000: introduce EFI authenticated capsule update - -Introduces EFI authenticated capsule update for corstone1000. Corstone1000 -implements platform-specific capsule update mechanism in u-bootdue to the SoC -design. This patch add authenticated capsule update mechanism to the -platform-specific firmware-update routine. - -Signed-off-by: Emekcan Aras -Upstream-Status: Inappropriate [Redesign of Capsule update interface is required] ---- - lib/efi_loader/efi_capsule.c | 39 ++++++++++++++++++++++++++++++++++++ - 1 file changed, 39 insertions(+) - -diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c -index 6a06605ad9..e1c78d8c1c 100644 ---- a/lib/efi_loader/efi_capsule.c -+++ b/lib/efi_loader/efi_capsule.c -@@ -820,6 +820,12 @@ efi_status_t __efi_runtime EFIAPI efi_update_capsule( - u64 scatter_gather_list) - { - struct efi_capsule_header *capsule; -+ struct efi_firmware_management_capsule_header *capsule_header; -+ struct efi_firmware_management_capsule_image_header *image; -+ size_t image_binary_size; -+ size_t tmp_capsule_payload_size=0; -+ void *tmp_capsule_payload=NULL; -+ void *image_binary; - unsigned int i; - efi_status_t ret; - -@@ -859,6 +865,39 @@ efi_status_t __efi_runtime EFIAPI efi_update_capsule( - goto out; - } - -+ capsule_header = (void *)capsule + capsule->header_size; -+ image = (void *)capsule_header + capsule_header->item_offset_list[0]; -+ if (IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE) && -+ !(image->image_capsule_support & -+ CAPSULE_SUPPORT_AUTHENTICATION)) { -+ /* no signature */ -+ log_err("Corstone1000: Capsule authentication flag check failed. Aborting update\n"); -+ ret = EFI_SECURITY_VIOLATION; -+ goto out; -+ } -+ -+ image_binary = (void *)image + sizeof(*image); -+ image_binary_size = image->update_image_size; -+ if (IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE) && -+ (image->image_capsule_support & -+ CAPSULE_SUPPORT_AUTHENTICATION)){ -+ ret = efi_capsule_authenticate(image_binary, image_binary_size, -+ &tmp_capsule_payload, -+ &tmp_capsule_payload_size); -+ -+ if (ret == EFI_SECURITY_VIOLATION) { -+ log_err("Corstone1000: Capsule authentication check failed. Aborting update\n"); -+ goto out; -+ } else if (ret != EFI_SUCCESS) { -+ goto out; -+ } -+ -+ log_debug("Corstone1000: Capsule authentication successful\n"); -+ } else { -+ log_debug("Corstone1000: Capsule authentication disabled. "); -+ log_debug("Corstone1000: Updating capsule without authenticating.\n"); -+ } -+ - /* copy the data to the contiguous buffer */ - efi_memcpy_runtime(corstone1000_capsule_buf, capsule, capsule->capsule_image_size); - diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0039-enables-ondisk-capsule-update-feature.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0039-enables-ondisk-capsule-update-feature.patch deleted file mode 100644 index cd002aca..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0039-enables-ondisk-capsule-update-feature.patch +++ /dev/null @@ -1,33 +0,0 @@ -From e5057a10641a7c84186bcbbcd12ee904300ebc53 Mon Sep 17 00:00:00 2001 -From: Emekcan Aras -Date: Fri, 13 Oct 2023 15:19:32 +0100 -Subject: [PATCH] Enables on-disk capsule update feature - -Enables on-disk capsule update feature for corstone1000. - -Signed-off-by: Emekcan Aras -Upstream-Status: Inappropriate [Redesign of Capsule update interface is required] ---- - lib/efi_loader/efi_capsule.c | 5 ++++ - 1 file changed, 5 insertions(+) - -diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c -index e1c78d8c1c..63e4c06e58 100644 ---- a/lib/efi_loader/efi_capsule.c -+++ b/lib/efi_loader/efi_capsule.c -@@ -1499,7 +1499,12 @@ efi_status_t efi_launch_capsules(void) - index = 0; - ret = efi_capsule_read_file(files[i], &capsule); - if (ret == EFI_SUCCESS) { -+ #if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) -+ /* capsule update only supports 1 image and no scatter gather list for corstone1000 */ -+ efi_update_capsule(&capsule, 1, 0); -+ #elif - ret = efi_capsule_update_firmware(capsule); -+ #endif - if (ret != EFI_SUCCESS) { - log_err("Applying capsule %ls failed.\n", - files[i]); --- -2.25.1 - diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0040-fix-runtime-capsule-update-flags-checks.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0040-fix-runtime-capsule-update-flags-checks.patch deleted file mode 100644 index b1d400d7..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0040-fix-runtime-capsule-update-flags-checks.patch +++ /dev/null @@ -1,56 +0,0 @@ -From a83aa9e1b8f6e312da82e54614fbca498493c34d Mon Sep 17 00:00:00 2001 -From: Emekcan Aras -Date: Thu, 19 Oct 2023 14:56:55 +0100 -Subject: [PATCH] fix runtime capsule update flags checks for corstone1000 - -Fixes capsule update flags checks in capsule update as these checks are missing -in the platform-specific capsule-update implementation in corstone1000. - -Signed-off-by: Emekcan Aras -Upstream-Status: Inappropriate [Redesign of Capsule update interface is required] ---- - lib/efi_loader/efi_capsule.c | 28 ++++++++++++++++++++++++++++ - 1 file changed, 28 insertions(+) - -diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c -index 307bcfd73c..34507482b7 100644 ---- a/lib/efi_loader/efi_capsule.c -+++ b/lib/efi_loader/efi_capsule.c -@@ -854,6 +854,34 @@ efi_status_t __efi_runtime EFIAPI efi_update_capsule( - continue; - } - -+ /* According to UEFI specs when the flag is CAPSULE_FLAGS_PERSIST_ACROSS_RESET, -+ ScatterGatherList can't be NULL.*/ -+ if ((capsule->flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) && -+ scatter_gather_list == 0){ -+ ret = EFI_INVALID_PARAMETER; -+ goto out; -+ } -+ -+ /*According to UEFI specs a capsule which has the CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE -+ * flag must have CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its -+ * header as well.*/ -+ if (capsule->flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE){ -+ if(!(capsule->flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET)){ -+ ret = EFI_INVALID_PARAMETER; -+ goto out; -+ } -+ } -+ -+ /* According to UEFI specs, a capsule which has the CAPSULE_FLAGS_INITIATE_RESET -+ * Flag must have CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its -+ * header as well.*/ -+ if (capsule->flags & CAPSULE_FLAGS_INITIATE_RESET){ -+ if(!(capsule->flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET)){ -+ ret = EFI_INVALID_PARAMETER; -+ goto out; -+ } -+ } -+ - log_debug("Capsule[%d] (guid:%pUs)\n", - i, &capsule->capsule_guid); - --- -2.25.1 - diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0041-scatter-gather-flag-workaround.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0041-scatter-gather-flag-workaround.patch deleted file mode 100644 index 8ce82a75..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0041-scatter-gather-flag-workaround.patch +++ /dev/null @@ -1,39 +0,0 @@ -From abc3b43996198012498abe5777cfeedde4538a90 Mon Sep 17 00:00:00 2001 -From: Emekcan Aras -Date: Mon, 6 Nov 2023 14:52:05 +0000 -Subject: [PATCH] workaround for scatter gather flag check for corstone1000 - -This workaround passes 1 as scatter_gather_list value to pass the NULL checks -for scatter_gather_list while CAPSULE_FLAGS_PERSIST_ACROSS_RESET flag is set -(which is introduced lately to align with UEFI specs). Since these flag checks -are not implemented in u-boot properly and corstone1000 does not support -scatter_gather_list during capsule update, this patch will skip the check only -for on-disk capsule update. - -Signed-off-by: Emekcan Aras -Upstream-Status: Inappropriate [Redesign of Capsule update interface is required] ---- - lib/efi_loader/efi_capsule.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c -index a7d70acf2a..efbedce460 100644 ---- a/lib/efi_loader/efi_capsule.c -+++ b/lib/efi_loader/efi_capsule.c -@@ -1530,8 +1530,11 @@ efi_status_t efi_launch_capsules(void) - ret = efi_capsule_read_file(files[i], &capsule); - if (ret == EFI_SUCCESS) { - #if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) -- /* capsule update only supports 1 image and no scatter gather list for corstone1000 */ -- efi_update_capsule(&capsule, 1, 0); -+ /* capsule update only supports 1 image and use of scatter_gather_list -+ * is not implemented for corstone1000 passing 1 to pass -+ * the NULL flag checks. This should will be fixed with -+ * new capsule update design*/ -+ ret = efi_update_capsule(&capsule, 1, 1); - #elif - ret = efi_capsule_update_firmware(capsule); - #endif --- -2.25.1 - diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0042-corstone1000-enable-virtio-net-support.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0042-corstone1000-enable-virtio-net-support.patch deleted file mode 100644 index 58b21a9c..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0042-corstone1000-enable-virtio-net-support.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 46a1faf3687764ddf1567455de39482b72e50725 Mon Sep 17 00:00:00 2001 -From: Emekcan Aras -Date: Wed, 15 Nov 2023 16:04:06 +0000 -Subject: [PATCH] corstone1000: enable virtio-net support - -Adds virtio-net support in corstone1000-fvp. - -Signed-off-by: Emekcan Aras -Upstream-Status: Pending [Not submitted to upstream yet] ---- - arch/arm/dts/corstone1000-fvp.dts | 6 ++++++ - board/armltd/corstone1000/corstone1000.c | 24 +++++++++++++++++++++++- - configs/corstone1000_defconfig | 2 ++ - 3 files changed, 31 insertions(+), 1 deletion(-) - -diff --git a/arch/arm/dts/corstone1000-fvp.dts b/arch/arm/dts/corstone1000-fvp.dts -index 26b0f1b3ce..8e54a40113 100644 ---- a/arch/arm/dts/corstone1000-fvp.dts -+++ b/arch/arm/dts/corstone1000-fvp.dts -@@ -21,6 +21,12 @@ - reg-io-width = <2>; - }; - -+ virtio: virtio-net@40400000 { -+ compatible = "virtio,mmio"; -+ reg = <0x40400000 0x10000>; -+ interrupts = <145>; -+ }; -+ - vmmc_v3_3d: fixed_v3_3d { - compatible = "regulator-fixed"; - regulator-name = "vmmc_supply"; -diff --git a/board/armltd/corstone1000/corstone1000.c b/board/armltd/corstone1000/corstone1000.c -index e3c0e5bf50..ef74dc9032 100644 ---- a/board/armltd/corstone1000/corstone1000.c -+++ b/board/armltd/corstone1000/corstone1000.c -@@ -18,6 +18,7 @@ - #include - #include - #include -+#include - - /* remove the DT nodes not needed in Linux */ - DT_NON_COMPLIANT_PURGE_LIST(foo) = { -@@ -101,6 +102,14 @@ static struct mm_region corstone1000_mem_map[] = { - .size = 0x80000000UL, - .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | - PTE_BLOCK_INNER_SHARE -+ }, { -+ /* ethernet */ -+ .virt = 0x40400000UL, -+ .phys = 0x40400000UL, -+ .size = 0x00100000UL, -+ .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | -+ PTE_BLOCK_NON_SHARE | -+ PTE_BLOCK_PXN | PTE_BLOCK_UXN - }, { - /* List terminator */ - 0, -@@ -150,10 +159,23 @@ void fwu_plat_get_bootidx(uint *boot_idx) - int board_late_init(void) - { - struct disk_partition part_info; -- struct udevice *dev, *bdev; -+ struct udevice *dev, *bdev,*virtio_bus, *virtio_child;; - struct nvmxip_plat *plat; - struct blk_desc *desc; - int ret; -+ const char *cmp_dtb = DEVICE_TREE; -+ -+ if (!strcmp(cmp_dtb, "corstone1000-fvp")) { -+ ret = uclass_first_device_err(UCLASS_VIRTIO, &virtio_bus); -+ if (!virtio_bus){ -+ log_err("Cannot find virtio device\n"); -+ return ret; -+ } -+ while (virtio_bus) { -+ device_foreach_child_probe(virtio_child, virtio_bus); -+ uclass_next_device(&virtio_bus); -+ } -+ } - - ret = uclass_first_device_err(UCLASS_NVMXIP, &dev); - if (ret < 0) { -diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig -index 2de3f5d7b3..8770b474e2 100644 ---- a/configs/corstone1000_defconfig -+++ b/configs/corstone1000_defconfig -@@ -78,3 +78,5 @@ CONFIG_DM_GPIO=y - CONFIG_SYSRESET_PSCI=y - CONFIG_EFI_SET_TIME=y - CONFIG_EFI_GET_TIME=y -+CONFIG_VIRTIO_NET=y -+CONFIG_VIRTIO_MMIO=y diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0043-firmware-psci-Fix-bind_smccc_features-psci-check.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0043-firmware-psci-Fix-bind_smccc_features-psci-check.patch deleted file mode 100644 index 946caa24..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0043-firmware-psci-Fix-bind_smccc_features-psci-check.patch +++ /dev/null @@ -1,57 +0,0 @@ -From fda3d08d17050a8b338ef4288d20389788b5b7e6 Mon Sep 17 00:00:00 2001 -From: Weizhao Ouyang -Date: Mon, 4 Mar 2024 14:42:40 +0000 -Subject: [PATCH] firmware: psci: Fix bind_smccc_features psci check - -Message-ID: <20240304144242.11666-2-o451686892@gmail.com> (raw) -In-Reply-To: <20240304144242.11666-1-o451686892@gmail.com> - -According to PSCI specification DEN0022F, PSCI_FEATURES is used to check -whether the SMCCC is implemented by discovering SMCCC_VERSION. - -Signed-off-by: Weizhao Ouyang -Signed-off-by: Bence Balogh -Upstream-Status: Submitted [https://lore.kernel.org/all/20240304144242.11666-2-o451686892@gmail.com/] ---- - drivers/firmware/psci.c | 5 ++++- - include/linux/arm-smccc.h | 6 ++++++ - 2 files changed, 10 insertions(+), 1 deletion(-) - -diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c -index c6b9efab41..03544d76ed 100644 ---- a/drivers/firmware/psci.c -+++ b/drivers/firmware/psci.c -@@ -135,10 +135,13 @@ static int bind_smccc_features(struct udevice *dev, int psci_method) - PSCI_VERSION_MAJOR(psci_0_2_get_version()) == 0) - return 0; - -- if (request_psci_features(ARM_SMCCC_ARCH_FEATURES) == -+ if (request_psci_features(ARM_SMCCC_VERSION) == - PSCI_RET_NOT_SUPPORTED) - return 0; - -+ if (invoke_psci_fn(ARM_SMCCC_VERSION, 0, 0, 0) < ARM_SMCCC_VERSION_1_1) -+ return 0; -+ - if (psci_method == PSCI_METHOD_HVC) - pdata->invoke_fn = smccc_invoke_hvc; - else -diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h -index f44e9e8f93..da3d29aabe 100644 ---- a/include/linux/arm-smccc.h -+++ b/include/linux/arm-smccc.h -@@ -55,8 +55,14 @@ - #define ARM_SMCCC_QUIRK_NONE 0 - #define ARM_SMCCC_QUIRK_QCOM_A6 1 /* Save/restore register a6 */ - -+#define ARM_SMCCC_VERSION 0x80000000 - #define ARM_SMCCC_ARCH_FEATURES 0x80000001 - -+#define ARM_SMCCC_VERSION_1_0 0x10000 -+#define ARM_SMCCC_VERSION_1_1 0x10001 -+#define ARM_SMCCC_VERSION_1_2 0x10002 -+#define ARM_SMCCC_VERSION_1_3 0x10003 -+ - #define ARM_SMCCC_RET_NOT_SUPPORTED ((unsigned long)-1) - - #ifndef __ASSEMBLY__ diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0044-corstone1000-set-unique-GUID-for-fvp-and-mps3.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0044-corstone1000-set-unique-GUID-for-fvp-and-mps3.patch deleted file mode 100644 index 86b1071c..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0044-corstone1000-set-unique-GUID-for-fvp-and-mps3.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 6dc17c01df592f685636e34ad8bb0a6ecb994e15 Mon Sep 17 00:00:00 2001 -From: Anusmita Dutta Mazumder -Date: Thu, 21 Mar 2024 20:34:46 +0000 -Subject: [PATCH] corstone1000: set unique GUID for fvp and mps3 - -This patch sets unique GUID for Corstone1000 FVP and MPS3 - -Upstream-Status: Inappropriate [Redesign of Capsule update interface is required] -Signed-off-by: Anusmita Dutta Mazumder ---- - lib/efi_loader/efi_firmware.c | 15 +++++++++++++-- - 1 file changed, 13 insertions(+), 2 deletions(-) - -diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c -index 7792a6aa83..1e49f79864 100644 ---- a/lib/efi_loader/efi_firmware.c -+++ b/lib/efi_loader/efi_firmware.c -@@ -16,16 +16,19 @@ - - #include - #include -+#include - - #define FMP_PAYLOAD_HDR_SIGNATURE SIGNATURE_32('M', 'S', 'S', '1') - - #if CONFIG_IS_ENABLED(TARGET_CORSTONE1000) - /* Firmware GUID */ --#define EFI_CORSTONE1000_FIRMWARE_GUID \ -+#define EFI_CORSTONE1000_FIRMWARE_GUID_FVP \ - EFI_GUID(0x989f3a4e, 0x46e0, 0x4cd0, 0x98, 0x77, \ - 0xa2, 0x5c, 0x70, 0xc0, 0x13, 0x29) - --efi_guid_t corstone1000_firmware_guid = EFI_CORSTONE1000_FIRMWARE_GUID; -+#define EFI_CORSTONE1000_FIRMWARE_GUID_MPS3 \ -+ EFI_GUID(0xdf1865d1, 0x90fb, 0x4d59, 0x9c, 0x38, \ -+ 0xc9, 0xf2, 0xc1, 0xbb, 0xa8, 0xcc) - - static efi_status_t efi_corstone1000_img_info_get ( - efi_uintn_t *image_info_size, -@@ -334,6 +337,14 @@ efi_status_t EFIAPI efi_firmware_get_image_info( - u16 **package_version_name) - { - efi_status_t ret; -+ efi_guid_t corstone1000_firmware_guid; -+ const char *cmp_dtb = DEVICE_TREE; -+ -+ if (!strcmp(cmp_dtb, "corstone1000-fvp")) { -+ corstone1000_firmware_guid = (efi_guid_t)EFI_CORSTONE1000_FIRMWARE_GUID_FVP; -+ } else { -+ corstone1000_firmware_guid = (efi_guid_t)EFI_CORSTONE1000_FIRMWARE_GUID_MPS3; -+ } - - EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this, - image_info_size, image_info, --- -2.38.1 - diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0045-efi-corstone1000-fwu-update-RPC-ABI.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0045-efi-corstone1000-fwu-update-RPC-ABI.patch deleted file mode 100644 index 00fc1f07..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0045-efi-corstone1000-fwu-update-RPC-ABI.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 7c25404d64ef8efec63c154ce38b0bb38845680f Mon Sep 17 00:00:00 2001 -From: Bence Balogh -Date: Tue, 5 Dec 2023 20:23:55 +0100 -Subject: [PATCH] efi: corstone1000: fwu: update RPC ABI - -The Trusted Services RPC protocol format changed: the -data has to be placed in w3 and the memory handle has -to be placed in w4-w5. - -Signed-off-by: Bence Balogh -Upstream-Status: Pending [Not submitted to upstream yet] ---- - lib/efi_loader/efi_capsule.c | 14 +++++++++++--- - lib/efi_loader/efi_setup.c | 14 +++++++++++--- - 2 files changed, 22 insertions(+), 6 deletions(-) - -diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c -index f3326b1f67..1d966e3f26 100644 ---- a/lib/efi_loader/efi_capsule.c -+++ b/lib/efi_loader/efi_capsule.c -@@ -790,12 +790,20 @@ static int __efi_runtime efi_corstone1000_buffer_ready_event(u32 capsule_image_s - } - - /* -- * setting the buffer ready event arguments in register w4: -+ * setting the buffer ready event arguments in register w3: - * - capsule update interface ID (31:16) - * - the buffer ready event ID (15:0) - */ -- msg.data1 = PREP_SEPROXY_SVC_ID(CORSTONE1000_SEPROXY_UPDATE_SVC_ID) | -- PREP_SEPROXY_EVT(CORSTONE1000_BUFFER_READY_EVT); /* w4 */ -+ msg.data0 = PREP_SEPROXY_SVC_ID(CORSTONE1000_SEPROXY_UPDATE_SVC_ID) | -+ PREP_SEPROXY_EVT(CORSTONE1000_BUFFER_READY_EVT); /* w3 */ -+ -+ /* -+ * setting the memory handle fields to -+ * FFA_MEM_HANDLE_INVALID (0xFFFF_FFFF_FFFF_FFFF) -+ * to signal that there is no shared memory used -+ */ -+ msg.data1 = 0xFFFFFFFF; /* w4 */ -+ msg.data2 = 0xFFFFFFFF; /* w5 */ - - return ffa_sync_send_receive(dev, CORSTONE1000_SEPROXY_PART_ID, &msg, 0); - } -diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c -index d20568c1c8..c31e74532f 100644 ---- a/lib/efi_loader/efi_setup.c -+++ b/lib/efi_loader/efi_setup.c -@@ -157,12 +157,20 @@ static int efi_corstone1000_uboot_efi_started_event(void) - } - - /* -- * setting the kernel started event arguments: -+ * setting the kernel started event arguments in register w3:: - * setting capsule update interface ID(31:16) - * the kernel started event ID(15:0) - */ -- msg.data1 = PREP_SEPROXY_SVC_ID(CORSTONE1000_SEPROXY_UPDATE_SVC_ID) | -- PREP_SEPROXY_EVT(CORSTONE1000_UBOOT_EFI_STARTED_EVT); /* w4 */ -+ msg.data0 = PREP_SEPROXY_SVC_ID(CORSTONE1000_SEPROXY_UPDATE_SVC_ID) | -+ PREP_SEPROXY_EVT(CORSTONE1000_UBOOT_EFI_STARTED_EVT); /* w3 */ -+ -+ /* -+ * setting the memory handle fields to -+ * FFA_MEM_HANDLE_INVALID (0xFFFF_FFFF_FFFF_FFFF) -+ * to signal that there is no shared memory used -+ */ -+ msg.data1 = 0xFFFFFFFF; /* w4 */ -+ msg.data2 = 0xFFFFFFFF; /* w5 */ - - return ffa_sync_send_receive(dev, CORSTONE1000_SEPROXY_PART_ID, &msg, 0); - } --- -2.25.1 - diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0046-Corstone1000-Change-MMCOMM-buffer-location.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0046-Corstone1000-Change-MMCOMM-buffer-location.patch deleted file mode 100644 index 500db81e..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0046-Corstone1000-Change-MMCOMM-buffer-location.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 7721d33dfc87b40db72cefa399c46b25b1255247 Mon Sep 17 00:00:00 2001 -From: Emekcan Aras -Date: Wed, 3 Apr 2024 14:02:42 +0100 -Subject: [PATCH] Corstone1000: Change MMCOMM buffer location - -MM Communicate buffer is accessed by normal world but at the moment -it's allocated in the secure ram. This moves mm communicate buffer -to the DDR and also fixes the capsule buffer size since it cannot be -more than the bank size. - -Signed-off-by: Emekcan Aras -Upstream-Status: Pending [Not submitted to upstream yet] ---- - configs/corstone1000_defconfig | 2 +- - include/configs/corstone1000.h | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig -index 8770b474e2..ae164be030 100644 ---- a/configs/corstone1000_defconfig -+++ b/configs/corstone1000_defconfig -@@ -62,7 +62,7 @@ CONFIG_NVMXIP_QSPI=y - CONFIG_EFI_MM_COMM_TEE=y - CONFIG_FFA_SHARED_MM_BUF_SIZE=4096 - CONFIG_FFA_SHARED_MM_BUF_OFFSET=0 --CONFIG_FFA_SHARED_MM_BUF_ADDR=0x02000000 -+CONFIG_FFA_SHARED_MM_BUF_ADDR=0x81FFF000 - CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y - CONFIG_EFI_CAPSULE_FIRMWARE_FIT=y - CONFIG_FWU_NUM_IMAGES_PER_BANK=4 -diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h -index 8622565a87..fe5b064c85 100644 ---- a/include/configs/corstone1000.h -+++ b/include/configs/corstone1000.h -@@ -31,7 +31,7 @@ - #define PREP_SEPROXY_EVT(x) (FIELD_PREP(PREP_SEPROXY_EVT_MASK, (x))) - - /* Size in 4KB pages of the EFI capsule buffer */ --#define CORSTONE1000_CAPSULE_BUFFER_SIZE (8192) /* 32 MB */ -+#define CORSTONE1000_CAPSULE_BUFFER_SIZE (4096) /* 16 MB */ - - /* Capsule GUID */ - #define EFI_CORSTONE1000_CAPSULE_ID_GUID \ --- -2.25.1 - - diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0047-corstone1000-dts-add-external-system-node.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0047-corstone1000-dts-add-external-system-node.patch deleted file mode 100644 index 1c873001..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0047-corstone1000-dts-add-external-system-node.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 03df80671f1f2102b04baa810b59ffb6edaece0b Mon Sep 17 00:00:00 2001 -From: Abdellatif El Khlifi -Date: Mon, 18 Mar 2024 17:00:56 +0000 -Subject: [PATCH] corstone1000: dts: add external system node - -add the external system node - -Signed-off-by: Abdellatif El Khlifi -Upstream-Status: Pending [Not submitted to upstream yet] ---- - arch/arm/dts/corstone1000.dtsi | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/arch/arm/dts/corstone1000.dtsi b/arch/arm/dts/corstone1000.dtsi -index 077673dd44..5cc4c26bac 100644 ---- a/arch/arm/dts/corstone1000.dtsi -+++ b/arch/arm/dts/corstone1000.dtsi -@@ -122,6 +122,13 @@ - interrupt-parent = <&gic>; - ranges; - -+ extsys0: remoteproc@1a010310 { -+ compatible = "arm,corstone1000-extsys"; -+ reg = <0x1a010310 0x4>, <0x1a010314 0x4>; -+ reg-names = "reset-control", "reset-status"; -+ firmware-name = "es_flashfw.elf"; -+ }; -+ - timer@1a220000 { - compatible = "arm,armv7-timer-mem"; - reg = <0x1a220000 0x1000>; --- -2.25.1 - diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0048-corstone1000-Enable-UEFI-Secure-boot.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0048-corstone1000-Enable-UEFI-Secure-boot.patch deleted file mode 100644 index 1e91249a..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0048-corstone1000-Enable-UEFI-Secure-boot.patch +++ /dev/null @@ -1,28 +0,0 @@ -From b2ef7318686d13cfa2ac76d6f2d69c17135328df Mon Sep 17 00:00:00 2001 -From: Harsimran Singh Tungal -Date: Thu, 11 Apr 2024 13:35:54 +0000 -Subject: [PATCH] corstone1000: Enable UEFI Secure boot - -Enable secure boot and related configurations for corstone1000 - -Upstream-Status: Pending [Not submitted to upstream yet] -Signed-off-by: Harsimran Singh Tungal ---- - configs/corstone1000_defconfig | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig -index 8770b474e2..0ecba096d5 100644 ---- a/configs/corstone1000_defconfig -+++ b/configs/corstone1000_defconfig -@@ -80,3 +80,7 @@ CONFIG_EFI_SET_TIME=y - CONFIG_EFI_GET_TIME=y - CONFIG_VIRTIO_NET=y - CONFIG_VIRTIO_MMIO=y -+CONFIG_EFI_SECURE_BOOT=y -+CONFIG_FIT_SIGNATURE=y -+CONFIG_EFI_LOADER=y -+CONFIG_CMD_NVEDIT_EFI=y --- -2.34.1 - diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0049-corstone1000-Add-secondary-cores-cpu-nodes-for-FVP.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0049-corstone1000-Add-secondary-cores-cpu-nodes-for-FVP.patch deleted file mode 100644 index 0e90f577..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0049-corstone1000-Add-secondary-cores-cpu-nodes-for-FVP.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 68708d6b4953f58a0484b9a83efa8318747cea80 Mon Sep 17 00:00:00 2001 -From: Harsimran Singh Tungal -Date: Thu, 9 May 2024 14:16:55 +0000 -Subject: [PATCH] arm: dts: corstone1000: enable secondary cores for FVP - -Add the secondary cores nodes in the dts file - -Upstream-Status: Submitted [https://lore.kernel.org/all/20240612100421.47938-1-harsimransingh.tungal@arm.com/] -Signed-off-by: Harsimran Singh Tungal ---- - arch/arm/dts/corstone1000-fvp.dts | 25 +++++++++++++++++++++++++ - arch/arm/dts/corstone1000.dtsi | 2 +- - 2 files changed, 26 insertions(+), 1 deletion(-) - -diff --git a/arch/arm/dts/corstone1000-fvp.dts b/arch/arm/dts/corstone1000-fvp.dts -index 26b0f1b3ce..3076fb9f34 100644 ---- a/arch/arm/dts/corstone1000-fvp.dts -+++ b/arch/arm/dts/corstone1000-fvp.dts -@@ -49,3 +49,28 @@ - clock-names = "smclk", "apb_pclk"; - }; - }; -+ -+&cpus { -+ cpu1: cpu@1 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a35"; -+ reg = <0x1>; -+ enable-method = "psci"; -+ next-level-cache = <&L2_0>; -+ }; -+ cpu2: cpu@2 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a35"; -+ reg = <0x2>; -+ enable-method = "psci"; -+ next-level-cache = <&L2_0>; -+ }; -+ cpu3: cpu@3 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a35"; -+ reg = <0x3>; -+ enable-method = "psci"; -+ next-level-cache = <&L2_0>; -+ }; -+}; -+ -diff --git a/arch/arm/dts/corstone1000.dtsi b/arch/arm/dts/corstone1000.dtsi -index 1e0ec075e4..5d9d95b21c 100644 ---- a/arch/arm/dts/corstone1000.dtsi -+++ b/arch/arm/dts/corstone1000.dtsi -@@ -21,7 +21,7 @@ - stdout-path = "serial0:115200n8"; - }; - -- cpus { -+ cpus: cpus { - #address-cells = <1>; - #size-cells = <0>; - --- -2.25.1 - diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0050-fwu-Use-metadata-v2.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0050-fwu-Use-metadata-v2.patch deleted file mode 100644 index 4388db44..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0050-fwu-Use-metadata-v2.patch +++ /dev/null @@ -1,105 +0,0 @@ -From 54b407fc74c9989c72ab7a571395d8793b409514 Mon Sep 17 00:00:00 2001 -From: Bence Balogh -Date: Wed, 3 Jul 2024 16:38:22 +0200 -Subject: [PATCH] fwu: Use metadata v2 - -The mdata structure was modified to use the v2 and did the minimal -necessarry changes to make it build without errors. This way the -U-Boot metadata is aligned with the TF-A and TF-M structs. - -Upstream-Status: Inappropriate -[This is done correctly upstream but using the upstream patches would -require too many backported patches. The merge commit of the upstream -changes is 7e52d6ccfb76e2afc2d183b357abe2a2e2f948cf.] -Signed-off-by: Bence Balogh ---- - cmd/fwu_mdata.c | 2 +- - include/fwu_mdata.h | 17 ++++++++++++++++- - lib/fwu_updates/fwu.c | 8 ++++---- - 3 files changed, 21 insertions(+), 6 deletions(-) - -diff --git a/cmd/fwu_mdata.c b/cmd/fwu_mdata.c -index f04af27de6..73374dca8b 100644 ---- a/cmd/fwu_mdata.c -+++ b/cmd/fwu_mdata.c -@@ -27,7 +27,7 @@ static void print_mdata(struct fwu_mdata *mdata) - - printf("\tImage Info\n"); - for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) { -- img_entry = &mdata->img_entry[i]; -+ img_entry = &mdata->fw_desc.img_entry[i]; - printf("\nImage Type Guid: %pUL\n", - &img_entry->image_type_uuid); - printf("Location Guid: %pUL\n", &img_entry->location_uuid); -diff --git a/include/fwu_mdata.h b/include/fwu_mdata.h -index c61221a917..6a0eb7dce9 100644 ---- a/include/fwu_mdata.h -+++ b/include/fwu_mdata.h -@@ -40,6 +40,16 @@ struct fwu_image_entry { - struct fwu_image_bank_info img_bank_info[CONFIG_FWU_NUM_BANKS]; - } __packed; - -+struct fwu_fw_store_desc { -+ uint8_t num_banks; -+ uint8_t reserved; -+ uint16_t num_images; -+ uint16_t img_entry_size; -+ uint16_t bank_info_entry_size; -+ -+ struct fwu_image_entry img_entry[CONFIG_FWU_NUM_IMAGES_PER_BANK]; -+} __packed; -+ - /** - * struct fwu_mdata - FWU metadata structure for multi-bank updates - * @crc32: crc32 value for the FWU metadata -@@ -60,8 +70,13 @@ struct fwu_mdata { - uint32_t version; - uint32_t active_index; - uint32_t previous_active_index; -+ uint32_t metadata_size; -+ uint16_t desc_offset; -+ uint16_t reserved1; -+ uint8_t bank_state[4]; -+ uint32_t reserved2; - -- struct fwu_image_entry img_entry[CONFIG_FWU_NUM_IMAGES_PER_BANK]; -+ struct fwu_fw_store_desc fw_desc; - } __packed; - - #endif /* _FWU_MDATA_H_ */ -diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c -index 5313d07302..488c9cc661 100644 ---- a/lib/fwu_updates/fwu.c -+++ b/lib/fwu_updates/fwu.c -@@ -131,7 +131,7 @@ static int in_trial_state(struct fwu_mdata *mdata) - struct fwu_image_bank_info *img_bank_info; - - active_bank = mdata->active_index; -- img_entry = &mdata->img_entry[0]; -+ img_entry = &mdata->fw_desc.img_entry[0]; - for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) { - img_bank_info = &img_entry[i].img_bank_info[active_bank]; - if (!img_bank_info->accepted) { -@@ -418,8 +418,8 @@ int fwu_get_image_index(u8 *image_index) - */ - for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) { - if (!guidcmp(&image_type_id, -- &mdata.img_entry[i].image_type_uuid)) { -- img_entry = &mdata.img_entry[i]; -+ &mdata.fw_desc.img_entry[i].image_type_uuid)) { -+ img_entry = &mdata.fw_desc.img_entry[i]; - img_bank_info = &img_entry->img_bank_info[update_bank]; - image_guid = &img_bank_info->image_uuid; - ret = fwu_plat_get_alt_num(dev, image_guid, &alt_num); -@@ -512,7 +512,7 @@ static int fwu_clrset_image_accept(efi_guid_t *img_type_id, u32 bank, u8 action) - if (ret) - return ret; - -- img_entry = &mdata.img_entry[0]; -+ img_entry = &mdata.fw_desc.img_entry[0]; - for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) { - if (!guidcmp(&img_entry[i].image_type_uuid, img_type_id)) { - img_bank_info = &img_entry[i].img_bank_info[bank]; --- -2.25.1 - diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0051-corstone1000-purge-remoteproc-dts-node.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0051-corstone1000-purge-remoteproc-dts-node.patch deleted file mode 100644 index 3b0430c8..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0051-corstone1000-purge-remoteproc-dts-node.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 4e0ab7af882fcf498fd8beb4024ea024e6464cef Mon Sep 17 00:00:00 2001 -From: Harsimran Singh Tungal -Date: Wed, 14 Aug 2024 14:33:50 +0000 -Subject: [PATCH] corstone1000: purge remoteproc DTS node - -Purge remoteproc DTS node -This is done to remove the remote proc node from the DTS passed -to Linux from U-Boot because the device tree binding for remoteproc -has not been upstreamed yet. Existence of remoteproc DTS node in Linux -is causing dt-schema test for SystemReady-IR v2.0 certification to fail. - -Upstream-Status: Pending -Signed-off-by: Harsimran Singh Tungal ---- - board/armltd/corstone1000/corstone1000.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/board/armltd/corstone1000/corstone1000.c b/board/armltd/corstone1000/corstone1000.c -index ef74dc9032..d474fce1b2 100644 ---- a/board/armltd/corstone1000/corstone1000.c -+++ b/board/armltd/corstone1000/corstone1000.c -@@ -30,8 +30,7 @@ DT_NON_COMPLIANT_PURGE_LIST(foo) = { - { .node_path = "/soc/mhu@1b010000" }, - { .node_path = "/soc/mhu@1b020000" }, - { .node_path = "/soc/mhu@1b030000" }, -- { .node_path = "/soc/client" }, -- { .node_path = "/soc/extsys@1A010310" }, -+ { .node_path = "/soc/remoteproc@1a010310" }, - }; - - #define CORSTONE1000_KERNEL_PARTS 2 --- -2.34.1 - diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0052-reserve-memory-for-se-comm.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0052-reserve-memory-for-se-comm.patch deleted file mode 100644 index 73fdc4bd..00000000 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0052-reserve-memory-for-se-comm.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 8fdd91630f335b71e55e570a011f07b083c47dd6 Mon Sep 17 00:00:00 2001 -From: Emekcan Aras -Date: Mon, 10 Jul 2023 19:00:43 +0100 -Subject: [PATCH] arm-bsp/u-boot: Reserve memory for RSS comm pointer access protocol - -This memory was used by OpenAMP to establish communication between -the Secure Enclave and Trusted Services. After transitioning from -OpenAMP to RSE_COMMS, this shared memory is now configured for the -pointer access protocol in RSE_COMMS. - -Since this memory may be still used by a user-space application -in linux as U-Boot is passing an EFI memory map starting from -0x80000000, this memory range should be reserved as the -pointer access protocol may be enabled on corstone1000 in the future. - -Upstream-Status: Pending [Not submitted to upstream yet] -Signed-off-by: Emekcan Aras - ---- - arch/arm/dts/corstone1000.dtsi | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/arch/arm/dts/corstone1000.dtsi b/arch/arm/dts/corstone1000.dtsi -index 0f8ad255ce..a71b89c025 100644 ---- a/arch/arm/dts/corstone1000.dtsi -+++ b/arch/arm/dts/corstone1000.dtsi -@@ -45,6 +45,17 @@ - lba = <65536>; - }; - -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ smem_mem: smem_region@88000000 { -+ reg = <0x0 0x88000000 0x0 0x100000>; -+ no-map; -+ }; -+ }; -+ - gic: interrupt-controller@1c000000 { - compatible = "arm,gic-400"; - #interrupt-cells = <3>; --- -2.17.1 From patchwork Wed Jul 30 11:53:25 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harsimran Singh Tungal X-Patchwork-Id: 67734 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id DFA59C87FC9 for ; Wed, 30 Jul 2025 11:54:10 +0000 (UTC) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.web11.33479.1753876441797384472 for ; Wed, 30 Jul 2025 04:54:01 -0700 Authentication-Results: mx.groups.io; dkim=none (message not signed); spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: harsimransingh.tungal@arm.com) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 5F00B2681; Wed, 30 Jul 2025 04:53:53 -0700 (PDT) Received: from e132995.cambridge.arm.com (e132995.arm.com [10.1.25.25]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id A30353F66E; Wed, 30 Jul 2025 04:54:00 -0700 (PDT) From: Harsimran Singh Tungal To: meta-arm@lists.yoctoproject.org Cc: Abdellatif El Khlifi , Harsimran Singh Tungal Subject: [PATCH 11/13] arm-bsp/u-boot: corstone1000: Add rebased features patches Date: Wed, 30 Jul 2025 12:53:25 +0100 Message-Id: <20250730115327.3671160-12-harsimransingh.tungal@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250730115327.3671160-1-harsimransingh.tungal@arm.com> References: <20250730115327.3671160-1-harsimransingh.tungal@arm.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Wed, 30 Jul 2025 11:54:10 -0000 X-Groupsio-URL: https://lists.yoctoproject.org/g/meta-arm/message/6648 From: Abdellatif El Khlifi Add rebased patches on U-Boot v2025.04 Signed-off-by: Abdellatif El Khlifi Signed-off-by: Harsimran Singh Tungal --- .../u-boot/u-boot-corstone1000.inc | 21 +++ ...00-set-CONFIG_FFA_SHARED_MM_BUF_ADDR.patch | 30 ++++ ...0026-corstone1000-Enable-MMC-for-FVP.patch | 94 ++++++++++++ ...stone1000-Enable-secure-boot-configs.patch | 38 +++++ ...stone1000-Enable-EFI-set_time-config.patch | 35 +++++ ...e1000-Enable-set-print-EFI-variables.patch | 37 +++++ ...rstone1000-Enable-virtio-net-support.patch | 122 ++++++++++++++++ ...000-Fix-unrecognized-filesystem-type.patch | 33 +++++ ...one1000-dts-Add-external-system-node.patch | 34 +++++ ...ts-Reserve-memory-for-RSS-comm-point.patch | 50 +++++++ ...-to-remove-non-compliant-nodes-and-p.patch | 137 ++++++++++++++++++ ...-Call-the-EVT_FT_FIXUP-event-handler.patch | 58 ++++++++ ...e1000-Purge-U-Boot-specific-DT-nodes.patch | 41 ++++++ ...rstone1000-purge-remoteproc-DTS-node.patch | 32 ++++ 14 files changed, 762 insertions(+) create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0025-corstone1000-set-CONFIG_FFA_SHARED_MM_BUF_ADDR.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0026-corstone1000-Enable-MMC-for-FVP.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0027-corstone1000-Enable-secure-boot-configs.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0028-corstone1000-Enable-EFI-set_time-config.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0029-corstone1000-Enable-set-print-EFI-variables.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0030-corstone1000-Enable-virtio-net-support.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0031-arm-corstone1000-Fix-unrecognized-filesystem-type.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0032-corstone1000-dts-Add-external-system-node.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0033-arm-bsp-u-boot-dts-Reserve-memory-for-RSS-comm-point.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0034-dt-Provide-a-way-to-remove-non-compliant-nodes-and-p.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0035-bootefi-Call-the-EVT_FT_FIXUP-event-handler.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0036-corstone1000-Purge-U-Boot-specific-DT-nodes.patch create mode 100644 meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0037-corstone1000-purge-remoteproc-DTS-node.patch diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot-corstone1000.inc b/meta-arm-bsp/recipes-bsp/u-boot/u-boot-corstone1000.inc index e19034f7..fa98dc10 100644 --- a/meta-arm-bsp/recipes-bsp/u-boot/u-boot-corstone1000.inc +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot-corstone1000.inc @@ -42,6 +42,27 @@ SRC_URI:append = " \ file://0023-fwu_arm_psa-corstone1000-Notify-SE-Proxy-SP-on-ExitB.patch \ file://0024-fwu_arm_psa-corstone1000-Set-Boot0001-for-on-disk-FW.patch \ " +# Other features +SRC_URI:append = " \ + file://0025-corstone1000-set-CONFIG_FFA_SHARED_MM_BUF_ADDR.patch \ + file://0026-corstone1000-Enable-MMC-for-FVP.patch \ + file://0027-corstone1000-Enable-secure-boot-configs.patch \ + file://0028-corstone1000-Enable-EFI-set_time-config.patch \ + file://0029-corstone1000-Enable-set-print-EFI-variables.patch \ + file://0030-corstone1000-Enable-virtio-net-support.patch \ + file://0031-arm-corstone1000-Fix-unrecognized-filesystem-type.patch \ + file://0032-corstone1000-dts-Add-external-system-node.patch \ + file://0033-arm-bsp-u-boot-dts-Reserve-memory-for-RSS-comm-point.patch \ + " + +# Purging device tree nodes +SRC_URI:append = " \ + file://0034-dt-Provide-a-way-to-remove-non-compliant-nodes-and-p.patch \ + file://0035-bootefi-Call-the-EVT_FT_FIXUP-event-handler.patch \ + file://0036-corstone1000-Purge-U-Boot-specific-DT-nodes.patch \ + ${@bb.utils.contains('MACHINE_FEATURES', 'corstone1000-extsys', \ + '', 'file://0037-corstone1000-purge-remoteproc-DTS-node.patch' , d)} \ + " do_configure:append() { openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=CRT/ -keyout ${B}/CRT.key -out ${B}/corstone1000_defconfig/CRT.crt -nodes -days 365 diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0025-corstone1000-set-CONFIG_FFA_SHARED_MM_BUF_ADDR.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0025-corstone1000-set-CONFIG_FFA_SHARED_MM_BUF_ADDR.patch new file mode 100644 index 00000000..09557204 --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0025-corstone1000-set-CONFIG_FFA_SHARED_MM_BUF_ADDR.patch @@ -0,0 +1,30 @@ +From 41b50de6e4727731db95531fcd779a24a16dcccf Mon Sep 17 00:00:00 2001 +From: Emekcan Aras +Date: Thu, 20 Mar 2025 15:49:26 +0000 +Subject: [PATCH 25/36] corstone1000: set CONFIG_FFA_SHARED_MM_BUF_ADDR + +Set the MM communication buffer to a new address + +Signed-off-by: Emekcan Aras +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Pending [Not submitted to upstream yet] +--- + configs/corstone1000_defconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig +index e02fb7cca67..59962f7145e 100644 +--- a/configs/corstone1000_defconfig ++++ b/configs/corstone1000_defconfig +@@ -14,7 +14,7 @@ CONFIG_FWU_NUM_IMAGES_PER_BANK=4 + CONFIG_EFI_MM_COMM_TEE=y + CONFIG_FFA_SHARED_MM_BUF_SIZE=4096 + CONFIG_FFA_SHARED_MM_BUF_OFFSET=0 +-CONFIG_FFA_SHARED_MM_BUF_ADDR=0x02000000 ++CONFIG_FFA_SHARED_MM_BUF_ADDR=0x81FFF000 + CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y + CONFIG_EFI_CAPSULE_ON_DISK=y + CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0026-corstone1000-Enable-MMC-for-FVP.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0026-corstone1000-Enable-MMC-for-FVP.patch new file mode 100644 index 00000000..fa169159 --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0026-corstone1000-Enable-MMC-for-FVP.patch @@ -0,0 +1,94 @@ +From 7a2620d318490c96204bbc493b028253dc8e8f8c Mon Sep 17 00:00:00 2001 +From: Vishnu Banavath +Date: Thu, 20 Mar 2025 15:56:14 +0000 +Subject: [PATCH 26/36] corstone1000: Enable MMC for FVP + +Enable support mmc/sdcard for the corstone1000 FVP + +Signed-off-by: Vishnu Banavath +Signed-off-by: Rui Miguel Silva +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Pending [Not submitted to upstream yet] +--- + board/armltd/corstone1000/corstone1000.c | 16 ++++++++++++++++ + configs/corstone1000_defconfig | 5 ++++- + include/configs/corstone1000.h | 4 +++- + 3 files changed, 23 insertions(+), 2 deletions(-) + +diff --git a/board/armltd/corstone1000/corstone1000.c b/board/armltd/corstone1000/corstone1000.c +index 2532c5f10fa..9189640ef75 100644 +--- a/board/armltd/corstone1000/corstone1000.c ++++ b/board/armltd/corstone1000/corstone1000.c +@@ -208,6 +208,22 @@ static struct mm_region corstone1000_mem_map[] = { + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN ++ }, { ++ /* MMC0 */ ++ .virt = 0x40300000UL, ++ .phys = 0x40300000UL, ++ .size = 0x00100000UL, ++ .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | ++ PTE_BLOCK_NON_SHARE | ++ PTE_BLOCK_PXN | PTE_BLOCK_UXN ++ }, { ++ /* MMC1 */ ++ .virt = 0x50000000UL, ++ .phys = 0x50000000UL, ++ .size = 0x00100000UL, ++ .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | ++ PTE_BLOCK_NON_SHARE | ++ PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* OCVM */ + .virt = 0x80000000UL, +diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig +index 59962f7145e..4c562536a89 100644 +--- a/configs/corstone1000_defconfig ++++ b/configs/corstone1000_defconfig +@@ -6,6 +6,7 @@ CONFIG_SYS_MALLOC_LEN=0x2000000 + CONFIG_NR_DRAM_BANKS=1 + CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y + CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x83f00000 ++CONFIG_DM_GPIO=y + CONFIG_DEFAULT_DEVICE_TREE="corstone1000-mps3" + CONFIG_SYS_BOOTM_LEN=0x800000 + CONFIG_SYS_LOAD_ADDR=0x82100000 +@@ -39,6 +40,7 @@ CONFIG_CMD_BOOTZ=y + CONFIG_CMD_GPT=y + CONFIG_CMD_LOADM=y + # CONFIG_CMD_LOADS is not set ++CONFIG_CMD_MMC=y + CONFIG_CMD_USB=y + # CONFIG_CMD_SETEXPR is not set + CONFIG_CMD_CACHE=y +@@ -50,9 +52,10 @@ CONFIG_OF_CONTROL=y + CONFIG_VERSION_VARIABLE=y + CONFIG_NET_RANDOM_ETHADDR=y + CONFIG_REGMAP=y ++CONFIG_CLK=y + CONFIG_ARM_FFA_TRANSPORT=y + CONFIG_MISC=y +-# CONFIG_MMC is not set ++CONFIG_ARM_PL180_MMCI=y + CONFIG_MTD=y + CONFIG_NVMXIP_QSPI=y + CONFIG_PHYLIB=y +diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h +index 3ada21cbba1..737b7c277fb 100644 +--- a/include/configs/corstone1000.h ++++ b/include/configs/corstone1000.h +@@ -25,7 +25,9 @@ + #define CFG_SYS_SDRAM_BASE PHYS_SDRAM_1 + + #define BOOT_TARGET_DEVICES(func) \ +- func(USB, usb, 0) ++ func(USB, usb, 0) \ ++ func(MMC, mmc, 0) \ ++ func(MMC, mmc, 1) + + #include + +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0027-corstone1000-Enable-secure-boot-configs.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0027-corstone1000-Enable-secure-boot-configs.patch new file mode 100644 index 00000000..fa361cfb --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0027-corstone1000-Enable-secure-boot-configs.patch @@ -0,0 +1,38 @@ +From 3104b2d8128efd9cf2e311d3e1eed7626f76039c Mon Sep 17 00:00:00 2001 +From: Harsimran Singh Tungal +Date: Thu, 20 Mar 2025 16:01:56 +0000 +Subject: [PATCH 27/36] corstone1000: Enable secure boot configs + +Enable secure boot and related configurations + +Signed-off-by: Harsimran Singh Tungal +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Pending [Not submitted to upstream yet] +--- + configs/corstone1000_defconfig | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig +index 4c562536a89..5297e2fa455 100644 +--- a/configs/corstone1000_defconfig ++++ b/configs/corstone1000_defconfig +@@ -12,6 +12,7 @@ CONFIG_SYS_BOOTM_LEN=0x800000 + CONFIG_SYS_LOAD_ADDR=0x82100000 + CONFIG_IDENT_STRING=" corstone1000 aarch64 " + CONFIG_FWU_NUM_IMAGES_PER_BANK=4 ++CONFIG_EFI_SECURE_BOOT=y + CONFIG_EFI_MM_COMM_TEE=y + CONFIG_FFA_SHARED_MM_BUF_SIZE=4096 + CONFIG_FFA_SHARED_MM_BUF_OFFSET=0 +@@ -22,6 +23,8 @@ CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y + CONFIG_EFI_CAPSULE_AUTHENTICATE=y + CONFIG_EFI_CAPSULE_CRT_FILE="CRT.crt" + CONFIG_FIT=y ++CONFIG_FIT_SIGNATURE=y ++CONFIG_LEGACY_IMAGE_FORMAT=y + CONFIG_DISTRO_DEFAULTS=y + CONFIG_BOOTDELAY=3 + CONFIG_USE_BOOTARGS=y +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0028-corstone1000-Enable-EFI-set_time-config.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0028-corstone1000-Enable-EFI-set_time-config.patch new file mode 100644 index 00000000..73af703c --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0028-corstone1000-Enable-EFI-set_time-config.patch @@ -0,0 +1,35 @@ +From 634ea749a2c590199ab1f284bed9843496ee2cde Mon Sep 17 00:00:00 2001 +From: Gowtham Suresh Kumar +Date: Thu, 20 Mar 2025 16:06:18 +0000 +Subject: [PATCH 28/36] corstone1000: Enable EFI set_time() config + +Enable EFI set_time() config + +SetTime_Conf and SetTime_Func tests in UEFI SCT test suite of ACS +fail with unsupported return value. CONFIG_EFI_SET_TIME and +CONFIG_EFI_GET_TIME config values are needed. +This commit enables the set_time() config. +get_time() config is enabled automatically. + +Signed-off-by: Gowtham Suresh Kumar +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Pending [Not submitted to upstream yet] +--- + configs/corstone1000_defconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig +index 5297e2fa455..a0a631f3f40 100644 +--- a/configs/corstone1000_defconfig ++++ b/configs/corstone1000_defconfig +@@ -13,6 +13,7 @@ CONFIG_SYS_LOAD_ADDR=0x82100000 + CONFIG_IDENT_STRING=" corstone1000 aarch64 " + CONFIG_FWU_NUM_IMAGES_PER_BANK=4 + CONFIG_EFI_SECURE_BOOT=y ++CONFIG_EFI_SET_TIME=y + CONFIG_EFI_MM_COMM_TEE=y + CONFIG_FFA_SHARED_MM_BUF_SIZE=4096 + CONFIG_FFA_SHARED_MM_BUF_OFFSET=0 +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0029-corstone1000-Enable-set-print-EFI-variables.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0029-corstone1000-Enable-set-print-EFI-variables.patch new file mode 100644 index 00000000..cfc58ded --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0029-corstone1000-Enable-set-print-EFI-variables.patch @@ -0,0 +1,37 @@ +From d63525b685e24efaa9553f3be1ce80a33602f66e Mon Sep 17 00:00:00 2001 +From: Harsimran Singh Tungal +Date: Thu, 20 Mar 2025 16:08:16 +0000 +Subject: [PATCH 29/36] corstone1000: Enable set/print EFI variables + +Enable set/print UEFI variables using "env" command + +Signed-off-by: Harsimran Singh Tungal +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Pending [Not submitted to upstream yet] +--- + configs/corstone1000_defconfig | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig +index a0a631f3f40..190f48974df 100644 +--- a/configs/corstone1000_defconfig ++++ b/configs/corstone1000_defconfig +@@ -41,6 +41,7 @@ CONFIG_SYS_PROMPT="corstone1000# " + CONFIG_CMD_FWU_METADATA=y + CONFIG_CMD_BOOTZ=y + # CONFIG_CMD_XIMG is not set ++CONFIG_CMD_NVEDIT_EFI=y + CONFIG_CMD_GPT=y + CONFIG_CMD_LOADM=y + # CONFIG_CMD_LOADS is not set +@@ -78,6 +79,7 @@ CONFIG_USB=y + CONFIG_USB_ISP1760=y + # CONFIG_RANDOM_UUID is not set + CONFIG_ERRNO_STR=y ++# CONFIG_HEXDUMP is not set + CONFIG_FWU_MULTI_BANK_UPDATE=y + CONFIG_FWU_MDATA_V2=y + CONFIG_FWU_ARM_PSA=y +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0030-corstone1000-Enable-virtio-net-support.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0030-corstone1000-Enable-virtio-net-support.patch new file mode 100644 index 00000000..f4d8341b --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0030-corstone1000-Enable-virtio-net-support.patch @@ -0,0 +1,122 @@ +From 631ca237b413178c6149e8da33f4aa5bc0fff7ed Mon Sep 17 00:00:00 2001 +From: Emekcan Aras +Date: Thu, 20 Mar 2025 16:22:44 +0000 +Subject: [PATCH 30/36] corstone1000: Enable virtio-net support + +Add virtio-net support in Corstone1000 FVP + +Signed-off-by: Emekcan Aras +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Pending [Not submitted to upstream yet] +--- + arch/arm/dts/corstone1000-fvp.dts | 6 ++++ + board/armltd/corstone1000/corstone1000.c | 42 ++++++++++++++++++++---- + configs/corstone1000_defconfig | 3 ++ + 3 files changed, 45 insertions(+), 6 deletions(-) + +diff --git a/arch/arm/dts/corstone1000-fvp.dts b/arch/arm/dts/corstone1000-fvp.dts +index 3076fb9f344..cd8a132271e 100644 +--- a/arch/arm/dts/corstone1000-fvp.dts ++++ b/arch/arm/dts/corstone1000-fvp.dts +@@ -21,6 +21,12 @@ + reg-io-width = <2>; + }; + ++ virtio: virtio-net@40400000 { ++ compatible = "virtio,mmio"; ++ reg = <0x40400000 0x10000>; ++ interrupts = <145>; ++ }; ++ + vmmc_v3_3d: fixed_v3_3d { + compatible = "regulator-fixed"; + regulator-name = "vmmc_supply"; +diff --git a/board/armltd/corstone1000/corstone1000.c b/board/armltd/corstone1000/corstone1000.c +index 9189640ef75..39fd10ed653 100644 +--- a/board/armltd/corstone1000/corstone1000.c ++++ b/board/armltd/corstone1000/corstone1000.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + #include + + #define CORSTONE1000_KERNEL_PARTS 2 +@@ -201,13 +202,21 @@ static struct mm_region corstone1000_mem_map[] = { + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { +- /* ethernet */ ++ /* virtio-net */ ++ .virt = 0x40400000UL, ++ .phys = 0x40400000UL, ++ .size = 0x00100000UL, ++ .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | ++ PTE_BLOCK_NON_SHARE | ++ PTE_BLOCK_PXN | PTE_BLOCK_UXN ++ }, { ++ /* Ethernet */ + .virt = 0x40100000UL, +- .phys = 0x40100000UL, +- .size = 0x00100000UL, +- .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | +- PTE_BLOCK_NON_SHARE | +- PTE_BLOCK_PXN | PTE_BLOCK_UXN ++ .phys = 0x40100000UL, ++ .size = 0x00100000UL, ++ .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | ++ PTE_BLOCK_NON_SHARE | ++ PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* MMC0 */ + .virt = 0x40300000UL, +@@ -367,3 +376,24 @@ efi_status_t fwu_notify_exit_boot_services(void) + out: + return efi_ret; + } ++ ++int board_late_init(void) ++{ ++ struct udevice *virtio_bus = NULL, *virtio_child = NULL; ++ const char *cmp_dtb = DEVICE_TREE; ++ int ret; ++ ++ if (!strcmp(cmp_dtb, "corstone1000-fvp")) { ++ ret = uclass_first_device_err(UCLASS_VIRTIO, &virtio_bus); ++ if (!virtio_bus) { ++ log_err("Cannot find virtio device, err (%d)\n", ret); ++ return ret; ++ } ++ while (virtio_bus) { ++ device_foreach_child_probe(virtio_child, virtio_bus); ++ uclass_next_device(&virtio_bus); ++ } ++ } ++ ++ return 0; ++} +diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig +index 190f48974df..d1401550660 100644 +--- a/configs/corstone1000_defconfig ++++ b/configs/corstone1000_defconfig +@@ -36,6 +36,7 @@ CONFIG_SYS_CBSIZE=512 + CONFIG_LOGLEVEL=7 + # CONFIG_DISPLAY_CPUINFO is not set + # CONFIG_DISPLAY_BOARDINFO is not set ++CONFIG_BOARD_LATE_INIT=y + CONFIG_SYS_PROMPT="corstone1000# " + # CONFIG_CMD_CONSOLE is not set + CONFIG_CMD_FWU_METADATA=y +@@ -77,6 +78,8 @@ CONFIG_TEE=y + CONFIG_OPTEE=y + CONFIG_USB=y + CONFIG_USB_ISP1760=y ++CONFIG_VIRTIO_MMIO=y ++CONFIG_VIRTIO_NET=y + # CONFIG_RANDOM_UUID is not set + CONFIG_ERRNO_STR=y + # CONFIG_HEXDUMP is not set +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0031-arm-corstone1000-Fix-unrecognized-filesystem-type.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0031-arm-corstone1000-Fix-unrecognized-filesystem-type.patch new file mode 100644 index 00000000..9cb30a51 --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0031-arm-corstone1000-Fix-unrecognized-filesystem-type.patch @@ -0,0 +1,33 @@ +From face25548766183af2a80ec7c60ba9f8f90ee387 Mon Sep 17 00:00:00 2001 +From: Rui Miguel Silva +Date: Fri, 4 Mar 2022 15:56:09 +0000 +Subject: [PATCH 31/36] arm: corstone1000: Fix unrecognized filesystem type + +Add a delay before checking USB sticks status + +Some USB sticks are not recognized by the USB bus, just add a +delay before checking status. + +Signed-off-by: Rui Miguel Silva +Upstream-Status: Pending [Not submitted to upstream yet] +--- + common/usb_storage.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/common/usb_storage.c b/common/usb_storage.c +index ac331f1c1b0..17f8a56e971 100644 +--- a/common/usb_storage.c ++++ b/common/usb_storage.c +@@ -782,6 +782,9 @@ static int usb_stor_BBB_transport(struct scsi_cmd *srb, struct us_data *us) + st: + retry = 0; + again: ++ if (srb->cmd[0] == SCSI_TST_U_RDY) ++ mdelay(100); ++ + debug("STATUS phase\n"); + result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE, + &actlen, USB_CNTL_TIMEOUT*5); +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0032-corstone1000-dts-Add-external-system-node.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0032-corstone1000-dts-Add-external-system-node.patch new file mode 100644 index 00000000..b145cede --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0032-corstone1000-dts-Add-external-system-node.patch @@ -0,0 +1,34 @@ +From fa900c31f2fc1cf9c3333cd565d779bb06d59bec Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Mon, 18 Mar 2024 17:00:56 +0000 +Subject: [PATCH 32/36] corstone1000: dts: Add external system node + +Add the external system node + +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Pending [Not submitted to upstream yet] +--- + arch/arm/dts/corstone1000.dtsi | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/arch/arm/dts/corstone1000.dtsi b/arch/arm/dts/corstone1000.dtsi +index 5d9d95b21cb..76bfc561df7 100644 +--- a/arch/arm/dts/corstone1000.dtsi ++++ b/arch/arm/dts/corstone1000.dtsi +@@ -118,6 +118,13 @@ + interrupt-parent = <&gic>; + ranges; + ++ extsys0: remoteproc@1a010310 { ++ compatible = "arm,corstone1000-extsys"; ++ reg = <0x1a010310 0x4>, <0x1a010314 0x4>; ++ reg-names = "reset-control", "reset-status"; ++ firmware-name = "es_flashfw.elf"; ++ }; ++ + timer@1a220000 { + compatible = "arm,armv7-timer-mem"; + reg = <0x1a220000 0x1000>; +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0033-arm-bsp-u-boot-dts-Reserve-memory-for-RSS-comm-point.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0033-arm-bsp-u-boot-dts-Reserve-memory-for-RSS-comm-point.patch new file mode 100644 index 00000000..54ddd047 --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0033-arm-bsp-u-boot-dts-Reserve-memory-for-RSS-comm-point.patch @@ -0,0 +1,50 @@ +From 548b7cc0126621af41eff92d504d79d67f85c648 Mon Sep 17 00:00:00 2001 +From: Emekcan Aras +Date: Mon, 10 Jul 2023 19:00:43 +0100 +Subject: [PATCH 33/36] arm-bsp/u-boot: dts: Reserve memory for RSS comm + pointer access protocol + +Add reserved-memory node for RSS comm pointer access protocol + +This memory was used by OpenAMP to establish communication between +the Secure Enclave and Trusted Services. After transitioning from +OpenAMP to RSE_COMMS, this shared memory is now configured for the +pointer access protocol in RSE_COMMS. + +Since this memory may be still used by a user-space application +in Linux as U-Boot is passing an EFI memory map starting from +0x80000000, this memory range should be reserved as the +pointer access protocol may be enabled on corstone1000 in the future. + +Signed-off-by: Emekcan Aras +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Pending [Not submitted to upstream yet] +--- + arch/arm/dts/corstone1000.dtsi | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/arch/arm/dts/corstone1000.dtsi b/arch/arm/dts/corstone1000.dtsi +index 76bfc561df7..74e95dcbc6b 100644 +--- a/arch/arm/dts/corstone1000.dtsi ++++ b/arch/arm/dts/corstone1000.dtsi +@@ -45,6 +45,17 @@ + lba = <65536>; + }; + ++ reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ smem_mem: smem_region@88000000 { ++ reg = <0x0 0x88000000 0x0 0x100000>; ++ no-map; ++ }; ++ }; ++ + gic: interrupt-controller@1c000000 { + compatible = "arm,gic-400"; + #interrupt-cells = <3>; +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0034-dt-Provide-a-way-to-remove-non-compliant-nodes-and-p.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0034-dt-Provide-a-way-to-remove-non-compliant-nodes-and-p.patch new file mode 100644 index 00000000..17d3f23a --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0034-dt-Provide-a-way-to-remove-non-compliant-nodes-and-p.patch @@ -0,0 +1,137 @@ +From 9965fa5c45f6babb3182886623f660cc725c5a62 Mon Sep 17 00:00:00 2001 +From: Sughosh Ganu +Date: Thu, 22 May 2025 17:57:14 +0100 +Subject: [PATCH 34/36] dt: Provide a way to remove non-compliant nodes and + properties + +Add a function which is registered to spy for a EVT_FT_FIXUP event, +and removes the non upstreamed nodes and properties from the +devicetree before it gets passed to the OS. + +This allows removing entire nodes, or specific properties under nodes +from the devicetree. The required nodes and properties can be +registered for removal through the DT_NON_COMPLIANT_PURGE and +DT_NON_COMPLIANT_PURGE_LIST macros. + +Signed-off-by: Sughosh Ganu +Upstream-Status: Denied [RFC: https://lore.kernel.org/u-boot/aca7e6fa-2dec-a7c5-e47e-84c5ffa6f9b7@gmx.de/T/#m16d14ee960427cc88066bdcdd76f0a26738bb66d] +--- + include/dt-structs.h | 11 +++++++ + lib/Makefile | 1 + + lib/dt_purge.c | 73 ++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 85 insertions(+) + create mode 100644 lib/dt_purge.c + +diff --git a/include/dt-structs.h b/include/dt-structs.h +index fa1622cb1dc..f535c60471b 100644 +--- a/include/dt-structs.h ++++ b/include/dt-structs.h +@@ -57,3 +57,14 @@ struct phandle_2_arg { + #endif + + #endif ++ ++struct dt_non_compliant_purge { ++ const char *node_path; ++ const char *prop; ++}; ++ ++#define DT_NON_COMPLIANT_PURGE(__name) \ ++ ll_entry_declare(struct dt_non_compliant_purge, __name, dt_purge) ++ ++#define DT_NON_COMPLIANT_PURGE_LIST(__name) \ ++ ll_entry_declare_list(struct dt_non_compliant_purge, __name, dt_purge) +diff --git a/lib/Makefile b/lib/Makefile +index a7bc2f3134a..82b021562f1 100644 +--- a/lib/Makefile ++++ b/lib/Makefile +@@ -70,6 +70,7 @@ endif + obj-$(CONFIG_$(PHASE_)CRC8) += crc8.o + obj-$(CONFIG_$(PHASE_)CRC16) += crc16.o + obj-$(CONFIG_$(PHASE_)CRC16) += crc16-ccitt.o ++obj-y += dt_purge.o + + obj-y += crypto/ + +diff --git a/lib/dt_purge.c b/lib/dt_purge.c +new file mode 100644 +index 00000000000..abae7c04fc7 +--- /dev/null ++++ b/lib/dt_purge.c +@@ -0,0 +1,73 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Copyright (c) 2023, Linaro Limited ++ */ ++ ++#include ++#include ++#include ++ ++#include ++ ++/** ++ * dt_non_compliant_purge() - Remove non-upstreamed nodes and properties ++ * from the DT ++ * @ctx: Context for event ++ * @event: Event to process ++ * ++ * Iterate through an array of DT nodes and properties, and remove them ++ * from the device-tree before the DT gets handed over to the kernel. ++ * These are nodes and properties which do not have upstream bindings ++ * and need to be purged before being handed over to the kernel. ++ * ++ * If both the node and property are specified, delete the property. If ++ * only the node is specified, delete the entire node, including it's ++ * subnodes, if any. ++ * ++ * Return: 0 if OK, -ve on error ++ */ ++static int dt_non_compliant_purge(void *ctx, struct event *event) ++{ ++ int nodeoff = 0; ++ int err = 0; ++ void *fdt; ++ const struct event_ft_fixup *fixup = &event->data.ft_fixup; ++ struct dt_non_compliant_purge *purge_entry; ++ struct dt_non_compliant_purge *purge_start = ++ ll_entry_start(struct dt_non_compliant_purge, dt_purge); ++ int nentries = ll_entry_count(struct dt_non_compliant_purge, dt_purge); ++ ++ if (fixup->images) ++ return 0; ++ ++ fdt = fixup->tree.fdt; ++ for (purge_entry = purge_start; purge_entry != purge_start + nentries; ++ purge_entry++) { ++ nodeoff = fdt_path_offset(fdt, purge_entry->node_path); ++ if (nodeoff < 0) { ++ log_debug("Error (%d) getting node offset for %s\n", ++ nodeoff, purge_entry->node_path); ++ continue; ++ } ++ ++ if (purge_entry->prop) { ++ err = fdt_delprop(fdt, nodeoff, purge_entry->prop); ++ if (err < 0 && err != -FDT_ERR_NOTFOUND) { ++ log_debug("Error (%d) deleting %s\n", ++ err, purge_entry->prop); ++ goto out; ++ } ++ } else { ++ err = fdt_del_node(fdt, nodeoff); ++ if (err) { ++ log_debug("Error (%d) trying to delete node %s\n", ++ err, purge_entry->node_path); ++ goto out; ++ } ++ } ++ } ++ ++out: ++ return err; ++} ++EVENT_SPY_FULL(EVT_FT_FIXUP, dt_non_compliant_purge); +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0035-bootefi-Call-the-EVT_FT_FIXUP-event-handler.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0035-bootefi-Call-the-EVT_FT_FIXUP-event-handler.patch new file mode 100644 index 00000000..d1a9b817 --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0035-bootefi-Call-the-EVT_FT_FIXUP-event-handler.patch @@ -0,0 +1,58 @@ +From 24cdb09130c32209485648e106da40f5c2732271 Mon Sep 17 00:00:00 2001 +From: Sughosh Ganu +Date: Thu, 22 May 2025 18:08:38 +0100 +Subject: [PATCH 35/36] bootefi: Call the EVT_FT_FIXUP event handler + +The bootefi command passes the devicetree to the kernel through the +EFI config table. Call the event handlers for fixing the devicetree +before jumping into the kernel. This removes any devicetree nodes +and/or properties that are specific only to U-Boot, and are not to be +passed to the OS. + +Signed-off-by: Sughosh Ganu +Upstream-Status: Denied [RFC: https://lore.kernel.org/u-boot/aca7e6fa-2dec-a7c5-e47e-84c5ffa6f9b7@gmx.de/T/#m16d14ee960427cc88066bdcdd76f0a26738bb66d] +--- + cmd/bootefi.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/cmd/bootefi.c b/cmd/bootefi.c +index c1454ffb948..2599afadf9a 100644 +--- a/cmd/bootefi.c ++++ b/cmd/bootefi.c +@@ -118,6 +118,24 @@ static int do_efi_selftest(void) + return ret != EFI_SUCCESS; + } + ++/** ++ * event_notify_dt_fixup() - call ft_fixup event ++ * ++ * @fdt: address of the device tree to be passed to the kernel ++ * through the configuration table ++ * Return: None ++ */ ++static void event_notify_dt_fixup(void *fdt) ++{ ++ int ret; ++ struct event_ft_fixup fixup = {0}; ++ ++ fixup.tree.fdt = fdt; ++ ret = event_notify(EVT_FT_FIXUP, &fixup, sizeof(fixup)); ++ if (ret) ++ printf("Error: %d: FDT Fixup event failed\n", ret); ++} ++ + /** + * do_bootefi() - execute `bootefi` command + * +@@ -173,6 +191,8 @@ static int do_bootefi(struct cmd_tbl *cmdtp, int flag, int argc, + if (ret != EFI_SUCCESS) + return CMD_RET_FAILURE; + ++ event_notify_dt_fixup(fdt); ++ + return do_efi_selftest(); + } + +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0036-corstone1000-Purge-U-Boot-specific-DT-nodes.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0036-corstone1000-Purge-U-Boot-specific-DT-nodes.patch new file mode 100644 index 00000000..c52e1a97 --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0036-corstone1000-Purge-U-Boot-specific-DT-nodes.patch @@ -0,0 +1,41 @@ +From 6466a6cf1ea529180d41ef4e75b16f33a050673a Mon Sep 17 00:00:00 2001 +From: Abdellatif El Khlifi +Date: Thu, 29 May 2025 14:42:42 +0100 +Subject: [PATCH 36/37] corstone1000: Purge U-Boot specific DT nodes + +Remove U-Boot specific DT nodes before passing the DT to Linux + +This is needed to pass SystemReady IR 2.0 dt-schema tests + +Signed-off-by: Abdellatif El Khlifi +Upstream-Status: Denied [RFC: https://lore.kernel.org/u-boot/aca7e6fa-2dec-a7c5-e47e-84c5ffa6f9b7@gmx.de/T/#m16d14ee960427cc88066bdcdd76f0a26738bb66d] +--- + board/armltd/corstone1000/corstone1000.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/board/armltd/corstone1000/corstone1000.c b/board/armltd/corstone1000/corstone1000.c +index 39fd10ed653..c8fcbf976e0 100644 +--- a/board/armltd/corstone1000/corstone1000.c ++++ b/board/armltd/corstone1000/corstone1000.c +@@ -23,6 +23,18 @@ + #include + #include + ++/* remove the DT nodes not needed in Linux */ ++DT_NON_COMPLIANT_PURGE_LIST(foo) = { ++ { .node_path = "/fwu-mdata" }, ++ { .node_path = "/nvmxip-qspi@08000000" }, ++ { .node_path = "/soc/mailbox@1b820000" }, ++ { .node_path = "/soc/mailbox@1b830000" }, ++ { .node_path = "/soc/mhu@1b000000" }, ++ { .node_path = "/soc/mhu@1b010000" }, ++ { .node_path = "/soc/mhu@1b020000" }, ++ { .node_path = "/soc/mhu@1b030000" }, ++}; ++ + #define CORSTONE1000_KERNEL_PARTS 2 + #define CORSTONE1000_KERNEL_PRIMARY "kernel_primary" + #define CORSTONE1000_KERNEL_SECONDARY "kernel_secondary" +-- +2.25.1 + diff --git a/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0037-corstone1000-purge-remoteproc-DTS-node.patch b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0037-corstone1000-purge-remoteproc-DTS-node.patch new file mode 100644 index 00000000..214a307e --- /dev/null +++ b/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0037-corstone1000-purge-remoteproc-DTS-node.patch @@ -0,0 +1,32 @@ +From 7a32af1d8f904990d016d96d50894c49686db14c Mon Sep 17 00:00:00 2001 +From: Harsimran Singh Tungal +Date: Thu, 29 May 2025 14:44:17 +0100 +Subject: [PATCH 37/37] corstone1000: purge remoteproc DTS node + +Purge remoteproc DTS node +This is done to remove the remote proc node from the DTS passed +to Linux from U-Boot because the device tree binding for remoteproc +has not been upstreamed yet. Existence of remoteproc DTS node in Linux +is causing dt-schema test for SystemReady-IR v2.0 certification to fail. + +Signed-off-by: Harsimran Singh Tungal +Upstream-Status: Denied [RFC: https://lore.kernel.org/u-boot/aca7e6fa-2dec-a7c5-e47e-84c5ffa6f9b7@gmx.de/T/#m16d14ee960427cc88066bdcdd76f0a26738bb66d] +--- + board/armltd/corstone1000/corstone1000.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/board/armltd/corstone1000/corstone1000.c b/board/armltd/corstone1000/corstone1000.c +index c8fcbf976e0..1b9c3a9ed16 100644 +--- a/board/armltd/corstone1000/corstone1000.c ++++ b/board/armltd/corstone1000/corstone1000.c +@@ -33,6 +33,7 @@ DT_NON_COMPLIANT_PURGE_LIST(foo) = { + { .node_path = "/soc/mhu@1b010000" }, + { .node_path = "/soc/mhu@1b020000" }, + { .node_path = "/soc/mhu@1b030000" }, ++ { .node_path = "/soc/remoteproc@1a010310" }, + }; + + #define CORSTONE1000_KERNEL_PARTS 2 +-- +2.25.1 + From patchwork Wed Jul 30 11:53:26 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harsimran Singh Tungal X-Patchwork-Id: 67731 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id F0312C87FCC for ; Wed, 30 Jul 2025 11:54:10 +0000 (UTC) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.web10.33480.1753876442826469574 for ; Wed, 30 Jul 2025 04:54:02 -0700 Authentication-Results: mx.groups.io; dkim=none (message not signed); spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: harsimransingh.tungal@arm.com) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 6D76E2573; Wed, 30 Jul 2025 04:53:54 -0700 (PDT) Received: from e132995.cambridge.arm.com (e132995.arm.com [10.1.25.25]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id A900F3F66E; Wed, 30 Jul 2025 04:54:01 -0700 (PDT) From: Harsimran Singh Tungal To: meta-arm@lists.yoctoproject.org Cc: Ali Can Ozaslan Subject: [PATCH 12/13] arm/edk2-basetools-native: WORKDIR fix Date: Wed, 30 Jul 2025 12:53:26 +0100 Message-Id: <20250730115327.3671160-13-harsimransingh.tungal@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250730115327.3671160-1-harsimransingh.tungal@arm.com> References: <20250730115327.3671160-1-harsimransingh.tungal@arm.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Wed, 30 Jul 2025 11:54:10 -0000 X-Groupsio-URL: https://lists.yoctoproject.org/g/meta-arm/message/6649 From: Ali Can Ozaslan Upstream has removed the need to explicitly set S = "${WORKDIR}/git", and now defaults to S = "${UNPACKDIR}". As a result, directly referencing ${WORKDIR}/git will fail when the source is unpacked elsewhere. Update do_install() to use ${S}/BaseTools instead of the hardcoded path. This issue was previously unnoticed as EDK2 tools (e.g. GenerateCapsule) were not being used in the build path at the time of the earlier refactor (commit eea74860). Signed-off-by: Ali Can Ozaslan --- meta-arm/recipes-bsp/uefi/edk2-basetools-native_202502.bb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta-arm/recipes-bsp/uefi/edk2-basetools-native_202502.bb b/meta-arm/recipes-bsp/uefi/edk2-basetools-native_202502.bb index e9e48217..0c08fce7 100644 --- a/meta-arm/recipes-bsp/uefi/edk2-basetools-native_202502.bb +++ b/meta-arm/recipes-bsp/uefi/edk2-basetools-native_202502.bb @@ -20,5 +20,5 @@ RDEPENDS:${PN} += "python3-core" do_install () { mkdir -p ${D}${bindir}/edk2-BaseTools - cp -r ${WORKDIR}/git/BaseTools/* ${D}${bindir}/edk2-BaseTools/ + cp -r ${S}/BaseTools/* ${D}${bindir}/edk2-BaseTools/ } From patchwork Wed Jul 30 11:53:27 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Harsimran Singh Tungal X-Patchwork-Id: 67735 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 14373C87FCB for ; Wed, 30 Jul 2025 11:54:11 +0000 (UTC) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.web11.33482.1753876443778599444 for ; Wed, 30 Jul 2025 04:54:03 -0700 Authentication-Results: mx.groups.io; dkim=none (message not signed); spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: harsimransingh.tungal@arm.com) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 740AD2681; Wed, 30 Jul 2025 04:53:55 -0700 (PDT) Received: from e132995.cambridge.arm.com (e132995.arm.com [10.1.25.25]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id B71273F66E; Wed, 30 Jul 2025 04:54:02 -0700 (PDT) From: Harsimran Singh Tungal To: meta-arm@lists.yoctoproject.org Cc: Harsimran Singh Tungal Subject: [PATCH 13/13] arm-bsp/doc: corstone1000: Update architecture document with new PSA FWU implementation details Date: Wed, 30 Jul 2025 12:53:27 +0100 Message-Id: <20250730115327.3671160-14-harsimransingh.tungal@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250730115327.3671160-1-harsimransingh.tungal@arm.com> References: <20250730115327.3671160-1-harsimransingh.tungal@arm.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Wed, 30 Jul 2025 11:54:11 -0000 X-Groupsio-URL: https://lists.yoctoproject.org/g/meta-arm/message/6650 Update the architecture documentation for Corstone-1000 to include details about the new PSA Firmware Update (FWU) implementation. The new section describes the bootloader abstraction layer (BAL), UEFI capsule update flow, FWU metadata handling, and the integration between TF-M and U-Boot for managing trial and accepted images. This documentation helps align the platform with PSA FWU requirements Signed-off-by: Harsimran Singh Tungal --- .../SystemArchitecturePSAFirmwareUpdate.png | Bin 0 -> 47522 bytes .../corstone1000/software-architecture.rst | 117 ++++++++++++++---- 2 files changed, 94 insertions(+), 23 deletions(-) create mode 100644 meta-arm-bsp/documentation/corstone1000/images/SystemArchitecturePSAFirmwareUpdate.png diff --git a/meta-arm-bsp/documentation/corstone1000/images/SystemArchitecturePSAFirmwareUpdate.png b/meta-arm-bsp/documentation/corstone1000/images/SystemArchitecturePSAFirmwareUpdate.png new file mode 100644 index 0000000000000000000000000000000000000000..75cee8be7d6873ab03bfd2b790772dccd4b67458 GIT binary patch literal 47522 zcmeFa1z1&Gw>C^{q`RbKgQWB(1&K|Aq#z|ogDBl8EuBiINQO7wz0J}WroQMa`S?(*!1}LnE9o_r>kae_O5O} zKdac-yLo~!PZ1$wA%UM`&hE_oa6Wz^ZeDiqje@25EeCKH7%v|$_{Rr^pAa|mn=#>_9r%nJu! zAph~pSlF0aJDY+h;F+sFYe8}E~6 z`LS~tueFCYAW)gTrTMXPj_+vd?Cjw2`)O7Vw#N^BJjW3{ z*U!5jFNhq_`jbqNqq;U0t~Y+p6%jl&ThY?S`o_u1K#Mv$Emgc zEXWgaIy*Rk`<>F-&o55@MB1&4r7cq0CvrSq2iVR3|7(9q!}*tm|DW8>+)Bwy*4@KO z#^4IyO?^#EWjSXxF23VCx|;&u`YDH>qH=NdIx%5q2RC~QOQedB-sEw^#??~G(bOC{ z-2+${7`x$WXM6m$i>tH4tzT;S>3&EDa5VkxDUKfuxR0yliB%$3{pZp>Q3SASO9wkk zS7$G9+vCdxPBeUM(p&<^&*kx(eej7KkKH(B8!+MHLDOTKwElH(PZeMIdgZ#DC|D$67v7vYLalohkB+)pc+NzyZL#t6b9Ha0bZj z=S-k|vy;g`Z+A+8;KV`N&QBkeajp!#6Z*3q@SOyS(*c10Z+8YB z3$NaPig(XN=W}JIQxf?t_4zCUJYjlPb8$*(l{}T{|)3nn2(c?eMS2X@<>RmW^3x=Vq^Z}d^UA<{qyiC!1fzJKw>aUPa9XgW7Y!sSs#4n z7mKG<}*$AqCh+rq^=VYay@;kl?X(iyy_&4!L|8U7) zOB^rxYYQh!{#3=kV@ZA)u(?z0)jyZa@$4Ub;=h{tC))8ZO-bZ09P1y0sFMupba;kK zE1inWr;@B+iP!JK?!UgdtehGzA0OD*uN(Z!oBkmb9OrYVy!=mD+&|3IoGo2!yiLu1 z@SI48c0?NA4<1lZnpsd5jF`H)I)FJyD@W!OzfTU1v&Pez#PQHSboc*2%9HCP%Rh0A z;~e0W|Ni2=Pdo4lnm94%zX9QS!UzAxLCZKGsbMaV^8K&6e?~s86ZZO8-G9Y!pYV96 z)&0kS`8QBEP$^QYr%<7mrMa6k62-~cgYz65D*vnYlfnl7ar*R6)c%Xc`_S3uW2E)xCU;&cQ~obp(yCx4y} z-AH_bl*MVC{{1K&zCUw1zkFF9AoCl4^5p*!3gtV|-hV-j{yAsYmgiFalOF%a;x2&` zFFd8&lceahvz|Eh-w0>@kIJn7WyZ{Rd>;LGOPNnl;PK%icwF8-vBUrPjG6z${Qtp< z|78i|Klcg!DvckT z>R+AHe^n{}8z#;FhOU*rq)AUPCBI>@6Qc76wfTz!)jy^^knHGh#3u3&r1+56{Pd51 z53hL=egAcsK8Be8-NN)A^7&u1<9}Y9{5P*9*KO0sZm&+8wJFjC1BNFPBw&>;A0YL2*T*)v3(QjQ)T zmmO1P*4EajCz%x;Yf<1wUN0n58s{xMtlZt*pB{W&J71siR99T^dqaN9K|YzYdA-y8 znXHR0cet-NDN=G9&iJoSx2W@6Z`#=R`ugP&jRKnyE?Q6k6pDofevJ}g(TNJkMUo*t zuv+z|-eZ)*QBH#~A7u#H87Rj?14r+0%@adZ;3#ju3f>wUs50+b`ts?m>xWl#hq~YS zEQy997Kp-Wgt<#3o#r}bj}8yNu9v8!!L~%QZR45J(o5d?w?m-_LG9F83>?i5LI%asb^m@H7hxM-;)&e`8`7BLfVEZuPttn3a28( zmtLSajL_%H$NT7*1iXXV{>}S~H18DCtSx6-Xsm>D?RXHiihgEbY4Aasiq1owm?WQ$ zaAHA1y$d+MDFiyhiFWjDi;&)Z9`k*T<;&!eN7sZ84pu9&?3A-9A)J9I?JuRci`24u zLUPT!V#yd~u`Wleo|&!3^4;4AynXcDW6^PEb^ODVP)CS$)Jw(15NuLUN1))@HU&$M+`p6HLxxKKquW!m4A>0aR!JAG zmI=vH#X)BqeJb0ni7(78;VRlC*wApSdmHI^kP8sKip>}?WOnsmVhsM z1%k>?+zO|4UJbZmg-B$cD92|=TOw=g+^bc~5^Zz8K!~*c6IqxDLabh8A~HOfp2e#+ zjpon4n-464VzIOj-rirJTt6dYwJroHRL$s|#ek-_dEH)OOam@el;eMxMx-KnYm76j zugG3TUXvATzOgjqY}lL=0$sY5ZZ*cktLfvC-`1P#`r%jqXiVU43|9n;wh- zw(mqX&I;M;#mj2(BRc4`mr(dp9>~Wye=sa?03PAUkLI(xW=UB?%BrTZw=w(L=v*2i zPc~w1yIVPhTlLm>xm&|^6LR2r4$7|C9FBR1|QGyd@I^H`5>jz$vIM8t@%ZGf>l zbkw@;#aCGwLiUqO#1NO!(yO!_2jj;6gC5g<3VVgm$=@mKXSRI*a;@ETNY~hJK_Ned z$9VC3Pz}bVr8iG*37B*Pn@C)RBQb zZ(N7O(q5EiR=$@TLCSgsXkfW57<1&Q-8G5t9(P7&&2|Rv%V-sA++TXv=y3;C)OAV2 zpvnw`PRu=e?Oh|QE*sUIG65#633^n+wmbOz;Z`MA3O-7jrrj?fLLu(C%S!mfVS4Jk zp+$d=WdD39CdyoT0$ZW!^E)b&hDxo6-*=61NLiwvSED0jt(K#y_(cs_i!q-iSfCNs zy)ui#kdcu>1Z1+L0ry!Td#X{FIN25dggpie?Ocr1RFhYU{kw*dTsV4;*Cp@ma7o@q zkM%`7&&$c2v#ECZ&tIkR(5t2kL^vu5BvP8p--%OSpL(|cJR~Y$xZtva$g@y#)GZe zePgPrzCP=+!}S=HFR!7}*(CIrJk|`UFFG^PN%&4E*aIhFrX8DsQd{<>@_p+IBPTv5 zzju4SrAl&dXWZE4>z7YtlDB=oB=+V=N|JLK+!OU!`*=4RH|#a^-Gt0z`*-O|pYGt( zU|~*)d8~ai>n9o*<%TEp@>{>s0QQ!8HaMI`DKTW12m_abX_Ef+GanBEVn~VIa3TJa z8-qbzr3SECySJT~pLEL&@9R~WRb6K1yuGyb9&z`ch?7|-YS@cR--e zSe2gkRBoFhxNbXe_b^I}i4@|}8BL|at5u}-iG3@@2^sXFh+3B!6zR)S0t+7B$?Hqz zqG>#sF~<)5_IcrQdlwcHsV-(fNNJ?*6N{i?mdnY}O01KgHxmLgBn+K$_comZGvpV0 z)9P;*s-!iiG7s4YhvyM4@vt2wap*Q+;oIndp)HLJ(g??|JymE7#}Dkqkks#au3p1(o^Ibc>|vq=-P* ztPsI-crmYTFJZoCf3~;;6R8iC;V!CQl}Q^~IUz1jVnm>TjDKr;RQ>gq+gVD*7d~98 zwciXBCFpl~-#yFc9QF|$9$PQO(+TdX)OC-Q>E9K0ljaqdUxR7DTMMuPIttWtvVqBx z-jLMDoyh&Z*+u^iPlCEmfpVN~mW)uDk{;_xF%zl%S&adWH8zdr;@$0Kt*5clC0U|w zk?L533Q`3Q)6JQww%zdz$TM9zU4Z>vvtLG@e9X!f!+a-Tot5-x1Lol|&r#FrUcFIo z)=4LBzFV2!_8DVnQAv(jEkoFW<-IJMZaM8WG*V{e4xL8rk}FOGm}EpZd|L= zaK?MQ_nQ1Kvq+p9ps9pPo6cFNbJax=6a_d|g?_!Dwl|WOsL}zy&poN&OBt`0i8A+o zBaHsG30hQK@`_ckwUYx6nXuZ}KpgeMz_>FKvLdEQKSOT~R%=k;!#9pI+#uG-sb_nT zp@u}vTw79-J)c`|^vpZyU2g)@nTPl%K9Y~TlSg7LN@fR?*0 zXfT&2R!xjU&@yMt@T6CiFfbwU_+>+S=xl9?DtlMYJ6SM@!DQ3*)sw;_zDq@fknLre43#n=mcbq;&s@3BQ&$A# zrj@L`klVL8-$klev_4dDnNouMMcqhH9EyaM#@?Qk67dftfs1xi8dg^i{)(1Gxo=as z(k3@Dj3d1&l{d2=J|Rs@@GuNkDblV=R$j9@UQtwO`rP>=%iM+8Wk~JBW1Hd6wYOha zTQ8KeI5OxH5rkLuOI<&6#6%jxT`3;yPx~ZMB^vcB!N@AtkIWi_5*)rDmQHCUJsu@BBx)s+qrybd14>lk&Yzal=dXDe|;wwa) z2-!~PUawT5m=)xVTN zGJAkW5-|;ut%O>kGj5c?7u$&=jGKs#GXzCgn1tu>1a9RA z-nx=batb-NniHWgNS#sCgF0H?1z?H?ZDSxXN#%+2vYq-0E}GSOl%Uw>=oaJn_bjAM z8F9(J-Tx_-pZOfXw0m+W_JNhRXH2d~LUSomE%;s}(IsZ8@g!cEHo}@Iz3iD<^+cD? z$p5n>(Kl3y=e+utf12A#3WjwS73}(@AwcaAMz|C|+C=PmI6-+}d?sqT>AgsMd6Zgw zXrrWIGdfdR-3aaBh_g{d1~c=!Q(0vJu@voDXFceHC*T1%(7OGDCM4dA#4}=f!q5~u z!Y4*}6j{u0O&0H2NM>_hr)oSw;!v#AP?SUzuyUk}z9KQ?F?68T!B~2ZY;qS^)`kVd zduQcE#KUj#y&xz2?8oDnB4=>@ci90J8vHym^C$($*Sk8W`Kaimpe*PN7FrCAFpDS2 zoH3ZqdOkqxGPuE7ibcEJm(L3?LvmIBaFbYu01K|VLez0V;C-2LC{!1n`pxQ{7cw7R z=*LA%mNo&%S-@>YyM>8#w{xa?i;Vq>-pxwbS#V(fN@UBTTLDPkH`@n_*7Hh*2}Lo+ zb6pc^CcyNN1|q*ig*xdLJAg{>@fsvRB)u8nDE;!@3o(Ilk_UsEIpU(pMNwFKbVZVL zG!*zRkGK$rQ}Ubxa4>bQGiJ5^ZhQhR8V*{m!!!$R`d++B{uGE~A{i@xFbR<`6vGZ7 z+X<;CN*?#}yi1>UuzYt$b;(*E1znGeLYYa!G7;xT_--!|zlbD{%9il!@z@69|CNy= zcR~;dQh_TY#hS~9-@hXB?++JV4quN6h*zngX!*plE&~H(gW}eQ{vvV?oeBFy7{h5{ z^h)PShvH~I^L8sWcv7lwq%0{UC8b!1AHt@!0dEbn5VCu7@9uYiQ4MB(zwSVIYj?tV zY^8wCIQohzjFQC|EG)#fe92pnR}xJ80Er7YOkHZuQTSbE8x$Y}ag;QSp%z>MLH-SO zyutMd$=`AuaI)EXkGY+MT*RX}|pH+e1=Tt-Nl zi#JV(rUDy(bZr;AoQ_7=p3L*KY=|JPAdUNu1;3zQo&PF1zo8ZiWg5Q5^oefEBC&+1 zR~?C%0fXVwRc4v|Tiyx9sv`HyU%s)Y2DNFHt&RhFdxUTSu)~)#~UtEKeAbytk3_(k$XBnhGH$r z&Wx03Y1de(ih6zi(-Wq#Y38ZFt#x2sFkVl6(tG8!JSiC+KfMvWpjQb6m}fNfnc}d! zG|+oiKD&!)B9*xJwmPsH=z=j^_ViV7DOR+&bK-gT*tLcLq2l(GY4jNeDnr^7qs@9M z>)l?EJ^FiZ&S9`0d3Tj1={I|A-2veExnz&{eI$%+@cSx+iV0kroH(3}o#aIfP0CzH zgbX$*OFqo9XG49W()5vtA=TYLtng+Sk%~K^hUv_+5d$vk4(Ms9(#k`GI&#Iie51b$S|#P!}>B2TdKPRVDV)X z_0k4%)Ir^xSr1_w$5qDoS6T9{bgPzaK^RRrt<54v4X#Z^;q;QtgqoVt{<9SFR9?7BRp{m4L2t7}1!iFBgBk@ZVUZ6{eHF3Ue8M0FU@wTeIEcP0Lfj&$qjD#ll| zkk_qCR|=HLIaG~0%^1<5D7fZ=@65f38U~PIu{zsM6;@>m(lI*HUI;cx9iFU>9#JI; zny~$(NuGYGHakPQ4v7k{IkDdYygl(g^__rsJ4p|ff=z?s?{EeNJRHO2)SaM2a&o&J zB-~cmPK|CvSjMgCSj3EwiU`Nqb}ET;ZxdDOGN0HC-vN{=D`a@X@;tr)9jfi5^M_Ze z=jEe`#`PcKUZ%=f;vghS#2d84n$S0{j})j=IXhH&jo9&pH++sV9=q-ZfZrpJw(h=q z6ea~I0Brlm&~(Lb78X^^2-%@%K*m;)YZ+R^7;+CKvofIQ3h42Jvkzn?oSY(qx)c<# zczptpkEIocaB3CONLLF{H2DfjJzl4o$x2h1n{OVMEN>+ch@%Grv^os@ae~)6Uv4;= ziB$h?BCEO@;BR*EmV4MRP$?M(TKxSReD`4tQJG}77@-F}>COq7X>kE`J4u82ZN4Rn zaaN2b+ukMGB_x0uQshjv!WoqL8YH&`n5D-S2$JVkCSr-$6xTuO*KqrL!`qtf+gp9Y z+u!zGM4jJb`5k@V<$MePz~&wLHC&tFLP3@IR{|klV?QtUT?Y7fR|_AtwJv0Lvfd?g zh&r&XwOT%gS^)4Tw<*kJv_LkX~{uDElTJmZ}gdzC=y`hiLP@G>Bd_w2Qwgb>iBgP<(~V$-Y$EPw=~6~;NuZD*%j&Ef9$z z_+gE>ii_YFVfR1$_Sn3O;9P8y5{n{b_}k2jF2z=T>6rp&^otUiFLy@b@EE=CPDmU0 z^tz^t-E${irJHQ=YbY+|=Qy22?9ib4OP(76ANH1qSsUC|lgm*&_o{-mLAsZmE_ka` z|LyIAW!9(X3>KP8Kuq7L(=CkX5U$?QGH`xM?_*&_G!y<*-MJ>aSMrZ2X&o7YKLVw= zeR3*`l>9O@(Qg`ivn`O307}O&3QYr8WbR|>K<&*o@kEi#4v%gcC6+|g1;pJj{(fqw zXAzGS7XbidlMcc9R`pbRku$!RlIQwH1TKYNC=PiuG!1$SNq68Q08!g@^!+7I%Z7KD z;|0J6WK@O`(tno6rMVJcmL=xl+z5VH4GDOCwumHQ#sNuNjMAqE3UL#d{%@b!sT7*j zhhUKNsF@@qdB2SaNfMSo$M!1$7#>Rl3{MRi-SNhFGpl!3Mx!DMADH)NUaXN{Bf>^MnE56-r+YSEqm^5?@s$~DN#DU zcoXP`&7+^nYq}@Fzy`AoINJX}e?cP`CFY!XI-tXsyGT&yBKsJHTJ|VCi1qJF-O-~t z>w`R-d6}q!L1}6`>9sT*4~xL6P(4S@ZFOv6&Gd!glbhtzJJkGEDlBOt9c^Ff4KRWvO+p(8e=JPzilFlS5!Cf2&i+`pZGQ^UAX9g?f|LB+9Z;{ zBvvFg%ko{N+@_oS=4gVM7(uuX4BV?p5e4I2FuKI_6lGiAJ2n5>jAmG*z=TpKETxs0 z_vSMwK@Hf;(`SVpScwtqy(L;j6JqKMcoVy`8YEw@J20i`rEU1i40Q)w!p-vYu##8{Hq(h}6CJith#SrG|!Wa#m{2(K)Z-r5QR#P;ehvIGvhSrI)5K2N8h~qu#fP zXw!K}V#EjHu24z{w=NaTA~#Pi3dR?bM9lr%ak`^K4Zx$N?_YPDN`h7)Lh6ADDgh{Y zxYd|1Z#}*-xCAs{&4HW9)+QR(N2b;}6SUkr0Uy)$(9a|(P|Hg1ik*gEFMav&NDhB@ z{Hfhr*dThzFi_->sUV7J7@kz8>2g36MP~>;(*`I!wWJ1^xnNJ`7AwS1%Yih?%9ltO zvTHQM>woAwmKx z}c|3ly$LY{#fc9jTGkJm(vA*0M z*q>5{Rau#gz~#+$Q1n(stH}|Nv*F8CK@T}0Xo*zkUOa8Am#y1qy->~`gpKN6q&*)Ig0>ez3A@Lj>=J@d`L^z=-{DW*A_Tqx^?Cj zy-@I3F)YAIU|)$X3l_1F1}^u#g$X(doeF;#V%8>4`JM!0w-f~Rd2)9!1WV7AaX~*PqI9##?$o0DVVEuSQ5`uF3E2!W zJ>_kmM_b38oZr0Nrgc6yRb@$=sG(KS%4GebA`3yk$?FaVO0}E8LoEYh(2RlSmEqFr zGr73yzTfsX^$BM*NXJwzVP<`5fe1=^QtZVdv{&0*Fhq&Ne5VXP=2t{R@uwOHnw+M9 zCTI)i=|0of+Ou9lKc9AJ4y!8alo<05Y~*wm`jQG=*kEisN6Emsci6f$kfFpvz}8wY z@~n33i8)7NgeqiG#7WsM6v@g`GN@rion>9!Na`xQxiV7HG^i;oewJVDs??g}9KkFU z%LDLVm*|o#g0KRK+OCoptwJR|69AvwsUzBS7FpKm;|M1b(q8H(PAo|jsq1KmMW$Y9 z3PJMwDOYUEO};+|)rG3BENPAjq0AJXt<`5PGjax05*)CmK^-T2OIe*)_M|3EG34Md zhPusm@2D8DGKQONd$aC$=trgT7-Kil{p(%=iodG$nW}hhKnBdQ%ZdU*T4cCHg8`u_ ze-e*b#&oE}QkLPhH860}3*eZ7alO*l;J%3q{#;Z{4cRTIiJ;$tn)V39W`kBr1>cpB zpy_elOX=}BM|>T*C5#;(l%`ozl!q+Jj-q(|Gmb=VQXzxo1_Rt?tfr4TP^qT8Xge`< z(9-E$L)KGOM&vlzUE^-{xfQ8QzOK#MP9n~4%c_oV?vs;R_eOP+hS7x3P1K9rLWCUZ z>`G3ko5kUknLvVS8NLiopwDd(LWbWev5XNA_-!2PQ`E?nQoLR3y5T^JJi2I9jEUBFXg#1Zp`oJ}N&6Ltk!~O&oB7OAXfQH< zU4w|^OLJZ%=*cDYT@_iPS(4{s8um~rT)zl+kcunT8JKZREp>2;4}p+Ya+j`Eio6e^ zgqStX(gg_3Zq779ge8|WkNDE8UbdEgf30M^%#5#-lo0(=5NpYZXJWjyrf>It>Mi+| zDV;3lv_pl51~6hm!rn^Bb_sHM+K^Oi1k<5JFsNldd@>Pf5ro&8guRxlgJiZlgSEVg zILK_>dDUzMX3vGupo^BfVga);(#BWLFsN(mw{!8@d^ z`zz#}dwb8x(e1?e-KUvI!%!+W0t4FC>Bdm%zMYYURiVDPLmD9#fEiAcNcyhH>n?)M zu*ZZ-o`l?%J3(p4U$cT&(;Q}c6$Spn08ZEOxZUUrNaiv}u<|LBal0YkA8tN!d>&A? zfp-vyK`vrC*-DY2tjA~q?~KA8zwwZ)PR;ydYU59%wiLSH>EYNK>~VHXYz9@=Z*n-) z(|U=^6=EKeJ9!E_4Y;=*}07Gpd$EzB|6{E-ZuQHLtS^1~e0#$3oV&p_o$RRWouEtP-3+rwD6e|9 zlB)D+P?@S_MX;I<9+NSo8ED)UEo2O^ka9E*j-oa@|H#k;5rUgZj$M@C#o_4kba8*^cE}Vvh(fZjy4EdZQ`A#@^>{iOI=+=X0%}L0K`Hq~gouBB3S_G)2bH zTW5%$mlj|lMuO5u_~=lHR5AzjnWuz!QQ~c}sXU!haz-P;{YMwg!ZyP%UDAzI{2aV@ ziwP%KEP-sExbo#!(-g0>Jf=2$P{?)}B|?w;R?iK{w$%YeqRnI3d~tYd9@f&nr@pK5 zIdRT}Foh`fGwWuMk3XK7o1#|W$RBwb)76la(5v=(MEAWV(7gHma1qS?mwueWRP9*e5A=Jd!Iu$`=$Qkj;9*)@q++zbkE zfNc9VL6qi+iM-Cnl{~&df4t@wef_cQi0qxbqVgx234`^dsN$>2iiKj#tbVv?ER4Ad znyDfx70b%+X9e?;BW_Bya<7LOE#8NRT#-XZ1B+!hP~W+5wF&a`vJ_5|v_dGj2+Ow<yX z-FBk#_R5Sy>PrCq*;P_`M~c+xJ26scvSA95{GT23#l7T-DoN4Yy(BN0p37S|s#vG< z6W&3JfQ~Nb(g#1RC4F6K*fWP`-Oe7cL8xY9_fVScbMBi_4T}~uq&)~Nv0Og7(;tJ5?&<9#W6ce$f)5Lw;bF4|26s4&6 ztt_f1K)*|K3Xv>H|NTi2^1I^2JnRnu1+WZQpOI!iA5|vOPwH8sNpCTf>_&DFn?& z=V=JjfvoaAC=74;f}B_dbU57yU0lT7^krdyYuK%lYLAQ%YXJ0u9H>Ws5UpGR>|<2K z9N0Rt>j<=n)$wd-as6obara9BrNF8M5~g*a3|n!dI!6X%F&^|pU0&!(dI03gcM)_z zhzZ&Zb=V~CfBAIn>13hO-8*WTB5ihn8yzJ?^rrE%ewuE{@yEOpvsv8n`YmT#UPW02 zT9cBozCQJKrqYh5l;Xw7p}P{cDWB8u=Ov8>&B2zPsgbp_IX`!wwV{q@I*{pf;1*KX>BA6_jGCdC_x%#yv z=}@dsV^t!<_56|TM}_mCj|JHvh=vW=ET(HPQ&nJJ42=Up_bmI;lkybe*7%w9$l;S0 zu9nJzsn)vVt&>-;f>Z(*Rz#r(hu^q0R)%1rT&u0jY&Y{>o4jbh`yt2Q%2~vu6~+DG zs5A_o57%K;P4AE;_X|`Enk-$bh9;$=bEbKoS*u$ed-Q<*_FfwYQUIA=Z_BpIgqJv0 zbH6VrW)3#4rH3u~jIa7ASU&urcYj}pX}{b8G4A2nt=*+}U*lp4jI&+%(e6v%R(*Zt zMP4LEqUMqY10Ge(4`~n)i%fTiHg=_%NcenDF~vc1m^zZ_ zHx|!V;8}O}*KC(F&r5^3vuGWRzl{K*@sEyuBW$Pzs4b(TZf^H)SJ< zxbHm}j{l${Ka(>KtaUiW^}{Ug+J1(jX-T5A06$aIeIKSD!SUUO*mUc`@YZto6S^GZ zDYghUt#&jr2^EVEG>O#q@R`w;{^h+LI@b@c1=l2R<)LZAjNEFYU!mneKjC1Y8&b6uUA2^Dbw6aVuGWT_3RaV=~`ch%Y|y zcqd3WxLZEH8{4DP?>(rcOE;ZomvUn_;@Y>Ch&lNOX!>`rSiHd3inNAq7&_TZIlad* zYW)5>U`M9YQ@dc`!v^ysIb_T!A$N<}F(KA-wLlwx6%VCnj$5G8;f)!7;`Ze7ZtO6E zrqMI@YPC>RliVAw6Ic$@%A>T9vbUuI+0_Siw8dBG~?Bb*TCYgbHtYKWmhbuz8i5nj!taR zg&B7;@RK4?e!YfMU5QQO3WsppvPLZksbSQvZ8ATPM)C|KeBn0Z{n~%2m%Cb;mo6#! zNsd+oi=lPnIHK^Pyw;DSWsX|k#aW21u`0~S!lj7K+N^&liGz5;!->4{)$JT8PZDBd zzkz^*!kSFZF@vDj;rSi>%w=+?1hzVQ((XTdU!C_C(tPsE^%-)zc}c!Q1C0DCm(+@ z6FuejjxESu|MXFk)v}NFNz4yC(o6Ea_3~Q^U0nV8q=8q(URAEzuDLoDdk@}AKT~3D zgpC-1)IU`Y9uxk+Sw>z!Yq3%CllU1H&O6j?{X}0@X!M`PBC`EbE%^X z3Ep3|rqi zthT$z=KYT_q#7?~jJ?~#B_fbq(@mjh^kV-^{+$Bi2`77E>#Rq~&+0AL2S>nq_|0Ji zuX;Wc`7PX!>S;5LYIY`KLqAvZ*~h+hJ0Clkc%bI`VcJqLi|Ug5_4e zEK)d#zS6g*(e2J%KBxL^Ire@qMGa8kj zKe;?FB7PI>NwIKP<5orGR{PC2ZZ`M@u^GWb9WU=cV<@pvg1nj%Rs3L2pYMx!sd0GE zlIxE{i&zW%wqic7vu82rA2x{HYMp7nY!HbwPVMv$-Ec+_Zrbk)FrMsz_j zM`~YbX-Q+@A|ZTcrexK1V+8*~8b3o)&yMjLjzU<48_>HenJIeqUDXU!s6id}>&N4WRAc$(jFTSt4un+IvyYVpF zHxlO4d2+baVqaR`D}aNv06>ia(37z*arqu_|Lh8?P2&cS^;fTNCe)Mfnw-1n9Fikf zqFZsUFO@G?Ek~kH-xhSh^rjhUI=)Z@U9jH;JQjM$(*Y{I-$%qCy|+(OJu+8HJ|g3_ zyG93sPHe^1{f$|4V?@yAK|kBA?G+L~OM$$h><6G)?@Y%2y76xD{|(rzhe5W~n^J63DKIyDF1@5ggL)A1B&A9k8SoUjxOzgM}1hHh|-r zsx;OSzFUj<)20#lIEOEe=Be(ns%H;?&dw5@M+Wy;RH@&z_)8w0%OII-ix33_bJ2a7 zuq&W4;AuYJ!+6k>w50qN&HxIrO*^IwyOWA!(M-rXR30dvRuOdGpD8zLT2L*aehagv9MpyhSLW=t5N zjo>&;<+oO&2ZUkd=3KezJ%Gdc;hpRa98pUgx_KOSxQNG{)RiENFiFcNs4(4+2CW~+ zF8G}zfPB;RfF-0vQu3_LQw^71xjBzG6_ULcX>!HaqZgBQ`Lp z8nit4#_KivdLcVek~sAfWzKJ81#GKy9+Ok1GWN`e*P7>L8kq7_pML3FU7 zC#zq=^%w&!|NHSOwgPiqaq6H&VP0+4442XS=+G}`R1>s>Nxc4IhtNL4ddZ4awgNhz z4Q%g7No!VO2VLgIs`v}_q9*hPya`*wzraGexh(?uI8=a(Pb(6iA(e{J&CHnw%>W%* z7UOz5D5Ts~dsd(&CJ9-Q2Sqd!;n&FeFUZ=vW~tdWJll>^*tPCZa2s~d66V_>vfJw_ zX)YFv)8F|P2@PN#?BYJ3qZ9KLrLW$+djIp)p8de5)^D>PyH3Fj>Rm9#35$DkBy!HU z(kU8;?Y-&G5&N>HXsw=o6{d72U*fq0tF8C`9P@%&R#?NAb>-0&orUSFy)DRSxkebl z^-EHHtB-T5lX}?Z+17{0rpFHphrC`6ATn4DnZKaC?aSoF{Ulx+)*edu;lnylc8m6! z5Qmb_t2H6lOP~uWl)t;P>{~WXM35#EY1Ljg%C$O2Qta$AlQZT1ttj`haJ$sw; z7fophux3eo<~#9YUqjgCR2IRTV2JDN(0uT=9(WrPl<})sRX{t`gjnZ4avQ>GDg^hf z-_DAfmyCBv=>2So7W;Gh*%xPrB3EV6q7W*HOxQW{57(+IE%NZF1;W*fHKkw)R76U& zj(PaP7wTTjZ5upGg!EsOfh9y^VY3XdaHfT?wk?a8i5lqxg-F33rj)|NDrn8>vL(Ef z@5-y>?QjSWe3^fHC3BD2T4&+=#^r2K@1URZ&#h=ajGT_j zja=d=lFP3T0@1ARE>3P9(19xGw@jJmgfqdR_qTWq>!g(KvMiv(X~7$i7~b^jG>K2! z<}o%8p!Y!A&SGy(H_23^hlBfFjCxtR5Phh&8E6U2w3+-TDqu*n%Kg|ZVKMxL%I9d; zg0Y#H^<`ZJXPplW{&B3r_y_|bYshSNGajNC^HvrOd$Q%u_6{^5-!(?z_flGWlcPMBp9FulUOTgKbhKs zxp9+<*966fcgZu7RoMhGaf{5Xh!NBvUgqQpn>C)SNi9N<-lv0B7=R(7Ua7@xGm zhsSoV6)R+9YuDVyzo6O7#H^n55m)$qtg4u1GOd2`mA=S(k}|02)sC zxzDwrg(|mTp~thW-Uf}nbTRaz+4B8oRrOu0?q7}49qd)AxzQ7Z_&D~q*xUStcpd0T zO^#Ukt{ul0Sm4wVkN|mU%^F%}bvZptX>obJ==FgpI2|KNc?h1APN%=hy41zw^1fBm zbzzSDz;ABd_2`wj``1u8VVOld6&Nl#kK(&C?hmkt&qKZ{hd1L;Fg`zr1Vs}}1q{!L ze&klx2Om{rkhrrpEtJ~svGXCqKy~Q1x3z_v;k0dK&85JT_{KR$^-b3wt z9^=Pb9K<11;&~+=y>7gd^XW}>hM8*g{ObtO;W;k(SpWNvBbC^XBQEHPr}u@3)*l6adApS;$ajjmHy zShAR1lJeTjF*Q3msnQ^X)co;7mdYPwU}3xTaLosD1y-Lj4ra#k>@TyVwceP>zptXB z>Fu%fJfvEt;)@E*nltOwT6Zkjpl)ogMK8b3?f#gw`;X0-kclr6*2dh+-FXA3>UfnO zu$JC}-wYvuZn?X|kRh~dx?UpwR?ZmXJvYrgl~{TSwU%8v<%mS4Jk$pV{Mf4#`N7h> z4;%&S6#Pj)(Y*1s7^dulSc9Ol_{Q=UIpru!`Qzg4&;k5K|1LbL%Pj(5LknZGlq)1h zcTRc%w#NJB-9eyCiqy`3XMK3NmA|gb?+B-9YkU!Mmw^yuT*4MXL*e&9DdHy-)(%O& zr2+s2?- z$O7Vp`L4Kol76?T#cpw4`{tW6qsTG`gZF%9uS)bHOPRpA%HhaqJ|!TjQG&zFt~|mf zK{50c|E*?W8P#hH9j>C-EHhkYLtQ`0(L}F}A$Sg6bI@^h!PWo ztTD8KEo0oaP_BlOox4?QX)l3vL_H#d^E>z-#rD5pJoz}8m;+kK3~xNRO&XehIGtGU zvZb~%Rw{N4w#A;x`MN39tTPtjW`Df}5hAFQsiy*)ZJ^o7I4Zx1b#pnY8K%ys_j|VB zuX5?LHVE6{TrNBP+Rz%T3(bIYdaXysqoq<0%f)4_Z7p2im5^E9t{Nuey8?-Qy)0Cm zk%Qm;?ybi~J_Wvlb3y@uDdRx@B9B})|xdpb1`eU z;Oaf^yZ5u7+E4r*vdONv2l(-WMe1b;E+Z2>!uZiFHO?q!tfdUu-e*IZt)ypmBh}7^ zi+21N942RZBCiAyL6cqLB}%ih`05iLek6(yTi)Ts)#K-c@n}-_FT;m2Nrj6{n^=w+ zo+2=a`l(Jn$~WG18^=3b7`V4KmLVYa@otc&qj~FFn|k4pS8YeqiSjQ70`NGXjmr&E zpzW^j(I%e16XyeMxli-$OKbfieg_W}=V&Ap8d{EiJDNrorYQJ`m!jhlo0Ic7efg9I zQ-bVM2Aa%L#Jum!A1h-iUmcA+=e2rUB&bpE%3+wdF9QwTHryO`-s?!EH?u!2*QBDU ztrABsY(Zxuc(uNqZA=yMd$_NrgO+CZGx1vTXZTkT^qhM`po`@SuBVsmKWZI><;>tDnIkMp^r;~(D%#B zM`THhfJBAz+|S+ZEt()=;ecgXrNR=I{FQNK<$}>7<&+Pzw;QJ?7#v^s#fh6bCN3PK zL{txTD9siYghwCtjTz)*NNvro_H@3+hbq&NJT}9-I9?1`4rjKPUP}o~6Q6EBt)2IH zm`*}~*`Gv2uCTN)VASn}g}+t%mj9>K1tZ~LpqTq%Uc(6kf-S?Q={LfGys^16LtBMp zlu1fysc>|pE<{>q`%Fz^9m_!eP>Az2duLBH_4N^R#V9Ujs}A8Q+0ujFY?}hf_?N$y zZ*Z)3tO+QpQxjs0V^lJv+cm#K=Py(}t;N<_oyxH-JK1ANdP;Q>cC9nM<~Ocn4qRnV zuQQnHF8|~9K)VJ`*u+2@TaDd@VLd0soReTgPAfd(H~y&>d&xndgDo zZ1l3{v6qpBwLyloY72`rLbm4yt)>FHJmOhw$|@PK|p_W zR5%Ah0g9V;zryqK6_pC>e6v+LW>8Qu5Y>)jsw4t#t3)1p6;?E7Pb}^iOxhzZD(vS? zOeU)`=f)L>myd|UBnIAbNEtWh>VzNH7R!e94AGvaXWBDDQy#Lv!d&dplCN#@$?^Y{ zPmk)j3bA%xTHZpqWXhcXwNA z$VK`oBmQaVJ@a@0w;6iG(T`RM5QdnTc(C&wSf1YVJv6pPx zSF<^)1`@vWd0OBqeu&;AzQ)M&92ZjRlC!o^{n8IFy1_f~7{p_KcTsBZZ+~yTUMVv+ zz2&EHudaP#4#L#*Sogfl~lk&FdRe1dw}V(+&1Mm~fb|tK3X_sE7-_ z^`Syem<@KA=4gRtzP7%7lKXiE@rB7`CI`FqFonrXA?^OwOf2V59-{9~K96E5&l|*j zOK7uNm&vU>&T7h4anPv->xl2I^pCqr-`3*F6~e%y&Zy8iHhvW2D-nq*z5(ct+Gd*iELn!ZP_?9IcU$w!Qi3@=G7jgoC1SL>fiE@I}YD;Ft{=E@%# z7DiFYn3+uFvdJVpMF=xu?5%N_h;giQWVDwvKBl2p%*a@b!)5df_&VDhc;E{sNw?pt zi@$+Q*>4ayRo3h)Sq@KaWuxs=WTVE(77Dl_eV-BkcW5d5sL5}(#h$2uM`Gt&3lIDB zF4muos3@*l9@z%G5{vF2Chz$A;NJIdV6)FlJ{gU^imh~Dq22nHeHxwvOWd5Umg0~cOJDtfMa*;!ltI2Klw4qf%^L=# z1!}O-TNJkvc)JF*(?8Jx)$d8gb1m3~D)pn`oUch_BVWFwR^l`-bT8$tbaPzK11&&M zf1~jdYS4x;fIH5vsOMbx_MEhO8kT9vM?fizHpAN+&m9J`;0v6;s!z@yo6I@H_$fF& z=Mh5I1fi)CZ5<*JP(Z49zE<=sOa`!1ET=OKu2ar1aO+C=!4unHbv*-i!5vqzg@@ny*%rN&CZnNIE}0yY zFbyG)o;BdXlBC$i#-+D=efGdAk51PHBCs zs;wHJP&Dg8kHrU}P4&e3b`Zq#%{%J+WY4U;C!UH;&bFl(L(;6zRMyk$TLvDtWPk8I zp5Lgp7u3noJwjsjqAm|p{^S?pc6anMXBP}n z3b_ZVvY3A+nc0TQ3%T>dsY`5mGD2$dEUX6^lsG0>fBNYLCg)o*E0yN9Gcyd|xQFjq zx=x9)R*C{Vta~CDVL;-w&%~YGPk_jS=yQsm`;o8xEf#@88P1?#wM15Wc->jl!Pb-n zdPFVVPkCi2gV-J2JFzK`bAAo*bDfAE1yrSt9*vUQ?` z5>NYAt^N9v2xrhE;G5jON5dp{M@@rTGCtmgF{WN9Sw8sTgoG`)3SD=t*cDRM_m$?f z824um0+>awb}EjVoIl_#lCF*9#Mnfrz}Na;_Y--dKByMn@&V+IPtXXWuGziM@c&n7F4|NqARP`*ZM^!&O^#T{&feLh14=j%8%>f{l{nP z(b+%TD_pzuXF#_lXT5;iPWbW1jgC(G)2L)n077UT(J9 zB;r1uwsvBrylxhZW;2YG!yc0HJglWJ1l1-gf#3aEhke_7;?};>s(vyI1WRIV`kn2> zBt4flVVBiY{isms@v`b;nG(4Z)qXXAJCP3hm7&=To!OueBjPOMT7p|cl43`%kn!AN zG42ZVp12@&3}3hG(pD2_KXnVi$cXob2BFh_+T(#;$cM`eImgo<_nsBnZ`)iBhJjTJL_PfBX>^%H`AHXL4M8Y zB^|6p`2*=s4;Xtuc)nl(&;Cn9wLypVG3U~Zb_*s-EH> zE&YYewFHNgz1jqkgSD9cI@MOx$Y|veHyc?B!%Yb+W9xmDB0mGDB%y4bIY&!pVm9V{6N)LjTxeYh4C*{X9ecqG-;w!IY6 z)5K{mzXX~&86Vw|<(_ssJ1+0*R~{U2+%FP_7SKJu-i{wn&E~wbV7E3*U%~lw$A^-8 zC!VdZDHeHpt&{c!x5at2KpSi;OuuJCJmveG; zod+~OEE}*8P#UQSFU;YGbBYL!$68PlK7B8n$tDkf!o#f@@##sf%z~S&ibF14BTDE2 zN*ry2@4bBrLCSaFvj!ub5@F-b1mNU;){kTkkHN&JZyRk+${qa?{XC?4kRTT{%n!U_ zN-rjn)heF(sI?hxom4s;tjzSWq1*3pi(an%H@n9Oj%56vEwl%DyC}CgT4{>mk(6G% zRpWSwv;W}fhl_Vi8T2E{^;12mpDJ+K3Dy8C&LgkK57gulkva9B41r6<5 zYS#N7Gmhg$S!lEns?O?1B6O_%Y$P7M65FC*JvI%`74o2q97L8vC3UssZkHNE(^LFg zX`#dk4R)HvkkUj%3fD&)iKH34sZ5!vzP(3gjmJRZH_PC%B-}BjB{=s-Wl} zlOb7ChO#)Bg)7gMSSP{dGhn@$dJmeoYf4-ye!`@dndkG1I~8ec%VLN6R*BQn5{~3f zuOFU+zRH1gSlBmj|E+d_g#w`&QV{fU`ii+#jWQHMBMs_mT`+PBNuqLOTg{}F`pc(v&M5cu~Bpl7y(nUmSQ_xd!3wleUqKSVpb`dM&-L z>OMK#?2q&zqLZEa&HM9sM2fz!hR5hMFeALt3U;nj=@1m29x@goUExNj^RCD4ctOEr zJek2>h4+_ac+QH%T5Y9es{8ZjWrz7mvuQ;ZT`D^MVKi!U^a1o5rj87*tM`>FC9P=? z6fwn~4et9Nj!!v*H)rc*M!Jc<-|yL|-a(gwj{KG`kdnu{FcSN!#|I3&kjSkv;!>uV z`%UGHW8qF;D7#=i#14K<@3LcTsvTLVG45Xz zzN1`*5vB3@b*iWQ5-iM*VI)60{m6352ZIII59?==B#n9?qsoMG`~*3n#Kq!S?IFAJ zFIx#=$}i=Kh=PiPqH@$;mH?@4KZXx0&1W~mSzbT$-9AXEnr*{Iz-5)D%&c{;6{;)D ztCSaB2T204udeIWT6&Z;r2xAPSzYE*6yMKjGW1bLoo2J=yXQUG(LKpi`Y(lieXT|Yoj(w4F=*Wjh|CrIS%aO7 zofp*~Z#-|jdZRJXB5sr=t6^GmpfGLhR9k=XRwtSe-@!79z}q{K?X$=BAnS0KN^GgR z(S0A+uwlB&AjU?jMdU-$<0m7gQ|}m5^G~g`2(T#5ye^y~O zV$Br}4q$}rS3%$9?2diXGM_DE#t7r4o z`|1KngZ*(jP$n*Knd0ZoU{A9Nxc$=r&)WTnSe;R>YUSk@?;0?J;q5AQq$JA5$q&Rc z(x)dK7z;(8WcwhjC_O^o@b+kg84iJf{Q@pq&$^0YpSavOXrLo)dcG_Qf*z znf01*WsynF6))r&AyDSw;{YBOS!e(B`@0*jxF)TWT+mSJeIQXVG33^ z5tG_f)eOU-IbkYDODJ@^FrNk9{S{hBXS0Z4l*g`;aco>(>Q#1uqW-z0ttuOA4*6n&LwbZ~iRO50LIpQKdTO{vh;+j01z(3#rR9`Y zCUcCW^;}zu>b}-cb=Yz=+`)7tq14QAb=G&2&T(FqLD8S{;lvmJ<~Ldxcd2xfAXu%!mFlWe)H26odn>BV8*M;vF>F@t(SxoPm;8=br!OT2m)d#m%b4RXILe~Hj7 z<8q$`4yahlSV4wV&Ylew)`Dn6JIQeA|8Qwl#{ylUVujmtCxTQr_LI+CE9hs0w!+t8 zHu9D3t!~iG8Z0VM!a`ZJyvS~JOBkwyoh~*RB@-ux{`$vD=h_CFw{XJV4|(r#=weP= zN+Bv9hTek=oM5iz1Z-S0eJ)^Zke>HcqSJflR0>gaI+?x6_`?^32~!1*a6bNR zTp`Ktycdngl5Os6Sz;g*nT6~Y;}OlMcb1R|D4+^-XQ@O*>P`9jS8WH&JflNn!xT7K z>Lry8sW|#VLo#T4OY1Rd#i=yJ(R^A=N&KQ2a&O@v^3|%SgL(Pqz#CIqok+#r|wVFY&W1F`oz>{A_0uqWo^d)+MO`8_u62p8$fuu49Z)M zsqGpvCD%_L+Nc_pQ<%FQz`2b+z50n&q)mb&wbU$ia~z!@L%&|t%(%{K$=k+H9Y45S zRA`R1s?!_Z@@TwR|2j=_QzS&~IEa`hR&-vWoMEqw=air=TyMh(@lM)ZAyQCmj zP}26z#s3jxx0`6BYs-(#q>W|Q%HZoxzQdmyJYTp;R21znK1jrb|L;T$WXSECt4ZHX zVUd*^EMiV2Tj!&LvZ%EeHt{1!5IMgW&IZ3=cLj_7&b#Oy7nyYinDfM7(#>G`-Dk{3 z`jMYlK;lo=Y^74!vY#ue|<>v zA>+q2nA?_T9Breb2%#RwVe)6yI~M`P7mGZuFEM<1ezuE{J~ft0I;dZ584tkp3e13D zuJwE#cGRdgqVA33oLz3v+qcvjwMapkzA-qOriI_VC`rNw4-|fuM#oYl1~yLnjhc}D zBsA0k#DVs<;yk!lrW9k?igBQD^B#PyC|B&#Ro%Fbk_( zHa%pBg5LOl7O@Z#1p4|>A2S&J@Pw+(9nD9ahgNwA!86brfh38|hT zb0GR1fnNR~ZNm#PeZ3+=E;jhUvRoF)1WR_XCEWuIHub*>*q9jZW8q5eMJ$K);F9wX zW(%dQd{6X|>^eRSr?kDXHdPdcC^@%n*USTTJxj3m|5?2WGSv#JPD{3+Kn@W%O4O6Q z=?jlVNf$c_`Kx378!$DWTH+H8o$(yHh5j6Ad9)v$f?T2U|MM04`o7-1{B6_!|J(n& z)BOK7tw5f-!(tioIcT9s{C! z*Nf1#$Zqjas(08H(L0WyK>Mhhi~aS;OH6_tQ<9lSNtp`k8fvfpl;vAR`I2hJgFYR{ z4>l7dp_-8*FJ{|Rko`Hw{6e}6VJVS|?O8a_Kc*I&MS8hk)dFm!^E$myjq(F+Bn^gM7!ae43iGx8i$i7i?T$1 zxkNHK#>0Q>^-c5kHe0n~i_?hsK#vs^@2>u0vD;4k9;#W?MsjiU+lflFZ*&ZY<@&7k=pd0 zB=O{g-whXhUxMw5$@{!Qpj>{VbPW{2N<=1ZC)VC1Ugfy#zvZ)k5*ZdnJ{Ufd<*Y8u z&gbfui*~QnNS%{R|2d(^?%Tb5zyz@`$8@dFR*&o!CU7jS6_&=}5r*8C`Dqoad+&)% zN72>`B8~8Te@yvKyAc_3zf!U_1^llE)O|NUdS-nQ*;CmrDciZ1S~SH-CguxcA(!DSep#6B$Jz3Wpw|AoLIRP2cIHE*sWU3DSxWjm+6 zP*FXU35~Rm2|lKQ4^IffXSv~vMIhvwrZ|*wtIqupp0xk|Uz z(t%X*z$tdB%f80b)8a5}0v!5C26 zjBHvy=R4x7yx~2=fr;Gmbh3OqU#uJfR}bj3EDw4txhyMedU&QEcOi{g&g#mKp-fT~e}DKnb=zC$QW9NI%G@*Q z)VW!#`P9chz>ytQ09IZs^pTj&13qWPJKLyex^+%Mpg$mOxliDxuava_K*F11y-w`K zakn_EVX#!FG}8{QTqugvxk_UZwk5A7y(8uo2Yez5o*U$XWIX6s4TtJWb_|5kqNA`1 zeg_re%AlN;`iuyTN(-H?P^z2A9$M?Y1(;A1)}8wT?z{lN z>OGh-@&mneKal=I!_IB)PP$%+CfQ@jz8k%77BVCpk;ypFBE0DwH{JMR@#&mPF+k$c zE`ejnB=IL8>*Jrg?4(nCN52)$q7w_inj`>H?2h-iOFO=pp7XnSc=!_43tG1fLmvbF zox!wPq=ncUwm+=v-P9|#dGO~bke%S5N4&37=8<^d%2RLf!WXa6K!X=dAyqU5Op)+w zd53K}ALBAQoLuxs^t~WxS-I!7sF4~rP;&>R_L7uDEle_6myV;HPC(0#l9w2&!6JD# z83BrfAOIudM&f{0^*n2EUx39?J$~7OhOD)xZ9}|bMhgkd5%tFd4a3xg#6hHYi{p?- zZJTyK-IR;+&+ao2Fcjc%RvzH|prgEUQfJ{Oo5g(1|{WTUAzleuur2vC+7(kE1c3ul{bMrt} z7{Ay7gt#}4X^y)z&=#E;AAJwHl*|v%@F&%Te+_z zkO)Ali*$V~6Yi^_11>#S#;YAh01wqoTp8#DqnPKeqnFVQrLp5L_j!cDf%5LZShR;I z`R;?fT^+2W4}gI>&j(}k@&{g~j6AR3dGPkTAmnAsTWOYG_rO>cMjW+vI0aCyx6zbh zq38f(RTwIxVZ^yEy7lfH;0JJueC8M$@F_JFhfk}5mzP6^YUaX2G5#|kh71r{sI>J| zALr{|5uKvryFhXm@me!z`I~>*4OHfTFsz>jdIJ5}n()P^LgcW71IH)xXcdX{z#+sE@!#;mw?KsoDSPwi$=}1~ z83biWsap*v!C+2vA_0FMc5 zCuGP_XrF!dM3Wt%K*FvsCCnZviFJedz$}P*iizkRp6|t$>yk&%*}3~NZ{OKj;>nxD zvGoRv>OSs1?ycqZXS1{1ea@;dfJP`fJLJ0kU1L3;o+` zsJAFQ!M_kV-t`%bDx4K(n%%j>Q~*e^1EA!(!TczQMDPO;!@b)X%aLcd(k~?b@!`*D znVuIM)$Q=i_Yx2mXZ5E(ZRpcN*HF;z2wwAgidl8Lf9{(Z3mGj+l#?|*Y1U@uy1tSj zTVFk0Y4o|9e7m$k&AX>WB7dJRzV&z;w>#k=Gl}KboZ@KQD6Km)0Q%vwjCc-%g@W$2 zShC{|fC&5>`{QdYow*MXwqUMcDJtZmDLe(+39N{d^|c9H9G?97S|pFnrWs9XwDGKS zRMn$S=}92%f`301jjnye=!sq+suz)!KT%YPmtR22^<%RoP>!FyH;q~ED6U--zvwj~tn_C6Y$)67TgxAkXO`ha-z9kNz z-WnN$zvo}jM ztx4bW-Rs|I+H-9g8!>}=-QO8ZIJYL6WHA9kSdY&t?^xz5hpO8Xs;l|^4EBkN5W zj9;sI=+tsR*g4%G-ZIvbVW9~!WNw^3jmmDLkOzNbxL*dT` zlT`gUM#Ly_&zM2Mla+N1mS-9E$g3 zbe^4<)pm{c8P$9yfMs4B#xP#8IN+9BNCu!>z;uh!L6Yn95h?svEWA{-LZP=Lr4g4H z{l!vCxxuPgxea=TN`j*5w2eO_LYmPAlkyL{T|hSMC%^UhIcmRDSSrUD zK4z2uw#pVeZ@@w{ZGYe^VOhBrgIv94sM4(~5>RwPZq(hgBI}>5YZ0CG;XbZcF(4W@ zuxE4`BQ}w|<(0Fm8m(ihoD5EXo}k;vko9>Xg)5M z=h&H!PMV?p%iCs*xh>6<&JbPvdzyZne(w_8Sfw^xnNjcYlEY+sgzo#8p6F^YBjN9> z(wV0=%i$}6d8b*Rva?_@K(wK-*C;(@t8Z{*627|jQ?aqD+(vF> z{nbHn5F?@|I_E#H5v2vM3E0Gpj|fHbUj-A)K>S1U?ujrW=F=8y{gs5@!Tg4ED)L+` zit6%Xkr1}meh*;=?G254IDbhaO!tCk8<&zmhX#=7%^ix)J(LKByH|4Sgc$;FR}yd< zbMPmcEa`#YV3mDk`~+seq!}M@wIwvcCWr6jo`nOVD7k zYqtP7ulIAruJ{0j^evLQbMJ>ZjeG?^auR4wci@ zAv#&(Nd>^5uLtI|uXaFj4bbD_nq3ghF~ucyhuAt#tu~p6x!-ucsdNj_Rw^zY&Yu>1 zxW)DyYWQ`-CsQY)GO}9S{r4eCsC101T1a@fRHR#}7DGfAEjjCjDx$E5z;XLM9}aV-rE; zhug^}cdCndv8K7o_T72b4s`9(jF;#iJf&xbnp$^rLs!>spz{qn^PHCmYYjK>+qI!D*dKng{8ik2Rw@B z2V-|>xT{ZQXa?8EDVG{A+^iaTC-cHicXxdii?@pw#)VirnN=*K4tm!+x5$5*BUJg^ z4_{ng?LWfkOrTA=y?GLSx)iy#GcIuv;<(HlrZ2@GA=Gye9$xR7ZWBQ==<$sau@0~e z&^6g%1{K|`QC@v};U6Edm39Q5K}IZ!s68HX>lRi$s(n*!7rN(Kleh7$L8XvYmtkjl zK3(0PRMZeEH6t&}A5=!`Jcd)9w^_f_(M$!A8qIIG!NV5Qu%pO*#Y`dR$b;Rpq*s$h zyJX=wUD(oLCr`R;#Gpav%5~<+PML_@FZxmXJiX^fEk}bzj%v>9^&dr}viNu8sdC&L zsgBIEIu<_37EpV5dDE=Mv%Su}{Q=^1p&iFW_6WAvhUg*0HvN)Te=K0cSm#e#AwBb%JrO+`CC^VX?H3(&Tw@wIs?xme zHjdNTji!XpdAD&(1oVq;d+2+^pkp4TnwekEwG9u_Wk*QipQHV0g!XrVl2MAP`6pIS zkzzI9ugns2?UKVe>k-n6)77uz>VB;Sl&plIhmO~6rK{Gz+Yw!e>1ksK z!rE@)mh@>{kGo~bsrin8^wD%D&th;~Q5Y*%=JViqnBnvh7GD_m#$qF^^`>TmJB`vh zFPP-u%&By;CmO|R<1yryu0JWUkkal5^Nq6z4W4$1As!hP3F}F1lkA%JxNmfxz1}L5 zF>oFC_&ksXW`KIymWgpC^qx_dYHLzZr}^%s+FFf)CpyzQh;m*yFZwo@*!`m287PrS zg{81O=?!IDULC>|<-AF<(_(64+54g7P3z3A#X@zrK2KSVg!|Z{KI@s%|0n7N0d}ikmqx#&+cJTe$(w%ZhrSYO&j7l8l_p7B5++`k?Y^6DD?_3`6hCFgT+=xsaBZ|Tt)1lWh zpI{v?z4&+(^VN#eVqlahZ6qUSWGmbJ{Pe428~jT^Q4FM1ZH#m0yd`3(k2d%sFJI@Z z{5A>y#OZ~Oj=F+BQsv&ZqSVTRc3amJhmRto~ zY@S@RnmUPVC-M07nmuOk(qK#J7)70O0%RO<=cil!p$4|e^{x$3hEzp7M ztA|-p8C~X%U26n-q6UIV2<%YmT<6`zC{%PTSk|UoQWSixTp&?E>m9b!GexzM@Y-Jn z#HTIycaOtuKN=Z88z(E;c>O?Q5|!e4rX&sVL(&+X1ibNK!$r03o_7K@Z!4Y;tW%XH zP^AwRREEN9&PI~iuhgHXU@kDG7VJA^g{4xbcWRpA?2LmXQ#;GM5xj(1Bm!KTfK-Sb628oD{ZKx+8jiAKThr zJ=SE4ba|GsQ(6RXAxR5d9>KTo?5SYTf>pZrSH2x26Hs5^iK|H7DdAsQxX+IK9+g87 z>vvu^;gCLz{nQ0VPd=V0jG>e}%unTsyuDmBVwRtT8 zn8BN~>StGveXmBkV!Q9;Us7DTVidxyHKCB0Q9Jy9cS1ZRa7anf^(iXuSbu0C-MD4) zW}Wu`MJ5YSqwW5TPMZGrN^$*%C{-HKZ=-PojZ$t6%~2M5P|5hA;rm6BF{zrScDKQY zHv$CQuNoes|MRcWSeU@2pq2g2C2<{oMxH^zHAnHW9)dkj>&crH;<^r{<${m}H^20u zGlKLDd*@f11?J$Q)GjS^#jb)B&yZIgJGJlmfe=7_7Jc%I?yQ|%R@w}=v@RR{uZ&PU zv-43P{QI$7EDEU1i}8{u+|r%?;CHNuJJY8oXvk!`tT;1UNGwDDgH zVnHs5nIV z1i=iT3BTzBuS6xD6}b$yKg&3fHcl9LWB9|M)J_$5+Mcsdg&SgcVD_Vy5@q$*kF*Z` zi)M1F+ArrXH1nn4aidI|>^?CQ_EA-@XxJ!FL;;BKCABFoujViI!$)0^62qe3XI{&n z#?6c{V$o}y+<4Y~_cqG3ScT0h>L3L1VuIht*+T9zoO9n=gz@SfFOb)JPy2`^7v%kc zMW1!V&h6t;^A~832RZ+e5N=Kju2<{P#&~td_MdtZ z22UASbALe72I8&Vbt67#>4fg`G5(qRx#EA=%xfDN@@mN=oJp(&v5oQV4@0|UK+r)T ziCM?}pL$Zi1)gGJkqGrfinr9bXX(Hja-e8GK!!REybJ zq-HClY~K)`l|N$`+@L%1=P*E@g6!}WnEv{=;cH&(Xvh=*3&^pR9@&l$87c(g>0Oyy+$$ssb{g2!p1* zT1vl;K}HVA4(GXn|IDu1elDVG0I7n6n5qU3w6?W|u1CzOyYXNS?u@T~&MvW;>{k#27+N zM{@0Rk*%9qvSfLZbpK+Y6x(`U0D7t$Oe;gq@hYac6X7X^(5SI9j(PI>oknV}7r5^q z)9HiZ%c6~w4`@0!rmA;y02;(|5Z^UhOTK-j?>(D{QK=;8NZ-D?cJ20On5d9)a5#W< z>daP1vl2qC5V&3jhwEcr2Hv{R~Z@rHKGIaL5SSa2bUhhmZVtg?baqO8zZ9h z+{ZIj7{#F)IE5ayIZsZu|!jKs{c=(+L_V(U&q!9D*4D(OB8N4xshIK~@1ka|vB( z8H#*V5MvM3uD0m}^Q0gE1NWtV@+={0AuLl@QH{C*oP=VYDsup#JQ_+UuE44MqoPXo zyeHbhL$FNM!F&z2>XXgd41jmaVz2lwDsn5M>D#B*y%uL6&xfIZv07H|Nd#L01F3rO zBxLZP-YLG@k4raEVa^D8aZBmlYkD+bOQ7+hCyN}5kjW}Hyyc2+g7?wEtPU!GkAwgN z4&Qz{*&7#12DvB$iC1Gmu3!!~!$-b@XfV}rDun|dJI&MmX=YzIa-wR^NsV<#L-pqk zmN-qN^V6e6fKSae^z*+CWB_Ajrv#*h;~cxKDemNX;&j=UWC6UhPlSByr=b5wFVT64 zSfkA7?#Cu>*t@)KfSA|2RRkbvyXy~U)`yQ+8-BMiRr4`+K43QrF`FoZftizA%G|zJ zTGHz=Mw#WTE|?HyFvHy8C76$TIPI9^442{3vE~EAx6BiB;`rTaOjW{h{RIJ%cm~My zLe0KCUVgZ~q;w3h17QH;mUeN%w1}e*Z^e%1=6_f{13i*S z<}2+Zlbi__%YTENNHtm}2+&Oz6J0l-NPR}0)cwaVJi$0~;p4+COQq8~C>Z4&0dk=* z02>G9gs~(J!>EbnUVu@bJ7B3X%a6euH(@tV_Sb1a#+X~6b9iDuEF6f&hx5UO|N2a^ z;2N71qgvtHTPUVp8l?uE@9$FaPJ7ydfZ?Dg&;$3ioU9%mZTn>nUCX)7pO|p!XQA0V zUuN76r=fN$@_i@CTPA1UeQ@DB3!OxAQ2S%$Bxdy*yPSou36s0x@|0I6dq)}23Fk{e z<&4QeNk8rq_Z=&OevJ$Oy6#kg(p~*?AY&R7%|BsN12d{9Ep#l^J-bYGvkuQY$UWG} z*{d2d7hdU%VQ1N8!4tCUR-`itN5%6s%O&j+p8gl}c%a$MegIg_(HbZ?Xmxk`aak}4 zndpEHcp^o7_RQ{v?tBFp4M{WJUj$U#kv;cXP*@Yde(Vu1JT3>o_PfpANsP+&Fb9Ba z58>t>mzLLsb}EMf96(7gRP>(KFaHQ8_zm4oDPX$Ru^aSOwa5xx@DVz#r1-AY83=l_P$XPUV2*(PT)U)Y$l1+YPWS*;g0V}3) zety^($9w^%NyZlcOn=#ouU=`9pz*GN^ct9|MmzoN2^b7JP&6z`&0#!%_KxZk`ks#` zo51~k+*@m-1*Q#y>)#qZ8ppRK$V-`kPP2n$CYHZ!y%A=#wpXKP>NJGqwf@gYa-u%t z=`Ymb340OApwg9z*+mhO>A9(zPyS+iB9uMnDWwqFo;@AF7~R!i)EkQLlr}#BIyoKK z=p~|cY_6#g3Y}EqD+TCzfjawUH|VHIC(3);wvX>zFNE=}>I+~p4OE{WiqV5I6eF?~ zr^jf(n!pp~#>Nj%k9LzR?1o{Pk@vZ6(pN^yYEB6J4IW$Y7F=ESxKLysE9n8~0xhn} zF1jE=d{n@7_&U#c0F)-(*Cl+kIof`JdI>U9ma`3p9FH;~Y#al_lI#QURkKqII<>!^ zC&~r7oqs+}^s^P(=DpcC##1%Hj&ZITCn}!%_wX?olPw=^Y$Ic4gNB*qdS*f^eZG zE-&!nR$eY7e)?_~o*Y8DK$PqHplB)3M0GQtD<>t|u3T7L6gL@wP$(ts-ANDp0nR^}BIFJ#77Jm`(z)9|;&Coo|?}UJxhyfV=l-tBm(cp)C3_ugS zR7w^NzBBRe@AWDR-EIhztQFpuI34&BkjEDX6@xZe%8+BgY^v%Bxi@5Ly7M>oVCU!6 zp{zKx-B(iZKILtuPU!+=0pkHV6o6Iz%3WcdE$%;ZoQko+78R>)0gAiw+a=e-jzmob zeqtnfvMi5^veDDSz?jx1SN2vS)YX}JF!C+7R~JCu!|{5s%y(>4#GMo2nYyA`yBy>B zI<*xrPSA@Vvq`7@FN*Y3P4K2ntTu~!aT6q}<}~2C7X`)&qdogO;8vNmkAvP_48>hz z(`#r4TeFt0Hh_2i*Jv{Z%g2#{9fn`qZt@xZUW959hg+iu6O*H?;njrbWy>; z!$=_FNF@XZvv`*X%wk`FL6+S0u}$`Owv~~hM1ygk$06T;kv8d#A{Y)hx5|;t^ahny zHa-Nj8peEE>re54JqE+7$=Ti(!IokQVmQrXj~352Yqw&TIqV&o&IT94u3ssfZB4;2 z*ffSh<6gCtTcnJ@hQ(mI|5#KiKiV8kF{pV8yR$+Q|E%5OTXD)!BCB3QRk=UbO{o{a zC0%k%cL(OL+sr+)Q$Gf(pU;D^fEk!z*{|6H4`!#6HYr-~n4X>5w^s&;QIG2kOj46)^OSQQRZcs^;WMer1N&e%N@Vo||693fRQypyd^{5vc?;b_ z8^xtjY)p0A+)@0nng~yvyzlnS9XN4W7Yh9z5A2RFdOV))k>la~^Db2c1w8q8uN&)p zjW~W;?#`-Jkw5-6`__ +and `PSA Firmware Update IHI 0093 `__ +specifications. + +To standardize and streamline capsule creation with multiple FMP payloads, the `EDK2 capsule generation tool `__ +tool has been integrated into the meta-arm Yocto layer for Corstone‑1000. This integration involves defining +build rules for generating UEFI capsules as part of the firmware image build process. Configuration parameters +exposed in the recipe allow developers to specify the number of FMP payloads, target image GUIDs, version numbers etc. +This capsule ensures that all update payloads conform to the UEFI FMP specification and are ready for +validation and delivery by U‑Boot. + +The FWU solution for Corstone-1000 is composed of three primary domains: + +- Host System +- Trusted Services intermediary +- Secure Enclave + +Each domain has distinct responsibilities and communicates through standardized interfaces. + + +.. image:: images/SystemArchitecturePSAFirmwareUpdate.png + :width: 690 + :alt: SystemArchitecturePSAFirmwareUpdate -In addition to always booting authorized images, it is equally important that the device only accepts -authorized (signed) images during the firmware update process. Corstone-1000 supports over-the-air (OTA) -firmware updates and complies with the `Platform Security Firmware Update for the A-profile Arm Architecture `__ -specification. +On the host side, U-Boot functions as the FWU client and orchestrates the update process from capsule retrieval to +payload delivery based on `PSA FWU DEN0018 specification `__ +via Arm FF-A framework. The Trusted-Services SE Proxy secure partition serves as a gateway between the non-secure host +environment and the Secure Enclave. The `PSA FWU service `__ running in the Trusted Services +implementation forwards the data to the Secure Enclave via MHU-based PSA calls. Within the Secure Enclave, the PSA FWU +Agent, conforming to `PSA Firmware Update IHI 0093 `__ specification, +orchestrates the actual flash programming, metadata management, and rollback protection mechanisms. The agent relies on a +bespoke `shim layer `__ to abstract hardware‑specific flash operations and bootloader interactions. As defined in the specification, the external flash is divided into two banks: one bank holds the currently running images, while the other is used to stage new images. @@ -336,23 +370,55 @@ New images are delivered and accepted in the form of UEFI capsules. :width: 690 :alt: ExternalFlash -When a firmware update is triggered, U-Boot begins by verifying the UEFI capsule by checking its signature, -version number, and size. After successful verification, it signals the Secure Enclave, which then -starts writing the capsule contents to flash memory. +When a FWU is initiated on Corstone-1000, the following sequence of operations takes place: + +#. **Capsule Retrieval and Preparation** + + U-Boot on the host system retrieves the firmware capsule. + It validates the capsule header and parses the FMP (Firmware Management Protocol) descriptor list to identify the payloads to be updated. + + For each FMP descriptor, U-Boot: + + Splits the firmware payload into 4 KiB chunks. + Invokes the PSA_FWU_Update API for each chunk, transmitting the buffer address via the FF-A (Firmware Framework for Arm) shared memory interface. + +#. **Secure Transmission and Forwarding** + + The PSA Firmware Update (FWU) service, running as part of Trusted Services, receives the chunks through Secure Partition Client (SPC) calls. + It forwards these chunks to the Secure Enclave using MHU-based PSA calls. + +#. **Flashing Within the Secure Enclave** + + Inside the Secure Enclave, the PSA FWU Agent dispatches each chunk to the shim layer. + + The shim layer: + + Erases the corresponding sectors in the non-active flash bank. + Writes the received firmware chunks at the correct offsets. + During partial updates, it also copies static partitions from the active bank to the non-active one to maintain consistency. + +#. **Finalization and Boot Preparation** + + After all chunks are successfully written: + + The shim updates the firmware manifest and the EFI System Resource Table (ESRT) entries to reflect the new image version. + This step enables the bootloader to recognize the new firmware for a trial boot. + The platform then performs an automatic reset, booting into the non-active bank in trial mode. + +#. **Trial Boot and Confirmation** + + In trial mode, U-Boot evaluates the new firmware and issues either an accept or reject command using the PSA FWU ABI. + These commands are sent to the Secure Enclave, instructing the shim to update the firmware metadata accordingly. + +#. **Recovery and Fallback Mechanism** + + If the trial boot is successful, the host sends an acknowledgment, transitioning the firmware state from 'trial' to 'regular'. -Once the write operation is complete, the Secure Enclave resets the entire system. The update process -is tracked using a state machine stored in the Metadata Block within flash. TF-M runs an OTA service -that is responsible for verifying and updating the images in the passive flash bank. Communication -between the UEFI capsule update subsystem and the OTA service follows the same data path described -earlier. After verifying the capsule, the OTA service writes the new images to the passive bank, -updates the system state to 'trial,' and initiates a reset. + If the system fails or becomes unresponsive: -During boot, the bootloaders in both the Secure Enclave and the Host system read the Metadata Block to -determine which bank to boot from. If the trial boot succeeds, the Host system sends an acknowledgment -that transitions the system state from 'trial' to 'regular.' If the system fails during the trial phase -or hangs, a watchdog timer triggers a reset. The Secure Enclave’s BL1 contains logic to detect multiple -resets and can revert to the previously known-good bank. This fallback mechanism is essential to ensure -the device remains available and functional. + A watchdog timer triggers a system reset. + The BL1 firmware in the Secure Enclave detects repeated failures and reverts to the previously known-good flash bank. + This rollback mechanism ensures the device remains operational and recoverable, even after a failed update. .. image:: images/SecureFirmwareUpdate.png @@ -401,6 +467,11 @@ References .. _arm-fmw-framework-a-profile-pdf: https://developer.arm.com/documentation/den0077/latest .. _arm-fmw-framework-m-profile-pdf: https://developer.arm.com/architectures/Firmware%20Framework%20for%20M-Profile .. _platform-security-fwu-for-a-profile-pdf: https://developer.arm.com/documentation/den0118/a/ +.. _psa-firmware-update-ihi-0093-api-reference-website: https://arm-software.github.io/psa-api/fwu/1.0/api/api.html +.. _edk2-capsule-generation-tool-repository: https://github.com/tianocore/edk2/blob/master/BaseTools/Source/Python/Capsule/GenerateCapsule.py +.. _psa-fwu-den0018-specification-website: https://developer.arm.com/documentation/den0118/latest/ +.. _ts-psa-fwu-service-website: https://trusted-services.readthedocs.io/en/stable/services/fwu/psa-fwu-m.html +.. _tfm-shim-layer-website: https://trustedfirmware-m.readthedocs.io/en/latest/design_docs/services/tfm_fwu_service.html#shim-layer-between-fwu-and-bootloader .. _op-tee-os-repository: https://github.com/OP-TEE/optee_os .. _psa-certified-website: https://www.psacertified.org/ .. _psa_l2-ready: https://www.psacertified.org/products/corstone-1000/