All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 00/24] Introduce Firmware Update Support for Arm PSA
@ 2025-07-25 15:49 abdellatif.elkhlifi
  2025-07-25 15:49 ` [PATCH v4 01/24] arm_ffa: Add FFA_MEM_SHARE support abdellatif.elkhlifi
                   ` (24 more replies)
  0 siblings, 25 replies; 29+ messages in thread
From: abdellatif.elkhlifi @ 2025-07-25 15:49 UTC (permalink / raw)
  To: u-boot
  Cc: Abdellatif El Khlifi, Tom Rini, Simon Glass, Sughosh Ganu,
	Heinrich Schuchardt, Ilias Apalodimas, Jens Wiklander,
	Michal Simek, Marek Vasut, Casey Connolly, Adriano Cordova,
	Mattijs Korpershoek, Davidson kumaresan, Hugues Kamba Mpiana,
	Adam Johnston

From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>

This patch series adds Firmware Update (FWU) support for Arm PSA
Certified platforms [1], enabling U-Boot to serve as
the FWU Client, with the Secure World acting as the Update Agent that
manages the firmware store and its metadata.

This implementation adheres to the Platform Security Firmware Update
specification [3] for the A-profile Arm Architecture and leverages the
Trusted Services framework [4] to interact with the Secure World update
agent. By delegating update management to the Secure World, U-Boot
handles only the client-side coordination, invoking a well-defined set
of ABIs over the FF-A interface [5] to deliver update capsules.

Key features include:

- Generic, platform-agnostic design.
- FF-A-based ABI: All interactions between U-Boot and the update agent
    occur over the FF-A interface, ensuring compatibility across
    PSA-compliant systems.
- Multi-payload capsules: Support for capsules containing multiple
    payloads, start/end markers, signed firmware images.
- ESRT support: Capsule payloads may be signed for authenticity, and
    U-Boot can populate the EFI System Resource Table (ESRT) for
     OS-level firmware management.
- On-disk and standard capsule handling.

For implementation details, please refer to the documentation [6].
For a real world example, please see the Arm PSA FWU logs [7] when used
for on-disk capsule update in Corstone-1000 [2].

Changes in v4:

- Update the function headers in fwu_arm_psa.c to pass kernel-doc tests

Cheers,
Abdellatif

[1]: PSA: https://www.psacertified.org
[2]: Corstone-1000: https://developer.arm.com/Processors/Corstone-1000
[3]: DEN0118 v1.0 A specification: https://developer.arm.com/documentation/den0118/latest 
[4]: Trusted Services documentation: https://trusted-services.readthedocs.io/en/stable
[5]: FF-A interface: doc/arch/arm64.ffa.rst
[6]: Documentation of the FWU for Arm PSA support: doc/develop/uefi/fwu_arm_psa.rst
[7]: Arm PSA FWU logs when used for on-disk capsule update in Corstone-1000

```
CapsuleApp: capsule block/size              0xDD741040/0x25ACE
Found EFI system partition on Boot0001: OnDiskFWU
FS2:;HD0b:;BLK4: 
Succeed to write edk2-corstone1000-fvp-v6.uefi.capsule
resetting ...
NOTICE:  BL2: v2.11.0(debug):v2.11.0-dirty
...
U-Boot 2025.07-rc5 (Jul 10 2025 - 15:23:22 +0000) corstone1000 aarch64 
...
FWU: System booting in Regular State
FWU: ABI version 1.0 detected
FWU: Updating 1 payload(s)
Applying capsule edk2-corstone1000-fvp-v6.uefi.capsule succeeded.
Reboot after firmware update.
NOTICE:  BL2: v2.11.0(debug):v2.11.0-dirty
...
U-Boot 2025.07-rc5 (Jul 10 2025 - 15:23:22 +0000) corstone1000 aarch64 
...
FWU: System booting in Trial State
...
Poky (Yocto Project Reference Distro) 5.2 corstone1000-fvp /dev/ttyAMA0
...
root@corstone1000-fvp:~# reboot
...
U-Boot 2025.07-rc5 (Jul 10 2025 - 15:23:22 +0000) corstone1000 aarch64 
...
FWU: System booting in Regular State
...
Poky (Yocto Project Reference Distro) 5.2 corstone1000-fvp /dev/ttyAMA0

corstone1000-fvp login:

root@corstone1000-fvp:~# cat /sys/firmware/efi/esrt/entries/entry*/*
0x0
f1d883f9-dfeb-5363-98d8-686ee3b69f4f
0
6
0
6
0
0x0
7fad470e-5ec5-5c03-a2c1-4756b495de61
0
0
0
0
0
0x0
f1933675-5a8c-5b6d-9ef4-846739e89bc8
0
0
0
0
0
0x0
f771aff9-c7e9-5f99-9eda-2369dd694f61
0
0
0
0
0
root@corstone1000-fvp:~# 
```

Cc: Tom Rini <trini@konsulko.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Sughosh Ganu <sughosh.ganu@linaro.org>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Michal Simek <michal.simek@amd.com>
Cc: Marek Vasut <marek.vasut+renesas@mailbox.org>
Cc: Casey Connolly <casey.connolly@linaro.org>
Cc: Adriano Cordova <adrianox@gmail.com>
Cc: Mattijs Korpershoek <mkorpershoek@kernel.org>
Cc: Davidson kumaresan <davidson.kumaresan@arm.com>
Cc: Hugues Kamba Mpiana <hugues.kambampiana@arm.com>
Cc: Adam Johnston <Adam.Johnston@arm.com>

Abdellatif El Khlifi (23):
  arm_ffa: Add FFA_MEM_SHARE support
  arm_ffa: Add FFA_MEM_RECLAIM support
  arm_ffa: sandbox: Replace the emulator error log with debug log
  arm_ffa: sandbox: Improve the readability of clearing the X registers
  arm_ffa: sandbox: Add FFA_MEM_SHARE emulation
  arm_ffa: sandbox: Add FFA_MEM_SHARE tests
  arm_ffa: sandbox: Add FFA_MEM_RECLAIM emulation
  arm_ffa: sandbox: Add FFA_MEM_RECLAIM tests
  fwu_arm_psa: Initialize the update agent
  fwu_arm_psa: Read the FWU directory through get_image_info()
  fwu_arm_psa: Add staging ABIs
  efi_loader: fwu_arm_psa: Add set_image and get_image_info support
  efi_loader: fwu_arm_psa: Keep the FMP payload header
  efi_loader: fwu: fwu_arm_psa: Skip accepting the payload after
    set_image()
  efi_loader: fwu: fwu_arm_psa: Disable trial state handling
  fwu_arm_psa: Add FWU acceptance mechanism
  fwu_arm_psa: Add ESRT support
  fwu_arm_psa: Add ExitBootService() notification handler
  fwu_arm_psa: corstone1000: Enable FWU support
  fwu_arm_psa: corstone1000: Perform bank logic when reading boot index
  fwu_arm_psa: corstone1000: Notify SE Proxy SP on ExitBootService()
  fwu_arm_psa: corstone1000: Set Boot0001 for on-disk FWU
  fwu_arm_psa: Document FWU support for Arm PSA

Emekcan Aras (1):
  efi_loader: capsule: Add runtime capsule flags checks

 MAINTAINERS                                   |    8 +
 .../include/asm/sandbox_arm_ffa_priv.h        |   21 +-
 board/armltd/corstone1000/corstone1000.c      |  255 ++-
 board/armltd/corstone1000/corstone1000.env    |    8 +
 configs/corstone1000_defconfig                |   13 +-
 doc/arch/arm64.ffa.rst                        |    4 +
 doc/develop/uefi/fwu_arm_psa.rst              |  154 ++
 doc/develop/uefi/index.rst                    |    1 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c     |  285 +++-
 drivers/firmware/arm-ffa/arm-ffa.c            |    4 +-
 drivers/firmware/arm-ffa/ffa-emul-uclass.c    |  108 +-
 drivers/firmware/arm-ffa/sandbox_ffa.c        |    4 +-
 include/arm_ffa.h                             |  111 +-
 include/arm_ffa_priv.h                        |  143 +-
 include/efi_api.h                             |    8 +
 include/efi_loader.h                          |    8 +
 include/fwu_arm_psa.h                         |  427 +++++
 lib/efi_loader/efi_capsule.c                  |   64 +-
 lib/efi_loader/efi_firmware.c                 |   42 +-
 lib/fwu_updates/Kconfig                       |   26 +
 lib/fwu_updates/Makefile                      |    2 +
 lib/fwu_updates/fwu.c                         |   29 +-
 lib/fwu_updates/fwu_arm_psa.c                 | 1470 +++++++++++++++++
 test/dm/ffa.c                                 |   73 +-
 24 files changed, 3178 insertions(+), 90 deletions(-)
 create mode 100644 doc/develop/uefi/fwu_arm_psa.rst
 create mode 100644 include/fwu_arm_psa.h
 create mode 100644 lib/fwu_updates/fwu_arm_psa.c


base-commit: 59e6462d7c08eeba744afa0f17846c398b8ef9e1
-- 
2.25.1


^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH v4 01/24] arm_ffa: Add FFA_MEM_SHARE support
  2025-07-25 15:49 [PATCH v4 00/24] Introduce Firmware Update Support for Arm PSA abdellatif.elkhlifi
@ 2025-07-25 15:49 ` abdellatif.elkhlifi
  2025-07-25 15:49 ` [PATCH v4 02/24] arm_ffa: Add FFA_MEM_RECLAIM support abdellatif.elkhlifi
                   ` (23 subsequent siblings)
  24 siblings, 0 replies; 29+ messages in thread
From: abdellatif.elkhlifi @ 2025-07-25 15:49 UTC (permalink / raw)
  To: u-boot
  Cc: Abdellatif El Khlifi, Tom Rini, Simon Glass, Ilias Apalodimas,
	Jens Wiklander, Casey Connolly, Heinrich Schuchardt

From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>

Add to the FF-A bus FFA_MEM_SHARE ABI

The FFA_MEM_SHARE is a memory management ABI described in the FF-A v1.0
specification [1].

This ABI starts a transaction to grant access to a memory region
to one or more Borrowers (aka Secure Partitions or endpoints).

This work is based on the implementation in Linux kernel [2].

[1]: https://developer.arm.com/documentation/den0077/a/?lang=en
[2]: commit cc2195fe536c28e192df5d07e6dd277af36814b4
     Files: drivers/firmware/arm_ffa/driver.c , include/linux/arm_ffa.h

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Tom Rini <trini@konsulko.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Casey Connolly <casey.connolly@linaro.org>
Cc: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>

---

Changelog of changes:
===========================

v3:

* Add copyright

v2:

* As suggested by Heinrich: The ops NULL check removed

v1:

* Add FFA_MEM_SHARE support

 doc/arch/arm64.ffa.rst                    |   2 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c | 212 +++++++++++++++++++++-
 drivers/firmware/arm-ffa/arm-ffa.c        |   3 +-
 include/arm_ffa.h                         |  86 ++++++++-
 include/arm_ffa_priv.h                    | 142 ++++++++++++++-
 5 files changed, 440 insertions(+), 5 deletions(-)

diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index f966f8ba6af..3eec735d741 100644
--- a/doc/arch/arm64.ffa.rst
+++ b/doc/arch/arm64.ffa.rst
@@ -185,6 +185,7 @@ The following features are provided:
     - FFA_INTERRUPT
     - FFA_MSG_SEND_DIRECT_REQ
     - FFA_MSG_SEND_DIRECT_RESP
+    - FFA_MEM_SHARE
 
 - Support for the 64-bit version of the following ABIs:
 
@@ -203,6 +204,7 @@ The following features are provided:
     - ffa_partition_info_get
     - ffa_sync_send_receive
     - ffa_rxtx_unmap
+    - ffa_memory_share
 
 - FF-A bus discovery makes sure FF-A framework is responsive and compatible
   with the driver
diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
index 96c64964bb7..9af574760d2 100644
--- a/drivers/firmware/arm-ffa/arm-ffa-uclass.c
+++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ * Copyright 2022-2023, 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * Authors:
  *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
@@ -95,6 +95,20 @@ static struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
 			"DENIED: Buffer pair already registered",
 		},
 	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_MEM_SHARE)] = {
+		{
+			[ABORTED] =
+			"ABORTED: Failure in the transmission of fragments or in time slicing",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: Validation failed for the Memory Transaction or the Endpoint memory access descriptor",
+			[NO_MEMORY] =
+			"NO_MEMORY: Insufficient memory to complete this operation",
+			[BUSY] =
+			"BUSY: The TX buffer is busy",
+			[DENIED] =
+			"DENIED: Memory region ownership, permission, access or attributes error",
+		},
+	},
 };
 
 /**
@@ -929,6 +943,177 @@ int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id,
 	return ffa_to_std_errno(ffa_errno);
 }
 
+/**
+ * ffa_mem_desc_offset() - helper for descriptors offset calculation
+ * @count: An integer defining the number of Endpoint memory access descriptors
+ *
+ * Calculate the offset of the Endpoint memory access descriptor and
+ * the Composite memory region descriptor.
+ *
+ * Return:
+ *
+ * The descriptor offset.
+ */
+static inline u32 ffa_mem_desc_offset(int count)
+{
+	u32 offset = count * sizeof(struct ffa_mem_region_attributes);
+
+	offset += sizeof(struct ffa_mem_region);
+
+	return offset;
+}
+
+/**
+ * ffa_setup_and_transmit() - set up the memory and transmit data using FF-A
+ * @dev: The FF-A bus device
+ * @func_id: An integer identifying the function
+ * @buffer: A pointer to the data to be transmitted (FF-A TX buffer)
+ * @args: A pointer to a structure containing additional user arguments
+ *
+ * Setup the memory transaction related to the access to a specified
+ * memory region.
+ * Currently we support FFA_MEM_SHARE only.
+ *
+ * Return:
+ *
+ * 0 on success. . Otherwise, failure
+ */
+static int ffa_setup_and_transmit(struct udevice *dev, u32 func_id,
+				  void *buffer, struct ffa_mem_ops_args *args)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	u32 composite_offset;
+	u32 total_length;
+	struct ffa_mem_region *mem_region = buffer;
+	struct ffa_composite_mem_region *composite;
+	struct ffa_mem_region_addr_range *constituent;
+	struct ffa_mem_region_attributes *ep_mem_access;
+	u32 idx;
+	struct ffa_priv *uc_priv;
+
+	uc_priv = dev_get_uclass_priv(dev);
+
+	mem_region->tag = args->tag;
+	mem_region->flags = args->flags;
+	mem_region->sender_id = uc_priv->id;
+
+	/*
+	 * These attributes are only valid for FFA_MEM_SHARE.
+	 * They are not valid for FFA_MEM_LEND (no implemented).
+	 */
+	if (func_id == FFA_MEM_SHARE)
+		mem_region->attributes = FFA_MEM_NORMAL | FFA_MEM_WRITE_BACK
+				 | FFA_MEM_INNER_SHAREABLE;
+	else
+		mem_region->attributes = 0;
+
+	mem_region->handle = 0;
+	mem_region->ep_count = args->nattrs;
+	mem_region->reserved1 = 0;
+	mem_region->reserved2 = 0;
+
+	ep_mem_access = buffer + ffa_mem_desc_offset(0);
+
+	composite_offset = ffa_mem_desc_offset(args->nattrs);
+
+	/* Multiple borrowers supported */
+	for (idx = 0; idx < args->nattrs; idx++, ep_mem_access++) {
+		ep_mem_access->receiver = args->attrs[idx].receiver;
+		ep_mem_access->attrs = args->attrs[idx].attrs;
+		ep_mem_access->composite_off = composite_offset;
+		ep_mem_access->flag = 0;
+		ep_mem_access->reserved = 0;
+	}
+
+	/* Only one Composite and one Constituent memory region supported */
+	composite = buffer + composite_offset;
+	composite->total_pg_cnt = args->pg_cnt;
+	composite->addr_range_cnt = FFA_MEM_CONSTITUENTS;
+	composite->reserved = 0;
+
+	constituent = &composite->constituents[0];
+	constituent->address = map_to_sysmem(args->address);
+	constituent->pg_cnt = args->pg_cnt;
+	constituent->reserved = 0;
+
+	total_length = composite_offset + sizeof(*composite) +
+		sizeof(*constituent);
+
+	/*
+	 * Note: Time slicing is not supported.
+	 * It's only available to EL1 and S-EL1 endpoints.
+	 */
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(func_id),
+			.a1 = total_length,
+			.a2 = total_length,
+			.a3 = 0, /* the TX buffer is used */
+			.a4 = 0, /* the TX buffer is used */
+			},
+			&res
+	);
+
+	if (res.a0 != FFA_SMC_32(FFA_SUCCESS)) {
+		ffa_errno = res.a2;
+		ffa_print_error_log(func_id, ffa_errno);
+		return ffa_to_std_errno(ffa_errno);
+	}
+
+	args->g_handle = PACK_HANDLE(res.a2, res.a3);
+	return 0;
+}
+
+/**
+ * ffa_memory_ops() - wrapper for the memory management ABIs
+ * @dev: The FF-A bus device
+ * @func_id: An integer identifying the function
+ * @args: A pointer to a structure containing additional user arguments
+ *
+ * Verify the use of the TX buffer then call ffa_setup_and_transmit().
+ * Currently we support FFA_MEM_SHARE only.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_memory_ops(struct udevice *dev, u32 func_id,
+			  struct ffa_mem_ops_args *args)
+{
+	void *buffer;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	if (!args->use_txbuf) {
+		log_err("only TX buffer supported\n");
+		return -EPROTONOSUPPORT;
+	}
+
+	buffer = uc_priv->pair.txbuf;
+
+	if (!buffer || !args->attrs || !args->address)
+		return -EINVAL;
+
+	return ffa_setup_and_transmit(dev, func_id, buffer, args);
+}
+
+/**
+ * ffa_memory_share_hdlr() - FFA_MEM_SHARE handler function
+ * @dev: The FF-A bus device
+ * @args: A pointer to a structure containing additional user arguments
+ *
+ * Implement FFA_MEM_SHARE FF-A function
+ * to grant access to a memory region to one or more Borrowers.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_memory_share_hdlr(struct udevice *dev, struct ffa_mem_ops_args *args)
+{
+	return ffa_memory_ops(dev, FFA_MEM_SHARE, args);
+}
+
 /* FF-A driver operations (used by clients for communicating with FF-A)*/
 
 /**
@@ -1006,6 +1191,31 @@ int ffa_rxtx_unmap(struct udevice *dev)
 	return ops->rxtx_unmap(dev);
 }
 
+/**
+ * ffa_memory_share() - FFA_MEM_SHARE driver operation
+ * @dev: The FF-A bus device
+ * @args: A pointer to a structure containing additional user arguments
+ *
+ * Driver operation for FFA_MEM_SHARE.
+ * Please see ffa_memory_share_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_memory_share(struct udevice *dev, struct ffa_mem_ops_args *args)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!args)
+		return -EINVAL;
+
+	if (!ops->memory_share)
+		return -ENOSYS;
+
+	return ops->memory_share(dev, args);
+}
+
 /**
  * ffa_do_probe() - probing FF-A framework
  * @dev:	the FF-A bus device (arm_ffa)
diff --git a/drivers/firmware/arm-ffa/arm-ffa.c b/drivers/firmware/arm-ffa/arm-ffa.c
index 94e6105cb38..df904cae412 100644
--- a/drivers/firmware/arm-ffa/arm-ffa.c
+++ b/drivers/firmware/arm-ffa/arm-ffa.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ * Copyright 2022-2023, 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * Authors:
  *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
@@ -84,6 +84,7 @@ static const struct ffa_bus_ops ffa_ops = {
 	.partition_info_get = ffa_get_partitions_info_hdlr,
 	.sync_send_receive = ffa_msg_send_direct_req_hdlr,
 	.rxtx_unmap = ffa_unmap_rxtx_buffers_hdlr,
+	.memory_share = ffa_memory_share_hdlr,
 };
 
 /* Registering the FF-A driver as an SMCCC feature driver */
diff --git a/include/arm_ffa.h b/include/arm_ffa.h
index 2994d8ee3ae..b91b0279371 100644
--- a/include/arm_ffa.h
+++ b/include/arm_ffa.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0+ */
 /*
- * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ * Copyright 2022-2023, 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * Authors:
  *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
@@ -81,11 +81,74 @@ struct ffa_send_direct_data {
 
 struct udevice;
 
+/**
+ * struct ffa_mem_region_attributes - Endpoint memory access descriptor
+ *
+ * The data structure used in memory management transactions to create an
+ * association between an endpoint, memory access permissions and a composite
+ * memory region description.
+ *
+ * For more details, please refer to Table 5.16 and Table 5.15 in the FF-A
+ * specification v1.0.
+ *
+ * This structure was taken from Linux.
+ */
+struct ffa_mem_region_attributes {
+	/* The ID of the VM to which the memory is being given or shared. */
+	u16 receiver;
+	/*
+	 * The permissions with which the memory region should be mapped in the
+	 * receiver's page table.
+	 */
+#define FFA_MEM_EXEC		BIT(3)
+#define FFA_MEM_NO_EXEC		BIT(2)
+#define FFA_MEM_RW		BIT(1)
+#define FFA_MEM_RO		BIT(0)
+	u8 attrs;
+	/*
+	 * Flags used during FFA_MEM_RETRIEVE_REQ and FFA_MEM_RETRIEVE_RESP
+	 * for memory regions with multiple borrowers.
+	 */
+#define FFA_MEM_RETRIEVE_SELF_BORROWER	BIT(0)
+	u8 flag;
+	/*
+	 * Offset in bytes from the start of the outer `ffa_memory_region` to
+	 * an `struct ffa_mem_region_addr_range`.
+	 */
+	u32 composite_off;
+	u64 reserved;
+};
+
+/**
+ * struct ffa_mem_ops_args - User arguments to the memory management ABIs
+ * @use_txbuf:	Whether to use the TX buffer for the memory transaction
+ * @nattrs:	Number of the borrowers
+ * @flags:	Memory transaction flags
+ * @tag:	The tag associated with the transaction
+ * @g_handle:	Globally unique Handle to identify the memory region (out)
+ * @address:	Virtual address of the memory region
+ * @attrs:	Memory access permissions of each borrower
+ *
+ * The structured filled by the user and passed to the memory
+ * management ABIs (e.g: FFA_MEM_SHARE)
+ */
+struct ffa_mem_ops_args {
+	bool use_txbuf;
+	u32 nattrs;
+	u32 flags;
+	u64 tag;
+	u64 g_handle;
+	void *address;
+	u32 pg_cnt;
+	struct ffa_mem_region_attributes *attrs;
+};
+
 /**
  * struct ffa_bus_ops - Operations for FF-A
  * @partition_info_get:	callback for the FFA_PARTITION_INFO_GET
  * @sync_send_receive:	callback for the FFA_MSG_SEND_DIRECT_REQ
  * @rxtx_unmap:	callback for the FFA_RXTX_UNMAP
+ * @memory_share:	callback for the FFA_MEM_SHARE
  *
  * The data structure providing all the operations supported by the driver.
  * This structure is EFI runtime resident.
@@ -97,6 +160,7 @@ struct ffa_bus_ops {
 				 struct ffa_send_direct_data *msg,
 				 bool is_smc64);
 	int (*rxtx_unmap)(struct udevice *dev);
+	int (*memory_share)(struct udevice *dev, struct ffa_mem_ops_args *args);
 };
 
 #define ffa_get_ops(dev)        ((struct ffa_bus_ops *)(dev)->driver->ops)
@@ -196,6 +260,26 @@ int ffa_partition_info_get(struct udevice *dev, const char *uuid_str,
 int ffa_get_partitions_info_hdlr(struct udevice *dev, const char *uuid_str,
 				 u32 *sp_count, struct ffa_partition_desc **sp_descs);
 
+/**
+ * ffa_memory_share() - FFA_MEM_SHARE driver operation
+ * Please see ffa_memory_share_hdlr() description for more details.
+ */
+int ffa_memory_share(struct udevice *dev, struct ffa_mem_ops_args *args);
+
+/**
+ * ffa_memory_share_hdlr() - FFA_MEM_SHARE handler function
+ * @dev: The FF-A bus device
+ * @args: A pointer to a structure containing additional user arguments
+ *
+ * Implement FFA_MEM_SHARE FF-A function
+ * to grant access to a memory region to one or more Borrowers.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_memory_share_hdlr(struct udevice *dev, struct ffa_mem_ops_args *args);
+
 struct ffa_priv;
 
 /**
diff --git a/include/arm_ffa_priv.h b/include/arm_ffa_priv.h
index d564c33c647..a259911d5b9 100644
--- a/include/arm_ffa_priv.h
+++ b/include/arm_ffa_priv.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0+ */
 /*
- * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ * Copyright 2022-2023, 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * Authors:
  *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
@@ -132,10 +132,11 @@ enum ffa_abis {
 	FFA_RUN                   = 0x6d,
 	FFA_MSG_SEND_DIRECT_REQ   = 0x6f,
 	FFA_MSG_SEND_DIRECT_RESP  = 0x70,
+	FFA_MEM_SHARE             = 0x73,
 
 	/* To be updated when adding new FFA IDs */
 	FFA_FIRST_ID              = FFA_ERROR, /* Lowest number ID */
-	FFA_LAST_ID               = FFA_MSG_SEND_DIRECT_RESP, /* Highest number ID */
+	FFA_LAST_ID               = FFA_MEM_SHARE, /* Highest number ID */
 };
 
 enum ffa_abi_errcode {
@@ -219,6 +220,143 @@ struct ffa_priv {
 	struct ffa_rxtxpair pair;
 };
 
+/* FF-A memory management ABIs data structures */
+
+/**
+ * struct ffa_mem_region - Lend, donate or share memory transaction descriptor
+ *
+ * Specifies the data structure that must be used by the Owner/Lender and a
+ * Borrower/Receiver in a transaction to donate, lend or share a memory region.
+ * It specifies the memory region description, properties and other transaction
+ * attributes in an invocation of the following ABIs.
+ *
+ * FFA_MEM_DONATE.
+ * FFA_MEM_LEND.
+ * FFA_MEM_SHARE.
+ * FFA_MEM_RETRIEVE_REQ.
+ * FFA_MEM_RETRIEVE_RESP.
+ *
+ * For more details, please refer to the Table 5.19 in the FF-A specification
+ * v1.0.
+ *
+ * The interpretation of some fields depends on the ABI this structure is used
+ * with. This variance in behavior is also specified in the Table 5.19.
+ *
+ * This structure was taken from Linux and adapted to FF-A v1.0.
+ */
+struct ffa_mem_region {
+	/* The ID of the VM/owner which originally sent the memory region */
+	u16 sender_id;
+#define FFA_MEM_NORMAL		BIT(5)
+#define FFA_MEM_DEVICE		BIT(4)
+
+#define FFA_MEM_WRITE_BACK	(3 << 2)
+#define FFA_MEM_NON_CACHEABLE	BIT(2)
+
+#define FFA_DEV_nGnRnE		(0 << 2)
+#define FFA_DEV_nGnRE		BIT(2)
+#define FFA_DEV_nGRE		(2 << 2)
+#define FFA_DEV_GRE		(3 << 2)
+
+#define FFA_MEM_NON_SHAREABLE	(0)
+#define FFA_MEM_OUTER_SHAREABLE	(2)
+#define FFA_MEM_INNER_SHAREABLE	(3)
+	/* Memory region attributes */
+	u8 attributes;
+
+	u8 reserved1;
+
+/*
+ * Clear memory region contents after unmapping it from the sender and
+ * before mapping it for any receiver.
+ */
+#define FFA_MEM_CLEAR			BIT(0)
+/*
+ * Whether the hypervisor may time slice the memory sharing or retrieval
+ * operation.
+ */
+#define FFA_TIME_SLICE_ENABLE		BIT(1)
+
+#define FFA_MEM_RETRIEVE_TYPE_IN_RESP	(0 << 3)
+#define FFA_MEM_RETRIEVE_TYPE_SHARE	BIT(3)
+#define FFA_MEM_RETRIEVE_TYPE_LEND	(2 << 3)
+#define FFA_MEM_RETRIEVE_TYPE_DONATE	(3 << 3)
+
+#define FFA_MEM_RETRIEVE_ADDR_ALIGN_HINT	BIT(9)
+#define FFA_MEM_RETRIEVE_ADDR_ALIGN(x)		((x) << 5)
+	/* Flags to control behaviour of the transaction. */
+	u32 flags;
+#define HANDLE_LOW_MASK		GENMASK_ULL(31, 0)
+#define HANDLE_HIGH_MASK	GENMASK_ULL(63, 32)
+#define HANDLE_LOW(x)		((u32)(FIELD_GET(HANDLE_LOW_MASK, (x))))
+#define	HANDLE_HIGH(x)		((u32)(FIELD_GET(HANDLE_HIGH_MASK, (x))))
+
+#define PACK_HANDLE(l, h)		\
+	(FIELD_PREP(HANDLE_LOW_MASK, (l)) | FIELD_PREP(HANDLE_HIGH_MASK, (h)))
+	/*
+	 * A globally-unique ID assigned by the hypervisor for a region
+	 * of memory being sent between VMs.
+	 */
+	u64 handle;
+	/*
+	 * An implementation defined value associated with the receiver and the
+	 * memory region.
+	 */
+	u64 tag;
+
+	u32 reserved2;
+
+	/*
+	 * The number of `ffa_mem_region_attributes` entries included in this
+	 * transaction.
+	 */
+	u32 ep_count;
+};
+
+/**
+ * struct ffa_mem_region_addr_range - Constituent memory region descriptor
+ *
+ * Each descriptor specifies the base address and size of a virtually or
+ * physically contiguous memory region.
+ *
+ * For more details, please refer to Table 5.14 in the FF-A
+ * specification v1.0.
+ *
+ * This structure was taken from Linux.
+ */
+struct ffa_mem_region_addr_range {
+	/* The base IPA of the constituent memory region, aligned to 4 kiB */
+	u64 address;
+	/* The number of 4 kiB pages in the constituent memory region. */
+	u32 pg_cnt;
+	u32 reserved;
+};
+
+/**
+ * struct ffa_composite_mem_region - Composite memory region descriptor
+ *
+ * For more details, please refer to Table 5.13 in the FF-A
+ * specification v1.0.
+ *
+ * This structure was taken from Linux.
+ */
+struct ffa_composite_mem_region {
+	/*
+	 * The total number of 4 kiB pages included in this memory region. This
+	 * must be equal to the sum of page counts specified in each
+	 * `struct ffa_mem_region_addr_range`.
+	 */
+	u32 total_pg_cnt;
+	/* The number of constituents included in this memory region range */
+#define FFA_MEM_CONSTITUENTS		(1)
+	u32 addr_range_cnt;
+	u64 reserved;
+	/** An array of `addr_range_cnt` memory region constituents. */
+	struct ffa_mem_region_addr_range constituents[];
+};
+
+/* Functions prototypes */
+
 /**
  * ffa_get_version_hdlr() - FFA_VERSION handler function
  * @dev: The FF-A bus device
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v4 02/24] arm_ffa: Add FFA_MEM_RECLAIM support
  2025-07-25 15:49 [PATCH v4 00/24] Introduce Firmware Update Support for Arm PSA abdellatif.elkhlifi
  2025-07-25 15:49 ` [PATCH v4 01/24] arm_ffa: Add FFA_MEM_SHARE support abdellatif.elkhlifi
