blob: ce40df0fd8fa08c42e1761ad853acec9bd0fe724 [file] [log] [blame]
Patrick Williams7784c422022-11-17 07:29:11 -06001From 70cf374fb55f2d62ecbe28049253df33b42b6749 Mon Sep 17 00:00:00 2001
Patrick Williams2390b1b2022-11-03 13:47:49 -05002From: Satish Kumar <satish.kumar01@arm.com>
3Date: Fri, 8 Jul 2022 09:48:06 +0100
Patrick Williams7784c422022-11-17 07:29:11 -06004Subject: [PATCH 20/20] FMP Support in Corstone1000.
Patrick Williams2390b1b2022-11-03 13:47:49 -05005
6The FMP support is used by u-boot to pupolate ESRT information
7for the kernel.
8
9The solution is platform specific and needs to be revisted.
10
11Signed-off-by: Satish Kumar <satish.kumar01@arm.com>
12
13Upstream-Status: Inappropriate [The solution is platform specific and needs to be revisted]
Patrick Williams7784c422022-11-17 07:29:11 -060014Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
Patrick Williams2390b1b2022-11-03 13:47:49 -050015---
16 .../provider/capsule_update_provider.c | 5 +
17 .../capsule_update/provider/component.cmake | 1 +
18 .../provider/corstone1000_fmp_service.c | 307 ++++++++++++++++++
19 .../provider/corstone1000_fmp_service.h | 26 ++
20 4 files changed, 339 insertions(+)
21 create mode 100644 components/service/capsule_update/provider/corstone1000_fmp_service.c
22 create mode 100644 components/service/capsule_update/provider/corstone1000_fmp_service.h
23
24diff --git a/components/service/capsule_update/provider/capsule_update_provider.c b/components/service/capsule_update/provider/capsule_update_provider.c
Patrick Williams7784c422022-11-17 07:29:11 -060025index e133753f8560..991a2235cd73 100644
Patrick Williams2390b1b2022-11-03 13:47:49 -050026--- a/components/service/capsule_update/provider/capsule_update_provider.c
27+++ b/components/service/capsule_update/provider/capsule_update_provider.c
28@@ -11,6 +11,7 @@
29 #include <protocols/service/capsule_update/capsule_update_proto.h>
30 #include <protocols/rpc/common/packed-c/status.h>
31 #include "capsule_update_provider.h"
32+#include "corstone1000_fmp_service.h"
33
34
35 #define CAPSULE_UPDATE_REQUEST (0x1)
36@@ -47,6 +48,8 @@ struct rpc_interface *capsule_update_provider_init(
37 rpc_interface = service_provider_get_rpc_interface(&context->base_provider);
38 }
39
40+ provision_fmp_variables_metadata(context->client.caller);
41+
42 return rpc_interface;
43 }
44
45@@ -85,6 +88,7 @@ static rpc_status_t event_handler(uint32_t opcode, struct rpc_caller *caller)
46 }
47 psa_call(caller,handle, PSA_IPC_CALL,
48 in_vec,IOVEC_LEN(in_vec), NULL, 0);
49+ set_fmp_image_info(caller, handle);
50 break;
51
52 case KERNEL_STARTED_EVENT:
53@@ -99,6 +103,7 @@ static rpc_status_t event_handler(uint32_t opcode, struct rpc_caller *caller)
54 }
55 psa_call(caller,handle, PSA_IPC_CALL,
56 in_vec,IOVEC_LEN(in_vec), NULL, 0);
57+ set_fmp_image_info(caller, handle);
58 break;
59 default:
60 EMSG("%s unsupported opcode", __func__);
61diff --git a/components/service/capsule_update/provider/component.cmake b/components/service/capsule_update/provider/component.cmake
Patrick Williams7784c422022-11-17 07:29:11 -060062index 1d412eb234d9..6b0601494938 100644
Patrick Williams2390b1b2022-11-03 13:47:49 -050063--- a/components/service/capsule_update/provider/component.cmake
64+++ b/components/service/capsule_update/provider/component.cmake
65@@ -10,4 +10,5 @@ endif()
66
67 target_sources(${TGT} PRIVATE
68 "${CMAKE_CURRENT_LIST_DIR}/capsule_update_provider.c"
69+ "${CMAKE_CURRENT_LIST_DIR}/corstone1000_fmp_service.c"
70 )
71diff --git a/components/service/capsule_update/provider/corstone1000_fmp_service.c b/components/service/capsule_update/provider/corstone1000_fmp_service.c
72new file mode 100644
Patrick Williams7784c422022-11-17 07:29:11 -060073index 000000000000..6a7a47a7ed99
Patrick Williams2390b1b2022-11-03 13:47:49 -050074--- /dev/null
75+++ b/components/service/capsule_update/provider/corstone1000_fmp_service.c
76@@ -0,0 +1,307 @@
77+/*
78+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
79+ *
80+ * SPDX-License-Identifier: BSD-3-Clause
81+ */
82+
83+#include "corstone1000_fmp_service.h"
84+#include <psa/client.h>
85+#include <psa/sid.h>
86+#include <psa/storage_common.h>
87+#include <trace.h>
88+
89+#include <service/smm_variable/backend/variable_index.h>
90+
91+#define VARIABLE_INDEX_STORAGE_UID (0x787)
92+
93+/**
94+ * Variable attributes
95+ */
96+#define EFI_VARIABLE_NON_VOLATILE (0x00000001)
97+#define EFI_VARIABLE_BOOTSERVICE_ACCESS (0x00000002)
98+#define EFI_VARIABLE_RUNTIME_ACCESS (0x00000004)
99+#define EFI_VARIABLE_HARDWARE_ERROR_RECORD (0x00000008)
100+#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS (0x00000010)
101+#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS (0x00000020)
102+#define EFI_VARIABLE_APPEND_WRITE (0x00000040)
103+#define EFI_VARIABLE_MASK \
104+ (EFI_VARIABLE_NON_VOLATILE | \
105+ EFI_VARIABLE_BOOTSERVICE_ACCESS | \
106+ EFI_VARIABLE_RUNTIME_ACCESS | \
107+ EFI_VARIABLE_HARDWARE_ERROR_RECORD | \
108+ EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | \
109+ EFI_VARIABLE_APPEND_WRITE)
110+
111+#define FMP_VARIABLES_COUNT 6
112+
113+static struct variable_metadata fmp_variables_metadata[FMP_VARIABLES_COUNT] = {
114+ {
115+ { 0x86c77a67, 0x0b97, 0x4633, \
116+ { 0xa1, 0x87, 0x49, 0x10, 0x4d, 0x06, 0x85, 0xc7} },
117+ /* name size = (variable_name + \0) * sizeof(u16) */
118+ .name_size = 42, { 'F', 'm', 'p', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'V', 'e', 'r', 's', 'i', 'o', 'n' },
119+ .attributes = EFI_VARIABLE_NON_VOLATILE, .uid = 0
120+ },
121+ {
122+ { 0x86c77a67, 0x0b97, 0x4633, \
123+ { 0xa1, 0x87, 0x49, 0x10, 0x4d, 0x06, 0x85, 0xc7} },
124+ /* name size = (variable_name + \0) * sizeof(u16) */
125+ .name_size = 34, { 'F', 'm', 'p', 'I', 'm', 'a', 'g', 'e', 'I', 'n', 'f', 'o', 'S', 'i', 'z', 'e' },
126+ .attributes = EFI_VARIABLE_NON_VOLATILE, .uid = 0
127+ },
128+ {
129+ { 0x86c77a67, 0x0b97, 0x4633, \
130+ { 0xa1, 0x87, 0x49, 0x10, 0x4d, 0x06, 0x85, 0xc7} },
131+ /* name size = (variable_name + \0) * sizeof(u16) */
132+ .name_size = 38, { 'F', 'm', 'p', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'C', 'o', 'u', 'n', 't' },
133+ .attributes = EFI_VARIABLE_NON_VOLATILE, .uid = 0
134+ },
135+ {
136+ { 0x86c77a67, 0x0b97, 0x4633, \
137+ { 0xa1, 0x87, 0x49, 0x10, 0x4d, 0x06, 0x85, 0xc7} },
138+ /* name size = (variable_name + \0) * sizeof(u16) */
139+ .name_size = 26, { 'F', 'm', 'p', 'I', 'm', 'a', 'g', 'e', 'I', 'n', 'f', 'o' },
140+ .attributes = EFI_VARIABLE_NON_VOLATILE, .uid = 0
141+ },
142+ {
143+ { 0x86c77a67, 0x0b97, 0x4633, \
144+ { 0xa1, 0x87, 0x49, 0x10, 0x4d, 0x06, 0x85, 0xc7} },
145+ /* name size = (variable_name + \0) * sizeof(u16) */
146+ .name_size = 28, { 'F', 'm', 'p', 'I', 'm', 'a', 'g', 'e', 'N', 'a', 'm', 'e', '1' },
147+ .attributes = EFI_VARIABLE_NON_VOLATILE, .uid = 0
148+ },
149+ {
150+ { 0x86c77a67, 0x0b97, 0x4633, \
151+ { 0xa1, 0x87, 0x49, 0x10, 0x4d, 0x06, 0x85, 0xc7} },
152+ /* name size = (variable_name + \0) * sizeof(u16) */
153+ .name_size = 32, { 'F', 'm', 'p', 'V', 'e', 'r', 's', 'i', 'o', 'n', 'N', 'a', 'm', 'e', '1' },
154+ .attributes = EFI_VARIABLE_NON_VOLATILE, .uid = 0
155+ },
156+};
157+
158+static psa_status_t protected_storage_set(struct rpc_caller *caller,
159+ psa_storage_uid_t uid, size_t data_length, const void *p_data)
160+{
161+ psa_status_t psa_status;
162+ psa_storage_create_flags_t create_flags = PSA_STORAGE_FLAG_NONE;
163+
164+ struct psa_invec in_vec[] = {
165+ { .base = psa_ptr_to_u32(&uid), .len = sizeof(uid) },
166+ { .base = psa_ptr_const_to_u32(p_data), .len = data_length },
167+ { .base = psa_ptr_to_u32(&create_flags), .len = sizeof(create_flags) },
168+ };
169+
170+ psa_status = psa_call(caller, TFM_PROTECTED_STORAGE_SERVICE_HANDLE, TFM_PS_ITS_SET,
171+ in_vec, IOVEC_LEN(in_vec), NULL, 0);
172+ if (psa_status < 0)
173+ EMSG("ipc_set: psa_call failed: %d", psa_status);
174+
175+ return psa_status;
176+}
177+
178+static psa_status_t protected_storage_get(struct rpc_caller *caller,
179+ psa_storage_uid_t uid, size_t data_size, void *p_data)
180+{
181+ psa_status_t psa_status;
182+ uint32_t offset = 0;
183+
184+ struct psa_invec in_vec[] = {
185+ { .base = psa_ptr_to_u32(&uid), .len = sizeof(uid) },
186+ { .base = psa_ptr_to_u32(&offset), .len = sizeof(offset) },
187+ };
188+
189+ struct psa_outvec out_vec[] = {
190+ { .base = psa_ptr_to_u32(p_data), .len = data_size },
191+ };
192+
193+ psa_status = psa_call(caller, TFM_PROTECTED_STORAGE_SERVICE_HANDLE,
194+ TFM_PS_ITS_GET, in_vec, IOVEC_LEN(in_vec),
195+ out_vec, IOVEC_LEN(out_vec));
196+
197+ if (psa_status == PSA_SUCCESS && out_vec[0].len != data_size) {
198+ EMSG("Return size does not match with expected size.");
199+ return PSA_ERROR_BUFFER_TOO_SMALL;
200+ }
201+
202+ return psa_status;
203+}
204+
205+static uint64_t name_hash(EFI_GUID *guid, size_t name_size,
206+ const int16_t *name)
207+{
208+ /* Using djb2 hash by Dan Bernstein */
209+ uint64_t hash = 5381;
210+
211+ /* Calculate hash over GUID */
212+ hash = ((hash << 5) + hash) + guid->Data1;
213+ hash = ((hash << 5) + hash) + guid->Data2;
214+ hash = ((hash << 5) + hash) + guid->Data3;
215+
216+ for (int i = 0; i < 8; ++i) {
217+
218+ hash = ((hash << 5) + hash) + guid->Data4[i];
219+ }
220+
221+ /* Extend to cover name up to but not including null terminator */
222+ for (int i = 0; i < name_size / sizeof(int16_t); ++i) {
223+
224+ if (!name[i]) break;
225+ hash = ((hash << 5) + hash) + name[i];
226+ }
227+
228+ return hash;
229+}
230+
231+
232+static void initialize_metadata(void)
233+{
234+ for (int i = 0; i < FMP_VARIABLES_COUNT; i++) {
235+
236+ fmp_variables_metadata[i].uid = name_hash(
237+ &fmp_variables_metadata[i].guid,
238+ fmp_variables_metadata[i].name_size,
239+ fmp_variables_metadata[i].name);
240+ }
241+}
242+
243+
244+void provision_fmp_variables_metadata(struct rpc_caller *caller)
245+{
246+ struct variable_metadata metadata;
247+ psa_status_t status;
248+ uint32_t dummy_values = 0xDEAD;
249+
250+ EMSG("Provisioning FMP metadata.");
251+
252+ initialize_metadata();
253+
254+ status = protected_storage_get(caller, VARIABLE_INDEX_STORAGE_UID,
255+ sizeof(struct variable_metadata), &metadata);
256+
257+ if (status == PSA_SUCCESS) {
258+ EMSG("UEFI variables store is already provisioned.");
259+ return;
260+ }
261+
262+ /* Provision FMP variables with dummy values. */
263+ for (int i = 0; i < FMP_VARIABLES_COUNT; i++) {
264+ protected_storage_set(caller, fmp_variables_metadata[i].uid,
265+ sizeof(dummy_values), &dummy_values);
266+ }
267+
268+ status = protected_storage_set(caller, VARIABLE_INDEX_STORAGE_UID,
269+ sizeof(struct variable_metadata) * FMP_VARIABLES_COUNT,
270+ fmp_variables_metadata);
271+
272+ if (status != EFI_SUCCESS) {
273+ return;
274+ }
275+
276+ EMSG("FMP metadata is provisioned");
277+}
278+
279+typedef struct {
280+ void *base;
281+ int len;
282+} variable_data_t;
283+
284+static variable_data_t fmp_variables_data[FMP_VARIABLES_COUNT];
285+
286+#define IMAGE_INFO_BUFFER_SIZE 256
287+static char image_info_buffer[IMAGE_INFO_BUFFER_SIZE];
288+#define IOCTL_CORSTONE1000_FMP_IMAGE_INFO 2
289+
290+static psa_status_t unpack_image_info(void *buffer, uint32_t size)
291+{
292+ typedef struct __attribute__ ((__packed__)) {
293+ uint32_t variable_count;
294+ uint32_t variable_size[FMP_VARIABLES_COUNT];
295+ uint8_t variable[];
296+ } packed_buffer_t;
297+
298+ packed_buffer_t *packed_buffer = buffer;
299+ int runner = 0;
300+
301+ if (packed_buffer->variable_count != FMP_VARIABLES_COUNT) {
302+ EMSG("Expected fmp varaibles = %u, but received = %u",
303+ FMP_VARIABLES_COUNT, packed_buffer->variable_count);
304+ return PSA_ERROR_PROGRAMMER_ERROR;
305+ }
306+
307+ for (int i = 0; i < packed_buffer->variable_count; i++) {
308+ EMSG("FMP variable %d : size %u", i, packed_buffer->variable_size[i]);
309+ fmp_variables_data[i].base = &packed_buffer->variable[runner];
310+ fmp_variables_data[i].len= packed_buffer->variable_size[i];
311+ runner += packed_buffer->variable_size[i];
312+ }
313+
314+ return PSA_SUCCESS;
315+}
316+
317+static psa_status_t get_image_info(struct rpc_caller *caller,
318+ psa_handle_t platform_service_handle)
319+{
320+ psa_status_t status;
321+ psa_handle_t handle;
322+ uint32_t ioctl_id = IOCTL_CORSTONE1000_FMP_IMAGE_INFO;
323+
324+ struct psa_invec in_vec[] = {
325+ { .base = &ioctl_id, .len = sizeof(ioctl_id) },
326+ };
327+
328+ struct psa_outvec out_vec[] = {
329+ { .base = image_info_buffer, .len = IMAGE_INFO_BUFFER_SIZE },
330+ };
331+
332+ memset(image_info_buffer, 0, IMAGE_INFO_BUFFER_SIZE);
333+
334+ psa_call(caller, platform_service_handle, PSA_IPC_CALL,
335+ in_vec, IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
336+
337+ status = unpack_image_info(image_info_buffer, IMAGE_INFO_BUFFER_SIZE);
338+ if (status != PSA_SUCCESS) {
339+ return status;
340+ }
341+
342+ return PSA_SUCCESS;
343+}
344+
345+static psa_status_t set_image_info(struct rpc_caller *caller)
346+{
347+ psa_status_t status;
348+
349+ for (int i = 0; i < FMP_VARIABLES_COUNT; i++) {
350+
351+ status = protected_storage_set(caller,
352+ fmp_variables_metadata[i].uid,
353+ fmp_variables_data[i].len, fmp_variables_data[i].base);
354+
355+ if (status != PSA_SUCCESS) {
356+
357+ EMSG("FMP variable %d set unsuccessful", i);
358+ return status;
359+ }
360+
361+ EMSG("FMP variable %d set success", i);
362+ }
363+
364+ return PSA_SUCCESS;
365+}
366+
367+void set_fmp_image_info(struct rpc_caller *caller,
368+ psa_handle_t platform_service_handle)
369+{
370+ psa_status_t status;
371+
372+ status = get_image_info(caller, platform_service_handle);
373+ if (status != PSA_SUCCESS) {
374+ return;
375+ }
376+
377+ status = set_image_info(caller);
378+ if (status != PSA_SUCCESS) {
379+ return;
380+ }
381+
382+ return;
383+}
384diff --git a/components/service/capsule_update/provider/corstone1000_fmp_service.h b/components/service/capsule_update/provider/corstone1000_fmp_service.h
385new file mode 100644
Patrick Williams7784c422022-11-17 07:29:11 -0600386index 000000000000..95fba2a04d5c
Patrick Williams2390b1b2022-11-03 13:47:49 -0500387--- /dev/null
388+++ b/components/service/capsule_update/provider/corstone1000_fmp_service.h
389@@ -0,0 +1,26 @@
390+/*
391+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
392+ *
393+ * SPDX-License-Identifier: BSD-3-Clause
394+ */
395+
396+#ifndef CORSTONE1000_FMP_SERVICE_H
397+#define CORSTONE1000_FMP_SERVICE_H
398+
399+#ifdef __cplusplus
400+extern "C" {
401+#endif
402+
403+#include <rpc_caller.h>
404+#include <psa/client.h>
405+
406+void provision_fmp_variables_metadata(struct rpc_caller *caller);
407+
408+void set_fmp_image_info(struct rpc_caller *caller,
409+ psa_handle_t platform_service_handle);
410+
411+#ifdef __cplusplus
412+} /* extern "C" */
413+#endif
414+
415+#endif /* CORSTONE1000_FMP_SERVICE_H */
416--
Patrick Williams7784c422022-11-17 07:29:11 -06004172.38.1
Patrick Williams2390b1b2022-11-03 13:47:49 -0500418