diff options
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.patch | 409 |
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 + |