@ 2025-07-25 15:49 ` abdellatif.elkhlifi
  2025-07-25 15:49 ` [PATCH v4 03/24] arm_ffa: sandbox: Replace the emulator error log with debug log abdellatif.elkhlifi
                   ` (22 subsequent siblings)
  24 siblings, 0 replies; 29+ messages in thread
From: abdellatif.elkhlifi @ 2025-07-25 15:49 UTC (permalink / raw)
  To: u-boot
  Cc: Abdellatif El Khlifi, Tom Rini, Simon Glass, Ilias Apalodimas,
	Jens Wiklander, Casey Connolly, Heinrich Schuchardt

From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>

Add to the FF-A bus FFA_MEM_RECLAIM ABI

The FFA_MEM_RECLAIM is a memory management ABI described in the FF-A
v1.0 specification [1].

This ABI restores exclusive access to a memory region back to its Owner.

This work is based on the implementation in Linux [2].

[1]: https://developer.arm.com/documentation/den0077/a/?lang=en
[2]: commit cc2195fe536c28e192df5d07e6dd277af36814b4
     File: drivers/firmware/arm_ffa/driver.c

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Tom Rini <trini@konsulko.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Casey Connolly <casey.connolly@linaro.org>
Cc: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>

---

Changelog of changes:
===========================

v2:

* As suggested by Heinrich: The ops NULL check removed

v1:

* Add FFA_MEM_RECLAIM support

 doc/arch/arm64.ffa.rst                    |  2 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c | 73 +++++++++++++++++++++++
 drivers/firmware/arm-ffa/arm-ffa.c        |  1 +
 include/arm_ffa.h                         | 25 +++++++-
 include/arm_ffa_priv.h                    |  3 +-
 5 files changed, 102 insertions(+), 2 deletions(-)

diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index 3eec735d741..d2c4fb49f79 100644
--- a/doc/arch/arm64.ffa.rst
+++ b/doc/arch/arm64.ffa.rst
@@ -186,6 +186,7 @@ The following features are provided:
     - FFA_MSG_SEND_DIRECT_REQ
     - FFA_MSG_SEND_DIRECT_RESP
     - FFA_MEM_SHARE
+    - FFA_MEM_RECLAIM
 
 - Support for the 64-bit version of the following ABIs:
 
@@ -205,6 +206,7 @@ The following features are provided:
     - ffa_sync_send_receive
     - ffa_rxtx_unmap
     - ffa_memory_share
+    - ffa_memory_reclaim
 
 - FF-A bus discovery makes sure FF-A framework is responsive and compatible
   with the driver
diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
index 9af574760d2..b9b66bf68f9 100644
--- a/drivers/firmware/arm-ffa/arm-ffa-uclass.c
+++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
@@ -109,6 +109,18 @@ static struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
 			"DENIED: Memory region ownership, permission, access or attributes error",
 		},
 	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_MEM_RECLAIM)] = {
+		{
+			[ABORTED] =
+			"ABORTED: ABI invocation failure",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: Invalid handle or flags",
+			[NO_MEMORY] =
+			"NO_MEMORY: Failure to create the Owner's mapping",
+			[DENIED] =
+			"DENIED: Memory region state issue",
+		},
+	},
 };
 
 /**
@@ -1114,6 +1126,44 @@ int ffa_memory_share_hdlr(struct udevice *dev, struct ffa_mem_ops_args *args)
 	return ffa_memory_ops(dev, FFA_MEM_SHARE, args);
 }
 
+/**
+ * ffa_memory_reclaim_hdlr() - FFA_MEM_RECLAIM handler function
+ * @dev: The FF-A bus device
+ * @g_handle: The memory region globally unique Handle
+ * @flags: Zero memory and time slicing flags
+ *
+ * Implement FFA_MEM_RECLAIM FF-A function
+ * to restore exclusive access to a memory region back to its Owner.
+ * Note: FFA_MEM_RECLAIM can not be used at EFI runtime because memory that was
+ * lent as per the memory map during boot time can not be reclaimed into the
+ * memory map during runtime.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_memory_reclaim_hdlr(struct udevice *dev, u64 g_handle, u32 flags)
+{
+	ffa_value_t res;
+	int ffa_errno;
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_MEM_RECLAIM),
+			.a1 = HANDLE_LOW(g_handle), .a2 = HANDLE_HIGH(g_handle),
+			.a3 = flags,
+			},
+			&res
+	);
+
+	if (res.a0 != FFA_SMC_32(FFA_SUCCESS)) {
+		ffa_errno = res.a2;
+		ffa_print_error_log(FFA_MEM_RECLAIM, ffa_errno);
+		return ffa_to_std_errno(ffa_errno);
+	}
+
+	return 0;
+}
+
 /* FF-A driver operations (used by clients for communicating with FF-A)*/
 
 /**
@@ -1216,6 +1266,29 @@ int ffa_memory_share(struct udevice *dev, struct ffa_mem_ops_args *args)
 	return ops->memory_share(dev, args);
 }
 
+/**
+ * ffa_memory_reclaim() - FFA_MEM_RECLAIM driver operation
+ * @dev: The FF-A bus device
+ * @g_handle: The memory region globally unique Handle
+ * @flags: Zero memory and time slicing flags
+ *
+ * Driver operation for FFA_MEM_RECLAIM.
+ * Please see ffa_memory_reclaim_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_memory_reclaim(struct udevice *dev, u64 g_handle, u32 flags)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->memory_reclaim)
+		return -ENOSYS;
+
+	return ops->memory_reclaim(dev, g_handle, flags);
+}
+
 /**
  * ffa_do_probe() - probing FF-A framework
  * @dev:	the FF-A bus device (arm_ffa)
diff --git a/drivers/firmware/arm-ffa/arm-ffa.c b/drivers/firmware/arm-ffa/arm-ffa.c
index df904cae412..de36f5647d2 100644
--- a/drivers/firmware/arm-ffa/arm-ffa.c
+++ b/drivers/firmware/arm-ffa/arm-ffa.c
@@ -85,6 +85,7 @@ static const struct ffa_bus_ops ffa_ops = {
 	.sync_send_receive = ffa_msg_send_direct_req_hdlr,
 	.rxtx_unmap = ffa_unmap_rxtx_buffers_hdlr,
 	.memory_share = ffa_memory_share_hdlr,
+	.memory_reclaim = ffa_memory_reclaim_hdlr,
 };
 
 /* Registering the FF-A driver as an SMCCC feature driver */
diff --git a/include/arm_ffa.h b/include/arm_ffa.h
index b91b0279371..1229e6e3d02 100644
--- a/include/arm_ffa.h
+++ b/include/arm_ffa.h
@@ -147,8 +147,9 @@ struct ffa_mem_ops_args {
  * struct ffa_bus_ops - Operations for FF-A
  * @partition_info_get:	callback for the FFA_PARTITION_INFO_GET
  * @sync_send_receive:	callback for the FFA_MSG_SEND_DIRECT_REQ
- * @rxtx_unmap:	callback for the FFA_RXTX_UNMAP
+ * @rxtx_unmap:		callback for the FFA_RXTX_UNMAP
  * @memory_share:	callback for the FFA_MEM_SHARE
+ * @memory_reclaim:	callback for the FFA_MEM_RECLAIM
  *
  * The data structure providing all the operations supported by the driver.
  * This structure is EFI runtime resident.
@@ -161,6 +162,7 @@ struct ffa_bus_ops {
 				 bool is_smc64);
 	int (*rxtx_unmap)(struct udevice *dev);
 	int (*memory_share)(struct udevice *dev, struct ffa_mem_ops_args *args);
+	int (*memory_reclaim)(struct udevice *dev, u64 g_handle, u32 flags);
 };
 
 #define ffa_get_ops(dev)        ((struct ffa_bus_ops *)(dev)->driver->ops)
@@ -280,6 +282,27 @@ int ffa_memory_share(struct udevice *dev, struct ffa_mem_ops_args *args);
  */
 int ffa_memory_share_hdlr(struct udevice *dev, struct ffa_mem_ops_args *args);
 
+/**
+ * ffa_memory_reclaim() - FFA_MEM_RECLAIM driver operation
+ * Please see ffa_memory_reclaim_hdlr() description for more details.
+ */
+int ffa_memory_reclaim(struct udevice *dev, u64 g_handle, u32 flags);
+
+/**
+ * ffa_memory_reclaim_hdlr() - FFA_MEM_RECLAIM handler function
+ * @dev: The FF-A bus device
+ * @g_handle: The memory region globally unique Handle
+ * @flags: Zero memory and time slicing flags
+ *
+ * Implement FFA_MEM_RECLAIM FF-A function
+ * to restore exclusive access to a memory region back to its Owner.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_memory_reclaim_hdlr(struct udevice *dev, u64 g_handle, u32 flags);
+
 struct ffa_priv;
 
 /**
diff --git a/include/arm_ffa_priv.h b/include/arm_ffa_priv.h
index a259911d5b9..54196199ce3 100644
--- a/include/arm_ffa_priv.h
+++ b/include/arm_ffa_priv.h
@@ -133,10 +133,11 @@ enum ffa_abis {
 	FFA_MSG_SEND_DIRECT_REQ   = 0x6f,
 	FFA_MSG_SEND_DIRECT_RESP  = 0x70,
 	FFA_MEM_SHARE             = 0x73,
+	FFA_MEM_RECLAIM           = 0x77,
 
 	/* To be updated when adding new FFA IDs */
 	FFA_FIRST_ID              = FFA_ERROR, /* Lowest number ID */
-	FFA_LAST_ID               = FFA_MEM_SHARE, /* Highest number ID */
+	FFA_LAST_ID               = FFA_MEM_RECLAIM, /* Highest number ID */
 };
 
 enum ffa_abi_errcode {
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v4 03/24] arm_ffa: sandbox: Replace the emulator error log with debug log
  2025-07-25 15:49 [PATCH v4 00/24] Introduce Firmware Update Support for Arm PSA abdellatif.elkhlifi
  2025-07-25 15:49 ` [PATCH v4 01/24] arm_ffa: Add FFA_MEM_SHARE support abdellatif.elkhlifi
  2025-07-25 15:49 ` [PATCH v4 02/24] arm_ffa: Add FFA_MEM_RECLAIM support abdellatif.elkhlifi
@ 2025-07-25 15:49 ` abdellatif.elkhlifi
  2025-07-25 15:49 ` [PATCH v4 04/24] arm_ffa: sandbox: Improve the readability of clearing the X registers abdellatif.elkhlifi
                   ` (21 subsequent siblings)
  24 siblings, 0 replies; 29+ messages in thread
From: abdellatif.elkhlifi @ 2025-07-25 15:49 UTC (permalink / raw)
  To: u-boot
  Cc: Abdellatif El Khlifi, Ilias Apalodimas, Tom Rini, Simon Glass,
	Jens Wiklander, Casey Connolly

From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>

Set the log to a debug log and reformulate the message

The message is about showing what the emulated FF-A ABI decided
based on the user arguments. The log is just for information purposes
and helpful when debugging.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Casey Connolly <casey.connolly@linaro.org>
---
 drivers/firmware/arm-ffa/ffa-emul-uclass.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/firmware/arm-ffa/ffa-emul-uclass.c b/drivers/firmware/arm-ffa/ffa-emul-uclass.c
index 1521d9b66ac..d2f051f7e2a 100644
--- a/drivers/firmware/arm-ffa/ffa-emul-uclass.c
+++ b/drivers/firmware/arm-ffa/ffa-emul-uclass.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ * Copyright 2022-2023, 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * Authors:
  *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
@@ -658,8 +658,7 @@ void sandbox_arm_ffa_smccc_smc(ffa_value_t *args, ffa_value_t *res)
 			args->a0);
 	}
 
-	if (ret != 0)
-		log_err("FF-A ABI internal failure (%d)\n", ret);
+	log_debug("Emulated FF-A ABI feedback (%d)\n", ret);
 }
 
 /**
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v4 04/24] arm_ffa: sandbox: Improve the readability of clearing the X registers
  2025-07-25 15:49 [PATCH v4 00/24] Introduce Firmware Update Support for Arm PSA abdellatif.elkhlifi
                   ` (2 preceding siblings ...)
  2025-07-25 15:49 ` [PATCH v4 03/24] arm_ffa: sandbox: Replace the emulator error log with debug log abdellatif.elkhlifi
@ 2025-07-25 15:49 ` abdellatif.elkhlifi
  2025-07-25 15:49 ` [PATCH v4 05/24] arm_ffa: sandbox: Add FFA_MEM_SHARE emulation abdellatif.elkhlifi
                   ` (20 subsequent siblings)
  24 siblings, 0 replies; 29+ messages in thread
From: abdellatif.elkhlifi @ 2025-07-25 15:49 UTC (permalink / raw)
  To: u-boot
  Cc: Abdellatif El Khlifi, Tom Rini, Simon Glass, Ilias Apalodimas,
	Jens Wiklander, Casey Connolly

From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>

Make clearing the must be zero registers more readable in the emulator

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Tom Rini <trini@konsulko.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Casey Connolly <casey.connolly@linaro.org>
---
 .../sandbox/include/asm/sandbox_arm_ffa_priv.h | 17 +++--------------
 drivers/firmware/arm-ffa/ffa-emul-uclass.c     | 18 +++++++++---------
 2 files changed, 12 insertions(+), 23 deletions(-)

diff --git a/arch/sandbox/include/asm/sandbox_arm_ffa_priv.h b/arch/sandbox/include/asm/sandbox_arm_ffa_priv.h
index b0881822d78..8f442145eba 100644
--- a/arch/sandbox/include/asm/sandbox_arm_ffa_priv.h
+++ b/arch/sandbox/include/asm/sandbox_arm_ffa_priv.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0+ */
 /*
- * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ * Copyright 2022-2023, 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * Authors:
  *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
@@ -39,19 +39,8 @@
 #define RXTX_BUFFERS_MIN_SIZE (RXTX_4K)
 #define RXTX_BUFFERS_MIN_PAGES (1)
 
-/* MBZ registers info */
-
-/* x1-x7 MBZ */
-#define FFA_X1X7_MBZ_CNT (7)
-#define FFA_X1X7_MBZ_REG_START (&res->a1)
-
-/* x4-x7 MBZ */
-#define FFA_X4X7_MBZ_CNT (4)
-#define FFA_X4X7_MBZ_REG_START (&res->a4)
-
-/* x3-x7 MBZ */
-#define FFA_X3X7_MBZ_CNT (5)
-#define FFA_X3_MBZ_REG_START (&res->a3)
+/* A helper macro used for clearing registers that Must Be Zero (MBZ) */
+#define FFA_X_REG_SIZE_IN_BYTE sizeof((((ffa_value_t *)0)->a0))
 
 /* number of emulated FF-A secure partitions (SPs) */
 #define SANDBOX_PARTITIONS_CNT (4)
diff --git a/drivers/firmware/arm-ffa/ffa-emul-uclass.c b/drivers/firmware/arm-ffa/ffa-emul-uclass.c
index d2f051f7e2a..dcf5bce9435 100644
--- a/drivers/firmware/arm-ffa/ffa-emul-uclass.c
+++ b/drivers/firmware/arm-ffa/ffa-emul-uclass.c
@@ -83,7 +83,7 @@ static int sandbox_ffa_version(struct udevice *emul, ffa_value_t *pargs, ffa_val
 	res->a0 = priv->fwk_version;
 
 	/* x1-x7 MBZ */
-	memset(FFA_X1X7_MBZ_REG_START, 0, FFA_X1X7_MBZ_CNT * sizeof(ulong));
+	memset(&res->a1, 0, 7 * FFA_X_REG_SIZE_IN_BYTE);
 
 	return 0;
 }
@@ -111,7 +111,7 @@ static int sandbox_ffa_id_get(struct udevice *emul, ffa_value_t *pargs, ffa_valu
 	res->a2 = priv->id;
 
 	/* x3-x7 MBZ */
-	memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong));
+	memset(&res->a3, 0, 5 * FFA_X_REG_SIZE_IN_BYTE);
 
 	return 0;
 }
@@ -136,14 +136,14 @@ static int sandbox_ffa_features(ffa_value_t *pargs, ffa_value_t *res)
 		res->a2 = RXTX_BUFFERS_MIN_SIZE;
 		res->a3 = 0;
 		/* x4-x7 MBZ */
-		memset(FFA_X4X7_MBZ_REG_START, 0, FFA_X4X7_MBZ_CNT * sizeof(ulong));
+		memset(&res->a4, 0, 4 * FFA_X_REG_SIZE_IN_BYTE);
 		return 0;
 	}
 
 	res->a0 = FFA_SMC_32(FFA_ERROR);
 	res->a2 = -NOT_SUPPORTED;
 	/* x3-x7 MBZ */
-	memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong));
+	memset(&res->a3, 0, 5 * FFA_X_REG_SIZE_IN_BYTE);
 	log_err("FF-A interface %lx not implemented\n", pargs->a1);
 
 	return ffa_to_std_errmap[NOT_SUPPORTED];
@@ -248,7 +248,7 @@ cleanup:
 	res->a1 = 0;
 
 	/* x3-x7 MBZ */
-	memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong));
+	memset(&res->a3, 0, 5 * FFA_X_REG_SIZE_IN_BYTE);
 
 	return ret;
 }
@@ -305,7 +305,7 @@ feedback:
 	res->a1 = 0;
 
 	/* x3-x7 MBZ */
-	memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong));
+	memset(&res->a3, 0, 5 * FFA_X_REG_SIZE_IN_BYTE);
 
 	return ret;
 }
@@ -352,7 +352,7 @@ feedback:
 	res->a1 = 0;
 
 	/* x3-x7 MBZ */
-	memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong));
+	memset(&res->a3, 0, 5 * FFA_X_REG_SIZE_IN_BYTE);
 
 	return ret;
 }
@@ -388,7 +388,7 @@ static int sandbox_ffa_rx_release(struct udevice *emul, ffa_value_t *pargs, ffa_
 	res->a1 = 0;
 
 	/* x3-x7 MBZ */
-	memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong));
+	memset(&res->a3, 0, 5 * FFA_X_REG_SIZE_IN_BYTE);
 
 	return ret;
 }
@@ -448,7 +448,7 @@ static int sandbox_ffa_msg_send_direct_req(struct udevice *emul,
 		res->a2 = -INVALID_PARAMETERS;
 
 		/* x3-x7 MBZ */
-		memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong));
+		memset(&res->a3, 0, 5 * FFA_X_REG_SIZE_IN_BYTE);
 
 		return ffa_to_std_errmap[INVALID_PARAMETERS];
 	}
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v4 05/24] arm_ffa: sandbox: Add FFA_MEM_SHARE emulation
  2025-07-25 15:49 [PATCH v4 00/24] Introduce Firmware Update Support for Arm PSA abdellatif.elkhlifi
                   ` (3 preceding siblings ...)
  2025-07-25 15:49 ` [PATCH v4 04/24] arm_ffa: sandbox: Improve the readability of clearing the X registers abdellatif.elkhlifi
@ 2025-07-25 15:49 ` abdellatif.elkhlifi
  2025-07-25 15:49 ` [PATCH v4 06/24] arm_ffa: sandbox: Add FFA_MEM_SHARE tests abdellatif.elkhlifi
                   ` (19 subsequent siblings)
  24 siblings, 0 replies; 29+ messages in thread
From: abdellatif.elkhlifi @ 2025-07-25 15:49 UTC (permalink / raw)
  To: u-boot
  Cc: Abdellatif El Khlifi, Tom Rini, Simon Glass, Ilias Apalodimas,
	Jens Wiklander, Casey Connolly

From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>

Add FFA_MEM_SHARE support to the FF-A emulator

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Tom Rini <trini@konsulko.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Casey Connolly <casey.connolly@linaro.org>
---
 .../include/asm/sandbox_arm_ffa_priv.h        |  4 ++
 drivers/firmware/arm-ffa/ffa-emul-uclass.c    | 43 +++++++++++++++++++
 drivers/firmware/arm-ffa/sandbox_ffa.c        |  3 +-
 3 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/arch/sandbox/include/asm/sandbox_arm_ffa_priv.h b/arch/sandbox/include/asm/sandbox_arm_ffa_priv.h
index 8f442145eba..fa09f9598ee 100644
--- a/arch/sandbox/include/asm/sandbox_arm_ffa_priv.h
+++ b/arch/sandbox/include/asm/sandbox_arm_ffa_priv.h
@@ -38,6 +38,7 @@
 /*  RX/TX buffers minimum size */
 #define RXTX_BUFFERS_MIN_SIZE (RXTX_4K)
 #define RXTX_BUFFERS_MIN_PAGES (1)
+#define RXTX_BUFFERS_MIN_PAGES_SIZE (RXTX_BUFFERS_MIN_PAGES * SZ_4K)
 
 /* A helper macro used for clearing registers that Must Be Zero (MBZ) */
 #define FFA_X_REG_SIZE_IN_BYTE sizeof((((ffa_value_t *)0)->a0))
@@ -59,6 +60,9 @@
 #define SANDBOX_SERVICE2_UUID_A3	0x9cc02d72
 #define SANDBOX_SERVICE2_UUID_A4	0xcdd998a7
 
+/* Globally unique Handle to identify the shared memory region */
+#define SANDBOX_MEM_HANDLE		0xffffffff
+
 /**
  * struct ffa_rxtxpair_info - structure hosting the RX/TX buffers flags
  * @rxbuf_owned:	RX buffer ownership flag (the owner is non secure world)
diff --git a/drivers/firmware/arm-ffa/ffa-emul-uclass.c b/drivers/firmware/arm-ffa/ffa-emul-uclass.c
index dcf5bce9435..4918404fb6d 100644
--- a/drivers/firmware/arm-ffa/ffa-emul-uclass.c
+++ b/drivers/firmware/arm-ffa/ffa-emul-uclass.c
@@ -563,6 +563,46 @@ static int sandbox_ffa_get_parts(struct udevice *emul, struct ffa_sandbox_data *
 	return 0;
 }
 
+/**
+ * sandbox_ffa_memory_share() - Emulated FFA_MEM_SHARE handler
+ * @emul: The sandbox FF-A emulator device
+ * @pargs: The SMC call input arguments a0-a7
+ * @res:  The SMC return data
+ *
+ * Emulate FFA_MEM_SHARE FF-A function.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int sandbox_ffa_memory_share(struct udevice *emul, ffa_value_t *pargs,
+				    ffa_value_t *res)
+{
+	int ret;
+
+	res->a1 = 0;
+
+	if (!pargs->a1 || pargs->a1 > RXTX_BUFFERS_MIN_PAGES_SIZE) {
+		/* FFA_ERROR encoding */
+		res->a0 = FFA_SMC_32(FFA_ERROR);
+		res->a2 = -INVALID_PARAMETERS;
+		ret = ffa_to_std_errmap[INVALID_PARAMETERS];
+		/* x3-x7 MBZ */
+		memset(&res->a3, 0, 5 * FFA_X_REG_SIZE_IN_BYTE);
+
+		return ret;
+	}
+
+	/* FFA_SUCCESS encoding */
+	res->a0 = FFA_SMC_32(FFA_SUCCESS);
+	res->a2 = SANDBOX_MEM_HANDLE;
+	res->a3 = SANDBOX_MEM_HANDLE;
+	/* x4-x7 MBZ */
+	memset(&res->a4, 0, 4 * FFA_X_REG_SIZE_IN_BYTE);
+
+	return 0;
+}
+
 /**
  * sandbox_query_ffa_emul_state() - Inspect the FF-A ABIs
  * @queried_func_id:	The FF-A function to be queried
@@ -653,6 +693,9 @@ void sandbox_arm_ffa_smccc_smc(ffa_value_t *args, ffa_value_t *res)
 	case FFA_SMC_32(FFA_RX_RELEASE):
 		ret = sandbox_ffa_rx_release(emul, args, res);
 		break;
+	case FFA_SMC_32(FFA_MEM_SHARE):
+		ret = sandbox_ffa_memory_share(emul, args, res);
+		break;
 	default:
 		log_err("Undefined FF-A interface (%lx)\n",
 			args->a0);
diff --git a/drivers/firmware/arm-ffa/sandbox_ffa.c b/drivers/firmware/arm-ffa/sandbox_ffa.c
index 44b32a829dd..8d85e660e2b 100644
--- a/drivers/firmware/arm-ffa/sandbox_ffa.c
+++ b/drivers/firmware/arm-ffa/sandbox_ffa.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ * Copyright 2022-2023, 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * Authors:
  *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
@@ -91,6 +91,7 @@ static const struct ffa_bus_ops sandbox_ffa_ops = {
 	.partition_info_get = ffa_get_partitions_info_hdlr,
 	.sync_send_receive = ffa_msg_send_direct_req_hdlr,
 	.rxtx_unmap = ffa_unmap_rxtx_buffers_hdlr,
+	.memory_share = ffa_memory_share_hdlr,
 };
 
 static const struct udevice_id sandbox_ffa_id[] = {
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v4 06/24] arm_ffa: sandbox: Add FFA_MEM_SHARE tests
  2025-07-25 15:49 [PATCH v4 00/24] Introduce Firmware Update Support for Arm PSA abdellatif.elkhlifi
                   ` (4 preceding siblings ...)
  2025-07-25 15:49 ` [PATCH v4 05/24] arm_ffa: sandbox: Add FFA_MEM_SHARE emulation abdellatif.elkhlifi
@ 2025-07-25 15:49 ` abdellatif.elkhlifi
  2025-07-25 15:49 ` [PATCH v4 07/24] arm_ffa: sandbox: Add FFA_MEM_RECLAIM emulation abdellatif.elkhlifi
                   ` (18 subsequent siblings)
  24 siblings, 0 replies; 29+ messages in thread
From: abdellatif.elkhlifi @ 2025-07-25 15:49 UTC (permalink / raw)
  To: u-boot; +Cc: Abdellatif El Khlifi, Simon Glass, Tom Rini, Mattijs Korpershoek

From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>

Add positive and negative test cases

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Mattijs Korpershoek <mkorpershoek@kernel.org>
---
 test/dm/ffa.c | 46 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 45 insertions(+), 1 deletion(-)

diff --git a/test/dm/ffa.c b/test/dm/ffa.c
index 593b7177fce..59eea9a57cc 100644
--- a/test/dm/ffa.c
+++ b/test/dm/ffa.c
@@ -2,7 +2,7 @@
 /*
  * Functional tests for UCLASS_FFA  class
  *
- * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ * Copyright 2022-2023, 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * Authors:
  *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
@@ -13,6 +13,7 @@
 #include <asm/sandbox_arm_ffa.h>
 #include <asm/sandbox_arm_ffa_priv.h>
 #include <dm/test.h>
+#include <linux/sizes.h>
 #include <test/test.h>
 #include <test/ut.h>
 
@@ -141,6 +142,43 @@ static int test_partitions_and_comms(const char *service_uuid,
 	return 0;
 }
 
+static int  test_ffa_memory_share(bool test_ack, struct unit_test_state *uts)
+{
+	struct ffa_mem_ops_args args = {0};
+	struct ffa_mem_region_attributes attrs = {0};
+	static u8 buf[SZ_4K];
+	int ret;
+	struct udevice *dev;
+
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	args.attrs = &attrs;
+	args.nattrs = 1;
+	args.address = buf;
+	args.pg_cnt = 1;
+
+	if (test_ack) {
+		args.use_txbuf = true;
+
+		ut_assertok(ffa_memory_share(dev, &args));
+		ut_asserteq(HANDLE_LOW(args.g_handle), SANDBOX_MEM_HANDLE);
+		ut_asserteq(HANDLE_HIGH(args.g_handle), SANDBOX_MEM_HANDLE);
+	} else {
+		/* Do not use the TX buffer as a transaction buffer */
+		args.use_txbuf = false;
+		ret = ffa_memory_share(dev, &args);
+		ut_asserteq(-EPROTONOSUPPORT, ret);
+
+		/* No memory region address given */
+		args.use_txbuf = true;
+		args.address = NULL;
+		ret = ffa_memory_share(dev, &args);
+		ut_asserteq(-EINVAL, ret);
+	}
+
+	return 0;
+}
+
 static int dm_test_ffa_ack(struct unit_test_state *uts)
 {
 	struct ffa_priv *uc_priv;
@@ -195,6 +233,9 @@ static int dm_test_ffa_ack(struct unit_test_state *uts)
 	ut_assertok(sandbox_query_ffa_emul_state(FFA_RX_RELEASE, &func_data));
 	check_rxbuf_release_flag(rxbuf_flag, uts);
 
+	/* Test FFA_MEM_SHARE */
+	test_ffa_memory_share(true, uts);
+
 	return 0;
 }
 DM_TEST(dm_test_ffa_ack, UTF_SCAN_FDT | UTF_CONSOLE);
@@ -253,6 +294,9 @@ static int dm_test_ffa_nack(struct unit_test_state *uts)
 	part_id = uc_priv->partitions.descs[0].info.id;
 	ut_assertok(ffa_sync_send_receive(dev, part_id, &msg, 1));
 
+	/* Test FFA_MEM_SHARE */
+	test_ffa_memory_share(false, uts);
+
 	return 0;
 }
 DM_TEST(dm_test_ffa_nack, UTF_SCAN_FDT | UTF_CONSOLE);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v4 07/24] arm_ffa: sandbox: Add FFA_MEM_RECLAIM emulation
  2025-07-25 15:49 [PATCH v4 00/24] Introduce Firmware Update Support for Arm PSA abdellatif.elkhlifi
                   ` (5 preceding siblings ...)
  2025-07-25 15:49 ` [PATCH v4 06/24] arm_ffa: sandbox: Add FFA_MEM_SHARE tests abdellatif.elkhlifi
