blob: 291d15d39e4576b359f80018b49cce353090d0ac [file] [log] [blame]
Patrick Williams8dd68482022-10-04 07:57:18 -05001From 10e155a677192731481ebe7f302e2d9ad790346a Mon Sep 17 00:00:00 2001
Brad Bishopbec4ebc2022-08-03 09:55:16 -04002From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Patrick Williams8dd68482022-10-04 07:57:18 -05003Date: Thu, 28 Jul 2022 15:01:55 +0100
4Subject: [PATCH 16/26] 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---
25 include/configs/corstone1000.h | 18 +++++
26 include/efi_loader.h | 4 +-
Patrick Williams8dd68482022-10-04 07:57:18 -050027 lib/efi_loader/efi_boottime.c | 36 ++++++++++
28 lib/efi_loader/efi_capsule.c | 124 ++++++++++++++++++++++++++++++++-
Brad Bishopbec4ebc2022-08-03 09:55:16 -040029 lib/efi_loader/efi_setup.c | 15 ++++
Patrick Williams8dd68482022-10-04 07:57:18 -050030 5 files changed, 193 insertions(+), 4 deletions(-)
Brad Bishopbec4ebc2022-08-03 09:55:16 -040031
32diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h
Patrick Williams8dd68482022-10-04 07:57:18 -050033index 5960c6b4be..fe5ec0adcd 100644
Brad Bishopbec4ebc2022-08-03 09:55:16 -040034--- a/include/configs/corstone1000.h
35+++ b/include/configs/corstone1000.h
36@@ -14,6 +14,24 @@
37
38 #include <linux/sizes.h>
39
40+/* The SE Proxy partition ID*/
41+#define CORSTONE1000_SEPROXY_PART_ID (0x8002)
42+
43+/* Update service ID provided by the SE Proxy secure partition*/
44+#define CORSTONE1000_SEPROXY_UPDATE_SVC_ID (0x4)
45+
46+/* Notification events used with SE Proxy update service */
47+#define CORSTONE1000_BUFFER_READY_EVT (0x1)
48+#define CORSTONE1000_KERNEL_STARTED_EVT (0x2)
49+
50+/* Size in 4KB pages of the EFI capsule buffer */
51+#define CORSTONE1000_CAPSULE_BUFFER_SIZE (8192) /* 32 MB */
52+
53+/* Capsule GUID */
54+#define EFI_CORSTONE1000_CAPSULE_ID_GUID \
55+ EFI_GUID(0x3a770ddc, 0x409b, 0x48b2, 0x81, 0x41, \
56+ 0x93, 0xb7, 0xc6, 0x0b, 0x20, 0x9e)
57+
Patrick Williams8dd68482022-10-04 07:57:18 -050058 #define FFA_SHARED_MM_BUFFER_SIZE SZ_4K /* 4 KB */
59
60 /*
Brad Bishopbec4ebc2022-08-03 09:55:16 -040061diff --git a/include/efi_loader.h b/include/efi_loader.h
Patrick Williams8dd68482022-10-04 07:57:18 -050062index 5b41985244..796419b69b 100644
Brad Bishopbec4ebc2022-08-03 09:55:16 -040063--- a/include/efi_loader.h
64+++ b/include/efi_loader.h
Patrick Williams92b42cb2022-09-03 06:53:57 -050065@@ -984,11 +984,11 @@ extern const struct efi_firmware_management_protocol efi_fmp_fit;
Brad Bishopbec4ebc2022-08-03 09:55:16 -040066 extern const struct efi_firmware_management_protocol efi_fmp_raw;
67
68 /* Capsule update */
69-efi_status_t EFIAPI efi_update_capsule(
70+efi_status_t __efi_runtime EFIAPI efi_update_capsule(
71 struct efi_capsule_header **capsule_header_array,
72 efi_uintn_t capsule_count,
73 u64 scatter_gather_list);
74-efi_status_t EFIAPI efi_query_capsule_caps(
75+efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps(
76 struct efi_capsule_header **capsule_header_array,
77 efi_uintn_t capsule_count,
78 u64 *maximum_capsule_size,
79diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
Patrick Williams8dd68482022-10-04 07:57:18 -050080index cede7826bd..9bf2596597 100644
Brad Bishopbec4ebc2022-08-03 09:55:16 -040081--- a/lib/efi_loader/efi_boottime.c
82+++ b/lib/efi_loader/efi_boottime.c
Patrick Williams8dd68482022-10-04 07:57:18 -050083@@ -2095,6 +2095,33 @@ static void efi_exit_caches(void)
Brad Bishopbec4ebc2022-08-03 09:55:16 -040084 #endif
85 }
86
87+#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000)
88+/**
89+ * efi_corstone1000_kernel_started_event - notifies SE Proxy FW update service
90+ *
91+ * This function notifies the SE Proxy update service that the kernel has already started
92+ *
93+ * Return:
94+ *
95+ * 0: on success, otherwise failure
96+ */
97+static int efi_corstone1000_kernel_started_event(void)
98+{
Brad Bishopbec4ebc2022-08-03 09:55:16 -040099+ struct ffa_send_direct_data msg = {0};
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400100+
101+ log_debug("[%s]\n", __func__);
102+
103+ /*
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400104+ * setting the kernel started event arguments
105+ */
Patrick Williams8dd68482022-10-04 07:57:18 -0500106+ msg.data0 = CORSTONE1000_SEPROXY_UPDATE_SVC_ID; /* x3 */
107+ msg.data2 = CORSTONE1000_KERNEL_STARTED_EVT; /* x5 */
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400108+
Patrick Williams8dd68482022-10-04 07:57:18 -0500109+ return ffa_bus_ops_get()->sync_send_receive(CORSTONE1000_SEPROXY_PART_ID, &msg);
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400110+}
111+
112+#endif
113+
114 /**
115 * efi_exit_boot_services() - stop all boot services
116 * @image_handle: handle of the loaded image
Patrick Williams8dd68482022-10-04 07:57:18 -0500117@@ -2210,6 +2237,15 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400118 /* Recalculate CRC32 */
119 efi_update_table_header_crc32(&systab.hdr);
120
121+#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000)
122+ /* Notifying SE Proxy FW update service */
123+ ffa_ret = efi_corstone1000_kernel_started_event();
124+ if (ffa_ret)
125+ debug("[efi_boottime][ERROR]: Failure to notify SE Proxy FW update service\n");
126+ else
127+ debug("[efi_boottime][INFO]: SE Proxy FW update service notified\n");
128+#endif
129+
130 /* Give the payload some time to boot */
131 efi_set_watchdog(0);
132 WATCHDOG_RESET();
133diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
Patrick Williams8dd68482022-10-04 07:57:18 -0500134index a6b98f066a..c0f3427a60 100644
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400135--- a/lib/efi_loader/efi_capsule.c
136+++ b/lib/efi_loader/efi_capsule.c
Patrick Williams92b42cb2022-09-03 06:53:57 -0500137@@ -25,6 +25,14 @@
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400138 #include <crypto/pkcs7_parser.h>
139 #include <linux/err.h>
140
141+#ifdef CONFIG_TARGET_CORSTONE1000
Patrick Williams8dd68482022-10-04 07:57:18 -0500142+#include <arm_ffa.h>
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400143+#include <cpu_func.h>
144+
145+void *__efi_runtime_data corstone1000_capsule_buf; /* capsule shared buffer virtual address */
146+efi_guid_t corstone1000_capsule_guid = EFI_CORSTONE1000_CAPSULE_ID_GUID;
147+#endif
148+
149 DECLARE_GLOBAL_DATA_PTR;
150
151 const efi_guid_t efi_guid_capsule_report = EFI_CAPSULE_REPORT_GUID;
Patrick Williams8dd68482022-10-04 07:57:18 -0500152@@ -512,6 +520,78 @@ static efi_status_t efi_capsule_update_firmware(
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400153 }
154 #endif /* CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT */
155
156+#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000)
157+
158+/**
159+ * efi_corstone1000_alloc_capsule_shared_buf - allocate capsule shared buffer
160+ * @capsule_image_size: The capsule data (header + payload)
161+ *
162+ * This function allocates the physically contiguous buffer shared between u-boot
163+ * and the secure world. On UpdateCapsule() capsule data is copied to the buffer
164+ * and a door bell event is generated.
165+ * The buffer is allocated at the start of the DDR memory after u-boot has been relocated
166+ * to the end of DDR.
167+ *
168+ * Return:
169+ *
170+ * 0: on success, otherwise failure
171+ */
172+efi_status_t efi_corstone1000_alloc_capsule_shared_buf(void)
173+{
174+ efi_status_t efi_ret;
175+ u64 ram_base = CONFIG_SYS_SDRAM_BASE;
176+
177+ log_debug("[%s]\n", __func__);
178+
179+ efi_ret = efi_allocate_pages(EFI_ALLOCATE_ADDRESS,
180+ EFI_RUNTIME_SERVICES_DATA,
181+ CORSTONE1000_CAPSULE_BUFFER_SIZE,
182+ &ram_base);
183+
184+ if (efi_ret != EFI_SUCCESS) {
185+ corstone1000_capsule_buf = NULL;
186+ log_err("EFI: Corstone1000: Allocating capsule shared buffer error (%d)\n"
187+ , (int)efi_ret);
188+ return efi_ret;
189+ }
190+
191+ log_info("EFI: Corstone1000: Capsule shared buffer at 0x%x , size %d pages\n"
192+ , (unsigned int)ram_base,
193+ CORSTONE1000_CAPSULE_BUFFER_SIZE);
194+
195+ corstone1000_capsule_buf = (void *)map_sysmem((phys_addr_t)ram_base, 0);
196+
197+ return EFI_SUCCESS;
198+}
199+
200+/**
201+ * efi_corstone1000_buffer_ready_event - issue door bell event
202+ * @capsule_image_size: The capsule data (header + payload)
203+ *
204+ * This function notifies the SE Proxy update service that capsule data is available
205+ * in the capsule shared buffer.
206+ *
207+ * Return:
208+ *
209+ * 0: on success, otherwise failure
210+ */
211+static int __efi_runtime efi_corstone1000_buffer_ready_event(u32 capsule_image_size)
212+{
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400213+ struct ffa_send_direct_data msg = {0};
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400214+
215+ log_debug("[%s]\n", __func__);
216+
217+ /*
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400218+ * setting the buffer ready event arguments
219+ */
Patrick Williams8dd68482022-10-04 07:57:18 -0500220+ msg.data0 = CORSTONE1000_SEPROXY_UPDATE_SVC_ID; /* x3 */
221+ msg.data1 = capsule_image_size; /* x4 */
222+ msg.data2 = CORSTONE1000_BUFFER_READY_EVT; /* x5 */
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400223+
Patrick Williams8dd68482022-10-04 07:57:18 -0500224+ return ffa_bus_ops_get()->sync_send_receive(CORSTONE1000_SEPROXY_PART_ID, &msg);
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400225+}
226+#endif
227+
228 /**
229 * efi_update_capsule() - process information from operating system
230 * @capsule_header_array: Array of virtual address pointers
Patrick Williams8dd68482022-10-04 07:57:18 -0500231@@ -525,7 +605,7 @@ static efi_status_t efi_capsule_update_firmware(
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400232 *
233 * Return: status code
234 */
235-efi_status_t EFIAPI efi_update_capsule(
236+efi_status_t __efi_runtime EFIAPI efi_update_capsule(
237 struct efi_capsule_header **capsule_header_array,
238 efi_uintn_t capsule_count,
239 u64 scatter_gather_list)
Patrick Williams8dd68482022-10-04 07:57:18 -0500240@@ -542,6 +622,13 @@ efi_status_t EFIAPI efi_update_capsule(
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400241 goto out;
242 }
243
244+#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000)
245+ if (capsule_count != 1 || !corstone1000_capsule_buf) {
246+ ret = EFI_INVALID_PARAMETER;
247+ goto out;
248+ }
249+#endif
250+
251 ret = EFI_SUCCESS;
252 for (i = 0, capsule = *capsule_header_array; i < capsule_count;
253 i++, capsule = *(++capsule_header_array)) {
Patrick Williams8dd68482022-10-04 07:57:18 -0500254@@ -554,6 +641,39 @@ efi_status_t EFIAPI efi_update_capsule(
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400255
256 log_debug("Capsule[%d] (guid:%pUs)\n",
257 i, &capsule->capsule_guid);
258+
259+#if CONFIG_IS_ENABLED(TARGET_CORSTONE1000)
260+ if (guidcmp(&corstone1000_capsule_guid, &capsule->capsule_guid)) {
261+ ret = EFI_INVALID_PARAMETER;
262+ log_err("Corstone1000: Invalid capsule GUID\n");
263+ goto out;
264+ }
265+
266+ if (efi_size_in_pages(capsule->capsule_image_size) >
267+ CORSTONE1000_CAPSULE_BUFFER_SIZE) {
268+ log_err("Corstone1000: Capsule data size exceeds the shared buffer size\n");
269+ ret = EFI_BUFFER_TOO_SMALL;
270+ goto out;
271+ }
272+
273+ /* copy the data to the contiguous buffer */
274+ efi_memcpy_runtime(corstone1000_capsule_buf, capsule, capsule->capsule_image_size);
275+
276+ /* invalidate the data cache */
277+ invalidate_dcache_all();
278+
279+ /* issue buffer ready event */
280+ ret = efi_corstone1000_buffer_ready_event(capsule->capsule_image_size);
281+ if (ret) {
282+ log_err("EFI: Corstone1000: Buffer ready event error (%d)\n", (int)ret);
283+ ret = EFI_DEVICE_ERROR;
284+ } else {
285+ ret = EFI_SUCCESS;
286+ }
287+
288+ goto out;
289+#endif
290+
291 if (!guidcmp(&capsule->capsule_guid,
292 &efi_guid_firmware_management_capsule_id)) {
293 ret = efi_capsule_update_firmware(capsule);
Patrick Williams8dd68482022-10-04 07:57:18 -0500294@@ -592,7 +712,7 @@ out:
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400295 *
296 * Return: status code
297 */
298-efi_status_t EFIAPI efi_query_capsule_caps(
299+efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps(
300 struct efi_capsule_header **capsule_header_array,
301 efi_uintn_t capsule_count,
302 u64 *maximum_capsule_size,
303diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
Patrick Williams8dd68482022-10-04 07:57:18 -0500304index 492ecf4cb1..bfd4687e10 100644
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400305--- a/lib/efi_loader/efi_setup.c
306+++ b/lib/efi_loader/efi_setup.c
307@@ -16,6 +16,13 @@
308
309 efi_status_t efi_obj_list_initialized = OBJ_LIST_NOT_INITIALIZED;
310
311+#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000)
312+/**
313+ * efi_corstone1000_alloc_capsule_shared_buf - allocate capsule shared buffer
314+ */
315+extern efi_status_t efi_corstone1000_alloc_capsule_shared_buf(void);
316+#endif
317+
318 /*
319 * Allow unaligned memory access.
320 *
321@@ -128,6 +135,14 @@ static efi_status_t efi_init_capsule(void)
322 {
323 efi_status_t ret = EFI_SUCCESS;
324
325+#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000)
326+ ret = efi_corstone1000_alloc_capsule_shared_buf();
327+ if (ret != EFI_SUCCESS) {
328+ printf("EFI: Corstone-1000: cannot allocate caspsule shared buffer\n");
329+ return ret;
330+ }
331+#endif
332+
333 if (IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_UPDATE)) {
334 ret = efi_set_variable_int(u"CapsuleMax",
335 &efi_guid_capsule_report,
336--
Patrick Williams8dd68482022-10-04 07:57:18 -05003372.17.1
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400338