343 lines
10 KiB
Diff
343 lines
10 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Robbie Harwood <rharwood@redhat.com>
|
|
Date: Tue, 12 Aug 2025 03:45:35 +0000
|
|
Subject: [PATCH] blsuki: Check for mounted /boot in emu
|
|
|
|
Irritatingly, BLS defines paths relative to the mountpoint of the
|
|
filesystem which contains its snippets, not / or any other fixed
|
|
location. So grub-emu needs to know whether /boot is a separate
|
|
filesystem from / and conditionally prepend a path.
|
|
|
|
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
|
|
Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
|
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
|
---
|
|
grub-core/Makefile.core.def | 3 ++
|
|
grub-core/commands/blsuki.c | 83 +++++++++++++++++++++++++++++++++++++----
|
|
grub-core/osdep/linux/getroot.c | 8 ++++
|
|
grub-core/osdep/unix/getroot.c | 4 +-
|
|
include/grub/emu/misc.h | 2 +-
|
|
5 files changed, 91 insertions(+), 9 deletions(-)
|
|
|
|
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
|
|
index 78fafdd8fa..ddc5e71bbb 100644
|
|
--- a/grub-core/Makefile.core.def
|
|
+++ b/grub-core/Makefile.core.def
|
|
@@ -378,6 +378,9 @@ 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/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 9440adb100..ed93a150b1 100644
|
|
--- a/grub-core/commands/blsuki.c
|
|
+++ b/grub-core/commands/blsuki.c
|
|
@@ -32,6 +32,13 @@
|
|
#include <grub/lib/envblk.h>
|
|
#include <filevercmp.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/"
|
|
@@ -79,6 +86,34 @@ static grub_blsuki_entry_t *entries;
|
|
|
|
#define FOR_BLSUKI_ENTRIES(var) FOR_LIST_ELEMENTS (var, entries)
|
|
|
|
+/*
|
|
+ * 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
|
|
+ static int separate_boot = -1;
|
|
+ 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 == 0)
|
|
+ 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.
|
|
@@ -526,7 +561,7 @@ bls_get_linux (grub_blsuki_entry_t *entry)
|
|
linux_path = blsuki_get_val (entry, "linux", NULL);
|
|
options = blsuki_expand_val (blsuki_get_val (entry, "options", NULL));
|
|
|
|
- if (grub_add (sizeof ("linux "), grub_strlen (linux_path), &size))
|
|
+ if (grub_add (sizeof ("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;
|
|
@@ -548,6 +583,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)
|
|
{
|
|
@@ -582,7 +618,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, sizeof (" " GRUB_BOOT_DEVICE) - 1, &size) ||
|
|
grub_add (size, grub_strlen (initrd_list[i]), &size))
|
|
{
|
|
grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected calculating initrd buffer size");
|
|
@@ -605,6 +641,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");
|
|
@@ -630,7 +667,7 @@ bls_get_devicetree (grub_blsuki_entry_t *entry)
|
|
dt_path = blsuki_expand_val (blsuki_get_val (entry, "devicetree", NULL));
|
|
if (dt_path != NULL)
|
|
{
|
|
- if (grub_add (sizeof ("devicetree "), grub_strlen (dt_path), &size) ||
|
|
+ if (grub_add (sizeof ("devicetree " GRUB_BOOT_DEVICE), grub_strlen (dt_path), &size) ||
|
|
grub_add (size, 1, &size))
|
|
{
|
|
grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected calculating device tree buffer size");
|
|
@@ -643,6 +680,7 @@ bls_get_devicetree (grub_blsuki_entry_t *entry)
|
|
|
|
tmp = dt_cmd;
|
|
tmp = grub_stpcpy (dt_cmd, "devicetree ");
|
|
+ tmp = blsuki_update_boot_device (tmp);
|
|
tmp = grub_stpcpy (tmp, dt_path);
|
|
tmp = grub_stpcpy (tmp, "\n");
|
|
}
|
|
@@ -757,7 +795,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");
|
|
}
|
|
@@ -799,10 +841,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;
|
|
@@ -833,7 +878,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 = sizeof (GRUB_BOOT_DEVICE) + sizeof (GRUB_BLS_CONFIG_PATH) - 1;
|
|
+ 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;
|
|
@@ -842,6 +895,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
|
|
@@ -851,6 +907,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,
|
|
@@ -892,15 +951,25 @@ blsuki_load_entries (char *path, bool enable_fallback)
|
|
}
|
|
|
|
if (dir == NULL)
|
|
- dir = (char *) GRUB_BLS_CONFIG_PATH;
|
|
+ {
|
|
+ dir_size = sizeof (GRUB_BOOT_DEVICE) + sizeof (GRUB_BLS_CONFIG_PATH) - 2;
|
|
+ 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 b832593213..a60cf18a01 100644
|
|
--- a/grub-core/osdep/linux/getroot.c
|
|
+++ b/grub-core/osdep/linux/getroot.c
|
|
@@ -139,6 +139,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)
|
|
{
|
|
@@ -199,6 +200,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
|
|
@@ -700,6 +702,7 @@ out:
|
|
return ret;
|
|
}
|
|
|
|
+#ifdef GRUB_UTIL
|
|
static char *
|
|
get_mdadm_uuid (const char *os_dev)
|
|
{
|
|
@@ -757,6 +760,7 @@ out:
|
|
|
|
return name;
|
|
}
|
|
+#endif
|
|
|
|
static int
|
|
grub_util_is_imsm (const char *os_dev)
|
|
@@ -1089,6 +1093,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)
|
|
{
|
|
@@ -1191,6 +1196,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)
|
|
@@ -1207,6 +1213,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)
|
|
@@ -1263,6 +1270,7 @@ grub_util_get_grub_dev_os (const char *os_dev)
|
|
|
|
return grub_dev;
|
|
}
|
|
+#endif
|
|
|
|
static void *mp = NULL;
|
|
static void
|
|
diff --git a/grub-core/osdep/unix/getroot.c b/grub-core/osdep/unix/getroot.c
|
|
index ee11b02fb6..62581ba601 100644
|
|
--- a/grub-core/osdep/unix/getroot.c
|
|
+++ b/grub-core/osdep/unix/getroot.c
|
|
@@ -16,8 +16,8 @@
|
|
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
-#include <config.h>
|
|
#include <config-util.h>
|
|
+#include <config.h>
|
|
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
@@ -567,6 +567,7 @@ grub_guess_root_devices (const char *dir_in)
|
|
|
|
#endif
|
|
|
|
+#ifdef GRUB_UTIL
|
|
void
|
|
grub_util_pull_lvm_by_command (const char *os_dev)
|
|
{
|
|
@@ -663,6 +664,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 f3a712a8b2..59b8038c60 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)
|
|
WARN_UNUSED_RESULT;
|
|
int
|
|
grub_util_device_is_mapped (const char *dev);
|