Add PSA FWU M update agent documentation
Document how the update agent uses the PSA Certified Firmware Update API
1.0 to implement Platform Security Firmware Update for the A-profile Arm
Architecture API.
Signed-off-by: Imre Kis <imre.kis@arm.com>
Change-Id: I55a7b80727b4b63acdf7ed27d2ab956d4ad81dc3
diff --git a/docs/services/fwu/index.rst b/docs/services/fwu/index.rst
index 8042445..4a7786a 100644
--- a/docs/services/fwu/index.rst
+++ b/docs/services/fwu/index.rst
@@ -7,9 +7,10 @@
fwu-service-description
fwu-gpt-disk-image
+ psa-fwu-m
--------------
-*Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2023-2024, Arm Limited and Contributors. All rights reserved.*
SPDX-License-Identifier: BSD-3-Clause
diff --git a/docs/services/fwu/psa-fwu-m.rst b/docs/services/fwu/psa-fwu-m.rst
new file mode 100644
index 0000000..26ffed0
--- /dev/null
+++ b/docs/services/fwu/psa-fwu-m.rst
@@ -0,0 +1,168 @@
+Firmware update on A+M systems
+------------------------------
+
+Concept
+'''''''
+
+Some platforms have both Cortex-A and Cortex-M subsystems and implement the PSA RoT on the M class core. On such systems
+the firmware store is usually read-only or not accessible to the Cortex-A cores due to security reasons. In such cases
+it may still be beneficial to implement the cloud update client on the Cortex-A subsystem, and a solution is needed to
+bridge the Cortex-A and the Cortex-M firmware update implementations. For this purpose TS implements a special firmware
+update agent which is documented below.
+
+.. figure:: ../image/psa-fwu-m-block.svg
+
+ Components on an A+M system.
+
+Standards and specifications
+''''''''''''''''''''''''''''
+
+* `Platform Security Firmware Update for the A-profile Arm Architecture`_ (A class FWU specification)
+* `PSA Certified Firmware Update API 1.0`_ (M class FWU specification)
+* `Trusted Firmware-M FWU service`_
+
+Update agent implementation
+'''''''''''''''''''''''''''
+
+The update agent implements the `Platform Security Firmware Update for the A-profile Arm Architecture`_ API (prefixed
+with ``fwu_``) and acts as a `PSA Certified Firmware Update API 1.0`_ client (prefixed with ``psa_fwu_``). The update
+agent has to align the slightly different APIs by maintaining an internal registry of image states and image handles.
+The differences between the two firmware update protocols are:
+
+* `Platform Security Firmware Update for the A-profile Arm Architecture`_ identifies images by UUID while
+ `PSA Certified Firmware Update API 1.0`_ identifies component by an 8 bit component ID.
+* Although similar calls are implemented, FWU-A operates on images, while FWU-M on the whole image set.
+* There is no *image handle* concept in `PSA Certified Firmware Update API 1.0`_
+* Differences in the returned details of the image query functions
+
+The solutions to these differences:
+
+* A static UUID to component ID mapping is used. This has to be passed to the agent init function.
+* Gathering per image based calls and then make the actual call to the M class side when the operation was called on
+ each image.
+* Implement internal image handle registry.
+* Convert the image query result returned by FWU-M to FWU-A format. There are similar field, but this imposes some
+ limitations.
+
+
+``fwu_discover()``
+``````````````````
+
+This function returns the list of implemented features.
+
+``fwu_begin_staging()``
+```````````````````````
+
+Clients can only write images in staging state. In order to switch to staging state, the client must call
+``fwu_begin_staging()``. This results in ``psa_fwu_start()`` calls on all selected images. The client can pass a list of
+the selected image UUIDs or select all images for staging.
+
+If the agent is already in staging state when ``fwu_begin_staging()`` is called, then the agent first discards all
+transient state by calling ``fwu_cancel_staging()`` and ``psa_fwu_clean()`` on all image.
+
+.. uml:: ../uml/psa_fwu_m_update_agent/fwu_begin_staging.puml
+
+``fwu_end_staging()``
+`````````````````````
+
+Finishes the staging state when all images that were selected for the update have been updated. If all selected images
+are also accepted the agent switches to regular state and the update is completed. If there are not accepted images, the
+agent switches to trial state, so the client can validate the new set of images and accept or reject them.
+
+On calling ``fwu_end_staging()`` the agent calls ``psa_fwu_finish()`` on each selected image, then calls
+``psa_fwu_install()``. If all images have been accepted (see ``fwu_commit()``) it also calls ``psa_fwu_accept()``.
+
+.. uml:: ../uml/psa_fwu_m_update_agent/fwu_end_staging.puml
+
+``fwu_cancel_staging()``
+````````````````````````
+
+Cancels staging state and reverts to original regular state. The function calls ``psa_fwu_cancel()`` on each selected
+image.
+
+.. uml:: ../uml/psa_fwu_m_update_agent/fwu_cancel_staging.puml
+
+``fwu_open()``
+``````````````
+
+`Platform Security Firmware Update for the A-profile Arm Architecture`_ has a concept of image handles. An image can be
+opened via ``fwu_open()``, then accessed by calling ``fwu_write_stream()`` or ``fwu_read_stream()``, and finally it can
+be closed by invoking ``fwu_commit()``. However `PSA Certified Firmware Update API 1.0`_ does not have a similar concept
+and once the staging process was started for an image by calling ``psa_fwu_start()``, the image can be written through
+``psa_fwu_write()``.
+
+The update agent provides an internal registry of opened images and their access rights so it can handle subsequent
+calls on the image handle. The open call can open an image for either write or read operations but not for both. The
+image is identified by its UUID. Only images which were selected for staging can be opened for write.
+
+There is no actual call made to the M class side on opening a image.
+
+`PSA Certified Firmware Update API 1.0`_ does not provide a function for reading images, so opening images will fail
+except for opening the image directory. Only the image directory supports read operations.
+
+``fwu_write_stream()``
+``````````````````````
+
+This function writes data into the opened image. The image handle has to be opened for write operations. The agent calls
+``psa_fwu_write()`` for doing the actual write and the write offset is tracked internally.
+
+``fwu_read_stream()``
+`````````````````````
+
+This function read data from the opened image. The image handle has to be opened for read operations.
+
+This call is only implemented for the image directory which returns the available image list as specified in
+`Platform Security Firmware Update for the A-profile Arm Architecture`_. It does not support the partial reading of the
+image directory.
+
+``fwu_commit()``
+````````````````
+
+The commit call closes the image handle. The client can also mark the image as accepted on commit and this the method
+for accepting all images before calling ``fwu_end_staging()``.
+
+There is no actual call made to the M class side on comiting an image.
+
+``fwu_accept_image()``
+``````````````````````
+
+`PSA Certified Firmware Update API 1.0`_ only provides a ``psa_fwu_accept()`` function which accepts the whole set of
+selected images. In order to align with the ``fwu_accept_image()`` API, it only marks the given image as accepted and
+calls ``psa_fwu_accept()`` when all images have been accepted. This results in a state transition to regular state.
+
+.. uml:: ../uml/psa_fwu_m_update_agent/fwu_accept.puml
+
+``fwu_select_previous()``
+`````````````````````````
+
+Selects previous working state (i.e. rejects the firmware update) and transitions back to regular state after calling
+``psa_fwu_reject()``.
+
+.. uml:: ../uml/psa_fwu_m_update_agent/fwu_select_previous.puml
+
+Image directory
+'''''''''''''''
+
+The client can read the image directory by opening and reading an image with dedicated UUID
+(``deee58d9-5147-4ad3-a290-77666e2341a5``). On image directory read, the agent will call ``psa_fwu_query()`` on each
+image and convert the value of similar fields.
+
+* The UUID is based on the UUID - component ID mapping passed upon agent initialization.
+* The images only support write operation due to FWU-M limitation.
+* The image maximal size is copied from the component info structure.
+* The lowest accepted version is set to 0.
+* The image version is converted from the fields of the component info structure into a single 32 bit value. The build
+ field is dropped due to lack of space in the 32 bit field.
+* The images is marked accepted if its state in the component info structure is ``PSA_FWU_UPDATED``.
+
+.. uml:: ../uml/psa_fwu_m_update_agent/image_directory.puml
+
+--------------
+
+.. _`Platform Security Firmware Update for the A-profile Arm Architecture`: https://developer.arm.com/documentation/den0118/latest/
+.. _`PSA Certified Firmware Update API 1.0`: https://arm-software.github.io/psa-api/fwu/1.0/
+.. _`Trusted Firmware-M FWU service`: https://tf-m-user-guide.trustedfirmware.org/design_docs/services/tfm_fwu_service.html
+
+*Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.*
+
+SPDX-License-Identifier: BSD-3-Clause
diff --git a/docs/services/image/psa-fwu-m-block.svg b/docs/services/image/psa-fwu-m-block.svg
new file mode 100644
index 0000000..8d9b9d0
--- /dev/null
+++ b/docs/services/image/psa-fwu-m-block.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Do not edit this file with editors other than draw.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="771px" height="261px" viewBox="-0.5 -0.5 771 261" content="<mxfile host="Electron" modified="2024-09-10T11:55:19.783Z" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/21.6.8 Chrome/114.0.5735.289 Electron/25.5.0 Safari/537.36" etag="9Li9al_JtGXNvUCZ0U1K" version="21.6.8" type="device"><diagram name="Page-1" id="wsX4NXpH4iRoKw5mJQQR">7Zhdc6IwFIZ/jTO7F3aACOglWt12pu10xt21vUwhQrqBOCF+9dfviQQBodadamtn9qZN3nzy5Lw5SAsN4tUPgWfRLQ8Ia1lGsGqhy5ZlWchE8E8p60wxkWllSihooLVCGNMXokVDq3MakLTSUXLOJJ1VRZ8nCfFlRcNC8GW125Sz6qozHJKaMPYxq6sTGsgoU7u2UehXhIZRvrJp6JYY5521kEY44MuShIYtNBCcy6wUrwaEKXo5l2zc6JXW7cYESeQhA+jE7j9b9O63d4XStXdzH73EbdPOpllgNtdPfNv2GU5TvWm5zkkIPk8CoiYzW6i/jKgk4xn2VesSDh+0SMZMNy+IkBQoeoyGCWiSqw56LWgjq1efwtyygagiPCZSrKGLHtDLceqA6uT1ZXE6Vn4GUelkLEeLWEdEuJ27gAYFze1fGHZqDL2zZojstxl2eh/LsIbwjosYq3ETLsCzZ0rS3SFp10matl0naZqnImnVSI6JPxcEtHsMGCTlyZnSdHa93UCz0duno4lqNH+O2rdnyq/XOSAanSZfn4xf/Wq8H3sgjCa/4K/Xv25ZDoNd9J8ElEJVur4C0TCMHqphJgHkZl3lQkY85Almw0LtFwdhQK3oc8MV5A3+ZyLlWr9o4Lnk1cMhKyofSuVHNdWFrWuXKz3zprLOKwmgeihXSqNUtRi2qeXjUgmG9NRLCgibhEH9XB5Rlm8pw6CefX9cACo+Fz7Zcxz6JoIFQiL39HOb40wQhiVdVPdx9Jipv5KUY2Ym+AJeCUU9cL79mgVYqovOC4HM9/e5dAoHMOCMi81YNJ0Sx89OR/A/pNQSuL0nwzjSDdixLuyqh7sHZpTTpWb3M31YeO+x1NLswyMaxT3QKKbzmU5x9zolJWJB4SmPaYPAJt2g02SDrvWEHOdIiczZSWRNJrAaEtnJTNBtIt1+I5NdDu8M0+z+T2PHTmNm/iXgLXvae8OsbVwYbkfPdbBj9XT3nMK2iy58Ok1hL7uBtl31HRdw/cdR2eY+owrg10t2qOsekuw+1OfZfV5hPaIiXmL1A2rX36nkQn0++voXrH1C8FAtPnJlnii+FaLhXw==</diagram></mxfile>" style="background-color: rgb(255, 255, 255);"><defs/><g><rect x="570" y="0" width="200" height="260" rx="30" ry="30" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 198px; height: 1px; padding-top: 7px; margin-left: 571px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">M-class</div></div></div></foreignObject><text x="670" y="19" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">M-class</text></switch></g><rect x="0" y="0" width="490" height="260" rx="39" ry="39" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 488px; height: 1px; padding-top: 7px; margin-left: 1px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">A-class</div></div></div></foreignObject><text x="245" y="19" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">A-class</text></switch></g><rect x="20" y="30" width="155" height="110" rx="16.5" ry="16.5" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 153px; height: 1px; padding-top: 37px; margin-left: 21px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Normal World</div></div></div></foreignObject><text x="98" y="49" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Normal World</text></switch></g><rect x="270" y="30" width="200" height="110" rx="16.5" ry="16.5" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 198px; height: 1px; padding-top: 37px; margin-left: 271px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Secure Partition</div></div></div></foreignObject><text x="370" y="49" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Secure Partition</text></switch></g><rect x="590" y="30" width="160" height="210" rx="24" ry="24" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 37px; margin-left: 591px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">TF-M</div></div></div></foreignObject><text x="670" y="49" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">TF-M</text></switch></g><path d="M 453.87 90 L 603.63 90" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 448.62 90 L 455.62 86.5 L 453.87 90 L 455.62 93.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 608.88 90 L 601.88 93.5 L 603.63 90 L 601.88 86.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 90px; margin-left: 529px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">PSA FWU ABI<br />IHI 0093</div></div></div></foreignObject><text x="529" y="93" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">PSA FWU ABI...</text></switch></g><rect x="292.5" y="60" width="155" height="60" rx="9" ry="9" fill="#ffe6cc" stroke="#d79b00" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 153px; height: 1px; padding-top: 90px; margin-left: 293px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">PSA FWU provider<br />(Update Agent)</div></div></div></foreignObject><text x="370" y="94" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">PSA FWU provider...</text></switch></g><path d="M 670 120 L 670 153.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 670 158.88 L 666.5 151.88 L 670 153.63 L 673.5 151.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="610" y="60" width="120" height="60" rx="9" ry="9" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 90px; margin-left: 611px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">PSA FWU service</div></div></div></foreignObject><text x="670" y="94" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">PSA FWU service</text></switch></g><path d="M 163.87 90 L 286.13 90" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 158.62 90 L 165.62 86.5 L 163.87 90 L 165.62 93.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 291.38 90 L 284.38 93.5 L 286.13 90 L 284.38 86.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 90px; margin-left: 220px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">PSA-A FWU ABI<br />DEN0118</div></div></div></foreignObject><text x="220" y="93" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="11px" text-anchor="middle">PSA-A FWU ABI...</text></switch></g><rect x="37.5" y="60" width="120" height="60" rx="9" ry="9" fill="#ffe6cc" stroke="#d79b00" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 90px; margin-left: 39px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">PSA FWU client</div></div></div></foreignObject><text x="98" y="94" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">PSA FWU client</text></switch></g><rect x="610" y="160" width="120" height="60" rx="9" ry="9" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 190px; margin-left: 611px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Firmware<br />storage</div></div></div></foreignObject><text x="670" y="194" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Firmware...</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.drawio.com/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg>
\ No newline at end of file
diff --git a/docs/services/uml/psa_fwu_m_update_agent/fwu_accept.puml b/docs/services/uml/psa_fwu_m_update_agent/fwu_accept.puml
new file mode 100644
index 0000000..c497599
--- /dev/null
+++ b/docs/services/uml/psa_fwu_m_update_agent/fwu_accept.puml
@@ -0,0 +1,30 @@
+'-------------------------------------------------------------------------------
+' Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+'
+' SPDX-License-Identifier: BSD-3-Clause
+'
+'-------------------------------------------------------------------------------
+
+@startuml
+participant "PSA FWU A Update Client" as client
+participant "PSA FWU A Update Agent" as agent
+participant "PSA FWU M Service" as service
+
+autoactivate on
+
+client -> agent: fwu_accept_image()
+
+alt state == Trial
+ agent -> agent: mark image accepted
+ agent --> agent
+
+ alt all images accepted
+ agent -> service: psa_fwu_accept()
+ service --> agent
+ hnote over agent: state = Regular
+ end
+end
+
+agent --> client
+
+@enduml
diff --git a/docs/services/uml/psa_fwu_m_update_agent/fwu_begin_staging.puml b/docs/services/uml/psa_fwu_m_update_agent/fwu_begin_staging.puml
new file mode 100644
index 0000000..5bec1ab
--- /dev/null
+++ b/docs/services/uml/psa_fwu_m_update_agent/fwu_begin_staging.puml
@@ -0,0 +1,36 @@
+'-------------------------------------------------------------------------------
+' Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+'
+' SPDX-License-Identifier: BSD-3-Clause
+'
+'-------------------------------------------------------------------------------
+
+@startuml
+participant "PSA FWU A Update Client" as client
+participant "PSA FWU A Update Agent" as agent
+participant "PSA FWU M Service" as service
+
+autoactivate on
+
+client -> agent: fwu_begin_staging()
+
+alt state == Staging
+ agent -> agent: fwu_cancel_staging()
+ agent --> agent
+
+ loop on all images
+ agent -> service: psa_fwu_clean(image)
+ service --> agent
+ end
+end
+
+loop on selected images
+ agent -> service: psa_fwu_start(image)
+ service --> agent
+end
+
+hnote over agent: state = Staging
+
+agent --> client
+
+@enduml
diff --git a/docs/services/uml/psa_fwu_m_update_agent/fwu_cancel_staging.puml b/docs/services/uml/psa_fwu_m_update_agent/fwu_cancel_staging.puml
new file mode 100644
index 0000000..48cf3f8
--- /dev/null
+++ b/docs/services/uml/psa_fwu_m_update_agent/fwu_cancel_staging.puml
@@ -0,0 +1,28 @@
+'-------------------------------------------------------------------------------
+' Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+'
+' SPDX-License-Identifier: BSD-3-Clause
+'
+'-------------------------------------------------------------------------------
+
+@startuml
+participant "PSA FWU A Update Client" as client
+participant "PSA FWU A Update Agent" as agent
+participant "PSA FWU M Service" as service
+
+autoactivate on
+
+client -> agent: fwu_cancel_staging()
+
+alt state == Staging
+ loop on all selected images
+ agent -> service: psa_fwu_cancel(image)
+ service --> agent
+ end
+
+ hnote over agent: state = Regular
+end
+
+agent --> client
+
+@enduml
diff --git a/docs/services/uml/psa_fwu_m_update_agent/fwu_end_staging.puml b/docs/services/uml/psa_fwu_m_update_agent/fwu_end_staging.puml
new file mode 100644
index 0000000..631ddf1
--- /dev/null
+++ b/docs/services/uml/psa_fwu_m_update_agent/fwu_end_staging.puml
@@ -0,0 +1,37 @@
+'-------------------------------------------------------------------------------
+' Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+'
+' SPDX-License-Identifier: BSD-3-Clause
+'
+'-------------------------------------------------------------------------------
+
+@startuml
+participant "PSA FWU A Update Client" as client
+participant "PSA FWU A Update Agent" as agent
+participant "PSA FWU M Service" as service
+
+autoactivate on
+
+client -> agent: fwu_end_staging()
+
+alt state == Staging
+ loop on all selected images
+ agent -> service: psa_fwu_finish(image)
+ service --> agent
+ end
+
+ agent -> service: psa_fwu_install()
+ service --> agent
+
+ alt all images accepted
+ agent -> service: psa_fwu_accept()
+ service --> agent
+ hnote over agent: state = Regular
+ else
+ hnote over agent: state = Trial
+ end
+end
+
+agent --> client
+
+@enduml
diff --git a/docs/services/uml/psa_fwu_m_update_agent/fwu_select_previous.puml b/docs/services/uml/psa_fwu_m_update_agent/fwu_select_previous.puml
new file mode 100644
index 0000000..985e496
--- /dev/null
+++ b/docs/services/uml/psa_fwu_m_update_agent/fwu_select_previous.puml
@@ -0,0 +1,25 @@
+'-------------------------------------------------------------------------------
+' Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+'
+' SPDX-License-Identifier: BSD-3-Clause
+'
+'-------------------------------------------------------------------------------
+
+@startuml
+participant "PSA FWU A Update Client" as client
+participant "PSA FWU A Update Agent" as agent
+participant "PSA FWU M Service" as service
+
+autoactivate on
+
+client -> agent: fwu_select_previous()
+
+alt state == Trial
+ agent -> service: psa_fwu_reject(0)
+ service --> agent
+ hnote over agent: state = Regular
+end
+
+agent --> client
+
+@enduml
diff --git a/docs/services/uml/psa_fwu_m_update_agent/image_directory.puml b/docs/services/uml/psa_fwu_m_update_agent/image_directory.puml
new file mode 100644
index 0000000..51434a9
--- /dev/null
+++ b/docs/services/uml/psa_fwu_m_update_agent/image_directory.puml
@@ -0,0 +1,30 @@
+'-------------------------------------------------------------------------------
+' Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+'
+' SPDX-License-Identifier: BSD-3-Clause
+'
+'-------------------------------------------------------------------------------
+
+@startuml
+participant "PSA FWU A Update Client" as client
+participant "PSA FWU A Update Agent" as agent
+participant "PSA FWU M Service" as service
+
+autoactivate on
+
+client -> agent: fwu_read_stream(image directory)
+
+agent -> agent: fill image_directory structure
+agent --> agent
+
+loop on all images
+ agent -> service: psa_fwu_query(image)
+ service --> agent: psa_fwu_component_info_t
+
+ agent -> agent: convert psa_fwu_component_info_t to img_info_entry
+ agent --> agent: img_info_entry
+end
+
+agent --> client
+
+@enduml