@ 2025-07-25 15:49 ` abdellatif.elkhlifi
  2025-07-25 15:49 ` [PATCH v4 08/24] arm_ffa: sandbox: Add FFA_MEM_RECLAIM tests abdellatif.elkhlifi
                   ` (17 subsequent siblings)
  24 siblings, 0 replies; 29+ messages in thread
From: abdellatif.elkhlifi @ 2025-07-25 15:49 UTC (permalink / raw)
  To: u-boot
  Cc: Abdellatif El Khlifi, Tom Rini, Simon Glass, Ilias Apalodimas,
	Jens Wiklander, Casey Connolly

From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>

Add FFA_MEM_RECLAIM support to the FF-A emulator

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Tom Rini <trini@konsulko.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Casey Connolly <casey.connolly@linaro.org>
---
 drivers/firmware/arm-ffa/ffa-emul-uclass.c | 42 ++++++++++++++++++++++
 drivers/firmware/arm-ffa/sandbox_ffa.c     |  1 +
 2 files changed, 43 insertions(+)

diff --git a/drivers/firmware/arm-ffa/ffa-emul-uclass.c b/drivers/firmware/arm-ffa/ffa-emul-uclass.c
index 4918404fb6d..a630392b6d1 100644
--- a/drivers/firmware/arm-ffa/ffa-emul-uclass.c
+++ b/drivers/firmware/arm-ffa/ffa-emul-uclass.c
@@ -603,6 +603,45 @@ static int sandbox_ffa_memory_share(struct udevice *emul, ffa_value_t *pargs,
 	return 0;
 }
 
+/**
+ * sandbox_ffa_memory_reclaim() - Emulated FFA_MEM_RECLAIM handler
+ * @emul: The sandbox FF-A emulator device
+ * @pargs: The SMC call input arguments a0-a7
+ * @res:  The SMC return data
+ *
+ * Emulate FFA_MEM_RECLAIM FF-A function.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int sandbox_ffa_memory_reclaim(struct udevice *emul, ffa_value_t *pargs,
+				      ffa_value_t *res)
+{
+	int ret;
+
+	res->a1 = 0;
+
+	if (pargs->a1 != SANDBOX_MEM_HANDLE ||
+	    pargs->a2 != SANDBOX_MEM_HANDLE) {
+		/* FFA_ERROR encoding */
+		res->a0 = FFA_SMC_32(FFA_ERROR);
+		res->a2 = -INVALID_PARAMETERS;
+		ret = ffa_to_std_errmap[INVALID_PARAMETERS];
+		/* x3-x7 MBZ */
+		memset(&res->a3, 0, 5 * FFA_X_REG_SIZE_IN_BYTE);
+
+		return ret;
+	}
+
+	/* FFA_SUCCESS encoding */
+	res->a0 = FFA_SMC_32(FFA_SUCCESS);
+	/* x2-x7 MBZ */
+	memset(&res->a2, 0, 6 * FFA_X_REG_SIZE_IN_BYTE);
+
+	return 0;
+}
+
 /**
  * sandbox_query_ffa_emul_state() - Inspect the FF-A ABIs
  * @queried_func_id:	The FF-A function to be queried
@@ -696,6 +735,9 @@ void sandbox_arm_ffa_smccc_smc(ffa_value_t *args, ffa_value_t *res)
 	case FFA_SMC_32(FFA_MEM_SHARE):
 		ret = sandbox_ffa_memory_share(emul, args, res);
 		break;
+	case FFA_SMC_32(FFA_MEM_RECLAIM):
+		ret = sandbox_ffa_memory_reclaim(emul, args, res);
+		break;
 	default:
 		log_err("Undefined FF-A interface (%lx)\n",
 			args->a0);
diff --git a/drivers/firmware/arm-ffa/sandbox_ffa.c b/drivers/firmware/arm-ffa/sandbox_ffa.c
index 8d85e660e2b..54c81d12f92 100644
--- a/drivers/firmware/arm-ffa/sandbox_ffa.c
+++ b/drivers/firmware/arm-ffa/sandbox_ffa.c
@@ -92,6 +92,7 @@ static const struct ffa_bus_ops sandbox_ffa_ops = {
 	.sync_send_receive = ffa_msg_send_direct_req_hdlr,
 	.rxtx_unmap = ffa_unmap_rxtx_buffers_hdlr,
 	.memory_share = ffa_memory_share_hdlr,
+	.memory_reclaim = ffa_memory_reclaim_hdlr,
 };
 
 static const struct udevice_id sandbox_ffa_id[] = {
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v4 08/24] arm_ffa: sandbox: Add FFA_MEM_RECLAIM tests
  2025-07-25 15:49 [PATCH v4 00/24] Introduce Firmware Update Support for Arm PSA abdellatif.elkhlifi
                   ` (6 preceding siblings ...)
  2025-07-25 15:49 ` [PATCH v4 07/24] arm_ffa: sandbox: Add FFA_MEM_RECLAIM emulation abdellatif.elkhlifi
@ 2025-07-25 15:49 ` abdellatif.elkhlifi
  2025-07-25 15:49 ` [PATCH v4 09/24] fwu_arm_psa: Initialize the update agent abdellatif.elkhlifi
                   ` (16 subsequent siblings)
  24 siblings, 0 replies; 29+ messages in thread
From: abdellatif.elkhlifi @ 2025-07-25 15:49 UTC (permalink / raw)
  To: u-boot; +Cc: Abdellatif El Khlifi, Tom Rini, Simon Glass, Mattijs Korpershoek

From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>

Add FFA_MEM_RECLAIM positive and negative test cases

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Tom Rini <trini@konsulko.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Mattijs Korpershoek <mkorpershoek@kernel.org>
---
 test/dm/ffa.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/test/dm/ffa.c b/test/dm/ffa.c
index 59eea9a57cc..f4a6716cfd8 100644
--- a/test/dm/ffa.c
+++ b/test/dm/ffa.c
@@ -179,6 +179,27 @@ static int  test_ffa_memory_share(bool test_ack, struct unit_test_state *uts)
 	return 0;
 }
 
+static int  test_ffa_memory_reclaim(bool test_ack, struct unit_test_state *uts)
+{
+	int ret;
+	u64 g_handle;
+	struct udevice *dev;
+
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	if (test_ack) {
+		g_handle = PACK_HANDLE(SANDBOX_MEM_HANDLE, SANDBOX_MEM_HANDLE);
+		ut_assertok(ffa_memory_reclaim(dev, g_handle, 0));
+	} else {
+		/* Provide a wrong handle */
+		g_handle = PACK_HANDLE(SANDBOX_MEM_HANDLE, 0);
+		ret = ffa_memory_reclaim(dev, g_handle, 0);
+		ut_asserteq(-EINVAL, ret);
+	}
+
+	return 0;
+}
+
 static int dm_test_ffa_ack(struct unit_test_state *uts)
 {
 	struct ffa_priv *uc_priv;
@@ -236,6 +257,9 @@ static int dm_test_ffa_ack(struct unit_test_state *uts)
 	/* Test FFA_MEM_SHARE */
 	test_ffa_memory_share(true, uts);
 
+	/* Test FFA_MEM_RECLAIM */
+	test_ffa_memory_reclaim(true, uts);
+
 	return 0;
 }
 DM_TEST(dm_test_ffa_ack, UTF_SCAN_FDT | UTF_CONSOLE);
@@ -297,6 +321,9 @@ static int dm_test_ffa_nack(struct unit_test_state *uts)
 	/* Test FFA_MEM_SHARE */
 	test_ffa_memory_share(false, uts);
 
+	/* Test FFA_MEM_RECLAIM */
+	test_ffa_memory_reclaim(false, uts);
+
 	return 0;
 }
 DM_TEST(dm_test_ffa_nack, UTF_SCAN_FDT | UTF_CONSOLE);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v4 09/24] fwu_arm_psa: Initialize the update agent
  2025-07-25 15:49 [PATCH v4 00/24] Introduce Firmware Update Support for Arm PSA abdellatif.elkhlifi
                   ` (7 preceding siblings ...)
  2025-07-25 15:49 ` [PATCH v4 08/24] arm_ffa: sandbox: Add FFA_MEM_RECLAIM tests abdellatif.elkhlifi
@ 2025-07-25 15:49 ` abdellatif.elkhlifi
  2025-07-25 15:49 ` [PATCH v4 10/24] fwu_arm_psa: Read the FWU directory through get_image_info() abdellatif.elkhlifi
                   ` (15 subsequent siblings)
  24 siblings, 0 replies; 29+ messages in thread
From: abdellatif.elkhlifi @ 2025-07-25 15:49 UTC (permalink / raw)
  To: u-boot
  Cc: Abdellatif El Khlifi, Davidson kumaresan, Sughosh Ganu, Tom Rini,
	Ilias Apalodimas, Simon Glass, Michal Simek, Marek Vasut,
	Casey Connolly

From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>

Add the initializations required for the update agent

The aim is adding support for the Trusted Services (aka TS)
Firmware Update API. This API allows the interaction with
the FWU services provided by Secure world.
At U-Boot level, we provide the PSA FWU ABI built on top of the
FF-A bus to invoke the FWU services in Secure world.

The design is based on the Platform Security Firmware Update
for the A-profile Arm Architecture specification [1].

In our design, the Secure world is the update agent. U-Boot
is the update client.

The update agent is initialized as follows:

- Trusted Services FWU SP discovery
- Setting up the shared buffer between the Normal world (U-Boot) and
  Secure world (Trusted Services)
- Notifying FWU SP about the shared buffer

[1]: DEN0118, 1.0 A:
    https://developer.arm.com/documentation/den0118/latest/

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Signed-off-by: Davidson kumaresan <davidson.kumaresan@arm.com>
Cc: Sughosh Ganu <sughosh.ganu@linaro.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Simon Glass <sjg@chromium.org>
Cc: Michal Simek <michal.simek@amd.com>
Cc: Marek Vasut <marek.vasut+renesas@mailbox.org>
Cc: Casey Connolly <casey.connolly@linaro.org>

---

Changelog of changes:
===========================

v4:

* Update the function headers in fwu_arm_psa.c to pass kernel-doc tests

v1:

* Add the feature

 MAINTAINERS                   |   7 +
 include/fwu_arm_psa.h         |  58 ++++++++
 lib/fwu_updates/Kconfig       |  18 +++
 lib/fwu_updates/Makefile      |   2 +
 lib/fwu_updates/fwu_arm_psa.c | 263 ++++++++++++++++++++++++++++++++++
 5 files changed, 348 insertions(+)
 create mode 100644 include/fwu_arm_psa.h
 create mode 100644 lib/fwu_updates/fwu_arm_psa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 92119667618..fdf34c74049 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1227,6 +1227,13 @@ T:	git https://source.denx.de/u-boot/custodians/u-boot-fsl-qoriq.git
 F:	drivers/watchdog/sp805_wdt.c
 F:	drivers/watchdog/sbsa_gwdt.c
 
+FWU ARM PSA
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+M:	Davidson kumaresan <davidson.kumaresan@arm.com>
+S:	Maintained
+F:	include/fwu_arm_psa.h
+F:	lib/fwu_updates/fwu_arm_psa.c
+
 FWU Multi Bank Update
 M:	Sughosh Ganu <sughosh.ganu@linaro.org>
 S:	Maintained
diff --git a/include/fwu_arm_psa.h b/include/fwu_arm_psa.h
new file mode 100644
index 00000000000..f1d42f9ef24
--- /dev/null
+++ b/include/fwu_arm_psa.h
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ *   Davidson kumaresan <davidson.kumaresan@arm.com>
+ */
+
+#ifndef __FWU_ARM_PSA_H
+#define __FWU_ARM_PSA_H
+
+#include <linux/bitfield.h>
+#include <u-boot/uuid.h>
+
+#define FWU_BUFFER_PAGES		(1024)
+
+/* 4 MB buffer shared with secure world */
+#define FWU_BUFFER_SIZE			(FWU_BUFFER_PAGES * EFI_PAGE_SIZE)
+
+/* TS UUID string for detecting all SPs  (in big-endian format) */
+#define ALL_TS_SP_UUID			"d776cdbd-5e82-5147-3b96-ac4349f8d486"
+/* In little-endian equivalent to: bdcd76d7-825e-4751-963b-86d4f84943ac */
+
+/* TS FWU service UUID string (in big-endian format) */
+#define TS_FWU_SERVICE_UUID		"38a82368-061b-0e47-7497-fd53fb8bce0c"
+/* In little-endian equivalent to:  6823a838-1b06-470e-9774-0cce8bfb53fd */
+
+#define TS_RPC_MEM_RETRIEVE		(0xff0001)
+#define TS_RPC_SERVICE_INFO_GET		(0xff0003)
+#define RPC_SUCCESS			(0)
+
+#define SVC_IFACE_ID_GET_MASK		GENMASK(7, 0)
+#define GET_SVC_IFACE_ID(x)		\
+			 ((u8)(FIELD_GET(SVC_IFACE_ID_GET_MASK, (x))))
+
+#define HANDLE_MSW_MASK			GENMASK(63, 32)
+#define HANDLE_LSW_MASK			GENMASK(31, 0)
+#define GET_FWU_BUF_MSW(x)		\
+				((u32)(FIELD_GET(HANDLE_MSW_MASK, (x))))
+#define GET_FWU_BUF_LSW(x)		\
+				((u32)(FIELD_GET(HANDLE_LSW_MASK, (x))))
+
+/**
+ * fwu_agent_init() - Setup the FWU agent
+ *
+ * Perform the initializations required to communicate
+ * and use the FWU agent in secure world.
+ * The frontend of the FWU agent is the Trusted Services (aka TS)
+ * FWU SP (aka Secure Partition).
+ *
+ * Return:
+ *
+ * 0 is returned on success. Otherwise, failure
+ */
+int fwu_agent_init(void);
+
+#endif
diff --git a/lib/fwu_updates/Kconfig b/lib/fwu_updates/Kconfig
index a722107c129..cdc96109f0a 100644
--- a/lib/fwu_updates/Kconfig
+++ b/lib/fwu_updates/Kconfig
@@ -46,4 +46,22 @@ config FWU_MDATA_V2
 	  metadata structure. This option enables support for FWU
 	  Metadata version 2 access.
 
+config FWU_ARM_PSA
+	bool "FMP driver for Arm PSA FWU specification"
+	depends on EFI_CAPSULE_FIRMWARE_MANAGEMENT && \
+		EFI_CAPSULE_FIRMWARE_RAW && \
+		ARM_FFA_TRANSPORT && (ARM64 || SANDBOX)
+	select EFI_CAPSULE_FIRMWARE
+	help
+	  Select this option if you want to enable firmware management protocol
+	  driver that supports the Arm PSA firmware update specification as
+	  mentioned in https://developer.arm.com/documentation/den0118/a/
+
+config FWU_BUFFER_PAGES
+	int "Number of 4KB pages in the FWU shared buffer"
+	depends on FWU_ARM_PSA
+	default 1024
+	help
+	  This defines the size of the FWU shared buffer used for communication.
+
 endif
diff --git a/lib/fwu_updates/Makefile b/lib/fwu_updates/Makefile
index 3681bef46cd..ae8e4b27793 100644
--- a/lib/fwu_updates/Makefile
+++ b/lib/fwu_updates/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-or-later
 #
 # Copyright (c) 2022, Linaro Limited
+# Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
 #
 
 obj-$(CONFIG_FWU_MULTI_BANK_UPDATE) += fwu.o
@@ -8,3 +9,4 @@ obj-$(CONFIG_FWU_MDATA_GPT_BLK) += fwu_gpt.o
 obj-$(CONFIG_FWU_MDATA_MTD) += fwu_mtd.o
 obj-$(CONFIG_FWU_MDATA_V1) += fwu_v1.o
 obj-$(CONFIG_FWU_MDATA_V2) += fwu_v2.o
+obj-$(CONFIG_FWU_ARM_PSA) += fwu_arm_psa.o
diff --git a/lib/fwu_updates/fwu_arm_psa.c b/lib/fwu_updates/fwu_arm_psa.c
new file mode 100644
index 00000000000..32cc4b5b637
--- /dev/null
+++ b/lib/fwu_updates/fwu_arm_psa.c
@@ -0,0 +1,263 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ *   Davidson kumaresan <davidson.kumaresan@arm.com>
+ */
+#include <arm_ffa.h>
+#include <dm.h>
+#include <fwu_arm_psa.h>
+#include <efi_loader.h>
+#include <fwu.h>
+#include <log.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <linux/errno.h>
+
+static void *g_fwu_buf;
+static u64 g_fwu_buf_handle;
+static u16 g_fwu_sp_id;
+static struct udevice *g_dev;
+static u16 g_svc_interface_id;
+static bool g_fwu_initialized;
+
+/**
+ * fwu_discover_ts_sp_id() - Query the FWU partition ID
+ *
+ * Description: Use the FF-A driver to get the FWU partition ID.
+ * If multiple partitions are found, use the first one.
+ *
+ * Return: 0 is returned on success. Otherwise, failure.
+ */
+static int fwu_discover_ts_sp_id(void)
+{
+	u32 count = 0;
+	int ret;
+	u32 i;
+	struct ffa_partition_desc *descs = NULL;
+	struct ffa_send_direct_data msg;
+	struct ffa_partition_uuid fwu_service_uuid = {0};
+
+	/* Ask the driver to fill the buffer with the SPs info */
+
+	ret = ffa_partition_info_get(g_dev, ALL_TS_SP_UUID, &count, &descs);
+	if (ret) {
+		log_err("FWU: Failure in querying partitions (err: %d)\n", ret);
+		return ret;
+	}
+
+	if (!count) {
+		log_err("FWU: No Trusted Service partition found\n");
+		return -ENODATA;
+	}
+
+	if (!descs) {
+		log_err("FWU: No partitions descriptors filled\n");
+		return -EINVAL;
+	}
+
+	if (uuid_str_to_le_bin(TS_FWU_SERVICE_UUID,
+			       (unsigned char *)&fwu_service_uuid)) {
+		log_err("FWU: invalid FWU SP  UUID\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < count ; i++) {
+		log_debug("FWU: Enquiring service from SP 0x%x\n",
+			  descs[i].info.id);
+
+		msg.data0 = TS_RPC_SERVICE_INFO_GET;
+		msg.data1 = fwu_service_uuid.a1;
+		msg.data2 = fwu_service_uuid.a2;
+		msg.data3 = fwu_service_uuid.a3;
+		msg.data4 = fwu_service_uuid.a4;
+
+		ret = ffa_sync_send_receive(g_dev, descs[i].info.id, &msg, 0);
+		if (ret) {
+			log_err("FWU: FF-A error for SERVICE_INFO_GET (err: %d)\n",
+				ret);
+			return ret;
+		}
+
+		if (msg.data0 != TS_RPC_SERVICE_INFO_GET) {
+			log_err("FWU: Wrong SERVICE_INFO_GET return: (%lx)\n",
+				msg.data0);
+			continue;
+		}
+
+		if (msg.data1 == RPC_SUCCESS) {
+			g_svc_interface_id = GET_SVC_IFACE_ID(msg.data2);
+			g_fwu_sp_id = descs[i].info.id;
+			log_debug("FWU: Service interface ID 0x%x found\n",
+				  g_svc_interface_id);
+			return 0;
+		}
+
+		log_debug("FWU: service not found\n");
+	}
+
+	log_err("FWU: No SP provides the service\n");
+
+	return -ENOENT;
+}
+
+/**
+ * fwu_shared_buf_reclaim() - Reclaim the shared communication buffer
+ *
+ * Description: In case of errors, this function can be called to retrieve
+ * the FWU shared buffer.
+ *
+ * Return: 0 is returned on success. Otherwise, failure.
+ */
+static int fwu_shared_buf_reclaim(void)
+{
+	int reclaim_ret;
+
+	reclaim_ret = ffa_memory_reclaim(g_dev, g_fwu_buf_handle, 0);
+	if (reclaim_ret)
+		log_err("FWU: FF-A memory reclaim failure (err: %d)\n",
+			reclaim_ret);
+	else
+		log_debug("FWU: Shared buffer reclaimed\n");
+
+	free(g_fwu_buf);
+	g_fwu_buf = NULL;
+
+	return reclaim_ret;
+}
+
+/**
+ * fwu_shared_buf_init() - Setup the FWU shared communication buffer
+ *
+ * Description: The communication with the TS FWU SP is based on a buffer shared
+ * between U-Boot and TS FWU SP allocated in normal world and accessed
+ * by both sides. The buffer contains the data exchanged between both sides
+ * such as the payloads data.
+ *
+ * Return: 0 is returned on success. Otherwise, failure.
+ */
+static int fwu_shared_buf_init(void)
+{
+	struct ffa_mem_ops_args args = {0};
+	struct ffa_mem_region_attributes attrs = {0};
+	struct ffa_send_direct_data msg;
+	int ret;
+
+	g_fwu_buf = memalign(EFI_PAGE_SIZE, FWU_BUFFER_SIZE);
+	if (!g_fwu_buf) {
+		log_err("FWU: Failure to allocate the shared buffer\n");
+		return -ENOMEM;
+	}
+
+	/* Setting up user arguments */
+	args.use_txbuf = true;
+	args.address = g_fwu_buf;
+	args.pg_cnt = FWU_BUFFER_PAGES;
+	args.nattrs = 1;
+	attrs.receiver = g_fwu_sp_id;
+	attrs.attrs = FFA_MEM_RW;
+	args.attrs = &attrs;
+
+	/* Registering the shared buffer with secure world (Trusted Services) */
+	ret = ffa_memory_share(g_dev, &args);
+	if (ret) {
+		free(g_fwu_buf);
+		g_fwu_buf = NULL;
+		log_err("FWU: Failure setting up the shared buffer (err: %d)\n",
+			ret);
+		return ret;
+	}
+
+	g_fwu_buf_handle = args.g_handle;
+
+	log_debug("FWU: shared buffer handle 0x%llx\n", g_fwu_buf_handle);
+
+	/* Inform the FWU SP know about the shared buffer */
+
+	msg.data0 = TS_RPC_MEM_RETRIEVE;
+	msg.data1 = GET_FWU_BUF_LSW(g_fwu_buf_handle);
+	msg.data2 = GET_FWU_BUF_MSW(g_fwu_buf_handle);
+
+	ret = ffa_sync_send_receive(g_dev, g_fwu_sp_id, &msg, 0);
+	if (ret) {
+		log_err("FWU: FF-A message error for MEM_RETRIEVE (err: %d)\n",
+			ret);
+		goto failure;
+	}
+
+	if (msg.data0 != TS_RPC_MEM_RETRIEVE) {
+		log_err("FWU: Unexpected MEM_RETRIEVE return: (%lx)\n",
+			msg.data0);
+		ret = -EINVAL;
+		goto failure;
+	}
+
+	if (msg.data1 != RPC_SUCCESS) {
+		log_err("FWU: MEM_RETRIEVE failed\n");
+		ret = -EOPNOTSUPP;
+		goto failure;
+	}
+
+	log_debug("FWU: MEM_RETRIEVE success for SP 0x%x\n", g_fwu_sp_id);
+
+	return 0;
+
+failure:
+	fwu_shared_buf_reclaim();
+	return ret;
+}
+
+/**
+ * fwu_agent_init() - Setup the FWU agent
+ *
+ * Description: Perform the initializations required to communicate
+ * and use the FWU agent in secure world.
+ * The frontend of the FWU agent is the Trusted Services (aka TS)
+ * FWU SP (aka Secure Partition).
+ *
+ * Return: 0 is returned on success. Otherwise, failure.
+ */
+int fwu_agent_init(void)
+{
+	int ret;
+	struct fwu_data *fwu_data;
+	u32 active_idx;
+
+	fwu_data = fwu_get_data();
+	if (!fwu_data) {
+		log_err("FWU: Cannot get FWU data\n");
+		return -EINVAL;
+	}
+
+	ret = fwu_get_active_index(&active_idx);
+	if (ret) {
+		log_err("FWU: Failed to read boot index, err (%d)\n",
+			ret);
+		return ret;
+	}
+
+	if (fwu_data->trial_state)
+		log_info("FWU: System booting in Trial State\n");
+	else
+		log_info("FWU: System booting in Regular State\n");
+
+	ret = uclass_first_device_err(UCLASS_FFA, &g_dev);
+	if (ret) {
+		log_err("FWU: Cannot find FF-A bus device, err (%d)\n", ret);
+		return ret;
+	}
+
+	ret = fwu_discover_ts_sp_id();
+	if (ret)
+		return ret;
+
+	ret = fwu_shared_buf_init();
+	if (ret)
+		return ret;
+
+	g_fwu_initialized = true;
+
+	return 0;
+}
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v4 10/24] fwu_arm_psa: Read the FWU directory through get_image_info()
  2025-07-25 15:49 [PATCH v4 00/24] Introduce Firmware Update Support for Arm PSA abdellatif.elkhlifi
                   ` (8 preceding siblings ...)
  2025-07-25 15:49 ` [PATCH v4 09/24] fwu_arm_psa: Initialize the update agent abdellatif.elkhlifi
@ 2025-07-25 15:49 ` abdellatif.elkhlifi
  2025-07-25 15:49 ` [PATCH v4 11/24] fwu_arm_psa: Add staging ABIs abdellatif.elkhlifi
                   ` (14 subsequent siblings)
  24 siblings, 0 replies; 29+ messages in thread
From: abdellatif.elkhlifi @ 2025-07-25 15:49 UTC (permalink / raw)
  To: u-boot
  Cc: Abdellatif El Khlifi, Davidson kumaresan, Sughosh Ganu, Tom Rini,
	Ilias Apalodimas, Simon Glass, Michal Simek, Marek Vasut,
	Casey Connolly

From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>

Implement get_image_info()

get_image_info() is implemented by fwu_arm_psa_get_image_info()
which reads the images information from the cached directory in Secure
world then populates the images descriptors.

The FWU Arm PSA setup ABIs have been implemented to allow
reading the directory data.

The ABIs are specified by the Platform Security Firmware Update for
the A-profile Arm Architecture specification [1].

For more details about PSA please see [2].

The implemented ABIs are as follows:

FWU_DISCOVER
FWU_OPEN
FWU_READ_STREAM
FWU_COMMIT

[1]: DEN0118, 1.0 A:
    https://developer.arm.com/documentation/den0118/latest/
[2]: https://www.psacertified.org/

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Signed-off-by: Davidson kumaresan <davidson.kumaresan@arm.com>
Cc: Sughosh Ganu <sughosh.ganu@linaro.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Simon Glass <sjg@chromium.org>
Cc: Michal Simek <michal.simek@amd.com>
Cc: Marek Vasut <marek.vasut+renesas@mailbox.org>
Cc: Casey Connolly <casey.connolly@linaro.org>

---

Changelog of changes:
===========================

v4:

* Update the function headers in fwu_arm_psa.c to pass kernel-doc tests

v2:

* As suggested by Michal: Add /** for marking kernel-doc format

v1:

* Implement get_image_info()

 include/fwu_arm_psa.h         | 206 ++++++++++++
 lib/fwu_updates/fwu_arm_psa.c | 570 +++++++++++++++++++++++++++++++++-
 2 files changed, 775 insertions(+), 1 deletion(-)

diff --git a/include/fwu_arm_psa.h b/include/fwu_arm_psa.h
index f1d42f9ef24..6cbda23f581 100644
--- a/include/fwu_arm_psa.h
+++ b/include/fwu_arm_psa.h
@@ -10,9 +10,16 @@
 #ifndef __FWU_ARM_PSA_H
 #define __FWU_ARM_PSA_H
 
+#include <efi_loader.h>
 #include <linux/bitfield.h>
 #include <u-boot/uuid.h>
 
+#define DEFAULT_HW_INSTANCE		(1)
+
+/* Default values of the ESRT fields which are not supported at this stage */
+#define PACKAGE_VERSION_NOT_SUP		(0xffffffff)
+#define LAST_ATTEMPT_NOT_SUP		(0)
+
 #define FWU_BUFFER_PAGES		(1024)
 
 /* 4 MB buffer shared with secure world */
@@ -26,6 +33,13 @@
 #define TS_FWU_SERVICE_UUID		"38a82368-061b-0e47-7497-fd53fb8bce0c"
 /* In little-endian equivalent to:  6823a838-1b06-470e-9774-0cce8bfb53fd */
 
+/* TS FWU directory UUID string (in big-endian format) */
+#define FWU_DIRECTORY_CANONICAL_UUID	"d958eede-4751-d34a-90a2-a541236e6677"
+/* In little-endian equivalent to:  deee58d9-5147-4ad3-a290-77666e2341a5 */
+
+/* The entries correspond to the payloads in the storage device and the fake ESRT image */
+#define FWU_DIRECTORY_IMAGE_ENTRIES_COUNT (CONFIG_FWU_NUM_IMAGES_PER_BANK + 1)
+
 #define TS_RPC_MEM_RETRIEVE		(0xff0001)
 #define TS_RPC_SERVICE_INFO_GET		(0xff0003)
 #define RPC_SUCCESS			(0)
@@ -34,6 +48,11 @@
 #define GET_SVC_IFACE_ID(x)		\
 			 ((u8)(FIELD_GET(SVC_IFACE_ID_GET_MASK, (x))))
 
+#define SVC_ID_MASK			GENMASK(15, 0)
+#define SVC_IFACE_ID_SET_MASK		GENMASK(23, 16)
+#define PACK_SVC_IFACE_ID(svc, iface)	(FIELD_PREP(SVC_ID_MASK, (svc)) | \
+					FIELD_PREP(SVC_IFACE_ID_SET_MASK, (iface)))
+
 #define HANDLE_MSW_MASK			GENMASK(63, 32)
 #define HANDLE_LSW_MASK			GENMASK(31, 0)
 #define GET_FWU_BUF_MSW(x)		\
@@ -41,6 +60,174 @@
 #define GET_FWU_BUF_LSW(x)		\
 				((u32)(FIELD_GET(HANDLE_LSW_MASK, (x))))
 
