On Wed, May 21, 2025 at 12:51:25PM +0000, Alec Brown wrote: > From: Robbie Harwood <rharw...@redhat.com> > > Irritatingly, BLS defines paths relative 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 67628f65f..93b88795e 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 2ad960ae3..bf2edc5ac 100644 > --- a/grub-core/commands/blsuki.c > +++ b/grub-core/commands/blsuki.c > @@ -32,6 +32,13 @@ > #include <grub/vercmp.h> > #include <grub/lib/envblk.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; > + > + 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); > +} > + > /* > * This function will add a new keyval pair to a list of keyvals stored in > the > * entry parameter. > @@ -582,7 +623,7 @@ bls_get_linux (grub_blsuki_entry_t *entry) > if (options == NULL) > options = blsuki_expand_val (grub_env_get ("default_kernelopts")); > > - if (grub_add (grub_strlen ("linux "), grub_strlen (linux_path), &size)) > + if (grub_add (grub_strlen ("linux " GRUB_BOOT_DEVICE), grub_strlen > (linux_path), &size)) > { > grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected while > calculating linux buffer size"); > goto finish; > @@ -604,6 +645,7 @@ bls_get_linux (grub_blsuki_entry_t *entry) > > tmp = linux_cmd; > tmp = grub_stpcpy (tmp, "linux "); > + tmp = blsuki_update_boot_device (tmp); > tmp = grub_stpcpy (tmp, linux_path); > if (options != NULL) > { > @@ -679,7 +721,7 @@ bls_get_initrd (grub_blsuki_entry_t *entry) > > for (i = 0; early_initrd_list != NULL && early_initrd_list[i] != NULL; > i++) > { > - if (grub_add (size, 1, &size) || > + if (grub_add (size, grub_strlen (" " GRUB_BOOT_DEVICE), &size) ||
s/grub_strlen/sizeof (...) - 1/ > grub_add (size, grub_strlen (prefix), &size) || > grub_add (size, grub_strlen (early_initrd_list[i]), &size)) > { > @@ -690,7 +732,7 @@ bls_get_initrd (grub_blsuki_entry_t *entry) > > for (i = 0; initrd_list != NULL && initrd_list[i] != NULL; i++) > { > - if (grub_add (size, 1, &size) || > + if (grub_add (size, grub_strlen (" " GRUB_BOOT_DEVICE), &size) || Ditto. > grub_add (size, grub_strlen (initrd_list[i]), &size)) > { > grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected calculating > initrd buffer size"); > @@ -713,6 +755,7 @@ bls_get_initrd (grub_blsuki_entry_t *entry) > { > grub_dprintf ("blsuki", "adding early initrd %s\n", > early_initrd_list[i]); > tmp = grub_stpcpy (tmp, " "); > + tmp = blsuki_update_boot_device (tmp); > tmp = grub_stpcpy (tmp, prefix); > tmp = grub_stpcpy (tmp, early_initrd_list[i]); > } > @@ -721,6 +764,7 @@ bls_get_initrd (grub_blsuki_entry_t *entry) > { > grub_dprintf ("blsuki", "adding initrd %s\n", initrd_list[i]); > tmp = grub_stpcpy (tmp, " "); > + tmp = blsuki_update_boot_device (tmp); > tmp = grub_stpcpy (tmp, initrd_list[i]); > } > tmp = grub_stpcpy (tmp, "\n"); > @@ -775,7 +819,7 @@ bls_get_devicetree (grub_blsuki_entry_t *entry) > } > } > > - if (grub_add (grub_strlen ("devicetree "), grub_strlen (dt_path), > &size) || > + if (grub_add (grub_strlen ("devicetree " GRUB_BOOT_DEVICE), > grub_strlen (dt_path), &size) || Ditto. > grub_add (size, 1, &size)) > { > grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected calculating > device tree buffer size"); > @@ -796,6 +840,7 @@ bls_get_devicetree (grub_blsuki_entry_t *entry) > tmp = dt_cmd; > tmp = grub_stpcpy (dt_cmd, "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, dt_path); > @@ -924,7 +969,11 @@ blsuki_set_find_entry_info (struct find_entry_info > *info, const char *dirname, c > > if (devid == NULL) > { > +#ifdef GRUB_MACHINE_EMU > + devid = "host"; > +#else > devid = grub_env_get ("root"); > +#endif > if (devid == NULL) > return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't > set"), "root"); > } > @@ -966,10 +1015,13 @@ blsuki_set_find_entry_info (struct find_entry_info > *info, const char *dirname, c > * parameter. If the fallback option is enabled, the default location will be > * checked for BLS config files if the first attempt fails. > */ > -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; > bool fallback = false; > @@ -1000,7 +1052,15 @@ blsuki_find_entry (struct find_entry_info *info, bool > enable_fallback) > */ > if (entries == NULL && fallback == false && enable_fallback == true) > { > - blsuki_set_find_entry_info (info, GRUB_BLS_CONFIG_PATH, NULL); > + default_size = grub_strlen (GRUB_BOOT_DEVICE) + grub_strlen > (GRUB_BLS_CONFIG_PATH); s/grub_strlen/sizeof/ * 2 Do not forget about NUL at the end... > + 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 = true; > @@ -1009,6 +1069,9 @@ blsuki_find_entry (struct find_entry_info *info, bool > enable_fallback) > fallback = false; > } > while (fallback == true); > + > + grub_free (default_dir); > + return GRUB_ERR_NONE; > } > > static grub_err_t > @@ -1018,6 +1081,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, > @@ -1059,15 +1125,25 @@ blsuki_load_entries (char *path, bool enable_fallback) > } > > if (dir == NULL) > - dir = (char *) GRUB_BLS_CONFIG_PATH; > + { > + dir_size = grub_strlen (GRUB_BOOT_DEVICE) + grub_strlen > (GRUB_BLS_CONFIG_PATH); Ditto... > + default_dir = grub_malloc (dir_size); > + if (default_dir == NULL) > + return grub_errno; > + > + tmp = blsuki_update_boot_device (default_dir); > + tmp = grub_stpcpy (tmp, GRUB_BLS_CONFIG_PATH); > + dir = default_dir; > + } > > r = blsuki_set_find_entry_info (&info, dir, devid); > if (r == GRUB_ERR_NONE) > - blsuki_find_entry (&info, enable_fallback); > + r = blsuki_find_entry (&info, enable_fallback); > > if (info.dev != NULL) > grub_device_close (info.dev); > > + grub_free (default_dir); > return r; > } > > diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c > index 527d4f0c5..2fc212276 100644 > --- a/grub-core/osdep/linux/getroot.c > +++ b/grub-core/osdep/linux/getroot.c > @@ -131,6 +131,7 @@ struct mountinfo_entry > char fstype[ESCAPED_PATH_MAX + 1], device[ESCAPED_PATH_MAX + 1]; > }; > > +#ifdef GRUB_UTIL > static char ** > grub_util_raid_getmembers (const char *name, int bootable) > { > @@ -191,6 +192,7 @@ grub_util_raid_getmembers (const char *name, int bootable) > > return devicelist; > } > +#endif > > /* Statting something on a btrfs filesystem always returns a virtual device > major/minor pair rather than the real underlying device, because btrfs > @@ -579,6 +581,7 @@ out: > return ret; > } > > +#ifdef GRUB_UTIL > static char * > get_mdadm_uuid (const char *os_dev) > { > @@ -636,6 +639,7 @@ out: > > return name; > } > +#endif > > static int > grub_util_is_imsm (const char *os_dev) > @@ -968,6 +972,7 @@ grub_util_part_to_disk (const char *os_dev, struct stat > *st, > return path; > } > > +#ifdef GRUB_UTIL > static char * > grub_util_get_raid_grub_dev (const char *os_dev) > { > @@ -1070,6 +1075,7 @@ grub_util_get_raid_grub_dev (const char *os_dev) > } > return grub_dev; > } > +#endif > > enum grub_dev_abstraction_types > grub_util_get_dev_abstraction_os (const char *os_dev) > @@ -1086,6 +1092,7 @@ grub_util_get_dev_abstraction_os (const char *os_dev) > return GRUB_DEV_ABSTRACTION_NONE; > } > > +#ifdef GRUB_UTIL > int > grub_util_pull_device_os (const char *os_dev, > enum grub_dev_abstraction_types ab) > @@ -1142,6 +1149,7 @@ grub_util_get_grub_dev_os (const char *os_dev) > > return grub_dev; > } > +#endif > > char * > grub_make_system_path_relative_to_its_root_os (const char *path) > diff --git a/grub-core/osdep/unix/getroot.c b/grub-core/osdep/unix/getroot.c > index c7aa202ab..1380638d3 100644 > --- a/grub-core/osdep/unix/getroot.c > +++ b/grub-core/osdep/unix/getroot.c The changes to this file look like unrelated ones. Are they really needed? > @@ -17,6 +17,14 @@ > */ > > #include <config.h> > +#undef _GL_INLINE_HEADER_BEGIN > +#undef _GL_INLINE_HEADER_END > +#undef _GL_GNUC_PREREQ > +#undef _GL_ATTRIBUTE_COLD > +#undef _GL_ATTRIBUTE_CONST > +#undef _GL_ATTRIBUTE_DEALLOC > +#undef _GL_ATTRIBUTE_FALLTHROUGH > +#undef _GL_ATTRIBUTE_MALLOC > #include <config-util.h> > > #include <sys/stat.h> > @@ -566,6 +574,7 @@ grub_guess_root_devices (const char *dir_in) > > #endif > > +#ifdef GRUB_UTIL > void > grub_util_pull_lvm_by_command (const char *os_dev) > { > @@ -662,6 +671,7 @@ out: > free (buf); > free (vgid); > } > +#endif > > /* ZFS has similar problems to those of btrfs (see above). */ > void > diff --git a/include/grub/emu/misc.h b/include/grub/emu/misc.h > index fefbec499..542f4c18d 100644 > --- a/include/grub/emu/misc.h > +++ b/include/grub/emu/misc.h > @@ -39,7 +39,7 @@ void grub_fini_all (void); > void grub_find_zpool_from_dir (const char *dir, > char **poolname, char **poolfs); > > -char *grub_make_system_path_relative_to_its_root (const char *path) > +char * EXPORT_FUNC(grub_make_system_path_relative_to_its_root) (const char > *path) s/* EXPORT_FUNC(/*EXPORT_FUNC (/ Daniel _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel