new file mode 100644
@@ -0,0 +1,73 @@
+From 5afc6fde140e4033c4b69450daed42c6a3dea2bc Mon Sep 17 00:00:00 2001
+From: Ali Can Ozaslan <ali.oezaslan@arm.com>
+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 <ali.oezaslan@arm.com>
+
+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
+
new file mode 100644
@@ -0,0 +1,30 @@
+From 1f8eb5887f3de167ac68c92b5b77efc51308603c Mon Sep 17 00:00:00 2001
+From: Ali Can Ozaslan <ali.oezaslan@arm.com>
+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 <ali.oezaslan@arm.com>
+
+---
+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.")
new file mode 100644
@@ -0,0 +1,5033 @@
+From 929ac4fdf22bdc84f7363be3f9604c586800e2c1 Mon Sep 17 00:00:00 2001
+From: Ali Can Ozaslan <ali.oezaslan@arm.com>
+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 <harsimransingh.tungal@arm.com>
+Signed-off-by: Ali Can Ozaslan <ali.oezaslan@arm.com>
+---
+ .../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
+ $<$<BOOL:TFM_PARTITION_PLATFORM>:${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
+ $<$<NOT:$<BOOL:${PLATFORM_DEFAULT_OTP}>>:${PLATFORM_DIR}/ext/accelerator/cc312/otp_cc312.c>
+ $<$<NOT:$<BOOL:${TFM_BL1_SOFTWARE_CRYPTO}>>:${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
+ $<$<BOOL:${CRYPTO_HW_ACCELERATOR}>:${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
+ $<$<NOT:$<BOOL:${TFM_BL1_SOFTWARE_CRYPTO}>>: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
+ $<$<NOT:$<BOOL:${PLATFORM_DEFAULT_OTP}>>:${PLATFORM_DIR}/ext/accelerator/cc312/otp_cc312.c>
+ io/io_block.c
+@@ -358,6 +363,12 @@ target_compile_definitions(bl2
+ $<$<BOOL:${CRYPTO_HW_ACCELERATOR_OTP_PROVISIONING}>:CRYPTO_HW_ACCELERATOR_OTP_PROVISIONING>
+ $<$<BOOL:${PLATFORM_PSA_ADAC_SECURE_DEBUG}>: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
+ $<BUILD_INTERFACE:${BL2_SOURCE}/ext/mcuboot/include>
++ ${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 <stdio.h>
++ #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
++ $<$<BOOL:${DEFAULT_MCUBOOT_FLASH_MAP}>:${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}
++ $<$<BOOL:${MCUBOOT_DIRECT_XIP_REVERT}>: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 <string.h>
++#include "psa/crypto.h"
++#include "psa/error.h"
++#include "tfm_bootloader_fwu_abstraction.h"
++
++#include <stdint.h>
++#include <string.h>
++#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; i<FWU_COMPONENT_NUMBER; i++)
++ {
++ fmp_header_image_info[i].fmp_hdr_size_recvd = 0;
++ fmp_header_image_info[i].image_size_recvd = 0;
++ memset(&fmp_header_image_info[i].fmp_hdr, 0, sizeof(fmp_header_image_info[i].fmp_hdr));
++ }
++}
++
++static psa_status_t erase_staging_area(struct fwu_metadata* metadata, psa_fwu_component_t component)
++{
++ if (!metadata) {
++ return PSA_ERROR_INVALID_ARGUMENT;
++ }
++
++ if (!is_image_index_valid(component)) {
++ FWU_LOG_MSG("%s: Invalid Component received \n\r", __func__);
++ return PSA_ERROR_GENERIC_ERROR;
++ }
++
++ uint32_t active_index = metadata->active_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<NR_OF_IMAGES_IN_FW_BANK; i++)
++ {
++ /* Check if image is received from the FWU client */
++ if (fmp_header_image_info[i].image_size_recvd) {
++ continue;
++ }
++
++ ret = copy_image_from_other_bank(i, active_index, previous_active_index);
++ if(ret) {
++ FWU_LOG_MSG("ERROR: %s: copy_image_from_other_bank failed for Image : %d\n\r",__func__, i);
++ return ret;
++ }
++
++ _metadata.fw_desc.img_entry[i].img_props[previous_active_index].version =
++ _metadata.fw_desc.img_entry[i].img_props[active_index].version;
++ _metadata.fw_desc.img_entry[i].img_props[previous_active_index].accepted = IMAGE_ACCEPTED;
++ priv_metadata.fmp_version[i] =
++ _metadata.fw_desc.img_entry[i].img_props[previous_active_index].version;
++ priv_metadata.fmp_last_attempt_version[i] =
++ _metadata.fw_desc.img_entry[i].img_props[previous_active_index].version;
++
++ priv_metadata.fmp_last_attempt_status[i] = LAST_ATTEMPT_STATUS_SUCCESS;
++
++ ret = private_metadata_write(&priv_metadata);
++ if (ret) {
++ goto out;
++ }
++
++ _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;
++
++}
++
++psa_status_t fwu_bootloader_install_image(const psa_fwu_component_t *candidates, uint8_t number)
++{
++ if (!candidates) {
++ return PSA_ERROR_INVALID_ARGUMENT;
++ }
++ if (!is_initialized) {
++ return PSA_ERROR_BAD_STATE;
++ }
++
++ psa_status_t ret;
++ FWU_LOG_MSG("%s: enter function\n\r", __func__);
++
++ /* Copy images from other bank which are not received by FWU client */
++ ret = maintain_bank_consistency();
++ if(ret) {
++ FWU_LOG_MSG("%s: ERROR: Copying images from other bank failed, ret = %d\n\r", __func__, ret);
++ return PSA_ERROR_INSUFFICIENT_DATA;
++ }
++
++ /* Update the metadata */
++ ret = fwu_update_metadata(candidates, number);
++
++ if (ret == PSA_SUCCESS) {
++ is_installed = true;
++ }
++
++ FWU_LOG_MSG("%s: exit: ret = %d\n\r", __func__, ret);
++ return ret;
++}
++
++psa_status_t fwu_bootloader_mark_image_accepted(const psa_fwu_component_t *trials,
++ uint8_t number)
++{
++ if (!trials) {
++ return PSA_ERROR_INVALID_ARGUMENT;
++ }
++
++ if (!is_initialized) {
++ return PSA_ERROR_BAD_STATE;
++ }
++
++ psa_status_t ret;
++ struct fwu_private_metadata priv_metadata;
++ uint8_t current_state;
++ uint8_t fwu_image_index;
++
++ FWU_LOG_MSG("%s: enter\n\r", __func__);
++
++ 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;
++ }
++
++ /* firmware update successful */
++ 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;
++ }
++
++ 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_READY) {
++ 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]);
++ continue;
++
++ } else if (current_state != PSA_FWU_TRIAL) {
++ FWU_ASSERT(0);
++ }
++
++ priv_metadata.fmp_version[fwu_image_index] =
++ _metadata.fw_desc.img_entry[fwu_image_index].img_props[_metadata.active_index].version;
++ priv_metadata.fmp_last_attempt_version[fwu_image_index] =
++ _metadata.fw_desc.img_entry[fwu_image_index].img_props[_metadata.active_index].version;
++
++ priv_metadata.fmp_last_attempt_status[fwu_image_index] = LAST_ATTEMPT_STATUS_SUCCESS;
++ }
++
++ ret = fwu_accept_image(&_metadata,
++ &priv_metadata, trials, number);
++ if (!ret) {
++ ret = update_nv_counters(&priv_metadata);
++ }
++
++ if (ret == PSA_SUCCESS) {
++ disable_host_ack_timer();
++ 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;
++ }
++
++ fwu_image_index = trials[i] - FWU_FAKE_IMAGES_INDEX_COUNT;
++ 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]);
++ }
++ }
++
++out:
++ Select_XIP_Mode_For_Shared_Flash();
++ FWU_LOG_MSG("%s: exit: ret = %d\n\r", __func__, ret);
++ return ret;
++}
++
++/* Reject the staged image. */
++psa_status_t fwu_bootloader_reject_staged_image(psa_fwu_component_t component)
++{
++
++ if (!is_image_index_valid(component)) {
++ FWU_LOG_MSG("%s: Invalid image index received \n\r", __func__);
++ return PSA_ERROR_INVALID_ARGUMENT;
++ }
++
++ if (!is_initialized) {
++ return PSA_ERROR_BAD_STATE;
++ }
++
++ int ret;
++ uint32_t active_index;;
++ uint32_t bank_offset;
++ uint32_t image_offset;
++ uint8_t image_index = component - FWU_FAKE_IMAGES_INDEX_COUNT; /* Decrement to get the correct fwu image index */
++
++ 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;
++ }
++ active_index = _metadata.active_index;
++
++ 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);
++ ret = PSA_ERROR_GENERIC_ERROR;
++ goto out;
++ }
++
++ image_offset = bank_offset + fwu_image[image_index].image_offset;
++
++ if (erase_image(image_offset, fwu_image[image_index].image_size)) {
++ return PSA_ERROR_GENERIC_ERROR;
++ }
++
++out:
++ Select_XIP_Mode_For_Shared_Flash();
++ FWU_LOG_MSG("%s: exit: ret = %d\n\r", __func__, ret);
++ return ret;
++}
++
++/* Reject the running image in trial state. */
++psa_status_t fwu_bootloader_reject_trial_image(psa_fwu_component_t component)
++{
++
++ if (!is_image_index_valid(component)) {
++ FWU_LOG_MSG("%s: Invalid image index received \n\r", __func__);
++ return PSA_ERROR_INVALID_ARGUMENT;
++ }
++
++ struct fwu_private_metadata priv_metadata;
++ int ret;
++ 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__);
++
++ /* Disable host ackowledgement timer */
++ disable_host_ack_timer();
++
++ /* Update the metadata active index to previous active index as trial images have been rejected */
++
++ Select_Write_Mode_For_Shared_Flash();
++ if (metadata_read(&_metadata, 1) || private_metadata_read(&priv_metadata)) {
++ ret = PSA_ERROR_GENERIC_ERROR;
++ goto out;
++ }
++ priv_metadata.fmp_last_attempt_version[fwu_image_index] =
++ _metadata.fw_desc.img_entry[fwu_image_index].img_props[_metadata.active_index].version;
++
++ priv_metadata.fmp_last_attempt_status[fwu_image_index] = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
++
++ ret = fwu_select_previous(&_metadata, &priv_metadata);
++
++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_abort(psa_fwu_component_t component)
++{
++ /* Not to be implemented as PSA FWU Trusted-Services is not using this function */
++ return PSA_SUCCESS;
++}
++
++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)
++{
++ if (component >= 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 <stdbool.h>
+ #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 <stdint.h>
+-#include <string.h>
+-#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 <stdio.h>
+- #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 <string.h>
+-
+-/*
+-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 <stdint.h>
+-#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
+
@@ -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:"