From f2502f90ab3decc5c3faf38ecfd13ac3bce4f411 Mon Sep 17 00:00:00 2001 From: California Sullivan Date: Tue, 20 Mar 2018 16:21:33 -0700 Subject: systemd-boot/rmc-boot.inc: update to work with v237 and meson Patch changes: * 0001-sd-boot-Link-RMC-library-into-bootloader-and-stub.patch removed because make is no longer used. * 0001-sd-boot-stub-check-LoadOptions-contains-data.patch removed because it was accepted upstream. * 0001-partially-revert-sd-boot-stub-Obtain-PE-section-offs.patch added to support RMC functionality. Upstream removed a snippet that found the root directory because they didn't need it anymore, but RMC does. * 0002-sd-boot-fix-RMC-compatibility-with-systemd-boot-and-.patch added to support building with meson instead of make. * Others refreshed inc file changes: * Don't commit pin, we can maintain these patches OK for now * EXTRA_OEMAKE -> EXTRA_OEMESON, and removed some superfluous options Signed-off-by: California Sullivan --- ...evert-sd-boot-stub-Obtain-PE-section-offs.patch | 46 ++++ ...Link-RMC-library-into-bootloader-and-stub.patch | 39 ---- ...boot-stub-check-LoadOptions-contains-data.patch | 42 ---- ...d-board-specific-boot-entries-from-RMC-da.patch | 250 -------------------- ...-RMC-compatibility-with-systemd-boot-and-.patch | 62 +++++ ...d-board-specific-boot-entries-from-RMC-da.patch | 252 +++++++++++++++++++++ ...pport-global-kernel-command-line-fragment.patch | 66 ------ ...-kernel-command-line-fragment-in-EFI-stub.patch | 81 ------- ...pport-global-kernel-command-line-fragment.patch | 67 ++++++ ...port-global-kernel-command-line-in-EFI-st.patch | 82 +++++++ recipes-bsp/systemd-boot/systemd-boot/rmc-boot.inc | 24 +- 11 files changed, 518 insertions(+), 493 deletions(-) create mode 100644 recipes-bsp/systemd-boot/systemd-boot/0001-partially-revert-sd-boot-stub-Obtain-PE-section-offs.patch delete mode 100644 recipes-bsp/systemd-boot/systemd-boot/0001-sd-boot-Link-RMC-library-into-bootloader-and-stub.patch delete mode 100644 recipes-bsp/systemd-boot/systemd-boot/0001-sd-boot-stub-check-LoadOptions-contains-data.patch delete mode 100644 recipes-bsp/systemd-boot/systemd-boot/0002-sd-boot-Load-board-specific-boot-entries-from-RMC-da.patch create mode 100644 recipes-bsp/systemd-boot/systemd-boot/0002-sd-boot-fix-RMC-compatibility-with-systemd-boot-and-.patch create mode 100644 recipes-bsp/systemd-boot/systemd-boot/0003-sd-boot-Load-board-specific-boot-entries-from-RMC-da.patch delete mode 100644 recipes-bsp/systemd-boot/systemd-boot/0003-sd-boot-Support-global-kernel-command-line-fragment.patch delete mode 100644 recipes-bsp/systemd-boot/systemd-boot/0004-sd-boot-Support-global-kernel-command-line-fragment-in-EFI-stub.patch create mode 100644 recipes-bsp/systemd-boot/systemd-boot/0004-sd-boot-Support-global-kernel-command-line-fragment.patch create mode 100644 recipes-bsp/systemd-boot/systemd-boot/0005-sd-boot-support-global-kernel-command-line-in-EFI-st.patch diff --git a/recipes-bsp/systemd-boot/systemd-boot/0001-partially-revert-sd-boot-stub-Obtain-PE-section-offs.patch b/recipes-bsp/systemd-boot/systemd-boot/0001-partially-revert-sd-boot-stub-Obtain-PE-section-offs.patch new file mode 100644 index 00000000..6d7b144d --- /dev/null +++ b/recipes-bsp/systemd-boot/systemd-boot/0001-partially-revert-sd-boot-stub-Obtain-PE-section-offs.patch @@ -0,0 +1,46 @@ +From beb095f41d458b7d684c0cd6cac1749e2fc3f29b Mon Sep 17 00:00:00 2001 +From: California Sullivan +Date: Wed, 21 Mar 2018 13:01:26 -0700 +Subject: [PATCH 1/5] partially revert "sd-boot: stub: Obtain PE section + offsets from RAM, not disk (#6250)" + +Only revert the section for finding the root_dir, as RMC needs this to +find its database file. + +Upstream-Status: Inappropriate [upstream doesn't need the root_dir]. + +Signed-off-by: California Sullivan +--- + src/boot/efi/stub.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c +index ff45cebd4..540ca5985 100644 +--- a/src/boot/efi/stub.c ++++ b/src/boot/efi/stub.c +@@ -30,6 +30,8 @@ static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE; + + EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { + EFI_LOADED_IMAGE *loaded_image; ++ EFI_FILE *root_dir; ++ CHAR16 *loaded_image_path; + CHAR8 *b; + UINTN size; + BOOLEAN secure = FALSE; +@@ -58,6 +60,13 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { + return err; + } + ++ root_dir = LibOpenRoot(loaded_image->DeviceHandle); ++ if (!root_dir) { ++ Print(L"Unable to open root directory: %r ", err); ++ uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); ++ return EFI_LOAD_ERROR; ++ } ++ + if (efivar_get_raw(&global_guid, L"SecureBoot", &b, &size) == EFI_SUCCESS) { + if (*b > 0) + secure = TRUE; +-- +2.14.3 + diff --git a/recipes-bsp/systemd-boot/systemd-boot/0001-sd-boot-Link-RMC-library-into-bootloader-and-stub.patch b/recipes-bsp/systemd-boot/systemd-boot/0001-sd-boot-Link-RMC-library-into-bootloader-and-stub.patch deleted file mode 100644 index 2f248e21..00000000 --- a/recipes-bsp/systemd-boot/systemd-boot/0001-sd-boot-Link-RMC-library-into-bootloader-and-stub.patch +++ /dev/null @@ -1,39 +0,0 @@ -From fe1c2fdfe81f2ac2b41fe8543ba07f1911770d26 Mon Sep 17 00:00:00 2001 -From: Jianxun Zhang -Date: Sat, 21 May 2016 18:52:07 -0700 -Subject: [PATCH] sd-boot: Link RMC library into bootloader and stub - -Add RMC library into bootloader binary and stub. - -Upstream-Status: Pending - -Signed-off-by: Jianxun Zhang ---- - Makefile.am | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/Makefile.am b/Makefile.am -index 305099ab6..9fb6f9b7b 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -2802,7 +2802,7 @@ $(top_builddir)/src/boot/efi/%.o: $(top_srcdir)/src/boot/efi/%.c $(addprefix $(t - - $(systemd_boot_solib): $(systemd_boot_objects) - $(AM_V_CCLD)$(LD) $(efi_ldflags) $(systemd_boot_objects) \ -- -o $@ -lefi -lgnuefi $(shell $(CC) -print-libgcc-file-name); \ -+ -o $@ -lefi -lgnuefi -lrmcefi $(shell $(CC) -print-libgcc-file-name); \ - nm -D -u $@ | grep ' U ' && exit 1 || : - - $(systemd_boot): $(systemd_boot_solib) -@@ -2852,7 +2852,7 @@ $(top_builddir)/src/boot/efi/%.o: $(top_srcdir)/src/boot/efi/%.c $(addprefix $(t - - $(stub_solib): $(stub_objects) - $(AM_V_CCLD)$(LD) $(efi_ldflags) $(stub_objects) \ -- -o $@ -lefi -lgnuefi $(shell $(CC) -print-libgcc-file-name); \ -+ -o $@ -lefi -lgnuefi -lrmcefi $(shell $(CC) -print-libgcc-file-name); \ - nm -D -u $@ | grep ' U ' && exit 1 || : - - $(stub): $(stub_solib) --- -2.11.0 - diff --git a/recipes-bsp/systemd-boot/systemd-boot/0001-sd-boot-stub-check-LoadOptions-contains-data.patch b/recipes-bsp/systemd-boot/systemd-boot/0001-sd-boot-stub-check-LoadOptions-contains-data.patch deleted file mode 100644 index 69acc8f8..00000000 --- a/recipes-bsp/systemd-boot/systemd-boot/0001-sd-boot-stub-check-LoadOptions-contains-data.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 87cd5a5e0f06ceb7f9dbdcc4029e0c279a38e6ad Mon Sep 17 00:00:00 2001 -From: Mikko Ylinen -Date: Mon, 27 Feb 2017 10:04:03 +0200 -Subject: [PATCH] sd-boot: stub: check LoadOptions contains data - -With some UEFI shells LoadOptionsSize is reported being > 0 -but the corresponding LoadOptions does not contain any data -(the first element has value 0). - -When that happens, the stub feature that allows .cmdline to be -replaced by what's in LoadOptions ends up copying nothing/random -data to the kernel cmdline resulting in different kinds of boot -problems. - -To fix this, add a check to see if LoadOptions contains data -before replacing the .cmdline. - -Upstream-Status: Accepted [https://github.com/systemd/systemd/pull/5467] - -Fixes [YOCTO #11078]. - -Signed-off-by: Mikko Ylinen ---- - src/boot/efi/stub.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c -index 7c1ffb1bc..b7d5d3cda 100644 ---- a/src/boot/efi/stub.c -+++ b/src/boot/efi/stub.c -@@ -87,7 +87,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { - cmdline_len = szs[0]; - - /* if we are not in secure boot mode, accept a custom command line and replace the built-in one */ -- if (!secure && loaded_image->LoadOptionsSize > 0) { -+ if (!secure && loaded_image->LoadOptionsSize > 0 && *(CHAR16 *)loaded_image->LoadOptions != 0) { - CHAR16 *options; - CHAR8 *line; - UINTN i; --- -2.11.0 - diff --git a/recipes-bsp/systemd-boot/systemd-boot/0002-sd-boot-Load-board-specific-boot-entries-from-RMC-da.patch b/recipes-bsp/systemd-boot/systemd-boot/0002-sd-boot-Load-board-specific-boot-entries-from-RMC-da.patch deleted file mode 100644 index e88012c3..00000000 --- a/recipes-bsp/systemd-boot/systemd-boot/0002-sd-boot-Load-board-specific-boot-entries-from-RMC-da.patch +++ /dev/null @@ -1,250 +0,0 @@ -From a3c4fc8c2847fe289a617bcba1d905f580f0e18d Mon Sep 17 00:00:00 2001 -From: Jianxun Zhang -Date: Wed, 1 Jun 2016 16:32:22 -0700 -Subject: [PATCH 2/3] sd-boot: Load board-specific boot entries from RMC - database - -RMC provides a centralized database file on ESP. The DB contains -fingerprints and any file blobs associated to physical boards. -Callers can fetch board-specific data with fingerprint info -collected from board at runtime if there is any record matched -board's fingerprint. - -To let bootloader know which file blob in RMC should be queried, -a special config file BOOTENTRY.CONFIG is defined as: - -boot.conf -install.conf - -Bootloader calls RMC APIs and other functions to perform these -tasks before it shows boot menu to user: - -(1) Load RMC database file from ESP -(2) Collect fingerprint data from board -(3) Query BOOTENTRY.CONFIG from RMC DB with fingerprint -(4) Parse BOOTENTRY.CONFIG to know names of boot entry files -(5) Query boot entry files one by one from RMC DB, and add - them into sd-boot config data. - -The final effect is that bootloader will show board-specific -boot entries in boot menu to user. User then can choose one -of them to boot system with the selected configuration. - -If any of these steps fails, bootloader simply skips loading -RMC configs or any entry file not successfully fetched from -RMC DB. Once any entry is loaded successfully from RMC DB, -bootloader skips loading any boot entries from ESP. - -Upstream-Status: Pending - -Signed-off-by: Jianxun Zhang ---- - src/boot/efi/boot.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 145 insertions(+), 2 deletions(-) - -diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c -index 30c1ead..d1b029b 100644 ---- a/src/boot/efi/boot.c -+++ b/src/boot/efi/boot.c -@@ -15,6 +15,7 @@ - - #include - #include -+#include - - #include "console.h" - #include "disk.h" -@@ -33,6 +34,9 @@ static const char __attribute__((used)) magic[] = "#### LoaderInfo: systemd-boot - - static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE; - -+static CHAR8* rmc_db; -+static rmc_fingerprint_t *rmc_fp; -+ - enum loader_type { - LOADER_UNDEFINED, - LOADER_EFI, -@@ -1702,6 +1706,136 @@ static VOID config_free(Config *config) { - FreePool(config->entry_oneshot); - } - -+/* Derived from line_get_key_value(), we could consolidate two functions later */ -+static CHAR8 *get_line(CHAR8 *content, UINT64 *pos) { -+ CHAR8 *line; -+ UINT64 linelen; -+ -+skip: -+ line = content + *pos; -+ if (*line == '\0') -+ return NULL; -+ -+ linelen = 0; -+ while (line[linelen] && !strchra((CHAR8 *)"\n\r", line[linelen])) -+ linelen++; -+ -+ /* move pos to next line */ -+ *pos += linelen; -+ if (content[*pos]) -+ (*pos)++; -+ -+ /* empty line */ -+ if (linelen == 0) -+ goto skip; -+ -+ /* terminate line */ -+ line[linelen] = '\0'; -+ -+ /* remove leading whitespace */ -+ while (strchra((CHAR8 *)" \t", *line)) { -+ line++; -+ linelen--; -+ } -+ -+ /* remove trailing whitespace */ -+ while (linelen > 0 && strchra((CHAR8 *)" \t", line[linelen-1])) -+ linelen--; -+ line[linelen] = '\0'; -+ -+ if (*line == '#') -+ goto skip; -+ -+ return line; -+} -+ -+/* load rmc database file from ESP and try to get fingerprint. These -+ * are essential information indicating we could query rmc data for -+ * this board at least -+ * return 0 if both database file and fingerprint can be obtained, otherwise -+ * non-zero value is returned. -+ * -+ * Note: db and fp hold valid values only when this function returns 0. -+ * Caller is responsible to free allocated memory pointed by *db and *fp when -+ * this function returns 0. -+ */ -+ -+static UINTN rmc_initialize(EFI_FILE *root_dir, EFI_SYSTEM_TABLE *sys_table, CHAR8 **db, rmc_fingerprint_t **fp) { -+ UINTN len; -+ UINTN ret = 1; -+ -+ if (!db || !fp) -+ return ret; -+ -+ *db = NULL; -+ *fp = NULL; -+ -+ /* load rmc database */ -+ len = file_read(root_dir, L"\\rmc.db", 0, 0, db); -+ -+ if (len <= 0) -+ goto done; -+ -+ *fp = AllocateZeroPool(sizeof(rmc_fingerprint_t)); -+ /* call rmc to get fingerprint. We will use single-action rmc APIs to query multiple files. -+ * This should bring a better performance than calling double-action rmc API every time. -+ */ -+ if (rmc_get_fingerprint(sys_table, *fp)) -+ goto done; -+ -+ ret = 0; -+done: -+ if (ret) { -+ FreePool(*db); -+ FreePool(*fp); -+ } -+ -+ return ret; -+} -+ -+/* load RMC entries -+ * return TRUE when at least one entry is loaded, otherwise, return FALSE -+ */ -+static BOOLEAN config_load_rmc_entries(Config *config, EFI_HANDLE *device, CHAR16 *loaded_image_path, CHAR8 *db, rmc_fingerprint_t *fp) { -+ CHAR8 *boot_entry = NULL; -+ CHAR8 *boot_config = NULL; -+ rmc_file_t rp; -+ CHAR8 *line; -+ UINT64 pos = 0; -+ BOOLEAN ret = FALSE; -+ -+ if (!db || !fp) -+ return ret; -+ -+ /* query boot entry config file */ -+ if (rmc_query_file_by_fp(fp, db, "BOOTENTRY.CONFIG", &rp)) -+ return ret; -+ -+ /* file blob read from rmc db is not necessarily null-terminated, and we -+ * should keep mem where rmc db lives from change during parsing -+ */ -+ boot_config = AllocatePool(rp.blob_len * sizeof(CHAR8) + 1); -+ CopyMem(boot_config, rp.blob, rp.blob_len); -+ boot_config[rp.blob_len] = '\0'; -+ /* parse boot entry config */ -+ while ((line = get_line(boot_config, &pos))) { -+ if (rmc_query_file_by_fp(fp, db, (char *)line, &rp)) -+ continue; -+ if (rp.blob_len > 0) { -+ boot_entry = AllocatePool(rp.blob_len * sizeof(CHAR8) + 1); -+ CopyMem(boot_entry, rp.blob, rp.blob_len); -+ boot_entry[rp.blob_len] = '\0'; -+ config_entry_add_from_file(config, device, -+ stra_to_str(line), boot_entry, -+ loaded_image_path); -+ /* tell caller success when a RMC entry is loaded */ -+ ret = TRUE; -+ } -+ } -+ -+ return ret; -+} -+ - EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { - CHAR16 *s; - CHAR8 *b; -@@ -1714,6 +1848,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { - UINT64 init_usec; - BOOLEAN menu = FALSE; - CHAR16 uuid[37]; -+ BOOLEAN rmc_entry = FALSE; - - InitializeLib(image, sys_table); - init_usec = time_usec(); -@@ -1745,6 +1880,8 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { - return EFI_LOAD_ERROR; - } - -+ /* Initialize rmc before loading any config */ -+ rmc_initialize(root_dir, sys_table, &rmc_db, &rmc_fp); - - /* the filesystem path to this image, to prevent adding ourselves to the menu */ - loaded_image_path = DevicePathToStr(loaded_image->FilePath); -@@ -1753,11 +1890,15 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { - ZeroMem(&config, sizeof(Config)); - config_load_defaults(&config, root_dir); - -+ if (rmc_db && rmc_fp) -+ rmc_entry = config_load_rmc_entries(&config, loaded_image->DeviceHandle, loaded_image_path, rmc_db, rmc_fp); -+ - /* scan /EFI/Linux/ directory */ - config_entry_add_linux(&config, loaded_image, root_dir); - -- /* scan /loader/entries/\*.conf files */ -- config_load_entries(&config, loaded_image->DeviceHandle, root_dir, loaded_image_path); -+ /* scan /loader/entries/\*.conf files only when no RMC entry is loaded */ -+ if (rmc_entry == FALSE) -+ config_load_entries(&config, loaded_image->DeviceHandle, root_dir, loaded_image_path); - - /* sort entries after version number */ - config_sort_entries(&config); -@@ -1851,6 +1992,8 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { - out: - FreePool(loaded_image_path); - config_free(&config); -+ FreePool(rmc_db); -+ FreePool(rmc_fp); - uefi_call_wrapper(root_dir->Close, 1, root_dir); - uefi_call_wrapper(BS->CloseProtocol, 4, image, &LoadedImageProtocol, image, NULL); - return err; --- -2.7.4 - diff --git a/recipes-bsp/systemd-boot/systemd-boot/0002-sd-boot-fix-RMC-compatibility-with-systemd-boot-and-.patch b/recipes-bsp/systemd-boot/systemd-boot/0002-sd-boot-fix-RMC-compatibility-with-systemd-boot-and-.patch new file mode 100644 index 00000000..a3e496f5 --- /dev/null +++ b/recipes-bsp/systemd-boot/systemd-boot/0002-sd-boot-fix-RMC-compatibility-with-systemd-boot-and-.patch @@ -0,0 +1,62 @@ +From af977853ab722194c4754e6693f430f50a42190f Mon Sep 17 00:00:00 2001 +From: California Sullivan +Date: Tue, 20 Mar 2018 10:08:14 -0700 +Subject: [PATCH 2/5] sd-boot: fix RMC compatibility with systemd-boot and + meson + +With autotools swapped out for meson a number of things need to be +changed. + +Upstream-Status: Pending + +Signed-off-by: California Sullivan +--- + meson_options.txt | 2 ++ + src/boot/efi/meson.build | 4 +++- + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/meson_options.txt b/meson_options.txt +index 39822d6cd..d8a480401 100644 +--- a/meson_options.txt ++++ b/meson_options.txt +@@ -279,6 +279,8 @@ option('efi-ldsdir', type : 'string', + description : 'path to the EFI lds directory') + option('efi-includedir', type : 'string', value : '/usr/include/efi', + description : 'path to the EFI header directory') ++option('rmc-includedir', type : 'string', value : '/usr/include/rmc', ++ description : 'path to the RMC header directory') + option('tpm-pcrindex', type : 'string', value : '8', + description : 'TPM PCR register number to use') + +diff --git a/src/boot/efi/meson.build b/src/boot/efi/meson.build +index 9f9ec4911..266ff928f 100644 +--- a/src/boot/efi/meson.build ++++ b/src/boot/efi/meson.build +@@ -83,6 +83,7 @@ if have_gnu_efi + efi_conf.set_quoted('EFI_MACHINE_TYPE_NAME', EFI_MACHINE_TYPE_NAME) + efi_conf.set10('ENABLE_TPM', get_option('tpm')) + efi_conf.set('SD_TPM_PCR', get_option('tpm-pcrindex')) ++ efi_conf.set('RMC_EFI', 'true') + + efi_config_h = configure_file( + output : 'efi_config.h', +@@ -121,6 +122,7 @@ if have_gnu_efi + '-Wsign-compare', + '-Wno-missing-field-initializers', + '-isystem', efi_incdir, ++ '-isystem', get_option('rmc-includedir'), + '-isystem', join_paths(efi_incdir, gnu_efi_arch), + '-include', efi_config_h] + if efi_arch == 'x86_64' +@@ -191,7 +193,7 @@ if have_gnu_efi + output : tuple[0], + command : efi_ld.split() + ['-o', '@OUTPUT@'] + + efi_ldflags + tuple[2] + +- ['-lefi', '-lgnuefi', libgcc_file_name]) ++ ['-lefi', '-lgnuefi', '-lrmcefi', libgcc_file_name]) + + test('no-undefined-symbols-' + tuple[0], + no_undefined_symbols, +-- +2.14.3 + 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 new file mode 100644 index 00000000..cef934ce --- /dev/null +++ b/recipes-bsp/systemd-boot/systemd-boot/0003-sd-boot-Load-board-specific-boot-entries-from-RMC-da.patch @@ -0,0 +1,252 @@ +From b780c67c780bae2f834d73017044680fabca4268 Mon Sep 17 00:00:00 2001 +From: Jianxun Zhang +Date: Wed, 1 Jun 2016 16:32:22 -0700 +Subject: [PATCH 3/5] sd-boot: Load board-specific boot entries from RMC + database + +RMC provides a centralized database file on ESP. The DB contains +fingerprints and any file blobs associated to physical boards. +Callers can fetch board-specific data with fingerprint info +collected from board at runtime if there is any record matched +board's fingerprint. + +To let bootloader know which file blob in RMC should be queried, +a special config file BOOTENTRY.CONFIG is defined as: + +boot.conf +install.conf + +Bootloader calls RMC APIs and other functions to perform these +tasks before it shows boot menu to user: + +(1) Load RMC database file from ESP +(2) Collect fingerprint data from board +(3) Query BOOTENTRY.CONFIG from RMC DB with fingerprint +(4) Parse BOOTENTRY.CONFIG to know names of boot entry files +(5) Query boot entry files one by one from RMC DB, and add + them into sd-boot config data. + +The final effect is that bootloader will show board-specific +boot entries in boot menu to user. User then can choose one +of them to boot system with the selected configuration. + +If any of these steps fails, bootloader simply skips loading +RMC configs or any entry file not successfully fetched from +RMC DB. Once any entry is loaded successfully from RMC DB, +bootloader skips loading any boot entries from ESP. + +Upstream-Status: Pending + +Signed-off-by: Jianxun Zhang +Signed-off-by: California Sullivan +--- + src/boot/efi/boot.c | 148 +++++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 146 insertions(+), 2 deletions(-) + +diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c +index b9c7c8394..93cfaf193 100644 +--- a/src/boot/efi/boot.c ++++ b/src/boot/efi/boot.c +@@ -16,6 +16,7 @@ + + #include + #include ++#include + + #include "console.h" + #include "disk.h" +@@ -35,6 +36,9 @@ static const char __attribute__((used)) magic[] = "#### LoaderInfo: systemd-boot + + static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE; + ++static CHAR8* rmc_db; ++static rmc_fingerprint_t *rmc_fp; ++ + enum loader_type { + LOADER_UNDEFINED, + LOADER_EFI, +@@ -1684,6 +1688,136 @@ static VOID config_free(Config *config) { + FreePool(config->entry_oneshot); + } + ++/* Derived from line_get_key_value(), we could consolidate two functions later */ ++static CHAR8 *get_line(CHAR8 *content, UINT64 *pos) { ++ CHAR8 *line; ++ UINT64 linelen; ++ ++skip: ++ line = content + *pos; ++ if (*line == '\0') ++ return NULL; ++ ++ linelen = 0; ++ while (line[linelen] && !strchra((CHAR8 *)"\n\r", line[linelen])) ++ linelen++; ++ ++ /* move pos to next line */ ++ *pos += linelen; ++ if (content[*pos]) ++ (*pos)++; ++ ++ /* empty line */ ++ if (linelen == 0) ++ goto skip; ++ ++ /* terminate line */ ++ line[linelen] = '\0'; ++ ++ /* remove leading whitespace */ ++ while (strchra((CHAR8 *)" \t", *line)) { ++ line++; ++ linelen--; ++ } ++ ++ /* remove trailing whitespace */ ++ while (linelen > 0 && strchra((CHAR8 *)" \t", line[linelen-1])) ++ linelen--; ++ line[linelen] = '\0'; ++ ++ if (*line == '#') ++ goto skip; ++ ++ return line; ++} ++ ++/* load rmc database file from ESP and try to get fingerprint. These ++ * are essential information indicating we could query rmc data for ++ * this board at least ++ * return 0 if both database file and fingerprint can be obtained, otherwise ++ * non-zero value is returned. ++ * ++ * Note: db and fp hold valid values only when this function returns 0. ++ * Caller is responsible to free allocated memory pointed by *db and *fp when ++ * this function returns 0. ++ */ ++ ++static UINTN rmc_initialize(EFI_FILE *root_dir, EFI_SYSTEM_TABLE *sys_table, CHAR8 **db, rmc_fingerprint_t **fp) { ++ UINTN len; ++ UINTN ret = 1; ++ ++ if (!db || !fp) ++ return ret; ++ ++ *db = NULL; ++ *fp = NULL; ++ ++ /* load rmc database */ ++ len = file_read(root_dir, L"\\rmc.db", 0, 0, db); ++ ++ if (len <= 0) ++ goto done; ++ ++ *fp = AllocateZeroPool(sizeof(rmc_fingerprint_t)); ++ /* call rmc to get fingerprint. We will use single-action rmc APIs to query multiple files. ++ * This should bring a better performance than calling double-action rmc API every time. ++ */ ++ if (rmc_get_fingerprint(sys_table, *fp)) ++ goto done; ++ ++ ret = 0; ++done: ++ if (ret) { ++ FreePool(*db); ++ FreePool(*fp); ++ } ++ ++ return ret; ++} ++ ++/* load RMC entries ++ * return TRUE when at least one entry is loaded, otherwise, return FALSE ++ */ ++static BOOLEAN config_load_rmc_entries(Config *config, EFI_HANDLE *device, CHAR16 *loaded_image_path, CHAR8 *db, rmc_fingerprint_t *fp) { ++ CHAR8 *boot_entry = NULL; ++ CHAR8 *boot_config = NULL; ++ rmc_file_t rp; ++ CHAR8 *line; ++ UINT64 pos = 0; ++ BOOLEAN ret = FALSE; ++ ++ if (!db || !fp) ++ return ret; ++ ++ /* query boot entry config file */ ++ if (rmc_query_file_by_fp(fp, db, "BOOTENTRY.CONFIG", &rp)) ++ return ret; ++ ++ /* file blob read from rmc db is not necessarily null-terminated, and we ++ * should keep mem where rmc db lives from change during parsing ++ */ ++ boot_config = AllocatePool(rp.blob_len * sizeof(CHAR8) + 1); ++ CopyMem(boot_config, rp.blob, rp.blob_len); ++ boot_config[rp.blob_len] = '\0'; ++ /* parse boot entry config */ ++ while ((line = get_line(boot_config, &pos))) { ++ if (rmc_query_file_by_fp(fp, db, (char *)line, &rp)) ++ continue; ++ if (rp.blob_len > 0) { ++ boot_entry = AllocatePool(rp.blob_len * sizeof(CHAR8) + 1); ++ CopyMem(boot_entry, rp.blob, rp.blob_len); ++ boot_entry[rp.blob_len] = '\0'; ++ config_entry_add_from_file(config, device, ++ stra_to_str(line), boot_entry, ++ loaded_image_path); ++ /* tell caller success when a RMC entry is loaded */ ++ ret = TRUE; ++ } ++ } ++ ++ return ret; ++} ++ + EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { + CHAR16 *s; + CHAR8 *b; +@@ -1696,6 +1830,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { + UINT64 init_usec; + BOOLEAN menu = FALSE; + CHAR16 uuid[37]; ++ BOOLEAN rmc_entry = FALSE; + + InitializeLib(image, sys_table); + init_usec = time_usec(); +@@ -1736,6 +1871,9 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { + } + } + ++ /* Initialize rmc before loading any config */ ++ rmc_initialize(root_dir, sys_table, &rmc_db, &rmc_fp); ++ + /* the filesystem path to this image, to prevent adding ourselves to the menu */ + loaded_image_path = DevicePathToStr(loaded_image->FilePath); + efivar_set(L"LoaderImageIdentifier", loaded_image_path, FALSE); +@@ -1743,11 +1881,15 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { + ZeroMem(&config, sizeof(Config)); + config_load_defaults(&config, root_dir); + ++ if (rmc_db && rmc_fp) ++ rmc_entry = config_load_rmc_entries(&config, loaded_image->DeviceHandle, loaded_image_path, rmc_db, rmc_fp); ++ + /* scan /EFI/Linux/ directory */ + config_entry_add_linux(&config, loaded_image, root_dir); + +- /* scan /loader/entries/\*.conf files */ +- config_load_entries(&config, loaded_image->DeviceHandle, root_dir, loaded_image_path); ++ /* scan /loader/entries/\*.conf files only when no RMC entry is loaded */ ++ if (rmc_entry == FALSE) ++ config_load_entries(&config, loaded_image->DeviceHandle, root_dir, loaded_image_path); + + /* sort entries after version number */ + config_sort_entries(&config); +@@ -1841,6 +1983,8 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { + out: + FreePool(loaded_image_path); + config_free(&config); ++ FreePool(rmc_db); ++ FreePool(rmc_fp); + uefi_call_wrapper(root_dir->Close, 1, root_dir); + uefi_call_wrapper(BS->CloseProtocol, 4, image, &LoadedImageProtocol, image, NULL); + return err; +-- +2.14.3 + diff --git a/recipes-bsp/systemd-boot/systemd-boot/0003-sd-boot-Support-global-kernel-command-line-fragment.patch b/recipes-bsp/systemd-boot/systemd-boot/0003-sd-boot-Support-global-kernel-command-line-fragment.patch deleted file mode 100644 index a4b63557..00000000 --- a/recipes-bsp/systemd-boot/systemd-boot/0003-sd-boot-Support-global-kernel-command-line-fragment.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 1e33f99e13a70c19c1f63f6ef1c5522a09adece6 Mon Sep 17 00:00:00 2001 -From: Jianxun Zhang -Date: Mon, 20 Jun 2016 13:08:20 -0700 -Subject: [PATCH 3/3] sd-boot: Support global kernel command line fragment - -Query file blob KBOOTPARAM from RMC. If it exists, we append -it to the new linux boot entry's cmdline. A boot entry could -be read from a .conf file on ESP, RMC database, or embedded -linux image. content in KBOOTPARAM is effective in all of -these cases. - -Upstream-Status: Pending - -Signed-off-by: Jianxun Zhang ---- - src/boot/efi/boot.c | 34 ++++++++++++++++++++++++++++++++++ - 1 file changed, 34 insertions(+) - -diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c -index d1b029b..8dffc48 100644 ---- a/src/boot/efi/boot.c -+++ b/src/boot/efi/boot.c -@@ -846,6 +846,40 @@ static VOID config_add_entry(Config *config, ConfigEntry *entry) { - config->entries = ReallocatePool(config->entries, - sizeof(VOID *) * config->entry_count, sizeof(VOID *) * i); - } -+ -+ /* rmc: a linux entry could be added from .conf file or an embedded linux image -+ * we put appending global command line here to cover both of two cases. -+ */ -+ if (entry->type == LOADER_LINUX && rmc_db && rmc_fp) { -+ rmc_file_t rmc_kp; -+ -+ if (!rmc_query_file_by_fp(rmc_fp, rmc_db, "KBOOTPARAM", &rmc_kp)) { -+ CHAR8 *cmdline; -+ CHAR16 *s; -+ CHAR16 *t; -+ CHAR16 *p; -+ -+ cmdline = AllocatePool(rmc_kp.blob_len * sizeof(CHAR8) + 1); -+ CopyMem(cmdline, rmc_kp.blob, rmc_kp.blob_len); -+ cmdline[rmc_kp.blob_len] = '\0'; -+ p = stra_to_str(cmdline); -+ t = p; -+ -+ while (*t) { -+ if (*t == '\n') -+ *t = '\0'; -+ t++; -+ } -+ -+ s = PoolPrint(L"%s %s", entry->options, p); -+ FreePool(entry->options); -+ FreePool(p); -+ FreePool(cmdline); -+ -+ entry->options = s; -+ } -+ } -+ - config->entries[config->entry_count++] = entry; - } - --- -2.7.4 - diff --git a/recipes-bsp/systemd-boot/systemd-boot/0004-sd-boot-Support-global-kernel-command-line-fragment-in-EFI-stub.patch b/recipes-bsp/systemd-boot/systemd-boot/0004-sd-boot-Support-global-kernel-command-line-fragment-in-EFI-stub.patch deleted file mode 100644 index 75082693..00000000 --- a/recipes-bsp/systemd-boot/systemd-boot/0004-sd-boot-Support-global-kernel-command-line-fragment-in-EFI-stub.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 4cb9c65ea9c0eba3ba04d036dccd4a5ab3d2547b Mon Sep 17 00:00:00 2001 -From: Mikko Ylinen -Date: Fri, 27 Jan 2017 13:31:45 +0200 -Subject: [PATCH] sd-boot: support global kernel command line in EFI stub - -This change integrates rmc into EFI stub and supports a -global fragment (RMC KBOOTPARAM) that is appended to the -cmdline at boot. - -The fragment is board-specific and read from the database. - -Implements [YOCTO #10924]. - -Upstream-status: Pending - -Signed-off-by: Mikko Ylinen ---- - src/boot/efi/stub.c | 33 +++++++++++++++++++++++++++++++++ - 1 file changed, 33 insertions(+) - -diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c -index 1e250f34f..f3865199f 100644 ---- a/src/boot/efi/stub.c -+++ b/src/boot/efi/stub.c -@@ -13,6 +13,7 @@ - - #include - #include -+#include - - #include "disk.h" - #include "graphics.h" -@@ -48,6 +49,9 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { - UINTN cmdline_len; - CHAR16 uuid[37]; - EFI_STATUS err; -+ INTN len; -+ CHAR8 *rmc_db = NULL; -+ rmc_file_t rmc_file; - - InitializeLib(image, sys_table); - -@@ -112,6 +116,35 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { - #endif - } - -+ len = file_read(root_dir, L"\\rmc.db", 0, 0, &rmc_db); -+ if (len <= 0) -+ rmc_db = NULL; -+ -+ /* If the board has a fragment in rmc database, append it to the cmdline */ -+ if (rmc_db && !rmc_gimme_file(sys_table, rmc_db, "KBOOTPARAM", &rmc_file)) { -+ CHAR8 *line; -+ UINTN i = 0; -+ UINTN j; -+ -+ line = AllocatePool(rmc_file.blob_len + cmdline_len + 2); -+ -+ while (i < cmdline_len && cmdline[i] != '\0') { -+ line[i] = cmdline[i]; -+ i++; -+ } -+ -+ line[i++] = ' '; -+ -+ for (j=0; j < rmc_file.blob_len; j++) -+ line[i+j] = rmc_file.blob[j]; -+ line[i+j] = '\0'; -+ -+ cmdline = line; -+ cmdline_len = i + j; -+ -+ FreePool(rmc_db); -+ } -+ - /* export the device path this image is started from */ - if (disk_get_part_uuid(loaded_image->DeviceHandle, uuid) == EFI_SUCCESS) - efivar_set(L"LoaderDevicePartUUID", uuid, FALSE); --- -2.11.0 - diff --git a/recipes-bsp/systemd-boot/systemd-boot/0004-sd-boot-Support-global-kernel-command-line-fragment.patch b/recipes-bsp/systemd-boot/systemd-boot/0004-sd-boot-Support-global-kernel-command-line-fragment.patch new file mode 100644 index 00000000..b4dd9c42 --- /dev/null +++ b/recipes-bsp/systemd-boot/systemd-boot/0004-sd-boot-Support-global-kernel-command-line-fragment.patch @@ -0,0 +1,67 @@ +From 159c8c54f92fb44d8abd2919fa83ad1cb640fac3 Mon Sep 17 00:00:00 2001 +From: Jianxun Zhang +Date: Mon, 20 Jun 2016 13:08:20 -0700 +Subject: [PATCH 4/5] sd-boot: Support global kernel command line fragment + +Query file blob KBOOTPARAM from RMC. If it exists, we append +it to the new linux boot entry's cmdline. A boot entry could +be read from a .conf file on ESP, RMC database, or embedded +linux image. content in KBOOTPARAM is effective in all of +these cases. + +Upstream-Status: Pending + +Signed-off-by: Jianxun Zhang +Signed-off-by: California Sullivan +--- + src/boot/efi/boot.c | 34 ++++++++++++++++++++++++++++++++++ + 1 file changed, 34 insertions(+) + +diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c +index 93cfaf193..2f400db3c 100644 +--- a/src/boot/efi/boot.c ++++ b/src/boot/efi/boot.c +@@ -851,6 +851,40 @@ static VOID config_add_entry(Config *config, ConfigEntry *entry) { + config->entries = ReallocatePool(config->entries, + sizeof(VOID *) * config->entry_count, sizeof(VOID *) * i); + } ++ ++ /* rmc: a linux entry could be added from .conf file or an embedded linux image ++ * we put appending global command line here to cover both of two cases. ++ */ ++ if (entry->type == LOADER_LINUX && rmc_db && rmc_fp) { ++ rmc_file_t rmc_kp; ++ ++ if (!rmc_query_file_by_fp(rmc_fp, rmc_db, "KBOOTPARAM", &rmc_kp)) { ++ CHAR8 *cmdline; ++ CHAR16 *s; ++ CHAR16 *t; ++ CHAR16 *p; ++ ++ cmdline = AllocatePool(rmc_kp.blob_len * sizeof(CHAR8) + 1); ++ CopyMem(cmdline, rmc_kp.blob, rmc_kp.blob_len); ++ cmdline[rmc_kp.blob_len] = '\0'; ++ p = stra_to_str(cmdline); ++ t = p; ++ ++ while (*t) { ++ if (*t == '\n') ++ *t = '\0'; ++ t++; ++ } ++ ++ s = PoolPrint(L"%s %s", entry->options, p); ++ FreePool(entry->options); ++ FreePool(p); ++ FreePool(cmdline); ++ ++ entry->options = s; ++ } ++ } ++ + config->entries[config->entry_count++] = entry; + } + +-- +2.14.3 + diff --git a/recipes-bsp/systemd-boot/systemd-boot/0005-sd-boot-support-global-kernel-command-line-in-EFI-st.patch b/recipes-bsp/systemd-boot/systemd-boot/0005-sd-boot-support-global-kernel-command-line-in-EFI-st.patch new file mode 100644 index 00000000..60e93ca8 --- /dev/null +++ b/recipes-bsp/systemd-boot/systemd-boot/0005-sd-boot-support-global-kernel-command-line-in-EFI-st.patch @@ -0,0 +1,82 @@ +From 405a77233dde990fa7815d1546dc5a6b5a608479 Mon Sep 17 00:00:00 2001 +From: Mikko Ylinen +Date: Fri, 27 Jan 2017 13:31:45 +0200 +Subject: [PATCH 5/5] sd-boot: support global kernel command line in EFI stub + +This change integrates rmc into EFI stub and supports a +global fragment (RMC KBOOTPARAM) that is appended to the +cmdline at boot. + +The fragment is board-specific and read from the database. + +Implements [YOCTO #10924]. + +Upstream-status: Pending + +Signed-off-by: Mikko Ylinen +Signed-off-by: California Sullivan +--- + src/boot/efi/stub.c | 33 +++++++++++++++++++++++++++++++++ + 1 file changed, 33 insertions(+) + +diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c +index 540ca5985..11047477b 100644 +--- a/src/boot/efi/stub.c ++++ b/src/boot/efi/stub.c +@@ -14,6 +14,7 @@ + + #include + #include ++#include + + #include "disk.h" + #include "graphics.h" +@@ -49,6 +50,9 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { + UINTN cmdline_len; + CHAR16 uuid[37]; + EFI_STATUS err; ++ INTN len; ++ CHAR8 *rmc_db = NULL; ++ rmc_file_t rmc_file; + + InitializeLib(image, sys_table); + +@@ -109,6 +113,35 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { + #endif + } + ++ len = file_read(root_dir, L"\\rmc.db", 0, 0, &rmc_db); ++ if (len <= 0) ++ rmc_db = NULL; ++ ++ /* If the board has a fragment in rmc database, append it to the cmdline */ ++ if (rmc_db && !rmc_gimme_file(sys_table, rmc_db, "KBOOTPARAM", &rmc_file)) { ++ CHAR8 *line; ++ UINTN i = 0; ++ UINTN j; ++ ++ line = AllocatePool(rmc_file.blob_len + cmdline_len + 2); ++ ++ while (i < cmdline_len && cmdline[i] != '\0') { ++ line[i] = cmdline[i]; ++ i++; ++ } ++ ++ line[i++] = ' '; ++ ++ for (j=0; j < rmc_file.blob_len; j++) ++ line[i+j] = rmc_file.blob[j]; ++ line[i+j] = '\0'; ++ ++ cmdline = line; ++ cmdline_len = i + j; ++ ++ FreePool(rmc_db); ++ } ++ + /* export the device path this image is started from */ + if (disk_get_part_uuid(loaded_image->DeviceHandle, uuid) == EFI_SUCCESS) + efivar_set(L"LoaderDevicePartUUID", uuid, FALSE); +-- +2.14.3 + diff --git a/recipes-bsp/systemd-boot/systemd-boot/rmc-boot.inc b/recipes-bsp/systemd-boot/systemd-boot/rmc-boot.inc index 11fddaf9..e27d4951 100644 --- a/recipes-bsp/systemd-boot/systemd-boot/rmc-boot.inc +++ b/recipes-bsp/systemd-boot/systemd-boot/rmc-boot.inc @@ -1,21 +1,15 @@ -# Pin systemd revision down for systemd-boot recipe. -# Patches could not be applied cleanly when systemd in OE is updated, -# though we don't expect a lot of changes could happen in bootloader. -# RMC is designed to support a large number of types of boards, so we -# should do explicit update with validation to prevent regression even -# resolving conflicts for a new tip could be done in a short time. - -# Revision: systemd v232 in OE -SRCREV_intel-x86-common = "a1e2ef7ec912902d8142e7cb5830cbfb47dba86c" +# This patchset contains hooks that allows systemd-boot to use RMC capablilities. DEPENDS_append_intel-x86-common = " rmc rmc-efi" -EXTRA_OEMAKE_append_intel-x86-common = ' EFI_LDFLAGS="-L${STAGING_DIR_HOST}/usr/lib" EFI_CFLAGS="-I${STAGING_INCDIR}/rmc -DRMC_EFI"' +EXTRA_OEMESON_append_intel-x86-common = ' \ + -Drmc-includedir="${STAGING_INCDIR}/rmc" \ + ' SRC_URI_append_intel-x86-common = " \ - file://0001-sd-boot-Link-RMC-library-into-bootloader-and-stub.patch \ - file://0002-sd-boot-Load-board-specific-boot-entries-from-RMC-da.patch \ - file://0003-sd-boot-Support-global-kernel-command-line-fragment.patch \ - file://0004-sd-boot-Support-global-kernel-command-line-fragment-in-EFI-stub.patch \ - file://0001-sd-boot-stub-check-LoadOptions-contains-data.patch \ + file://0001-partially-revert-sd-boot-stub-Obtain-PE-section-offs.patch \ + file://0002-sd-boot-fix-RMC-compatibility-with-systemd-boot-and-.patch \ + file://0003-sd-boot-Load-board-specific-boot-entries-from-RMC-da.patch \ + file://0004-sd-boot-Support-global-kernel-command-line-fragment.patch \ + file://0005-sd-boot-support-global-kernel-command-line-in-EFI-st.patch \ " -- cgit v1.2.3-54-g00ecf