diff mbox series

[02/13] arm-bsp/trusted-firmware-m: corstone1000: Add Bootloader Abstraction Layer (BAL) support

Message ID 20250730115327.3671160-3-harsimransingh.tungal@arm.com
State New
Headers show
Series Add PSA FWU support and capsule generation via EDK2 tooling | expand

Commit Message

Harsimran Singh Tungal July 30, 2025, 11:53 a.m. UTC
From: Ali Can Ozaslan <ali.oezaslan@arm.com>

Introduce Bootloader Abstraction Layer (BAL) support for Corstone-1000 to
enable flexible integration of firmware update including partial capsule
update.
This change includes:
- Enable the firmware update partition for Corstone-1000 and create
  placeholder bootloader abstraction layer for Corstone-1000.
- Change the insertion logic of TFM_FWU_BOOTLOADER_LIB to select a new
  platform-specific bootloader abstraction layer.
- Use the necessary flags to use the service and resolve any linker
  issues that may arise.
- Migration of capsule update logic to a new BAL module under
  `platform/ext/target/corstone1000/bootloader/mcuboot/`.
- Implementation of BAL APIs in `tfm_mcuboot_fwu.c` as per the PSA FWU
  state machine.
- Removal of `uefi_capsule_parser.c` and `uefi_capsule_parser.h` as capsule
  parsing is done in U-Boot.
- Enhancement of `uefi_fmp.c` to handle FMP metadata for multiple images.
- Update of `provisioning.c` and `security_cnt_bl2.c` to handle new BAL
  return values.
- Addition of `fwu_config.h.in` with default FWU configuration.
- Metadata layout changes to include size and image GUIDs for U-Boot
  compatibility during FWU Accept flow.

Signed-off-by: Harsimran Singh Tungal <harsimransingh.tungal@arm.com>
Signed-off-by: Ali Can Ozaslan <ali.oezaslan@arm.com>
---
 ...m-specific-TFM_FWU_BOOTLOADER_LIB-se.patch |   73 +
 ...Platform-CS1000-Enable-FWU-partition.patch |   30 +
 ...e1000-Implement-Bootloader-Abstracti.patch | 5033 +++++++++++++++++
 .../trusted-firmware-m-corstone1000.inc       |    3 +
 4 files changed, 5139 insertions(+)
 create mode 100644 meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0025-FWU-Make-platform-specific-TFM_FWU_BOOTLOADER_LIB-se.patch
 create mode 100644 meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0026-Platform-CS1000-Enable-FWU-partition.patch
 create mode 100644 meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0027-Platform-Corstone1000-Implement-Bootloader-Abstracti.patch
diff mbox series

Patch

diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0025-FWU-Make-platform-specific-TFM_FWU_BOOTLOADER_LIB-se.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0025-FWU-Make-platform-specific-TFM_FWU_BOOTLOADER_LIB-se.patch
new file mode 100644
index 00000000..5c503141
--- /dev/null
+++ b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0025-FWU-Make-platform-specific-TFM_FWU_BOOTLOADER_LIB-se.patch
@@ -0,0 +1,73 @@ 
+From 5afc6fde140e4033c4b69450daed42c6a3dea2bc Mon Sep 17 00:00:00 2001
+From: Ali Can Ozaslan <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
+
diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0026-Platform-CS1000-Enable-FWU-partition.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0026-Platform-CS1000-Enable-FWU-partition.patch
new file mode 100644
index 00000000..c6b97733
--- /dev/null
+++ b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0026-Platform-CS1000-Enable-FWU-partition.patch
@@ -0,0 +1,30 @@ 
+From 1f8eb5887f3de167ac68c92b5b77efc51308603c Mon Sep 17 00:00:00 2001
+From: Ali Can Ozaslan <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.")
diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0027-Platform-Corstone1000-Implement-Bootloader-Abstracti.patch b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0027-Platform-Corstone1000-Implement-Bootloader-Abstracti.patch
new file mode 100644
index 00000000..da275a19
--- /dev/null
+++ b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0027-Platform-Corstone1000-Implement-Bootloader-Abstracti.patch
@@ -0,0 +1,5033 @@ 
+From 929ac4fdf22bdc84f7363be3f9604c586800e2c1 Mon Sep 17 00:00:00 2001
+From: Ali Can Ozaslan <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
+
diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-corstone1000.inc b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-corstone1000.inc
index f49a4271..87302069 100644
--- a/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-corstone1000.inc
+++ b/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-corstone1000.inc
@@ -43,6 +43,9 @@  SRC_URI:append:corstone1000 = " \
     file://0022-CC312-alignment-of-cc312-differences.patch \
     file://0023-Platform-CS1000-Remove-duplicate-configuration-parameters.patch \
     file://0024-Platform-corstone1000-Allow-FWU-calls-in-RSE-COMMS.patch \
+    file://0025-FWU-Make-platform-specific-TFM_FWU_BOOTLOADER_LIB-se.patch \
+    file://0026-Platform-CS1000-Enable-FWU-partition.patch \
+    file://0027-Platform-Corstone1000-Implement-Bootloader-Abstracti.patch \
     "
 
 FILESEXTRAPATHS:prepend:corstone1000-mps3 := "${THISDIR}/files/corstone1000/psa-adac:"