+enum fwu_abis {
+	FWU_DISCOVER = 0,
+	FWU_OPEN = 19,
+	FWU_READ_STREAM = 21,
+	FWU_COMMIT = 22,
+	/* To be updated when adding new FWU IDs */
+	FWU_FIRST_ID = FWU_DISCOVER, /* Lowest number ID */
+	FWU_LAST_ID = FWU_COMMIT, /* Highest number ID */
+};
+
+enum fwu_abi_errcode {
+	FWU_UNKNOWN = 1,
+	FWU_BUSY,
+	FWU_OUT_OF_BOUNDS,
+	FWU_AUTH_FAIL,
+	FWU_NO_PERMISSION,
+	FWU_DENIED,
+	FWU_RESUME,
+	FWU_NOT_AVAILABLE,
+	MAX_NUMBER_FWU_ERR
+};
+
+/* Container structure and helper macros to map between an FF-A error and relevant error log */
+struct fwu_abi_errmap {
+	char *err_str[MAX_NUMBER_FWU_ERR];
+};
+
+#define FWU_ERRMAP_COUNT (FWU_LAST_ID - FWU_FIRST_ID + 1)
+#define FWU_ID_TO_ERRMAP_ID(fwu_id) ((fwu_id) - FWU_FIRST_ID)
+
+/**
+ * struct fwu_open_args - fwu_open ABI arguments
+ * @function_id: fwu_open service ID
+ * @image_type_guid: GUID of the image to be opened
+ * @op_type: The operation that the Client will perform on the image
+ */
+struct __packed fwu_open_args {
+	u32 function_id;
+	efi_guid_t image_type_guid;
+#define FWU_OP_TYPE_READ 0
+#define FWU_OP_TYPE_WRITE 1
+	u8  op_type;
+};
+
+/**
+ * struct fwu_open_resp - fwu_open ABI returns
+ * @status: The ABI return status
+ * @handle: Staging context identifier
+ */
+struct __packed fwu_open_resp {
+	int status;
+	u32  handle;
+};
+
+/**
+ * struct fwu_discover_args - fwu_discover ABI arguments
+ * @function_id: fwu_discover service ID
+ */
+struct __packed fwu_discover_args {
+	u32 function_id;
+};
+
+/**
+ * struct fwu_discover_resp - fwu_discover ABI returns
+ * @status: The ABI return status
+ * @service_status: the status of the service provider
+ * @version_major: the ABI major version
+ * @version_minor: the ABI minor version
+ * @off_function_presence: the offset (in bytes) of the function_presence array
+ *                         relative to the start of this data structure
+ * @num_func: the number of entries in the function_presence array
+ * @max_payload_size: the maximum number of bytes that a payload can contain
+ * @flags: flags listing the update capabilities
+ * @vendor_specific_flags: Vendor specific update capabilities flags
+ * @function_presence: array of bytes indicating functions that are implemented
+ */
+struct __packed fwu_discover_resp {
+	int status;
+	u16 service_status;
+	u8 version_major;
+	u8 version_minor;
+	u16 off_function_presence;
+	u16 num_func;
+	u64 max_payload_size;
+	u32 flags;
+	u32 vendor_specific_flags;
+	void *function_presence;
+};
+
+/**
+ * struct fwu_read_stream_args - fwu_read_stream ABI arguments
+ * @function_id: fwu_read_stream service ID
+ * @handle: The handle of the context being read from
+ */
+struct __packed fwu_read_stream_args {
+	u32 function_id;
+	u32  handle;
+};
+
+/**
+ * struct fwu_read_stream_resp - fwu_read_stream ABI returns
+ * @status: The ABI return status
+ * @read_bytes: Number of bytes read by the current ABI call
+ * @total_bytes: Total number of bytes that can be read
+ * @payload: The read data by the current ABI call
+ */
+struct __packed fwu_read_stream_resp {
+	int status;
+	u32  read_bytes;
+	u32  total_bytes;
+	u8  payload[];
+};
+
+/**
+ * struct fwu_commit_args - fwu_commit ABI arguments
+ * @function_id: fwu_commit service ID
+ * @handle: The handle of the context being closed
+ * @acceptance_req: If positive, the Client requests the image to be marked as
+ *                  unaccepted
+ * @max_atomic_len: Hint, maximum time (in ns) that the Update Agent can execute
+ *                  continuously without yielding back to the Client state
+ */
+struct __packed fwu_commit_args {
+	u32 function_id;
+	u32 handle;
+#define FWU_IMG_ACCEPTED 0
+#define FWU_IMG_NOT_ACCEPTED 1
+	u32 acceptance_req;
+	u32 max_atomic_len;
+};
+
+/**
+ * struct fwu_commit_resp - fwu_commit ABI returns
+ * @status: The ABI return status
+ * @progress: Units of work already completed by the Update Agent
+ * @total_work: Units of work the Update Agent must perform until fwu_commit
+ *              returns successfully
+ */
+struct __packed fwu_commit_resp {
+	int status;
+	u32 progress;
+	u32 total_work;
+};
+
+/*
+ * FWU directory information structures
+ */
+
+struct __packed fwu_image_info_entry {
+	efi_guid_t image_guid;
+	u32 client_permissions;
+	u32 img_max_size;
+	u32 lowest_acceptable_version;
+	u32 img_version;
+	u32 accepted;
+	u32 reserved;
+};
+
+struct __packed fwu_image_directory {
+	u32 directory_version;
+	u32 img_info_offset;
+	u32 num_images;
+	u32 correct_boot;
+	u32 img_info_size;
+	u32 reserved;
+	struct fwu_image_info_entry entries[FWU_DIRECTORY_IMAGE_ENTRIES_COUNT];
+};
+
 /**
  * fwu_agent_init() - Setup the FWU agent
  *
@@ -55,4 +242,23 @@
  */
 int fwu_agent_init(void);
 
+/**
+ * fwu_arm_psa_get_image_info() - Arm PSA implementation for GetImageInfo()
+ *
+ * Initialize the update agent in secure world if not initialized.
+ * Then, read the FWU directory information including the current
+ * images information. For more details refer to fwu_image_directory structure.
+ *
+ * Return:
+ *
+ * EFI_SUCCESS is returned on success. Otherwise, failure
+ */
+efi_status_t fwu_arm_psa_get_image_info(efi_uintn_t *image_info_size,
+					struct efi_firmware_image_descriptor *image_info,
+					u32 *descriptor_version,
+					u8 *descriptor_count,
+					efi_uintn_t *descriptor_size,
+					u32 *package_version,
+					u16 **package_version_name);
+
 #endif
diff --git a/lib/fwu_updates/fwu_arm_psa.c b/lib/fwu_updates/fwu_arm_psa.c
index 32cc4b5b637..75d19a69872 100644
--- a/lib/fwu_updates/fwu_arm_psa.c
+++ b/lib/fwu_updates/fwu_arm_psa.c
@@ -9,7 +9,6 @@
 #include <arm_ffa.h>
 #include <dm.h>
 #include <fwu_arm_psa.h>
-#include <efi_loader.h>
 #include <fwu.h>
 #include <log.h>
 #include <malloc.h>
@@ -21,7 +20,465 @@ static u64 g_fwu_buf_handle;
 static u16 g_fwu_sp_id;
 static struct udevice *g_dev;
 static u16 g_svc_interface_id;
+static u64 g_max_payload_size;
+static u8 g_fwu_version_major;
+static u8 g_fwu_version_minor;
 static bool g_fwu_initialized;
+struct fwu_image_directory g_fwu_cached_directory;
+
+/* Error mapping declarations */
+
+int fwu_to_std_errmap[MAX_NUMBER_FWU_ERR] = {
+	[FWU_UNKNOWN] = -EOPNOTSUPP,
+	[FWU_OUT_OF_BOUNDS] = -ERANGE,
+	[FWU_AUTH_FAIL] = -EFAULT,
+	[FWU_BUSY] = -EBUSY,
+	[FWU_NO_PERMISSION] = -EPERM,
+	[FWU_DENIED] = -EACCES,
+	[FWU_RESUME] = -EAGAIN,
+	[FWU_NOT_AVAILABLE] = -ENAVAIL,
+};
+
+static struct fwu_abi_errmap err_msg_map[FWU_ERRMAP_COUNT] = {
+	[FWU_ID_TO_ERRMAP_ID(FWU_OPEN)] = {
+		{
+			[FWU_UNKNOWN] =
+			"FWU_UNKNOWN: Image type with GUID=image_type_guid does not exist",
+			[FWU_DENIED] =
+			"FWU_DENIED: An image cannot be opened for writing outside of this Staging state",
+			[FWU_NOT_AVAILABLE] =
+			"FWU_NOT_AVAILABLE: The Update Agent does not support the op_type for this image",
+		},
+	},
+	[FWU_ID_TO_ERRMAP_ID(FWU_READ_STREAM)] = {
+		{
+			[FWU_UNKNOWN] =
+			"FWU_UNKNOWN: Handle is not recognized",
+			[FWU_DENIED] =
+			"FWU_DENIED: The image cannot be temporarily read from",
+			[FWU_NO_PERMISSION] =
+			"FWU_NO_PERMISSION: The image cannot be read from",
+		},
+	},
+	[FWU_ID_TO_ERRMAP_ID(FWU_COMMIT)] = {
+		{
+			[FWU_UNKNOWN] =
+			"FWU_UNKNOWN: Handle is not recognized",
+			[FWU_DENIED] =
+			"FWU_DENIED: The image can only be accepted after activation",
+			[FWU_AUTH_FAIL] =
+			"FWU_AUTH_FAIL: Image closed, authentication failed",
+			[FWU_RESUME] =
+			"FWU_RESUME: The Update Agent yielded",
+		},
+	},
+};
+
+/**
+ * fwu_to_std_errno() - convert FWU error code to standard error code
+ * @fwu_errno:	Error code returned by the FWU ABI
+ *
+ * Description: Map the given FWU error code as specified
+ * by the spec to a U-Boot standard error code.
+ *
+ * Return: The standard error code on success. . Otherwise, failure.
+ */
+static int fwu_to_std_errno(int fwu_errno)
+{
+	int err_idx = -fwu_errno;
+
+	/* Map the FWU error code to the standard u-boot error code */
+	if (err_idx > 0 && err_idx < MAX_NUMBER_FWU_ERR)
+		return fwu_to_std_errmap[err_idx];
+	return -EINVAL;
+}
+
+/**
+ * fwu_print_error_log() - print the error log of the selected FWU ABI
+ * @fwu_id:	FWU ABI ID
+ * @fwu_errno:	Error code returned by the FWU ABI
+ *
+ * Description: Map the FWU error code to the error log relevant to the
+ * selected FWU ABI. Then the error log is printed.
+ *
+ * Return: 0 on success. Otherwise, failure.
+ */
+static int fwu_print_error_log(u32 fwu_id, int fwu_errno)
+{
+	int err_idx = -fwu_errno, abi_idx = 0;
+
+	/* Map the FWU error code to the corresponding error log */
+
+	if (err_idx <= 0 || err_idx >= MAX_NUMBER_FWU_ERR)
+		return -EINVAL;
+
+	if (fwu_id < FWU_FIRST_ID || fwu_id > FWU_LAST_ID)
+		return -EINVAL;
+
+	abi_idx = FWU_ID_TO_ERRMAP_ID(fwu_id);
+
+	if (!err_msg_map[abi_idx].err_str[err_idx])
+		return -EINVAL;
+
+	log_err("%s\n", err_msg_map[abi_idx].err_str[err_idx]);
+
+	return 0;
+}
+
+/**
+ * fwu_invoke_svc() - FWU service call request
+ * @svc_id: FWU ABI function ID
+ * @svc_name: FWU ABI function name
+ * @req_args_sz: Size in bytes of the arguments of the FWU ABI function
+ * @expect_resp_sz: Size in bytes of the response of the FWU ABI function
+ * @extra_resp_bytes: Size in bytes of the extra response data
+ *
+ * Description: Invoke a FWU ABI by issuing a TS service call request.
+ *
+ * Return: 0 on success. Otherwise, failure.
+ */
+static int fwu_invoke_svc(u32 svc_id, const char *svc_name,
+			  u32 req_args_sz, u32 expect_resp_sz,
+			  u32 *extra_resp_bytes)
+{
+	struct ffa_send_direct_data msg;
+	int ret;
+	int *svc_status_in_buf = g_fwu_buf, svc_status_in_reg;
+	u32 expect_total_resp_sz;
+
+	log_debug("FWU: Invoking %s\n", svc_name);
+
+	if (!expect_resp_sz || !svc_name || !req_args_sz) {
+		log_err("%s: Invalid invoke arguments\n", svc_name);
+		return -EINVAL;
+	}
+
+	msg.data0 = PACK_SVC_IFACE_ID(svc_id, g_svc_interface_id);
+	msg.data1 = GET_FWU_BUF_LSW(g_fwu_buf_handle);
+	msg.data2 = GET_FWU_BUF_MSW(g_fwu_buf_handle);
+	msg.data3 = req_args_sz;
+	msg.data4 = 0;
+
+	ret = ffa_sync_send_receive(g_dev, g_fwu_sp_id, &msg, 0);
+	if (ret) {
+		log_err("%s: FF-A error %d\n", svc_name, ret);
+		return ret;
+	}
+
+	if (msg.data0 != PACK_SVC_IFACE_ID(svc_id, g_svc_interface_id)) {
+		log_err("%s: Unexpected service/interface ID 0x%lx\n",
+			svc_name, msg.data0);
+		return -EINVAL;
+	}
+
+	if (msg.data1 != RPC_SUCCESS) {
+		log_err("%s: TS RPC error 0x%lx\n", svc_name, msg.data1);
+		return -ECOMM;
+	}
+
+	svc_status_in_reg = (int)msg.data2;
+	if (*svc_status_in_buf != svc_status_in_reg) {
+		log_err("%s: Status mismatch (reg %d , buf %d)\n",
+			svc_name, svc_status_in_reg, *svc_status_in_buf);
+		return -EINVAL;
+	}
+
+	if (svc_status_in_reg < 0) {
+		fwu_print_error_log(svc_id, svc_status_in_reg);
+		if (svc_status_in_reg != -FWU_RESUME)
+			return fwu_to_std_errno(svc_status_in_reg);
+	}
+
+	if (!extra_resp_bytes)
+		expect_total_resp_sz = expect_resp_sz;
+	else
+		expect_total_resp_sz = expect_resp_sz + *extra_resp_bytes;
+
+	if (msg.data3 != expect_total_resp_sz) {
+		log_err("%s: Unexpected response size (%ld , %d)\n",
+			svc_name, msg.data3, expect_total_resp_sz);
+		return -EINVAL;
+	}
+
+	if (svc_status_in_reg == -FWU_RESUME)
+		return fwu_to_std_errno(svc_status_in_reg);
+
+	return 0;
+}
+
+/**
+ * fwu_discover() -  fwu_discover ABI
+ *
+ * Description: This call indicates the version of the ABI alongside a list of
+ * the implemented functions (aka services).
+ * Only max_payload_size is saved for future use.
+ *
+ * Return: 0 on success. Otherwise, failure.
+ */
+static int fwu_discover(void)
+{
+	int ret;
+	struct fwu_discover_args *args = g_fwu_buf;
+	struct fwu_discover_resp *resp = g_fwu_buf;
+	char *svc_name = "FWU_DISCOVER";
+
+	/* Filling the arguments in the shared buffer */
+	args->function_id = FWU_DISCOVER;
+
+	/* Executing the FWU ABI through the FF-A bus */
+	ret = fwu_invoke_svc(args->function_id, svc_name, sizeof(*args),
+			     sizeof(int), NULL);
+	if (ret) {
+		log_debug("FWU_DISCOVER: error %d\n", ret);
+		return ret;
+	}
+
+	g_max_payload_size = resp->max_payload_size;
+	g_fwu_version_major = resp->version_major;
+	g_fwu_version_minor = resp->version_minor;
+
+	log_debug("FWU: max_payload_size %llu\n", g_max_payload_size);
+	log_info("FWU: ABI version %d.%d detected\n", g_fwu_version_major,
+		 g_fwu_version_minor);
+
+	return 0;
+}
+
+/**
+ * fwu_open() -  fwu_open ABI
+ * @guid: GUID of the image to be opened
+ * @op_type: The operation that the Client will perform on the image
+ * @handle: Staging context identifier
+ *
+ * Description: Returns a handle to the image with a given GUID.
+ *
+ * Return: 0 on success. Otherwise, failure.
+ */
+static int fwu_open(const efi_guid_t *guid, u8  op_type,
+		    u32 *handle)
+{
+	int ret;
+	struct fwu_open_args *args = g_fwu_buf;
+	struct fwu_open_resp *resp = g_fwu_buf;
+	char *svc_name = "FWU_OPEN";
+
+	if (!guid || !handle)
+		return -EINVAL;
+
+	/* Filling the arguments in the shared buffer */
+	args->function_id = FWU_OPEN;
+
+	guidcpy(&args->image_type_guid, guid);
+	args->op_type = op_type;
+
+	/* Executing the FWU ABI through the FF-A bus */
+	ret = fwu_invoke_svc(args->function_id, svc_name,
+			     sizeof(*args), sizeof(*resp), NULL);
+	if (ret)
+		return ret;
+
+	*handle = resp->handle;
+
+	return 0;
+}
+
+/**
+ * fwu_read_stream() -  fwu_read_stream ABI
+ * @handle: The handle of the context being read from
+ * @buffer: The destination buffer where the data will be copied to
+ * @buffer_size: The size of the destination buffer
+ *
+ * Description: The call reads at most g_max_payload_size bytes from the Update
+ * Agent context pointed to by handle.
+ *
+ * Return: 0 on success. Otherwise, failure.
+ */
+static int fwu_read_stream(u32 handle, u8 *buffer, u32 buffer_size)
+{
+	int ret;
+	u32 curr_read_offset = 0, new_read_offset, fwu_buf_bytes_left;
+	struct fwu_read_stream_args *args = g_fwu_buf;
+	struct fwu_read_stream_resp *resp = g_fwu_buf;
+	char *svc_name = "FWU_READ_STREAM";
+
+	if (!buffer || !buffer_size)
+		return -EINVAL;
+
+	do {
+		/* Filling the arguments in the shared buffer */
+		args->function_id = FWU_READ_STREAM;
+		args->handle = handle;
+
+		/* Executing the FWU ABI through the FF-A bus */
+		ret = fwu_invoke_svc(args->function_id, svc_name, sizeof(*args),
+				     sizeof(*resp), &resp->read_bytes);
+		if (ret)
+			return ret;
+
+		if (resp->read_bytes > g_max_payload_size) {
+			log_err("%s: Bytes read > max_payload_size (%d , %llu)\n",
+				svc_name, resp->read_bytes,
+				g_max_payload_size);
+			return -EINVAL;
+		}
+
+		fwu_buf_bytes_left = FWU_BUFFER_SIZE - sizeof(*resp);
+
+		if (resp->read_bytes > fwu_buf_bytes_left) {
+			log_err("%s: Bytes read > shared buffer (%d , %d)\n",
+				svc_name, resp->read_bytes, fwu_buf_bytes_left);
+			return -EINVAL;
+		}
+
+		if (resp->total_bytes > buffer_size) {
+			log_err("%s: Total bytes > dest buffer (%d , %d)\n",
+				svc_name, resp->total_bytes, buffer_size);
+			return -EINVAL;
+		}
+
+		new_read_offset = resp->read_bytes + curr_read_offset;
+
+		if (new_read_offset > buffer_size) {
+			log_err("%s: Bytes read > dest buffer (%d , %d)\n",
+				svc_name, new_read_offset, buffer_size);
+			return -EINVAL;
+		}
+
+		memcpy(buffer + curr_read_offset, resp->payload,
+		       resp->read_bytes);
+
+		curr_read_offset = new_read_offset;
+
+		if (curr_read_offset > resp->total_bytes) {
+			log_err("%s: Offset bypassed total bytes (%d , %d)\n",
+				svc_name, curr_read_offset, resp->total_bytes);
+			return -EINVAL;
+		}
+
+	} while (curr_read_offset != resp->total_bytes);
+
+	return ret;
+}
+
+/**
+ * fwu_commit() -  fwu_commit ABI
+ * @handle: The handle of the context being closed
+ * @acceptance_req: Acceptance status set by the Client
+ * @max_atomic_len: Hint, maximum time (in ns) that the Update Agent can execute
+ *                  continuously without yielding back to the Client state
+ *
+ * Description: The call closes the image pointed to by handle. The image can be
+ * any entity opened with fwu_open().
+ *
+ * Return: 0 on success. Otherwise, failure.
+ */
+static int fwu_commit(u32 handle, u32 acceptance_req, u32 max_atomic_len)
+{
+	struct fwu_commit_args *args = g_fwu_buf;
+	struct fwu_commit_resp *resp = g_fwu_buf;
+	char *svc_name = "FWU_COMMIT";
+	int ret;
+
+	/* Filling the arguments in the shared buffer */
+	args->function_id = FWU_COMMIT;
+	args->handle = handle;
+	args->acceptance_req = acceptance_req;
+	args->max_atomic_len = max_atomic_len;
+
+	/* Executing the FWU ABI through the FF-A bus */
+	ret = fwu_invoke_svc(args->function_id, svc_name,
+			     sizeof(*args), sizeof(*resp), NULL);
+
+	while (resp->status == -FWU_RESUME)
+		ret = fwu_invoke_svc(args->function_id, svc_name, sizeof(*args),
+				     sizeof(*resp), NULL);
+
+	if (ret)
+		return ret;
+
+	log_debug("%s:  Progress %d/%d\n", svc_name, resp->progress,
+		  resp->total_work);
+
+	return 0;
+}
+
+/**
+ * fwu_read_directory() - Read FWU directory information
+ *
+ * Description: Read FWU directory information.
+ * For more details see fwu_image_directory structure.
+ *
+ * Return: 0 on success. Otherwise, failure.
+ */
+static int fwu_read_directory(void)
+{
+	int ret, close_ret;
+	u32 handle = 0;
+	efi_guid_t dir_guid = {0};
+	char *uuid_str = FWU_DIRECTORY_CANONICAL_UUID;
+
+	if (!uuid_str) {
+		log_err("FWU: No directory UUID provided\n");
+		return -EINVAL;
+	}
+
+	if (uuid_str_to_le_bin(uuid_str, dir_guid.b)) {
+		log_err("FWU: Invalid directory UUID\n");
+		return -EINVAL;
+	}
+
+	ret = fwu_open(&dir_guid, FWU_OP_TYPE_READ, &handle);
+	if (ret) {
+		log_err("FWU: Open image directory failed (err: %d)\n",
+			ret);
+		return ret;
+	}
+
+	log_debug("FWU: Image directory handle (0x%x)\n", handle);
+
+	ret = fwu_read_stream(handle, (u8 *)&g_fwu_cached_directory,
+			      sizeof(g_fwu_cached_directory));
+	if (ret) {
+		log_err("FWU: Read image directory failed (err: %d)\n",
+			ret);
+		goto close_handle;
+	}
+
+	log_debug("FWU: directory_version (%d)\n",
+		  g_fwu_cached_directory.directory_version);
+
+	/*
+	 * Note: The expected images in the directory are:
+	 * - The images to be updated
+	 * - The ESRT image (an image containing ESRT data)
+	 * The ESRT image is not involved in the FWU.
+	 * It should be removed from the count.
+	 */
+	g_fwu_cached_directory.num_images -= 1;
+
+	if (g_fwu_cached_directory.num_images !=
+	    CONFIG_FWU_NUM_IMAGES_PER_BANK) {
+		log_err("FWU: Unexpected image count (%d , %d)\n",
+			g_fwu_cached_directory.num_images,
+			CONFIG_FWU_NUM_IMAGES_PER_BANK);
+		ret = -EINVAL;
+		goto close_handle;
+	}
+
+	log_debug("FWU: images to be updated (%d)\n",
+		  g_fwu_cached_directory.num_images);
+	log_debug("FWU: img_info_size (%d)\n",
+		  g_fwu_cached_directory.img_info_size);
+
+close_handle:
+	/* The Update Agent can execute for an unbounded time */
+	close_ret = fwu_commit(handle, FWU_IMG_NOT_ACCEPTED, 0);
+	if (close_ret)
+		log_err("FWU: Close image directory handle failed (err: %d)\n",
+			close_ret);
+
+	return ret;
+}
 
 /**
  * fwu_discover_ts_sp_id() - Query the FWU partition ID
@@ -257,7 +714,118 @@ int fwu_agent_init(void)
 	if (ret)
 		return ret;
 
+	ret = fwu_discover();
+	if (ret)
+		goto failure;
+
 	g_fwu_initialized = true;
 
 	return 0;
+
+failure:
+	fwu_shared_buf_reclaim();
+	return ret;
+}
+
+/**
+ * fwu_arm_psa_get_image_info() - Arm PSA implementation for GetImageInfo()
+ *
+ * @image_info_size:		Size of @image_info
+ * @image_info:			Image information
+ * @descriptor_version:		Pointer to version number
+ * @descriptor_count:		Pointer to number of descriptors
+ * @descriptor_size:		Pointer to descriptor size
+ * @package_version:		Package version
+ * @package_version_name:	Package version's name
+ *
+ * Description: Initialize the update agent in secure world if not initialized.
+ * Then, read the FWU directory information including the current
+ * images information. For more details refer to fwu_image_directory structure.
+ *
+ * Return: EFI_SUCCESS is returned on success. Otherwise, failure.
+ */
+efi_status_t fwu_arm_psa_get_image_info(efi_uintn_t *image_info_size,
+					struct efi_firmware_image_descriptor *image_info,
+					u32 *descriptor_version,
+					u8 *descriptor_count,
+					efi_uintn_t *descriptor_size,
+					u32 *package_version,
+					u16 **package_version_name)
+{
+	int ret;
+	int required_image_info_size;
+	size_t image_info_desc_size = sizeof(*image_info);
+
+	if (!g_fwu_initialized) {
+		ret = fwu_agent_init();
+		if (ret) {
+			log_err("FWU: Update agent init failed, ret = %d\n",
+				ret);
+			return EFI_EXIT(EFI_DEVICE_ERROR);
+		}
+	}
+
+	ret = fwu_read_directory();
+	if (ret)
+		return EFI_NOT_READY;
+
+	required_image_info_size = g_fwu_cached_directory.num_images *
+		image_info_desc_size;
+
+	if (*image_info_size < required_image_info_size) {
+		*image_info_size = required_image_info_size;
+		return EFI_BUFFER_TOO_SMALL;
+	}
+
+	*descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;
+	*descriptor_count = g_fwu_cached_directory.num_images;
+	*descriptor_size = image_info_desc_size;
+	*package_version = PACKAGE_VERSION_NOT_SUP; /* Not supported */
+	*package_version_name = NULL; /* Not supported */
+
+	for (int i = 0; i < g_fwu_cached_directory.num_images; i++) {
+		/* Only image indexes starting from 1 are supported */
+		image_info[i].image_index = i + 1;
+
+		/* Corresponding ESRT field: FwClass */
+		guidcpy(&image_info[i].image_type_id,
+			&g_fwu_cached_directory.entries[i].image_guid);
+
+		image_info[i].image_id = image_info[i].image_index;
+		image_info[i].image_id_name = NULL; /* Not supported */
+
+		/* Corresponding ESRT field: FwVersion */
+		image_info[i].version =
+			g_fwu_cached_directory.entries[i].img_version;
+
+		image_info[i].version_name = NULL; /* Not supported */
+		image_info[i].size =
+			g_fwu_cached_directory.entries[i].img_max_size;
+
+		image_info[i].attributes_supported =
+			IMAGE_ATTRIBUTE_IMAGE_UPDATABLE |
+			IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED;
+		image_info[i].attributes_setting =
+				IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;
+
+		/* Check if the capsule authentication is enabled */
+		if (IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE))
+			image_info[i].attributes_setting |=
+				IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED;
+
+		/* Corresponding ESRT field: LowestSupportedFwVersion */
+		image_info[i].lowest_supported_image_version =
+			g_fwu_cached_directory.entries[i].lowest_acceptable_version;
+
+		/* Corresponding ESRT field: LastAttemptVersion (not supported) */
+		image_info[i].last_attempt_version = LAST_ATTEMPT_NOT_SUP;
+
+		/* Corresponding ESRT field: LastAttemptStatus (not supported) */
+		image_info[i].last_attempt_status = LAST_ATTEMPT_NOT_SUP;
+
+		image_info[i].hardware_instance = DEFAULT_HW_INSTANCE;
+		image_info[i].dependencies = NULL; /* Not supported */
+	}
+
+	return EFI_SUCCESS;
 }
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v4 11/24] fwu_arm_psa: Add staging ABIs
  2025-07-25 15:49 [PATCH v4 00/24] Introduce Firmware Update Support for Arm PSA abdellatif.elkhlifi
                   ` (9 preceding siblings ...)
  2025-07-25 15:49 ` [PATCH v4 10/24] fwu_arm_psa: Read the FWU directory through get_image_info() abdellatif.elkhlifi
