blob: 0a829c410a7c5c321e200a15173574fd960bf6da [file] [log] [blame]
Patrick Williams92b42cb2022-09-03 06:53:57 -05001From 652259af2f795a5d69c628ae7b1e79d33c234abd Mon Sep 17 00:00:00 2001
Brad Bishopbec4ebc2022-08-03 09:55:16 -04002From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
3Date: Thu, 11 Nov 2021 16:27:59 +0000
Patrick Williams92b42cb2022-09-03 06:53:57 -05004Subject: [PATCH 11/24] 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>
23---
24 include/configs/corstone1000.h | 18 +++++
25 include/efi_loader.h | 4 +-
26 lib/efi_loader/efi_boottime.c | 47 ++++++++++++
27 lib/efi_loader/efi_capsule.c | 135 ++++++++++++++++++++++++++++++++-
28 lib/efi_loader/efi_setup.c | 15 ++++
29 5 files changed, 215 insertions(+), 4 deletions(-)
30
31diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h
32index afc9ccfc192b..a400cdef69d0 100644
33--- a/include/configs/corstone1000.h
34+++ b/include/configs/corstone1000.h
35@@ -14,6 +14,24 @@
36
37 #include <linux/sizes.h>
38
39+/* The SE Proxy partition ID*/
40+#define CORSTONE1000_SEPROXY_PART_ID (0x8002)
41+
42+/* Update service ID provided by the SE Proxy secure partition*/
43+#define CORSTONE1000_SEPROXY_UPDATE_SVC_ID (0x4)
44+
45+/* Notification events used with SE Proxy update service */
46+#define CORSTONE1000_BUFFER_READY_EVT (0x1)
47+#define CORSTONE1000_KERNEL_STARTED_EVT (0x2)
48+
49+/* Size in 4KB pages of the EFI capsule buffer */
50+#define CORSTONE1000_CAPSULE_BUFFER_SIZE (8192) /* 32 MB */
51+
52+/* Capsule GUID */
53+#define EFI_CORSTONE1000_CAPSULE_ID_GUID \
54+ EFI_GUID(0x3a770ddc, 0x409b, 0x48b2, 0x81, 0x41, \
55+ 0x93, 0xb7, 0xc6, 0x0b, 0x20, 0x9e)
56+
57 /* MM SP UUID binary data (little-endian format) */
58 #define MM_SP_UUID_DATA \
59 0xed, 0x32, 0xd5, 0x33, \
60diff --git a/include/efi_loader.h b/include/efi_loader.h
Patrick Williams92b42cb2022-09-03 06:53:57 -050061index 5b41985244e2..796419b69b40 100644
Brad Bishopbec4ebc2022-08-03 09:55:16 -040062--- a/include/efi_loader.h
63+++ b/include/efi_loader.h
Patrick Williams92b42cb2022-09-03 06:53:57 -050064@@ -984,11 +984,11 @@ extern const struct efi_firmware_management_protocol efi_fmp_fit;
Brad Bishopbec4ebc2022-08-03 09:55:16 -040065 extern const struct efi_firmware_management_protocol efi_fmp_raw;
66
67 /* Capsule update */
68-efi_status_t EFIAPI efi_update_capsule(
69+efi_status_t __efi_runtime EFIAPI efi_update_capsule(
70 struct efi_capsule_header **capsule_header_array,
71 efi_uintn_t capsule_count,
72 u64 scatter_gather_list);
73-efi_status_t EFIAPI efi_query_capsule_caps(
74+efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps(
75 struct efi_capsule_header **capsule_header_array,
76 efi_uintn_t capsule_count,
77 u64 *maximum_capsule_size,
78diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
Patrick Williams92b42cb2022-09-03 06:53:57 -050079index c68d9ed4f0bd..f2b5c7834c01 100644
Brad Bishopbec4ebc2022-08-03 09:55:16 -040080--- a/lib/efi_loader/efi_boottime.c
81+++ b/lib/efi_loader/efi_boottime.c
Patrick Williams92b42cb2022-09-03 06:53:57 -050082@@ -2095,6 +2095,44 @@ static void efi_exit_caches(void)
Brad Bishopbec4ebc2022-08-03 09:55:16 -040083 #endif
84 }
85
86+#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000)
87+/**
88+ * efi_corstone1000_kernel_started_event - notifies SE Proxy FW update service
89+ *
90+ * This function notifies the SE Proxy update service that the kernel has already started
91+ *
92+ * Return:
93+ *
94+ * 0: on success, otherwise failure
95+ */
96+static int efi_corstone1000_kernel_started_event(void)
97+{
98+ struct ffa_interface_data func_data = {0};
99+ struct ffa_send_direct_data msg = {0};
100+ u16 part_id = CORSTONE1000_SEPROXY_PART_ID;
101+
102+ log_debug("[%s]\n", __func__);
103+
104+ /*
105+ * telling the driver which partition to use
106+ */
107+ func_data.data0_size = sizeof(part_id);
108+ func_data.data0 = &part_id;
109+
110+ /*
111+ * setting the kernel started event arguments
112+ */
113+ msg.a3 = CORSTONE1000_SEPROXY_UPDATE_SVC_ID;
114+ msg.a5 = CORSTONE1000_KERNEL_STARTED_EVT;
115+
116+ func_data.data1_size = sizeof(msg);
117+ func_data.data1 = &msg;
118+
119+ return ffa_helper_msg_send_direct_req(&func_data);
120+}
121+
122+#endif
123+
124 /**
125 * efi_exit_boot_services() - stop all boot services
126 * @image_handle: handle of the loaded image
Patrick Williams92b42cb2022-09-03 06:53:57 -0500127@@ -2208,6 +2246,15 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400128 /* Recalculate CRC32 */
129 efi_update_table_header_crc32(&systab.hdr);
130
131+#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000)
132+ /* Notifying SE Proxy FW update service */
133+ ffa_ret = efi_corstone1000_kernel_started_event();
134+ if (ffa_ret)
135+ debug("[efi_boottime][ERROR]: Failure to notify SE Proxy FW update service\n");
136+ else
137+ debug("[efi_boottime][INFO]: SE Proxy FW update service notified\n");
138+#endif
139+
140 /* Give the payload some time to boot */
141 efi_set_watchdog(0);
142 WATCHDOG_RESET();
143diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
Patrick Williams92b42cb2022-09-03 06:53:57 -0500144index a6b98f066a0b..a0689ba912fc 100644
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400145--- a/lib/efi_loader/efi_capsule.c
146+++ b/lib/efi_loader/efi_capsule.c
Patrick Williams92b42cb2022-09-03 06:53:57 -0500147@@ -25,6 +25,14 @@
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400148 #include <crypto/pkcs7_parser.h>
149 #include <linux/err.h>
150
151+#ifdef CONFIG_TARGET_CORSTONE1000
152+#include <arm_ffa_helper.h>
153+#include <cpu_func.h>
154+
155+void *__efi_runtime_data corstone1000_capsule_buf; /* capsule shared buffer virtual address */
156+efi_guid_t corstone1000_capsule_guid = EFI_CORSTONE1000_CAPSULE_ID_GUID;
157+#endif
158+
159 DECLARE_GLOBAL_DATA_PTR;
160
161 const efi_guid_t efi_guid_capsule_report = EFI_CAPSULE_REPORT_GUID;
Patrick Williams92b42cb2022-09-03 06:53:57 -0500162@@ -512,6 +520,89 @@ static efi_status_t efi_capsule_update_firmware(
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400163 }
164 #endif /* CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT */
165
166+#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000)
167+
168+/**
169+ * efi_corstone1000_alloc_capsule_shared_buf - allocate capsule shared buffer
170+ * @capsule_image_size: The capsule data (header + payload)
171+ *
172+ * This function allocates the physically contiguous buffer shared between u-boot
173+ * and the secure world. On UpdateCapsule() capsule data is copied to the buffer
174+ * and a door bell event is generated.
175+ * The buffer is allocated at the start of the DDR memory after u-boot has been relocated
176+ * to the end of DDR.
177+ *
178+ * Return:
179+ *
180+ * 0: on success, otherwise failure
181+ */
182+efi_status_t efi_corstone1000_alloc_capsule_shared_buf(void)
183+{
184+ efi_status_t efi_ret;
185+ u64 ram_base = CONFIG_SYS_SDRAM_BASE;
186+
187+ log_debug("[%s]\n", __func__);
188+
189+ efi_ret = efi_allocate_pages(EFI_ALLOCATE_ADDRESS,
190+ EFI_RUNTIME_SERVICES_DATA,
191+ CORSTONE1000_CAPSULE_BUFFER_SIZE,
192+ &ram_base);
193+
194+ if (efi_ret != EFI_SUCCESS) {
195+ corstone1000_capsule_buf = NULL;
196+ log_err("EFI: Corstone1000: Allocating capsule shared buffer error (%d)\n"
197+ , (int)efi_ret);
198+ return efi_ret;
199+ }
200+
201+ log_info("EFI: Corstone1000: Capsule shared buffer at 0x%x , size %d pages\n"
202+ , (unsigned int)ram_base,
203+ CORSTONE1000_CAPSULE_BUFFER_SIZE);
204+
205+ corstone1000_capsule_buf = (void *)map_sysmem((phys_addr_t)ram_base, 0);
206+
207+ return EFI_SUCCESS;
208+}
209+
210+/**
211+ * efi_corstone1000_buffer_ready_event - issue door bell event
212+ * @capsule_image_size: The capsule data (header + payload)
213+ *
214+ * This function notifies the SE Proxy update service that capsule data is available
215+ * in the capsule shared buffer.
216+ *
217+ * Return:
218+ *
219+ * 0: on success, otherwise failure
220+ */
221+static int __efi_runtime efi_corstone1000_buffer_ready_event(u32 capsule_image_size)
222+{
223+ struct ffa_interface_data func_data = {0};
224+ struct ffa_send_direct_data msg = {0};
225+ u16 part_id = CORSTONE1000_SEPROXY_PART_ID;
226+
227+ log_debug("[%s]\n", __func__);
228+
229+ /*
230+ * telling the driver which partition to use
231+ */
232+ func_data.data0_size = sizeof(part_id);
233+ func_data.data0 = &part_id;
234+
235+ /*
236+ * setting the buffer ready event arguments
237+ */
238+ msg.a3 = CORSTONE1000_SEPROXY_UPDATE_SVC_ID;
239+ msg.a4 = capsule_image_size;
240+ msg.a5 = CORSTONE1000_BUFFER_READY_EVT;
241+
242+ func_data.data1_size = sizeof(msg);
243+ func_data.data1 = &msg;
244+
245+ return ffa_helper_msg_send_direct_req(&func_data);
246+}
247+#endif
248+
249 /**
250 * efi_update_capsule() - process information from operating system
251 * @capsule_header_array: Array of virtual address pointers
Patrick Williams92b42cb2022-09-03 06:53:57 -0500252@@ -525,7 +616,7 @@ static efi_status_t efi_capsule_update_firmware(
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400253 *
254 * Return: status code
255 */
256-efi_status_t EFIAPI efi_update_capsule(
257+efi_status_t __efi_runtime EFIAPI efi_update_capsule(
258 struct efi_capsule_header **capsule_header_array,
259 efi_uintn_t capsule_count,
260 u64 scatter_gather_list)
Patrick Williams92b42cb2022-09-03 06:53:57 -0500261@@ -542,6 +633,13 @@ efi_status_t EFIAPI efi_update_capsule(
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400262 goto out;
263 }
264
265+#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000)
266+ if (capsule_count != 1 || !corstone1000_capsule_buf) {
267+ ret = EFI_INVALID_PARAMETER;
268+ goto out;
269+ }
270+#endif
271+
272 ret = EFI_SUCCESS;
273 for (i = 0, capsule = *capsule_header_array; i < capsule_count;
274 i++, capsule = *(++capsule_header_array)) {
Patrick Williams92b42cb2022-09-03 06:53:57 -0500275@@ -554,6 +652,39 @@ efi_status_t EFIAPI efi_update_capsule(
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400276
277 log_debug("Capsule[%d] (guid:%pUs)\n",
278 i, &capsule->capsule_guid);
279+
280+#if CONFIG_IS_ENABLED(TARGET_CORSTONE1000)
281+ if (guidcmp(&corstone1000_capsule_guid, &capsule->capsule_guid)) {
282+ ret = EFI_INVALID_PARAMETER;
283+ log_err("Corstone1000: Invalid capsule GUID\n");
284+ goto out;
285+ }
286+
287+ if (efi_size_in_pages(capsule->capsule_image_size) >
288+ CORSTONE1000_CAPSULE_BUFFER_SIZE) {
289+ log_err("Corstone1000: Capsule data size exceeds the shared buffer size\n");
290+ ret = EFI_BUFFER_TOO_SMALL;
291+ goto out;
292+ }
293+
294+ /* copy the data to the contiguous buffer */
295+ efi_memcpy_runtime(corstone1000_capsule_buf, capsule, capsule->capsule_image_size);
296+
297+ /* invalidate the data cache */
298+ invalidate_dcache_all();
299+
300+ /* issue buffer ready event */
301+ ret = efi_corstone1000_buffer_ready_event(capsule->capsule_image_size);
302+ if (ret) {
303+ log_err("EFI: Corstone1000: Buffer ready event error (%d)\n", (int)ret);
304+ ret = EFI_DEVICE_ERROR;
305+ } else {
306+ ret = EFI_SUCCESS;
307+ }
308+
309+ goto out;
310+#endif
311+
312 if (!guidcmp(&capsule->capsule_guid,
313 &efi_guid_firmware_management_capsule_id)) {
314 ret = efi_capsule_update_firmware(capsule);
Patrick Williams92b42cb2022-09-03 06:53:57 -0500315@@ -592,7 +723,7 @@ out:
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400316 *
317 * Return: status code
318 */
319-efi_status_t EFIAPI efi_query_capsule_caps(
320+efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps(
321 struct efi_capsule_header **capsule_header_array,
322 efi_uintn_t capsule_count,
323 u64 *maximum_capsule_size,
324diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
Patrick Williams92b42cb2022-09-03 06:53:57 -0500325index 492ecf4cb15c..bfd4687e10b5 100644
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400326--- a/lib/efi_loader/efi_setup.c
327+++ b/lib/efi_loader/efi_setup.c
328@@ -16,6 +16,13 @@
329
330 efi_status_t efi_obj_list_initialized = OBJ_LIST_NOT_INITIALIZED;
331
332+#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000)
333+/**
334+ * efi_corstone1000_alloc_capsule_shared_buf - allocate capsule shared buffer
335+ */
336+extern efi_status_t efi_corstone1000_alloc_capsule_shared_buf(void);
337+#endif
338+
339 /*
340 * Allow unaligned memory access.
341 *
342@@ -128,6 +135,14 @@ static efi_status_t efi_init_capsule(void)
343 {
344 efi_status_t ret = EFI_SUCCESS;
345
346+#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000)
347+ ret = efi_corstone1000_alloc_capsule_shared_buf();
348+ if (ret != EFI_SUCCESS) {
349+ printf("EFI: Corstone-1000: cannot allocate caspsule shared buffer\n");
350+ return ret;
351+ }
352+#endif
353+
354 if (IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_UPDATE)) {
355 ret = efi_set_variable_int(u"CapsuleMax",
356 &efi_guid_capsule_report,
357--
Patrick Williams92b42cb2022-09-03 06:53:57 -05003582.37.1
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400359