FWU: Align to FWU API v1.0

'component' and 'component state' is newly introduced in
FWU API v1.0. The FWU process is now based on component
state other than image state.

Remove the image ID convertion layer as image ID is removed
in FWU API v1.0.

Update the shim layer between FWU and bootloader to fit the new
FWU APIs.

Update the FWU design document accordingly.

Signed-off-by: Sherry Zhang <sherry.zhang2@arm.com>
Change-Id: Idcbf2b643f22a5c6ec09869510d406662948c61d
diff --git a/config/config_default.cmake b/config/config_default.cmake
index 395e303..4cfd886 100755
--- a/config/config_default.cmake
+++ b/config/config_default.cmake
@@ -157,13 +157,6 @@
 set(PLATFORM_SP_STACK_SIZE              "0x500"     CACHE STRING    "The stack size of the TF-M Platform Secure Partition")
 set(PLATFORM_NV_COUNTER_MODULE_DISABLED FALSE       CACHE BOOL      "Disable Non-volatile counter module")
 
-set(PLATFORM_HAS_FIRMWARE_UPDATE_SUPPORT OFF        CACHE BOOL      "Platform supports firmware update, such as network connectivities and bootloader support")
-set(TFM_PARTITION_FIRMWARE_UPDATE       OFF         CACHE BOOL      "Enable firmware update partition")
-set(TFM_FWU_BOOTLOADER_LIB              "mcuboot"   CACHE STRING    "Bootloader configure file for Firmware Update partition")
-set(PSA_FWU_MAX_BLOCK_SIZE              1024        CACHE STRING    "The maximum permitted size for block in psa_fwu_write, in bytes.")
-set(TFM_FWU_BUF_SIZE                    ""          CACHE STRING    "Size of the FWU internal data transfer buffer (defaults to PSA_FWU_MAX_BLOCK_SIZE if not set)")
-set(FWU_STACK_SIZE                      "0x600"     CACHE STRING    "The stack size of the Firmware Update Secure Partition")
-
 ################################## Dependencies ################################
 
 set(MBEDCRYPTO_PATH                     "DOWNLOAD"  CACHE PATH      "Path to Mbed Crypto (or DOWNLOAD to fetch automatically")
diff --git a/config/set_config.cmake b/config/set_config.cmake
index 1a6b26e..804dbff 100644
--- a/config/set_config.cmake
+++ b/config/set_config.cmake
@@ -77,6 +77,9 @@
     include(${CMAKE_SOURCE_DIR}/bl2/ext/mcuboot/mcuboot_default_config.cmake)
 endif()
 
+# Include FWU partition configs.
+include(config/tfm_fwu_config.cmake)
+
 # Include coprocessor configs
 include(config/cp_config_default.cmake)
 
diff --git a/config/tfm_fwu_config.cmake b/config/tfm_fwu_config.cmake
new file mode 100755
index 0000000..f7272c9
--- /dev/null
+++ b/config/tfm_fwu_config.cmake
@@ -0,0 +1,22 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2022, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+set(PLATFORM_HAS_FIRMWARE_UPDATE_SUPPORT  OFF         CACHE BOOL      "Platform supports firmware update, such as network connectivities and bootloader support")
+set(TFM_PARTITION_FIRMWARE_UPDATE         OFF         CACHE BOOL      "Enable firmware update partition")
+set(TFM_FWU_BOOTLOADER_LIB                "mcuboot"   CACHE STRING    "Bootloader configure file for Firmware Update partition")
+set(TFM_CONFIG_FWU_MAX_WRITE_SIZE         1024        CACHE STRING    "The maximum permitted size for block in psa_fwu_write, in bytes.")
+set(TFM_CONFIG_FWU_MAX_MANIFEST_SIZE      0           CACHE STRING    "The maximum permitted size for manifest in psa_fwu_start(), in bytes.")
+set(TFM_FWU_BUF_SIZE                      ""          CACHE STRING    "Size of the FWU internal data transfer buffer (defaults to PSA_FWU_MAX_BLOCK_SIZE if not set)")
+set(FWU_STACK_SIZE                        "0x600"     CACHE STRING    "The stack size of the Firmware Update Secure Partition")
+set(FWU_DEVICE_CONFIG_FILE                ""          CACHE STRING    "The device configuration file for Firmware Update partition")
+if (DEFINED MCUBOOT_UPGRADE_STRATEGY)
+    if(${MCUBOOT_UPGRADE_STRATEGY} STREQUAL "SWAP_USING_SCRATCH" OR ${MCUBOOT_UPGRADE_STRATEGY} STREQUAL "SWAP_USING_MOVE")
+        set(FWU_SUPPORT_TRIAL_STATE ON CACHE BOOL "Device support TRIAL component state.")
+    endif()
+else()
+    set(FWU_SUPPORT_TRIAL_STATE OFF CACHE BOOL "Device support TRIAL component state.")
+endif()
diff --git a/docs/technical_references/design_docs/media/fwu-states.svg b/docs/technical_references/design_docs/media/fwu-states.svg
new file mode 100755
index 0000000..8039f14
--- /dev/null
+++ b/docs/technical_references/design_docs/media/fwu-states.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentStyleType="text/css" height="869px" preserveAspectRatio="none" style="width:403px;height:869px;background:#FFFFFF;" version="1.1" viewBox="0 0 403 869" width="403px" zoomAndPan="magnify"><defs/><g><rect fill="#FFFFFF" height="40" rx="12.5" ry="12.5" style="stroke:#000000;stroke-width:1.0;" width="50" x="105.5" y="7"/><text fill="#000000" font-family="Lato,sans-serif" font-size="12" lengthAdjust="spacing" textLength="40" x="110.5" y="31.6414">READY</text><rect fill="#FFFFFF" height="40" rx="12.5" ry="12.5" style="stroke:#000000;stroke-width:1.0;" width="63" x="15" y="123"/><text fill="#000000" font-family="Lato,sans-serif" font-size="12" lengthAdjust="spacing" textLength="53" x="20" y="147.6414">WRITING</text><rect fill="#FFFFFF" height="40" rx="12.5" ry="12.5" style="stroke:#000000;stroke-width:1.0;" width="79" x="7" y="239"/><text fill="#000000" font-family="Lato,sans-serif" font-size="12" lengthAdjust="spacing" textLength="69" x="12" y="263.6414">CANDIDATE</text><rect fill="#FFFFFF" height="40" rx="12.5" ry="12.5" style="stroke:#000000;stroke-width:1.0;" width="63" x="100" y="369"/><text fill="#000000" font-family="Lato,sans-serif" font-size="12" lengthAdjust="spacing" textLength="53" x="105" y="393.6414">STAGED *</text><rect fill="#FFFFFF" height="40" rx="12.5" ry="12.5" style="stroke:#000000;stroke-width:1.0;" width="51" x="173" y="239"/><text fill="#000000" font-family="Lato,sans-serif" font-size="12" lengthAdjust="spacing" textLength="41" x="178" y="263.6414">FAILED</text><rect fill="#FFFFFF" height="40" rx="12.5" ry="12.5" style="stroke:#000000;stroke-width:1.0;" width="75" x="226" y="369"/><text fill="#000000" font-family="Lato,sans-serif" font-size="12" lengthAdjust="spacing" textLength="65" x="231" y="393.6414">REJECTED *</text><rect fill="#FFFFFF" height="40" rx="12.5" ry="12.5" style="stroke:#000000;stroke-width:1.0;" width="50" x="179.5" y="499"/><text fill="#000000" font-family="Lato,sans-serif" font-size="12" lengthAdjust="spacing" textLength="40" x="184.5" y="523.6414">TRIAL *</text><rect fill="#FFFFFF" height="40" rx="12.5" ry="12.5" style="stroke:#000000;stroke-width:1.0;" width="66" x="171.5" y="615"/><text fill="#000000" font-family="Lato,sans-serif" font-size="12" lengthAdjust="spacing" textLength="56" x="176.5" y="639.6414">UPDATED</text><rect fill="#FFFFFF" height="40" rx="12.5" ry="12.5" style="stroke:#000000;stroke-width:1.0;" width="50" x="179.5" y="731"/><text fill="#000000" font-family="Lato,sans-serif" font-size="12" lengthAdjust="spacing" textLength="40" x="184.5" y="755.6414">READY</text><!--MD5=[28b091a9324bc665227cbdd5c64568c5]
+link Start to Writing--><g id="link_Start_Writing"><path d="M116.44,47.08 C101.9,66.81 79.19,97.63 63.62,118.76 " fill="none" id="Start-to-Writing" style="stroke:#0000FF;stroke-width:1.0;"/><polygon fill="#0000FF" points="60.61,122.86,69.1714,117.9914,63.5779,118.8362,62.7332,113.2427,60.61,122.86" style="stroke:#0000FF;stroke-width:1.0;"/><text fill="#000000" font-family="Consolas,Menlo,monospace" font-size="12" lengthAdjust="spacing" textLength="35" x="95.5" y="89.9883">start</text></g><!--MD5=[809ec20dfa1295c4642186e63aa045f8]
+link Writing to Writing--><g id="link_Writing_Writing"><path d="M78.32,132.68 C96.33,130.67 113,134.11 113,143 C113,151.06 99.31,154.64 83.33,153.74 " fill="none" id="Writing-to-Writing" style="stroke:#0000FF;stroke-width:1.0;"/><polygon fill="#0000FF" points="78.32,153.32,86.9444,158.0761,83.3016,153.7482,87.6295,150.1055,78.32,153.32" style="stroke:#0000FF;stroke-width:1.0;"/><text fill="#000000" font-family="Consolas,Menlo,monospace" font-size="12" lengthAdjust="spacing" textLength="35" x="119" y="147.9883">write</text></g><!--MD5=[c452d5c1487cc0f2a16ec09e1ebeb498]
+link Writing to Candidate--><g id="link_Writing_Candidate"><path d="M46.5,163.08 C46.5,182.48 46.5,212.61 46.5,233.7 " fill="none" id="Writing-to-Candidate" style="stroke:#0000FF;stroke-width:1.0;"/><polygon fill="#0000FF" points="46.5,238.86,50.5,229.86,46.5,233.86,42.5,229.86,46.5,238.86" style="stroke:#0000FF;stroke-width:1.0;"/><text fill="#000000" font-family="Consolas,Menlo,monospace" font-size="12" lengthAdjust="spacing" textLength="42" x="47.5" y="205.9883">finish</text></g><!--MD5=[1e580f2a5c35a06e4aed74591dc8f2d0]
+link Writing to Failed--><g id="link_Writing_Failed"><path d="M71.94,163.08 C98.68,183.14 140.71,214.66 168.92,235.81 " fill="none" id="Writing-to-Failed" style="stroke:#0000FF;stroke-width:1.0;"/><polygon fill="#0000FF" points="172.98,238.86,168.18,230.26,168.98,235.86,163.38,236.66,172.98,238.86" style="stroke:#0000FF;stroke-width:1.0;"/><text fill="#000000" font-family="Consolas,Menlo,monospace" font-size="12" lengthAdjust="spacing" textLength="42" x="133.5" y="205.9883">cancel</text></g><!--MD5=[86e4efad9860276429e6c81242466072]
+link Candidate to Staged--><g id="link_Candidate_Staged"><path d="M43.01,279.33 C40.98,296.29 40.65,320.99 51.5,339 C61.41,355.45 79.16,367.14 95.43,374.97 " fill="none" id="Candidate-to-Staged" style="stroke:#8B0000;stroke-width:1.0;"/><polygon fill="#8B0000" points="99.97,377.07,93.479,369.6628,95.4315,374.972,90.1222,376.9244,99.97,377.07" style="stroke:#8B0000;stroke-width:1.0;"/><text fill="#000000" font-family="Consolas,Menlo,monospace" font-size="12" lengthAdjust="spacing" textLength="49" x="52.5" y="328.9883">install</text></g><!--MD5=[6e8b06a321fbf587dbbb055d0b4e0f9e]
+link Candidate to Failed--><g id="link_Candidate_Failed"><path d="M86.04,259 C111.55,259 144.25,259 167.81,259 " fill="none" id="Candidate-to-Failed" style="stroke:#0000FF;stroke-width:1.0;"/><polygon fill="#0000FF" points="172.99,259,163.99,255,167.99,259,163.99,263,172.99,259" style="stroke:#0000FF;stroke-width:1.0;"/><text fill="#000000" font-family="Consolas,Menlo,monospace" font-size="12" lengthAdjust="spacing" textLength="42" x="108.5" y="252.9883">cancel</text></g><!--MD5=[d4d7d25629e036e3232ad0960ebf72b6]
+link Staged to Trial--><g id="link_Staged_Trial"><path d="M132.91,409.06 C134.86,425.84 139.5,450.43 150.5,469 C156.82,479.67 166.22,489.36 175.41,497.24 " fill="none" id="Staged-to-Trial" style="stroke:#8B0000;stroke-width:1.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#8B0000" points="179.33,500.51,174.9929,491.6675,175.4947,497.3021,169.8602,497.8039,179.33,500.51" style="stroke:#8B0000;stroke-width:1.0;"/><text fill="#000000" font-family="Consolas,Menlo,monospace" font-size="12" lengthAdjust="spacing" textLength="42" x="163.5" y="452.3296">reboot</text><text fill="#000000" font-family="Lato,sans-serif" font-size="12" lengthAdjust="spacing" textLength="3" x="205.5" y="451.8375">:</text><text fill="#000000" font-family="Lato,sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="69" x="151.5" y="466.2296">install success</text></g><!--MD5=[6b849a9d54236769877241b12840d8d2]
+reverse link Failed to Staged--><g id="link_Failed_Staged"><path d="M190.93,283.94 C185.42,299.99 177.23,321.34 167.5,339 C161.79,349.35 154.19,360.03 147.44,368.76 " fill="none" id="Failed-backto-Staged" style="stroke:#8B0000;stroke-width:1.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#8B0000" points="192.55,279.14,185.883,286.3892,190.9517,283.8777,193.4633,288.9464,192.55,279.14" style="stroke:#8B0000;stroke-width:1.0;"/><text fill="#000000" font-family="Consolas,Menlo,monospace" font-size="12" lengthAdjust="spacing" textLength="42" x="190" y="322.3296">reboot</text><text fill="#000000" font-family="Lato,sans-serif" font-size="12" lengthAdjust="spacing" textLength="3" x="232" y="321.8375">:</text><text fill="#000000" font-family="Lato,sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="60" x="182.5" y="336.2296">install failed</text></g><!--MD5=[6b849a9d54236769877241b12840d8d2]
+reverse link Failed to Staged--><g id="link_Failed_Staged"><path d="M168.12,269.26 C149.34,276.73 126.74,289.31 115.5,309 C104.88,327.59 112.67,352.18 120.66,368.95 " fill="none" id="Failed-backto-Staged-1" style="stroke:#8B0000;stroke-width:1.0;"/><polygon fill="#8B0000" points="172.81,267.47,162.975,266.9473,168.1396,269.2553,165.8315,274.4199,172.81,267.47" style="stroke:#8B0000;stroke-width:1.0;"/><text fill="#000000" font-family="Consolas,Menlo,monospace" font-size="12" lengthAdjust="spacing" textLength="42" x="116.5" y="328.9883">reject</text></g><!--MD5=[4d415c9b773123c37ce42f12237de1fc]
+link Trial to Updated--><g id="link_Trial_Updated"><path d="M204.5,539.08 C204.5,558.48 204.5,588.61 204.5,609.7 " fill="none" id="Trial-to-Updated" style="stroke:#8B0000;stroke-width:1.0;"/><polygon fill="#8B0000" points="204.5,614.86,208.5,605.86,204.5,609.86,200.5,605.86,204.5,614.86" style="stroke:#8B0000;stroke-width:1.0;"/><text fill="#000000" font-family="Consolas,Menlo,monospace" font-size="12" lengthAdjust="spacing" textLength="42" x="205.5" y="581.9883">accept</text></g><!--MD5=[71ab68107f7e180decc84935bd3705da]
+reverse link Start to Failed--><g id="link_Start_Failed"><path d="M139.23,52 C150.63,83.9 170.75,142.18 184.5,193 C188.63,208.27 192.35,225.81 194.91,238.82 " fill="none" id="Start-backto-Failed" style="stroke:#0000FF;stroke-width:1.0;"/><polygon fill="#0000FF" points="137.47,47.11,136.7338,56.9313,139.1535,51.8181,144.2667,54.2377,137.47,47.11" style="stroke:#0000FF;stroke-width:1.0;"/><text fill="#000000" font-family="Consolas,Menlo,monospace" font-size="12" lengthAdjust="spacing" textLength="35" x="177.5" y="147.9883">clean</text></g><!--MD5=[5b18d785e1ed9c85922a1d1dbb6dfde5]
+reverse link Rejected to Trial--><g id="link_Rejected_Trial"><path d="M252.49,413.88 C241.2,438.38 223.85,476.03 213.39,498.71 " fill="none" id="Rejected-backto-Trial" style="stroke:#8B0000;stroke-width:1.0;"/><polygon fill="#8B0000" points="254.67,409.16,247.2628,415.651,252.572,413.6985,254.5244,419.0078,254.67,409.16" style="stroke:#8B0000;stroke-width:1.0;"/><text fill="#000000" font-family="Consolas,Menlo,monospace" font-size="12" lengthAdjust="spacing" textLength="42" x="240.5" y="458.9883">reject</text></g><!--MD5=[8730496acf69e4d93e6ebba34c197634]
+reverse link Failed to Rejected--><g id="link_Failed_Rejected"><path d="M228.72,272.5 C243.9,280.52 260.86,292.54 269.5,309 C279.28,327.63 275.23,352.21 270.38,368.97 " fill="none" id="Failed-backto-Rejected" style="stroke:#8B0000;stroke-width:1.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#8B0000" points="224.08,270.14,230.2826,277.7904,228.5349,272.4103,233.915,270.6626,224.08,270.14" style="stroke:#8B0000;stroke-width:1.0;"/><text fill="#000000" font-family="Consolas,Menlo,monospace" font-size="12" lengthAdjust="spacing" textLength="42" x="276.5" y="322.3296">reboot</text><text fill="#000000" font-family="Lato,sans-serif" font-size="12" lengthAdjust="spacing" textLength="3" x="318.5" y="321.8375">:</text><text fill="#000000" font-family="Lato,sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="39" x="279.5" y="336.2296">rollback</text></g><!--MD5=[91632b8e9666b14c55229d961249920f]
+link Trial to Failed--><g id="link_Trial_Failed"><path d="M229.82,508.82 C248.89,500.81 274.54,487.56 291.5,469 C340.87,414.97 372.29,369.09 330.5,309 C307.81,276.37 260.69,265.42 229.33,261.78 " fill="none" id="Trial-to-Failed" style="stroke:#8B0000;stroke-width:1.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#8B0000" points="224.06,261.22,232.5867,266.1491,229.032,261.7486,233.4325,258.194,224.06,261.22" style="stroke:#8B0000;stroke-width:1.0;"/><text fill="#000000" font-family="Consolas,Menlo,monospace" font-size="12" lengthAdjust="spacing" textLength="42" x="350.5" y="387.3296">reboot</text><text fill="#000000" font-family="Lato,sans-serif" font-size="12" lengthAdjust="spacing" textLength="3" x="392.5" y="386.8375">:</text><text fill="#000000" font-family="Lato,sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="39" x="353.5" y="401.2296">rollback</text></g><!--MD5=[43a8c4662c8a2715cf5aeba88f635b26]
+link Updated to End--><g id="link_Updated_End"><path d="M204.5,655.08 C204.5,674.48 204.5,704.61 204.5,725.7 " fill="none" id="Updated-to-End" style="stroke:#0000FF;stroke-width:1.0;"/><polygon fill="#0000FF" points="204.5,730.86,208.5,721.86,204.5,725.86,200.5,721.86,204.5,730.86" style="stroke:#0000FF;stroke-width:1.0;"/><text fill="#000000" font-family="Consolas,Menlo,monospace" font-size="12" lengthAdjust="spacing" textLength="35" x="205.5" y="697.9883">clean</text></g><rect fill="#DDDDDD" height="69.5684" id="_legend" rx="7.5" ry="7.5" style="stroke:#000000;stroke-width:1.0;" width="281" x="54.25" y="784"/><text fill="#000000" font-family="Consolas,Menlo,monospace" font-size="12" lengthAdjust="spacing" textLength="7" x="67.25" y="802.3296">*</text><text fill="#000000" font-family="Lato,sans-serif" font-size="12" lengthAdjust="spacing" textLength="207" x="83.25" y="801.8375">Transient states that always transition at</text><text fill="#000000" font-family="Lato,sans-serif" font-size="12" font-weight="bold" lengthAdjust="spacing" textLength="37" x="292.25" y="801.8375">reboot</text><text fill="#0000FF" font-family="Consolas,Menlo,monospace" font-size="12" lengthAdjust="spacing" text-decoration="line-through" textLength="21" x="60.25" y="816.7217">———</text><text fill="#000000" font-family="Lato,sans-serif" font-size="12" lengthAdjust="spacing" textLength="229" x="83.25" y="816.2296">Blue transitions apply to a single component</text><text fill="#8B0000" font-family="Consolas,Menlo,monospace" font-size="12" lengthAdjust="spacing" text-decoration="line-through" textLength="21" x="60.25" y="831.1138">———</text><text fill="#000000" font-family="Lato,sans-serif" font-size="12" lengthAdjust="spacing" textLength="208" x="83.25" y="830.6217">Red transitions apply to all compoments</text><text fill="#000000" font-family="Consolas,Menlo,monospace" font-size="12" lengthAdjust="spacing" textLength="21" x="60.25" y="845.5059">---</text><text fill="#000000" font-family="Lato,sans-serif" font-size="12" lengthAdjust="spacing" textLength="197" x="83.25" y="845.0138">Dashed lines indicate a transition over</text><text fill="#000000" font-family="Lato,sans-serif" font-size="12" font-weight="bold" lengthAdjust="spacing" textLength="37" x="282.25" y="845.0138">reboot</text></g></svg>
\ No newline at end of file
diff --git a/docs/technical_references/design_docs/tfm_fwu_service.rst b/docs/technical_references/design_docs/tfm_fwu_service.rst
index b48d5e6..48c2ea3 100644
--- a/docs/technical_references/design_docs/tfm_fwu_service.rst
+++ b/docs/technical_references/design_docs/tfm_fwu_service.rst
@@ -18,15 +18,17 @@
 
 This partition supports the following features:
 