@ 2025-07-25 15:49 ` abdellatif.elkhlifi
  2025-07-25 15:49 ` [PATCH v4 12/24] efi_loader: fwu_arm_psa: Add set_image and get_image_info support abdellatif.elkhlifi
                   ` (13 subsequent siblings)
  24 siblings, 0 replies; 29+ messages in thread
From: abdellatif.elkhlifi @ 2025-07-25 15:49 UTC (permalink / raw)
  To: u-boot
  Cc: Abdellatif El Khlifi, Davidson kumaresan, Heinrich Schuchardt,
	Ilias Apalodimas, Tom Rini, Simon Glass, Adriano Cordova,
	Sughosh Ganu, Michal Simek

From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>

Implement the ABIs and logic for updating images

The staging process defined by the Platform Security Firmware
Update for the A-profile Arm Architecture specification [1] is
executed through the staging ABIs.

The capsule should contain at least 3 payloads (2 dummy payloads
to indicate the start and the end of the staging process.
In addition, one or multiple payloads to write in the storage device).

The implemented ABIs are as follows:

FWU_BEGIN_STAGING
FWU_END_STAGING
FWU_CANCEL_STAGING
FWU_WRITE_STREAM

[1]: DEN0118, 1.0 A:
    https://developer.arm.com/documentation/den0118/latest/

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Signed-off-by: Davidson kumaresan <davidson.kumaresan@arm.com>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Adriano Cordova <adrianox@gmail.com>
Cc: Sughosh Ganu <sughosh.ganu@linaro.org>
Cc: Michal Simek <michal.simek@amd.com>

---

Changelog of changes:
===========================

v4:

* Update the function headers in fwu_arm_psa.c to pass kernel-doc tests

v2:

* As suggested by Michal: Add /** for marking kernel-doc format

v1:

* Add staging ABIs

 include/efi_api.h             |   8 +
 include/efi_loader.h          |   8 +
 include/fwu_arm_psa.h         | 130 +++++++++++++
 lib/efi_loader/efi_capsule.c  |  23 ++-
 lib/fwu_updates/fwu_arm_psa.c | 356 ++++++++++++++++++++++++++++++++++
 5 files changed, 523 insertions(+), 2 deletions(-)

diff --git a/include/efi_api.h b/include/efi_api.h
index eb61eafa028..cd19ec5e22c 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -10,6 +10,11 @@
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  *	Stephane Eranian <eranian@hpl.hp.com>
  *
+ * Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Author:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ *
  * From include/linux/efi.h in kernel 4.1 with some additions/subtractions
  */
 
@@ -25,6 +30,9 @@
  */
 #define EFI_SPECIFICATION_VERSION (2 << 16 | 110)
 
+#define EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_VERSION 0x00000001
+#define EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_VERSION 0x00000003
+
 /* Types and defines for EFI CreateEvent */
 enum efi_timer_delay {
 	EFI_TIMER_STOP = 0,
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 8fd09aad2d0..3ad1d84a113 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -3,6 +3,11 @@
  *  EFI application loader
  *
  *  Copyright (c) 2016 Alexander Graf
+ *
+ * Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Author:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _EFI_LOADER_H
@@ -392,6 +397,9 @@ extern const efi_guid_t smbios3_guid;
 extern const efi_guid_t efi_guid_text_input_protocol;
 extern const efi_guid_t efi_guid_text_output_protocol;
 
+/*The current processed capsule */
+extern struct efi_capsule_header *g_capsule_data;
+
 /**
  * struct efi_open_protocol_info_item - open protocol info item
  *
diff --git a/include/fwu_arm_psa.h b/include/fwu_arm_psa.h
index 6cbda23f581..00c78ba7e7c 100644
--- a/include/fwu_arm_psa.h
+++ b/include/fwu_arm_psa.h
@@ -40,6 +40,21 @@
 /* The entries correspond to the payloads in the storage device and the fake ESRT image */
 #define FWU_DIRECTORY_IMAGE_ENTRIES_COUNT (CONFIG_FWU_NUM_IMAGES_PER_BANK + 1)
 
+/*
+ * GUIDs for dummy payloads
+ *
+ * The GUIDs are generated with the UUIDv5 format.
+ * Namespace: 7b5c472e-5671-4fb7-a824-36a8e86f05c1
+ * Names: DUMMY_START, DUMMY_END
+ */
+#define FWU_DUMMY_START_IMAGE_GUID \
+	EFI_GUID(0x6f784cbf, 0x7938, 0x5c23, 0x8d, 0x6e, \
+		0x24, 0xd2, 0xf1, 0x41, 0x0f, 0xa9)
+
+#define FWU_DUMMY_END_IMAGE_GUID \
+	EFI_GUID(0xb57e432b, 0xa250, 0x5c73, 0x93, 0xe3, \
+		0x90, 0x20, 0x5e, 0x64, 0xba, 0xba)
+
 #define TS_RPC_MEM_RETRIEVE		(0xff0001)
 #define TS_RPC_SERVICE_INFO_GET		(0xff0003)
 #define RPC_SUCCESS			(0)
@@ -62,7 +77,11 @@
 
 enum fwu_abis {
 	FWU_DISCOVER = 0,
+	FWU_BEGIN_STAGING = 16,
+	FWU_END_STAGING = 17,
+	FWU_CANCEL_STAGING = 18,
 	FWU_OPEN = 19,
+	FWU_WRITE_STREAM = 20,
 	FWU_READ_STREAM = 21,
 	FWU_COMMIT = 22,
 	/* To be updated when adding new FWU IDs */
@@ -82,6 +101,14 @@ enum fwu_abi_errcode {
 	MAX_NUMBER_FWU_ERR
 };
 
+/* Enum to classify the possible type of payloads */
+typedef enum {
+	FWU_PAYLOAD_TYPE_REAL = 1,
+	FWU_PAYLOAD_TYPE_DUMMY_START,
+	FWU_PAYLOAD_TYPE_DUMMY_END,
+	FWU_PAYLOAD_TYPE_INVALID,
+} fwu_payload_type;
+
 /* Container structure and helper macros to map between an FF-A error and relevant error log */
 struct fwu_abi_errmap {
 	char *err_str[MAX_NUMBER_FWU_ERR];
@@ -173,6 +200,64 @@ struct __packed fwu_read_stream_resp {
 	u8  payload[];
 };
 
+/**
+ * struct fwu_begin_staging_args - fwu_begin_staging ABI arguments
+ * @function_id: fwu_begin_staging service ID
+ * @reserved: Reserved, must be zero
+ * @vendor_flags: Vendor specific staging flags
+ * @partial_update_count: The number of elements in the update_guid
+array
+ * @update_guid: An array of image type GUIDs that the update Client will update
+ *               during the Staging state
+ */
+struct __packed fwu_begin_staging_args {
+	u32 function_id;
+	u32 reserved;
+	u32 vendor_flags;
+	u32 partial_update_count;
+	efi_guid_t update_guid[];
+};
+
+/**
+ * struct fwu_begin_staging_resp - fwu_begin_staging ABI returns
+ * @status: The ABI return status
+ */
+struct __packed fwu_begin_staging_resp {
+	int status;
+};
+
+/**
+ * struct fwu_end_staging_args - fwu_end_staging ABI arguments
+ * @function_id: fwu_end_staging service ID state
+ */
+struct __packed fwu_end_staging_args {
+	u32 function_id;
+};
+
+/**
+ * struct fwu_end_staging_resp - fwu_end_staging ABI returns
+ * @status: The ABI return status
+ */
+struct __packed fwu_end_staging_resp {
+	int status;
+};
+
+/**
+ * struct fwu_cancel_staging_args - fwu_cancel_staging ABI arguments
+ * @function_id: fwu_cancel_staging service ID state
+ */
+struct __packed fwu_cancel_staging_args {
+	u32 function_id;
+};
+
+/**
+ * struct fwu_cancel_staging_resp - fwu_cancel_staging ABI returns
+ * @status: The ABI return status
+ */
+struct __packed fwu_cancel_staging_resp {
+	int status;
+};
+
 /**
  * struct fwu_commit_args - fwu_commit ABI arguments
  * @function_id: fwu_commit service ID
@@ -204,6 +289,28 @@ struct __packed fwu_commit_resp {
 	u32 total_work;
 };
 
+/**
+ * struct fwu_write_stream_args - fwu_write_stream ABI arguments
+ * @function_id: fwu_write_stream service ID
+ * @handle: The handle of the context being written to
+ * @data_len: Size of the data present in the payload
+ * @payload: The data to be transferred
+ */
+struct __packed fwu_write_stream_args {
+	u32 function_id;
+	u32  handle;
+	u32 data_len;
+	u8 payload[];
+};
+
+/**
+ * struct fwu_write_stream_resp - fwu_write_stream ABI returns
+ * @status: The ABI return status
+ */
+struct __packed fwu_write_stream_resp {
+	int status;
+};
+
 /*
  * FWU directory information structures
  */
@@ -261,4 +368,27 @@ efi_status_t fwu_arm_psa_get_image_info(efi_uintn_t *image_info_size,
 					u32 *package_version,
 					u16 **package_version_name);
 
+/**
+ * fwu_update_image() - Update an image
+ *
+ * Perform staging.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+int fwu_update_image(const void *image, u8 image_index, u32 image_size);
+
+/**
+ * fwu_is_dummy_payload() - Identifies a dummy payload
+ * @image_index:	The payload index
+ *
+ * Check whether the payload is dummy or not.
+ *
+ * Return:
+ *
+ * An enum value reflecting whether the payload is dummy or not.
+ */
+fwu_payload_type fwu_get_payload_type(u32 image_index);
+
 #endif
diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
index f19e78ae9d1..234e3c1b3c0 100644
--- a/lib/efi_loader/efi_capsule.c
+++ b/lib/efi_loader/efi_capsule.c
@@ -4,6 +4,11 @@
  *
  *  Copyright (c) 2018 Linaro Limited
  *			Author: AKASHI Takahiro
+ *
+ * Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Author:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #define LOG_CATEGORY LOGC_EFI
@@ -15,6 +20,7 @@
 #include <fdtdec.h>
 #include <fs.h>
 #include <fwu.h>
+#include <fwu_arm_psa.h>
 #include <hang.h>
 #include <malloc.h>
 #include <mapmem.h>
@@ -40,6 +46,8 @@ const efi_guid_t fwu_guid_os_request_fw_revert =
 const efi_guid_t fwu_guid_os_request_fw_accept =
 		FWU_OS_REQUEST_FW_ACCEPT_GUID;
 
+struct efi_capsule_header *g_capsule_data;
+
 #define FW_ACCEPT_OS	(u32)0x8000
 
 #ifdef CONFIG_EFI_CAPSULE_ON_DISK
@@ -196,6 +204,12 @@ efi_fmp_find(efi_guid_t *image_type, u8 image_index, u64 instance,
 			continue;
 		fmp = fmp_handler->protocol_interface;
 
+		if (IS_ENABLED(CONFIG_FWU_ARM_PSA)) {
+			if (fwu_get_payload_type(image_index) !=
+				FWU_PAYLOAD_TYPE_REAL)
+				return fmp;
+		}
+
 		/* get device's image info */
 		info_size = 0;
 		image_info = NULL;
@@ -586,7 +600,7 @@ static efi_status_t efi_capsule_update_firmware(
 	capsule_size = capsule_data->capsule_image_size
 			- capsule_data->header_size;
 
-	if (capsule->version != 0x00000001)
+	if (capsule->version != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_VERSION)
 		return EFI_UNSUPPORTED;
 
 	handles = NULL;
@@ -597,6 +611,10 @@ static efi_status_t efi_capsule_update_firmware(
 	if (ret != EFI_SUCCESS)
 		return EFI_UNSUPPORTED;
 
+	if (IS_ENABLED(CONFIG_FWU_ARM_PSA)) {
+		g_capsule_data = capsule_data;
+	}
+
 	/* Payload */
 	for (item = capsule->embedded_driver_count;
 	     item < capsule->embedded_driver_count
@@ -611,7 +629,8 @@ static efi_status_t efi_capsule_update_firmware(
 
 		image = (void *)capsule + capsule->item_offset_list[item];
 
-		if (image->version != 0x00000003) {
+		if (image->version !=
+			EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_VERSION) {
 			ret = EFI_UNSUPPORTED;
 			goto out;
 		}
diff --git a/lib/fwu_updates/fwu_arm_psa.c b/lib/fwu_updates/fwu_arm_psa.c
index 75d19a69872..77f7c2f2359 100644
--- a/lib/fwu_updates/fwu_arm_psa.c
+++ b/lib/fwu_updates/fwu_arm_psa.c
@@ -25,6 +25,7 @@ static u8 g_fwu_version_major;
 static u8 g_fwu_version_minor;
 static bool g_fwu_initialized;
 struct fwu_image_directory g_fwu_cached_directory;
+efi_guid_t g_update_guid[CONFIG_FWU_NUM_IMAGES_PER_BANK];
 
 /* Error mapping declarations */
 
@@ -60,6 +61,18 @@ static struct fwu_abi_errmap err_msg_map[FWU_ERRMAP_COUNT] = {
 			"FWU_NO_PERMISSION: The image cannot be read from",
 		},
 	},
+	[FWU_ID_TO_ERRMAP_ID(FWU_WRITE_STREAM)] = {
+		{
+			[FWU_UNKNOWN] =
+			"FWU_UNKNOWN: Unrecognized handle",
+			[FWU_DENIED] =
+			"FWU_DENIED: The system is not in a Staging state",
+			[FWU_NO_PERMISSION] =
+			"FWU_NO_PERMISSION: The image cannot be written to",
+			[FWU_OUT_OF_BOUNDS] =
+			"FWU_OUT_OF_BOUNDS: less than data_len bytes available in the image",
+		},
+	},
 	[FWU_ID_TO_ERRMAP_ID(FWU_COMMIT)] = {
 		{
 			[FWU_UNKNOWN] =
@@ -72,6 +85,34 @@ static struct fwu_abi_errmap err_msg_map[FWU_ERRMAP_COUNT] = {
 			"FWU_RESUME: The Update Agent yielded",
 		},
 	},
+	[FWU_ID_TO_ERRMAP_ID(FWU_BEGIN_STAGING)] = {
+		{
+			[FWU_UNKNOWN] =
+			"FWU_UNKNOWN: One of more GUIDs in the update_guid field are unknown to the Update Agent",
+			[FWU_DENIED] =
+			"FWU_DENIED: The Firmware Store is in the Trial state or the platform did not boot correctly",
+			[FWU_BUSY] =
+			"FWU_BUSY: The Client is temporarily prevented from entering the Staging state",
+		},
+	},
+	[FWU_ID_TO_ERRMAP_ID(FWU_END_STAGING)] = {
+		{
+			[FWU_BUSY] =
+			"FWU_BUSY: There are open image handles",
+			[FWU_DENIED] =
+			"FWU_DENIED: The system is not in a Staging state",
+			[FWU_AUTH_FAIL] =
+			"FWU_AUTH_FAIL: At least one of the updated images fails to authenticate",
+			[FWU_NOT_AVAILABLE] =
+			"FWU_NOT_AVAILABLE: The Update Agent does not support partial updates",
+		},
+	},
+	[FWU_ID_TO_ERRMAP_ID(FWU_CANCEL_STAGING)] = {
+		{
+			[FWU_DENIED] =
+			"FWU_DENIED: The system is not in a Staging state",
+		},
+	},
 };
 
 /**
@@ -125,6 +166,110 @@ static int fwu_print_error_log(u32 fwu_id, int fwu_errno)
 	return 0;
 }
 
+/**
+ * fwu_get_payload_type() - Identifies the payload type
+ * @image_index:	The payload index
+ *
+ * Description: Identifies the FWU payload type based on the image index.
+ *
+ * Return:
+ *
+ * FWU_PAYLOAD_TYPE_REAL for a real payload
+ * FWU_PAYLOAD_TYPE_DUMMY_START for the start of a dummy payload
+ * FWU_PAYLOAD_TYPE_DUMMY_END for the end of a dummy payload
+ * FWU_PAYLOAD_TYPE_INVALID for an invalid image_index
+ *
+ */
+fwu_payload_type fwu_get_payload_type(u32 image_index)
+{
+	efi_guid_t *image_guid = NULL;
+	int i;
+	struct efi_fw_image *fw_array;
+
+	fw_array = update_info.images;
+	for (i = 0; i < update_info.num_images; i++) {
+		if (fw_array[i].image_index == image_index) {
+			image_guid = &fw_array[i].image_type_id;
+			break;
+		}
+	}
+
+	if (!image_guid)
+		return FWU_PAYLOAD_TYPE_INVALID;
+
+	if (!guidcmp(image_guid,
+		     &((efi_guid_t)FWU_DUMMY_START_IMAGE_GUID)))
+		return FWU_PAYLOAD_TYPE_DUMMY_START;
+
+	if (!guidcmp(image_guid,
+		     &((efi_guid_t)FWU_DUMMY_END_IMAGE_GUID)))
+		return FWU_PAYLOAD_TYPE_DUMMY_END;
+
+	return FWU_PAYLOAD_TYPE_REAL;
+}
+
+/**
+ * fwu_get_capsule_guids() - Detect the payloads GUIDs in the caspsule
+ *
+ * @partial_update_count:	A pointer to the number of payloads to update
+ * @saved_guids:	A pointer to a GUIDs array for the payloads GUIDs
+ *
+ * Description: Parse the current capsule and detect the payloads GUIDs.
+ *
+ * Return: EFI_SUCCESS is returned on success. Otherwise, failure.
+ */
+static efi_status_t fwu_get_capsule_guids(u32 *partial_update_count,
+					  efi_guid_t saved_guids[])
+{
+	struct efi_firmware_management_capsule_header *capsule;
+	struct efi_firmware_management_capsule_image_header *image;
+	int item;
+	size_t capsule_size;
+	efi_status_t ret = EFI_SUCCESS;
+
+	if (!saved_guids || !partial_update_count)
+		return EFI_INVALID_PARAMETER;
+
+	*partial_update_count = 0;
+	capsule = (void *)g_capsule_data + g_capsule_data->header_size;
+	capsule_size = g_capsule_data->capsule_image_size
+		- g_capsule_data->header_size;
+
+	/* Payload */
+	for (item = capsule->embedded_driver_count;
+	     item < capsule->embedded_driver_count
+		     + capsule->payload_item_count; item++) {
+		/* sanity check */
+		if ((capsule->item_offset_list[item] + sizeof(*image)
+				>= capsule_size)) {
+			ret = EFI_INVALID_PARAMETER;
+			log_err("FWU: Insufficient data, err (0x%lx)\n", ret);
+			break;
+		}
+
+		image = (void *)capsule + capsule->item_offset_list[item];
+
+		if (image->version !=
+			EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_VERSION) {
+			ret = EFI_UNSUPPORTED;
+			log_err("FWU: Version check failed, err (0x%lx)\n",
+				ret);
+			break;
+		}
+
+		if (fwu_get_payload_type(image->update_image_index) !=
+					 FWU_PAYLOAD_TYPE_REAL)
+			continue;
+
+		guidcpy(&saved_guids[*partial_update_count],
+			&image->update_image_type_id);
+
+		(*partial_update_count)++;
+	}
+
+	return ret;
+}
+
 /**
  * fwu_invoke_svc() - FWU service call request
  * @svc_id: FWU ABI function ID
@@ -360,6 +505,86 @@ static int fwu_read_stream(u32 handle, u8 *buffer, u32 buffer_size)
 	return ret;
 }
 
+/**
+ * fwu_begin_staging() -  fwu_begin_staging ABI
+ *
+ * Description: This call indicates to the Update Agent that a new staging
+ *  process will commence.
+ *
+ * Return: 0 on success. Otherwise, failure.
+ */
+static int fwu_begin_staging(void)
+{
+	struct fwu_begin_staging_args *args = g_fwu_buf;
+	struct fwu_begin_staging_resp *resp = g_fwu_buf;
+	char *svc_name = "FWU_BEGIN_STAGING";
+	efi_status_t ret;
+
+	/* Filling the arguments in the shared buffer */
+	args->function_id = FWU_BEGIN_STAGING;
+
+	args->reserved = 0;
+	args->vendor_flags = 0;
+
+	ret = fwu_get_capsule_guids(&args->partial_update_count,
+				    args->update_guid);
+	if (ret) {
+		log_err("FWU: Failure to get the payloads GUIDs\n");
+		return -ENODATA;
+	}
+
+	log_info("FWU: Updating %d payload(s)\n", args->partial_update_count);
+
+	/* Executing the FWU ABI through the FF-A bus */
+	return fwu_invoke_svc(args->function_id, svc_name,
+			      sizeof(*args), sizeof(*resp), NULL);
+}
+
+/**
+ * fwu_end_staging() -  fwu_end_staging ABI
+ *
+ * Description: The Client informs the Update Agent that all the images, meant
+ * to be updated, have been transferred to the Update Agent and that the staging
+ * has terminated.
+ *
+ * Return: 0 on success. Otherwise, failure.
+ */
+static int fwu_end_staging(void)
+{
+	struct fwu_end_staging_args *args = g_fwu_buf;
+	struct fwu_end_staging_resp *resp = g_fwu_buf;
+	char *svc_name = "FWU_END_STAGING";
+
+	/* Filling the arguments in the shared buffer */
+	args->function_id = FWU_END_STAGING;
+
+	/* Executing the FWU ABI through the FF-A bus */
+	return fwu_invoke_svc(args->function_id, svc_name,
+			      sizeof(*args), sizeof(*resp), NULL);
+}
+
+/**
+ * fwu_cancel_staging() -  fwu_cancel_staging ABI
+ *
+ * Description: The Client cancels the staging procedure and the system
+ * transitions back to the Regular state.
+ *
+ * Return: 0 on success. Otherwise, failure.
+ */
+static int fwu_cancel_staging(void)
+{
+	struct fwu_cancel_staging_args *args = g_fwu_buf;
+	struct fwu_cancel_staging_resp *resp = g_fwu_buf;
+	char *svc_name = "FWU_CANCEL_STAGING";
+
+	/* Filling the arguments in the shared buffer */
+	args->function_id = FWU_CANCEL_STAGING;
+
+	/* Executing the FWU ABI through the FF-A bus */
+	return fwu_invoke_svc(args->function_id, svc_name,
+			      sizeof(*args), sizeof(*resp), NULL);
+}
+
 /**
  * fwu_commit() -  fwu_commit ABI
  * @handle: The handle of the context being closed
@@ -402,6 +627,137 @@ static int fwu_commit(u32 handle, u32 acceptance_req, u32 max_atomic_len)
 	return 0;
 }
 
+/**
+ * fwu_write_stream() -  fwu_write_stream ABI
+ * @handle: The handle of the context being writen to
+ * @payload: The data to be transferred
+ * @payload_size: Size of the data present in the payload
+ *
+ *  Description: The call writes at most max_payload_size bytes to the Update
+ *  Agent context pointed to by handle.
+ *
+ * Return: 0 on success. Otherwise, failure
+ */
+static int fwu_write_stream(u32 handle, const u8 *payload, u32 payload_size)
+{
+	int ret;
+	u32 write_size, max_write_size, curr_write_offset = 0;
+	u32 payload_bytes_left = payload_size, fwu_buf_bytes_left;
+	struct fwu_write_stream_args *args = g_fwu_buf;
+	struct fwu_write_stream_resp *resp = g_fwu_buf;
+	char *svc_name = "FWU_WRITE_STREAM";
+
+	if (!payload || !payload_size)
+		return -EINVAL;
+
+	fwu_buf_bytes_left = FWU_BUFFER_SIZE - sizeof(*args);
+
+	if (g_max_payload_size <= fwu_buf_bytes_left)
+		max_write_size = g_max_payload_size;
+	else
+		max_write_size = fwu_buf_bytes_left;
+
+	while (curr_write_offset < payload_size) {
+		if (payload_bytes_left <= max_write_size)
+			write_size = payload_bytes_left;
+		else
+			write_size = max_write_size;
+
+		/* Filling the arguments in the shared buffer */
+		args->function_id = FWU_WRITE_STREAM;
+		args->handle = handle;
+		args->data_len = write_size;
+		memcpy(args->payload, payload + curr_write_offset, write_size);
+
+		/* Executing the FWU ABI through the FF-A bus */
+		ret = fwu_invoke_svc(args->function_id, svc_name, sizeof(*args),
+				     sizeof(*resp), NULL);
+		if (ret)
+			return ret;
+
+		curr_write_offset += write_size;
+		payload_bytes_left -= write_size;
+
+		log_debug("%s:  %d bytes written, remaining %d bytes\n",
+			  svc_name, write_size, payload_bytes_left);
+	}
+
+	return ret;
+}
+
+/**
+ * fwu_update_image() - Update an image
+ *
+ * @image: Pointer to the payload to write
+ * @image_index: The payload index
+ * @image_size: The payload size
+ *
+ * Description: Perform staging with multiple payloads support.
+ * The capsule is expected to:
+ *     - Start with a dummy payload to mark the start of the payloads sequence
+ *     - One or more payloads to be written to the storage device
+ *     - End with a dummy payload to mark the end of the payloads sequence
+ *
+ * The possible payloads in the capsule are described in the board file
+ * through struct efi_fw_image. This includes the dummy payloads.
+ * The dummy payloads image indexes must be >= CONFIG_FWU_NUM_IMAGES_PER_BANK
+ * The dummy payloads are not sent to the Secure world and are not written to
+ * the storage device.
+ *
+ * Return: 0 on success. Otherwise, failure.
+ */
+int fwu_update_image(const void *image, u8 image_index, u32 image_size)
+{
+	int ret;
+	u32 handle;
+
+	if (!image)
+		return -EINVAL;
+
+	/* Only image indexes starting from 1 are supported */
+	if (!image_index || image_index > update_info.num_images)
+		return -EINVAL;
+
+	if (fwu_get_payload_type(image_index) ==
+		FWU_PAYLOAD_TYPE_DUMMY_START) {
+		return fwu_begin_staging();
+	}
+
+	if (fwu_get_payload_type(image_index) ==
+		FWU_PAYLOAD_TYPE_DUMMY_END) {
+		ret = fwu_end_staging();
+		if (ret)
+			goto cancel_staging;
+		return 0;
+	}
+
+	ret = fwu_open(&g_fwu_cached_directory.entries[image_index - 1].image_guid,
+		       FWU_OP_TYPE_WRITE, &handle);
+	if (ret)
+		goto cancel_staging;
+
+	ret = fwu_write_stream(handle, image, image_size);
+	if (ret)
+		goto cancel_staging;
+
+	/*
+	 * The Update Agent can execute for an unbounded time.
+	 * The image should be tried before being accepted.
+	 * So, we put the acceptance request as 'not accepted'.
+	 */
+	ret = fwu_commit(handle, FWU_IMG_NOT_ACCEPTED, 0);
+	if (ret)
+		goto cancel_staging;
+
+	log_debug("FWU: Image at index %d updated\n", image_index);
+
+	return 0;
+
+cancel_staging:
+
+	return fwu_cancel_staging();
+}
+
 /**
  * fwu_read_directory() - Read FWU directory information
  *
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v4 12/24] efi_loader: fwu_arm_psa: Add set_image and get_image_info support
  2025-07-25 15:49 [PATCH v4 00/24] Introduce Firmware Update Support for Arm PSA abdellatif.elkhlifi
                   ` (10 preceding siblings ...)
  2025-07-25 15:49 ` [PATCH v4 11/24] fwu_arm_psa: Add staging ABIs abdellatif.elkhlifi
@ 2025-07-25 15:49 ` abdellatif.elkhlifi
  2025-08-20 12:28   ` Ilias Apalodimas
  2025-07-25 15:49 ` [PATCH v4 13/24] efi_loader: fwu_arm_psa: Keep the FMP payload header abdellatif.elkhlifi
                   ` (12 subsequent siblings)
  24 siblings, 1 reply; 29+ messages in thread
From: abdellatif.elkhlifi @ 2025-07-25 15:49 UTC (permalink / raw)
  To: u-boot
  Cc: Abdellatif El Khlifi, Davidson kumaresan, Heinrich Schuchardt,
	Sughosh Ganu, Tom Rini, Ilias Apalodimas, Simon Glass,
	Michal Simek, Marek Vasut, Casey Connolly, Adriano Cordova

From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>

Implement set_image and get_image_info through RAW functions

The implementation is done using efi_firmware_raw_set_image()
and efi_firmware_get_image_info()

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Signed-off-by: Davidson kumaresan <davidson.kumaresan@arm.com>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
Cc: Sughosh Ganu <sughosh.ganu@linaro.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Simon Glass <sjg@chromium.org>
Cc: Michal Simek <michal.simek@amd.com>
Cc: Marek Vasut <marek.vasut+renesas@mailbox.org>
Cc: Casey Connolly <casey.connolly@linaro.org>
Cc: Adriano Cordova <adrianox@gmail.com>

---

Changelog of changes:
===========================

v2:

* Following Heinrich comment: The changes at efi_firmware_raw_set_image()
    simplified by removing the "else" so it is clear we are just adding FWU_ARM_PSA
    support and skipping the use of DFU in case of FWU_ARM_PSA

v1:

* Add set_image and get_image_info support for FWU_ARM_PSA

 lib/efi_loader/efi_firmware.c | 35 +++++++++++++++++++++++++++++++----
 1 file changed, 31 insertions(+), 4 deletions(-)

diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
index 75501e21557..38945b34e7b 100644
--- a/lib/efi_loader/efi_firmware.c
+++ b/lib/efi_loader/efi_firmware.c
@@ -4,6 +4,12 @@
  *
  *  Copyright (c) 2020 Linaro Limited
  *			Author: AKASHI Takahiro
+ *
+ * Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ *   Davidson kumaresan <davidson.kumaresan@arm.com>
  */
 
 #define LOG_CATEGORY LOGC_EFI
@@ -14,6 +20,7 @@
 #include <efi_variable.h>
 #include <env.h>
 #include <fwu.h>
+#include <fwu_arm_psa.h>
 #include <image.h>
 #include <signatures.h>
 
@@ -601,10 +608,21 @@ efi_status_t EFIAPI efi_firmware_get_image_info(
 	     !descriptor_size || !package_version || !package_version_name))
 		return EFI_EXIT(EFI_INVALID_PARAMETER);
 
-	ret = efi_fill_image_desc_array(image_info_size, image_info,
-					descriptor_version, descriptor_count,
-					descriptor_size, package_version,
-					package_version_name);
+	if (IS_ENABLED(CONFIG_FWU_ARM_PSA)) {
+		ret = fwu_arm_psa_get_image_info(image_info_size, image_info,
+						 descriptor_version,
+						 descriptor_count,
+						 descriptor_size,
+						 package_version,
+						 package_version_name);
+	} else {
+		ret = efi_fill_image_desc_array(image_info_size, image_info,
+						descriptor_version,
+						descriptor_count,
+						descriptor_size,
+						package_version,
+						package_version_name);
+	}
 
 	return EFI_EXIT(ret);
 }
@@ -749,6 +767,15 @@ efi_status_t EFIAPI efi_firmware_raw_set_image(
 	if (status != EFI_SUCCESS)
 		return EFI_EXIT(status);
 
+	if (IS_ENABLED(CONFIG_FWU_ARM_PSA)) {
+		if (fwu_update_image(image, image_index, image_size))
+			return EFI_EXIT(EFI_DEVICE_ERROR);
+
+		efi_firmware_set_fmp_state_var(&state, image_index);
+
+		return EFI_EXIT(EFI_SUCCESS);
+	}
+
 	/*
 	 * dfu_alt_num is assigned from 0 while image_index starts from 1.
 	 * dfu_alt_num is calculated by (image_index - 1) when multi bank update
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v4 13/24] efi_loader: fwu_arm_psa: Keep the FMP payload header
  2025-07-25 15:49 [PATCH v4 00/24] Introduce Firmware Update Support for Arm PSA abdellatif.elkhlifi
                   ` (11 preceding siblings ...)
  2025-07-25 15:49 ` [PATCH v4 12/24] efi_loader: fwu_arm_psa: Add set_image and get_image_info support abdellatif.elkhlifi
@ 2025-07-25 15:49 ` abdellatif.elkhlifi
  2025-07-25 15:50 ` [PATCH v4 14/24] efi_loader: fwu: fwu_arm_psa: Skip accepting the payload after set_image() abdellatif.elkhlifi
                   ` (11 subsequent siblings)
  24 siblings, 0 replies; 29+ messages in thread
From: abdellatif.elkhlifi @ 2025-07-25 15:49 UTC (permalink / raw)
  To: u-boot
  Cc: Abdellatif El Khlifi, Heinrich Schuchardt, Sughosh Ganu, Tom Rini,
	Ilias Apalodimas, Simon Glass, Michal Simek, Marek Vasut,
	Casey Connolly, Adriano Cordova

From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>

Allow sending the payload with its FMP header

The Secure world needs the data provided by the payload
FMP header. So, let's keep it in case of FWU_ARM_PSA.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
Cc: Sughosh Ganu <sughosh.ganu@linaro.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Simon Glass <sjg@chromium.org>
Cc: Michal Simek <michal.simek@amd.com>
Cc: Marek Vasut <marek.vasut+renesas@mailbox.org>
Cc: Casey Connolly <casey.connolly@linaro.org>
Cc: Adriano Cordova <adrianox@gmail.com>
---
 lib/efi_loader/efi_firmware.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
