On Sat, Apr 12, 2025 at 03:53:10AM +0000, Alec Brown wrote: > Irritatingly, BLS defines paths relatives to the mountpoint of the > filesystem which contains its snippets, not / or any other fixed > location. So grub2-emu needs to know whether /boot is a separate > filesystem from / and conditionally prepend a path. > > Signed-off-by: Robbie Harwood <rharw...@redhat.com> > Signed-off-by: Alec Brown <alec.r.br...@oracle.com> > --- > grub-core/Makefile.core.def | 4 ++ > grub-core/commands/blsuki.c | 92 ++++++++++++++++++++++++++++++--- > grub-core/osdep/linux/getroot.c | 8 +++ > grub-core/osdep/unix/getroot.c | 10 ++++ > include/grub/emu/misc.h | 2 +- > 5 files changed, 107 insertions(+), 9 deletions(-) > > diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def > index f3b776c0a..9a0e7bc55 100644 > --- a/grub-core/Makefile.core.def > +++ b/grub-core/Makefile.core.def > @@ -367,6 +367,10 @@ kernel = { > emu = kern/emu/cache_s.S; > emu = kern/emu/hostdisk.c; > emu = osdep/unix/hostdisk.c; > + emu = osdep/relpath.c; > + emu = osdep/getroot.c; > + emu = osdep/unix/getroot.c; > + emu = osdep/devmapper/getroot.c; > emu = osdep/exec.c; > extra_dist = osdep/unix/exec.c; > emu = osdep/devmapper/hostdisk.c; > diff --git a/grub-core/commands/blsuki.c b/grub-core/commands/blsuki.c > index 0fb4f870a..7b7b3e0e4 100644 > --- a/grub-core/commands/blsuki.c > +++ b/grub-core/commands/blsuki.c > @@ -32,6 +32,13 @@ > #include <grub/lib/envblk.h> > #include <grub/lib/vercmp.h> > > +#ifdef GRUB_MACHINE_EMU > +#include <grub/emu/misc.h> > +#define GRUB_BOOT_DEVICE "/boot" > +#else > +#define GRUB_BOOT_DEVICE "" > +#endif > + > GRUB_MOD_LICENSE ("GPLv3+"); > > #define GRUB_BLS_CONFIG_PATH "/loader/entries/" > @@ -56,6 +63,40 @@ static grub_blsuki_entry_t *entries = NULL; > > #define FOR_BLSUKI_ENTRIES(var) FOR_LIST_ELEMENTS (var, entries) > > +#ifdef GRUB_MACHINE_EMU > +/* > + * Cache probing in blsuki_update_boot_device(). > + */ > +static int separate_boot = -1; > +#endif > + > +/* > + * BLS appears to make paths relative to the filesystem that snippets are > + * on, not /. Attempt to cope. > + */ > +static char *blsuki_update_boot_device (char *tmp) > +{ > +#ifdef GRUB_MACHINE_EMU > + char *ret = NULL;
You do not need this initialization... > + if (separate_boot != -1) > + goto probed; > + > + separate_boot = 0; > + > + ret = grub_make_system_path_relative_to_its_root (GRUB_BOOT_DEVICE); > + > + if (ret != NULL && ret[0] == '\0') > + separate_boot = 1; > + > + probed: > + if (!separate_boot) > + return tmp; > +#endif > + > + return grub_stpcpy (tmp, GRUB_BOOT_DEVICE); > +} > + > static grub_err_t > blsuki_add_keyval (grub_blsuki_entry_t *entry, char *key, char *val) > { > @@ -561,7 +602,7 @@ bls_create_entry (grub_blsuki_entry_t *entry) > goto finish; > } > > - if (grub_add (sizeof ("linux "), grub_strlen (linux_path), &linux_size)) > + if (grub_add (sizeof ("linux " GRUB_BOOT_DEVICE), grub_strlen > (linux_path), &linux_size)) > { > grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected calculating > linux buffer size"); > goto finish; > @@ -572,6 +613,7 @@ bls_create_entry (grub_blsuki_entry_t *entry) > tmp = clinux; > tmp = grub_stpcpy (tmp, "linux"); > tmp = grub_stpcpy (tmp, " "); > + tmp = blsuki_update_boot_device (tmp); > tmp = grub_stpcpy (tmp, linux_path); > > /* Strip the ".conf" off the end before we make it our "id" field. */ > @@ -655,7 +697,7 @@ bls_create_entry (grub_blsuki_entry_t *entry) > > for (i = 0; early_initrds != NULL && early_initrds[i] != NULL; i++) > { > - if (grub_add (initrd_size, sizeof (" "), &initrd_size) || > + if (grub_add (initrd_size, sizeof (" " GRUB_BOOT_DEVICE), > &initrd_size) || > grub_add (initrd_size, grub_strlen (initrd_prefix), &initrd_size) > || > grub_add (initrd_size, grub_strlen (early_initrds[i]), > &initrd_size) || > grub_add (initrd_size, 1, &initrd_size)) > @@ -667,7 +709,7 @@ bls_create_entry (grub_blsuki_entry_t *entry) > > for (i = 0; initrds != NULL && initrds[i] != NULL; i++) > { > - if (grub_add (initrd_size, sizeof (" "), &initrd_size) || > + if (grub_add (initrd_size, sizeof (" " GRUB_BOOT_DEVICE), > &initrd_size) || > grub_add (initrd_size, grub_strlen (initrds[i]), &initrd_size) || > grub_add (initrd_size, 1, &initrd_size)) > { > @@ -691,6 +733,7 @@ bls_create_entry (grub_blsuki_entry_t *entry) > { > grub_dprintf ("blsuki", "adding early initrd %s\n", early_initrds[i]); > tmp = grub_stpcpy (tmp, " "); > + tmp = blsuki_update_boot_device (tmp); > tmp = grub_stpcpy (tmp, initrd_prefix); > tmp = grub_stpcpy (tmp, early_initrds[i]); > grub_free (early_initrds[i]); > @@ -700,6 +743,7 @@ bls_create_entry (grub_blsuki_entry_t *entry) > { > grub_dprintf ("blsuki", "adding initrd %s\n", initrds[i]); > tmp = grub_stpcpy (tmp, " "); > + tmp = blsuki_update_boot_device (tmp); > tmp = grub_stpcpy (tmp, initrds[i]); > } > tmp = grub_stpcpy (tmp, "\n"); > @@ -718,7 +762,7 @@ bls_create_entry (grub_blsuki_entry_t *entry) > } > } > > - if (grub_add (sizeof ("devicetree "), grub_strlen (devicetree), > &dt_size) || > + if (grub_add (sizeof ("devicetree " GRUB_BOOT_DEVICE), grub_strlen > (devicetree), &dt_size) || > grub_add (dt_size, 1, &dt_size)) > { > grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected calculating > device tree buffer size"); > @@ -740,6 +784,7 @@ bls_create_entry (grub_blsuki_entry_t *entry) > tmp = dt; > tmp = grub_stpcpy (dt, "devicetree"); > tmp = grub_stpcpy (tmp, " "); > + tmp = blsuki_update_boot_device (tmp); > if (add_dt_prefix == true) > tmp = grub_stpcpy (tmp, prefix); > tmp = grub_stpcpy (tmp, devicetree); > @@ -836,10 +881,13 @@ blsuki_set_find_entry_info (struct find_entry_info > *info, const char *dirname, c > } > > /* info: the filesystem object the file is on. */ > -static void > +static grub_err_t > blsuki_find_entry (struct find_entry_info *info, bool enable_fallback) > { > struct read_entry_info read_entry_info; > + char *default_dir = NULL; > + char *tmp; > + grub_size_t default_size; > grub_fs_t dir_fs = NULL; > grub_device_t dir_dev = NULL; > int fallback = 0; > @@ -869,12 +917,25 @@ blsuki_find_entry (struct find_entry_info *info, bool > enable_fallback) > */ > if (entries == NULL && fallback == 0 && enable_fallback == true) > { > - blsuki_set_find_entry_info (info, GRUB_BLS_CONFIG_PATH, NULL); > + if (grub_add (grub_strlen (GRUB_BOOT_DEVICE), grub_strlen > (GRUB_BLS_CONFIG_PATH), &default_size)) You do not need overflow checks here... > + return grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected > calculating default directory buffer size"); > + > + default_dir = grub_malloc (default_size); > + if (default_dir == NULL) > + return grub_errno; > + > + tmp = blsuki_update_boot_device (default_dir); > + tmp = grub_stpcpy (tmp, GRUB_BLS_CONFIG_PATH); > + > + blsuki_set_find_entry_info (info, default_dir, NULL); > grub_dprintf ("blsuki", "Entries weren't found in %s, fallback to > %s\n", > read_entry_info.dirname, info->dirname); > fallback = 1; > goto read_fallback; > } > + > + grub_free (default_dir); > + return GRUB_ERR_NONE; > } > > static grub_err_t > @@ -884,6 +945,9 @@ blsuki_load_entries (char *path, bool enable_fallback) > static grub_err_t r; > const char *devid = NULL; > char *dir = NULL; > + char *default_dir = NULL; > + char *tmp; > + grub_size_t dir_size; > struct find_entry_info info = { > .dev = NULL, > .fs = NULL, > @@ -925,15 +989,27 @@ blsuki_load_entries (char *path, bool enable_fallback) > } > > if (dir == NULL) > - dir = (char *) GRUB_BLS_CONFIG_PATH; > + { > + if (grub_add (grub_strlen (GRUB_BOOT_DEVICE), grub_strlen > (GRUB_BLS_CONFIG_PATH), &dir_size)) Ditto... Daniel _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel