diff --git a/0001-openfw-Ensure-get_devargs-and-get_devname-functions-.patch b/0001-openfw-Ensure-get_devargs-and-get_devname-functions-.patch new file mode 100644 index 0000000..f7f01c0 --- /dev/null +++ b/0001-openfw-Ensure-get_devargs-and-get_devname-functions-.patch @@ -0,0 +1,52 @@ +From 468628bdc39800341e7aa6ff7795cc0d93cfaf3f Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Tue, 11 Apr 2023 10:59:34 +0800 +Subject: [PATCH 1/2] openfw: Ensure get_devargs and get_devname functions are + consistent + +Commit 165c9b234 changed the logic of ieee1275_get_devargs() to use the +first or second occurrence of a colon as a separator between device name +and arguments. However, this didn't align with the complementary +function ieee1275_get_devname, which uses the first occurrence of a +colon after the namespace keyword as arguments for the nvme-of device. + +This commit addresses the inconsistency by ensuring that both functions +follow a common logic. Now, get_devargs and get_devname functions are +consistent with each other, making it easier to understand and maintain +the codebase. + +Signed-off-by: Michael Chang +--- + grub-core/kern/ieee1275/openfw.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c +index e2ffec32d..3bbd07d95 100644 +--- a/grub-core/kern/ieee1275/openfw.c ++++ b/grub-core/kern/ieee1275/openfw.c +@@ -354,13 +354,16 @@ static char * + grub_ieee1275_get_devargs (const char *path) + { + char *colon = grub_strchr (path, ':'); +- char *colon_check = colon; + +- /* Find the last occurence of colon */ +- while(colon_check){ +- colon = colon_check; +- colon_check = grub_strchr (colon+1, ':'); +- } ++ /* Use the same logic in grub_ieee1275_get_devname for nvme-of arguments */ ++ if (grub_strstr(path, "nvme-of")) ++ { ++ char *namespace_split = grub_strstr(path,"/namespace@"); ++ if (namespace_split) ++ colon = grub_strchr (namespace_split, ':'); ++ else ++ colon = NULL; ++ } + + if (! colon) + return 0; +-- +2.39.2 + diff --git a/0002-prep_loadenv-Fix-regex-for-Open-Firmware-device-spec.patch b/0002-prep_loadenv-Fix-regex-for-Open-Firmware-device-spec.patch new file mode 100644 index 0000000..387b3de --- /dev/null +++ b/0002-prep_loadenv-Fix-regex-for-Open-Firmware-device-spec.patch @@ -0,0 +1,204 @@ +From 990902e28c390217d25ea474e5ef163d79eadc7f Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Fri, 31 Mar 2023 15:19:58 +0800 +Subject: [PATCH 2/2] prep_loadenv: Fix regex for Open Firmware device + specifier with encoded commas + +The Open Firmware device specifier allows for comma-separated properties +of a component, but this conflicts with the way that grub separates +device and partition in its device specifier. To address this, grub +encodes commas in Open Firmware device strings with a leading backslash +as an established convention. + +However, the regular expression used to extract the boot device +substring from the $cmdpath environment variable did not properly retain +commas with leading backslashes as part of the device. This could cause +the comma to be incorrectly interpreted as a partition delimiter and +result in a broken name for the boot disk. + +To fix this issue, we have updated the regular expression to properly +handle the encoded comma in the Open Firmware device specifier, ensuring +that the correct boot device is identified and used. + +Signed-off-by: Michael Chang +--- + grub-core/commands/prep_loadenv.c | 108 ++++++++++++++++++++++-------- + 1 file changed, 79 insertions(+), 29 deletions(-) + +diff --git a/grub-core/commands/prep_loadenv.c b/grub-core/commands/prep_loadenv.c +index de1b95689..c9797c50a 100644 +--- a/grub-core/commands/prep_loadenv.c ++++ b/grub-core/commands/prep_loadenv.c +@@ -15,7 +15,7 @@ + GRUB_MOD_LICENSE ("GPLv3+"); + + static char * +-match_substr (regmatch_t *match, const char *str) ++match_substr (const regmatch_t *match, const char *str) + { + if (match->rm_so != -1) + { +@@ -185,24 +185,18 @@ prep_partname (const char *devname, char **prep) + return err; + } + +-static grub_err_t +-boot_disk_prep_partname (char **name) ++static regmatch_t * ++regex_match_str (const char *pattern, const char *str, grub_size_t *nmatch) + { + regex_t regex; + int ret; + grub_size_t s; + char *comperr; +- const char *cmdpath; + regmatch_t *matches = NULL; + grub_err_t err = GRUB_ERR_NONE; + +- *name = NULL; +- +- cmdpath = grub_env_get ("cmdpath"); +- if (!cmdpath) +- return GRUB_ERR_NONE; +- +- ret = regcomp (®ex, "\\(([^,]+)(,?.*)?\\)(.*)", REG_EXTENDED); ++ *nmatch = 0; ++ ret = regcomp (®ex, pattern, REG_EXTENDED); + if (ret) + goto fail; + +@@ -210,22 +204,11 @@ boot_disk_prep_partname (char **name) + if (! matches) + goto fail; + +- ret = regexec (®ex, cmdpath, regex.re_nsub + 1, matches, 0); +- if (!ret) ++ ret = regexec (®ex, str, regex.re_nsub + 1, matches, 0); ++ if (ret == 0) + { +- char *devname = devname = match_substr (matches + 1, cmdpath); +- if (!devname) +- { +- err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "%s contains no disk name", cmdpath); +- goto out; +- } +- +- err = prep_partname (devname, name); +- out: +- grub_free (devname); +- regfree (®ex); +- grub_free (matches); +- return err; ++ *nmatch = regex.re_nsub + 1; ++ return matches; + } + + fail: +@@ -235,13 +218,58 @@ boot_disk_prep_partname (char **name) + if (!comperr) + { + regfree (®ex); +- return grub_errno; ++ return NULL; + } + regerror (ret, ®ex, comperr, s); + err = grub_error (GRUB_ERR_TEST_FAILURE, "%s", comperr); + regfree (®ex); + grub_free (comperr); +- return err; ++ return NULL; ++} ++ ++static grub_err_t ++boot_disk_prep_partname (const char *varname, char **name) ++{ ++ const char *cmdpath; ++ regmatch_t *matches; ++ grub_size_t nmatch; ++ char *devname = NULL; ++ ++ if (varname) ++ cmdpath = grub_env_get (varname); ++ else ++ cmdpath = grub_env_get ("cmdpath"); ++ if (!cmdpath) ++ return GRUB_ERR_NONE; ++ ++ matches = regex_match_str("\\((.*)\\)(.*)", cmdpath, &nmatch); ++ if (matches && nmatch >= 2) ++ devname = match_substr (matches + 1, cmdpath); ++ if (devname == NULL) ++ goto quit; ++ grub_free (matches); ++ ++ matches = regex_match_str ("(.*[^\\])(,.*)", devname, &nmatch); ++ if (matches && nmatch >= 2) ++ { ++ char *n = match_substr (matches + 1, devname); ++ grub_free (devname); ++ devname = n; ++ } ++ else ++ grub_errno = GRUB_ERR_NONE; ++ if (devname) ++ { ++ grub_printf ("search prep from disk `%s'\n", devname); ++ prep_partname (devname, name); ++ } ++ ++ quit: ++ grub_free (devname); ++ grub_free (matches); ++ if (grub_errno) ++ grub_print_error (); ++ return GRUB_ERR_NONE; + } + + static grub_err_t +@@ -274,13 +302,31 @@ grub_cmd_prep_loadenv (grub_command_t cmd __attribute__ ((unused)), + return GRUB_ERR_NONE; + } + ++static grub_err_t ++grub_cmd_prep_partname (grub_command_t cmd __attribute__ ((unused)), ++ int argc, ++ char **argv) ++{ ++ char *prep = NULL; ++ const char *varname = NULL; ++ ++ if (argc > 0) ++ varname = argv[0]; ++ ++ boot_disk_prep_partname(varname, &prep); ++ if (prep) ++ grub_printf ("prep: %s\n", prep); ++ ++ return GRUB_ERR_NONE; ++} ++ + static void + early_prep_loadenv (void) + { + grub_err_t err; + char *prep; + +- err = boot_disk_prep_partname (&prep); ++ err = boot_disk_prep_partname (NULL, &prep); + if (err == GRUB_ERR_NONE && prep) + err = prep_read_envblk (prep); + if (err == GRUB_ERR_BAD_FILE_TYPE || err == GRUB_ERR_FILE_NOT_FOUND) +@@ -295,6 +341,10 @@ static grub_command_t cmd_prep_load; + GRUB_MOD_INIT(prep_loadenv) + { + early_env_hook = early_prep_loadenv; ++ cmd_prep_load = ++ grub_register_command("prep_partname", grub_cmd_prep_partname, ++ "VARNAME", ++ N_("Get partition name of PReP.")); + cmd_prep_load = + grub_register_command("prep_load_env", grub_cmd_prep_loadenv, + "DEVICE", +-- +2.39.2 + diff --git a/0004-Introduce-prep_load_env-command.patch b/0004-Introduce-prep_load_env-command.patch index ac6c87f..a245395 100644 --- a/0004-Introduce-prep_load_env-command.patch +++ b/0004-Introduce-prep_load_env-command.patch @@ -11,6 +11,10 @@ exported to grub as environment variables. Please note there's no support for whitelist variables and also --skip-sig option compared to ordinary load_env command. +v2: +To avoid disrupting the boot process with errors, it's important to log +any errors that may occur and always return GRUB_ERR_NONE. + Signed-off-by: Michael Chang --- grub-core/Makefile.core.def | 5 + @@ -18,11 +22,9 @@ Signed-off-by: Michael Chang 2 files changed, 232 insertions(+) create mode 100644 grub-core/commands/prep_loadenv.c -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index 49bdb63b69..4d529859be 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def -@@ -2624,3 +2624,8 @@ module = { +@@ -2624,3 +2624,8 @@ common = lib/libtasn1_wrap/tests/Test_strings.c; common = lib/libtasn1_wrap/wrap_tests.c; }; @@ -31,12 +33,9 @@ index 49bdb63b69..4d529859be 100644 + name = prep_loadenv; + common = commands/prep_loadenv.c; +}; -diff --git a/grub-core/commands/prep_loadenv.c b/grub-core/commands/prep_loadenv.c -new file mode 100644 -index 0000000000..f4bb270a2b --- /dev/null +++ b/grub-core/commands/prep_loadenv.c -@@ -0,0 +1,227 @@ +@@ -0,0 +1,230 @@ +#include +#include +#include @@ -247,7 +246,10 @@ index 0000000000..f4bb270a2b + out: + grub_free (devname); + grub_free (prep); -+ return err; ++ ++ if (err) ++ grub_print_error (); ++ return GRUB_ERR_NONE; +} + +static grub_command_t cmd_prep_load; @@ -264,6 +266,3 @@ index 0000000000..f4bb270a2b +{ + grub_unregister_command (cmd_prep_load); +} --- -2.34.1 - diff --git a/0005-export-environment-at-start-up.patch b/0005-export-environment-at-start-up.patch index 767a429..ae1124c 100644 --- a/0005-export-environment-at-start-up.patch +++ b/0005-export-environment-at-start-up.patch @@ -17,19 +17,15 @@ Signed-off-by: Michael Chang include/grub/env.h | 1 + 5 files changed, 85 insertions(+) -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index 4d529859be..f3140815b8 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def -@@ -2628,4 +2628,6 @@ module = { +@@ -2617,4 +2617,6 @@ module = { name = prep_loadenv; common = commands/prep_loadenv.c; + cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)'; + cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB)'; }; -diff --git a/grub-core/commands/prep_loadenv.c b/grub-core/commands/prep_loadenv.c -index f4bb270a2b..4f40f7e41a 100644 --- a/grub-core/commands/prep_loadenv.c +++ b/grub-core/commands/prep_loadenv.c @@ -10,6 +10,7 @@ @@ -40,11 +36,10 @@ index f4bb270a2b..4f40f7e41a 100644 GRUB_MOD_LICENSE ("GPLv3+"); -@@ -184,6 +185,65 @@ prep_partname (const char *devname, char **prep) - return err; +@@ -185,6 +186,65 @@ } -+static grub_err_t + static grub_err_t +boot_disk_prep_partname (char **name) +{ + regex_t regex; @@ -103,11 +98,12 @@ index f4bb270a2b..4f40f7e41a 100644 + return err; +} + - static grub_err_t ++static grub_err_t grub_cmd_prep_loadenv (grub_command_t cmd __attribute__ ((unused)), int argc, -@@ -211,10 +271,27 @@ grub_cmd_prep_loadenv (grub_command_t cmd __attribute__ ((unused)), - return err; + char **argv) +@@ -214,10 +274,27 @@ + return GRUB_ERR_NONE; } +static void @@ -134,11 +130,9 @@ index f4bb270a2b..4f40f7e41a 100644 cmd_prep_load = grub_register_command("prep_load_env", grub_cmd_prep_loadenv, "DEVICE", -diff --git a/grub-core/kern/env.c b/grub-core/kern/env.c -index c408626423..ec0d268905 100644 --- a/grub-core/kern/env.c +++ b/grub-core/kern/env.c -@@ -28,6 +28,8 @@ static struct grub_env_context initial_context; +@@ -28,6 +28,8 @@ /* The current context. */ struct grub_env_context *grub_current_context = &initial_context; @@ -147,11 +141,9 @@ index c408626423..ec0d268905 100644 /* Return the hash representation of the string S. */ static unsigned int grub_env_hashval (const char *s) -diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c -index c7c6d2d0b8..42ea96e39e 100644 --- a/grub-core/kern/main.c +++ b/grub-core/kern/main.c -@@ -310,6 +310,9 @@ grub_main (void) +@@ -310,6 +310,9 @@ grub_boot_time ("Before execution of embedded config."); @@ -161,17 +153,12 @@ index c7c6d2d0b8..42ea96e39e 100644 if (load_config) grub_parser_execute (load_config); -diff --git a/include/grub/env.h b/include/grub/env.h -index 76f832eb94..636e190a21 100644 --- a/include/grub/env.h +++ b/include/grub/env.h -@@ -68,5 +68,6 @@ grub_env_extractor_open (int source); +@@ -68,5 +68,6 @@ grub_err_t grub_env_extractor_close (int source); +extern void (*EXPORT_VAR (early_env_hook)) (void); #endif /* ! GRUB_ENV_HEADER */ --- -2.34.1 - diff --git a/grub2.changes b/grub2.changes index 01832b0..4564f93 100644 --- a/grub2.changes +++ b/grub2.changes @@ -1,3 +1,20 @@ +------------------------------------------------------------------- +Tue Apr 11 11:13:26 UTC 2023 - Michael Chang + +- Resolve some issues with OS boot failure on PPC NVMe-oF disks and made + enhancements to PPC secure boot's root device discovery config (bsc#1207230) +- Ensure get_devargs and get_devname functions are consistent + * 0001-openfw-Ensure-get_devargs-and-get_devname-functions-.patch +- Fix regex for Open Firmware device specifier with encoded commas + * 0002-prep_loadenv-Fix-regex-for-Open-Firmware-device-spec.patch +- Fix regular expression in PPC secure boot config to prevent escaped commas + from being treated as delimiters when retrieving partition substrings. +- Use prep_load_env in PPC secure boot config to handle unset host-specific + environment variables and ensure successful command execution. + * 0004-Introduce-prep_load_env-command.patch +- Refreshed + * 0005-export-environment-at-start-up.patch + ------------------------------------------------------------------- Thu Mar 23 05:25:50 UTC 2023 - Michael Chang diff --git a/grub2.spec b/grub2.spec index 67d28d0..b78d475 100644 --- a/grub2.spec +++ b/grub2.spec @@ -505,6 +505,8 @@ Patch975: 0002-discard-cached-key-before-entering-grub-shell-and-ed.patch Patch976: 0001-ieee1275-ofdisk-retry-on-open-and-read-failure.patch Patch977: 0001-loader-linux-Ensure-the-newc-pathname-is-NULL-termin.patch Patch978: 0002-Restrict-cryptsetup-key-file-permission-for-better-s.patch +Patch979: 0001-openfw-Ensure-get_devargs-and-get_devname-functions-.patch +Patch980: 0002-prep_loadenv-Fix-regex-for-Open-Firmware-device-spec.patch Requires: gettext-runtime %if 0%{?suse_version} >= 1140 @@ -920,12 +922,22 @@ echo "earlycfg: root=$root prefix=$prefix" EOF cat > ./grub.cfg <<'EOF' -regexp --set 1:bdev --set 2:bpart --set 3:bpath '\(([^,]+)(,?.*)?\)(.*)' "$cmdpath" +regexp --set 1:bdev --set 2:bpath '\((.*)\)(.*)' "$cmdpath" +regexp --set 1:bdev --set 2:bpart '(.*[^\])(,.*)' "$bdev" echo "bdev=$bdev" echo "bpart=$bpart" echo "bpath=$bpath" +if [ -z "$ENV_FS_UUID" ]; then + echo "Reading vars from ($bdev)" + prep_load_env "($bdev)" +fi + +echo "ENV_HINT=$ENV_HINT" +echo "ENV_GRUB_DIR=$ENV_GRUB_DIR" +echo "ENV_FS_UUID=$ENV_FS_UUID" + if [ "$btrfs_relative_path" = xy ]; then btrfs_relative_path=1 fi