index 38945b34e7b..e1fc3f577d4 100644
--- a/lib/efi_loader/efi_firmware.c
+++ b/lib/efi_loader/efi_firmware.c
@@ -517,8 +517,11 @@ static void efi_firmware_get_fw_version(const void **p_image,
 		/* FMP header is inserted above the capsule payload */
 		state->fw_version = header->fw_version;
 
-		*p_image += header->header_size;
-		*p_image_size -= header->header_size;
+		if (!IS_ENABLED(CONFIG_FWU_ARM_PSA)) {
+			*p_image += header->header_size;
+			*p_image_size -= header->header_size;
+		}
+
 	}
 }
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v4 14/24] efi_loader: fwu: fwu_arm_psa: Skip accepting the payload after set_image()
  2025-07-25 15:49 [PATCH v4 00/24] Introduce Firmware Update Support for Arm PSA abdellatif.elkhlifi
                   ` (12 preceding siblings ...)
  2025-07-25 15:49 ` [PATCH v4 13/24] efi_loader: fwu_arm_psa: Keep the FMP payload header abdellatif.elkhlifi
@ 2025-07-25 15:50 ` abdellatif.elkhlifi
  2025-08-20 12:37   ` Ilias Apalodimas
  2025-07-25 15:50 ` [PATCH v4 15/24] efi_loader: fwu: fwu_arm_psa: Disable trial state handling abdellatif.elkhlifi
                   ` (10 subsequent siblings)
  24 siblings, 1 reply; 29+ messages in thread
From: abdellatif.elkhlifi @ 2025-07-25 15:50 UTC (permalink / raw)
  To: u-boot
  Cc: Abdellatif El Khlifi, Heinrich Schuchardt, Sughosh Ganu, Tom Rini,
	Ilias Apalodimas, Simon Glass, Michal Simek, Marek Vasut,
	Casey Connolly, Adriano Cordova

From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>

Do not update the acceptance metadata bit after updating an image

The update agent (secure world) is responsible of setting the acceptance
bit in the metadata.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
Cc: Sughosh Ganu <sughosh.ganu@linaro.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Simon Glass <sjg@chromium.org>
Cc: Michal Simek <michal.simek@amd.com>
Cc: Marek Vasut <marek.vasut+renesas@mailbox.org>
Cc: Casey Connolly <casey.connolly@linaro.org>
Cc: Adriano Cordova <adrianox@gmail.com>
---
 lib/efi_loader/efi_capsule.c | 23 +++++++++++++----------
 lib/fwu_updates/fwu.c        | 21 +++++++++++++++++++++
 2 files changed, 34 insertions(+), 10 deletions(-)

diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
index 234e3c1b3c0..1dac691d24d 100644
--- a/lib/efi_loader/efi_capsule.c
+++ b/lib/efi_loader/efi_capsule.c
@@ -696,17 +696,20 @@ static efi_status_t efi_capsule_update_firmware(
 				status = fwu_clear_accept_image(image_type_id,
 								update_index);
 			}
-			ret = fwu_to_efi_error(status);
-			if (ret != EFI_SUCCESS) {
-				log_err("Unable to %s the accept bit for the image %pUs\n",
-					fw_accept_os ? "clear" : "set",
-					image_type_id);
-				goto out;
-			}
 
-			log_debug("%s the accepted bit for Image %pUs\n",
-				  fw_accept_os ? "Cleared" : "Set",
-				  image_type_id);
+			if (!IS_ENABLED(CONFIG_FWU_ARM_PSA)) {
+				ret = fwu_to_efi_error(status);
+				if (ret != EFI_SUCCESS) {
+					log_err("Unable to %s the accept bit for the image %pUs\n",
+						fw_accept_os ? "clear" : "set",
+						image_type_id);
+					goto out;
+				}
+
+				log_debug("%s the accepted bit for Image %pUs\n",
+					  fw_accept_os ? "Cleared" : "Set",
+					  image_type_id);
+			}
 		}
 
 	}
diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c
index 7f085a0211f..46b6f9356a7 100644
--- a/lib/fwu_updates/fwu.c
+++ b/lib/fwu_updates/fwu.c
@@ -1,6 +1,11 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright (c) 2022, Linaro Limited
+ *
+ * Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Author:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #include <dm.h>
@@ -586,6 +591,14 @@ out:
  */
 int fwu_accept_image(efi_guid_t *img_type_id, u32 bank)
 {
+	/*
+	 * In case of Arm PSA accepting images is either
+	 * at ExitBootServices() or in the OS. So, let's skip setting the
+	 * acceptance bit (not used in Arm PSA)
+	 */
+	if (IS_ENABLED(CONFIG_FWU_ARM_PSA))
+		return EFI_SUCCESS;
+
 	return fwu_clrset_image_accept(img_type_id, bank,
 				       IMAGE_ACCEPT_SET);
 }
@@ -606,6 +619,14 @@ int fwu_accept_image(efi_guid_t *img_type_id, u32 bank)
  */
 int fwu_clear_accept_image(efi_guid_t *img_type_id, u32 bank)
 {
+	/*
+	 * In case of Arm PSA accepting images is either
+	 * at ExitBootServices() or in the OS. So, let's skip clearing the
+	 * acceptance bit (not used in Arm PSA)
+	 */
+	if (IS_ENABLED(CONFIG_FWU_ARM_PSA))
+		return EFI_SUCCESS;
+
 	return fwu_clrset_image_accept(img_type_id, bank,
 				       IMAGE_ACCEPT_CLEAR);
 }
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v4 15/24] efi_loader: fwu: fwu_arm_psa: Disable trial state handling
  2025-07-25 15:49 [PATCH v4 00/24] Introduce Firmware Update Support for Arm PSA abdellatif.elkhlifi
                   ` (13 preceding siblings ...)
  2025-07-25 15:50 ` [PATCH v4 14/24] efi_loader: fwu: fwu_arm_psa: Skip accepting the payload after set_image() abdellatif.elkhlifi
@ 2025-07-25 15:50 ` abdellatif.elkhlifi
  2025-07-25 15:50 ` [PATCH v4 16/24] fwu_arm_psa: Add FWU acceptance mechanism abdellatif.elkhlifi
                   ` (9 subsequent siblings)
  24 siblings, 0 replies; 29+ messages in thread
From: abdellatif.elkhlifi @ 2025-07-25 15:50 UTC (permalink / raw)
  To: u-boot
  Cc: Abdellatif El Khlifi, Heinrich Schuchardt, Sughosh Ganu, Tom Rini,
	Ilias Apalodimas, Simon Glass, Michal Simek, Marek Vasut,
	Casey Connolly, Adriano Cordova

From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>

No need for trial state handling in U-Boot for FWU Arm PSA

In FWU Arm PSA mode, trial state is handled by Secure world.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
Cc: Sughosh Ganu <sughosh.ganu@linaro.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Simon Glass <sjg@chromium.org>
Cc: Michal Simek <michal.simek@amd.com>
Cc: Marek Vasut <marek.vasut+renesas@mailbox.org>
Cc: Casey Connolly <casey.connolly@linaro.org>
Cc: Adriano Cordova <adrianox@gmail.com>
---
 lib/efi_loader/efi_capsule.c | 7 +++++--
 lib/fwu_updates/fwu.c        | 8 +++++++-
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
index 1dac691d24d..113cfe30fde 100644
--- a/lib/efi_loader/efi_capsule.c
+++ b/lib/efi_loader/efi_capsule.c
@@ -562,7 +562,9 @@ static efi_status_t efi_capsule_update_firmware(
 	if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
 		if (fwu_empty_capsule(capsule_data)) {
 			if (fwu_empty_capsule_checks_pass()) {
-				return fwu_empty_capsule_process(capsule_data);
+				return !IS_ENABLED(CONFIG_FWU_ARM_PSA) ?
+					fwu_empty_capsule_process(capsule_data) :
+					0;
 			} else {
 				log_err("FWU empty capsule checks failed. Cannot start update\n");
 				return EFI_INVALID_PARAMETER;
@@ -1377,7 +1379,8 @@ efi_status_t efi_launch_capsules(void)
 
 	efi_capsule_scan_done();
 
-	if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
+	if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE) &&
+	    !IS_ENABLED(CONFIG_FWU_ARM_PSA)) {
 		if (capsule_update == true && update_status == true) {
 			ret = fwu_post_update_process(fw_accept_os);
 		} else if (capsule_update == true && update_status == false) {
diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c
index 46b6f9356a7..7ae3dfffae2 100644
--- a/lib/fwu_updates/fwu.c
+++ b/lib/fwu_updates/fwu.c
@@ -345,6 +345,11 @@ int fwu_get_mdata(struct fwu_mdata *mdata)
 		if (parts_ok[i])
 			continue;
 
+		if (IS_ENABLED(CONFIG_FWU_ARM_PSA)) {
+			log_err("FWU metadata copy %d invalid\n", i);
+			return -ENOTSYNC;
+		}
+
 		memcpy(parts_mdata[i], parts_mdata[1 - i], mdata_size);
 		err = fwu_sync_mdata(parts_mdata[i], i ? SECONDARY_PART : PRIMARY_PART);
 		if (err) {
@@ -786,7 +791,8 @@ static int fwu_boottime_checks(void)
 
 	in_trial = in_trial_state();
 
-	ret = in_trial ? fwu_trial_count_update() : trial_counter_update(NULL);
+	ret = (in_trial && !IS_ENABLED(CONFIG_FWU_ARM_PSA)) ?
+	       fwu_trial_count_update() : trial_counter_update(NULL);
 
 	if (!ret)
 		boottime_check = 1;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v4 16/24] fwu_arm_psa: Add FWU acceptance mechanism
  2025-07-25 15:49 [PATCH v4 00/24] Introduce Firmware Update Support for Arm PSA abdellatif.elkhlifi
                   ` (14 preceding siblings ...)
  2025-07-25 15:50 ` [PATCH v4 15/24] efi_loader: fwu: fwu_arm_psa: Disable trial state handling abdellatif.elkhlifi
@ 2025-07-25 15:50 ` abdellatif.elkhlifi
  2025-07-25 15:50 ` [PATCH v4 17/24] fwu_arm_psa: Add ESRT support abdellatif.elkhlifi
                   ` (8 subsequent siblings)
  24 siblings, 0 replies; 29+ messages in thread
From: abdellatif.elkhlifi @ 2025-07-25 15:50 UTC (permalink / raw)
  To: u-boot
  Cc: Abdellatif El Khlifi, Sughosh Ganu, Tom Rini, Ilias Apalodimas,
	Simon Glass, Michal Simek, Marek Vasut, Casey Connolly

From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>

Accept the FWU at ExitBootServices()

Provide the FWU_ACCEPT_IMAGE ABI and setup an event triggered
on ExitBootServices().
This mechanism notifies Secure world that the system booted
successfully by accepting the images in trial state.

Also, add FWU_ARM_PSA_ACCEPT_IMAGES config
to allow platforms to switch off image acceptance
in ExitBootServices().

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Sughosh Ganu <sughosh.ganu@linaro.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Simon Glass <sjg@chromium.org>
Cc: Michal Simek <michal.simek@amd.com>
Cc: Marek Vasut <marek.vasut+renesas@mailbox.org>
Cc: Casey Connolly <casey.connolly@linaro.org>

---

Changelog of changes:
===========================

v4:

* Update the function headers in fwu_arm_psa.c to pass kernel-doc tests

v2:

* As suggested by Michal: Add /** for marking kernel-doc format

v1:

* Accept the FWU at ExitBootServices()

 include/fwu_arm_psa.h         |  22 ++++-
 lib/fwu_updates/Kconfig       |   8 ++
 lib/fwu_updates/fwu_arm_psa.c | 176 ++++++++++++++++++++++++++++++++++
 3 files changed, 205 insertions(+), 1 deletion(-)

diff --git a/include/fwu_arm_psa.h b/include/fwu_arm_psa.h
index 00c78ba7e7c..6400cf44d1b 100644
--- a/include/fwu_arm_psa.h
+++ b/include/fwu_arm_psa.h
@@ -84,9 +84,10 @@ enum fwu_abis {
 	FWU_WRITE_STREAM = 20,
 	FWU_READ_STREAM = 21,
 	FWU_COMMIT = 22,
+	FWU_ACCEPT_IMAGE = 23,
 	/* To be updated when adding new FWU IDs */
 	FWU_FIRST_ID = FWU_DISCOVER, /* Lowest number ID */
-	FWU_LAST_ID = FWU_COMMIT, /* Highest number ID */
+	FWU_LAST_ID = FWU_ACCEPT_IMAGE, /* Highest number ID */
 };
 
 enum fwu_abi_errcode {
@@ -311,6 +312,25 @@ struct __packed fwu_write_stream_resp {
 	int status;
 };
 
+/**
+ * struct fwu_accept_image_args - fwu_accept_image ABI arguments
+ * @function_id: fwu_accept_image service ID
+ * @image_type_guid: GUID of the image to be accepted
+ */
+struct __packed fwu_accept_image_args {
+	u32 function_id;
+	u32 reserved;
+	efi_guid_t image_type_guid;
+};
+
+/**
+ * struct fwu_accept_image_resp - fwu_accept_image ABI returns
+ * @status: The ABI return status
+ */
+struct __packed fwu_accept_image_resp {
+	int status;
+};
+
 /*
  * FWU directory information structures
  */
diff --git a/lib/fwu_updates/Kconfig b/lib/fwu_updates/Kconfig
index cdc96109f0a..958e54dec37 100644
--- a/lib/fwu_updates/Kconfig
+++ b/lib/fwu_updates/Kconfig
@@ -57,6 +57,14 @@ config FWU_ARM_PSA
 	  driver that supports the Arm PSA firmware update specification as
 	  mentioned in https://developer.arm.com/documentation/den0118/a/
 
+config FWU_ARM_PSA_ACCEPT_IMAGES
+	bool "Accept images at EFI ExitBootServices() level"
+	depends on FWU_ARM_PSA
+	default y
+	help
+	  Select this option if reaching ExitBootServices() level means the boot succeeded
+	  This option will add a callback at ExitBootServices() that accepts all the images.
+
 config FWU_BUFFER_PAGES
 	int "Number of 4KB pages in the FWU shared buffer"
 	depends on FWU_ARM_PSA
diff --git a/lib/fwu_updates/fwu_arm_psa.c b/lib/fwu_updates/fwu_arm_psa.c
index 77f7c2f2359..42c002e0f25 100644
--- a/lib/fwu_updates/fwu_arm_psa.c
+++ b/lib/fwu_updates/fwu_arm_psa.c
@@ -8,6 +8,7 @@
  */
 #include <arm_ffa.h>
 #include <dm.h>
+#include <fwu.h>
 #include <fwu_arm_psa.h>
 #include <fwu.h>
 #include <log.h>
@@ -113,6 +114,14 @@ static struct fwu_abi_errmap err_msg_map[FWU_ERRMAP_COUNT] = {
 			"FWU_DENIED: The system is not in a Staging state",
 		},
 	},
+	[FWU_ID_TO_ERRMAP_ID(FWU_ACCEPT_IMAGE)] = {
+		{
+			[FWU_UNKNOWN] =
+			"FWU_UNKNOWN: Image with type=image_type_guid is not managed by the Update Agent",
+			[FWU_DENIED] =
+			"FWU_DENIED: The system has not booted with the active bank, or the image cannot be accepted before being activated",
+		},
+	},
 };
 
 /**
@@ -685,6 +694,35 @@ static int fwu_write_stream(u32 handle, const u8 *payload, u32 payload_size)
 	return ret;
 }
 
+/**
+ * fwu_accept() -  fwu_accept_image ABI
+ *
+ * @guid: GUID of the image to be accepted
+ *
+ * Description: Sets the status of the firmware image, with a given GUID
+ * to "accepted" in the active firmware bank.
+ *
+ * Return: 0 on success. Otherwise, failure.
+ */
+static int fwu_accept(const efi_guid_t *guid)
+{
+	struct fwu_accept_image_args *args = g_fwu_buf;
+	struct fwu_accept_image_resp *resp = g_fwu_buf;
+	char *svc_name = "FWU_ACCEPT_IMAGE";
+
+	if (!guid)
+		return -EINVAL;
+
+	/* Filling the arguments in the shared buffer */
+	args->function_id = FWU_ACCEPT_IMAGE;
+
+	guidcpy(&args->image_type_guid, guid);
+
+	/* Executing the FWU ABI through the FF-A bus */
+	return fwu_invoke_svc(args->function_id, svc_name,
+			     sizeof(*args), sizeof(*resp), NULL);
+}
+
 /**
  * fwu_update_image() - Update an image
  *
@@ -1022,6 +1060,138 @@ failure:
 	return ret;
 }
 
+/**
+ * fwu_one_image_accepted() - Accept one image in trial state
+ *
+ * @img_entry: Pointer to the image entry.
+ * @active_idx: Active bank index.
+ * @image_number: Image number for logging purposes.
+ *
+ * Description: Invoke FWU accept image ABI to accept the image.
+ *
+ * Return: true is returned on success, false on failure.
+ */
+static bool fwu_one_image_accepted(const struct fwu_image_entry *img_entry,
+				   u32 active_idx,
+				   u32 image_number)
+{
+	const struct fwu_image_bank_info *bank_info =
+		&img_entry->img_bank_info[active_idx];
+	int fwu_ret;
+
+	if (!bank_info->accepted) {
+		fwu_ret = fwu_accept(&bank_info->image_guid);
+		if (fwu_ret) {
+			log_err("FWU: Failed to accept image #%d\n",
+				image_number + 1);
+			return false;
+		}
+		log_debug("FWU: Image #%d accepted\n", image_number + 1);
+	}
+
+	return true;
+}
+
+/**
+ * fwu_all_images_accepted() - Accept any pending firmware update images
+ *
+ * @fwu_data: Pointer to FWU data structure
+ *
+ * Description: Read from the metadata the acceptance state of each image.
+ * Then, accept the images which are not accepted yet.
+ *
+ * Return: true is returned on success, false on failure.
+ */
+static bool fwu_all_images_accepted(const struct fwu_data *fwu_data)
+{
+	int fwu_ret;
+	u32 active_idx;
+	u32 i;
+	bool accepted;
+
+	fwu_ret = fwu_get_active_index(&active_idx);
+	if (fwu_ret) {
+		log_err("FWU: Failed to read boot index, err (%d)\n",
+			fwu_ret);
+		return false;
+	}
+
+	for (i = 0 ; i < CONFIG_FWU_NUM_IMAGES_PER_BANK ; i++) {
+		accepted = fwu_one_image_accepted(&fwu_data->fwu_images[i], active_idx, i);
+		if (!accepted)
+			return false;
+	}
+
+	return true;
+}
+
+/**
+ * fwu_accept_notify_exit_boot_services() - ExitBootServices callback
+ *
+ * @event:	callback event
+ * @context:	callback context
+ *
+ * Description: Reaching ExitBootServices() level means the boot succeeded.
+ * So, accept all the images.
+ *
+ * Return: EFI_SUCCESS on success. Otherwise, failure.
+ */
+static void EFIAPI fwu_accept_notify_exit_boot_services(struct efi_event *event,
+							void *context)
+{
+	efi_status_t efi_ret = EFI_SUCCESS;
+	bool all_accepted;
+	struct fwu_data *fwu_data;
+
+	EFI_ENTRY("%p, %p", event, context);
+
+	fwu_data = fwu_get_data();
+	if (!fwu_data) {
+		log_err("FWU: Cannot get FWU data\n");
+		efi_ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
+	if (fwu_data->trial_state) {
+		all_accepted = fwu_all_images_accepted(fwu_data);
+		if (!all_accepted) {
+			efi_ret = EFI_ACCESS_DENIED;
+			goto out;
+		}
+
+	} else {
+		log_info("FWU: ExitBootServices: Booting in regular state\n");
+	}
+
+out:
+	EFI_EXIT(efi_ret);
+}
+
+/**
+ * fwu_setup_accept_event() - Setup the FWU accept event
+ *
+ * Description: Create a FWU accept event triggered on ExitBootServices().
+ *
+ * Return: 0 is returned on success. Otherwise, failure.
+ */
+static int fwu_setup_accept_event(void)
+{
+	efi_status_t efi_ret;
+	struct efi_event *evt = NULL;
+
+	efi_ret = efi_create_event(EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,
+				   fwu_accept_notify_exit_boot_services, NULL,
+				   &efi_guid_event_group_exit_boot_services,
+				   &evt);
+	if (efi_ret != EFI_SUCCESS) {
+		log_err("FWU: Cannot install accept event %p, err (%lu)\n", evt,
+			efi_ret);
+		return -EPERM;
+	}
+
+	return 0;
+}
+
 /**
  * fwu_agent_init() - Setup the FWU agent
  *
@@ -1074,6 +1244,12 @@ int fwu_agent_init(void)
 	if (ret)
 		goto failure;
 
+	if (IS_ENABLED(CONFIG_FWU_ARM_PSA_ACCEPT_IMAGES)) {
+		ret = fwu_setup_accept_event();
+		if (ret)
+			goto failure;
+	}
+
 	g_fwu_initialized = true;
 
 	return 0;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v4 17/24] fwu_arm_psa: Add ESRT support
  2025-07-25 15:49 [PATCH v4 00/24] Introduce Firmware Update Support for Arm PSA abdellatif.elkhlifi
                   ` (15 preceding siblings ...)
  2025-07-25 15:50 ` [PATCH v4 16/24] fwu_arm_psa: Add FWU acceptance mechanism abdellatif.elkhlifi
@ 2025-07-25 15:50 ` abdellatif.elkhlifi
  2025-07-25 15:50 ` [PATCH v4 18/24] fwu_arm_psa: Add ExitBootService() notification handler abdellatif.elkhlifi
                   ` (7 subsequent siblings)
  24 siblings, 0 replies; 29+ messages in thread
From: abdellatif.elkhlifi @ 2025-07-25 15:50 UTC (permalink / raw)
  To: u-boot
  Cc: Abdellatif El Khlifi, Sughosh Ganu, Tom Rini, Ilias Apalodimas,
	Simon Glass, Michal Simek, Marek Vasut, Casey Connolly

From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>

Read ESRT data from Secure world in GetImageInfo()

Use FWU_READ_STREAM ABI to read ESRT data from Secure world.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Sughosh Ganu <sughosh.ganu@linaro.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Simon Glass <sjg@chromium.org>
Cc: Michal Simek <michal.simek@amd.com>
Cc: Marek Vasut <marek.vasut+renesas@mailbox.org>
Cc: Casey Connolly <casey.connolly@linaro.org>

---

Changelog of changes:
===========================

v4:

* Update the function headers in fwu_arm_psa.c to pass kernel-doc tests

v2:

* As suggested by Michal: Add /** for marking kernel-doc format

v1:

* Read ESRT data from Secure world in GetImageInfo()

 include/fwu_arm_psa.h         |  13 ++++
 lib/fwu_updates/fwu_arm_psa.c | 112 +++++++++++++++++++++++++++++++---
 2 files changed, 115 insertions(+), 10 deletions(-)

diff --git a/include/fwu_arm_psa.h b/include/fwu_arm_psa.h
index 6400cf44d1b..12cd8e68b22 100644
--- a/include/fwu_arm_psa.h
+++ b/include/fwu_arm_psa.h
@@ -16,6 +16,9 @@
 
 #define DEFAULT_HW_INSTANCE		(1)
 
+/* The minimum supported ESRT version */
+#define EFI_SYSTEM_RESOURCE_TABLE_FIRMWARE_RESOURCE_VERSION		(1)
+
 /* Default values of the ESRT fields which are not supported at this stage */
 #define PACKAGE_VERSION_NOT_SUP		(0xffffffff)
 #define LAST_ATTEMPT_NOT_SUP		(0)
@@ -355,6 +358,16 @@ struct __packed fwu_image_directory {
 	struct fwu_image_info_entry entries[FWU_DIRECTORY_IMAGE_ENTRIES_COUNT];
 };
 
+/**
+ * struct fwu_esrt_data_wrapper - Wrapper for the ESRT data
+ * @data: The ESRT data read from secure world
+ * @entries: The ESRT entries
+ */
+struct __packed fwu_esrt_data_wrapper {
+	struct efi_system_resource_table data;
+	struct efi_system_resource_entry entries[CONFIG_FWU_NUM_IMAGES_PER_BANK];
+};
+
 /**
  * fwu_agent_init() - Setup the FWU agent
  *
diff --git a/lib/fwu_updates/fwu_arm_psa.c b/lib/fwu_updates/fwu_arm_psa.c
index 42c002e0f25..f4302371a41 100644
--- a/lib/fwu_updates/fwu_arm_psa.c
+++ b/lib/fwu_updates/fwu_arm_psa.c
@@ -27,6 +27,7 @@ static u8 g_fwu_version_minor;
 static bool g_fwu_initialized;
 struct fwu_image_directory g_fwu_cached_directory;
 efi_guid_t g_update_guid[CONFIG_FWU_NUM_IMAGES_PER_BANK];
+struct fwu_esrt_data_wrapper g_esrt_data;
 
 /* Error mapping declarations */
 
@@ -874,6 +875,96 @@ close_handle:
 	return ret;
 }
 
+/**
+ * fwu_esrt_sanity_check() - Verify ESRT data
+ *
+ * Description: Make sure the ESRT data matches the directory data.
+ *
+ * Return: 0 on success. Otherwise, failure.
+ */
+static int fwu_esrt_sanity_check(void)
+{
+	int i;
+
+	log_debug("FWU: ESRT data check ...\n");
+
+	if (g_esrt_data.data.fw_resource_count !=
+	    CONFIG_FWU_NUM_IMAGES_PER_BANK) {
+		log_err("FWU: Unexpected ESRT entries count (%d , %d)\n",
+			g_esrt_data.data.fw_resource_count,
+			CONFIG_FWU_NUM_IMAGES_PER_BANK);
+		return -EINVAL;
+	}
+
+	if (g_esrt_data.data.fw_resource_version <
+		EFI_SYSTEM_RESOURCE_TABLE_FIRMWARE_RESOURCE_VERSION) {
+		log_err("FWU: Secure world ESRT version %llu not supported\n",
+			g_esrt_data.data.fw_resource_version);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < g_fwu_cached_directory.num_images; i++) {
+		if (guidcmp(&g_fwu_cached_directory.entries[i].image_guid,
+			    &g_esrt_data.data.entries[i].fw_class)) {
+			log_err("FWU: GUID mismatch for image %d\n", i + 1);
+			return -EINVAL;
+		}
+	}
+
+	log_debug("FWU: ESRT data check passed\n");
+
+	return 0;
+}
+
+/**
+ * fwu_read_esrt() - Read the ESRT data
+ *
+ * Description: Read the ESRT data from the Secure world.
+ *
+ * Return: 0 on success. Otherwise, failure.
+ */
+static int fwu_read_esrt(void)
+{
+	int ret, close_ret;
+	u32 handle = 0;
+	efi_guid_t esrt_guid = EFI_SYSTEM_RESOURCE_TABLE_GUID;
+	u32 esrt_data_size;
+
+	ret = fwu_open(&esrt_guid, FWU_OP_TYPE_READ, &handle);
+	if (ret) {
+		log_err("FWU: Open ESRT image failed (err: %d)\n",
+			ret);
+		return ret;
+	}
+
+	log_debug("FWU: ESRT image handle (0x%x)\n", handle);
+
+	esrt_data_size = sizeof(g_esrt_data);
+
+	ret = fwu_read_stream(handle, (u8 *)&g_esrt_data, esrt_data_size);
+	if (ret) {
+		log_err("FWU: Read ESRT image failed (err: %d)\n",
+			ret);
+		goto close_handle;
+	}
+
+	ret = fwu_esrt_sanity_check();
+	if (ret)
+		goto close_handle;
+
+	log_debug("FWU: ESRT version supported by Secure world (%llu)\n",
+		  g_esrt_data.data.fw_resource_version);
+
+close_handle:
+	/* The Update Agent can execute for an unbounded time */
+	close_ret = fwu_commit(handle, FWU_IMG_NOT_ACCEPTED, 0);
+	if (close_ret)
+		log_err("FWU: Close ESRT image handle failed (err: %d)\n",
+			close_ret);
+
+	return ret;
+}
+
 /**
  * fwu_discover_ts_sp_id() - Query the FWU partition ID
  *
@@ -1158,7 +1249,6 @@ static void EFIAPI fwu_accept_notify_exit_boot_services(struct efi_event *event,
 			efi_ret = EFI_ACCESS_DENIED;
 			goto out;
 		}
-
 	} else {
 		log_info("FWU: ExitBootServices: Booting in regular state\n");
 	}
@@ -1301,6 +1391,10 @@ efi_status_t fwu_arm_psa_get_image_info(efi_uintn_t *image_info_size,
 	if (ret)
 		return EFI_NOT_READY;
 
+	ret = fwu_read_esrt();
+	if (ret)
+		return EFI_NOT_READY;
+
 	required_image_info_size = g_fwu_cached_directory.num_images *
 		image_info_desc_size;
 
@@ -1320,15 +1414,13 @@ efi_status_t fwu_arm_psa_get_image_info(efi_uintn_t *image_info_size,
 		image_info[i].image_index = i + 1;
 
 		/* Corresponding ESRT field: FwClass */
-		guidcpy(&image_info[i].image_type_id,
-			&g_fwu_cached_directory.entries[i].image_guid);
+		guidcpy(&image_info[i].image_type_id, &g_esrt_data.entries[i].fw_class);
 
 		image_info[i].image_id = image_info[i].image_index;
 		image_info[i].image_id_name = NULL; /* Not supported */
 
 		/* Corresponding ESRT field: FwVersion */
-		image_info[i].version =
-			g_fwu_cached_directory.entries[i].img_version;
+		image_info[i].version = g_esrt_data.entries[i].fw_version;
 
 		image_info[i].version_name = NULL; /* Not supported */
 		image_info[i].size =
@@ -1347,13 +1439,13 @@ efi_status_t fwu_arm_psa_get_image_info(efi_uintn_t *image_info_size,
 
 		/* Corresponding ESRT field: LowestSupportedFwVersion */
 		image_info[i].lowest_supported_image_version =
-			g_fwu_cached_directory.entries[i].lowest_acceptable_version;
+			g_esrt_data.entries[i].lowest_supported_fw_version;
 
-		/* Corresponding ESRT field: LastAttemptVersion (not supported) */
-		image_info[i].last_attempt_version = LAST_ATTEMPT_NOT_SUP;
+		/* Corresponding ESRT field: LastAttemptVersion */
+		image_info[i].last_attempt_version = g_esrt_data.entries[i].last_attempt_version;
 
-		/* Corresponding ESRT field: LastAttemptStatus (not supported) */
-		image_info[i].last_attempt_status = LAST_ATTEMPT_NOT_SUP;
+		/* Corresponding ESRT field: LastAttemptStatus */
+		image_info[i].last_attempt_status = g_esrt_data.entries[i].last_attempt_status;
 
 		image_info[i].hardware_instance = DEFAULT_HW_INSTANCE;
 		image_info[i].dependencies = NULL; /* Not supported */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v4 18/24] fwu_arm_psa: Add ExitBootService() notification handler
  2025-07-25 15:49 [PATCH v4 00/24] Introduce Firmware Update Support for Arm PSA abdellatif.elkhlifi
                   ` (16 preceding siblings ...)
  2025-07-25 15:50 ` [PATCH v4 17/24] fwu_arm_psa: Add ESRT support abdellatif.elkhlifi