-- Query image information
-  Fetch information about the firmware images on the device. This covers the
-  images in the running area and also the staging area.
-- Store image
-  Write a candidate image to its staging area.
-- Validate image
-  Starts the validation of the image.
-- Trigger reboot
-  Trigger a reboot to restart the platform.
+- Query the firmware store information.
+- Image preparation: prepare a new firmware image in the component's firmware store.
+- Image installation: install prepared firmware images on all components that have been prepared for installation.
+- Image trial: manage a trial of new firmware images atomically on all components that are in TRIAL state.
+
+A typical flow through the component states is shown below [1]_.
+
+.. figure:: media/fwu-states.svg
+   :scale: 65 %
+   :align: center
+   :name: The component state model transitions.
 
 **********
 Components
@@ -40,14 +42,13 @@
    +-----------------------------+---------------------------------------------------------------+---------------------------------------------------------------------------------------+
    | Manifest                    | The manifest file is a description of the service components. | ``./secure_fw/partitions/firmware_update/tfm_firmware_update.yaml``                   |
    +-----------------------------+---------------------------------------------------------------+---------------------------------------------------------------------------------------+
+   | NSPE client API interface   | This module exports the client API of PSA Firmware Update to  | ``./interface/src/tfm_fwu_api.c``                                                     |
+   |                             | the NSPE(i.e. to the applications).                           |                                                                                       |
+   +-----------------------------+---------------------------------------------------------------+---------------------------------------------------------------------------------------+
    | IPC request handlers        | This module handles all the secure requests in IPC model.     | ``./secure_fw/partitions/firmware_update/tfm_fwu_req_mngr.c``                         |
    |                             | It maitains the image state context and calls the image ID    |                                                                                       |
    |                             | converter to achieve the firmware update functionalities.     |                                                                                       |
    +-----------------------------+---------------------------------------------------------------+---------------------------------------------------------------------------------------+
-   | Image ID Converter          | This module converts the image ID between psa_image_id_t,     | ``./secure_fw/partitions/firmware_update/tfm_fwu_internal.c``                         |
-   |                             | which is the image ID structure in user interfaces, and       |                                                                                       |
-   |                             | bl_image_id_t which is the image ID structure in bootloader.  |                                                                                       |
-   +-----------------------------+---------------------------------------------------------------+---------------------------------------------------------------------------------------+
    | Shim layer between FWU and  | This module provides the APIs with the functionality of       | ``./secure_fw/partitions/firmware_update/bootloader/tfm_bootloader_fwu_abstraction.h``|
    | bootloader                  | operating the bootloader to cooperate with the Firmware Update|                                                                                       |
    |                             | service                                                       |                                                                                       |
@@ -60,10 +61,8 @@
 ***********************
 Service API description
 ***********************
-This service follows the PSA Firmware Update API spec of version 0.7 [1]_.
-It implements the mandatory interface functions listed in section 5.1 and the
-optional interface ``psa_fwu_accept()``. Please refer to Firmware Update spec
-for the detailed description.
+This service follows the PSA Firmware Update API spec of version 1.0 [1]_. Please refer to
+Firmware Update spec for the detailed description.
 
 *************************************
 Shim Layer between FWU and bootloader
@@ -108,17 +107,21 @@
 
 .. code-block:: c
 
-    psa_status_t fwu_bootloader_staging_area_init(bl_image_id_t bootloader_image_id);
+    psa_status_t fwu_bootloader_staging_area_init(psa_fwu_component_t component,
+                                                  const void *manifest,
+                                                  size_t manifest_size);
 
 **Description**
 
-Prepare the staging area of the image with the given ID for image download.
+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.
 
 **Parameters**
 
-- ``bootloader_image_id``: The identifier of the target image in bootloader.
+- ``component``: The identifier of the target component in bootloader.
+- ``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.
+- ``manifest_size``: Size of the manifest buffer in bytes.
 
 fwu_bootloader_load_image(function)
 -----------------------------------
@@ -126,18 +129,18 @@
 
 .. code-block:: c
 
-    psa_status_t fwu_bootloader_load_image(bl_image_id_t bootloader_image_id,
+    psa_status_t fwu_bootloader_load_image(psa_fwu_component_t component,
                                            size_t        image_offset,
                                            const void    *block,
                                            size_t        block_size);
 
 **Description**
 
-Load the image to its staging area.
+Load the image into the target component.
 
 **Parameters**
 
-- ``bootloader_image_id``: The identifier of the target image in bootloader.
+- ``component``: The identifier of the target component in bootloader.
 - ``image_offset``: The offset of the image being passed into block, in bytes.
 - ``block``: A buffer containing a block of image data. This might be a complete image or a subset.
 - ``block_size``: Size of block.
@@ -148,9 +151,8 @@
 
 .. code-block:: c
 
-    psa_status_t fwu_bootloader_install_image(bl_image_id_t bootloader_image_id,
-                                              bl_image_id_t       *dependency,
-                                              psa_image_version_t *dependency_version);
+    psa_status_t fwu_bootloader_install_image(psa_fwu_component_t *candidates,
+                                              uint8_t number);
 
 **Description**
 
@@ -161,9 +163,8 @@
 
 **Parameters**
 
-- ``bootloader_image_id``: The identifier of the target image in bootloader.
-- ``dependency``: Bootloader image ID of dependency if needed.
-- ``dependency_version``: Bootloader image version of dependency if needed.
+- ``candidates``: A list of components in CANDIDATE state.
+- ``number``: Number of components in CANDIDATE state.
 
 fwu_bootloader_mark_image_accepted(function)
 --------------------------------------------
@@ -171,33 +172,68 @@
 
 .. code-block:: c
 
-    psa_status_t fwu_bootloader_mark_image_accepted(bl_image_id_t bootloader_image_id);
+    psa_status_t fwu_bootloader_mark_image_accepted(const psa_fwu_component_t *trials,
+                                                    uint8_t number);
 
 **Description**
 
-Call this API to mark the running images as permanent/accepted to avoid
+Call this API to mark the TRIAL(running) image in component as confirmed to avoid
 revert when next time bootup. Usually, this API is called after the running
 images have been verified as valid.
 
 **Parameters**
 
-    N/A
+- ``trials``: A list of components in TRIAL state.
+- ``number``: Number of components in TRIAL state.
 
-fwu_bootloader_abort(function)
-------------------------------
+fwu_bootloader_reject_staged_image(function)
+--------------------------------------------
 **Prototype**
 
 .. code-block:: c
 
-    psa_status_t fwu_bootloader_abort(void);
+    psa_status_t fwu_bootloader_reject_staged_image(psa_fwu_component_t component);
 
 **Description**
 
-Abort the current image download process.
+The component is in STAGED state. Call this API to Uninstall the staged image in the
+component so that this image will not be treated as a candidate next time bootup.
 
 **Parameters**
 
-    N/A
+- ``component``: The identifier of the target component in bootloader.
+
+fwu_bootloader_reject_trial_image(function)
+--------------------------------------------
+**Prototype**
+
+.. code-block:: c
+
+    psa_status_t fwu_bootloader_reject_trial_image(psa_fwu_component_t component);
+
+**Description**
+
+The component is in TRIAL state. Mark the running image in the component as rejected.
+
+**Parameters**
+
+- ``component``: The identifier of the target component in bootloader.
+
+fwu_bootloader_clean_component(function)
+----------------------------------------
+**Prototype**
+
+.. code-block:: c
+
+    psa_status_t fwu_bootloader_clean_component(psa_fwu_component_t component);
+
+**Description**
+
+The component is in FAILED or UPDATED state. Clean the staging area of the component.
+
+**Parameters**
+
+- ``component``: The identifier of the target component in bootloader.
 
 fwu_bootloader_get_image_info(function)
 ---------------------------------------
@@ -205,9 +241,10 @@
 
 .. code-block:: c
 
-    psa_status_t fwu_bootloader_get_image_info(bl_image_id_t    bootloader_image_id,
-                                               bool             staging_area,
-                                               tfm_image_info_t *info);
+    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);
 
 **Description**
 
@@ -216,13 +253,10 @@
 
 **Parameters**
 
-    - ``bootloader_image_id``: The identifier of the target image in bootloader.
-    - ``active_image``: Indicates image location.
-
-        - ``True``: the running image.
-        - ``False``: the image in the passive(or staging) slot.
-
-    - ``info``: Buffer containing the image information.
+    - ``component``: The identifier of the target component in bootloader.
+    - ``query_state``: Whether query the 'state' field of psa_fwu_component_info_t.
+    - ``query_impl_info``: Whether Query 'impl' field of psa_fwu_component_info_t.
+    - ``info``: Buffer containing return the component information.
 
 ******************************************
 Additional shared data between BL2 and SPE
@@ -235,26 +269,48 @@
 size. The FWU partition will read the shared data at the partition
 initialization.
 
-******************
-Image ID structure
-******************
-The structure of image ID is:
-    image_id[7:0]: slot.
-    image_id[15:8]: image type.
-    image_id[31:16]: specific image ID.
+*********************************************
+Build configurations related to FWU partition
+*********************************************
+- ``TFM_PARTITION_FIRMWARE_UPDATE`` Controls whether FWU partition is enabled or not.
+- ``TFM_FWU_BOOTLOADER_LIB`` Bootloader configure file for FWU partition.
+- ``TFM_CONFIG_FWU_MAX_WRITE_SIZE`` The maximum permitted size for block in psa_fwu_write, in bytes.
+- ``TFM_FWU_BUF_SIZE`` Size of the FWU internal data transfer buffer (defaults to
+  TFM_CONFIG_FWU_MAX_WRITE_SIZE if not set).
+- ``FWU_STACK_SIZE`` The stack size of FWU Partition.
+- ``FWU_DEVICE_CONFIG_FILE`` The device configuration file for FWU partition. The default value is
+  the configuration file generated for MCUboot. The following macros should be defined in the
+  configuration file:
 
-Three image types are defined in this partition.
-- FWU_IMAGE_TYPE_NONSECURE: the non_secure image
-- FWU_IMAGE_TYPE_SECURE: the secure image
-- FWU_IMAGE_TYPE_FULL: the secure + non_secure image
+  - ``FWU_COMPONENT_NUMBER`` The number of components on the device.
 
-Macros **FWU_CALCULATE_IMAGE_ID**, **FWU_IMAGE_ID_GET_TYPE** and
-**FWU_IMAGE_ID_GET_SLOT** are dedicated to converting the image id, type, and
-slot. The service users can call these macros to get the image ID.
+    .. Note::
 
-.. Note::
+        In this design, component ID ranges from 0 to ``FWU_COMPONENT_NUMBER`` - 1.
 
-    The image ID structure, as well as the macros listed here, is TF-M specific implementation.
+  - ``FWU_SUPPORT_TRIAL_STATE`` Whether TRIAL component state is supported.
+- ``TEST_NS_FWU`` FWU nonsecure tests switch.
+- ``TEST_S_FWU`` FWU secure tests switch.
+
+    .. Note::
+
+        The running image which supports revert mechanism should be confirmed before initiating a
+        firmware update process. For example, if the running image is built with
+        ``-DMCUBOOT_UPGRADE_STRATEGY=SWAP_USING_MOVE``, the image should be confirmed either by
+        adding ``-DMCUBOOT_CONFIRM_IMAGE=ON`` build option or by calling ``psa_fwu_accept()`` API
+        before initiating a firmware update process. Otherwise, ``PSA_ERROR_BAD_STATE`` will be
+        returned by ``psa_fwu_start()``.
+
+*************************************
+Limitations of current implementation
+*************************************
+Currently, the MCUboot based implementation does not record image update results like failure or
+success. And FWU partition does not detect failure errors in bootloader installation. If an image
+installation fails in the bootloader and the old image still runs after reboot, ``PSA_FWU_READY``
+state will be returned by ``psa_fwu_query()`` after reboot.
+
+Currently, image download recovery after a reboot is not supported. If a reboot happens in image
+preparation, the downloaded image data will be ignored after the reboot.
 
 ***********************************
 Benefits Analysis on this Partition
@@ -265,7 +321,7 @@
 The APIs listed in PSA Firmware Update API spec [1]_ can also be implemented in
 the non-secure side.
 
-Pros and Cons for Implementing FWU APIs in Secure Side
+Pros and Cons for implementing FWU APIs in secure side
 ======================================================
 
 Pros
@@ -304,7 +360,7 @@
 Reference
 *********
 
-.. [1] `PSA Firwmare Update API <https://developer.arm.com/documentation/ihi0093/0000/>`_
+.. [1] `PSA Firwmare Update API <https://arm-software.github.io/psa-api/fwu/1.0/>`_
 
 --------------
 
diff --git a/interface/include/psa/error.h b/interface/include/psa/error.h
index e8903f0..fee8c99 100644
--- a/interface/include/psa/error.h
+++ b/interface/include/psa/error.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -28,8 +28,6 @@
 #endif
 
 #define PSA_SUCCESS                     ((psa_status_t)0)
-#define PSA_SUCCESS_REBOOT              ((psa_status_t)1)
-#define PSA_SUCCESS_RESTART             ((psa_status_t)2)
 
 #define PSA_ERROR_PROGRAMMER_ERROR      ((psa_status_t)-129)
 #define PSA_ERROR_CONNECTION_REFUSED    ((psa_status_t)-130)
@@ -52,7 +50,9 @@
 #define PSA_ERROR_HARDWARE_FAILURE      ((psa_status_t)-147)
 #define PSA_ERROR_INVALID_SIGNATURE     ((psa_status_t)-149)
 #define PSA_ERROR_DEPENDENCY_NEEDED     ((psa_status_t)-156)
-#define PSA_ERROR_CURRENTLY_INSTALLING  ((psa_status_t)-157)
+#define PSA_ERROR_FLASH_ABUSE           ((psa_status_t)-160)
+#define PSA_ERROR_INSUFFICIENT_POWER    ((psa_status_t)-161)
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/interface/include/psa/fwu_config.h.in b/interface/include/psa/fwu_config.h.in
index e7b9b51..9bc8616 100644
--- a/interface/include/psa/fwu_config.h.in
+++ b/interface/include/psa/fwu_config.h.in
@@ -8,6 +8,35 @@
 #ifndef __FWU_CONFIG_H__
 #define __FWU_CONFIG_H__
 
