blob: 57f1b9a202dbdea8c29c263a0bd647ba96cf6a6d [file] [log] [blame]
Andrew Geisslerea144b032023-01-27 16:03:57 -06001From 7702c4aeda51011be95ecbaab0dc2e7373d04286 Mon Sep 17 00:00:00 2001
Brad Bishopbec4ebc2022-08-03 09:55:16 -04002From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Andrew Geisslerea144b032023-01-27 16:03:57 -06003Date: Tue, 29 Nov 2022 15:11:27 +0000
4Subject: [PATCH 11/25] efi: corstone1000: introduce EFI capsule update
Brad Bishopbec4ebc2022-08-03 09:55:16 -04005
6This commit provides capsule update feature for Corstone1000.
7
8This feature is available before and after ExitBootServices().
9
10A platform specific capsule buffer is allocated. This buffer
11is physically contiguous and allocated at the start of the DDR
12memory after u-boot relocation to the end of DDR.
13
14The capsule buffer is shared between u-boot and the secure world.
15On UpdateCapsule() , capsule data is copied to the buffer
16and a buffer ready event is generated using FF-A transport.
17
18On ExitBootServices() a kernel started event is sent to the
19SE Proxy FW update service. This event is generated on each boot.
20
21Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
22Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
Patrick Williams8dd68482022-10-04 07:57:18 -050023Upstream-Status: Pending [Not submitted to upstream yet]
Brad Bishopbec4ebc2022-08-03 09:55:16 -040024---
Andrew Geisslerea144b032023-01-27 16:03:57 -060025 board/armltd/corstone1000/corstone1000.c | 4 +
26 configs/corstone1000_defconfig | 3 +
27 include/configs/corstone1000.h | 18 ++++
28 include/efi_loader.h | 4 +-
29 lib/efi_loader/efi_boottime.c | 36 +++++++
30 lib/efi_loader/efi_capsule.c | 124 ++++++++++++++++++++++-
31 lib/efi_loader/efi_setup.c | 15 +++
32 7 files changed, 200 insertions(+), 4 deletions(-)
Brad Bishopbec4ebc2022-08-03 09:55:16 -040033
Andrew Geisslerea144b032023-01-27 16:03:57 -060034diff --git a/board/armltd/corstone1000/corstone1000.c b/board/armltd/corstone1000/corstone1000.c
35index 4f4b96a095..76816f8f4e 100644
36--- a/board/armltd/corstone1000/corstone1000.c
37+++ b/board/armltd/corstone1000/corstone1000.c
38@@ -66,6 +66,10 @@ static struct mm_region corstone1000_mem_map[] = {
39
40 struct mm_region *mem_map = corstone1000_mem_map;
41
42+void set_dfu_alt_info(char *interface, char *devstr)
43+{
44+}
45+
46 int board_init(void)
47 {
48 return 0;
49diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
50index c26f99e7e5..c72d027711 100644
51--- a/configs/corstone1000_defconfig
52+++ b/configs/corstone1000_defconfig
53@@ -54,3 +54,6 @@ CONFIG_USB_ISP1760=y
54 CONFIG_ERRNO_STR=y
55 CONFIG_EFI_MM_COMM_TEE=y
56 CONFIG_ARM_FFA_TRANSPORT=y
57+CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
58+CONFIG_EFI_CAPSULE_FIRMWARE_FIT=y
59+CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y
Brad Bishopbec4ebc2022-08-03 09:55:16 -040060diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h
Andrew Geisslerea144b032023-01-27 16:03:57 -060061index 0362d29ac2..4d20090c9b 100644
Brad Bishopbec4ebc2022-08-03 09:55:16 -040062--- a/include/configs/corstone1000.h
63+++ b/include/configs/corstone1000.h
64@@ -14,6 +14,24 @@
65
66 #include <linux/sizes.h>
67
68+/* The SE Proxy partition ID*/
69+#define CORSTONE1000_SEPROXY_PART_ID (0x8002)
70+
71+/* Update service ID provided by the SE Proxy secure partition*/
72+#define CORSTONE1000_SEPROXY_UPDATE_SVC_ID (0x4)
73+
74+/* Notification events used with SE Proxy update service */
75+#define CORSTONE1000_BUFFER_READY_EVT (0x1)
76+#define CORSTONE1000_KERNEL_STARTED_EVT (0x2)
77+
78+/* Size in 4KB pages of the EFI capsule buffer */
79+#define CORSTONE1000_CAPSULE_BUFFER_SIZE (8192) /* 32 MB */
80+
81+/* Capsule GUID */
82+#define EFI_CORSTONE1000_CAPSULE_ID_GUID \
83+ EFI_GUID(0x3a770ddc, 0x409b, 0x48b2, 0x81, 0x41, \
84+ 0x93, 0xb7, 0xc6, 0x0b, 0x20, 0x9e)
85+
Patrick Williams8dd68482022-10-04 07:57:18 -050086 #define FFA_SHARED_MM_BUFFER_SIZE SZ_4K /* 4 KB */
87
88 /*
Brad Bishopbec4ebc2022-08-03 09:55:16 -040089diff --git a/include/efi_loader.h b/include/efi_loader.h
Andrew Geisslerea144b032023-01-27 16:03:57 -060090index 545ba06d94..773c4f6310 100644
Brad Bishopbec4ebc2022-08-03 09:55:16 -040091--- a/include/efi_loader.h
92+++ b/include/efi_loader.h
Andrew Geisslerea144b032023-01-27 16:03:57 -060093@@ -993,11 +993,11 @@ extern const struct efi_firmware_management_protocol efi_fmp_fit;
Brad Bishopbec4ebc2022-08-03 09:55:16 -040094 extern const struct efi_firmware_management_protocol efi_fmp_raw;
95
96 /* Capsule update */
97-efi_status_t EFIAPI efi_update_capsule(
98+efi_status_t __efi_runtime EFIAPI efi_update_capsule(
99 struct efi_capsule_header **capsule_header_array,
100 efi_uintn_t capsule_count,
101 u64 scatter_gather_list);
102-efi_status_t EFIAPI efi_query_capsule_caps(
103+efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps(
104 struct efi_capsule_header **capsule_header_array,
105 efi_uintn_t capsule_count,
106 u64 *maximum_capsule_size,
107diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
Andrew Geisslerea144b032023-01-27 16:03:57 -0600108index 1099ccc800..d9eed33ac8 100644
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400109--- a/lib/efi_loader/efi_boottime.c
110+++ b/lib/efi_loader/efi_boottime.c
Andrew Geisslerea144b032023-01-27 16:03:57 -0600111@@ -2103,6 +2103,33 @@ static void efi_exit_caches(void)
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400112 #endif
113 }
114
115+#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000)
116+/**
117+ * efi_corstone1000_kernel_started_event - notifies SE Proxy FW update service
118+ *
119+ * This function notifies the SE Proxy update service that the kernel has already started
120+ *
121+ * Return:
122+ *
123+ * 0: on success, otherwise failure
124+ */
125+static int efi_corstone1000_kernel_started_event(void)
126+{
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400127+ struct ffa_send_direct_data msg = {0};
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400128+
129+ log_debug("[%s]\n", __func__);
130+
131+ /*
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400132+ * setting the kernel started event arguments
133+ */
Patrick Williams8dd68482022-10-04 07:57:18 -0500134+ msg.data0 = CORSTONE1000_SEPROXY_UPDATE_SVC_ID; /* x3 */
135+ msg.data2 = CORSTONE1000_KERNEL_STARTED_EVT; /* x5 */
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400136+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600137+ return ffa_bus_ops_get()->sync_send_receive(CORSTONE1000_SEPROXY_PART_ID, &msg, 0);
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400138+}
139+
140+#endif
141+
142 /**
143 * efi_exit_boot_services() - stop all boot services
144 * @image_handle: handle of the loaded image
Andrew Geisslerea144b032023-01-27 16:03:57 -0600145@@ -2209,6 +2236,15 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400146 /* Recalculate CRC32 */
147 efi_update_table_header_crc32(&systab.hdr);
148
149+#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000)
150+ /* Notifying SE Proxy FW update service */
151+ ffa_ret = efi_corstone1000_kernel_started_event();
152+ if (ffa_ret)
153+ debug("[efi_boottime][ERROR]: Failure to notify SE Proxy FW update service\n");
154+ else
155+ debug("[efi_boottime][INFO]: SE Proxy FW update service notified\n");
156+#endif
157+
158 /* Give the payload some time to boot */
159 efi_set_watchdog(0);
160 WATCHDOG_RESET();
161diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
Andrew Geisslerea144b032023-01-27 16:03:57 -0600162index a6b98f066a..636b61f0ad 100644
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400163--- a/lib/efi_loader/efi_capsule.c
164+++ b/lib/efi_loader/efi_capsule.c
Patrick Williams92b42cb2022-09-03 06:53:57 -0500165@@ -25,6 +25,14 @@
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400166 #include <crypto/pkcs7_parser.h>
167 #include <linux/err.h>
168
169+#ifdef CONFIG_TARGET_CORSTONE1000
Patrick Williams8dd68482022-10-04 07:57:18 -0500170+#include <arm_ffa.h>
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400171+#include <cpu_func.h>
172+
173+void *__efi_runtime_data corstone1000_capsule_buf; /* capsule shared buffer virtual address */
174+efi_guid_t corstone1000_capsule_guid = EFI_CORSTONE1000_CAPSULE_ID_GUID;
175+#endif
176+
177 DECLARE_GLOBAL_DATA_PTR;
178
179 const efi_guid_t efi_guid_capsule_report = EFI_CAPSULE_REPORT_GUID;
Patrick Williams8dd68482022-10-04 07:57:18 -0500180@@ -512,6 +520,78 @@ static efi_status_t efi_capsule_update_firmware(
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400181 }
182 #endif /* CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT */
183
184+#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000)
185+
186+/**
187+ * efi_corstone1000_alloc_capsule_shared_buf - allocate capsule shared buffer
188+ * @capsule_image_size: The capsule data (header + payload)
189+ *
190+ * This function allocates the physically contiguous buffer shared between u-boot
191+ * and the secure world. On UpdateCapsule() capsule data is copied to the buffer
192+ * and a door bell event is generated.
193+ * The buffer is allocated at the start of the DDR memory after u-boot has been relocated
194+ * to the end of DDR.
195+ *
196+ * Return:
197+ *
198+ * 0: on success, otherwise failure
199+ */
200+efi_status_t efi_corstone1000_alloc_capsule_shared_buf(void)
201+{
202+ efi_status_t efi_ret;
203+ u64 ram_base = CONFIG_SYS_SDRAM_BASE;
204+
205+ log_debug("[%s]\n", __func__);
206+
207+ efi_ret = efi_allocate_pages(EFI_ALLOCATE_ADDRESS,
208+ EFI_RUNTIME_SERVICES_DATA,
209+ CORSTONE1000_CAPSULE_BUFFER_SIZE,
210+ &ram_base);
211+
212+ if (efi_ret != EFI_SUCCESS) {
213+ corstone1000_capsule_buf = NULL;
214+ log_err("EFI: Corstone1000: Allocating capsule shared buffer error (%d)\n"
215+ , (int)efi_ret);
216+ return efi_ret;
217+ }
218+
219+ log_info("EFI: Corstone1000: Capsule shared buffer at 0x%x , size %d pages\n"
220+ , (unsigned int)ram_base,
221+ CORSTONE1000_CAPSULE_BUFFER_SIZE);
222+
223+ corstone1000_capsule_buf = (void *)map_sysmem((phys_addr_t)ram_base, 0);
224+
225+ return EFI_SUCCESS;
226+}
227+
228+/**
229+ * efi_corstone1000_buffer_ready_event - issue door bell event
230+ * @capsule_image_size: The capsule data (header + payload)
231+ *
232+ * This function notifies the SE Proxy update service that capsule data is available
233+ * in the capsule shared buffer.
234+ *
235+ * Return:
236+ *
237+ * 0: on success, otherwise failure
238+ */
239+static int __efi_runtime efi_corstone1000_buffer_ready_event(u32 capsule_image_size)
240+{
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400241+ struct ffa_send_direct_data msg = {0};
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400242+
243+ log_debug("[%s]\n", __func__);
244+
245+ /*
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400246+ * setting the buffer ready event arguments
247+ */
Patrick Williams8dd68482022-10-04 07:57:18 -0500248+ msg.data0 = CORSTONE1000_SEPROXY_UPDATE_SVC_ID; /* x3 */
249+ msg.data1 = capsule_image_size; /* x4 */
250+ msg.data2 = CORSTONE1000_BUFFER_READY_EVT; /* x5 */
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400251+
Andrew Geisslerea144b032023-01-27 16:03:57 -0600252+ return ffa_bus_ops_get()->sync_send_receive(NULL, CORSTONE1000_SEPROXY_PART_ID, &msg, 0);
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400253+}
254+#endif
255+
256 /**
257 * efi_update_capsule() - process information from operating system
258 * @capsule_header_array: Array of virtual address pointers
Patrick Williams8dd68482022-10-04 07:57:18 -0500259@@ -525,7 +605,7 @@ static efi_status_t efi_capsule_update_firmware(
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400260 *
261 * Return: status code
262 */
263-efi_status_t EFIAPI efi_update_capsule(
264+efi_status_t __efi_runtime EFIAPI efi_update_capsule(
265 struct efi_capsule_header **capsule_header_array,
266 efi_uintn_t capsule_count,
267 u64 scatter_gather_list)
Patrick Williams8dd68482022-10-04 07:57:18 -0500268@@ -542,6 +622,13 @@ efi_status_t EFIAPI efi_update_capsule(
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400269 goto out;
270 }
271
272+#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000)
273+ if (capsule_count != 1 || !corstone1000_capsule_buf) {
274+ ret = EFI_INVALID_PARAMETER;
275+ goto out;
276+ }
277+#endif
278+
279 ret = EFI_SUCCESS;
280 for (i = 0, capsule = *capsule_header_array; i < capsule_count;
281 i++, capsule = *(++capsule_header_array)) {
Patrick Williams8dd68482022-10-04 07:57:18 -0500282@@ -554,6 +641,39 @@ efi_status_t EFIAPI efi_update_capsule(
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400283
284 log_debug("Capsule[%d] (guid:%pUs)\n",
285 i, &capsule->capsule_guid);
286+
287+#if CONFIG_IS_ENABLED(TARGET_CORSTONE1000)
288+ if (guidcmp(&corstone1000_capsule_guid, &capsule->capsule_guid)) {
289+ ret = EFI_INVALID_PARAMETER;
290+ log_err("Corstone1000: Invalid capsule GUID\n");
291+ goto out;
292+ }
293+
294+ if (efi_size_in_pages(capsule->capsule_image_size) >
295+ CORSTONE1000_CAPSULE_BUFFER_SIZE) {
296+ log_err("Corstone1000: Capsule data size exceeds the shared buffer size\n");
297+ ret = EFI_BUFFER_TOO_SMALL;
298+ goto out;
299+ }
300+
301+ /* copy the data to the contiguous buffer */
302+ efi_memcpy_runtime(corstone1000_capsule_buf, capsule, capsule->capsule_image_size);
303+
304+ /* invalidate the data cache */
305+ invalidate_dcache_all();
306+
307+ /* issue buffer ready event */
308+ ret = efi_corstone1000_buffer_ready_event(capsule->capsule_image_size);
309+ if (ret) {
310+ log_err("EFI: Corstone1000: Buffer ready event error (%d)\n", (int)ret);
311+ ret = EFI_DEVICE_ERROR;
312+ } else {
313+ ret = EFI_SUCCESS;
314+ }
315+
316+ goto out;
317+#endif
318+
319 if (!guidcmp(&capsule->capsule_guid,
320 &efi_guid_firmware_management_capsule_id)) {
321 ret = efi_capsule_update_firmware(capsule);
Patrick Williams8dd68482022-10-04 07:57:18 -0500322@@ -592,7 +712,7 @@ out:
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400323 *
324 * Return: status code
325 */
326-efi_status_t EFIAPI efi_query_capsule_caps(
327+efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps(
328 struct efi_capsule_header **capsule_header_array,
329 efi_uintn_t capsule_count,
330 u64 *maximum_capsule_size,
331diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
Andrew Geisslerea144b032023-01-27 16:03:57 -0600332index c633fcd91e..443f409906 100644
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400333--- a/lib/efi_loader/efi_setup.c
334+++ b/lib/efi_loader/efi_setup.c
335@@ -16,6 +16,13 @@
336
337 efi_status_t efi_obj_list_initialized = OBJ_LIST_NOT_INITIALIZED;
338
339+#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000)
340+/**
341+ * efi_corstone1000_alloc_capsule_shared_buf - allocate capsule shared buffer
342+ */
343+extern efi_status_t efi_corstone1000_alloc_capsule_shared_buf(void);
344+#endif
345+
346 /*
347 * Allow unaligned memory access.
348 *
349@@ -128,6 +135,14 @@ static efi_status_t efi_init_capsule(void)
350 {
351 efi_status_t ret = EFI_SUCCESS;
352
353+#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000)
354+ ret = efi_corstone1000_alloc_capsule_shared_buf();
355+ if (ret != EFI_SUCCESS) {
356+ printf("EFI: Corstone-1000: cannot allocate caspsule shared buffer\n");
357+ return ret;
358+ }
359+#endif
360+
361 if (IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_UPDATE)) {
362 ret = efi_set_variable_int(u"CapsuleMax",
363 &efi_guid_capsule_report,
364--
Patrick Williams8dd68482022-10-04 07:57:18 -05003652.17.1
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400366