@ 2025-07-25 15:50 ` abdellatif.elkhlifi
  2025-07-25 15:50 ` [PATCH v4 19/24] efi_loader: capsule: Add runtime capsule flags checks abdellatif.elkhlifi
                   ` (6 subsequent siblings)
  24 siblings, 0 replies; 29+ messages in thread
From: abdellatif.elkhlifi @ 2025-07-25 15:50 UTC (permalink / raw)
  To: u-boot
  Cc: Abdellatif El Khlifi, Sughosh Ganu, Tom Rini, Ilias Apalodimas,
	Simon Glass, Michal Simek, Marek Vasut, Casey Connolly

From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>

Provide a weak function that can be overridden

Some boards need to perform custom actions on ExitBootService()
related to FWU. This function can be overridden by the board.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Sughosh Ganu <sughosh.ganu@linaro.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Simon Glass <sjg@chromium.org>
Cc: Michal Simek <michal.simek@amd.com>
Cc: Marek Vasut <marek.vasut+renesas@mailbox.org>
Cc: Casey Connolly <casey.connolly@linaro.org>

---

Changelog of changes:
===========================

v4:

* Update the function headers in fwu_arm_psa.c to pass kernel-doc tests

v1:

* Adding the feature

 lib/fwu_updates/fwu_arm_psa.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/lib/fwu_updates/fwu_arm_psa.c b/lib/fwu_updates/fwu_arm_psa.c
index f4302371a41..443166ea451 100644
--- a/lib/fwu_updates/fwu_arm_psa.c
+++ b/lib/fwu_updates/fwu_arm_psa.c
@@ -1216,6 +1216,19 @@ static bool fwu_all_images_accepted(const struct fwu_data *fwu_data)
 	return true;
 }
 
+/**
+ * fwu_notify_exit_boot_services() - FWU notification handler
+ *
+ * Description: Some boards need to perform custom actions on ExitBootService()
+ * related to FWU. This function can be overridden by the board.
+ *
+ * Return: EFI_SUCCESS on success. Otherwise, failure.
+ */
+efi_status_t __weak fwu_notify_exit_boot_services(void)
+{
+	return EFI_SUCCESS;
+}
+
 /**
  * fwu_accept_notify_exit_boot_services() - ExitBootServices callback
  *
@@ -1254,6 +1267,8 @@ static void EFIAPI fwu_accept_notify_exit_boot_services(struct efi_event *event,
 	}
 
 out:
+	fwu_notify_exit_boot_services();
+
 	EFI_EXIT(efi_ret);
 }
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v4 19/24] efi_loader: capsule: Add runtime capsule flags checks
  2025-07-25 15:49 [PATCH v4 00/24] Introduce Firmware Update Support for Arm PSA abdellatif.elkhlifi
                   ` (17 preceding siblings ...)
  2025-07-25 15:50 ` [PATCH v4 18/24] fwu_arm_psa: Add ExitBootService() notification handler abdellatif.elkhlifi
@ 2025-07-25 15:50 ` abdellatif.elkhlifi
  2025-07-25 15:50 ` [PATCH v4 20/24] fwu_arm_psa: corstone1000: Enable FWU support abdellatif.elkhlifi
                   ` (5 subsequent siblings)
  24 siblings, 0 replies; 29+ messages in thread
From: abdellatif.elkhlifi @ 2025-07-25 15:50 UTC (permalink / raw)
  To: u-boot
  Cc: Emekcan Aras, Abdellatif El Khlifi, Heinrich Schuchardt,
	Ilias Apalodimas, Tom Rini, Simon Glass, Adriano Cordova,
	Sughosh Ganu

From: Emekcan Aras <emekcan.aras@arm.com>

Add missing checks according to the UEFI specification [1]

checks added for these capsule flags:

CAPSULE_FLAGS_PERSIST_ACROSS_RESET
CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE
CAPSULE_FLAGS_INITIATE_RESET

[1]: Table 8.8 Flag Firmware Behavior,
        https://uefi.org/specs/UEFI/2.10/08_Services_Runtime_Services.html

Signed-off-by: Emekcan Aras <emekcan.aras@arm.com>
Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Adriano Cordova <adrianox@gmail.com>
Cc: Sughosh Ganu <sughosh.ganu@linaro.org>

---

Changelog of changes:
===========================

v2:

* As suggested by Heinrich: Simplify the logic

v1:

* Add runtime capsule flags checks

 lib/efi_loader/efi_capsule.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
index 113cfe30fde..2c8fd74365f 100644
--- a/lib/efi_loader/efi_capsule.c
+++ b/lib/efi_loader/efi_capsule.c
@@ -769,6 +769,17 @@ efi_status_t EFIAPI efi_update_capsule(
 			continue;
 		}
 
+		if (capsule->flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) {
+			if (!scatter_gather_list) {
+				ret = EFI_INVALID_PARAMETER;
+				goto out;
+			}
+		} else if (capsule->flags & (CAPSULE_FLAGS_INITIATE_RESET |
+						CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) {
+			ret = EFI_INVALID_PARAMETER;
+			goto out;
+		}
+
 		log_debug("Capsule[%d] (guid:%pUs)\n",
 			  i, &capsule->capsule_guid);
 		ret  = efi_capsule_update_firmware(capsule);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v4 20/24] fwu_arm_psa: corstone1000: Enable FWU support
  2025-07-25 15:49 [PATCH v4 00/24] Introduce Firmware Update Support for Arm PSA abdellatif.elkhlifi
                   ` (18 preceding siblings ...)
  2025-07-25 15:50 ` [PATCH v4 19/24] efi_loader: capsule: Add runtime capsule flags checks abdellatif.elkhlifi
@ 2025-07-25 15:50 ` abdellatif.elkhlifi
  2025-07-25 15:50 ` [PATCH v4 21/24] fwu_arm_psa: corstone1000: Perform bank logic when reading boot index abdellatif.elkhlifi
                   ` (4 subsequent siblings)
  24 siblings, 0 replies; 29+ messages in thread
From: abdellatif.elkhlifi @ 2025-07-25 15:50 UTC (permalink / raw)
  To: u-boot; +Cc: Abdellatif El Khlifi, Tom Rini, Hugues Kamba Mpiana

From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>

Provide the update_info structure and FWU configs for Corstone-1000

update_info defines the image to be used for FWU.
The FWU configs enabled are the FWU Arm PSA configs.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Tom Rini <trini@konsulko.com>
Cc: Hugues Kamba Mpiana <hugues.kambampiana@arm.com>
---
 board/armltd/corstone1000/corstone1000.c | 138 ++++++++++++++++++++++-
 configs/corstone1000_defconfig           |  10 +-
 2 files changed, 146 insertions(+), 2 deletions(-)

diff --git a/board/armltd/corstone1000/corstone1000.c b/board/armltd/corstone1000/corstone1000.c
index 3ad77f51949..d2176b9174d 100644
--- a/board/armltd/corstone1000/corstone1000.c
+++ b/board/armltd/corstone1000/corstone1000.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * (C) Copyright 2022 ARM Limited
+ * (C) Copyright 2022, 2025 Arm Limited
  * (C) Copyright 2022 Linaro
  * Rui Miguel Silva <rui.silva@linaro.org>
  */
@@ -8,8 +8,11 @@
 #include <blk.h>
 #include <cpu_func.h>
 #include <dm.h>
+#include <generated/dt.h>
 #include <env.h>
+#include <efi_loader.h>
 #include <fwu.h>
+#include <fwu_arm_psa.h>
 #include <netdev.h>
 #include <nvmxip.h>
 #include <part.h>
@@ -21,6 +24,133 @@
 #define CORSTONE1000_KERNEL_PRIMARY "kernel_primary"
 #define CORSTONE1000_KERNEL_SECONDARY "kernel_secondary"
 
+#if IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT)
+
+/* The total number of upgradable images including the start and end dummy payloads */
+#define CAPSULE_PAYLOADS_MAX_COUNT (CONFIG_FWU_NUM_IMAGES_PER_BANK + 2)
+
+/*
+ * GUIDs for capsule updatable firmware images
+ *
+ * The GUIDs are generating with the UUIDv5 format.
+ * Namespace used for FVP GUIDs: 989f3a4e-46e0-4cd0-9877-a25c70c01329
+ * Namespace used for MPS3 GUIDs: df1865d1-90fb-4d59-9c38-c9f2c1bba8cc
+ * Names: the image names stated in the fw_name field
+ */
+
+#define FWU_FVP_BL2_IMAGE_GUID \
+	EFI_GUID(0xf1d883f9, 0xdfeb, 0x5363, 0x98, 0xd8,	\
+		0x68, 0x6e, 0xe3, 0xb6, 0x9f, 0x4f)
+
+#define FWU_MPS3_BL2_IMAGE_GUID \
+	EFI_GUID(0xfbfbefaa, 0x0a56, 0x50d5, 0xb6, 0x51,	\
+		0x74, 0x09, 0x1d, 0x3d, 0x62, 0xcf)
+
+#define FWU_FVP_TFM_S_IMAGE_GUID \
+	EFI_GUID(0x7fad470e, 0x5ec5, 0x5c03, 0xa2, 0xc1,	\
+		0x47, 0x56, 0xb4, 0x95, 0xde, 0x61)
+
+#define FWU_MPS3_TFM_S_IMAGE_GUID \
+	EFI_GUID(0xaf4cc7ad, 0xee2e, 0x5a39, 0xaa, 0xd5,	\
+		0xfa, 0xc8, 0xa1, 0xe6, 0x17, 0x3c)
+
+#define FWU_FVP_FIP_IMAGE_GUID \
+	EFI_GUID(0xf1933675, 0x5a8c, 0x5b6d, 0x9e, 0xf4,	\
+		0x84, 0x67, 0x39, 0xe8, 0x9b, 0xc8)
+
+#define FWU_MPS3_FIP_IMAGE_GUID \
+	EFI_GUID(0x55302f96, 0xc4f0, 0x5cf9, 0x86, 0x24,	\
+		0xe7, 0xcc, 0x38, 0x8f, 0x2b, 0x68)
+
+#define FWU_FVP_INITRAMFS_IMAGE_GUID \
+	EFI_GUID(0xf771aff9, 0xc7e9, 0x5f99, 0x9e, 0xda,	\
+		0x23, 0x69, 0xdd, 0x69, 0x4f, 0x61)
+
+#define FWU_MPS3_INITRAMFS_IMAGE_GUID \
+	EFI_GUID(0x3e8ac972, 0xc33c, 0x5cc9, 0x90, 0xa0,	\
+		0xcd, 0xd3, 0x15, 0x96, 0x83, 0xea)
+
+enum fw_image_index {
+	FW_IMAGE_INDEX_BL2 = 1,
+	FW_IMAGE_INDEX_TFM_S,
+	FW_IMAGE_INDEX_FIP,
+	FW_IMAGE_INDEX_INITRAMFS,
+	FW_IMAGE_INDEX_DUMMY_START,
+	FW_IMAGE_INDEX_DUMMY_END
+};
+
+struct efi_fw_image fw_mps3_images[] = {
+	{
+		.image_type_id = FWU_MPS3_BL2_IMAGE_GUID,
+		.fw_name = u"BL2",
+		.image_index = FW_IMAGE_INDEX_BL2,
+	},
+	{
+		.image_type_id = FWU_MPS3_TFM_S_IMAGE_GUID,
+		.fw_name = u"TFM_S",
+		.image_index = FW_IMAGE_INDEX_TFM_S,
+	},
+	{
+		.image_type_id = FWU_MPS3_FIP_IMAGE_GUID,
+		.fw_name = u"FIP",
+		.image_index = FW_IMAGE_INDEX_FIP,
+	},
+	{
+		.image_type_id = FWU_MPS3_INITRAMFS_IMAGE_GUID,
+		.fw_name = u"INITRAMFS",
+		.image_index = FW_IMAGE_INDEX_INITRAMFS,
+	},
+	{
+		.image_type_id = FWU_DUMMY_START_IMAGE_GUID,
+		.fw_name = u"DUMMY_START",
+		.image_index = FW_IMAGE_INDEX_DUMMY_START,
+	},
+	{
+		.image_type_id = FWU_DUMMY_END_IMAGE_GUID,
+		.fw_name = u"DUMMY_END",
+		.image_index = FW_IMAGE_INDEX_DUMMY_END,
+	},
+};
+
+struct efi_fw_image fw_fvp_images[] = {
+	{
+		.image_type_id = FWU_FVP_BL2_IMAGE_GUID,
+		.fw_name = u"BL2",
+		.image_index = FW_IMAGE_INDEX_BL2,
+	},
+	{
+		.image_type_id = FWU_FVP_TFM_S_IMAGE_GUID,
+		.fw_name = u"TFM_S",
+		.image_index = FW_IMAGE_INDEX_TFM_S,
+	},
+	{
+		.image_type_id = FWU_FVP_FIP_IMAGE_GUID,
+		.fw_name = u"FIP",
+		.image_index = FW_IMAGE_INDEX_FIP,
+	},
+	{
+		.image_type_id = FWU_FVP_INITRAMFS_IMAGE_GUID,
+		.fw_name = u"INITRAMFS",
+		.image_index = FW_IMAGE_INDEX_INITRAMFS,
+	},
+	{
+		.image_type_id = FWU_DUMMY_START_IMAGE_GUID,
+		.fw_name = u"DUMMY_START",
+		.image_index = FW_IMAGE_INDEX_DUMMY_START,
+	},
+	{
+		.image_type_id = FWU_DUMMY_END_IMAGE_GUID,
+		.fw_name = u"DUMMY_END",
+		.image_index = FW_IMAGE_INDEX_DUMMY_END,
+	},
+};
+
+struct efi_capsule_update_info update_info = {
+	.num_images = CAPSULE_PAYLOADS_MAX_COUNT,
+};
+
+#endif /* EFI_HAVE_CAPSULE_SUPPORT */
+
 static int corstone1000_boot_idx;
 
 static struct mm_region corstone1000_mem_map[] = {
@@ -79,6 +209,12 @@ struct mm_region *mem_map = corstone1000_mem_map;
 
 int board_init(void)
 {
+#if IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT)
+	if (!strcmp(DEVICE_TREE, "corstone1000-fvp"))
+		update_info.images = fw_fvp_images;
+	else
+		update_info.images = fw_mps3_images;
+#endif
 	return 0;
 }
 
diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
index 80163580f85..5b10e3f7484 100644
--- a/configs/corstone1000_defconfig
+++ b/configs/corstone1000_defconfig
@@ -10,11 +10,16 @@ CONFIG_DEFAULT_DEVICE_TREE="corstone1000-mps3"
 CONFIG_SYS_BOOTM_LEN=0x800000
 CONFIG_SYS_LOAD_ADDR=0x82100000
 CONFIG_IDENT_STRING=" corstone1000 aarch64 "
+CONFIG_FWU_NUM_IMAGES_PER_BANK=4
 CONFIG_EFI_MM_COMM_TEE=y
 CONFIG_FFA_SHARED_MM_BUF_SIZE=4096
 CONFIG_FFA_SHARED_MM_BUF_OFFSET=0
 CONFIG_FFA_SHARED_MM_BUF_ADDR=0x02000000
+CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
 CONFIG_EFI_CAPSULE_ON_DISK=y
+CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y
+CONFIG_EFI_CAPSULE_AUTHENTICATE=y
+CONFIG_EFI_CAPSULE_CRT_FILE="CRT.crt"
 CONFIG_FIT=y
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_BOOTDELAY=3
@@ -38,6 +43,7 @@ CONFIG_CMD_LOADM=y
 CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_CACHE=y
+CONFIG_CMD_EFIDEBUG=y
 CONFIG_CMD_RTC=y
 CONFIG_CMD_TIME=y
 CONFIG_CMD_GETTIME=y
@@ -67,4 +73,6 @@ CONFIG_USB_ISP1760=y
 # CONFIG_RANDOM_UUID is not set
 CONFIG_ERRNO_STR=y
 CONFIG_FWU_MULTI_BANK_UPDATE=y
-CONFIG_FWU_MDATA_V1=y
+CONFIG_FWU_MDATA_V2=y
+CONFIG_FWU_ARM_PSA=y
+# CONFIG_TOOLS_MKEFICAPSULE is not set
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v4 21/24] fwu_arm_psa: corstone1000: Perform bank logic when reading boot index
  2025-07-25 15:49 [PATCH v4 00/24] Introduce Firmware Update Support for Arm PSA abdellatif.elkhlifi
                   ` (19 preceding siblings ...)
  2025-07-25 15:50 ` [PATCH v4 20/24] fwu_arm_psa: corstone1000: Enable FWU support abdellatif.elkhlifi
@ 2025-07-25 15:50 ` abdellatif.elkhlifi
  2025-07-25 15:50 ` [PATCH v4 22/24] fwu_arm_psa: corstone1000: Notify SE Proxy SP on ExitBootService() abdellatif.elkhlifi
                   ` (3 subsequent siblings)
  24 siblings, 0 replies; 29+ messages in thread
From: abdellatif.elkhlifi @ 2025-07-25 15:50 UTC (permalink / raw)
  To: u-boot; +Cc: Abdellatif El Khlifi, Tom Rini, Hugues Kamba Mpiana

From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>

Move bank logic from board_late_init to fwu_plat_get_bootidx

board_late_init is called very early before the FWU subsystem is setup.
So, the metadata is still not initialized at that level. Reading the boot
index at that level returns an invalid value.
Moving the bank logic to fwu_plat_get_bootidx guarantees the returned
boot index is reflecting the value read from the metadata.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Tom Rini <trini@konsulko.com>
Cc: Hugues Kamba Mpiana <hugues.kambampiana@arm.com>
---
 board/armltd/corstone1000/corstone1000.c | 63 +++++++++++-------------
 configs/corstone1000_defconfig           |  1 -
 2 files changed, 29 insertions(+), 35 deletions(-)

diff --git a/board/armltd/corstone1000/corstone1000.c b/board/armltd/corstone1000/corstone1000.c
index d2176b9174d..2ccf851e6c5 100644
--- a/board/armltd/corstone1000/corstone1000.c
+++ b/board/armltd/corstone1000/corstone1000.c
@@ -151,8 +151,6 @@ struct efi_capsule_update_info update_info = {
 
 #endif /* EFI_HAVE_CAPSULE_SUPPORT */
 
-static int corstone1000_boot_idx;
-
 static struct mm_region corstone1000_mem_map[] = {
 	{
 		/* CVM */
@@ -234,45 +232,37 @@ int dram_init_banksize(void)
 }
 
 void fwu_plat_get_bootidx(uint *boot_idx)
-{
-	int ret;
-
-	/*
-	 * in our platform, the Secure Enclave is the one who controls
-	 * all the boot tries and status, so, every time we get here
-	 * we know that the we are booting from the active index
-	 */
-	ret = fwu_get_active_index(boot_idx);
-	if (ret < 0) {
-		*boot_idx = CONFIG_FWU_NUM_BANKS;
-		log_err("corstone1000: failed to read active index\n");
-	}
-}
-
-int board_late_init(void)
 {
 	struct disk_partition part_info;
 	struct udevice *dev, *bdev;
 	struct nvmxip_plat *plat;
 	struct blk_desc *desc;
 	int ret;
+	bool kernel_addr_set, kernel_size_set;
 
 	ret = uclass_first_device_err(UCLASS_NVMXIP, &dev);
 	if (ret < 0) {
-		log_err("Cannot find kernel device\n");
-		return ret;
+		log_err("Cannot find kernel device, err (%d)\n", ret);
+		return;
 	}
 
 	plat = dev_get_plat(dev);
 	device_find_first_child(dev, &bdev);
 	desc = dev_get_uclass_plat(bdev);
-	ret = fwu_get_active_index(&corstone1000_boot_idx);
+	ret = fwu_get_active_index(boot_idx);
 	if (ret < 0) {
+		*boot_idx = CONFIG_FWU_NUM_BANKS;
 		log_err("corstone1000: failed to read boot index\n");
-		return ret;
+		return;
 	}
 
-	if (!corstone1000_boot_idx)
+	kernel_addr_set = env_get_hex("kernel_addr", 0) ? true : false;
+	kernel_size_set = env_get_hex("kernel_size", 0) ? true : false;
+
+	if (kernel_addr_set && kernel_size_set)
+		return;
+
+	if (!(*boot_idx))
 		ret = part_get_info_by_name(desc, CORSTONE1000_KERNEL_PRIMARY,
 					    &part_info);
 	else
@@ -281,18 +271,23 @@ int board_late_init(void)
 
 	if (ret < 0) {
 		log_err("failed to fetch kernel partition index: %d\n",
-			corstone1000_boot_idx);
-		return ret;
+			*boot_idx);
+		return;
 	}
 
-	ret = 0;
-
-	ret |= env_set_hex("kernel_addr", plat->phys_base +
-			   (part_info.start * part_info.blksz));
-	ret |= env_set_hex("kernel_size", part_info.size * part_info.blksz);
-
-	if (ret < 0)
-		log_err("failed to setup kernel addr and size\n");
+	if (!kernel_addr_set) {
+		ret = env_set_hex("kernel_addr", plat->phys_base +
+				(part_info.start * part_info.blksz));
+		if (ret)
+			log_err("cannot set kernel_addr variable, err (%d)\n",
+				ret);
+	}
 
-	return ret;
+	if (!kernel_size_set) {
+		ret = env_set_hex("kernel_size",
+				  part_info.size * part_info.blksz);
+		if (ret)
+			log_err("cannot set kernel_size variable, err (%d)\n",
+				ret);
+	}
 }
diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
index 5b10e3f7484..d52d39a0b36 100644
--- a/configs/corstone1000_defconfig
+++ b/configs/corstone1000_defconfig
@@ -31,7 +31,6 @@ CONFIG_SYS_CBSIZE=512
 CONFIG_LOGLEVEL=7
 # CONFIG_DISPLAY_CPUINFO is not set
 # CONFIG_DISPLAY_BOARDINFO is not set
-CONFIG_BOARD_LATE_INIT=y
 CONFIG_SYS_PROMPT="corstone1000# "
 # CONFIG_CMD_CONSOLE is not set
 CONFIG_CMD_FWU_METADATA=y
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v4 22/24] fwu_arm_psa: corstone1000: Notify SE Proxy SP on ExitBootService()
  2025-07-25 15:49 [PATCH v4 00/24] Introduce Firmware Update Support for Arm PSA abdellatif.elkhlifi
                   ` (20 preceding siblings ...)
  2025-07-25 15:50 ` [PATCH v4 21/24] fwu_arm_psa: corstone1000: Perform bank logic when reading boot index abdellatif.elkhlifi
@ 2025-07-25 15:50 ` abdellatif.elkhlifi
  2025-07-25 15:50 ` [PATCH v4 23/24] fwu_arm_psa: corstone1000: Set Boot0001 for on-disk FWU abdellatif.elkhlifi
                   ` (2 subsequent siblings)
  24 siblings, 0 replies; 29+ messages in thread
From: abdellatif.elkhlifi @ 2025-07-25 15:50 UTC (permalink / raw)
  To: u-boot; +Cc: Abdellatif El Khlifi, Tom Rini, Hugues Kamba Mpiana

From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>

Implement the notification in fwu_notify_exit_boot_services()

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Tom Rini <trini@konsulko.com>
Cc: Hugues Kamba Mpiana <hugues.kambampiana@arm.com>
---
 board/armltd/corstone1000/corstone1000.c | 60 ++++++++++++++++++++++++
 1 file changed, 60 insertions(+)

diff --git a/board/armltd/corstone1000/corstone1000.c b/board/armltd/corstone1000/corstone1000.c
index 2ccf851e6c5..2532c5f10fa 100644
--- a/board/armltd/corstone1000/corstone1000.c
+++ b/board/armltd/corstone1000/corstone1000.c
@@ -5,6 +5,7 @@
  * Rui Miguel Silva <rui.silva@linaro.org>
  */
 
+#include <arm_ffa.h>
 #include <blk.h>
 #include <cpu_func.h>
 #include <dm.h>
@@ -19,11 +20,28 @@
 #include <dm/platform_data/serial_pl01x.h>
 #include <asm/armv8/mmu.h>
 #include <asm/global_data.h>
+#include <linux/bitfield.h>
 
 #define CORSTONE1000_KERNEL_PARTS 2
 #define CORSTONE1000_KERNEL_PRIMARY "kernel_primary"
 #define CORSTONE1000_KERNEL_SECONDARY "kernel_secondary"
 
+/* The SE Proxy partition ID*/
+#define CORSTONE1000_SEPROXY_PART_ID (0x8002)
+
+/* Update service ID provided by  the SE Proxy SP*/
+#define CORSTONE1000_SEPROXY_UPDATE_SVC_ID (0x4)
+#define PREP_SEPROXY_SVC_ID_MASK GENMASK(31, 16)
+#define PREP_SEPROXY_SVC_ID(x)  (FIELD_PREP(PREP_SEPROXY_SVC_ID_MASK, (x)))
+
+/* Notification event used with SE Proxy SP */
+#define CORSTONE1000_UBOOT_EFI_STARTED_EVT (0x3)
+#define PREP_SEPROXY_EVT_MASK GENMASK(15, 0)
+#define PREP_SEPROXY_EVT(x) (FIELD_PREP(PREP_SEPROXY_EVT_MASK, (x)))
+
+/* Signal that there is no shared memory used when notifying SE Proxy SP */
+#define FFA_MEM_HANDLE_INVALID (0xffffffff)
+
 #if IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT)
 
 /* The total number of upgradable images including the start and end dummy payloads */
@@ -291,3 +309,45 @@ void fwu_plat_get_bootidx(uint *boot_idx)
 				ret);
 	}
 }
+
+/**
+ * fwu_notify_exit_boot_services() - ExitBootService event handler
+ *
+ * Notify SE Proxy SP when reaching ExitBootService().
+ *
+ * Return:
+ *
+ * EFI_SUCCESS on success. Otherwise, failure
+ */
+efi_status_t fwu_notify_exit_boot_services(void)
+{
+	efi_status_t efi_ret = EFI_SUCCESS;
+	int ffa_ret;
+	struct ffa_send_direct_data msg = {0};
+	struct udevice *dev;
+
+	ffa_ret = uclass_first_device_err(UCLASS_FFA, &dev);
+	if (ffa_ret) {
+		log_err("Cannot find FF-A bus device, err (%d)\n", ffa_ret);
+		efi_ret = EFI_DEVICE_ERROR;
+		goto out;
+	}
+
+	msg.data0 = PREP_SEPROXY_SVC_ID(CORSTONE1000_SEPROXY_UPDATE_SVC_ID) |
+					PREP_SEPROXY_EVT(CORSTONE1000_UBOOT_EFI_STARTED_EVT);
+
+	msg.data1 = FFA_MEM_HANDLE_INVALID;
+	msg.data2 = FFA_MEM_HANDLE_INVALID;
+
+	ffa_ret = ffa_sync_send_receive(dev, CORSTONE1000_SEPROXY_PART_ID, &msg, 0);
+	if (ffa_ret) {
+		log_err("Cannot notify SE Proxy SP, err (%d)\n", ffa_ret);
+		efi_ret = EFI_NO_RESPONSE;
+		goto out;
+	}
+
+	log_debug("SE Proxy SP notified\n");
+
+out:
+	return efi_ret;
+}
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v4 23/24] fwu_arm_psa: corstone1000: Set Boot0001 for on-disk FWU
  2025-07-25 15:49 [PATCH v4 00/24] Introduce Firmware Update Support for Arm PSA abdellatif.elkhlifi
                   ` (21 preceding siblings ...)
  2025-07-25 15:50 ` [PATCH v4 22/24] fwu_arm_psa: corstone1000: Notify SE Proxy SP on ExitBootService() abdellatif.elkhlifi
@ 2025-07-25 15:50 ` abdellatif.elkhlifi
  2025-07-25 15:50 ` [PATCH v4 24/24] fwu_arm_psa: Document FWU support for Arm PSA abdellatif.elkhlifi
  2025-08-20 12:33 ` [PATCH v4 00/24] Introduce Firmware Update Support " Abdellatif El Khlifi
  24 siblings, 0 replies; 29+ messages in thread
From: abdellatif.elkhlifi @ 2025-07-25 15:50 UTC (permalink / raw)
  To: u-boot; +Cc: Abdellatif El Khlifi, Tom Rini, Hugues Kamba Mpiana

From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>

Set Boot0001 to point to the ESP partition path

On-disk FWU requires setting the boot option to where the
EFI System Partition (ESP) is so U-Boot's capsule driver
can detect the ESP partition and start the FWU.

Corstone-1000 supports on-disk FWU on FVP.
The ESP partition is at mmc 1:1 and is accessible with boot option 1.

To avoid setting manually Boot0001 at factory level, Boot0001 is
set in the bootcmd. So, before starting the on-disk FWU, the bootcmd
will be executed and Boot0001 will be set automatically.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Tom Rini <trini@konsulko.com>
Cc: Hugues Kamba Mpiana <hugues.kambampiana@arm.com>
---
 board/armltd/corstone1000/corstone1000.env | 8 ++++++++
 configs/corstone1000_defconfig             | 2 +-
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/board/armltd/corstone1000/corstone1000.env b/board/armltd/corstone1000/corstone1000.env
index ee318b1b1c3..6e631b12bc2 100644
--- a/board/armltd/corstone1000/corstone1000.env
+++ b/board/armltd/corstone1000/corstone1000.env
@@ -1,5 +1,13 @@
 /* SPDX-License-Identifier: GPL-2.0+ */
 
+/*
+ * Copyright 2023, 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ */
+
 usb_pgood_delay=250
 boot_bank_flag=0x08005006
 kernel_addr_r=0x88200000
+prepare_ondisk_fwu=
+	if mmc dev 1; then
+		efidebug boot add -B 1 OnDiskFWU mmc 1:1 / ;
+	fi;
diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
index d52d39a0b36..e02fb7cca67 100644
--- a/configs/corstone1000_defconfig
+++ b/configs/corstone1000_defconfig
@@ -25,7 +25,7 @@ CONFIG_DISTRO_DEFAULTS=y
 CONFIG_BOOTDELAY=3
 CONFIG_USE_BOOTARGS=y
 CONFIG_BOOTARGS="console=ttyAMA0 loglevel=9 ip=dhcp earlyprintk"
