summaryrefslogtreecommitdiff
path: root/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0011-efi-corstone1000-fwu-introduce-EFI-capsule-update.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0011-efi-corstone1000-fwu-introduce-EFI-capsule-update.patch')
-rw-r--r--meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0011-efi-corstone1000-fwu-introduce-EFI-capsule-update.patch409
1 files changed, 409 insertions, 0 deletions
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0011-efi-corstone1000-fwu-introduce-EFI-capsule-update.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0011-efi-corstone1000-fwu-introduce-EFI-capsule-update.patch
new file mode 100644
index 0000000000..d2c440c828
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0011-efi-corstone1000-fwu-introduce-EFI-capsule-update.patch
@@ -0,0 +1,409 @@
+From 90b2741149a538c93aed61522c0d3363351bd578 Mon Sep 17 00:00:00 2001
+From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+Date: Mon, 17 Jul 2023 15:56:18 +0100
+Subject: [PATCH 11/33] efi: corstone1000: fwu: introduce EFI capsule update
+
+This commit provides capsule update feature for Corstone1000.
+
+This feature is available before and after ExitBootServices().
+
+A platform specific capsule buffer is allocated. This buffer
+is physically contiguous and allocated at the start of the DDR
+memory after u-boot relocation to the end of DDR.
+
+The capsule buffer is shared between u-boot and the secure world.
+
+On UpdateCapsule() , capsule data is copied to the buffer and a buffer ready event is generated using FF-A transport.
+
+On efi_init_capsule() in U-Boot, an EFI started event is sent to SE Proxy FW update service. This event is generated on each boot.
+
+Note: The SE proxy SP requires that the interface/event IDs are passed using register w4 for the buffer ready event and the EFI started event.
+
+ interface ID (31:16)
+ event ID (15:0)
+
+Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+Signed-off-by: Vishnu Banavath <vishnu.banavath@arm.com>
+Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
+Upstream-Status: Pending [Not submitted to upstream yet]
+---
+ board/armltd/corstone1000/corstone1000.c | 4 +
+ configs/corstone1000_defconfig | 3 +
+ include/configs/corstone1000.h | 24 ++++
+ include/efi_loader.h | 4 +-
+ lib/efi_loader/efi_boottime.c | 7 ++
+ lib/efi_loader/efi_capsule.c | 136 ++++++++++++++++++++++-
+ lib/efi_loader/efi_setup.c | 64 +++++++++++
+ 7 files changed, 238 insertions(+), 4 deletions(-)
+
+diff --git a/board/armltd/corstone1000/corstone1000.c b/board/armltd/corstone1000/corstone1000.c
+index 6ec8e6144f..c840290885 100644
+--- a/board/armltd/corstone1000/corstone1000.c
++++ b/board/armltd/corstone1000/corstone1000.c
+@@ -67,6 +67,10 @@ static struct mm_region corstone1000_mem_map[] = {
+
+ struct mm_region *mem_map = corstone1000_mem_map;
+
++void set_dfu_alt_info(char *interface, char *devstr)
++{
++}
++
+ int board_init(void)
+ {
+ return 0;
+diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
+index ee5481b63c..40ba415ecb 100644
+--- a/configs/corstone1000_defconfig
++++ b/configs/corstone1000_defconfig
+@@ -58,3 +58,6 @@ 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_FIRMWARE_FIT=y
++CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y
+diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h
+index 3347c11792..8927b09499 100644
+--- a/include/configs/corstone1000.h
++++ b/include/configs/corstone1000.h
+@@ -14,6 +14,30 @@
+
+ #include <linux/sizes.h>
+
++/* The SE Proxy partition ID*/
++#define CORSTONE1000_SEPROXY_PART_ID (0x8002)
++
++/* Update service ID provided by the SE Proxy secure partition*/
++#define CORSTONE1000_SEPROXY_UPDATE_SVC_ID (0x4)
++
++/* Notification events used with SE Proxy update service */
++#define CORSTONE1000_BUFFER_READY_EVT (0x1)
++#define CORSTONE1000_UBOOT_EFI_STARTED_EVT (0x2)
++
++#define PREP_SEPROXY_SVC_ID_MASK GENMASK(31, 16)
++#define PREP_SEPROXY_SVC_ID(x) (FIELD_PREP(PREP_SEPROXY_SVC_ID_MASK, (x)))
++
++#define PREP_SEPROXY_EVT_MASK GENMASK(15, 0)
++#define PREP_SEPROXY_EVT(x) (FIELD_PREP(PREP_SEPROXY_EVT_MASK, (x)))
++
++/* Size in 4KB pages of the EFI capsule buffer */
++#define CORSTONE1000_CAPSULE_BUFFER_SIZE (8192) /* 32 MB */
++
++/* Capsule GUID */
++#define EFI_CORSTONE1000_CAPSULE_ID_GUID \
++ EFI_GUID(0x3a770ddc, 0x409b, 0x48b2, 0x81, 0x41, \
++ 0x93, 0xb7, 0xc6, 0x0b, 0x20, 0x9e)
++
+ #define V2M_BASE 0x80000000
+
+ #define CFG_PL011_CLOCK 50000000
+diff --git a/include/efi_loader.h b/include/efi_loader.h
+index 38d7f66bab..0a613ed51e 100644
+--- a/include/efi_loader.h
++++ b/include/efi_loader.h
+@@ -1036,11 +1036,11 @@ extern const struct efi_firmware_management_protocol efi_fmp_fit;
+ extern const struct efi_firmware_management_protocol efi_fmp_raw;
+
+ /* Capsule update */
+-efi_status_t EFIAPI efi_update_capsule(
++efi_status_t __efi_runtime EFIAPI efi_update_capsule(
+ struct efi_capsule_header **capsule_header_array,
+ efi_uintn_t capsule_count,
+ u64 scatter_gather_list);
+-efi_status_t EFIAPI efi_query_capsule_caps(
++efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps(
+ struct efi_capsule_header **capsule_header_array,
+ efi_uintn_t capsule_count,
+ u64 *maximum_capsule_size,
+diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
+index d5065f296a..a5da77c36c 100644
+--- a/lib/efi_loader/efi_boottime.c
++++ b/lib/efi_loader/efi_boottime.c
+@@ -23,6 +23,13 @@
+ #include <asm/setjmp.h>
+ #include <linux/libfdt_env.h>
+
++#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000)
++#include <arm_ffa.h>
++#include <dm.h>
++#include <linux/bitfield.h>
++#include <linux/bitops.h>
++#endif
++
+ DECLARE_GLOBAL_DATA_PTR;
+
+ /* Task priority level */
+diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
+index 7a6f195cbc..ea084e4ed2 100644
+--- a/lib/efi_loader/efi_capsule.c
++++ b/lib/efi_loader/efi_capsule.c
+@@ -26,6 +26,17 @@
+ #include <crypto/pkcs7_parser.h>
+ #include <linux/err.h>
+
++#ifdef CONFIG_TARGET_CORSTONE1000
++#include <arm_ffa.h>
++#include <cpu_func.h>
++#include <dm.h>
++#include <linux/bitfield.h>
++#include <linux/bitops.h>
++
++void *__efi_runtime_data corstone1000_capsule_buf; /* capsule shared buffer virtual address */
++efi_guid_t corstone1000_capsule_guid = EFI_CORSTONE1000_CAPSULE_ID_GUID;
++#endif
++
+ DECLARE_GLOBAL_DATA_PTR;
+
+ const efi_guid_t efi_guid_capsule_report = EFI_CAPSULE_REPORT_GUID;
+@@ -709,6 +720,87 @@ static efi_status_t efi_capsule_update_firmware(
+ }
+ #endif /* CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT */
+
++#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000)
++
++/**
++ * efi_corstone1000_alloc_capsule_shared_buf - allocate capsule shared buffer
++ * @capsule_image_size: The capsule data (header + payload)
++ *
++ * This function allocates the physically contiguous buffer shared between u-boot
++ * and the secure world. On UpdateCapsule() capsule data is copied to the buffer
++ * and a door bell event is generated.
++ * The buffer is allocated at the start of the DDR memory after u-boot has been relocated
++ * to the end of DDR.
++ *
++ * Return:
++ *
++ * 0: on success, otherwise failure
++ */
++efi_status_t efi_corstone1000_alloc_capsule_shared_buf(void)
++{
++ efi_status_t efi_ret;
++ u64 ram_base = CFG_SYS_SDRAM_BASE;
++
++ log_debug("[%s]\n", __func__);
++
++ efi_ret = efi_allocate_pages(EFI_ALLOCATE_ADDRESS,
++ EFI_RUNTIME_SERVICES_DATA,
++ CORSTONE1000_CAPSULE_BUFFER_SIZE,
++ &ram_base);
++
++ if (efi_ret != EFI_SUCCESS) {
++ corstone1000_capsule_buf = NULL;
++ log_err("EFI: Corstone1000: Allocating capsule shared buffer error (%d)\n"
++ , (int)efi_ret);
++ return efi_ret;
++ }
++
++ log_info("EFI: Corstone1000: Capsule shared buffer at 0x%x , size %d pages\n"
++ , (unsigned int)ram_base,
++ CORSTONE1000_CAPSULE_BUFFER_SIZE);
++
++ corstone1000_capsule_buf = (void *)map_sysmem((phys_addr_t)ram_base, 0);
++
++ return EFI_SUCCESS;
++}
++
++/**
++ * efi_corstone1000_buffer_ready_event - issue door bell event
++ * @capsule_image_size: The capsule data (header + payload)
++ *
++ * This function notifies the SE Proxy update service that capsule data is available
++ * in the capsule shared buffer.
++ *
++ * Return:
++ *
++ * 0: on success, otherwise failure
++ */
++static int __efi_runtime efi_corstone1000_buffer_ready_event(u32 capsule_image_size)
++{
++ struct ffa_send_direct_data msg = {0};
++ int ret;
++ struct udevice *dev;
++
++ log_debug("[%s]\n", __func__);
++
++ ret = uclass_first_device_err(UCLASS_FFA, &dev);
++ if (ret) {
++ log_err("Cannot find FF-A bus device\n");
++ return ret;
++ }
++
++ /*
++ * setting the buffer ready event arguments in register w4:
++ * - capsule update interface ID (31:16)
++ * - the buffer ready event ID (15:0)
++ */
++ msg.data1 = PREP_SEPROXY_SVC_ID(CORSTONE1000_SEPROXY_UPDATE_SVC_ID) |
++ PREP_SEPROXY_EVT(CORSTONE1000_BUFFER_READY_EVT); /* w4 */
++
++ return ffa_sync_send_receive(dev, CORSTONE1000_SEPROXY_PART_ID, &msg, 0);
++}
++#endif
++
+ /**
+ * efi_update_capsule() - process information from operating system
+ * @capsule_header_array: Array of virtual address pointers
+@@ -722,7 +814,7 @@ static efi_status_t efi_capsule_update_firmware(
+ *
+ * Return: status code
+ */
+-efi_status_t EFIAPI efi_update_capsule(
++efi_status_t __efi_runtime EFIAPI efi_update_capsule(
+ struct efi_capsule_header **capsule_header_array,
+ efi_uintn_t capsule_count,
+ u64 scatter_gather_list)
+@@ -739,6 +831,13 @@ efi_status_t EFIAPI efi_update_capsule(
+ goto out;
+ }
+
++#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000)
++ if (capsule_count != 1 || !corstone1000_capsule_buf) {
++ ret = EFI_INVALID_PARAMETER;
++ goto out;
++ }
++#endif
++
+ ret = EFI_SUCCESS;
+ for (i = 0, capsule = *capsule_header_array; i < capsule_count;
+ i++, capsule = *(++capsule_header_array)) {
+@@ -751,6 +850,39 @@ efi_status_t EFIAPI efi_update_capsule(
+
+ log_debug("Capsule[%d] (guid:%pUs)\n",
+ i, &capsule->capsule_guid);
++
++#if CONFIG_IS_ENABLED(TARGET_CORSTONE1000)
++ if (guidcmp(&corstone1000_capsule_guid, &capsule->capsule_guid)) {
++ ret = EFI_INVALID_PARAMETER;
++ log_err("Corstone1000: Invalid capsule GUID\n");
++ goto out;
++ }
++
++ if (efi_size_in_pages(capsule->capsule_image_size) >
++ CORSTONE1000_CAPSULE_BUFFER_SIZE) {
++ log_err("Corstone1000: Capsule data size exceeds the shared buffer size\n");
++ ret = EFI_BUFFER_TOO_SMALL;
++ goto out;
++ }
++
++ /* copy the data to the contiguous buffer */
++ efi_memcpy_runtime(corstone1000_capsule_buf, capsule, capsule->capsule_image_size);
++
++ /* invalidate the data cache */
++ invalidate_dcache_all();
++
++ /* issue buffer ready event */
++ ret = efi_corstone1000_buffer_ready_event(capsule->capsule_image_size);
++ if (ret) {
++ log_err("EFI: Corstone1000: Buffer ready event error (%d)\n", (int)ret);
++ ret = EFI_DEVICE_ERROR;
++ } else {
++ ret = EFI_SUCCESS;
++ }
++
++ goto out;
++#endif
++
+ if (!guidcmp(&capsule->capsule_guid,
+ &efi_guid_firmware_management_capsule_id)) {
+ ret = efi_capsule_update_firmware(capsule);
+@@ -789,7 +921,7 @@ out:
+ *
+ * Return: status code
+ */
+-efi_status_t EFIAPI efi_query_capsule_caps(
++efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps(
+ struct efi_capsule_header **capsule_header_array,
+ efi_uintn_t capsule_count,
+ u64 *maximum_capsule_size,
+diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
+index 58d4e13402..bf90a98b5a 100644
+--- a/lib/efi_loader/efi_setup.c
++++ b/lib/efi_loader/efi_setup.c
+@@ -17,6 +17,18 @@
+
+ efi_status_t efi_obj_list_initialized = OBJ_LIST_NOT_INITIALIZED;
+
++#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000)
++#include <linux/bitfield.h>
++#include <linux/bitops.h>
++#include <arm_ffa.h>
++#include <dm.h>
++
++/**
++ * efi_corstone1000_alloc_capsule_shared_buf - allocate capsule shared buffer
++ */
++extern efi_status_t efi_corstone1000_alloc_capsule_shared_buf(void);
++#endif
++
+ /*
+ * Allow unaligned memory access.
+ *
+@@ -120,6 +132,42 @@ static efi_status_t efi_init_secure_boot(void)
+ }
+ #endif /* CONFIG_EFI_SECURE_BOOT */
+
++#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000)
++/**
++ * efi_corstone1000_uboot-efi_started_event - notifies SE Proxy FW update service
++ *
++ * This function notifies the SE Proxy update service that uboot efi has already started
++ *
++ * Return:
++ *
++ * 0: on success, otherwise failure
++ * */
++static int efi_corstone1000_uboot_efi_started_event(void)
++{
++ struct ffa_send_direct_data msg = {0};
++ int ret;
++ struct udevice *dev;
++
++ log_debug("[%s]\n", __func__);
++
++ ret = uclass_first_device_err(UCLASS_FFA, &dev);
++ if (ret) {
++ log_err("Cannot find FF-A bus device\n");
++ return ret;
++ }
++
++ /*
++ * setting the kernel started event arguments:
++ * setting capsule update interface ID(31:16)
++ * the kernel started event ID(15:0)
++ */
++ msg.data1 = PREP_SEPROXY_SVC_ID(CORSTONE1000_SEPROXY_UPDATE_SVC_ID) |
++ PREP_SEPROXY_EVT(CORSTONE1000_UBOOT_EFI_STARTED_EVT); /* w4 */
++
++ return ffa_sync_send_receive(dev, CORSTONE1000_SEPROXY_PART_ID, &msg, 0);
++}
++#endif
++
+ /**
+ * efi_init_capsule - initialize capsule update state
+ *
+@@ -129,6 +177,22 @@ static efi_status_t efi_init_capsule(void)
+ {
+ efi_status_t ret = EFI_SUCCESS;
+
++#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000)
++ int ffa_ret;
++
++ ffa_ret = efi_corstone1000_uboot_efi_started_event();
++ if (ffa_ret)
++ log_err("Failure to notify SE Proxy FW update service\n");
++ else
++ debug("SE Proxy FW update service notified\n");
++
++ ret = efi_corstone1000_alloc_capsule_shared_buf();
++ if (ret != EFI_SUCCESS) {
++ printf("EFI: Corstone-1000: cannot allocate caspsule shared buffer\n");
++ return ret;
++ }
++#endif
++
+ if (IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT)) {
+ u16 var_name16[12];
+
+--
+2.25.1
+