-#cmakedefine PSA_FWU_MAX_BLOCK_SIZE @PSA_FWU_MAX_BLOCK_SIZE@
+/* This file contains device specific configurations in FWU partition based
+ * on MCUboot.
+ */
+
+/* Components if the device. When porting a specific bootloader to FWU partition,
+ * the bootloader specific image types can be defined here.
+ */
+#if MCUBOOT_IMAGE_NUMBER > 1
+#define FWU_COMPONENT_ID_SECURE           0x00U
+#define FWU_COMPONENT_ID_NONSECURE        0x01U
+#else
+#define FWU_COMPONENT_ID_FULL             0x00U
+#endif
+#define FWU_COMPONENT_NUMBER              MCUBOOT_IMAGE_NUMBER
+
+/* The maximum size of an image digest in bytes. This is dependent
+ * on the hash algorithm used.
+ */
+#define TFM_FWU_MAX_DIGEST_SIZE              32
+
+/* 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/interface/include/psa/update.h b/interface/include/psa/update.h
index 5af0f1c..3c8037a 100644
--- a/interface/include/psa/update.h
+++ b/interface/include/psa/update.h
@@ -5,6 +5,8 @@
  *
  */
 
+/* PSA Firmware Update API v1.0 Beta */
+
 #ifndef PSA_UPDATE_H
 #define PSA_UPDATE_H
 
@@ -12,255 +14,268 @@
 #include <stdint.h>
 
 #include "psa/error.h"
+#ifdef FWU_DEVICE_CONFIG_FILE
+#include FWU_DEVICE_CONFIG_FILE
+#else
 #include "psa/fwu_config.h"
+#endif
 #include "tfm_fwu_defs.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#define TFM_FWU_INVALID_IMAGE_ID             0
-
-/* The maximum size of an image digest in bytes. This is dependent
- * on the hash algorithm used.
+/**
+ * @brief The major version of this implementation of the Firmware Update API.
  */
-#define PSA_FWU_MAX_DIGEST_SIZE              32
-#define TFM_IMAGE_INFO_INVALID_DIGEST        0xFF
-
-/* The image ID macros. */
-#define FWU_IMAGE_ID_SLOT_POSITION           0U
-
-/* The area where the image is running. */
-#define FWU_IMAGE_ID_SLOT_ACTIVE             0x01U
-
-/* The area to stage the image. */
-#define FWU_IMAGE_ID_SLOT_STAGE              0x02U
-#define FWU_IMAGE_ID_SLOT_MASK               0x00FF
-
-#define FWU_IMAGE_ID_TYPE_POSITION           8U
-#define FWU_IMAGE_ID_SPECIFIC_ID_POSITION    16U
-
-#define FWU_CALCULATE_IMAGE_ID(slot, type, specific_id)             \
-                             ((slot & FWU_IMAGE_ID_SLOT_MASK) |     \
-                             (type << FWU_IMAGE_ID_TYPE_POSITION) | \
-                             (specific_id << FWU_IMAGE_ID_SPECIFIC_ID_POSITION))
-#define FWU_IMAGE_ID_GET_TYPE(image_id) (image_id >> FWU_IMAGE_ID_TYPE_POSITION)
-#define FWU_IMAGE_ID_GET_SLOT(image_id) (image_id & FWU_IMAGE_ID_SLOT_MASK)
-
-/* Image state macros. */
-#define PSA_IMAGE_UNDEFINED            0
-#define PSA_IMAGE_CANDIDATE            1
-#define PSA_IMAGE_INSTALLED            2
-#define PSA_IMAGE_REJECTED             3
-#define PSA_IMAGE_PENDING_INSTALL      4
-#define PSA_IMAGE_REBOOT_NEEDED        5
-
-/*
- * image_id[7:0]: slot.
- * image_id[15:8]: image type.
- * image_id[31:16]: specific image ID.
- */
-typedef uint32_t psa_image_id_t;
-
-typedef struct tfm_image_version_s {
-    uint8_t iv_major;
-    uint8_t iv_minor;
-    uint16_t iv_revision;
-    uint32_t iv_build_num;
-} psa_image_version_t;
-
-typedef struct tfm_image_info_s {
-    psa_image_version_t version;
-    uint8_t state;
-    uint8_t digest[PSA_FWU_MAX_DIGEST_SIZE];
-} psa_image_info_t;
-
-typedef struct psa_hash_s {
-    uint8_t value[PSA_FWU_MAX_DIGEST_SIZE];
-} psa_hash_t;
+#define PSA_FWU_API_VERSION_MAJOR 1
 
 /**
- * \brief Writes an image to its staging area.
- *
- * Writes the image data 'block' with length 'block_size' to its staging area.
- * If the image size is less than or equal to PSA_FWU_MAX_BLOCK_SIZE, the
- * caller can send the entire image in one call.
- * If the image size is greater than PSA_FWU_MAX_BLOCK_SIZE, the caller must
- * send parts of the image by calling this API multiple times with different
- * data blocks.
- *
- * \param[in] image_id        The identifier of the image
- * \param[in] block_offset    The offset of the block 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. The size must not be greater than
- *                            PSA_FWU_MAX_BLOCK_SIZE.
- *
- * \return A status indicating the success/failure of the operation
- *
- * \retval PSA_SUCCESS                     The data in block has been
- *                                         successfully stored.
- * \retval PSA_ERROR_INVALID_ARGUMENT      One of the following error
- *                                         conditions occurred:
- *                                         The parameter size is greater than
- *                                         PSA_FWU_MAX_BLOCK_SIZE;
- *                                         The parameter size is 0;
- *                                         The combination of offset and size
- *                                         is out of bounds.
- *
- * \retval PSA_ERROR_INSUFFICIENT_MEMORY   There is not enough memory to
- *                                         process the update
- * \retval PSA_ERROR_INSUFFICIENT_STORAGE  There is not enough storage to
- *                                         process the update
- * \retval PSA_ERROR_GENERAL_ERROR         A fatal error occurred
- * \retval PSA_ERROR_CURRENTLY_INSTALLING        The image is currently locked for
- *                                         writing.
+ * @brief The minor version of this implementation of the Firmware Update API.
  */
-psa_status_t psa_fwu_write(psa_image_id_t image_id,
-                           size_t block_offset,
+#define PSA_FWU_API_VERSION_MINOR 0
+
+/**
+ * @brief A status code that indicates that the firmware of another component
+ *        requires updating.
+ */
+#define PSA_ERROR_DEPENDENCY_NEEDED ((psa_status_t)-156)
+
+/**
+ * @brief A status code that indicates that the system is limiting i/o
+ *        operations to avoid rapid flash exhaustion.
+ */
+#define PSA_ERROR_FLASH_ABUSE ((psa_status_t)-160)
+
+/**
+ * @brief A status code that indicates that the system does not have enough
+ *        power to carry out the request.
+ */
+#define PSA_ERROR_INSUFFICIENT_POWER ((psa_status_t)-161)
+
+/**
+ * @brief The action was completed successfully and requires a system reboot to
+ *        complete installation.
+ */
+#define PSA_SUCCESS_REBOOT ((psa_status_t)+1)
+
+/**
+ * @brief The action was completed successfully and requires a restart of the
+ *        component to complete installation.
+ */
+#define PSA_SUCCESS_RESTART ((psa_status_t)+2)
+
+/**
+ * @brief Firmware component type identifier.
+ */
+typedef uint8_t psa_fwu_component_t;
+
+/**
+ * @brief Version information about a firmware image.
+ */
+typedef struct psa_fwu_image_version_t {
+    /* The major version of an image. */
+    uint8_t major;
+    /* The minor version of an image. */
+    uint8_t minor;
+    /* The revision or patch version of an image. */
+    uint16_t patch;
+    /* The build number of an image. */
+    uint32_t build;
+} psa_fwu_image_version_t;
+
+/**
+ * @brief The READY state: the component is ready to start another update.
+ */
+#define PSA_FWU_READY 0u
+
+/**
+ * @brief The WRITING state: a new firmware image is being written to the
+ *        firmware store.
+ */
+#define PSA_FWU_WRITING 1u
+
+/**
+ * @brief The CANDIDATE state: a new firmware image is ready for installation.
+ */
+#define PSA_FWU_CANDIDATE 2u
+
+/**
+ * @brief The STAGED state: a new firmware image is queued for installation.
+ */
+#define PSA_FWU_STAGED 3u
+
+/**
+ * @brief The FAILED state: a firmware update has been cancelled or has failed.
+ */
+#define PSA_FWU_FAILED 4u
+
+/**
+ * @brief The TRIAL state: a new firmware image requires testing prior to
+ *        acceptance of the update.
+ */
+#define PSA_FWU_TRIAL 5u
+
+/**
+ * @brief The REJECTED state: a new firmware image has been rejected after
+ *        testing.
+ */
+#define PSA_FWU_REJECTED 6u
+
+/**
+ * @brief The UPDATED state: a firmware update has been successful, and the new
+ *        image is now active.
+ */
+#define PSA_FWU_UPDATED 7u
+
+/**
+ * @brief Flag to indicate whether the image data in the component staging area
+ *        is discarded at system reset.
+ */
+#define PSA_FWU_FLAG_VOLATILE_STAGING 0x00000001u
+
+/**
+ * @brief Flag to indicate whether a firmware component expects encrypted images
+ *        during an update.
+ */
+#define PSA_FWU_FLAG_ENCRYPTION 0x00000002u
+
+/**
+ * @brief The implementation-specific data in the component information
+ *        structure.
+ */
+typedef struct {
+    /* The digest of second image when store state is CANDIDATE. */
+    uint8_t candidate_digest[TFM_FWU_MAX_DIGEST_SIZE];
+ } psa_fwu_impl_info_t;
+
+/**
+ * @brief Information about the firmware store for a firmware component.
+ */
+typedef struct psa_fwu_component_info_t {
+    /* State of the component. */
+    uint8_t state;
+    /* Error for second image when store state is REJECTED or FAILED. */
+    psa_status_t error;
+    /* Version of active image. */
+    psa_fwu_image_version_t version;
+    /* Maximum image size in bytes. */
+    uint32_t max_size;
+    /* Flags that describe extra information about the firmware component. */
+    uint32_t flags;
+    /* Implementation-defined image location. */
+    uint32_t location;
+    /* Reserved for implementation-specific usage. */
+    psa_fwu_impl_info_t impl;
+} psa_fwu_component_info_t;
+
+/**
+ * @brief Retrieve the firmware store information for a specific firmware
+ *        component.
+ *
+ * @param component Firmware component for which information is requested.
+ * @param info      Output parameter for component information.
+ *
+ * @return Result status.
+ */
+psa_status_t psa_fwu_query(psa_fwu_component_t component,
+                           psa_fwu_component_info_t *info);
+
+/**
+ * @brief Begin a firmware update operation for a specific firmware component.
+ *
+ * @param component     Identifier of the firmware component to be updated.
+ * @param manifest      A pointer to a buffer containing a detached manifest for
+ *                      the update.
+ * @param manifest_size The size of the detached manifest.
+ *
+ * @return Result status.
+ */
+psa_status_t psa_fwu_start(psa_fwu_component_t component,
+                           const void *manifest,
+                           size_t manifest_size);
+
+/**
+ * @brief The maximum permitted size for block in psa_fwu_write(), in bytes.
+ */
+#define PSA_FWU_MAX_WRITE_SIZE TFM_CONFIG_FWU_MAX_WRITE_SIZE
+
+/**
+ * @brief Write a firmware image, or part of a firmware image, to its staging
+ *        area.
+ *
+ * @param component    Identifier of the firmware component being updated.
+ * @param image_offset The offset of the data block in the whole image.
+ * @param block        A buffer containing a block of image data.
+ * @param block_size   Size of block, in bytes.
+ *
+ * @return Result status.
+ */
+psa_status_t psa_fwu_write(psa_fwu_component_t component,
+                           size_t image_offset,
                            const void *block,
                            size_t block_size);
 
-
 /**
- * \brief Starts the installation of an image.
+ * @brief Mark a firmware image in the staging area as ready for installation.
  *
- * The authenticity and integrity of the image is checked during installation.
- * If a reboot is required to complete installation then the implementation
- * can choose to defer the authenticity checks to that point.
+ * @param component Identifier of the firmware component to install.
  *
- * \param[in] image_id            The identifier of the image to install
- * \param[out] dependency_uuid    If PSA_ERROR_DEPENDENCY_NEEDED is returned,
- *                                this parameter is filled with dependency
- *                                information
- * \param[out] dependency_version If PSA_ERROR_DEPENDENCY_NEEDED is returned,
- *                                this parameter is filled with the minimum
- *                                required version for the dependency
- *
- * \return A status indicating the success/failure of the operation
- *
- * \retval PSA_SUCCESS                     The image was successfully
- *                                         installed. The platform does not
- *                                         require a reboot.
- * \retval PSA_SUCCESS_REBOOT              A system reboot is needed to finish
- *                                         installation.
- * \retval PSA_ERROR_INVALID_ARGUMENT      Bad input parameter
- * \retval PSA_ERROR_INVALID_SIGNATURE     The signature is incorrect
- * \retval PSA_ERROR_GENERAL_ERROR         A fatal error occurred
- * \retval PSA_ERROR_DEPENDENCY_NEEDED     A different image requires
- *                                         installation first
- * \retval PSA_ERROR_STORAGE_FAILURE       Some persistent storage could not be
- *                                         read or written by the
- *                                         implementation
+ * @return Result status.
  */
-psa_status_t psa_fwu_install(psa_image_id_t image_id,
-                             psa_image_id_t *dependency_uuid,
-                             psa_image_version_t *dependency_version);
+psa_status_t psa_fwu_finish(psa_fwu_component_t component);
 
 /**
- * \brief Aborts an ongoing installation and erases the staging area of the
- *        image.
+ * @brief Abandon an update that is in WRITING or CANDIDATE state.
  *
- * \param[in] image_id      The identifier of the image to abort installation
+ * @param component Identifier of the firmware component to be cancelled.
  *
- * \return A status indicating the success/failure of the operation
- *
- * \retval PSA_SUCCESS                    Installation of the provided image_id
- *                                        has been aborted
- * \retval PSA_ERROR_INVALID_ARGUMENT     No image with the provided image_id
- *                                        is currently being installed
- * \retval PSA_ERROR_NOT_PERMITTED        The caller is not authorized to
- *                                        abort an installation
+ * @return Result status.
  */
-psa_status_t psa_fwu_abort(psa_image_id_t image_id);
+psa_status_t psa_fwu_cancel(psa_fwu_component_t component);
 
 /**
- * \brief Returns information for an image of a particular image_id.
+ * @brief Prepare the component for another update.
  *
- * \param[in] image_id         The image_id of the image to query
+ * @param component Identifier of the firmware component to tidy up.
  *
- * \param[out] info            Output parameter for image information
- *                             related to the image_id
- *
- * \return A status indicating the success/failure of the operation
- *
- * \retval PSA_SUCCESS                     Image information has been returned
- * \retval PSA_ERROR_NOT_PERMITTED         The caller is not authorized to
- *                                         access platform version information
+ * @return Result status.
  */
-psa_status_t psa_fwu_query(psa_image_id_t image_id,
-                           psa_image_info_t *info);
+psa_status_t psa_fwu_clean(psa_fwu_component_t component);
 
 /**
- * \brief Requests the platform to reboot. On success, the platform initiates
- *        a reboot, and might not return to the caller.
+ * @brief Start the installation of all firmware images that have been prepared
+ *        for update.
  *
- * \return A status indicating the success/failure of the operation
+ * @return Result status.
+ */
+psa_status_t psa_fwu_install(void);
+
+/**
+ * @brief Requests the platform to reboot.
  *
- * \retval PSA_SUCCESS                   The platform will reboot soon
- * \retval PSA_ERROR_NOT_PERMITTED       The caller is not authorized to
- *                                       reboot the platform
+ * @return Result status.
  */
 psa_status_t psa_fwu_request_reboot(void);
 
 /**
- * \brief Indicates to the implementation that the upgrade was successful.
+ * @brief Abandon an installation that is in STAGED or TRIAL state.
  *
- * \param[in] image_id         The image_id of the image to query
+ * @param error An application-specific error code chosen by the application.
  *
- * \return A status indicating the success/failure of the operation
- *
- * \retval PSA_SUCCESS                  The image and its dependencies have
- *                                      transitioned into a PSA_IMAGE_INSTALLED
- *                                      state
- * \retval PSA_ERROR_NOT_SUPPORTED      The implementation does not support a
- *                                      PSA_IMAGE_PENDING_INSTALL state
- * \retval PSA_ERROR_NOT_PERMITTED      The caller is not permitted to make
- *                                      this call
+ * @return Result status.
  */
-psa_status_t psa_fwu_accept(psa_image_id_t image_id);
+psa_status_t psa_fwu_reject(psa_status_t error);
 
 /**
- * \brief Stores a manifest object and associates it with a particular image ID.
+ * @brief Accept a firmware update that is currently in TRIAL state.
  *
- * \param[in] image_id            The identifier of the image
- *
- * \param[in] manifest            A pointer to a buffer containing a manifest
- *                                object
- *
- * \param[in] manifest_size       The size of the manifest parameter
- *
- * \param[in] manifest_dependency Output parameter containing the hash of a
- *                                required manifest when
- *                                PSA_ERROR_DEPENDENCY_NEEDED is returned
- *
- * \return A status indicating the success/failure of the operation
- *
- * \retval PSA_SUCCESS                     The manifest is persisted
- * \retval PSA_ERROR_NOT_PERMITTED         The manifest is too old to be
- *                                         installed
- * \retval PSA_ERROR_WRONG_DEVICE          The manifest is not intended for this
- *                                         device
- * \retval PSA_ERROR_INVALID_SIGNATURE     The manifest signature is not valid
- * \retval PSA_ERROR_DEPENDENCY_NEEDED     A different manifest is needed
- * \retval PSA_ERROR_INVALID_ARGUMENT      Parameter size is 0 or a pointer
- *                                         parameter is NULL
- * \retval PSA_ERROR_COMMUNICATION_FAILURE The system could not communicate with
- *                                         the installer
- * \retval PSA_ERROR_NOT_SUPPORTED         This function is not implemented
- * \retval PSA_ERROR_CURRENTLY_INSTALLING  An existing manifest for image ID is
- *                                         currently being installed and is
- *                                         locked from writing
- * \retval PSA_ERROR_GENERIC_ERROR         A fatal error occurred
+ * @return Result status.
  */
-psa_status_t psa_fwu_set_manifest(psa_image_id_t image_id,
-                                  const void *manifest,
-                                  size_t manifest_size,
-                                  psa_hash_t *manifest_dependency);
-
+psa_status_t psa_fwu_accept(void);
 
 #ifdef __cplusplus
 }
 #endif