-CONFIG_BOOTCOMMAND="echo Loading kernel from $kernel_addr to memory ... ; unzip $kernel_addr 0x90000000; loadm 0x90000000 $kernel_addr_r $filesize; usb start; usb reset; run distro_bootcmd; bootefi $kernel_addr_r $fdtcontroladdr;"
+CONFIG_BOOTCOMMAND="echo Loading kernel from $kernel_addr to memory ... ; unzip $kernel_addr 0x90000000; loadm 0x90000000 $kernel_addr_r $filesize; usb start; usb reset; run prepare_ondisk_fwu ; run distro_bootcmd; bootefi $kernel_addr_r $fdtcontroladdr;"
 CONFIG_CONSOLE_RECORD=y
 CONFIG_SYS_CBSIZE=512
 CONFIG_LOGLEVEL=7
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v4 24/24] fwu_arm_psa: Document FWU support for Arm PSA
  2025-07-25 15:49 [PATCH v4 00/24] Introduce Firmware Update Support for Arm PSA abdellatif.elkhlifi
                   ` (22 preceding siblings ...)
  2025-07-25 15:50 ` [PATCH v4 23/24] fwu_arm_psa: corstone1000: Set Boot0001 for on-disk FWU abdellatif.elkhlifi
@ 2025-07-25 15:50 ` abdellatif.elkhlifi
  2025-08-20 12:33 ` [PATCH v4 00/24] Introduce Firmware Update Support " Abdellatif El Khlifi
  24 siblings, 0 replies; 29+ messages in thread
From: abdellatif.elkhlifi @ 2025-07-25 15:50 UTC (permalink / raw)
  To: u-boot
  Cc: Abdellatif El Khlifi, Davidson kumaresan, Heinrich Schuchardt,
	Sughosh Ganu, Tom Rini, Ilias Apalodimas, Simon Glass,
	Michal Simek, Marek Vasut, Casey Connolly, Adriano Cordova

From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>

Add documentation

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Signed-off-by: Davidson kumaresan <davidson.kumaresan@arm.com>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
Cc: Sughosh Ganu <sughosh.ganu@linaro.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Simon Glass <sjg@chromium.org>
Cc: Michal Simek <michal.simek@amd.com>
Cc: Marek Vasut <marek.vasut+renesas@mailbox.org>
Cc: Casey Connolly <casey.connolly@linaro.org>
Cc: Adriano Cordova <adrianox@gmail.com>

---

Changelog of changes:
===========================

v2:

* As suggested by Heinrich: Removing the Corstone-1000 specific information
    and addressing nits

v1:

* Add documentation

 MAINTAINERS                      |   1 +
 doc/develop/uefi/fwu_arm_psa.rst | 154 +++++++++++++++++++++++++++++++
 doc/develop/uefi/index.rst       |   1 +
 3 files changed, 156 insertions(+)
 create mode 100644 doc/develop/uefi/fwu_arm_psa.rst

diff --git a/MAINTAINERS b/MAINTAINERS
index fdf34c74049..a75bc1d2379 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1231,6 +1231,7 @@ FWU ARM PSA
 M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
 M:	Davidson kumaresan <davidson.kumaresan@arm.com>
 S:	Maintained
+F:	doc/develop/uefi/fwu_arm_psa.rst
 F:	include/fwu_arm_psa.h
 F:	lib/fwu_updates/fwu_arm_psa.c
 
diff --git a/doc/develop/uefi/fwu_arm_psa.rst b/doc/develop/uefi/fwu_arm_psa.rst
new file mode 100644
index 00000000000..8f27d31483b
--- /dev/null
+++ b/doc/develop/uefi/fwu_arm_psa.rst
@@ -0,0 +1,154 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
+
+Firmware Update (FWU) Support for Arm PSA
+==========================================
+
+U-Boot implements Firmware Update (FWU) support for Arm `PSA Certified`_
+platforms.
+
+The feature aligns with the Platform Security Firmware Update
+specification for the A-profile Arm Architecture
+(see `DEN0118 v1.0 A specification`_) and leverages the Trusted Services (TS)
+framework to interact with Secure world update agent.
+
+Overview
+--------
+
+The FWU subsystem enables secure  firmware updates by
+delegating the update management to a Secure world agent. U-Boot acts as the
+FWU client, coordinating updates via a well-defined set of ABIs over the FF-A
+interface (see :doc:`Arm FF-A Support <../../arch/arm64.ffa>`).
+
+FWU for Arm PSA supports both on-disk and standard capsule updates.
+
+Key Features
+------------
+
+1. PSA Firmware Update Initialization
+-------------------------------------
+
+- Initialization of the update agent using the FF-A transport and discovery of
+  the Trusted Services FWU SP.
+
+- Discovery of the version of the ABIs using FWU_DISCOVER ABI.
+
+- Establishment and sharing of communication buffers between U-Boot
+  (Normal world) and Secure world.
+
+2. ESRT Support
+---------------
+
+Retrieval of ESRT (EFI System Resource Table) data from Secure world using
+FWU_READ_STREAM ABI, enabling compliance with UEFI standards
+(see `UEFI v2.10 specification`_).
+
+3. UEFI Capsule Handling
+------------------------
+
+- Runtime checks for capsule flags as per UEFI 2.10 specification:
+
+    - CAPSULE_FLAGS_PERSIST_ACROSS_RESET
+
+    - CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE
+
+    - CAPSULE_FLAGS_INITIATE_RESET
+
+- Support for keeping the FMP payload header in Arm PSA mode to preserve
+  critical metadata required by Secure world.
+
+4. Staging and Update Flow
+--------------------------
+
+- Full support for update staging flow as per PSA spec:
+
+    - FWU_BEGIN_STAGING
+
+    - FWU_END_STAGING
+
+    - FWU_CANCEL_STAGING
+
+    - FWU_WRITE_STREAM
+
+- Capsules can contain multiple payloads (including start/end markers
+  and the update content).
+
+5. Directory Access
+-------------------
+
+- Reading the FWU directory from Secure world using FWU_READ_STREAM ABI.
+
+6. Image Update Lifecycle
+-------------------------
+
+- Implementation of get_image_info() and set_image() using raw EFI firmware
+  services provided by the FMP driver for raw images.
+
+- FWU_ACCEPT_IMAGE ABI issued on ExitBootServices() to commit successfully
+  booted trial images.
+
+- Option to disable automatic acceptance on ExitBootServices() via
+  CONFIG_FWU_ARM_PSA_ACCEPT_IMAGES.
+
+Configuration Options
+---------------------
+
+To enable FWU support for Arm PSA, enable the following options in your board
+configuration:
+
+CONFIG_FWU_ARM_PSA
+     enables the PSA-compliant firmware update client in U-Boot.
+
+CONFIG_FWU_ARM_PSA_ACCEPT_IMAGES
+     enables auto-acceptance on ExitBootServices(). Disable this setting
+     if auto-acceptance shall be handled at a later boot stage.
+
+Platform Integration: Corstone-1000
+-----------------------------------
+
+`Corstone-1000`_ is the reference implementation for the FWU Arm PSA feature.
+
+ABIs Implemented
+----------------
+
+The following ABIs from the PSA FWU specification have been implemented:
+
+    - FWU_DISCOVER
+
+    - FWU_BEGIN_STAGING
+
+    - FWU_END_STAGING
+
+    - FWU_CANCEL_STAGING
+
+    - FWU_OPEN
+
+    - FWU_WRITE_STREAM
+
+    - FWU_READ_STREAM
+
+    - FWU_COMMIT
+
+    - FWU_ACCEPT_IMAGE
+
+ExitBootServices() Integration
+------------------------------
+
+- The U-Boot FWU client performs several key actions during ExitBootServices():
+
+- Notifies Secure world about successful boot.
+
+- Accepts updated images in trial state.
+
+- Supports board-level override of fwu_notify_exit_boot_services() for custom
+  behavior.
+
+Contributors
+------------
+   * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+   * Davidson kumaresan <davidson.kumaresan@arm.com>
+
+.. _`DEN0118 v1.0 A specification`: https://developer.arm.com/documentation/den0118/latest/
+.. _`PSA Certified`: https://www.psacertified.org/
+.. _`UEFI v2.10 specification`: https://uefi.org/specs/UEFI/2.10/
+.. _`Corstone-1000`: https://corstone1000.docs.arm.com/en/latest/software-architecture.html
diff --git a/doc/develop/uefi/index.rst b/doc/develop/uefi/index.rst
index e26b1fbe05c..573630740a0 100644
--- a/doc/develop/uefi/index.rst
+++ b/doc/develop/uefi/index.rst
@@ -10,6 +10,7 @@ can be run an UEFI payload.
 .. toctree::
    :maxdepth: 2
 
+   fwu_arm_psa.rst
    uefi.rst
    u-boot_on_efi.rst
    iscsi.rst
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* Re: [PATCH v4 12/24] efi_loader: fwu_arm_psa: Add set_image and get_image_info support
  2025-07-25 15:49 ` [PATCH v4 12/24] efi_loader: fwu_arm_psa: Add set_image and get_image_info support abdellatif.elkhlifi
@ 2025-08-20 12:28   ` Ilias Apalodimas
  2025-08-20 15:16     ` Tom Rini
  0 siblings, 1 reply; 29+ messages in thread
From: Ilias Apalodimas @ 2025-08-20 12:28 UTC (permalink / raw)
  To: abdellatif.elkhlifi, Tom Rini
  Cc: u-boot, Davidson kumaresan, Heinrich Schuchardt, Sughosh Ganu,
	Simon Glass, Michal Simek, Marek Vasut, Casey Connolly,
	Adriano Cordova

Hi Abdelllatif

On Fri, 25 Jul 2025 at 18:50, <abdellatif.elkhlifi@arm.com> wrote:
>
> From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>
> Implement set_image and get_image_info through RAW functions
>
> The implementation is done using efi_firmware_raw_set_image()
> and efi_firmware_get_image_info()
>
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> Signed-off-by: Davidson kumaresan <davidson.kumaresan@arm.com>
> Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
> Cc: Sughosh Ganu <sughosh.ganu@linaro.org>
> Cc: Tom Rini <trini@konsulko.com>
> Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> Cc: Simon Glass <sjg@chromium.org>
> Cc: Michal Simek <michal.simek@amd.com>
> Cc: Marek Vasut <marek.vasut+renesas@mailbox.org>
> Cc: Casey Connolly <casey.connolly@linaro.org>
> Cc: Adriano Cordova <adrianox@gmail.com>
>
> ---
>
> Changelog of changes:
> ===========================
>
> v2:
>
> * Following Heinrich comment: The changes at efi_firmware_raw_set_image()
>     simplified by removing the "else" so it is clear we are just adding FWU_ARM_PSA
>     support and skipping the use of DFU in case of FWU_ARM_PSA
>
> v1:
>
> * Add set_image and get_image_info support for FWU_ARM_PSA
>
>  lib/efi_loader/efi_firmware.c | 35 +++++++++++++++++++++++++++++++----
>  1 file changed, 31 insertions(+), 4 deletions(-)
>
> diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
> index 75501e21557..38945b34e7b 100644
> --- a/lib/efi_loader/efi_firmware.c
> +++ b/lib/efi_loader/efi_firmware.c
> @@ -4,6 +4,12 @@
>   *
>   *  Copyright (c) 2020 Linaro Limited
>   *                     Author: AKASHI Takahiro
> + *
> + * Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
> + *
> + * Authors:
> + *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + *   Davidson kumaresan <davidson.kumaresan@arm.com>

Copyright updates are usually done on significant contributions. I am
not this qualifies as such.
Tom is there a policy for that in U-Boot docs?

>   */
>
>  #define LOG_CATEGORY LOGC_EFI
> @@ -14,6 +20,7 @@
>  #include <efi_variable.h>
>  #include <env.h>
>  #include <fwu.h>
> +#include <fwu_arm_psa.h>
>  #include <image.h>
>  #include <signatures.h>
>
> @@ -601,10 +608,21 @@ efi_status_t EFIAPI efi_firmware_get_image_info(
>              !descriptor_size || !package_version || !package_version_name))
>                 return EFI_EXIT(EFI_INVALID_PARAMETER);
>
> -       ret = efi_fill_image_desc_array(image_info_size, image_info,
> -                                       descriptor_version, descriptor_count,
> -                                       descriptor_size, package_version,
> -                                       package_version_name);
> +       if (IS_ENABLED(CONFIG_FWU_ARM_PSA)) {
> +               ret = fwu_arm_psa_get_image_info(image_info_size, image_info,
> +                                                descriptor_version,
> +                                                descriptor_count,
> +                                                descriptor_size,
> +                                                package_version,
> +                                                package_version_name);
> +       } else {
> +               ret = efi_fill_image_desc_array(image_info_size, image_info,
> +                                               descriptor_version,
> +                                               descriptor_count,
> +                                               descriptor_size,
> +                                               package_version,
> +                                               package_version_name);
> +       }

Since the functions above seem to accept the same arguments, why don't
we you define your own version of efi_fill_image_desc_array() if PSA
is enabled?
GetImageInfo() is defined by the EFI spec and I'd like to keep it as
abstracted as possible from the internal implementation details.


>
>         return EFI_EXIT(ret);
>  }
> @@ -749,6 +767,15 @@ efi_status_t EFIAPI efi_firmware_raw_set_image(
>         if (status != EFI_SUCCESS)
>                 return EFI_EXIT(status);
>
> +       if (IS_ENABLED(CONFIG_FWU_ARM_PSA)) {
> +               if (fwu_update_image(image, image_index, image_size))
> +                       return EFI_EXIT(EFI_DEVICE_ERROR);
> +
> +               efi_firmware_set_fmp_state_var(&state, image_index);
> +
> +               return EFI_EXIT(EFI_SUCCESS);
> +       }
> +
>         /*
>          * dfu_alt_num is assigned from 0 while image_index starts from 1.
>          * dfu_alt_num is calculated by (image_index - 1) when multi bank update
> --
> 2.25.1
>

Thanks
/Ilias

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v4 00/24] Introduce Firmware Update Support for Arm PSA
  2025-07-25 15:49 [PATCH v4 00/24] Introduce Firmware Update Support for Arm PSA abdellatif.elkhlifi
                   ` (23 preceding siblings ...)
  2025-07-25 15:50 ` [PATCH v4 24/24] fwu_arm_psa: Document FWU support for Arm PSA abdellatif.elkhlifi
@ 2025-08-20 12:33 ` Abdellatif El Khlifi
  24 siblings, 0 replies; 29+ messages in thread
From: Abdellatif El Khlifi @ 2025-08-20 12:33 UTC (permalink / raw)
  To: Heinrich Schuchardt, Michal Simek
  Cc: Tom Rini, Simon Glass, Sughosh Ganu, Ilias Apalodimas,
	Jens Wiklander, Marek Vasut, Casey Connolly, Adriano Cordova,
	Mattijs Korpershoek, Davidson kumaresan, Hugues Kamba Mpiana,
	Adam Johnston, u-boot

Hi Heinrich, Michal,

> This patch series adds Firmware Update (FWU) support for Arm PSA
> Certified platforms [1], enabling U-Boot to serve as
> the FWU Client, with the Secure World acting as the Update Agent that
> manages the firmware store and its metadata.
> 
> This implementation adheres to the Platform Security Firmware Update
> specification [3] for the A-profile Arm Architecture and leverages the
> Trusted Services framework [4] to interact with the Secure World update
> agent. By delegating update management to the Secure World, U-Boot
> handles only the client-side coordination, invoking a well-defined set
> of ABIs over the FF-A interface [5] to deliver update capsules.
> 
> Key features include:
> 
> - Generic, platform-agnostic design.
> - FF-A-based ABI: All interactions between U-Boot and the update agent
>     occur over the FF-A interface, ensuring compatibility across
>     PSA-compliant systems.
> - Multi-payload capsules: Support for capsules containing multiple
>     payloads, start/end markers, signed firmware images.
> - ESRT support: Capsule payloads may be signed for authenticity, and
>     U-Boot can populate the EFI System Resource Table (ESRT) for
>      OS-level firmware management.
> - On-disk and standard capsule handling.
> 
> For implementation details, please refer to the documentation [6].
> For a real world example, please see the Arm PSA FWU logs [7] when used
> for on-disk capsule update in Corstone-1000 [2].
> 
> Changes in v4:
> 
> - Update the function headers in fwu_arm_psa.c to pass kernel-doc tests
> 
> Cheers,
> Abdellatif
> 
> [1]: PSA: https://www.psacertified.org
> [2]: Corstone-1000: https://developer.arm.com/Processors/Corstone-1000
> [3]: DEN0118 v1.0 A specification: https://developer.arm.com/documentation/den0118/latest 
> [4]: Trusted Services documentation: https://trusted-services.readthedocs.io/en/stable
> [5]: FF-A interface: doc/arch/arm64.ffa.rst
> [6]: Documentation of the FWU for Arm PSA support: doc/develop/uefi/fwu_arm_psa.rst
> [7]: Arm PSA FWU logs when used for on-disk capsule update in Corstone-1000
> 
> ```
> CapsuleApp: capsule block/size              0xDD741040/0x25ACE
> Found EFI system partition on Boot0001: OnDiskFWU
> FS2:;HD0b:;BLK4: 
> Succeed to write edk2-corstone1000-fvp-v6.uefi.capsule
> resetting ...
> NOTICE:  BL2: v2.11.0(debug):v2.11.0-dirty
> ...
> U-Boot 2025.07-rc5 (Jul 10 2025 - 15:23:22 +0000) corstone1000 aarch64 
> ...
> FWU: System booting in Regular State
> FWU: ABI version 1.0 detected
> FWU: Updating 1 payload(s)
> Applying capsule edk2-corstone1000-fvp-v6.uefi.capsule succeeded.
> Reboot after firmware update.
> NOTICE:  BL2: v2.11.0(debug):v2.11.0-dirty
> ...
> U-Boot 2025.07-rc5 (Jul 10 2025 - 15:23:22 +0000) corstone1000 aarch64 
> ...
> FWU: System booting in Trial State
> ...
> Poky (Yocto Project Reference Distro) 5.2 corstone1000-fvp /dev/ttyAMA0
> ...
> root@corstone1000-fvp:~# reboot
> ...
> U-Boot 2025.07-rc5 (Jul 10 2025 - 15:23:22 +0000) corstone1000 aarch64 
> ...
> FWU: System booting in Regular State
> ...
> Poky (Yocto Project Reference Distro) 5.2 corstone1000-fvp /dev/ttyAMA0
> 
> corstone1000-fvp login:
> 
> root@corstone1000-fvp:~# cat /sys/firmware/efi/esrt/entries/entry*/*
> 0x0
> f1d883f9-dfeb-5363-98d8-686ee3b69f4f
> 0
> 6
> 0
> 6
> 0
> 0x0
> 7fad470e-5ec5-5c03-a2c1-4756b495de61
> 0
> 0
> 0
> 0
> 0
> 0x0
> f1933675-5a8c-5b6d-9ef4-846739e89bc8
> 0
> 0
> 0
> 0
> 0
> 0x0
> f771aff9-c7e9-5f99-9eda-2369dd694f61
> 0
> 0
> 0
> 0
> 0
> root@corstone1000-fvp:~# 
> ```

This is a gentle reminder regarding the review of my patchset.
All review comments have been addressed in the latest version.

For your convenience, here are the test instructions for evaluating the Arm PSA
Firmware Update (FWU) on the Fixed Virtual Platform (FVP):

1) Building the Software Stack on Corstone-1000:

    Please refer to the Corstone-1000 User Guide [1] for detailed build and
    configuration steps.

2) Generating Capsules and Testing on FVP:

    Instructions for creating firmware update capsules and running the tests on
    the FVP can be found here [2].

Your review and feedback would be greatly appreciated.

Cheers
Abdellatif

[1]: https://git.yoctoproject.org/meta-arm/tree/meta-arm-bsp/documentation/corstone1000/user-guide.rst
[2]: https://git.yoctoproject.org/meta-arm/tree/meta-arm-bsp/documentation/corstone1000/user-guide.rst#n838

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v4 14/24] efi_loader: fwu: fwu_arm_psa: Skip accepting the payload after set_image()
  2025-07-25 15:50 ` [PATCH v4 14/24] efi_loader: fwu: fwu_arm_psa: Skip accepting the payload after set_image() abdellatif.elkhlifi
@ 2025-08-20 12:37   ` Ilias Apalodimas
  0 siblings, 0 replies; 29+ messages in thread
From: Ilias Apalodimas @ 2025-08-20 12:37 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: u-boot, Heinrich Schuchardt, Sughosh Ganu, Tom Rini, Simon Glass,
	Michal Simek, Marek Vasut, Casey Connolly, Adriano Cordova

 ?

On Fri, 25 Jul 2025 at 18:50, <abdellatif.elkhlifi@arm.com> wrote:
>
> From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>
> Do not update the acceptance metadata bit after updating an image
>
> The update agent (secure world) is responsible of setting the acceptance

[...]

>
> diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
> index 234e3c1b3c0..1dac691d24d 100644
> --- a/lib/efi_loader/efi_capsule.c
> +++ b/lib/efi_loader/efi_capsule.c
> @@ -696,17 +696,20 @@ static efi_status_t efi_capsule_update_firmware(
>                                 status = fwu_clear_accept_image(image_type_id,
>                                                                 update_index);
>                         }
> -                       ret = fwu_to_efi_error(status);
> -                       if (ret != EFI_SUCCESS) {
> -                               log_err("Unable to %s the accept bit for the image %pUs\n",
> -                                       fw_accept_os ? "clear" : "set",
> -                                       image_type_id);
> -                               goto out;
> -                       }
>
> -                       log_debug("%s the accepted bit for Image %pUs\n",
> -                                 fw_accept_os ? "Cleared" : "Set",
> -                                 image_type_id);
> +                       if (!IS_ENABLED(CONFIG_FWU_ARM_PSA)) {

The function above always returns EFI_SUCCESS if PSA is enabled

> +                               ret = fwu_to_efi_error(status);
> +                               if (ret != EFI_SUCCESS) {
> +                                       log_err("Unable to %s the accept bit for the image %pUs\n",
> +                                               fw_accept_os ? "clear" : "set",
> +                                               image_type_id);
> +                                       goto out;
> +                               }
> +
> +                               log_debug("%s the accepted bit for Image %pUs\n",
> +                                         fw_accept_os ? "Cleared" : "Set",
> +                                         image_type_id);

I don't think we need more ifdefery here. Just slightly tweak the %s
prints in case PSA is enabled.
Something like
log_debug("%s %s the accepted bit for image %pUs\n",
IS_ENABLED(CONFIG_FWU_ARM_PSA) ? "PSA will" : "", fw_accept_os ?
"Cleared" : "Set", etc etc

> +                       }
>                 }
>
>         }
> diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c
> index 7f085a0211f..46b6f9356a7 100644
> --- a/lib/fwu_updates/fwu.c
> +++ b/lib/fwu_updates/fwu.c
> @@ -1,6 +1,11 @@
>  // SPDX-License-Identifier: GPL-2.0-or-later
>  /*
>   * Copyright (c) 2022, Linaro Limited
> + *
> + * Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
> + *
> + * Author:
> + *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   */

I've pinged Tom about the copyright updates, I don't think this is
such a big change that justifies it

>
>  #include <dm.h>
> @@ -586,6 +591,14 @@ out:
>   */
>  int fwu_accept_image(efi_guid_t *img_type_id, u32 bank)
>  {
> +       /*
> +        * In case of Arm PSA accepting images is either
[...]

Thanks
/Ilias

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v4 12/24] efi_loader: fwu_arm_psa: Add set_image and get_image_info support
  2025-08-20 12:28   ` Ilias Apalodimas
@ 2025-08-20 15:16     ` Tom Rini
  0 siblings, 0 replies; 29+ messages in thread
From: Tom Rini @ 2025-08-20 15:16 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: abdellatif.elkhlifi, u-boot, Davidson kumaresan,
	Heinrich Schuchardt, Sughosh Ganu, Simon Glass, Michal Simek,
	Marek Vasut, Casey Connolly, Adriano Cordova

[-- Attachment #1: Type: text/plain, Size: 2431 bytes --]

On Wed, Aug 20, 2025 at 03:28:22PM +0300, Ilias Apalodimas wrote:
> Hi Abdelllatif
> 
> On Fri, 25 Jul 2025 at 18:50, <abdellatif.elkhlifi@arm.com> wrote:
> >
> > From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> >
> > Implement set_image and get_image_info through RAW functions
> >
> > The implementation is done using efi_firmware_raw_set_image()
> > and efi_firmware_get_image_info()
> >
> > Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > Signed-off-by: Davidson kumaresan <davidson.kumaresan@arm.com>
> > Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
> > Cc: Sughosh Ganu <sughosh.ganu@linaro.org>
> > Cc: Tom Rini <trini@konsulko.com>
> > Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> > Cc: Simon Glass <sjg@chromium.org>
> > Cc: Michal Simek <michal.simek@amd.com>
> > Cc: Marek Vasut <marek.vasut+renesas@mailbox.org>
> > Cc: Casey Connolly <casey.connolly@linaro.org>
> > Cc: Adriano Cordova <adrianox@gmail.com>
> >
> > ---
> >
> > Changelog of changes:
> > ===========================
> >
> > v2:
> >
> > * Following Heinrich comment: The changes at efi_firmware_raw_set_image()
> >     simplified by removing the "else" so it is clear we are just adding FWU_ARM_PSA
> >     support and skipping the use of DFU in case of FWU_ARM_PSA
> >
> > v1:
> >
> > * Add set_image and get_image_info support for FWU_ARM_PSA
> >
> >  lib/efi_loader/efi_firmware.c | 35 +++++++++++++++++++++++++++++++----
> >  1 file changed, 31 insertions(+), 4 deletions(-)
> >
> > diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
> > index 75501e21557..38945b34e7b 100644
> > --- a/lib/efi_loader/efi_firmware.c
> > +++ b/lib/efi_loader/efi_firmware.c
> > @@ -4,6 +4,12 @@
> >   *
> >   *  Copyright (c) 2020 Linaro Limited
> >   *                     Author: AKASHI Takahiro
> > + *
> > + * Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
> > + *
> > + * Authors:
> > + *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + *   Davidson kumaresan <davidson.kumaresan@arm.com>
> 
> Copyright updates are usually done on significant contributions. I am
> not this qualifies as such.
> Tom is there a policy for that in U-Boot docs?

We don't have a formal policy, but indeed it's my understanding that
copyright claims need to be for "significant contributions" as well.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2025-08-20 15:17 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-25 15:49 [PATCH v4 00/24] Introduce Firmware Update Support for Arm PSA abdellatif.elkhlifi
2025-07-25 15:49 ` [PATCH v4 01/24] arm_ffa: Add FFA_MEM_SHARE support abdellatif.elkhlifi
2025-07-25 15:49 ` [PATCH v4 02/24] arm_ffa: Add FFA_MEM_RECLAIM support abdellatif.elkhlifi
2025-07-25 15:49 ` [PATCH v4 03/24] arm_ffa: sandbox: Replace the emulator error log with debug log abdellatif.elkhlifi
2025-07-25 15:49 ` [PATCH v4 04/24] arm_ffa: sandbox: Improve the readability of clearing the X registers abdellatif.elkhlifi
2025-07-25 15:49 ` [PATCH v4 05/24] arm_ffa: sandbox: Add FFA_MEM_SHARE emulation abdellatif.elkhlifi
2025-07-25 15:49 ` [PATCH v4 06/24] arm_ffa: sandbox: Add FFA_MEM_SHARE tests abdellatif.elkhlifi
2025-07-25 15:49 ` [PATCH v4 07/24] arm_ffa: sandbox: Add FFA_MEM_RECLAIM emulation abdellatif.elkhlifi
2025-07-25 15:49 ` [PATCH v4 08/24] arm_ffa: sandbox: Add FFA_MEM_RECLAIM tests abdellatif.elkhlifi
2025-07-25 15:49 ` [PATCH v4 09/24] fwu_arm_psa: Initialize the update agent abdellatif.elkhlifi
2025-07-25 15:49 ` [PATCH v4 10/24] fwu_arm_psa: Read the FWU directory through get_image_info() abdellatif.elkhlifi
2025-07-25 15:49 ` [PATCH v4 11/24] fwu_arm_psa: Add staging ABIs abdellatif.elkhlifi
2025-07-25 15:49 ` [PATCH v4 12/24] efi_loader: fwu_arm_psa: Add set_image and get_image_info support abdellatif.elkhlifi
2025-08-20 12:28   ` Ilias Apalodimas
2025-08-20 15:16     ` Tom Rini
2025-07-25 15:49 ` [PATCH v4 13/24] efi_loader: fwu_arm_psa: Keep the FMP payload header abdellatif.elkhlifi
2025-07-25 15:50 ` [PATCH v4 14/24] efi_loader: fwu: fwu_arm_psa: Skip accepting the payload after set_image() abdellatif.elkhlifi
2025-08-20 12:37   ` Ilias Apalodimas
2025-07-25 15:50 ` [PATCH v4 15/24] efi_loader: fwu: fwu_arm_psa: Disable trial state handling abdellatif.elkhlifi
2025-07-25 15:50 ` [PATCH v4 16/24] fwu_arm_psa: Add FWU acceptance mechanism abdellatif.elkhlifi
2025-07-25 15:50 ` [PATCH v4 17/24] fwu_arm_psa: Add ESRT support abdellatif.elkhlifi
2025-07-25 15:50 ` [PATCH v4 18/24] fwu_arm_psa: Add ExitBootService() notification handler abdellatif.elkhlifi
2025-07-25 15:50 ` [PATCH v4 19/24] efi_loader: capsule: Add runtime capsule flags checks abdellatif.elkhlifi
2025-07-25 15:50 ` [PATCH v4 20/24] fwu_arm_psa: corstone1000: Enable FWU support abdellatif.elkhlifi
2025-07-25 15:50 ` [PATCH v4 21/24] fwu_arm_psa: corstone1000: Perform bank logic when reading boot index abdellatif.elkhlifi
2025-07-25 15:50 ` [PATCH v4 22/24] fwu_arm_psa: corstone1000: Notify SE Proxy SP on ExitBootService() abdellatif.elkhlifi
2025-07-25 15:50 ` [PATCH v4 23/24] fwu_arm_psa: corstone1000: Set Boot0001 for on-disk FWU abdellatif.elkhlifi
2025-07-25 15:50 ` [PATCH v4 24/24] fwu_arm_psa: Document FWU support for Arm PSA abdellatif.elkhlifi
2025-08-20 12:33 ` [PATCH v4 00/24] Introduce Firmware Update Support " Abdellatif El Khlifi

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.