summaryrefslogtreecommitdiffstats
path: root/recipes-bsp/systemd-boot/systemd-boot/0003-sd-boot-Load-board-specific-boot-entries-from-RMC-da.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes-bsp/systemd-boot/systemd-boot/0003-sd-boot-Load-board-specific-boot-entries-from-RMC-da.patch')
-rw-r--r--recipes-bsp/systemd-boot/systemd-boot/0003-sd-boot-Load-board-specific-boot-entries-from-RMC-da.patch252
1 files changed, 0 insertions, 252 deletions
diff --git a/recipes-bsp/systemd-boot/systemd-boot/0003-sd-boot-Load-board-specific-boot-entries-from-RMC-da.patch b/recipes-bsp/systemd-boot/systemd-boot/0003-sd-boot-Load-board-specific-boot-entries-from-RMC-da.patch
deleted file mode 100644
index cef934ce..00000000
--- a/recipes-bsp/systemd-boot/systemd-boot/0003-sd-boot-Load-board-specific-boot-entries-from-RMC-da.patch
+++ /dev/null
@@ -1,252 +0,0 @@
1From b780c67c780bae2f834d73017044680fabca4268 Mon Sep 17 00:00:00 2001
2From: Jianxun Zhang <jianxun.zhang@linux.intel.com>
3Date: Wed, 1 Jun 2016 16:32:22 -0700
4Subject: [PATCH 3/5] sd-boot: Load board-specific boot entries from RMC
5 database
6
7RMC provides a centralized database file on ESP. The DB contains
8fingerprints and any file blobs associated to physical boards.
9Callers can fetch board-specific data with fingerprint info
10collected from board at runtime if there is any record matched
11board's fingerprint.
12
13To let bootloader know which file blob in RMC should be queried,
14a special config file BOOTENTRY.CONFIG is defined as:
15
16boot.conf
17install.conf
18
19Bootloader calls RMC APIs and other functions to perform these
20tasks before it shows boot menu to user:
21
22(1) Load RMC database file from ESP
23(2) Collect fingerprint data from board
24(3) Query BOOTENTRY.CONFIG from RMC DB with fingerprint
25(4) Parse BOOTENTRY.CONFIG to know names of boot entry files
26(5) Query boot entry files one by one from RMC DB, and add
27 them into sd-boot config data.
28
29The final effect is that bootloader will show board-specific
30boot entries in boot menu to user. User then can choose one
31of them to boot system with the selected configuration.
32
33If any of these steps fails, bootloader simply skips loading
34RMC configs or any entry file not successfully fetched from
35RMC DB. Once any entry is loaded successfully from RMC DB,
36bootloader skips loading any boot entries from ESP.
37
38Upstream-Status: Pending
39
40Signed-off-by: Jianxun Zhang <jianxun.zhang@linux.intel.com>
41Signed-off-by: California Sullivan <california.l.sullivan@intel.com>
42---
43 src/boot/efi/boot.c | 148 +++++++++++++++++++++++++++++++++++++++++++++++++++-
44 1 file changed, 146 insertions(+), 2 deletions(-)
45
46diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c
47index b9c7c8394..93cfaf193 100644
48--- a/src/boot/efi/boot.c
49+++ b/src/boot/efi/boot.c
50@@ -16,6 +16,7 @@
51
52 #include <efi.h>
53 #include <efilib.h>
54+#include <rmc_api.h>
55
56 #include "console.h"
57 #include "disk.h"
58@@ -35,6 +36,9 @@ static const char __attribute__((used)) magic[] = "#### LoaderInfo: systemd-boot
59
60 static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE;
61
62+static CHAR8* rmc_db;
63+static rmc_fingerprint_t *rmc_fp;
64+
65 enum loader_type {
66 LOADER_UNDEFINED,
67 LOADER_EFI,
68@@ -1684,6 +1688,136 @@ static VOID config_free(Config *config) {
69 FreePool(config->entry_oneshot);
70 }
71
72+/* Derived from line_get_key_value(), we could consolidate two functions later */
73+static CHAR8 *get_line(CHAR8 *content, UINT64 *pos) {
74+ CHAR8 *line;
75+ UINT64 linelen;
76+
77+skip:
78+ line = content + *pos;
79+ if (*line == '\0')
80+ return NULL;
81+
82+ linelen = 0;
83+ while (line[linelen] && !strchra((CHAR8 *)"\n\r", line[linelen]))
84+ linelen++;
85+
86+ /* move pos to next line */
87+ *pos += linelen;
88+ if (content[*pos])
89+ (*pos)++;
90+
91+ /* empty line */
92+ if (linelen == 0)
93+ goto skip;
94+
95+ /* terminate line */
96+ line[linelen] = '\0';
97+
98+ /* remove leading whitespace */
99+ while (strchra((CHAR8 *)" \t", *line)) {
100+ line++;
101+ linelen--;
102+ }
103+
104+ /* remove trailing whitespace */
105+ while (linelen > 0 && strchra((CHAR8 *)" \t", line[linelen-1]))
106+ linelen--;
107+ line[linelen] = '\0';
108+
109+ if (*line == '#')
110+ goto skip;
111+
112+ return line;
113+}
114+
115+/* load rmc database file from ESP and try to get fingerprint. These
116+ * are essential information indicating we could query rmc data for
117+ * this board at least
118+ * return 0 if both database file and fingerprint can be obtained, otherwise
119+ * non-zero value is returned.
120+ *
121+ * Note: db and fp hold valid values only when this function returns 0.
122+ * Caller is responsible to free allocated memory pointed by *db and *fp when
123+ * this function returns 0.
124+ */
125+
126+static UINTN rmc_initialize(EFI_FILE *root_dir, EFI_SYSTEM_TABLE *sys_table, CHAR8 **db, rmc_fingerprint_t **fp) {
127+ UINTN len;
128+ UINTN ret = 1;
129+
130+ if (!db || !fp)
131+ return ret;
132+
133+ *db = NULL;
134+ *fp = NULL;
135+
136+ /* load rmc database */
137+ len = file_read(root_dir, L"\\rmc.db", 0, 0, db);
138+
139+ if (len <= 0)
140+ goto done;
141+
142+ *fp = AllocateZeroPool(sizeof(rmc_fingerprint_t));
143+ /* call rmc to get fingerprint. We will use single-action rmc APIs to query multiple files.
144+ * This should bring a better performance than calling double-action rmc API every time.
145+ */
146+ if (rmc_get_fingerprint(sys_table, *fp))
147+ goto done;
148+
149+ ret = 0;
150+done:
151+ if (ret) {
152+ FreePool(*db);
153+ FreePool(*fp);
154+ }
155+
156+ return ret;
157+}
158+
159+/* load RMC entries
160+ * return TRUE when at least one entry is loaded, otherwise, return FALSE
161+ */
162+static BOOLEAN config_load_rmc_entries(Config *config, EFI_HANDLE *device, CHAR16 *loaded_image_path, CHAR8 *db, rmc_fingerprint_t *fp) {
163+ CHAR8 *boot_entry = NULL;
164+ CHAR8 *boot_config = NULL;
165+ rmc_file_t rp;
166+ CHAR8 *line;
167+ UINT64 pos = 0;
168+ BOOLEAN ret = FALSE;
169+
170+ if (!db || !fp)
171+ return ret;
172+
173+ /* query boot entry config file */
174+ if (rmc_query_file_by_fp(fp, db, "BOOTENTRY.CONFIG", &rp))
175+ return ret;
176+
177+ /* file blob read from rmc db is not necessarily null-terminated, and we
178+ * should keep mem where rmc db lives from change during parsing
179+ */
180+ boot_config = AllocatePool(rp.blob_len * sizeof(CHAR8) + 1);
181+ CopyMem(boot_config, rp.blob, rp.blob_len);
182+ boot_config[rp.blob_len] = '\0';
183+ /* parse boot entry config */
184+ while ((line = get_line(boot_config, &pos))) {
185+ if (rmc_query_file_by_fp(fp, db, (char *)line, &rp))
186+ continue;
187+ if (rp.blob_len > 0) {
188+ boot_entry = AllocatePool(rp.blob_len * sizeof(CHAR8) + 1);
189+ CopyMem(boot_entry, rp.blob, rp.blob_len);
190+ boot_entry[rp.blob_len] = '\0';
191+ config_entry_add_from_file(config, device,
192+ stra_to_str(line), boot_entry,
193+ loaded_image_path);
194+ /* tell caller success when a RMC entry is loaded */
195+ ret = TRUE;
196+ }
197+ }
198+
199+ return ret;
200+}
201+
202 EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
203 CHAR16 *s;
204 CHAR8 *b;
205@@ -1696,6 +1830,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
206 UINT64 init_usec;
207 BOOLEAN menu = FALSE;
208 CHAR16 uuid[37];
209+ BOOLEAN rmc_entry = FALSE;
210
211 InitializeLib(image, sys_table);
212 init_usec = time_usec();
213@@ -1736,6 +1871,9 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
214 }
215 }
216
217+ /* Initialize rmc before loading any config */
218+ rmc_initialize(root_dir, sys_table, &rmc_db, &rmc_fp);
219+
220 /* the filesystem path to this image, to prevent adding ourselves to the menu */
221 loaded_image_path = DevicePathToStr(loaded_image->FilePath);
222 efivar_set(L"LoaderImageIdentifier", loaded_image_path, FALSE);
223@@ -1743,11 +1881,15 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
224 ZeroMem(&config, sizeof(Config));
225 config_load_defaults(&config, root_dir);
226
227+ if (rmc_db && rmc_fp)
228+ rmc_entry = config_load_rmc_entries(&config, loaded_image->DeviceHandle, loaded_image_path, rmc_db, rmc_fp);
229+
230 /* scan /EFI/Linux/ directory */
231 config_entry_add_linux(&config, loaded_image, root_dir);
232
233- /* scan /loader/entries/\*.conf files */
234- config_load_entries(&config, loaded_image->DeviceHandle, root_dir, loaded_image_path);
235+ /* scan /loader/entries/\*.conf files only when no RMC entry is loaded */
236+ if (rmc_entry == FALSE)
237+ config_load_entries(&config, loaded_image->DeviceHandle, root_dir, loaded_image_path);
238
239 /* sort entries after version number */
240 config_sort_entries(&config);
241@@ -1841,6 +1983,8 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
242 out:
243 FreePool(loaded_image_path);
244 config_free(&config);
245+ FreePool(rmc_db);
246+ FreePool(rmc_fp);
247 uefi_call_wrapper(root_dir->Close, 1, root_dir);
248 uefi_call_wrapper(BS->CloseProtocol, 4, image, &LoadedImageProtocol, image, NULL);
249 return err;
250--
2512.14.3
252