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;
+
+  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))
+       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))
+       return grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected 
calculating default directory buffer size");
+
+      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
@@ -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)
  WARN_UNUSED_RESULT;
 int
 grub_util_device_is_mapped (const char *dev);
-- 
2.27.0


_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to