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 <[email protected]>
> Signed-off-by: Alec Brown <[email protected]>
> ---
> 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
[email protected]
https://lists.gnu.org/mailman/listinfo/grub-devel