+
 #endif /* PSA_UPDATE_H */
diff --git a/interface/include/tfm_fwu_defs.h b/interface/include/tfm_fwu_defs.h
index fe7e2bf..a940d1f 100644
--- a/interface/include/tfm_fwu_defs.h
+++ b/interface/include/tfm_fwu_defs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -12,20 +12,17 @@
 extern "C" {
 #endif
 
-/* Image type identities. When porting a specific bootloader to FWU partition,
- * the bootloader specific image types can be defined here.
- */
-#define FWU_IMAGE_TYPE_NONSECURE        0x01U
-#define FWU_IMAGE_TYPE_SECURE           0x02U
-#define FWU_IMAGE_TYPE_FULL             0x03U
-
 /* FWU message types that distinguish FWU services. */
-#define TFM_FWU_WRITE                1001
-#define TFM_FWU_INSTALL              1002
-#define TFM_FWU_ABORT                1003
-#define TFM_FWU_QUERY                1004
-#define TFM_FWU_REQUEST_REBOOT       1005
-#define TFM_FWU_ACCEPT               1006
+#define TFM_FWU_START                1001
+#define TFM_FWU_WRITE                1002
+#define TFM_FWU_FINISH               1003
+#define TFM_FWU_CANCEL               1004
+#define TFM_FWU_INSTALL              1005
+#define TFM_FWU_CLEAN                1006
+#define TFM_FWU_REJECT               1007
+#define TFM_FWU_REQUEST_REBOOT       1008
+#define TFM_FWU_ACCEPT               1009
+#define TFM_FWU_QUERY                1010
 
 #ifdef __cplusplus
 }
diff --git a/interface/src/tfm_fwu_api.c b/interface/src/tfm_fwu_api.c
index 3cba758..f7565bf 100644
--- a/interface/src/tfm_fwu_api.c
+++ b/interface/src/tfm_fwu_api.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -10,56 +10,75 @@
 #include "psa_manifest/sid.h"
 #include "tfm_api.h"
 
-psa_status_t psa_fwu_write(const psa_image_id_t image_id,
-                           size_t block_offset,
+psa_status_t psa_fwu_start(psa_fwu_component_t component,
+                           const void *manifest,
+                           size_t manifest_size)
+{
+    psa_invec in_vec[] = {
+        { .base = &component, .len = sizeof(component) },
+        { .base = manifest, .len = manifest_size }
+    };
+
+    return psa_call(TFM_FIRMWARE_UPDATE_SERVICE_HANDLE, TFM_FWU_START,
+                    in_vec, IOVEC_LEN(in_vec), NULL, 0);
+}
+
+psa_status_t psa_fwu_write(psa_fwu_component_t component,
+                           size_t image_offset,
                            const void *block,
                            size_t block_size)
 {
     psa_invec in_vec[] = {
-        { .base = &image_id, .len = sizeof(image_id) },
-        { .base = &block_offset, .len = sizeof(block_offset) },
+        { .base = &component, .len = sizeof(component) },
+        { .base = &image_offset, .len = sizeof(image_offset) },
         { .base = block, .len = block_size }
     };
 
     return psa_call(TFM_FIRMWARE_UPDATE_SERVICE_HANDLE, TFM_FWU_WRITE,
+                      in_vec, IOVEC_LEN(in_vec), NULL, 0);
+}
+
+psa_status_t psa_fwu_finish(psa_fwu_component_t component)
+{
+    psa_invec in_vec[] = {
+        { .base = &component, .len = sizeof(component) },
+    };
+
+    return psa_call(TFM_FIRMWARE_UPDATE_SERVICE_HANDLE, TFM_FWU_FINISH,
                     in_vec, IOVEC_LEN(in_vec), NULL, 0);
 }
 
-psa_status_t psa_fwu_install(const psa_image_id_t image_id,
-                             psa_image_id_t *dependency_uuid,
-                             psa_image_version_t *dependency_version)
+psa_status_t psa_fwu_install(void)
 {
-    psa_invec in_vec[] = {
-        { .base = &image_id, .len = sizeof(image_id) }
-    };
-
-    psa_outvec out_vec[] = {
-        { .base = dependency_uuid, .len = sizeof(*dependency_uuid) },
-        { .base = dependency_version, .len = sizeof(*dependency_version)}
-    };
-
-    if ((dependency_uuid == NULL) || (dependency_version == NULL)) {
-        return PSA_ERROR_INVALID_ARGUMENT;
-    }
-
     return psa_call(TFM_FIRMWARE_UPDATE_SERVICE_HANDLE, TFM_FWU_INSTALL,
-                    in_vec, IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
+                    NULL, 0, NULL, 0);
 }
 
-psa_status_t psa_fwu_abort(const psa_image_id_t image_id)
+psa_status_t psa_fwu_cancel(psa_fwu_component_t component)
 {
     psa_invec in_vec[] = {
-        { .base = &image_id, .len = sizeof(image_id) }
+        { .base = &component, .len = sizeof(component) },
     };
 
-    return psa_call(TFM_FIRMWARE_UPDATE_SERVICE_HANDLE, TFM_FWU_ABORT,
+    return psa_call(TFM_FIRMWARE_UPDATE_SERVICE_HANDLE, TFM_FWU_CANCEL,
                     in_vec, IOVEC_LEN(in_vec), NULL, 0);
 }
 
-psa_status_t psa_fwu_query(const psa_image_id_t image_id, psa_image_info_t *info)
+psa_status_t psa_fwu_clean(psa_fwu_component_t component)
 {
     psa_invec in_vec[] = {
-        { .base = &image_id, .len = sizeof(image_id) }
+        { .base = &component, .len = sizeof(component) },
+    };
+
+    return psa_call(TFM_FIRMWARE_UPDATE_SERVICE_HANDLE, TFM_FWU_CLEAN,
+                    in_vec, IOVEC_LEN(in_vec), NULL, 0);
+}
+
+psa_status_t psa_fwu_query(psa_fwu_component_t component,
+                           psa_fwu_component_info_t *info)
+{
+    psa_invec in_vec[] = {
+        { .base = &component, .len = sizeof(component) }
     };
     psa_outvec out_vec[] = {
         { .base = info, .len = sizeof(*info)}
@@ -75,24 +94,18 @@
                     NULL, 0, NULL, 0);
 }
 
-psa_status_t psa_fwu_accept(psa_image_id_t image_id)
+psa_status_t psa_fwu_accept(void)
 {
-    psa_invec in_vec[] = {
-        { .base = &image_id, .len = sizeof(image_id) }
-    };
-
     return psa_call(TFM_FIRMWARE_UPDATE_SERVICE_HANDLE, TFM_FWU_ACCEPT,
-                    in_vec, IOVEC_LEN(in_vec), NULL, 0);
+                    NULL, 0, NULL, 0);
 }
 
-psa_status_t psa_fwu_set_manifest(psa_image_id_t image_id,
-                                  const void *manifest,
-                                  size_t manifest_size,
-                                  psa_hash_t *manifest_dependency)
+psa_status_t psa_fwu_reject(psa_status_t error)
 {
-    psa_status_t status;
+    psa_invec in_vec[] = {
+        { .base = &error, .len = sizeof(error) }
+    };
 
-    status = PSA_ERROR_NOT_SUPPORTED;
-
-    return status;
+    return psa_call(TFM_FIRMWARE_UPDATE_SERVICE_HANDLE, TFM_FWU_REJECT,
+                    in_vec, IOVEC_LEN(in_vec), NULL, 0);
 }
diff --git a/secure_fw/partitions/firmware_update/CMakeLists.txt b/secure_fw/partitions/firmware_update/CMakeLists.txt
index 79a1a0e..0727579 100644
--- a/secure_fw/partitions/firmware_update/CMakeLists.txt
+++ b/secure_fw/partitions/firmware_update/CMakeLists.txt
@@ -29,7 +29,6 @@
 target_sources(tfm_psa_rot_partition_fwu
     PRIVATE
         tfm_fwu_req_mngr.c
-        tfm_fwu.c
         ${CMAKE_BINARY_DIR}/generated/secure_fw/partitions/firmware_update/auto_generated/intermedia_tfm_firmware_update.c
 )
 target_sources(tfm_partitions
@@ -49,10 +48,28 @@
         tfm_sprt
 )
 
+
+# Generate firmware update feature
+if (NOT FWU_DEVICE_CONFIG_FILE)
+    configure_file(${CMAKE_SOURCE_DIR}/interface/include/psa/fwu_config.h.in
+                   ${CMAKE_BINARY_DIR}/generated/interface/include/psa/fwu_config.h
+                   @ONLY)
+    set(FWU_DEVICE_CONFIG_FILE "${CMAKE_BINARY_DIR}/generated/interface/include/psa/fwu_config.h")
+else()
+    # FWU_DEVICE_CONFIG_FILE exists and is a file
+    if(NOT EXISTS ${FWU_DEVICE_CONFIG_FILE})
+        message(FATAL_ERROR "FWU_DEVICE_CONFIG_FILE:${FWU_DEVICE_CONFIG_FILE} does not exist.")
+    elseif(IS_DIRECTORY ${FWU_DEVICE_CONFIG_FILE})
+        message(FATAL_ERROR "FWU_DEVICE_CONFIG_FILE:${FWU_DEVICE_CONFIG_FILE} is a folder while a file is expected.")
+    endif()
+endif()
+
+
 target_compile_definitions(tfm_psa_rot_partition_fwu
     PRIVATE
         $<$<BOOL:${DEFAULT_MCUBOOT_FLASH_MAP}>:DEFAULT_MCUBOOT_FLASH_MAP>
         $<$<BOOL:${TFM_FWU_BUF_SIZE}>:TFM_FWU_BUF_SIZE=${TFM_FWU_BUF_SIZE}>
+        FWU_DEVICE_CONFIG_FILE="${FWU_DEVICE_CONFIG_FILE}"
 )
 
 ############################ Partition Defs ####################################
@@ -66,16 +83,14 @@
     INTERFACE
     TFM_PARTITION_FIRMWARE_UPDATE
 )
-# Generate firmware update feature
-configure_file(${CMAKE_SOURCE_DIR}/interface/include/psa/fwu_config.h.in
-               ${CMAKE_BINARY_DIR}/generated/interface/include/psa/fwu_config.h
-               @ONLY)
 
 ################ Display the configuration being applied #######################
 
 include(utils)
 dump_options("Firmware Update Partition config"
 "
-    FWU_STACK_SIZE
+    TFM_FWU_BOOTLOADER_LIB;
+    FWU_STACK_SIZE;
+    FWU_DEVICE_CONFIG_FILE
 "
 )
diff --git a/secure_fw/partitions/firmware_update/bootloader/mcuboot/CMakeLists.txt b/secure_fw/partitions/firmware_update/bootloader/mcuboot/CMakeLists.txt
index 271ed0a..6bc22dc 100644
--- a/secure_fw/partitions/firmware_update/bootloader/mcuboot/CMakeLists.txt
+++ b/secure_fw/partitions/firmware_update/bootloader/mcuboot/CMakeLists.txt
@@ -1,5 +1,5 @@
 #-------------------------------------------------------------------------------
-# Copyright (c) 2021, Arm Limited. All rights reserved.
+# Copyright (c) 2021-2022, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
diff --git a/secure_fw/partitions/firmware_update/bootloader/mcuboot/tfm_mcuboot_fwu.c b/secure_fw/partitions/firmware_update/bootloader/mcuboot/tfm_mcuboot_fwu.c
index 7ce8148..0842084 100644
--- a/secure_fw/partitions/firmware_update/bootloader/mcuboot/tfm_mcuboot_fwu.c
+++ b/secure_fw/partitions/firmware_update/bootloader/mcuboot/tfm_mcuboot_fwu.c
@@ -14,10 +14,13 @@
 #include "sysflash/sysflash.h"
 #include "tfm_api.h"
 #include "tfm_bootloader_fwu_abstraction.h"
-#include "tfm_fwu_req_mngr.h"
 #include "tfm_boot_status.h"
 #include "service_api.h"
 
+#if (FWU_COMPONENT_NUMBER != MCUBOOT_IMAGE_NUMBER)
+    #error "FWU_COMPONENT_NUMBER mismatch with MCUBOOT_IMAGE_NUMBER"
+#endif
+
 #if (MCUBOOT_IMAGE_NUMBER == 1)
 #define MAX_IMAGE_INFO_LENGTH    (sizeof(struct image_version) + \
                                   SHARED_DATA_ENTRY_HEADER_SIZE)
@@ -25,7 +28,7 @@
 #define MAX_IMAGE_INFO_LENGTH    2 * (sizeof(struct image_version) + \
                                       SHARED_DATA_ENTRY_HEADER_SIZE)
 #endif
-#define TFM_MCUBOOT_FWU_INVALID_IMAGE_ID    0xFF
+
 /*
  * \struct fwu_image_info_data
  *
@@ -40,96 +43,16 @@
 } fwu_image_info_data_t;
 
 typedef struct tfm_fwu_mcuboot_ctx_s {
-    /* The flash area corresponding to mcuboot_image_id. */
+    /* The flash area corresponding to component. */
     const struct flash_area *fap;
-    uint8_t mcuboot_image_id;
 
     /* The size of the downloaded data in the FWU process. */
     size_t loaded_size;
 } tfm_fwu_mcuboot_ctx_t;
 
-static tfm_fwu_mcuboot_ctx_t mcuboot_ctx[TFM_FWU_MAX_IMAGES];
+static tfm_fwu_mcuboot_ctx_t mcuboot_ctx[FWU_COMPONENT_NUMBER];
 static fwu_image_info_data_t __attribute__((aligned(4))) boot_shared_data;
 
-static int convert_id_from_bl_to_mcuboot(bl_image_id_t bl_image_id,
-                                         uint8_t *mcuboot_image_id)
-{
-#if (MCUBOOT_IMAGE_NUMBER == 1)
-    /* Only full image upgrade is supported in this case. */
-    if (bl_image_id != FWU_IMAGE_TYPE_FULL) {
-        LOG_ERRFMT("TFM FWU: multi-image is not supported in current mcuboot configuration.");
-        return -1;
-    }
-
-    /* The image id in mcuboot. 0: the full image. */
-    *mcuboot_image_id = 0;
-#else
-    if (bl_image_id == FWU_IMAGE_TYPE_SECURE) {
-        /* The image id in mcuboot. 0: the secure image. */
-        *mcuboot_image_id = 0;
-    } else if (bl_image_id == FWU_IMAGE_TYPE_NONSECURE) {
-        /* The image id in mcuboot. 1: the non-secure image. */
-        *mcuboot_image_id = 1;
-    }  else {
-        LOG_ERRFMT("TFM FWU: invalid image_type: %d", bl_image_id);
-        return -1;
-    }
-#endif
-    return 0;
-}
-
-#if (MCUBOOT_IMAGE_NUMBER > 1)
-static int convert_id_from_mcuboot_to_bl(uint8_t mcuboot_image_id,
-                                         bl_image_id_t *bl_image_id)
-{
-    uint8_t image_type;
-
-    if (bl_image_id == NULL) {
-        return -1;
-    }
-
-    if (mcuboot_image_id == 0) {
-        /* The image id in mcuboot. 0: the secure image. */
-        image_type = FWU_IMAGE_TYPE_SECURE;
-    } else if (mcuboot_image_id == 1) {
-        /* The image id in mcuboot. 1: the non-secure image. */
-        image_type = FWU_IMAGE_TYPE_NONSECURE;
-    }  else {
-        LOG_ERRFMT("TFM FWU: invalid mcuboot image id\n\r: %d",
-                mcuboot_image_id);
-        return -1;
-    }
-
-    *bl_image_id = image_type;
-    return 0;
-}
-#endif
-
-/*
- * Get the flash area of the image mcuboot_image_id.
- */
-static bool get_flash_image_index(uint8_t mcuboot_image_id, uint8_t *index)
-{
-    for (uint8_t i = 0; i < TFM_FWU_MAX_IMAGES; i++) {
-        if (mcuboot_ctx[i].mcuboot_image_id == mcuboot_image_id) {
-            *index = i;
-            return true;
-        }
-    }
-    return false;
-}
-
-static bool get_next_free_index(uint8_t *index)
-{
-    for (uint8_t i = 0; i < TFM_FWU_MAX_IMAGES; i++) {
-        if (mcuboot_ctx[i].fap == NULL) {
-            *index = i;
-            return true;
-        }
-    }
-    return false;
-}
-
 static int fwu_bootloader_get_shared_data(void)
 {
     return tfm_core_get_boot_data(TLV_MAJOR_FWU,
@@ -137,8 +60,8 @@
                                   sizeof(boot_shared_data));
 }
 
-static psa_status_t get_running_image_version(uint8_t mcuboot_image_id,
-                                              struct image_version *image_ver)
+static psa_status_t get_active_image_version(psa_fwu_component_t component,
+                                             struct image_version *image_ver)
 {
     struct shared_data_tlv_entry tlv_entry;
     uint8_t *tlv_end;
@@ -148,7 +71,7 @@
      * is shared between MCUboot and TF-M. Read the shared memory.
      */
     if (boot_shared_data.header.tlv_magic != SHARED_DATA_TLV_INFO_MAGIC) {
-        return PSA_ERROR_GENERIC_ERROR;
+        return PSA_ERROR_DATA_CORRUPT;
     }
 
     tlv_end = (uint8_t *)&boot_shared_data +
@@ -158,9 +81,9 @@
     while (tlv_curr < tlv_end) {
         (void)memcpy(&tlv_entry, tlv_curr, SHARED_DATA_ENTRY_HEADER_SIZE);
         if ((GET_FWU_CLAIM(tlv_entry.tlv_type) == SW_VERSION) &&
-            (GET_FWU_MODULE(tlv_entry.tlv_type) == mcuboot_image_id)) {
+            (GET_FWU_MODULE(tlv_entry.tlv_type) == component)) {
             if (tlv_entry.tlv_len != sizeof(struct image_version)) {
-                return PSA_ERROR_GENERIC_ERROR;
+                return PSA_ERROR_DATA_CORRUPT;
             }
             memcpy(image_ver,
                 tlv_curr + SHARED_DATA_ENTRY_HEADER_SIZE,
@@ -170,87 +93,68 @@
         tlv_curr += SHARED_DATA_ENTRY_HEADER_SIZE + tlv_entry.tlv_len;
     }
 
-    return PSA_ERROR_GENERIC_ERROR;
+    return PSA_ERROR_DATA_CORRUPT;
 }
 
 psa_status_t fwu_bootloader_init(void)
 {
     if (fwu_bootloader_get_shared_data() != TFM_SUCCESS) {
-        return PSA_ERROR_GENERIC_ERROR;
+        return PSA_ERROR_STORAGE_FAILURE;
     }
     /* add Init of specific flash driver */
     flash_area_driver_init();
     return PSA_SUCCESS;
 }
 
-psa_status_t fwu_bootloader_staging_area_init(bl_image_id_t bootloader_image_id)
+psa_status_t fwu_bootloader_staging_area_init(psa_fwu_component_t component,
+                                              const void *manifest,
+                                              size_t manifest_size)
 {
-    uint8_t mcuboot_image_id = 0;
-    uint8_t index;
     const struct flash_area *fap;
 
-    if (convert_id_from_bl_to_mcuboot(bootloader_image_id,
-                                      &mcuboot_image_id) != 0) {
+    /* MCUboot uses bundled manifest. */
+    if ((manifest_size != 0) || (component >= FWU_COMPONENT_NUMBER)) {
         return PSA_ERROR_INVALID_ARGUMENT;
     }
 
-    if (flash_area_open(FLASH_AREA_IMAGE_SECONDARY(mcuboot_image_id),
+    if (flash_area_open(FLASH_AREA_IMAGE_SECONDARY(component),
                         &fap) != 0) {
         LOG_ERRFMT("TFM FWU: opening flash failed.\r\n");
-        return PSA_ERROR_GENERIC_ERROR;
+        return PSA_ERROR_STORAGE_FAILURE;
     }
+    mcuboot_ctx[component].fap = fap;
 
-    if (get_flash_image_index(mcuboot_image_id, &index) ||
-        get_next_free_index(&index)) {
-        mcuboot_ctx[index].mcuboot_image_id = mcuboot_image_id;
-        mcuboot_ctx[index].fap = fap;
-
-        /* Reset the loaded_size. */
-        mcuboot_ctx[index].loaded_size = 0;
-    } else {
-        return PSA_ERROR_INSUFFICIENT_MEMORY;
-    }
-
-    if (flash_area_erase(fap, 0, fap->fa_size) != 0) {
-        LOG_ERRFMT("TFM FWU: erasing flash failed.\r\n");
-        return PSA_ERROR_GENERIC_ERROR;
-    }
+    /* Reset the loaded_size. */
+    mcuboot_ctx[component].loaded_size = 0;
 
     return PSA_SUCCESS;
 }
 
-psa_status_t fwu_bootloader_load_image(bl_image_id_t bootloader_image_id,
+psa_status_t fwu_bootloader_load_image(psa_fwu_component_t component,
                                        size_t block_offset,
                                        const void *block,
                                        size_t block_size)
 {
-    uint8_t mcuboot_image_id = 0;
-    uint8_t index;
     const struct flash_area *fap;
 
-    if (block == NULL) {
+    if (block == NULL || component >= FWU_COMPONENT_NUMBER) {
         return PSA_ERROR_INVALID_ARGUMENT;
     }
 
-    if (convert_id_from_bl_to_mcuboot(bootloader_image_id,
-                                      &mcuboot_image_id) != 0) {
-        return PSA_ERROR_INVALID_ARGUMENT;
-    }
-
-    /* The image should already be added into the mcuboot_ctx. */
-    if (get_flash_image_index(mcuboot_image_id, &index)) {
-        fap = mcuboot_ctx[index].fap;
+    /* The component should already be added into the mcuboot_ctx. */
+    if (mcuboot_ctx[component].fap != NULL) {
+        fap = mcuboot_ctx[component].fap;
     } else {
-        return PSA_ERROR_INVALID_ARGUMENT;
+        return PSA_ERROR_BAD_STATE;
     }
 
     if (flash_area_write(fap, block_offset, block, block_size) != 0) {
         LOG_ERRFMT("TFM FWU: write flash failed.\r\n");
-        return PSA_ERROR_GENERIC_ERROR;
+        return PSA_ERROR_STORAGE_FAILURE;
     }
 
     /* The overflow check has been done in flash_area_write. */
-    mcuboot_ctx[index].loaded_size += block_size;
+    mcuboot_ctx[component].loaded_size += block_size;
     return PSA_SUCCESS;
 }
 
@@ -289,15 +193,12 @@
 }
 #endif
 
-psa_status_t fwu_bootloader_install_image(bl_image_id_t bootloader_image_id,
-                                          bl_image_id_t *dependency,
-                                        psa_image_version_t *dependency_version)
+psa_status_t fwu_bootloader_install_image(const psa_fwu_component_t *candidates, uint8_t number)
 {
-    uint8_t mcuboot_image_id = 0;
-    const struct flash_area *fap;
-    uint8_t index;
-    psa_status_t ret;
+    uint8_t index_i, cand_index;
 #if (MCUBOOT_IMAGE_NUMBER > 1)
+    psa_fwu_component_t component;
+    const struct flash_area *fap;
     struct image_tlv_iter it;
     struct image_header hdr;
     int rc;
@@ -307,157 +208,176 @@
     struct image_version image_ver = { 0 };
     const struct flash_area *fap_secondary;
     struct image_header hdr_secondary;
-    uint8_t boot_magic[BOOT_MAGIC_SZ];
-    bool check_pass = false;
+    bool check_pass = true;
 #endif
 
-    if ((dependency == NULL || dependency_version == NULL)) {
-        return PSA_ERROR_INVALID_ARGUMENT;
-    }
-
-    if (convert_id_from_bl_to_mcuboot(bootloader_image_id,
-                                      &mcuboot_image_id) != 0) {
-        return PSA_ERROR_INVALID_ARGUMENT;
-    }
-
-    /* The image should already be added into the mcuboot_ctx. */
-    if (get_flash_image_index(mcuboot_image_id, &index)) {
-        fap = mcuboot_ctx[index].fap;
-    } else {
+    if (candidates == NULL) {
         return PSA_ERROR_INVALID_ARGUMENT;
     }
 
 #if (MCUBOOT_IMAGE_NUMBER > 1)
-    /* Read the image header. */
-    if (flash_area_read(fap, 0, &hdr, sizeof(hdr)) != 0) {
-        return PSA_ERROR_GENERIC_ERROR;
-    }
-
-    /* Return PSA_ERROR_GENERIC_ERROR if the image header is invalid. */
-    if (hdr.ih_magic != IMAGE_MAGIC) {
-        return PSA_ERROR_GENERIC_ERROR;
-    }
-
-    /* Initialize the iterator. */
-    if (bootutil_tlv_iter_begin(&it, &hdr, fap, IMAGE_TLV_DEPENDENCY, true)) {
-        return PSA_ERROR_GENERIC_ERROR;
-    }
-
-    /* Iterate and verify the image dependencies. */
-    while (true) {
-        rc = bootutil_tlv_iter_next(&it, &off, &len, NULL);
-        if (rc < 0) {
-            return PSA_ERROR_GENERIC_ERROR;
-        } else if (rc > 0) {
-            /* No more dependency found. */
-            rc = 0;
-            ret = PSA_SUCCESS_REBOOT;
-            break;
+    for (cand_index = 0; cand_index < number; cand_index++) {
+        component = candidates[cand_index];
+        /* The image should already be added into the mcuboot_ctx. */
+        if ((component >= FWU_COMPONENT_NUMBER) ||
+           (mcuboot_ctx[component].fap == NULL)) {
+            return PSA_ERROR_INVALID_ARGUMENT;
         }
-        check_pass = false;
-
-        /* A dependency requirement is found. */
-        if (flash_area_read(fap, off, &dep, len) != 0) {
-            return PSA_ERROR_GENERIC_ERROR;
+        fap = mcuboot_ctx[component].fap;
+        /* Read the image header. */
+        if (flash_area_read(fap, 0, &hdr, sizeof(hdr)) != 0) {
+            return PSA_ERROR_STORAGE_FAILURE;
         }
 
-        if (dep.image_id > MCUBOOT_IMAGE_NUMBER) {
-            return PSA_ERROR_GENERIC_ERROR;
+        /* Return PSA_ERROR_DATA_CORRUPT if the image header is invalid. */
+        if (hdr.ih_magic != IMAGE_MAGIC) {
+            return PSA_ERROR_DATA_CORRUPT;
         }
 
-        /* As this partition does not validate the image in the secondary slot,
-         * so it has no information of which image will be chosen to run after
-         * reboot. So if the dependency image in the primary slot or that in the
-         * secondary slot can meet the dependency requirement, then the
-         * dependency check pass.
-         */
-        /* Check the dependency image in the primary slot. */
-        if (get_running_image_version(dep.image_id,
-                                      &image_ver) != PSA_SUCCESS) {
-            return PSA_ERROR_GENERIC_ERROR;
+        /* Initialize the iterator. */
+        if (bootutil_tlv_iter_begin(&it, &hdr, fap, IMAGE_TLV_DEPENDENCY, true)) {
+            return PSA_ERROR_STORAGE_FAILURE;
         }
-
-        /* Check whether the version of the running image can meet the
-         * dependency requirement.
-         */
-        if (is_version_greater_or_equal(&image_ver,
-                                        &dep.image_min_version)) {
-            check_pass = true;
-        } else {
-            /* The running image cannot meet the dependency requirement. Check
-             * the dependency image in the secondary slot.
-             */
-            if ((flash_area_open(FLASH_AREA_IMAGE_SECONDARY(dep.image_id),
-                                 &fap_secondary)) != 0) {
-                return PSA_ERROR_GENERIC_ERROR;
-            }
-            if (flash_area_read(fap_secondary,
-                                0,
-                                &hdr_secondary,
-                                sizeof(hdr_secondary)) != 0) {
-                flash_area_close(fap_secondary);
-                return PSA_ERROR_GENERIC_ERROR;
+        /* Check dependencies. */
+        while (true) {
+            rc = bootutil_tlv_iter_next(&it, &off, &len, NULL);
+            if (rc < 0) {
+                return PSA_ERROR_STORAGE_FAILURE;
+            } else if (rc > 0) {
+                /* No more dependency found. */
+                rc = 0;
+                break;
             }
 
-            /* Check the version of the dependency image in the secondary slot
-             * only if the image header, as well as the boot magic, is good.
+            /* A dependency requirement is found. Set check_pass to false. */
+            check_pass = false;
+            if (flash_area_read(fap, off, &dep, len) != 0) {
+                return PSA_ERROR_STORAGE_FAILURE;
+            }
+
+            if (dep.image_id > MCUBOOT_IMAGE_NUMBER) {
+                return PSA_ERROR_DATA_CORRUPT;
+            }
+
+            /* As this partition does not validate the image in the secondary slot,
+             * so it has no information of which image will be chosen to run after
+             * reboot. So if the dependency image in the primary slot or that in the
+             * secondary slot can meet the dependency requirement, then the
+             * dependency check pass.
              */
-            if (hdr_secondary.ih_magic == IMAGE_MAGIC) {
-                /* Check the boot magic. */
-                if (flash_area_read(fap_secondary,
-                                    fap_secondary->fa_size - BOOT_MAGIC_SZ,
-                                    boot_magic,
-                                    BOOT_MAGIC_SZ) != 0) {
-                    flash_area_close(fap_secondary);
-                    return PSA_ERROR_GENERIC_ERROR;
+            /* Check the dependency image in the primary slot. */
+            if (get_active_image_version(dep.image_id,
+                                        &image_ver) != PSA_SUCCESS) {
+                return PSA_ERROR_STORAGE_FAILURE;
+            }
+
+            /* Check whether the version of the running image can meet the
+             * dependency requirement.
+             */
+            if (is_version_greater_or_equal(&image_ver,
+                                            &dep.image_min_version)) {
+                check_pass = true;
+            } else {
+                /* Check whether the CANDIDATE image can meet this image's dependency
+                 * requirement.
+                 */
+                for (index_i = 0; index_i < number; index_i++) {
+                    if (candidates[index_i] == dep.image_id)
+                        break;
                 }
-                if ((memcmp(boot_magic, &boot_img_magic, BOOT_MAGIC_SZ) == 0) &&
-                    (is_version_greater_or_equal(&hdr_secondary.ih_ver,
-                                                 &dep.image_min_version))) {
-                    /* The dependency image in the secondary slot meet the
-                     * dependency requirement.
+                if ((index_i < number) && (mcuboot_ctx[dep.image_id].fap != NULL)) {
+                    /* The running image cannot meet the dependency requirement. Check
+                     * the dependency image in the secondary slot.
                      */
-                    check_pass = true;
+                    fap_secondary = mcuboot_ctx[dep.image_id].fap;
+                    if (flash_area_read(fap_secondary,
+                                        0,
+                                        &hdr_secondary,
+                                        sizeof(hdr_secondary)) != 0) {
+                        return PSA_ERROR_STORAGE_FAILURE;
+                    }
+
+                    /* Check the version of the dependency image in the secondary slot
+                     * only if the image header is good.
+                     */
+                    if (hdr_secondary.ih_magic == IMAGE_MAGIC &&
+                        (is_version_greater_or_equal(&hdr_secondary.ih_ver,
+                                                     &dep.image_min_version))) {
+                        /* The dependency image in the secondary slot meet the
+                         * dependency requirement.
+                         */
+                        check_pass = true;
+                    }
                 }
             }
-            flash_area_close(fap_secondary);
-        }
-        if (!check_pass) {
-            if (convert_id_from_mcuboot_to_bl(dep.image_id,
-                                              dependency) != 0) {
-                return PSA_ERROR_GENERIC_ERROR;
-            }
 
-            /* Return the first dependency check failed image. */
-            memcpy(dependency_version,
-                   &dep.image_min_version,
-                   sizeof(*dependency_version));
-            ret = PSA_ERROR_DEPENDENCY_NEEDED;
-            break;
+            /* Return directly if dependency check fails. */
+            if (!check_pass) {
+                return PSA_ERROR_DEPENDENCY_NEEDED;
+            }
         }
     }
-#else
-    /* No dependency check is needed in single image case. */
-    ret = PSA_SUCCESS_REBOOT;
 #endif
 
-    /* Write the boot magic in the image trailer so that this image will be
-     * taken as a candidate. Note that even if a dependency is required, the
-     * boot magic should still be set. Therefore when circular dependency exists
-     * the firmware update will not enter the loop of returning
-     * PSA_ERROR_DEPENDENCY_NEEDED when installing. When all the dependencies
-     * are installed, the user should call the psa_fwu_install API to install
-     * this image again.
+    /* Write the boot magic in image trailer so that these images will be
+     * taken as candidates.
      */
-    if (boot_set_pending_multi(mcuboot_image_id, false) != 0) {
-        return PSA_ERROR_GENERIC_ERROR;
-    } else {
-        return ret;
+    for (cand_index = 0; cand_index < number; cand_index++) {
+        if (boot_set_pending_multi(candidates[cand_index], false) != 0) {
+            /* If failure happens, reject candidates have been installed successfully. */
+            for (index_i = 0; index_i < cand_index; index_i++) {
+                if (fwu_bootloader_reject_staged_image(candidates[index_i]) != PSA_SUCCESS) {
+                    break;
+                }
+            }
+            return PSA_ERROR_STORAGE_FAILURE;
+        }
     }
+    return PSA_SUCCESS_REBOOT;
 }
 
-psa_status_t fwu_bootloader_mark_image_accepted(
-                                              bl_image_id_t bootloader_image_id)
+static inline uint32_t
+boot_magic_off(const struct flash_area *fap)
+{
+    return flash_area_get_size(fap) - BOOT_MAGIC_SZ;
+}
+
+#if (defined(MCUBOOT_DIRECT_XIP) && defined(MCUBOOT_DIRECT_XIP_REVERT)) || \
+    defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE)
+static inline uint32_t
+boot_image_ok_off(const struct flash_area *fap)
+{
+    return ALIGN_DOWN(boot_magic_off(fap) - BOOT_MAX_ALIGN, BOOT_MAX_ALIGN);
+}
+
+static psa_status_t erase_image_ok(const struct flash_area *fap)
+{
+    uint32_t off;
+    uint8_t buf[BOOT_MAX_ALIGN];
+    uint8_t erased_val;
+    uint32_t align;
+
+    /* off of image OK flag is already BOOT_MAX_ALIGN aligned. */
+    off = boot_image_ok_off(fap);
+
+    /* Clear the image ok trailer. */
+    align = flash_area_align(fap);
+    align = ALIGN_UP(BOOT_MAX_ALIGN, align);
+    if (align > BOOT_MAX_ALIGN) {
+        return PSA_ERROR_STORAGE_FAILURE;
+    }
+    erased_val = flash_area_erased_val(fap);
+    memset(buf, erased_val, align);
+    if (flash_area_write(fap, off, buf, align) != 0) {
+        return PSA_ERROR_STORAGE_FAILURE;
+    }
+
+    return PSA_SUCCESS;
+}
+#endif
+
+psa_status_t fwu_bootloader_mark_image_accepted(const psa_fwu_component_t *trials,
+                                                uint8_t number)
 {
     /* As RAM_LOAD and OVERWRITE_ONLY do not support image revert, the image
      * does not need to be confirmed explicitly in these two upgrade strategies.
@@ -470,44 +390,109 @@
      */
 #if (defined(MCUBOOT_DIRECT_XIP) && defined(MCUBOOT_DIRECT_XIP_REVERT)) || \
     defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE)
-    uint8_t mcuboot_image_id = 0;
+    uint8_t trial_index, i;
+    psa_fwu_component_t component;
+    const struct flash_area *fap;
 
-    if (convert_id_from_bl_to_mcuboot(bootloader_image_id,
-                                    &mcuboot_image_id) != 0) {
+    if (trials == NULL) {
         return PSA_ERROR_INVALID_ARGUMENT;
     }
-
-    if (boot_set_confirmed_multi(mcuboot_image_id) != 0) {
-        return PSA_ERROR_GENERIC_ERROR;
+    for (trial_index = 0; trial_index < number; trial_index++) {
+        component = trials[trial_index];
+        if (component >= FWU_COMPONENT_NUMBER) {
+            return PSA_ERROR_INVALID_ARGUMENT;
+        }
+        if (flash_area_open(FLASH_AREA_IMAGE_SECONDARY(component),
+                            &fap) != 0) {
+            return PSA_ERROR_STORAGE_FAILURE;
+        }
+        if (fap == NULL) {
+            return PSA_ERROR_INVALID_ARGUMENT;
+        }
+        mcuboot_ctx[component].fap = fap;
+    }
+    for (trial_index = 0; trial_index < number; trial_index++) {
+        component = trials[trial_index];
+        if (boot_set_confirmed_multi(component) != 0) {
+            for (i = 0; i < trial_index; i++) {
+                if (erase_image_ok(mcuboot_ctx[component].fap) != 0) {
+                    break;
+                }
+            }
+            return PSA_ERROR_STORAGE_FAILURE;
+        }
     }
 #else
-    (void)bootloader_image_id;
+    (void)trials;
+    (void)number;
 #endif
     return PSA_SUCCESS;
 }
 
-psa_status_t fwu_bootloader_abort(bl_image_id_t bootloader_image_id)
+static psa_status_t erase_boot_magic(const struct flash_area *fap)
 {
-    uint8_t mcuboot_image_id = 0;
-    const struct flash_area *fap;
-    uint8_t index;
+    uint32_t off, pad_off;
+    uint8_t magic[BOOT_MAGIC_ALIGN_SIZE];
+    uint8_t erased_val;
 
-    if (convert_id_from_bl_to_mcuboot(bootloader_image_id,
-                                      &mcuboot_image_id) != 0) {
+    off = boot_magic_off(fap);
+    pad_off = ALIGN_DOWN(off, BOOT_MAX_ALIGN);
+    erased_val = flash_area_erased_val(fap);
+    memset(&magic[0], erased_val, sizeof(magic));
+
+    /* Clear the boot magic trailer. */
+    if (flash_area_write(fap, pad_off, &magic[0], BOOT_MAGIC_ALIGN_SIZE)) {
+        return PSA_ERROR_STORAGE_FAILURE;
+    }
+    return PSA_SUCCESS;
+}
+
+/* Reject the staged image. */
+psa_status_t fwu_bootloader_reject_staged_image(psa_fwu_component_t component)
+{
+    if (component >= FWU_COMPONENT_NUMBER) {
         return PSA_ERROR_INVALID_ARGUMENT;
     }
 
     /* The image should already be added into the mcuboot_ctx. */
-    if (get_flash_image_index(mcuboot_image_id, &index)) {
-        fap = mcuboot_ctx[index].fap;
+    if (mcuboot_ctx[component].fap != NULL) {
+        return erase_boot_magic(mcuboot_ctx[component].fap);
+    }
+
+    /* The component is not in FWU process. */
+    return PSA_ERROR_DOES_NOT_EXIST;
+}
+
+/* Reject the running image in trial state. */
+psa_status_t fwu_bootloader_reject_trial_image(psa_fwu_component_t component)
+{
+    if (component >= FWU_COMPONENT_NUMBER) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    /* The image will be reverted if it is not accepted explicitly. */
+    return PSA_SUCCESS_REBOOT;
+}
+
+psa_status_t fwu_bootloader_abort(psa_fwu_component_t component)
+{
+    const struct flash_area *fap;
+
+    if (component >= FWU_COMPONENT_NUMBER) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    /* The image should already be added into the mcuboot_ctx. */
+    if (mcuboot_ctx[component].fap != NULL) {
+        fap = mcuboot_ctx[component].fap;
     } else {
         return PSA_ERROR_INVALID_ARGUMENT;
     }
 
     flash_area_erase(fap, 0, fap->fa_size);
     flash_area_close(fap);
-    mcuboot_ctx[index].fap = NULL;
-    mcuboot_ctx[index].loaded_size = 0;
+    mcuboot_ctx[component].fap = NULL;
+    mcuboot_ctx[component].loaded_size = 0;
     return PSA_SUCCESS;
 }
 
@@ -538,7 +523,7 @@
         }
 
         if (flash_area_read(fap, off, tmpbuf, blk_sz)) {
-            return PSA_ERROR_GENERIC_ERROR;
+            return PSA_ERROR_STORAGE_FAILURE;
         }
         status = psa_hash_update(&handle, tmpbuf, blk_sz);
         if (status != PSA_SUCCESS) {
@@ -551,150 +536,134 @@
     return status;
 }
 
-static psa_status_t get_secondary_image_info(uint8_t image_id,
-                                             psa_image_info_t *info)
+static psa_status_t get_second_image_digest(psa_fwu_component_t component,
+                                            psa_fwu_component_info_t *info)
 {
     const struct flash_area *fap = NULL;
-    struct image_header hdr = {0};
-    uint8_t hash[PSA_FWU_MAX_DIGEST_SIZE] = {0};
+    uint8_t hash[TFM_FWU_MAX_DIGEST_SIZE] = {0};
     size_t hash_size = 0;
     psa_status_t ret = PSA_SUCCESS;
-    uint8_t index;
     size_t data_size;
 
-    if (info == NULL) {
+    if (component >= FWU_COMPONENT_NUMBER) {
         return PSA_ERROR_INVALID_ARGUMENT;
     }
 
-    if ((flash_area_open(FLASH_AREA_IMAGE_SECONDARY(image_id),
+    /* Check if the image is in a FWU process. */
+    if (mcuboot_ctx[component].fap != NULL) {
+        /* Calculate hash on the downloaded data. */
+        data_size = mcuboot_ctx[component].loaded_size;
+    } else {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+    if ((flash_area_open(FLASH_AREA_IMAGE_SECONDARY(component),
                             &fap)) != 0) {
         LOG_ERRFMT("TFM FWU: opening flash failed.\r\n");
-        return PSA_ERROR_GENERIC_ERROR;
+        return PSA_ERROR_STORAGE_FAILURE;
     }
 
-    if (flash_area_read(fap, 0, &hdr, sizeof(hdr)) != 0) {
-        flash_area_close(fap);
-        LOG_ERRFMT("TFM FWU: reading flash failed.\r\n");
-        return PSA_ERROR_GENERIC_ERROR;
-    }
-
-
-    /* Check if the image is in a FWU process. */
-    if (get_flash_image_index(image_id, &index)) {
-
-        /* Calculate hash on the downloaded data. */
-        data_size = mcuboot_ctx[index].loaded_size;
-    } else {
-        /* Check if a valid image exists on the staging area.
-         * If a valid image exists, the FWU partition has no information on the
-         * image size downloaded as the image is copied from the running slot
-         * during the reboot. So in this case when calculating the image hash,
-         * the range starts from the image header till the end of the protected
-         * TLV area.
-         */
-        if (hdr.ih_magic == IMAGE_MAGIC) {
-            info->version.iv_major = hdr.ih_ver.iv_major;
-            info->version.iv_minor = hdr.ih_ver.iv_minor;
-            info->version.iv_revision = hdr.ih_ver.iv_revision;
-            info->version.iv_build_num = hdr.ih_ver.iv_build_num;
-            LOG_ERRFMT("version= %d., %d., %d.,+ %d\n\r",
-                    info->version.iv_major,
-                    info->version.iv_minor,
-                    info->version.iv_revision,
-                    info->version.iv_build_num);
-
-            /* Calculate hash on from the image header to the protected TLV. */
-            data_size = hdr.ih_hdr_size + hdr.ih_img_size +
-                        hdr.ih_protect_tlv_size;
-        } else {
-            /* No image in the staging area. */
-            return PSA_ERROR_DOES_NOT_EXIST;
-        }
-    }
-
-    if (util_img_hash(fap, data_size, hash, (size_t)PSA_FWU_MAX_DIGEST_SIZE,
+    if (util_img_hash(fap, data_size, hash, (size_t)TFM_FWU_MAX_DIGEST_SIZE,
                       &hash_size) == PSA_SUCCESS) {
-        memcpy(info->digest, hash, hash_size);
-        ret = PSA_SUCCESS;
+        memcpy(info->impl.candidate_digest, hash, hash_size);
     } else {
-        ret = PSA_ERROR_GENERIC_ERROR;
+        ret = PSA_ERROR_STORAGE_FAILURE;
     }
 
-    /* The actual image state will be filled in the tfm_fwu_req_mngr.c where
-     * the image state is maintained.
-     */
-    info->state = PSA_IMAGE_UNDEFINED;
     flash_area_close(fap);
     return ret;
 }
 
-psa_status_t fwu_bootloader_get_image_info(bl_image_id_t bootloader_image_id,
-                                  bool active_image,
-                                  psa_image_info_t *info)
+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)
 {
-    struct image_version image_ver = { 0 };
-    uint8_t mcuboot_image_id = 0;
 #if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) && \
     !defined(MCUBOOT_OVERWRITE_ONLY)
-    const struct flash_area *fap = NULL;
     uint8_t image_ok = BOOT_FLAG_UNSET;
 #endif
+    const struct flash_area *fap = NULL;
+    struct image_version image_version;
+    psa_status_t ret = PSA_SUCCESS;
+
     if (info == NULL) {
         return PSA_ERROR_INVALID_ARGUMENT;
     }
 
-    if (convert_id_from_bl_to_mcuboot(bootloader_image_id,
-                                      &mcuboot_image_id) != 0) {
+    if (component >= FWU_COMPONENT_NUMBER) {
         return PSA_ERROR_INVALID_ARGUMENT;
     }
 
-    memset(info, 0, sizeof(psa_image_info_t));
-    memset(info->digest, TFM_IMAGE_INFO_INVALID_DIGEST, sizeof(info->digest));
+    if ((flash_area_open(FLASH_AREA_IMAGE_PRIMARY(component),
+                        &fap)) != 0) {
+        LOG_ERRFMT("TFM FWU: opening flash failed.\r\n");
+        return PSA_ERROR_STORAGE_FAILURE;
+    }
+    info->max_size = fap->fa_size;
+    info->location = fap->fa_id;
+    info->flags = PSA_FWU_FLAG_VOLATILE_STAGING;
 
-    if (active_image) {
-    /* As DIRECT_XIP, RAM_LOAD and OVERWRITE_ONLY do not support image revert.
-     * So the running image is in INSTALLED state in these three upgrade
-     * strategies. In the SWAP case, the image_ok flag should be read to check
-     * whether the running image has been confirmed as a pernament image.
-     */
-#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) && \
-    !defined(MCUBOOT_OVERWRITE_ONLY)
-        if ((flash_area_open(FLASH_AREA_IMAGE_PRIMARY(mcuboot_image_id),
-                            &fap)) != 0) {
-            LOG_ERRFMT("TFM FWU: opening flash failed.\r\n");
-            return PSA_ERROR_GENERIC_ERROR;
-        }
-
+    if (query_state) {
+        /* As DIRECT_XIP, RAM_LOAD and OVERWRITE_ONLY do not support image revert.
+         * So the running image is in INSTALLED state in these three upgrade
+         * strategies. In the SWAP case, the image_ok flag should be read to check
+         * whether the running image has been confirmed as a pernament image.
+         */
+    #if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) && \
+        !defined(MCUBOOT_OVERWRITE_ONLY)
         /* Get value of image-ok flag of the image to check whether application
          * itself is already confirmed.
          */
         if (boot_read_image_ok(fap, &image_ok) != 0) {
-            return PSA_ERROR_GENERIC_ERROR;
+            ret = PSA_ERROR_STORAGE_FAILURE;
+            goto close_return;
         }
         if (image_ok == BOOT_FLAG_SET) {
-            info->state = PSA_IMAGE_INSTALLED;
+            info->state = PSA_FWU_READY;
         } else {
-            info->state = PSA_IMAGE_PENDING_INSTALL;
+            info->state = PSA_FWU_TRIAL;
         }
-#else
-        info->state = PSA_IMAGE_INSTALLED;
-#endif
-        if (get_running_image_version(mcuboot_image_id,
-                                      &image_ver) == PSA_SUCCESS) {
-            info->version.iv_major = image_ver.iv_major;
-            info->version.iv_minor = image_ver.iv_minor;
-            info->version.iv_revision = image_ver.iv_revision;
-            info->version.iv_build_num = image_ver.iv_build_num;
-
-            /* The image in the primary slot is verified by the bootloader.
-             * The image digest in the primary slot should not be exposed to
-             * nonsecure.
-             */
-            return PSA_SUCCESS;
-        } else {
-            return PSA_ERROR_GENERIC_ERROR;
-        }
-    } else {
-        return get_secondary_image_info(mcuboot_image_id, info);
+    #else
+        info->state = PSA_FWU_READY;
+    #endif
     }
+    if (get_active_image_version(component,
+                                    &image_version) == PSA_SUCCESS) {
+        info->version.major = image_version.iv_major;
+        info->version.minor = image_version.iv_minor;
+        info->version.patch = image_version.iv_revision;
+        info->version.build = image_version.iv_build_num;
+    } else {
+        ret = PSA_ERROR_STORAGE_FAILURE;
+        goto close_return;
+    }
+    if (query_impl_info) {
+        ret = get_second_image_digest(component, info);
+    }
+
+close_return:
+    flash_area_close(fap);
+    return ret;
+}
+
+psa_status_t fwu_bootloader_clean_component(psa_fwu_component_t component)
+{
+    const struct flash_area *fap = NULL;
+
+    if (component >= FWU_COMPONENT_NUMBER) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    /* Check if the image is in a FWU process. */
+    if (mcuboot_ctx[component].fap != NULL) {
+        fap = mcuboot_ctx[component].fap;
+        if (flash_area_erase(fap, 0, fap->fa_size) != 0) {
+            return PSA_ERROR_STORAGE_FAILURE;
+        }
+        mcuboot_ctx[component].fap = NULL;
+    } else {
+        return PSA_ERROR_DOES_NOT_EXIST;
+    }
+
+    return PSA_SUCCESS;
 }
diff --git a/secure_fw/partitions/firmware_update/bootloader/tfm_bootloader_fwu_abstraction.h b/secure_fw/partitions/firmware_update/bootloader/tfm_bootloader_fwu_abstraction.h
index 002fb74..571f61b 100644
--- a/secure_fw/partitions/firmware_update/bootloader/tfm_bootloader_fwu_abstraction.h
+++ b/secure_fw/partitions/firmware_update/bootloader/tfm_bootloader_fwu_abstraction.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -15,8 +15,6 @@
 extern "C" {
 #endif
 
-typedef uint8_t bl_image_id_t;
-
 /**
  * Bootloader related initialization for firmware update, such as reading
  * some necessary shared data from the memory if needed.
@@ -27,37 +25,45 @@
 psa_status_t fwu_bootloader_init(void);
 
 /**
- * \brief Initialize the staging area of the image with given ID.
+ * \brief Initialize the staging area of the component.
  *
- * Prepare the staging area of the image with given ID for image download.
+ * 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] bootloader_image_id The identifier of the target image in
- *                                bootloader
+ * \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_GENERIC_ERROR      A fatal error occurred
+ *         PSA_ERROR_INSUFFICIENT_MEMORY
+ *         PSA_ERROR_INSUFFICIENT_STORAGE
+ *         PSA_ERROR_COMMUNICATION_FAILURE
+ *         PSA_ERROR_STORAGE_FAILURE
  *
  */
-psa_status_t fwu_bootloader_staging_area_init(bl_image_id_t
-                                              bootloader_image_id);
+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 device.
+ * \brief Load the image into the target component.
  *
- * Prepare the staging area of the image with given ID 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.
+ * The component is in WRITING state. Write the image data into the target
+ * component.
  *
- * \param[in] bootloader_image_id The identifier of the target image in
- *                                bootloader
- * \param[in] block_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.
+ * \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
@@ -68,25 +74,22 @@
  *         PSA_ERROR_GENERIC_ERROR         A fatal error occurred
  *
  */
-psa_status_t fwu_bootloader_load_image(bl_image_id_t bootloader_image_id,
-                                       size_t block_offset,
+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.
  *
- * Check the authenticity and integrity of the 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.
  *
- * 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] bootloader_image_id The identifier of the target image in
- *                                bootloader
- * \param[out] dependency         Bootloader image ID of dependency if needed
- * \param[out] dependency_version Bootloader image version of dependency if
- *                                needed
+ * \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
@@ -102,54 +105,84 @@
  *                                       timestamp and it has expired, then
  *                                       this error is also returned.
  */
-psa_status_t fwu_bootloader_install_image(bl_image_id_t bootloader_image_id,
-                                          bl_image_id_t *dependency,
-                                      psa_image_version_t *dependency_version);
+psa_status_t fwu_bootloader_install_image(const psa_fwu_component_t *candidates,
+                                          uint8_t number);
 
 /**
- * \brief Marks the image in the primary slot as confirmed.
+ * \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_GENERIC_ERROR       A fatal error occurred
+ *         PSA_ERROR_INSUFFICIENT_MEMORY
+ *         PSA_ERROR_INSUFFICIENT_STORAGE
+ *         PSA_ERROR_COMMUNICATION_FAILURE
+ *         PSA_ERROR_STORAGE_FAILURE
  */
-psa_status_t fwu_bootloader_mark_image_accepted(
-                                             bl_image_id_t bootloader_image_id);
+psa_status_t fwu_bootloader_mark_image_accepted(const psa_fwu_component_t *trials,
+                                                uint8_t number);
 
 /**
- * \brief Abort the current image download process.
+ * \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_GENERIC_ERROR       A fatal error occurred
+ *         PSA_ERROR_STORAGE_FAILURE
  */
-psa_status_t fwu_bootloader_abort(bl_image_id_t bootloader_image_id);
+psa_status_t fwu_bootloader_clean_component(psa_fwu_component_t component);
 
 /**
  * \brief Get the image information.
  *
- * Get the image information of the given bootloader_image_id in staging area
+ * Get the image information of the given component in staging area
  * or the running area.
  *
- * \param[in] bootloader_image_id  The identifier of the target image in
- *                                 bootloader
- * \param[in] active_image         Indicates image location
- *                                 True: the running image.
- *                                 False: the image in the passive(or staging)
- *                                 slot.
- * \param[out] info                Buffer containing return the image
- *                                 information
- *
+ * \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(bl_image_id_t bootloader_image_id,
-                                           bool active_image,
-                                           psa_image_info_t *info);
+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
diff --git a/secure_fw/partitions/firmware_update/tfm_fwu.c b/secure_fw/partitions/firmware_update/tfm_fwu.c
deleted file mode 100644
index 025d241..0000000
--- a/secure_fw/partitions/firmware_update/tfm_fwu.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- */
-
-#include <stdint.h>
-#include "tfm_sp_log.h"
-#include "tfm_platform_api.h"
-#include "tfm_fwu.h"
-
-psa_status_t tfm_internal_fwu_initialize(psa_image_id_t image_id)
-{
-    uint8_t image_type = (uint8_t)FWU_IMAGE_ID_GET_TYPE(image_id);
-    uint8_t slot_id = (uint8_t)FWU_IMAGE_ID_GET_SLOT(image_id);
-
-    /* Check the image slot, the target should be the staging slot. */
-    if (slot_id != FWU_IMAGE_ID_SLOT_STAGE) {
-        LOG_ERRFMT("TFM FWU: invalid slot_id: %d", slot_id);
-        return PSA_ERROR_INVALID_ARGUMENT;
-    }
-
-    return fwu_bootloader_staging_area_init(image_type);
-}
-
-psa_status_t tfm_internal_fwu_write(psa_image_id_t image_id,
-                           size_t block_offset,
-                           const void *block,
-                           size_t block_size)
-{
-    uint8_t image_type = (uint8_t)FWU_IMAGE_ID_GET_TYPE(image_id);
-    uint8_t slot_id = (uint8_t)FWU_IMAGE_ID_GET_SLOT(image_id);
-
-    if ((block == NULL) || (slot_id != FWU_IMAGE_ID_SLOT_STAGE)) {
-        return PSA_ERROR_INVALID_ARGUMENT;
-    }
-
-    return fwu_bootloader_load_image(image_type,
-                                     block_offset,
-                                     block,
-                                     block_size);
-}
-
-psa_status_t tfm_internal_fwu_install(psa_image_id_t image_id,
-                                      psa_image_id_t *dependency,
-                                      psa_image_version_t *dependency_version)
-{
-    uint8_t image_type = (uint8_t)FWU_IMAGE_ID_GET_TYPE(image_id);
-    uint8_t slot_id = (uint8_t)FWU_IMAGE_ID_GET_SLOT(image_id);
-    bl_image_id_t dependency_bl;
-    psa_image_version_t version;
-    psa_status_t result;
-
-    /* Check the image slot, the target should be the staging slot. */
-    if (slot_id != FWU_IMAGE_ID_SLOT_STAGE) {
-        LOG_ERRFMT("TFM FWU: invalid slot_id: %d", slot_id);
-        return PSA_ERROR_INVALID_ARGUMENT;
-    }
-
-    result = fwu_bootloader_install_image(image_type,
-                                          &dependency_bl,
-                                          &version);
-    if (result == PSA_ERROR_DEPENDENCY_NEEDED) {
-        if (dependency == NULL || dependency_version == NULL) {
-            return PSA_ERROR_INVALID_ARGUMENT;
-        }
-
-        *dependency = (psa_image_id_t)FWU_CALCULATE_IMAGE_ID(FWU_IMAGE_ID_SLOT_STAGE,
-                                                             dependency_bl,
-                                                             0);
-        *dependency_version = version;
-    }
-
-    return result;
-}
-
-psa_status_t tfm_internal_fwu_abort(psa_image_id_t image_id)
-{
-    uint8_t image_type = (uint8_t)FWU_IMAGE_ID_GET_TYPE(image_id);
-    uint8_t slot_id = (uint8_t)FWU_IMAGE_ID_GET_SLOT(image_id);
-
-    if (slot_id != FWU_IMAGE_ID_SLOT_STAGE) {
-        return PSA_ERROR_INVALID_ARGUMENT;
-    }
-
-    return fwu_bootloader_abort(image_type);
-}
-
-/* The image version of the given image. */
-psa_status_t tfm_internal_fwu_query(psa_image_id_t image_id,
-                           psa_image_info_t *info)
-{
-    uint8_t image_type = (uint8_t)FWU_IMAGE_ID_GET_TYPE(image_id);
-    uint8_t slot_id = (uint8_t)FWU_IMAGE_ID_GET_SLOT(image_id);
-    bool active_image = 0;
-
-    if (slot_id == FWU_IMAGE_ID_SLOT_STAGE) {
-        active_image = false;
-    } else if (slot_id == FWU_IMAGE_ID_SLOT_ACTIVE) {
-        active_image = true;
-    } else {
-        LOG_ERRFMT("TFM FWU: invalid slot_id: %d", slot_id);
-        return PSA_ERROR_INVALID_ARGUMENT;
-    }
-
-    return fwu_bootloader_get_image_info(image_type, active_image, info);
-}
-
-void tfm_internal_fwu_request_reboot(void)
-{
-    tfm_platform_system_reset();
-}
-
-psa_status_t tfm_internal_fwu_accept(psa_image_id_t image_id)
-{
-    uint8_t image_type = (uint8_t)FWU_IMAGE_ID_GET_TYPE(image_id);
-
-    return fwu_bootloader_mark_image_accepted(image_type);
-}
diff --git a/secure_fw/partitions/firmware_update/tfm_fwu.h b/secure_fw/partitions/firmware_update/tfm_fwu.h
deleted file mode 100644
index ec64d9a..0000000
--- a/secure_fw/partitions/firmware_update/tfm_fwu.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- */
-
-#ifndef __TFM_FWU_H__
-#define __TFM_FWU_H__
-
-#include <stddef.h>
-
-#include "psa/update.h"
-#include "tfm_bootloader_fwu_abstraction.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Initialization for starting a firmware update with image_id.
- */
-psa_status_t tfm_internal_fwu_initialize(psa_image_id_t image_id);
-
-psa_status_t tfm_internal_fwu_write(psa_image_id_t image_id,
-                                    size_t block_offset,
-                                    const void *block,
-                                    size_t block_size);
-
-/*
- * Starts the installation of an image with image_id. Check the authenticity
- * and integrity of the image. Error code PSA_SUCCESS_REBOOT is returned if a
- * reboot is needed to complete the check.
- */
-psa_status_t tfm_internal_fwu_install(psa_image_id_t image_id,
-                                      psa_image_id_t *dependency_uuid,
-                                      psa_image_version_t *dependency_version);
-
-/*
- * Abort the firmware update process.
- */
-psa_status_t tfm_internal_fwu_abort(psa_image_id_t image_id);
-
-/*
- * Get the image information of the given image_id in staging area
- * or the running area.
- */
-psa_status_t tfm_internal_fwu_query(psa_image_id_t image_id,
-                                    psa_image_info_t *info);
-
-/*
- * Request a reboot.
- */
-void tfm_internal_fwu_request_reboot(void);
-
-/*
- * Marks the image in the primary slot as confirmed.
- */
-psa_status_t tfm_internal_fwu_accept(psa_image_id_t image_id);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __TFM_FWU_H__ */
diff --git a/secure_fw/partitions/firmware_update/tfm_fwu_req_mngr.c b/secure_fw/partitions/firmware_update/tfm_fwu_req_mngr.c
index 3abc39d..b57cdff 100644
--- a/secure_fw/partitions/firmware_update/tfm_fwu_req_mngr.c
+++ b/secure_fw/partitions/firmware_update/tfm_fwu_req_mngr.c
@@ -8,314 +8,526 @@
 #include <stdint.h>
 #include <stdbool.h>
 #include <string.h>
-#include "tfm_fwu_req_mngr.h"
-#include "tfm_fwu.h"
+#include "tfm_platform_api.h"
+#include "tfm_bootloader_fwu_abstraction.h"
 #include "psa/update.h"
 #include "service_api.h"
 #include "tfm_api.h"
-
 #include "psa/service.h"
 #include "psa_manifest/tfm_firmware_update.h"
+#include "compiler_ext_defs.h"
+
+#define COMPONENTS_ITER(x)  \
+    for ((x) = 0; (x) < (FWU_COMPONENT_NUMBER); (x)++)
 
 typedef struct tfm_fwu_ctx_s {
-    psa_image_id_t image_id;
-    uint8_t image_state;
+    psa_status_t error;
+    uint8_t component_state;
     bool in_use;
 } tfm_fwu_ctx_t;
 
 /**
  * \brief The context of FWU service.
  */
-static tfm_fwu_ctx_t fwu_ctx[TFM_FWU_MAX_IMAGES];
+static tfm_fwu_ctx_t fwu_ctx[FWU_COMPONENT_NUMBER];
 
 #if PSA_FRAMEWORK_HAS_MM_IOVEC != 1
 #ifndef TFM_FWU_BUF_SIZE
-#define TFM_FWU_BUF_SIZE PSA_FWU_MAX_BLOCK_SIZE
+#define TFM_FWU_BUF_SIZE PSA_FWU_MAX_WRITE_SIZE
 #endif
-static uint8_t data_block[TFM_FWU_BUF_SIZE];
+static uint8_t block[TFM_FWU_BUF_SIZE] __aligned(4);
 #endif
-/**
- * \brief Check if the image is in FWU process, return the index if it is.
- */
-static bool get_image_index(psa_image_id_t image_id, uint8_t *index)
-{
-    if (!index) {
-        return false;
-    }
 
-    for (uint8_t i = 0; i < TFM_FWU_MAX_IMAGES; i++) {
-        if (fwu_ctx[i].in_use && (fwu_ctx[i].image_id == image_id)) {
-            *index = i;
-            return true;
-        }
-    }
-    return false;
-}
-
-/**
- * \brief The the next free index in fwu_ctx.
- */
-static bool get_next_free_index(uint8_t *index)
+static psa_status_t tfm_fwu_start(const psa_msg_t *msg)
 {
-    for (uint8_t i = 0; i < TFM_FWU_MAX_IMAGES; i++) {
-        if (!fwu_ctx[i].in_use) {
-            *index = i;
-            return true;
-        }
-    }
-    return false;
-}
-
-static psa_status_t tfm_fwu_write_req(const psa_msg_t *msg)
-{
-    psa_image_id_t image_id;
-    size_t block_offset;
-    size_t data_length, num;
-    psa_status_t status = PSA_SUCCESS;
-    uint8_t image_index;
+    psa_fwu_component_t component;
 #if PSA_FRAMEWORK_HAS_MM_IOVEC == 1
-    uint8_t *data_block;
+    uint8_t *manifest = NULL;
 #else
-    size_t write_size;
+    uint8_t manifest[TFM_CONFIG_FWU_MAX_MANIFEST_SIZE];
+#endif
+    size_t manifest_size;
+    psa_status_t status;
+    psa_fwu_component_info_t info;
+
+    /* Check input parameters. */
+    if (msg->in_size[0] != sizeof(component)) {
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+    if (msg->in_size[1] > sizeof(manifest)) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+    psa_read(msg->handle, 0, &component, sizeof(component));
+
+    if (component >= FWU_COMPONENT_NUMBER) {
+        return PSA_ERROR_DOES_NOT_EXIST;
+    }
+    manifest_size = msg->in_size[1];
+    if (manifest_size > 0) {
+#if PSA_FRAMEWORK_HAS_MM_IOVEC == 1
+        manifest = (uint8_t *)psa_map_invec(msg->handle, 1);
+#else
+        psa_read(msg->handle, 1, manifest, manifest_size);
+#endif
+    }
+
+    /* The component is in FWU process. */
+    if (fwu_ctx[component].in_use) {
+        if (fwu_ctx[component].component_state != PSA_FWU_READY) {
+            return PSA_ERROR_BAD_STATE;
+        }
+    } else {
+        /* Query the state of the component. */
+        status = fwu_bootloader_get_image_info(component, true, false, &info);
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
+        if (info.state != PSA_FWU_READY) {
+            return PSA_ERROR_BAD_STATE;
+        }
+
+        /* The component is not in FWU process. Initialize the ctx for this component. */
+        status = fwu_bootloader_staging_area_init(component,
+                                                  (const void *)&manifest,
+                                                  manifest_size);
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
+        fwu_ctx[component].in_use = true;
+        fwu_ctx[component].component_state = PSA_FWU_WRITING;
+    }
+    return PSA_SUCCESS;
+}
+
+static psa_status_t tfm_fwu_write(const psa_msg_t *msg)
+{
+    psa_fwu_component_t component;
+    size_t image_offset;
+    size_t block_size;
+    psa_status_t status = PSA_SUCCESS;
+#if PSA_FRAMEWORK_HAS_MM_IOVEC == 1
+    uint8_t *block;
+#else
+    size_t write_size, num;
 #endif
 
     /* Check input parameters. */
-    if (msg->in_size[2] > PSA_FWU_MAX_BLOCK_SIZE) {
+    if (msg->in_size[2] > PSA_FWU_MAX_WRITE_SIZE) {
         return PSA_ERROR_INVALID_ARGUMENT;
     }
+    block_size = msg->in_size[2];
 
-    if (msg->in_size[0] != sizeof(image_id) ||
-        msg->in_size[1] != sizeof(block_offset)) {
+    if (msg->in_size[0] != sizeof(component) ||
+        msg->in_size[1] != sizeof(image_offset)) {
         return PSA_ERROR_PROGRAMMER_ERROR;
     }
 
-    num = psa_read(msg->handle, 0, &image_id, sizeof(image_id));
-    if (num != sizeof(image_id)) {
-        return PSA_ERROR_PROGRAMMER_ERROR;
+    psa_read(msg->handle, 0, &component, sizeof(component));
+    if (component >= FWU_COMPONENT_NUMBER) {
+        return PSA_ERROR_DOES_NOT_EXIST;
     }
 
-    num = psa_read(msg->handle, 1, &block_offset, sizeof(block_offset));
-    if (num != sizeof(block_offset)) {
-        return PSA_ERROR_PROGRAMMER_ERROR;
+    psa_read(msg->handle, 1, &image_offset, sizeof(image_offset));
+
+    /* Check the component state. */
+    if (!fwu_ctx[component].in_use ||
+        fwu_ctx[component].component_state != PSA_FWU_WRITING) {
+        return PSA_ERROR_BAD_STATE;
     }
-    if (get_image_index(image_id, &image_index)) {
-        /* The image is in FWU process. */
-        if ((fwu_ctx[image_index].image_state != PSA_IMAGE_CANDIDATE) &&
-            (fwu_ctx[image_index].image_state != PSA_IMAGE_REJECTED)) {
-            return PSA_ERROR_CURRENTLY_INSTALLING;
-        }
-    } else {
-        /* The image is not in FWU process. */
-        if (get_next_free_index(&image_index)) {
-            /* Get a free index. Start the FWU process of this image. */
-            status = tfm_internal_fwu_initialize(image_id);
-            if (status != PSA_SUCCESS) {
-                return status;
-            }
-            fwu_ctx[image_index].in_use = true;
-            fwu_ctx[image_index].image_id = image_id;
-            fwu_ctx[image_index].image_state = PSA_IMAGE_CANDIDATE;
-        } else {
-            /* No more resource can be used. */
-            return PSA_ERROR_INSUFFICIENT_MEMORY;
-        }
-    }
-    data_length = msg->in_size[2];
 #if PSA_FRAMEWORK_HAS_MM_IOVEC == 1
-    data_block = (uint8_t *)psa_map_invec(msg->handle, 2);
-    if (data_length > 0) {
-        status = tfm_internal_fwu_write(image_id,
-                                        block_offset,
-                                        data_block,
-                                        data_length);
+    if (block_size > 0) {
+        block = (uint8_t *)psa_map_invec(msg->handle, 2);
+        status = fwu_bootloader_load_image(component,
+                                           image_offset,
+                                           block,
+                                           block_size);
     }
 #else
-    memset(data_block, 0, sizeof(data_block));
-    while (data_length > 0) {
-        write_size = sizeof(data_block) <= data_length ?
-                     sizeof(data_block) : data_length;
-        num = psa_read(msg->handle, 2, data_block, write_size);
+    while (block_size > 0) {
+        write_size = sizeof(block) <= block_size ?
+                     sizeof(block) : block_size;
+        num = psa_read(msg->handle, 2, block, write_size);
         if (num != write_size) {
             return PSA_ERROR_PROGRAMMER_ERROR;
         }
 
-        status = tfm_internal_fwu_write(image_id,
-                                        block_offset,
-                                        data_block,
-                                        write_size);
+        status = fwu_bootloader_load_image(component,
+                                           image_offset,
+                                           block,
+                                           write_size);
         if (status != PSA_SUCCESS) {
             return status;
         }
-        data_length -= write_size;
-        block_offset += write_size;
+        block_size -= write_size;
+        image_offset += write_size;
     }
 #endif
+    return status;
+}
+
+static psa_status_t tfm_fwu_finish(const psa_msg_t *msg)
+{
+    psa_fwu_component_t component;
+
+    /* Check input parameters. */
+    if (msg->in_size[0] != sizeof(component)) {
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+    psa_read(msg->handle, 0, &component, sizeof(component));
+    if (component >= FWU_COMPONENT_NUMBER) {
+        return PSA_ERROR_DOES_NOT_EXIST;
+    }
+
+    /* Check the component state. */
+    if (!fwu_ctx[component].in_use ||
+        fwu_ctx[component].component_state != PSA_FWU_WRITING) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    /* Validity, authenticity and integrity of the image is deferred to system
+     * reboot.
+     */
+    fwu_ctx[component].component_state = PSA_FWU_CANDIDATE;
     return PSA_SUCCESS;
 }
 
-static psa_status_t tfm_fwu_install_req(const psa_msg_t *msg)
+static psa_status_t tfm_fwu_install(void)
 {
-    psa_image_id_t image_id;
-    psa_image_id_t dependency_id;
-    psa_image_version_t dependency_version;
-    size_t num;
+    psa_fwu_component_t component = 0;
     psa_status_t status;
-    uint8_t image_index;
+    uint8_t candidate_number = 0, index;
+    psa_fwu_component_info_t info;
+    psa_fwu_component_t candidates[FWU_COMPONENT_NUMBER];
 
-    /* Check input parameters. */
-    if (msg->in_size[0] != sizeof(image_id) ||
-        msg->out_size[0] != sizeof(dependency_id) ||
-        msg->out_size[1] != sizeof(dependency_version)) {
-        return PSA_ERROR_PROGRAMMER_ERROR;
-    }
-
-    num = psa_read(msg->handle, 0, &image_id, sizeof(image_id));
-    if (num != sizeof(image_id)) {
-        return PSA_ERROR_PROGRAMMER_ERROR;
-    }
-
-    if ((!get_image_index(image_id, &image_index)) ||
-       (fwu_ctx[image_index].image_state != PSA_IMAGE_CANDIDATE)) {
-        return PSA_ERROR_INVALID_ARGUMENT;
-    } else {
-        status = tfm_internal_fwu_install(image_id,
-                                          &dependency_id,
-                                          &dependency_version);
-        if (status == PSA_SUCCESS) {
-            fwu_ctx[image_index].image_state = PSA_IMAGE_INSTALLED;
-
-            /* The image has been successfully installed, free the index. */
-            fwu_ctx[image_index].in_use = false;
-        } else if (status == PSA_SUCCESS_REBOOT) {
-            fwu_ctx[image_index].image_state = PSA_IMAGE_REBOOT_NEEDED;
-        } else if (status == PSA_ERROR_DEPENDENCY_NEEDED) {
-            psa_write(msg->handle, 0, &dependency_id, sizeof(dependency_id));
-            psa_write(msg->handle, 1, &dependency_version,
-                      sizeof(dependency_version));
+    /* If at least one component is in STAGED, TRIAL or REJECTED state results
+     * PSA_ERROR_BAD_STATE error.
+     */
+    COMPONENTS_ITER(component) {
+        if (fwu_ctx[component].in_use) {
+            if (fwu_ctx[component].component_state == PSA_FWU_STAGED ||
+                fwu_ctx[component].component_state == PSA_FWU_REJECTED) {
+                return PSA_ERROR_BAD_STATE;
+            } else if (fwu_ctx[component].component_state == PSA_FWU_CANDIDATE) {
+                candidates[candidate_number++] = component;
+            }
         } else {
-            fwu_ctx[image_index].image_state = PSA_IMAGE_REJECTED;
-        }
-
-        return status;
-    }
-}
-
-static psa_status_t tfm_fwu_query_req(const psa_msg_t *msg)
-{
-    psa_image_id_t image_id;
-    size_t num;
-    psa_image_info_t info;
-    psa_status_t result;
-    uint8_t image_index;
-
-    /* Check input parameters. */
-    if (msg->in_size[0] != sizeof(image_id)) {
-        return PSA_ERROR_PROGRAMMER_ERROR;
-    }
-    num = psa_read(msg->handle, 0, &image_id, sizeof(image_id));
-    if (num != sizeof(image_id)) {
-        return PSA_ERROR_PROGRAMMER_ERROR;
-    }
-    result = tfm_internal_fwu_query(image_id, &info);
-    if (result == PSA_SUCCESS) {
-        /* Fill the image state if the query image is not the running image. */
-        if (info.state == PSA_IMAGE_UNDEFINED) {
-            if (get_image_index(image_id, &image_index)) {
-                /* The queried image is the currently updating image. */
-                info.state = fwu_ctx[image_index].image_state;
+            status = fwu_bootloader_get_image_info(component, true, false, &info);
+            if (status != PSA_SUCCESS) {
+                return status;
+            }
+            if (info.state == PSA_FWU_TRIAL) {
+                return PSA_ERROR_BAD_STATE;
             }
         }
+    }
 
+    /* No components in CANDIDATE state. */
+    if (candidate_number == 0) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    status = fwu_bootloader_install_image(candidates,
+                                          candidate_number);
+
+    if (status == PSA_ERROR_DEPENDENCY_NEEDED) {
+        /* No need to update the CANDIDATE components' state in this case. */
+        return status;
+    }
+
+    /* Update the CANDIDATE components' state and error context accordingly. */
+    for (index = 0; index < candidate_number; index++) {
+        component = candidates[index];
+        if (status == PSA_SUCCESS) {
+            /* Check TRIAL state is supported or not. */
+#ifdef FWU_SUPPORT_TRIAL_STATE
+            fwu_ctx[component].component_state = PSA_FWU_TRIAL;
+#else
+            fwu_ctx[component].component_state = PSA_FWU_UPDATED;
+#endif
+        } else if (status != PSA_SUCCESS_REBOOT && status != PSA_SUCCESS_RESTART) {
+            /* Switch to FAILED state on other errors. */
+            fwu_ctx[component].component_state = PSA_FWU_FAILED;
+            fwu_ctx[component].error = status;
+        } else {
+            fwu_ctx[component].component_state = PSA_FWU_STAGED;
+        }
+    }
+    return status;
+}
+
+static psa_status_t tfm_fwu_query(const psa_msg_t *msg)
+{
+    psa_fwu_component_t component = { 0 };
+    psa_fwu_component_info_t info;
+    psa_status_t result;
+    bool query_impl_info = false, query_state = true;
+
+    /* Check input parameters. */
+    if (msg->in_size[0] != sizeof(component) ||
+        msg->out_size[0] != sizeof(psa_fwu_component_info_t)) {
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+    psa_read(msg->handle, 0, &component, sizeof(component));
+    if (component >= FWU_COMPONENT_NUMBER) {
+        return PSA_ERROR_DOES_NOT_EXIST;
+    }
+
+    if (fwu_ctx[component].in_use) {
+        info.state = fwu_ctx[component].component_state;
+        query_state = false;
+        /* The psa_fwu_impl_info_t contains the digest of second image when
+         * store state is CANDIDATE. Calculate the digest when store state is
+         * CANDIDATE.
+         */
+        if (fwu_ctx[component].component_state == PSA_FWU_CANDIDATE) {
+            query_impl_info = true;
+        } else if (fwu_ctx[component].component_state == PSA_FWU_REJECTED ||
+                   fwu_ctx[component].component_state == PSA_FWU_FAILED) {
+            info.error = fwu_ctx[component].error;
+        }
+    }
+
+    /* If there is no active ctx, the possible component states are READY and
+     * TRIAL.
+     */
+    result = fwu_bootloader_get_image_info(component, query_state,
+                                           query_impl_info, &info);
+    if (result == PSA_SUCCESS) {
         psa_write(msg->handle, 0, &info, sizeof(info));
     }
 
     return result;
 }
 
-static psa_status_t tfm_fwu_request_reboot_req(void)
+static psa_status_t tfm_fwu_request_reboot(void)
 {
-    tfm_internal_fwu_request_reboot();
+    tfm_platform_system_reset();
 
     return PSA_SUCCESS;
 }
 
-static psa_status_t tfm_fwu_accept_req(const psa_msg_t *msg)
+static psa_status_t tfm_fwu_accept(void)
 {
-    psa_image_id_t image_id;
+#ifdef FWU_SUPPORT_TRIAL_STATE
+    psa_fwu_component_t component = 0;
+    psa_status_t status = PSA_ERROR_BAD_STATE;
+    psa_fwu_component_info_t info;
+    psa_fwu_component_t trials[FWU_COMPONENT_NUMBER];
+    uint8_t trials_number = 0, index;
+
+    COMPONENTS_ITER(component) {
+        if (fwu_ctx[component].in_use) {
+            if (fwu_ctx[component].component_state == PSA_FWU_TRIAL) {
+                trials[trials_number++] = component;
+            }
+        } else {
+            status = fwu_bootloader_get_image_info(component, true, false, &info);
+            if (status != PSA_SUCCESS) {
+                return status;
+            }
+            if (info.state == PSA_FWU_TRIAL) {
+                trials[trials_number++] = component;
+                fwu_ctx[component].in_use = true;
+                fwu_ctx[component].component_state = PSA_FWU_TRIAL;
+            }
+        }
+    }
+
+    if (trials_number == 0) {
+        return PSA_ERROR_BAD_STATE;
+    }
+    status = fwu_bootloader_mark_image_accepted(trials, trials_number);
+    if (status != PSA_SUCCESS) {
+        /* Rebooting the system results in the image being automatically rejected.
+         * Keep the component in TRIAL state.
+         */
+        return status;
+    }
+
+    for (index = 0; index < trials_number; index++) {
+        component = trials[index];
+        fwu_ctx[component].component_state = PSA_FWU_UPDATED;
+    }
+    return status;
+#else
+    return PSA_ERROR_NOT_SUPPORTED;
+#endif
+}
+
+psa_status_t tfm_fwu_reject(const psa_msg_t *msg)
+{
+    psa_fwu_component_t component = 0;
+    psa_status_t status = PSA_SUCCESS, error;
+    psa_fwu_component_info_t info;
+    bool staged_trial_component_found = false, in_trial_state = false;
     size_t num;
 
     /* Check input parameters. */
-    if (msg->in_size[0] != sizeof(image_id)) {
+    if (msg->in_size[0] != sizeof(error)) {
         return PSA_ERROR_PROGRAMMER_ERROR;
     }
-    num = psa_read(msg->handle, 0, &image_id, sizeof(image_id));
-    if (num != sizeof(image_id)) {
+    num = psa_read(msg->handle, 0, &error, sizeof(error));
+    if (num != sizeof(error)) {
         return PSA_ERROR_PROGRAMMER_ERROR;
     }
 
-    /* This operation set the running image to INSTALLED state, the images
-     * in the staging area does not impact this operation.
-     */
-    return tfm_internal_fwu_accept(image_id);
-}
-
-static psa_status_t tfm_fwu_abort_req(const psa_msg_t *msg)
-{
-    psa_image_id_t image_id;
-    size_t num;
-    uint8_t image_index;
-    psa_status_t status;
-
-    if (msg->in_size[0] != sizeof(image_id)) {
-        return PSA_ERROR_PROGRAMMER_ERROR;
-    }
-
-    num = psa_read(msg->handle, 0, &image_id, sizeof(image_id));
-    if (num != sizeof(image_id)) {
-        return PSA_ERROR_PROGRAMMER_ERROR;
-    }
-
-    if (get_image_index(image_id, &image_index)) {
-        /* The image is in FWU process. */
-        if ((fwu_ctx[image_index].image_state == PSA_IMAGE_CANDIDATE) ||
-           (fwu_ctx[image_index].image_state == PSA_IMAGE_REBOOT_NEEDED) ||
-           (fwu_ctx[image_index].image_state == PSA_IMAGE_REJECTED)) {
-            status = tfm_internal_fwu_abort(image_id);
+    COMPONENTS_ITER(component) {
+        in_trial_state = false;
+        if (fwu_ctx[component].in_use) {
+            if (fwu_ctx[component].component_state == PSA_FWU_STAGED) {
+                /* If the installation state is STAGED, then the state of
+                 * affected components changes to FAILED.
+                 */
+                fwu_ctx[component].component_state = PSA_FWU_FAILED;
+                fwu_ctx[component].error = error;
+                staged_trial_component_found = true;
+                /* Reject the staged image. */
+                status = fwu_bootloader_reject_staged_image(component);
+                if (status != PSA_SUCCESS) {
+                    return status;
+                }
+            } else if (fwu_ctx[component].component_state == PSA_FWU_TRIAL) {
+                staged_trial_component_found = true;
+                in_trial_state = true;
+            }
+        } else {
+            status = fwu_bootloader_get_image_info(component, true, false, &info);
             if (status != PSA_SUCCESS) {
                 return status;
             }
 
-            fwu_ctx[image_index].image_state = PSA_IMAGE_UNDEFINED;
-            fwu_ctx[image_index].in_use = false;
-            fwu_ctx[image_index].image_id = TFM_FWU_INVALID_IMAGE_ID;
+            /* Reject the component if it is in TRIAL state. Reserve a ctx
+             * for the component to record its state.
+             */
+            if (info.state == PSA_FWU_TRIAL) {
+                fwu_ctx[component].in_use = true;
+                in_trial_state = true;
+                fwu_ctx[component].component_state = PSA_FWU_TRIAL;
+                staged_trial_component_found = true;
+            }
+        }
+        if (in_trial_state) {
+            /* Reject the running(trial) image. */
+            status = fwu_bootloader_reject_trial_image(component);
+            /* If a reboot is required, the state of affected components
+             * changes to REJECTED and PSA_SUCCESS_REBOOT is returned.
+             * If a component restart is required, the state of affected
+             * components changes to REJECTED and PSA_SUCCESS_RESTART is
+             * returned.
+             * If no reboot or component restart is required, the state
+             * of affected components changes to FAILED and PSA_SUCCESS
+             * is returned.
+             */
+            if (status == PSA_SUCCESS_REBOOT || status == PSA_SUCCESS_RESTART) {
+                fwu_ctx[component].component_state = PSA_FWU_REJECTED;
+                fwu_ctx[component].error = error;
+            } else if (status == PSA_SUCCESS) {
+                fwu_ctx[component].component_state = PSA_FWU_FAILED;
+                fwu_ctx[component].error = error;
+            } else {
+                return status;
+            }
+        }
+    }
+    if (!staged_trial_component_found) {
+        /* There are no components in the STAGED or TRIAL state. */
+        return PSA_ERROR_BAD_STATE;
+    }
+    return status;
+}
+
+static psa_status_t tfm_fwu_cancel(const psa_msg_t *msg)
+{
+    psa_fwu_component_t component;
+
+    if (msg->in_size[0] != sizeof(component)) {
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    psa_read(msg->handle, 0, &component, sizeof(component));
+    if (component >= FWU_COMPONENT_NUMBER) {
+        return PSA_ERROR_DOES_NOT_EXIST;
+    }
+
+    if (fwu_ctx[component].in_use) {
+        /* The component is in FWU process. */
+        if ((fwu_ctx[component].component_state == PSA_FWU_WRITING) ||
+           (fwu_ctx[component].component_state == PSA_FWU_CANDIDATE)) {
+            fwu_ctx[component].component_state = PSA_FWU_FAILED;
+            fwu_ctx[component].error = PSA_SUCCESS;
             return PSA_SUCCESS;
         } else {
             /* If the image is in INSTALLED state or UNDEFINED, it should not in
              * a FWU process.
              */
-            return PSA_ERROR_PROGRAMMER_ERROR;
+            return PSA_ERROR_BAD_STATE;
         }
     } else {
-        /* No image with the provided image_id is not in FWU process. */
-        return PSA_ERROR_INVALID_ARGUMENT;
+        /* The component is not in WRITING or CANDIDATE state. */
+        return PSA_ERROR_BAD_STATE;
+    }
+}
+
+static psa_status_t tfm_fwu_clean(const psa_msg_t *msg)
+{
+    psa_fwu_component_t component;
+    psa_status_t status;
+
+    if (msg->in_size[0] != sizeof(component)) {
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    psa_read(msg->handle, 0, &component, sizeof(component));
+    if (component >= FWU_COMPONENT_NUMBER) {
+        return PSA_ERROR_DOES_NOT_EXIST;
+    }
+
+    if (fwu_ctx[component].in_use) {
+        /* The component is in FWU process. */
+        if ((fwu_ctx[component].component_state == PSA_FWU_FAILED) ||
+            (fwu_ctx[component].component_state == PSA_FWU_UPDATED)) {
+            status = fwu_bootloader_clean_component(component);
+            if (status != PSA_SUCCESS) {
+                return status;
+            }
+            fwu_ctx[component].component_state = PSA_FWU_READY;
+            fwu_ctx[component].in_use = false;
+            return PSA_SUCCESS;
+        } else {
+            /* If the image is in INSTALLED state or UNDEFINED, it should not in
+             * a FWU process.
+             */
+            return PSA_ERROR_BAD_STATE;
+        }
+    } else {
+        /* The component is not in FAILED or UPDATED state. */
+        return PSA_ERROR_BAD_STATE;
     }
 }
 
 psa_status_t tfm_firmware_update_service_sfn(const psa_msg_t *msg)
 {
     switch (msg->type) {
+    case TFM_FWU_START:
+        return tfm_fwu_start(msg);
     case TFM_FWU_WRITE:
-        return tfm_fwu_write_req(msg);
+        return tfm_fwu_write(msg);
+    case TFM_FWU_FINISH:
+        return tfm_fwu_finish(msg);
     case TFM_FWU_INSTALL:
-        return tfm_fwu_install_req(msg);
-    case TFM_FWU_ABORT:
-        return tfm_fwu_abort_req(msg);
+        return tfm_fwu_install();
+    case TFM_FWU_CANCEL:
+        return tfm_fwu_cancel(msg);
+    case TFM_FWU_CLEAN:
+        return tfm_fwu_clean(msg);
     case TFM_FWU_QUERY:
-        return tfm_fwu_query_req(msg);
+        return tfm_fwu_query(msg);
     case TFM_FWU_REQUEST_REBOOT:
-        return tfm_fwu_request_reboot_req();
+        return tfm_fwu_request_reboot();
     case TFM_FWU_ACCEPT:
-        return tfm_fwu_accept_req(msg);
+        return tfm_fwu_accept();
+    case TFM_FWU_REJECT:
+        return tfm_fwu_reject(msg);
     default:
         return PSA_ERROR_NOT_SUPPORTED;
     }
diff --git a/secure_fw/partitions/firmware_update/tfm_fwu_req_mngr.h b/secure_fw/partitions/firmware_update/tfm_fwu_req_mngr.h
deleted file mode 100644
index 6600f6a..0000000
--- a/secure_fw/partitions/firmware_update/tfm_fwu_req_mngr.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- */
-
-#ifndef __TFM_FWU_REQ_MNGR_H__
-#define __TFM_FWU_REQ_MNGR_H__
-
-#include <stddef.h>
-
-#include "psa/client.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* The maxinum of images that TF-M support to update concurrently. */
-#define TFM_FWU_MAX_IMAGES    2
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* __TFM_FWU_REQ_MNGR_H__ */