Compare commits
No commits in common. "rawhide" and "f43" have entirely different histories.
30 changed files with 24 additions and 4474 deletions
|
|
@ -1,102 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Leo Sandoval <lsandova@redhat.com>
|
||||
Date: Fri, 11 Apr 2025 15:31:53 -0600
|
||||
Subject: [PATCH] Include function name on debug and error print functions
|
||||
|
||||
Together with the line number, the debug log gives more context when
|
||||
debugging.
|
||||
|
||||
Signed-off-by: Leo Sandoval <lsandova@redhat.com>
|
||||
---
|
||||
grub-core/kern/err.c | 4 ++--
|
||||
grub-core/kern/misc.c | 4 ++--
|
||||
include/grub/err.h | 6 +++---
|
||||
include/grub/misc.h | 5 +++--
|
||||
4 files changed, 10 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/grub-core/kern/err.c b/grub-core/kern/err.c
|
||||
index aebfe0cf83..ba04b57fb7 100644
|
||||
--- a/grub-core/kern/err.c
|
||||
+++ b/grub-core/kern/err.c
|
||||
@@ -38,14 +38,14 @@ static int grub_error_stack_assert;
|
||||
#endif
|
||||
|
||||
grub_err_t
|
||||
-grub_error (grub_err_t n, const char *file, const int line, const char *fmt, ...)
|
||||
+grub_error (grub_err_t n, const char *file, const char *function, const int line, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int m;
|
||||
|
||||
grub_errno = n;
|
||||
|
||||
- m = grub_snprintf (grub_errmsg, sizeof (grub_errmsg), "%s:%d:", file, line);
|
||||
+ m = grub_snprintf (grub_errmsg, sizeof (grub_errmsg), "%s:%s:%d:", file, function, line);
|
||||
if (m < 0)
|
||||
m = 0;
|
||||
|
||||
diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
|
||||
index 69bd655f3d..541c7bb80c 100644
|
||||
--- a/grub-core/kern/misc.c
|
||||
+++ b/grub-core/kern/misc.c
|
||||
@@ -248,7 +248,7 @@ grub_debug_enabled (const char * condition)
|
||||
}
|
||||
|
||||
void
|
||||
-grub_real_dprintf (const char *file, const int line, const char *condition,
|
||||
+grub_real_dprintf (const char *file, const char *function, const int line, const char *condition,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
@@ -272,7 +272,7 @@ grub_real_dprintf (const char *file, const int line, const char *condition,
|
||||
else
|
||||
last_had_cr = 0;
|
||||
#endif
|
||||
- grub_printf ("%s:%d:%s: ", file, line, condition);
|
||||
+ grub_printf ("%s:%s:%d:%s: ", file, function, line, condition);
|
||||
va_start (args, fmt);
|
||||
grub_vprintf (fmt, args);
|
||||
va_end (args);
|
||||
diff --git a/include/grub/err.h b/include/grub/err.h
|
||||
index 7530f58b29..6379a6baf8 100644
|
||||
--- a/include/grub/err.h
|
||||
+++ b/include/grub/err.h
|
||||
@@ -88,10 +88,10 @@ struct grub_error_saved
|
||||
extern grub_err_t EXPORT_VAR(grub_errno);
|
||||
extern char EXPORT_VAR(grub_errmsg)[GRUB_MAX_ERRMSG];
|
||||
|
||||
-grub_err_t EXPORT_FUNC(grub_error) (grub_err_t n, const char *file, const int line, const char *fmt, ...)
|
||||
- __attribute__ ((format (GNU_PRINTF, 4, 5)));
|
||||
+grub_err_t EXPORT_FUNC(grub_error) (grub_err_t n, const char *file, const char *function, const int line, const char *fmt, ...)
|
||||
+ __attribute__ ((format (GNU_PRINTF, 5, 6)));
|
||||
|
||||
-#define grub_error(n, fmt, ...) grub_error (n, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
|
||||
+#define grub_error(n, fmt, ...) grub_error (n, __FILE__, __FUNCTION__, __LINE__, fmt, ##__VA_ARGS__)
|
||||
|
||||
|
||||
void EXPORT_FUNC(grub_fatal) (const char *fmt, ...) __attribute__ ((noreturn));
|
||||
diff --git a/include/grub/misc.h b/include/grub/misc.h
|
||||
index 0429339ef3..2b9096a0b3 100644
|
||||
--- a/include/grub/misc.h
|
||||
+++ b/include/grub/misc.h
|
||||
@@ -43,7 +43,7 @@
|
||||
#define CONCAT(a, b) CONCAT_(a, b)
|
||||
#endif
|
||||
|
||||
-#define grub_dprintf(condition, ...) grub_real_dprintf(GRUB_FILE, __LINE__, condition, __VA_ARGS__)
|
||||
+#define grub_dprintf(condition, ...) grub_real_dprintf(GRUB_FILE, __FUNCTION__, __LINE__, condition, __VA_ARGS__)
|
||||
|
||||
void *EXPORT_FUNC(grub_memmove) (void *dest, const void *src, grub_size_t n);
|
||||
char *EXPORT_FUNC(grub_strcpy) (char *dest, const char *src);
|
||||
@@ -420,9 +420,10 @@ int EXPORT_FUNC(grub_puts_) (const char *s);
|
||||
int EXPORT_FUNC(grub_debug_is_enabled) (void);
|
||||
int EXPORT_FUNC(grub_debug_enabled) (const char *condition);
|
||||
void EXPORT_FUNC(grub_real_dprintf) (const char *file,
|
||||
+ const char *function,
|
||||
const int line,
|
||||
const char *condition,
|
||||
- const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 4, 5)));
|
||||
+ const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 5, 6)));
|
||||
int EXPORT_FUNC(grub_printf) (const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 1, 2)));
|
||||
int EXPORT_FUNC(grub_printf_) (const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 1, 2)));
|
||||
void EXPORT_FUNC(grub_qdprintf) (const char *condition,
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alec Brown <alec.r.brown@oracle.com>
|
||||
Date: Tue, 12 Aug 2025 03:45:32 +0000
|
||||
Subject: [PATCH] kern/misc: Implement grub_strtok()
|
||||
|
||||
Add the functions grub_strtok() and grub_strtok_r() to help parse strings into
|
||||
tokens separated by characters in the "delim" parameter. These functions are
|
||||
present in gnulib but calling them directly from the gnulib code is quite
|
||||
challenging since the call "#include <string.h>" would include the header file
|
||||
grub-core/lib/posix_wrap/string.h instead of grub-core/lib/gnulib/string.h,
|
||||
where strtok() and strtok_r() are declared. Since this overlap is quite
|
||||
problematic, the simpler solution was to implement the code in the GRUB based
|
||||
on gnulib's implementation. For more information on these functions, visit the
|
||||
Linux Programmer's Manual, man strtok.
|
||||
|
||||
Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/kern/misc.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
include/grub/misc.h | 3 +++
|
||||
2 files changed, 65 insertions(+)
|
||||
|
||||
diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
|
||||
index 69bd655f3d..c69fe7fb19 100644
|
||||
--- a/grub-core/kern/misc.c
|
||||
+++ b/grub-core/kern/misc.c
|
||||
@@ -453,6 +453,68 @@ grub_strword (const char *haystack, const char *needle)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+char *
|
||||
+grub_strtok_r (char *s, const char *delim, char **save_ptr)
|
||||
+{
|
||||
+ char *token;
|
||||
+ const char *c;
|
||||
+ bool is_delim;
|
||||
+
|
||||
+ if (s == NULL)
|
||||
+ s = *save_ptr;
|
||||
+
|
||||
+ /* Scan leading delimiters. */
|
||||
+ while (*s != '\0')
|
||||
+ {
|
||||
+ is_delim = false;
|
||||
+ for (c = delim; *c != '\0'; c++)
|
||||
+ {
|
||||
+ if (*s == *c)
|
||||
+ {
|
||||
+ is_delim = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ if (is_delim == true)
|
||||
+ s++;
|
||||
+ else
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (*s == '\0')
|
||||
+ {
|
||||
+ *save_ptr = s;
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ /* Find the end of the token. */
|
||||
+ token = s;
|
||||
+ while (*s != '\0')
|
||||
+ {
|
||||
+ for (c = delim; *c != '\0'; c++)
|
||||
+ {
|
||||
+ if (*s == *c)
|
||||
+ {
|
||||
+ *s = '\0';
|
||||
+ *save_ptr = s + 1;
|
||||
+ return token;
|
||||
+ }
|
||||
+ }
|
||||
+ s++;
|
||||
+ }
|
||||
+
|
||||
+ *save_ptr = s;
|
||||
+ return token;
|
||||
+}
|
||||
+
|
||||
+char *
|
||||
+grub_strtok (char *s, const char *delim)
|
||||
+{
|
||||
+ static char *last;
|
||||
+
|
||||
+ return grub_strtok_r (s, delim, &last);
|
||||
+}
|
||||
+
|
||||
int
|
||||
grub_isspace (int c)
|
||||
{
|
||||
diff --git a/include/grub/misc.h b/include/grub/misc.h
|
||||
index 0429339ef3..626f0c3535 100644
|
||||
--- a/include/grub/misc.h
|
||||
+++ b/include/grub/misc.h
|
||||
@@ -134,6 +134,9 @@ char *EXPORT_FUNC(grub_strchr) (const char *s, int c);
|
||||
char *EXPORT_FUNC(grub_strrchr) (const char *s, int c);
|
||||
int EXPORT_FUNC(grub_strword) (const char *s, const char *w);
|
||||
|
||||
+char *EXPORT_FUNC(grub_strtok_r) (char *s, const char *delim, char **save_ptr);
|
||||
+char *EXPORT_FUNC(grub_strtok) (char *s, const char *delim);
|
||||
+
|
||||
/* Copied from gnulib.
|
||||
Written by Bruno Haible <bruno@clisp.org>, 2005. */
|
||||
static inline char *
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,43 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alec Brown <alec.r.brown@oracle.com>
|
||||
Date: Tue, 12 Aug 2025 03:45:34 +0000
|
||||
Subject: [PATCH] util/misc.c: Change offset type for
|
||||
grub_util_write_image_at()
|
||||
|
||||
Adding filevercmp support to grub-core/commands/blsuki.c from gnulib will cause
|
||||
issues with the type of the offset parameter for grub_util_write_image_at() for
|
||||
emu builds. To fix this issue, we can change the type from off_t to grub_off_t.
|
||||
|
||||
Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
include/grub/util/misc.h | 2 +-
|
||||
util/misc.c | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/include/grub/util/misc.h b/include/grub/util/misc.h
|
||||
index e9e0a6724a..bfce065583 100644
|
||||
--- a/include/grub/util/misc.h
|
||||
+++ b/include/grub/util/misc.h
|
||||
@@ -36,7 +36,7 @@ char *grub_util_read_image (const char *path);
|
||||
void grub_util_load_image (const char *path, char *buf);
|
||||
void grub_util_write_image (const char *img, size_t size, FILE *out,
|
||||
const char *name);
|
||||
-void grub_util_write_image_at (const void *img, size_t size, off_t offset,
|
||||
+void grub_util_write_image_at (const void *img, size_t size, grub_off_t offset,
|
||||
FILE *out, const char *name);
|
||||
|
||||
char *make_system_path_relative_to_its_root (const char *path);
|
||||
diff --git a/util/misc.c b/util/misc.c
|
||||
index 0f928e5b49..6e16a68d9a 100644
|
||||
--- a/util/misc.c
|
||||
+++ b/util/misc.c
|
||||
@@ -101,7 +101,7 @@ grub_util_read_image (const char *path)
|
||||
}
|
||||
|
||||
void
|
||||
-grub_util_write_image_at (const void *img, size_t size, off_t offset, FILE *out,
|
||||
+grub_util_write_image_at (const void *img, size_t size, grub_off_t offset, FILE *out,
|
||||
const char *name)
|
||||
{
|
||||
grub_util_info ("writing 0x%" GRUB_HOST_PRIxLONG_LONG " bytes at offset 0x%"
|
||||
|
|
@ -1,342 +0,0 @@
|
|||
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 5e0e757344..885dd436de 100644
|
||||
--- a/grub-core/Makefile.core.def
|
||||
+++ b/grub-core/Makefile.core.def
|
||||
@@ -376,6 +376,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 4bf386b590..8bf281c1d8 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_or_ddf (const char *os_dev)
|
||||
@@ -1096,6 +1100,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)
|
||||
{
|
||||
@@ -1198,6 +1203,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)
|
||||
@@ -1214,6 +1220,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)
|
||||
@@ -1270,6 +1277,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);
|
||||
|
|
@ -1,822 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alec Brown <alec.r.brown@oracle.com>
|
||||
Date: Tue, 12 Aug 2025 03:45:36 +0000
|
||||
Subject: [PATCH] blsuki: Add uki command to load Unified Kernel Image entries
|
||||
|
||||
A Unified Kernel Image (UKI) is a single UEFI PE file that combines
|
||||
a UEFI boot stub, a Linux kernel image, an initrd, and further resources.
|
||||
The uki command will locate where the UKI file is and create a GRUB menu
|
||||
entry to load it.
|
||||
|
||||
The Unified Kernel Image Specification: https://uapi-group.org/specifications/specs/unified_kernel_image/
|
||||
|
||||
Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
docs/grub.texi | 36 +++-
|
||||
grub-core/commands/blsuki.c | 476 ++++++++++++++++++++++++++++++++++++++++----
|
||||
include/grub/menu.h | 2 +
|
||||
3 files changed, 474 insertions(+), 40 deletions(-)
|
||||
|
||||
diff --git a/docs/grub.texi b/docs/grub.texi
|
||||
index 336f8e87ed..531e847f32 100644
|
||||
--- a/docs/grub.texi
|
||||
+++ b/docs/grub.texi
|
||||
@@ -3344,7 +3344,8 @@ chain-loaded system, @pxref{drivemap}.
|
||||
@subsection blsuki_save_default
|
||||
|
||||
If this variable is set, menu entries generated from BLS config files
|
||||
-(@pxref{blscfg}) will be set as the default boot entry when selected.
|
||||
+(@pxref{blscfg}) or UKI files (@pxref{uki}) will be set as the default boot
|
||||
+entry when selected.
|
||||
|
||||
@node check_appended_signatures
|
||||
@subsection check_appended_signatures
|
||||
@@ -4434,6 +4435,7 @@ you forget a command, you can run the command @command{help}
|
||||
* true:: Do nothing, successfully
|
||||
* trust:: Add public key to list of trusted keys
|
||||
* trust_certificate:: Add an x509 certificate to the list of trusted certificates
|
||||
+* uki:: Load Unified Kernel Image menu entries
|
||||
* unset:: Unset an environment variable
|
||||
@comment * vbeinfo:: List available video modes
|
||||
* verify_appended:: Verify appended digital signature
|
||||
@@ -6062,6 +6064,38 @@ Unset the environment variable @var{envvar}.
|
||||
@end deffn
|
||||
|
||||
|
||||
+@node uki
|
||||
+@subsection uki
|
||||
+
|
||||
+@deffn Command uki [@option{-p|--path} dir] [@option{-f|--enable-fallback}] [@option{-d|--show-default}] [@option{-n|--show-non-default}] [@option{-e|--entry} file]
|
||||
+Load Unified Kernel Image (UKI) files into the GRUB menu. Boot entries
|
||||
+generated from @command{uki} won't interfere with entries from @file{grub.cfg} appearing in the
|
||||
+GRUB menu. Also, entries generated from @command{uki} exists only in memory and don't
|
||||
+update @file{grub.cfg}.
|
||||
+
|
||||
+By default, the UKI files are stored in the @file{/EFI/Linux} directory in the EFI
|
||||
+system partition. If UKI files are stored elsewhere, the @option{--path} option can be
|
||||
+used to check a different directory instead of the default location. If no UKI
|
||||
+files are found while using the @option{--path} option, the @option{--enable-fallback} option can
|
||||
+be used to check for files in the default location.
|
||||
+
|
||||
+The @option{--show-default} option allows the default boot entry to be added to the
|
||||
+GRUB menu from the UKI files.
|
||||
+
|
||||
+The @option{--show-non-default} option allows non-default boot entries to be added to
|
||||
+the GRUB menu from the UKI files.
|
||||
+
|
||||
+The @option{--entry} option allows specific boot entries to be added to the GRUB menu
|
||||
+from the UKI files.
|
||||
+
|
||||
+The @option{--entry}, @option{--show-default}, and @option{--show-non-default} options
|
||||
+are used to filter which UKI files are added to the GRUB menu. If none are
|
||||
+used, all files in the default location or the location specified by @option{--path}
|
||||
+will be added to the GRUB menu.
|
||||
+
|
||||
+For more information on UKI, see: @uref{https://uapi-group.org/specifications/specs/unified_kernel_image/, The Unified Kernel Image Specification}
|
||||
+@end deffn
|
||||
+
|
||||
@ignore
|
||||
@node vbeinfo
|
||||
@subsection vbeinfo
|
||||
diff --git a/grub-core/commands/blsuki.c b/grub-core/commands/blsuki.c
|
||||
index ed93a150b1..cb00f936a7 100644
|
||||
--- a/grub-core/commands/blsuki.c
|
||||
+++ b/grub-core/commands/blsuki.c
|
||||
@@ -32,6 +32,12 @@
|
||||
#include <grub/lib/envblk.h>
|
||||
#include <filevercmp.h>
|
||||
|
||||
+#ifdef GRUB_MACHINE_EFI
|
||||
+#include <grub/efi/efi.h>
|
||||
+#include <grub/efi/disk.h>
|
||||
+#include <grub/efi/pe32.h>
|
||||
+#endif
|
||||
+
|
||||
#ifdef GRUB_MACHINE_EMU
|
||||
#include <grub/emu/misc.h>
|
||||
#define GRUB_BOOT_DEVICE "/boot"
|
||||
@@ -42,14 +48,28 @@
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
#define GRUB_BLS_CONFIG_PATH "/loader/entries/"
|
||||
+#define GRUB_UKI_CONFIG_PATH "/EFI/Linux"
|
||||
|
||||
#define BLS_EXT_LEN (sizeof (".conf") - 1)
|
||||
+#define UKI_EXT_LEN (sizeof (".efi") - 1)
|
||||
|
||||
/*
|
||||
* It is highly unlikely to ever receive a large amount of keyval pairs. A
|
||||
* limit of 10000 is more than enough.
|
||||
*/
|
||||
#define BLSUKI_KEYVALS_MAX 10000
|
||||
+/*
|
||||
+ * The only sections we read are ".cmdline" and ".osrel". The ".cmdline"
|
||||
+ * section has a size limit of 4096 and it would be very unlikely for the size
|
||||
+ * of the ".osrel" section to be 5 times larger than 4096.
|
||||
+ */
|
||||
+#define UKI_SECTION_SIZE_MAX (5 * 4096)
|
||||
+
|
||||
+enum blsuki_cmd_type
|
||||
+ {
|
||||
+ BLSUKI_BLS_CMD,
|
||||
+ BLSUKI_UKI_CMD,
|
||||
+ };
|
||||
|
||||
static const struct grub_arg_option bls_opt[] =
|
||||
{
|
||||
@@ -61,6 +81,18 @@ static const struct grub_arg_option bls_opt[] =
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
+#ifdef GRUB_MACHINE_EFI
|
||||
+static const struct grub_arg_option uki_opt[] =
|
||||
+ {
|
||||
+ {"path", 'p', 0, N_("Specify path to find UKI entries."), N_("DIR"), ARG_TYPE_PATHNAME},
|
||||
+ {"enable-fallback", 'f', 0, "Fallback to the default BLS path if --path fails to find UKI entries.", 0, ARG_TYPE_NONE},
|
||||
+ {"show-default", 'd', 0, N_("Allow the default UKI entry to be added to the GRUB menu."), 0, ARG_TYPE_NONE},
|
||||
+ {"show-non-default", 'n', 0, N_("Allow the non-default UKI entries to be added to the GRUB menu."), 0, ARG_TYPE_NONE},
|
||||
+ {"entry", 'e', 0, N_("Allow specificUKII entries to be added to the GRUB menu."), N_("FILE"), ARG_TYPE_FILE},
|
||||
+ {0, 0, 0, 0, 0, 0}
|
||||
+ };
|
||||
+#endif
|
||||
+
|
||||
struct keyval
|
||||
{
|
||||
const char *key;
|
||||
@@ -71,6 +103,7 @@ struct read_entry_info
|
||||
{
|
||||
const char *devid;
|
||||
const char *dirname;
|
||||
+ enum blsuki_cmd_type cmd_type;
|
||||
grub_file_t file;
|
||||
};
|
||||
|
||||
@@ -82,7 +115,7 @@ struct find_entry_info
|
||||
grub_fs_t fs;
|
||||
};
|
||||
|
||||
-static grub_blsuki_entry_t *entries;
|
||||
+static grub_blsuki_entry_t *entries = NULL;
|
||||
|
||||
#define FOR_BLSUKI_ENTRIES(var) FOR_LIST_ELEMENTS (var, entries)
|
||||
|
||||
@@ -181,7 +214,7 @@ blsuki_add_keyval (grub_blsuki_entry_t *entry, char *key, char *val)
|
||||
* Find the value of the key named by keyname. If there are allowed to be
|
||||
* more than one, pass a pointer set to -1 to the last parameter the first
|
||||
* time, and pass the same pointer through each time after, and it'll return
|
||||
- * them in sorted order as defined in the BLS fragment file.
|
||||
+ * them in sorted order.
|
||||
*/
|
||||
static char *
|
||||
blsuki_get_val (grub_blsuki_entry_t *entry, const char *keyname, int *last)
|
||||
@@ -310,20 +343,212 @@ bls_parse_keyvals (grub_file_t f, grub_blsuki_entry_t *entry)
|
||||
return err;
|
||||
}
|
||||
|
||||
+#ifdef GRUB_MACHINE_EFI
|
||||
+/*
|
||||
+ * This function searches for the .cmdline, .osrel, and .linux sections of a
|
||||
+ * UKI. We only need to store the data for the .cmdline and .osrel sections,
|
||||
+ * but we also need to verify that the .linux section exists.
|
||||
+ */
|
||||
+static grub_err_t
|
||||
+uki_parse_keyvals (grub_file_t f, grub_blsuki_entry_t *entry)
|
||||
+{
|
||||
+ struct grub_msdos_image_header *dos = NULL;
|
||||
+ struct grub_pe_image_header *pe = NULL;
|
||||
+ grub_off_t section_offset = 0;
|
||||
+ struct grub_pe32_section_table *section = NULL;
|
||||
+ struct grub_pe32_coff_header *coff_header = NULL;
|
||||
+ char *val = NULL;
|
||||
+ char *key = NULL;
|
||||
+ const char *target[] = {".cmdline", ".osrel", ".linux", NULL};
|
||||
+ bool has_linux = false;
|
||||
+ grub_err_t err = GRUB_ERR_NONE;
|
||||
+
|
||||
+ dos = grub_zalloc (sizeof (*dos));
|
||||
+ if (dos == NULL)
|
||||
+ return grub_errno;
|
||||
+ if (grub_file_read (f, dos, sizeof (*dos)) < (grub_ssize_t) sizeof (*dos))
|
||||
+ {
|
||||
+ err = grub_error (GRUB_ERR_FILE_READ_ERROR, "failed to read UKI image header");
|
||||
+ goto finish;
|
||||
+ }
|
||||
+ if (dos->msdos_magic != GRUB_DOS_MAGIC)
|
||||
+ {
|
||||
+ err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "plain image kernel is not supported");
|
||||
+ goto finish;
|
||||
+ }
|
||||
+
|
||||
+ grub_dprintf ("blsuki", "PE/COFF header @ %08x\n", dos->pe_image_header_offset);
|
||||
+ pe = grub_zalloc (sizeof (*pe));
|
||||
+ if (pe == NULL)
|
||||
+ {
|
||||
+ err = grub_errno;
|
||||
+ goto finish;
|
||||
+ }
|
||||
+ if (grub_file_seek (f, dos->pe_image_header_offset) == (grub_off_t) -1 ||
|
||||
+ grub_file_read (f, pe, sizeof (*pe)) != sizeof (*pe))
|
||||
+ {
|
||||
+ err = grub_error (GRUB_ERR_FILE_READ_ERROR, "failed to read COFF image header");
|
||||
+ goto finish;
|
||||
+ }
|
||||
+ if (pe->optional_header.magic != GRUB_PE32_NATIVE_MAGIC)
|
||||
+ {
|
||||
+ err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "non-native image not supported");
|
||||
+ goto finish;
|
||||
+ }
|
||||
+
|
||||
+ coff_header = &(pe->coff_header);
|
||||
+ section_offset = dos->pe_image_header_offset + sizeof (*pe);
|
||||
+
|
||||
+ for (int i = 0; i < coff_header->num_sections; i++)
|
||||
+ {
|
||||
+ section = grub_zalloc (sizeof (*section));
|
||||
+ if (section == NULL)
|
||||
+ {
|
||||
+ err = grub_errno;
|
||||
+ goto finish;
|
||||
+ }
|
||||
+
|
||||
+ if (grub_file_seek (f, section_offset) == (grub_off_t) -1 ||
|
||||
+ grub_file_read (f, section, sizeof (*section)) != sizeof (*section))
|
||||
+ {
|
||||
+ err = grub_error (GRUB_ERR_FILE_READ_ERROR, "failed to read section header");
|
||||
+ goto finish;
|
||||
+ }
|
||||
+
|
||||
+ key = grub_strndup (section->name, 8);
|
||||
+ if (key == NULL)
|
||||
+ {
|
||||
+ err = grub_errno;
|
||||
+ goto finish;
|
||||
+ }
|
||||
+
|
||||
+ for (int j = 0; target[j] != NULL; j++)
|
||||
+ {
|
||||
+ if (grub_strcmp (key, target[j]) == 0)
|
||||
+ {
|
||||
+ /*
|
||||
+ * We don't need to read the contents of the .linux PE section, but we
|
||||
+ * should verify that the section exists.
|
||||
+ */
|
||||
+ if (grub_strcmp (key, ".linux") == 0)
|
||||
+ {
|
||||
+ has_linux = true;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (section->raw_data_size > UKI_SECTION_SIZE_MAX)
|
||||
+ {
|
||||
+ err = grub_error (GRUB_ERR_BAD_NUMBER, "UKI section size is larger than expected");
|
||||
+ goto finish;
|
||||
+ }
|
||||
+
|
||||
+ val = grub_zalloc (section->raw_data_size);
|
||||
+ if (val == NULL)
|
||||
+ {
|
||||
+ err = grub_errno;
|
||||
+ goto finish;
|
||||
+ }
|
||||
+
|
||||
+ if (grub_file_seek (f, section->raw_data_offset) == (grub_off_t) -1 ||
|
||||
+ grub_file_read (f, val, section->raw_data_size) != (grub_ssize_t) section->raw_data_size)
|
||||
+ {
|
||||
+ err = grub_error (GRUB_ERR_FILE_READ_ERROR, "failed to read section");
|
||||
+ goto finish;
|
||||
+ }
|
||||
+
|
||||
+ err = blsuki_add_keyval (entry, key, val);
|
||||
+ if (err != GRUB_ERR_NONE)
|
||||
+ goto finish;
|
||||
+
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ section_offset += sizeof (*section);
|
||||
+ grub_free (section);
|
||||
+ grub_free (val);
|
||||
+ grub_free (key);
|
||||
+ section = NULL;
|
||||
+ val = NULL;
|
||||
+ key = NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (has_linux == false)
|
||||
+ err = grub_error (GRUB_ERR_NO_KERNEL, "UKI is missing the '.linux' section");
|
||||
+
|
||||
+ finish:
|
||||
+ grub_free (dos);
|
||||
+ grub_free (pe);
|
||||
+ grub_free (section);
|
||||
+ grub_free (val);
|
||||
+ grub_free (key);
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * This function obtains the keyval pairs when the .osrel data is input into
|
||||
+ * the osrel_ptr parameter and returns the keyval pair. Since we are using
|
||||
+ * grub_strtok_r(), the osrel_ptr will be updated to the following line of
|
||||
+ * osrel. This function returns NULL when it reaches the end of osrel.
|
||||
+ */
|
||||
+static char *
|
||||
+uki_read_osrel (char **osrel_ptr, char **val_ret)
|
||||
+{
|
||||
+ char *key, *val;
|
||||
+ grub_size_t val_size;
|
||||
+
|
||||
+ for (;;)
|
||||
+ {
|
||||
+ key = grub_strtok_r (NULL, "\n\r", osrel_ptr);
|
||||
+ if (key == NULL)
|
||||
+ return NULL;
|
||||
+
|
||||
+ /* Remove leading white space */
|
||||
+ while (*key == ' ' || *key == '\t')
|
||||
+ key++;
|
||||
+
|
||||
+ /* Skip commented lines */
|
||||
+ if (*key == '#')
|
||||
+ continue;
|
||||
+
|
||||
+ /* Split key/value */
|
||||
+ key = grub_strtok_r (key, "=", &val);
|
||||
+ if (key == NULL || *val == '\0')
|
||||
+ continue;
|
||||
+
|
||||
+ /* Remove quotes from value */
|
||||
+ val_size = grub_strlen (val);
|
||||
+ if ((*val == '\"' && val[val_size - 1] == '\"') ||
|
||||
+ (*val == '\'' && val[val_size - 1] == '\''))
|
||||
+ {
|
||||
+ val[val_size - 1] = '\0';
|
||||
+ val++;
|
||||
+ }
|
||||
+
|
||||
+ *val_ret = val;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return key;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
/*
|
||||
* If a file hasn't already been opened, this function opens a BLS config file
|
||||
- * and initializes entry data before parsing keyvals and adding the entry to
|
||||
- * the list of BLS entries.
|
||||
+ * or UKI and initializes entry data before parsing keyvals and adding the entry
|
||||
+ * to the list of BLS or UKI entries.
|
||||
*/
|
||||
static int
|
||||
blsuki_read_entry (const char *filename,
|
||||
const struct grub_dirhook_info *dirhook_info __attribute__ ((__unused__)),
|
||||
void *data)
|
||||
{
|
||||
- grub_size_t path_len = 0, filename_len;
|
||||
- grub_err_t err;
|
||||
+ grub_size_t path_len = 0, ext_len = 0, filename_len;
|
||||
+ grub_err_t err = GRUB_ERR_NONE;
|
||||
char *p = NULL;
|
||||
+ const char *ext = NULL;
|
||||
grub_file_t f = NULL;
|
||||
+ enum grub_file_type file_type = 0;
|
||||
grub_blsuki_entry_t *entry;
|
||||
struct read_entry_info *info = (struct read_entry_info *) data;
|
||||
|
||||
@@ -331,17 +556,31 @@ blsuki_read_entry (const char *filename,
|
||||
|
||||
filename_len = grub_strlen (filename);
|
||||
|
||||
+ if (info->cmd_type == BLSUKI_BLS_CMD)
|
||||
+ {
|
||||
+ ext = ".conf";
|
||||
+ ext_len = BLS_EXT_LEN;
|
||||
+ file_type = GRUB_FILE_TYPE_CONFIG;
|
||||
+ }
|
||||
+#ifdef GRUB_MACHINE_EFI
|
||||
+ else if (info->cmd_type == BLSUKI_UKI_CMD)
|
||||
+ {
|
||||
+ ext = ".efi";
|
||||
+ ext_len = UKI_EXT_LEN;
|
||||
+ file_type = GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE;
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
if (info->file != NULL)
|
||||
f = info->file;
|
||||
else
|
||||
{
|
||||
- if (filename_len < BLS_EXT_LEN ||
|
||||
- grub_strcmp (filename + filename_len - BLS_EXT_LEN, ".conf") != 0)
|
||||
+ if (filename_len < ext_len ||
|
||||
+ grub_strcmp (filename + filename_len - ext_len, ext) != 0)
|
||||
return 0;
|
||||
|
||||
p = grub_xasprintf ("(%s)%s/%s", info->devid, info->dirname, filename);
|
||||
-
|
||||
- f = grub_file_open (p, GRUB_FILE_TYPE_CONFIG);
|
||||
+ f = grub_file_open (p, file_type);
|
||||
grub_free (p);
|
||||
if (f == NULL)
|
||||
goto finish;
|
||||
@@ -373,7 +612,26 @@ blsuki_read_entry (const char *filename,
|
||||
goto finish;
|
||||
}
|
||||
|
||||
- err = bls_parse_keyvals (f, entry);
|
||||
+ entry->dirname = grub_strdup (info->dirname);
|
||||
+ if (entry->dirname == NULL)
|
||||
+ {
|
||||
+ grub_free (entry);
|
||||
+ goto finish;
|
||||
+ }
|
||||
+
|
||||
+ entry->devid = grub_strdup (info->devid);
|
||||
+ if (entry->devid == NULL)
|
||||
+ {
|
||||
+ grub_free (entry);
|
||||
+ goto finish;
|
||||
+ }
|
||||
+
|
||||
+ if (info->cmd_type == BLSUKI_BLS_CMD)
|
||||
+ err = bls_parse_keyvals (f, entry);
|
||||
+#ifdef GRUB_MACHINE_EFI
|
||||
+ else if (info->cmd_type == BLSUKI_UKI_CMD)
|
||||
+ err = uki_parse_keyvals (f, entry);
|
||||
+#endif
|
||||
|
||||
if (err == GRUB_ERR_NONE)
|
||||
blsuki_add_entry (entry);
|
||||
@@ -389,7 +647,7 @@ blsuki_read_entry (const char *filename,
|
||||
|
||||
/*
|
||||
* This function returns a list of values that had the same key in the BLS
|
||||
- * config file. The number of entries in this list is returned by the len
|
||||
+ * config file or UKI. The number of entries in this list is returned by the len
|
||||
* parameter.
|
||||
*/
|
||||
static char **
|
||||
@@ -764,7 +1022,7 @@ bls_create_entry (grub_blsuki_entry_t *entry)
|
||||
linux_cmd, initrd_cmd ? initrd_cmd : "",
|
||||
dt_cmd ? dt_cmd : "");
|
||||
|
||||
- grub_normal_add_menu_entry (argc, argv, classes, id, users, hotkey, NULL, src, 0, entry);
|
||||
+ grub_normal_add_menu_entry (argc, argv, classes, id, users, hotkey, NULL, src, 0, NULL, NULL, entry);
|
||||
|
||||
finish:
|
||||
grub_free (linux_cmd);
|
||||
@@ -776,6 +1034,70 @@ bls_create_entry (grub_blsuki_entry_t *entry)
|
||||
grub_free (src);
|
||||
}
|
||||
|
||||
+#ifdef GRUB_MACHINE_EFI
|
||||
+/*
|
||||
+ * This function puts together the section data received from the UKI and
|
||||
+ * generates a new entry in the GRUB boot menu.
|
||||
+ */
|
||||
+static void
|
||||
+uki_create_entry (grub_blsuki_entry_t *entry)
|
||||
+{
|
||||
+ const char **argv = NULL;
|
||||
+ char *id = entry->filename;
|
||||
+ char *title = NULL;
|
||||
+ char *options = NULL;
|
||||
+ char *osrel, *osrel_line;
|
||||
+ char *key = NULL;
|
||||
+ char *value = NULL;
|
||||
+ char *src = NULL;
|
||||
+ bool blsuki_save_default;
|
||||
+
|
||||
+ /*
|
||||
+ * Although .osrel is listed as optional in the UKI specification, the .osrel
|
||||
+ * section is needed to generate the GRUB menu entry title.
|
||||
+ */
|
||||
+ osrel = blsuki_get_val (entry, ".osrel", NULL);
|
||||
+ if (osrel == NULL)
|
||||
+ {
|
||||
+ grub_dprintf ("blsuki", "Skipping file %s with no '.osrel' key.\n", entry->filename);
|
||||
+ goto finish;
|
||||
+ }
|
||||
+
|
||||
+ osrel_line = osrel;
|
||||
+ while ((key = uki_read_osrel (&osrel_line, &value)) != NULL)
|
||||
+ {
|
||||
+ if (grub_strcmp ("PRETTY_NAME", key) == 0)
|
||||
+ {
|
||||
+ title = value;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ options = blsuki_get_val (entry, ".cmdline", NULL);
|
||||
+
|
||||
+ argv = grub_zalloc (2 * sizeof (char *));
|
||||
+ if (argv == NULL)
|
||||
+ goto finish;
|
||||
+ argv[0] = title;
|
||||
+
|
||||
+ blsuki_save_default = grub_env_get_bool ("blsuki_save_default", false);
|
||||
+ src = grub_xasprintf ("%schainloader (%s)%s/%s%s%s\n",
|
||||
+ blsuki_save_default ? "savedefault\n" : "",
|
||||
+ entry->devid, entry->dirname,
|
||||
+ entry->filename,
|
||||
+ (options != NULL) ? " " : "",
|
||||
+ (options != NULL) ? options : "");
|
||||
+
|
||||
+ grub_normal_add_menu_entry (1, argv, NULL, id, NULL, NULL, NULL, src, 0, NULL, NULL, entry);
|
||||
+
|
||||
+ finish:
|
||||
+ grub_free (argv);
|
||||
+ grub_free (src);
|
||||
+ grub_free (options);
|
||||
+ grub_free (osrel);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
/*
|
||||
* This function fills a find_entry_info struct passed in by the info parameter.
|
||||
* If the dirname or devid parameters are set to NULL, the dirname and devid
|
||||
@@ -785,7 +1107,7 @@ bls_create_entry (grub_blsuki_entry_t *entry)
|
||||
* device.
|
||||
*/
|
||||
static grub_err_t
|
||||
-blsuki_set_find_entry_info (struct find_entry_info *info, const char *dirname, const char *devid)
|
||||
+blsuki_set_find_entry_info (struct find_entry_info *info, const char *dirname, const char *devid, enum blsuki_cmd_type cmd_type)
|
||||
{
|
||||
grub_device_t dev;
|
||||
grub_fs_t fs;
|
||||
@@ -795,10 +1117,23 @@ blsuki_set_find_entry_info (struct find_entry_info *info, const char *dirname, c
|
||||
|
||||
if (devid == NULL)
|
||||
{
|
||||
+ if (cmd_type == BLSUKI_BLS_CMD)
|
||||
+ {
|
||||
#ifdef GRUB_MACHINE_EMU
|
||||
- devid = "host";
|
||||
+ devid = "host";
|
||||
#else
|
||||
- devid = grub_env_get ("root");
|
||||
+ devid = grub_env_get ("root");
|
||||
+#endif
|
||||
+ }
|
||||
+#ifdef GRUB_MACHINE_EFI
|
||||
+ else if (cmd_type == BLSUKI_UKI_CMD)
|
||||
+ {
|
||||
+ grub_efi_loaded_image_t *image = grub_efi_get_loaded_image (grub_efi_image_handle);
|
||||
+
|
||||
+ if (image == NULL)
|
||||
+ return grub_error (GRUB_ERR_BAD_DEVICE, N_("unable to find boot device"));
|
||||
+ devid = grub_efidisk_get_device_name (image->device_handle);
|
||||
+ }
|
||||
#endif
|
||||
if (devid == NULL)
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable '%s' isn't set"), "root");
|
||||
@@ -837,15 +1172,16 @@ blsuki_set_find_entry_info (struct find_entry_info *info, const char *dirname, c
|
||||
}
|
||||
|
||||
/*
|
||||
- * This function searches for BLS config files based on the data in the info
|
||||
- * parameter. If the fallback option is enabled, the default location will be
|
||||
- * checked for BLS config files if the first attempt fails.
|
||||
+ * This function searches for BLS config files and UKIs based on the data in the
|
||||
+ * info parameter. If the fallback option is enabled, the default location will
|
||||
+ * be checked for BLS config files or UKIs if the first attempt fails.
|
||||
*/
|
||||
static grub_err_t
|
||||
-blsuki_find_entry (struct find_entry_info *info, bool enable_fallback)
|
||||
+blsuki_find_entry (struct find_entry_info *info, bool enable_fallback, enum blsuki_cmd_type cmd_type)
|
||||
{
|
||||
struct read_entry_info read_entry_info;
|
||||
char *default_dir = NULL;
|
||||
+ const char *cmd_dir = NULL;
|
||||
char *tmp;
|
||||
grub_size_t default_size;
|
||||
grub_fs_t dir_fs = NULL;
|
||||
@@ -862,6 +1198,7 @@ blsuki_find_entry (struct find_entry_info *info, bool enable_fallback)
|
||||
dir_dev = info->dev;
|
||||
dir_fs = info->fs;
|
||||
read_entry_info.devid = info->devid;
|
||||
+ read_entry_info.cmd_type = cmd_type;
|
||||
|
||||
r = dir_fs->fs_dir (dir_dev, read_entry_info.dirname, blsuki_read_entry,
|
||||
&read_entry_info);
|
||||
@@ -874,19 +1211,27 @@ blsuki_find_entry (struct find_entry_info *info, bool enable_fallback)
|
||||
/*
|
||||
* If we aren't able to find BLS entries in the directory given by info->dirname,
|
||||
* we can fallback to the default location "/boot/loader/entries/" and see if we
|
||||
- * can find the files there.
|
||||
+ * can find the files there. If we can't find UKI entries, fallback to
|
||||
+ * "/EFI/Linux" on the EFI system partition.
|
||||
*/
|
||||
if (entries == NULL && fallback == false && enable_fallback == true)
|
||||
{
|
||||
- default_size = sizeof (GRUB_BOOT_DEVICE) + sizeof (GRUB_BLS_CONFIG_PATH) - 1;
|
||||
+ if (cmd_type == BLSUKI_BLS_CMD)
|
||||
+ cmd_dir = GRUB_BLS_CONFIG_PATH;
|
||||
+#ifdef GRUB_MACHINE_EFI
|
||||
+ else if (cmd_type == BLSUKI_UKI_CMD)
|
||||
+ cmd_dir = GRUB_UKI_CONFIG_PATH;
|
||||
+#endif
|
||||
+
|
||||
+ default_size = sizeof (GRUB_BOOT_DEVICE) + grub_strlen (cmd_dir);
|
||||
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);
|
||||
+ tmp = grub_stpcpy (tmp, cmd_dir);
|
||||
|
||||
- blsuki_set_find_entry_info (info, default_dir, NULL);
|
||||
+ blsuki_set_find_entry_info (info, default_dir, NULL, cmd_type);
|
||||
grub_dprintf ("blsuki", "Entries weren't found in %s, fallback to %s\n",
|
||||
read_entry_info.dirname, info->dirname);
|
||||
fallback = true;
|
||||
@@ -901,15 +1246,17 @@ blsuki_find_entry (struct find_entry_info *info, bool enable_fallback)
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
-blsuki_load_entries (char *path, bool enable_fallback)
|
||||
+blsuki_load_entries (char *path, bool enable_fallback, enum blsuki_cmd_type cmd_type)
|
||||
{
|
||||
- grub_size_t len;
|
||||
+ grub_size_t len, ext_len = 0;
|
||||
static grub_err_t r;
|
||||
const char *devid = NULL;
|
||||
char *dir = NULL;
|
||||
char *default_dir = NULL;
|
||||
char *tmp;
|
||||
+ const char *cmd_dir = NULL;
|
||||
grub_size_t dir_size;
|
||||
+ const char *ext = NULL;
|
||||
struct find_entry_info info = {
|
||||
.dev = NULL,
|
||||
.fs = NULL,
|
||||
@@ -918,12 +1265,26 @@ blsuki_load_entries (char *path, bool enable_fallback)
|
||||
struct read_entry_info rei = {
|
||||
.devid = NULL,
|
||||
.dirname = NULL,
|
||||
+ .cmd_type = cmd_type,
|
||||
};
|
||||
|
||||
if (path != NULL)
|
||||
{
|
||||
+ if (cmd_type == BLSUKI_BLS_CMD)
|
||||
+ {
|
||||
+ ext = ".conf";
|
||||
+ ext_len = BLS_EXT_LEN;
|
||||
+ }
|
||||
+#ifdef GRUB_MACHINE_EFI
|
||||
+ else if (cmd_type == BLSUKI_UKI_CMD)
|
||||
+ {
|
||||
+ ext = ".efi";
|
||||
+ ext_len = UKI_EXT_LEN;
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
len = grub_strlen (path);
|
||||
- if (len >= BLS_EXT_LEN && grub_strcmp (path + len - BLS_EXT_LEN, ".conf") == 0)
|
||||
+ if (len >= ext_len && grub_strcmp (path + len - ext_len, ext) == 0)
|
||||
{
|
||||
rei.file = grub_file_open (path, GRUB_FILE_TYPE_CONFIG);
|
||||
if (rei.file == NULL)
|
||||
@@ -952,19 +1313,26 @@ blsuki_load_entries (char *path, bool enable_fallback)
|
||||
|
||||
if (dir == NULL)
|
||||
{
|
||||
- dir_size = sizeof (GRUB_BOOT_DEVICE) + sizeof (GRUB_BLS_CONFIG_PATH) - 2;
|
||||
+ if (cmd_type == BLSUKI_BLS_CMD)
|
||||
+ cmd_dir = GRUB_BLS_CONFIG_PATH;
|
||||
+#ifdef GRUB_MACHINE_EFI
|
||||
+ else if (cmd_type == BLSUKI_UKI_CMD)
|
||||
+ cmd_dir = GRUB_UKI_CONFIG_PATH;
|
||||
+#endif
|
||||
+
|
||||
+ dir_size = sizeof (GRUB_BOOT_DEVICE) + grub_strlen (cmd_dir);
|
||||
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);
|
||||
+ tmp = grub_stpcpy (tmp, cmd_dir);
|
||||
dir = default_dir;
|
||||
}
|
||||
|
||||
- r = blsuki_set_find_entry_info (&info, dir, devid);
|
||||
+ r = blsuki_set_find_entry_info (&info, dir, devid, cmd_type);
|
||||
if (r == GRUB_ERR_NONE)
|
||||
- r = blsuki_find_entry (&info, enable_fallback);
|
||||
+ r = blsuki_find_entry (&info, enable_fallback, cmd_type);
|
||||
|
||||
if (info.dev != NULL)
|
||||
grub_device_close (info.dev);
|
||||
@@ -1002,11 +1370,11 @@ blsuki_is_default_entry (const char *def_entry, grub_blsuki_entry_t *entry, int
|
||||
}
|
||||
|
||||
/*
|
||||
- * This function creates a GRUB boot menu entry for each BLS entry in the
|
||||
- * entries list.
|
||||
+ * This function creates a GRUB boot menu entry for each BLS or UKI entry in
|
||||
+ * the entries list.
|
||||
*/
|
||||
static grub_err_t
|
||||
-blsuki_create_entries (bool show_default, bool show_non_default, char *entry_id)
|
||||
+blsuki_create_entries (bool show_default, bool show_non_default, char *entry_id, enum blsuki_cmd_type cmd_type)
|
||||
{
|
||||
const char *def_entry = NULL;
|
||||
grub_blsuki_entry_t *entry = NULL;
|
||||
@@ -1025,7 +1393,12 @@ blsuki_create_entries (bool show_default, bool show_non_default, char *entry_id)
|
||||
(show_non_default == true && blsuki_is_default_entry (def_entry, entry, idx) == false) ||
|
||||
(entry_id != NULL && grub_strcmp (entry_id, entry->filename) == 0))
|
||||
{
|
||||
- bls_create_entry (entry);
|
||||
+ if (cmd_type == BLSUKI_BLS_CMD)
|
||||
+ bls_create_entry (entry);
|
||||
+#ifdef GRUB_MACHINE_EFI
|
||||
+ else if (cmd_type == BLSUKI_UKI_CMD)
|
||||
+ uki_create_entry (entry);
|
||||
+#endif
|
||||
entry->visible = true;
|
||||
}
|
||||
|
||||
@@ -1036,8 +1409,7 @@ blsuki_create_entries (bool show_default, bool show_non_default, char *entry_id)
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
-grub_cmd_blscfg (grub_extcmd_context_t ctxt, int argc __attribute__ ((unused)),
|
||||
- char **args __attribute__ ((unused)))
|
||||
+blsuki_cmd (grub_extcmd_context_t ctxt, enum blsuki_cmd_type cmd_type)
|
||||
{
|
||||
grub_err_t err;
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
@@ -1074,24 +1446,50 @@ grub_cmd_blscfg (grub_extcmd_context_t ctxt, int argc __attribute__ ((unused)),
|
||||
show_non_default = true;
|
||||
}
|
||||
|
||||
- err = blsuki_load_entries (path, enable_fallback);
|
||||
+ err = blsuki_load_entries (path, enable_fallback, cmd_type);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
|
||||
- return blsuki_create_entries (show_default, show_non_default, entry_id);
|
||||
+ return blsuki_create_entries (show_default, show_non_default, entry_id, cmd_type);
|
||||
+}
|
||||
+
|
||||
+static grub_err_t
|
||||
+grub_cmd_blscfg (grub_extcmd_context_t ctxt, int argc __attribute__ ((unused)),
|
||||
+ char **args __attribute__ ((unused)))
|
||||
+{
|
||||
+ return blsuki_cmd (ctxt, BLSUKI_BLS_CMD);
|
||||
}
|
||||
|
||||
static grub_extcmd_t bls_cmd;
|
||||
|
||||
+#ifdef GRUB_MACHINE_EFI
|
||||
+static grub_err_t
|
||||
+grub_cmd_uki (grub_extcmd_context_t ctxt, int argc __attribute__ ((unused)),
|
||||
+ char **args __attribute__ ((unused)))
|
||||
+{
|
||||
+ return blsuki_cmd (ctxt, BLSUKI_UKI_CMD);
|
||||
+}
|
||||
+
|
||||
+static grub_extcmd_t uki_cmd;
|
||||
+#endif
|
||||
+
|
||||
GRUB_MOD_INIT(blsuki)
|
||||
{
|
||||
bls_cmd = grub_register_extcmd ("blscfg", grub_cmd_blscfg, 0,
|
||||
N_("[-p|--path] [-f|--enable-fallback] DIR [-d|--show-default] [-n|--show-non-default] [-e|--entry] FILE"),
|
||||
N_("Import Boot Loader Specification snippets."),
|
||||
bls_opt);
|
||||
+#ifdef GRUB_MACHINE_EFI
|
||||
+ uki_cmd = grub_register_extcmd ("uki", grub_cmd_uki, 0,
|
||||
+ N_("[-p|--path] DIR [-f|--enable-fallback] [-d|--show-default] [-n|--show-non-default] [-e|--entry] FILE"),
|
||||
+ N_("Import Unified Kernel Images"), uki_opt);
|
||||
+#endif
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(blsuki)
|
||||
{
|
||||
grub_unregister_extcmd (bls_cmd);
|
||||
+#ifdef GRUB_MACHINE_EFI
|
||||
+ grub_unregister_extcmd (uki_cmd);
|
||||
+#endif
|
||||
}
|
||||
diff --git a/include/grub/menu.h b/include/grub/menu.h
|
||||
index 43a3c5809b..0e4978dc3b 100644
|
||||
--- a/include/grub/menu.h
|
||||
+++ b/include/grub/menu.h
|
||||
@@ -39,6 +39,8 @@ struct grub_blsuki_entry
|
||||
grub_size_t keyvals_size;
|
||||
int nkeyvals;
|
||||
char *filename;
|
||||
+ char *dirname;
|
||||
+ char *devid;
|
||||
bool visible;
|
||||
};
|
||||
typedef struct grub_blsuki_entry grub_blsuki_entry_t;
|
||||
|
|
@ -1,168 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Fri, 15 Nov 2024 15:34:29 +0800
|
||||
Subject: [PATCH] posix_wrap: Tweaks in preparation for libtasn1
|
||||
|
||||
Cc: Vladimir Serbinenko <phcoder@gmail.com>
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Signed-off-by: Gary Lin <glin@suse.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Tested-by: Stefan Berger <stefanb@linux.ibm.com>
|
||||
---
|
||||
grub-core/lib/posix_wrap/c-ctype.h | 114 +++++++++++++++++++++++++++++++++++++
|
||||
grub-core/lib/posix_wrap/string.h | 21 +++++++
|
||||
2 files changed, 135 insertions(+)
|
||||
create mode 100644 grub-core/lib/posix_wrap/c-ctype.h
|
||||
|
||||
diff --git a/grub-core/lib/posix_wrap/c-ctype.h b/grub-core/lib/posix_wrap/c-ctype.h
|
||||
new file mode 100644
|
||||
index 0000000000..5f8fc8ce3f
|
||||
--- /dev/null
|
||||
+++ b/grub-core/lib/posix_wrap/c-ctype.h
|
||||
@@ -0,0 +1,114 @@
|
||||
+/*
|
||||
+ * GRUB -- GRand Unified Bootloader
|
||||
+ * Copyright (C) 2024 Free Software Foundation, Inc.
|
||||
+ *
|
||||
+ * GRUB is free software: you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License as published by
|
||||
+ * the Free Software Foundation, either version 3 of the License, or
|
||||
+ * (at your option) any later version.
|
||||
+ *
|
||||
+ * GRUB is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
+ */
|
||||
+
|
||||
+#ifndef GRUB_POSIX_C_CTYPE_H
|
||||
+#define GRUB_POSIX_C_CTYPE_H 1
|
||||
+
|
||||
+#include <grub/misc.h>
|
||||
+
|
||||
+static inline bool
|
||||
+c_isspace (int c)
|
||||
+{
|
||||
+ return !!grub_isspace (c);
|
||||
+}
|
||||
+
|
||||
+static inline bool
|
||||
+c_isdigit (int c)
|
||||
+{
|
||||
+ return !!grub_isdigit (c);
|
||||
+}
|
||||
+
|
||||
+static inline bool
|
||||
+c_islower (int c)
|
||||
+{
|
||||
+ return !!grub_islower (c);
|
||||
+}
|
||||
+
|
||||
+static inline bool
|
||||
+c_isascii (int c)
|
||||
+{
|
||||
+ return !(c & ~0x7f);
|
||||
+}
|
||||
+
|
||||
+static inline bool
|
||||
+c_isupper (int c)
|
||||
+{
|
||||
+ return !!grub_isupper (c);
|
||||
+}
|
||||
+
|
||||
+static inline bool
|
||||
+c_isxdigit (int c)
|
||||
+{
|
||||
+ return !!grub_isxdigit (c);
|
||||
+}
|
||||
+
|
||||
+static inline bool
|
||||
+c_isprint (int c)
|
||||
+{
|
||||
+ return !!grub_isprint (c);
|
||||
+}
|
||||
+
|
||||
+static inline bool
|
||||
+c_iscntrl (int c)
|
||||
+{
|
||||
+ return !grub_isprint (c);
|
||||
+}
|
||||
+
|
||||
+static inline bool
|
||||
+c_isgraph (int c)
|
||||
+{
|
||||
+ return grub_isprint (c) && !grub_isspace (c);
|
||||
+}
|
||||
+
|
||||
+static inline bool
|
||||
+c_isalnum (int c)
|
||||
+{
|
||||
+ return grub_isalpha (c) || grub_isdigit (c);
|
||||
+}
|
||||
+
|
||||
+static inline bool
|
||||
+c_ispunct (int c)
|
||||
+{
|
||||
+ return grub_isprint (c) && !grub_isspace (c) && !c_isalnum (c);
|
||||
+}
|
||||
+
|
||||
+static inline bool
|
||||
+c_isalpha (int c)
|
||||
+{
|
||||
+ return !!grub_isalpha (c);
|
||||
+}
|
||||
+
|
||||
+static inline bool
|
||||
+c_isblank (int c)
|
||||
+{
|
||||
+ return c == ' ' || c == '\t';
|
||||
+}
|
||||
+
|
||||
+static inline int
|
||||
+c_tolower (int c)
|
||||
+{
|
||||
+ return grub_tolower (c);
|
||||
+}
|
||||
+
|
||||
+static inline int
|
||||
+c_toupper (int c)
|
||||
+{
|
||||
+ return grub_toupper (c);
|
||||
+}
|
||||
+
|
||||
+#endif
|
||||
diff --git a/grub-core/lib/posix_wrap/string.h b/grub-core/lib/posix_wrap/string.h
|
||||
index 1adb450b5a..d3e400d500 100644
|
||||
--- a/grub-core/lib/posix_wrap/string.h
|
||||
+++ b/grub-core/lib/posix_wrap/string.h
|
||||
@@ -84,6 +84,27 @@ memchr (const void *s, int c, grub_size_t n)
|
||||
return grub_memchr (s, c, n);
|
||||
}
|
||||
|
||||
+static inline char *
|
||||
+strncat (char *dest, const char *src, grub_size_t n)
|
||||
+{
|
||||
+ const char *end;
|
||||
+ char *str = dest;
|
||||
+ grub_size_t src_len;
|
||||
+
|
||||
+ dest += grub_strlen (dest);
|
||||
+
|
||||
+ end = grub_memchr (src, '\0', n);
|
||||
+ if (end != NULL)
|
||||
+ src_len = (grub_size_t) (end - src);
|
||||
+ else
|
||||
+ src_len = n;
|
||||
+
|
||||
+ dest[src_len] = '\0';
|
||||
+ grub_memcpy (dest, src, src_len);
|
||||
+
|
||||
+ return str;
|
||||
+}
|
||||
+
|
||||
#define memcmp grub_memcmp
|
||||
#define memcpy grub_memcpy
|
||||
#define memmove grub_memmove
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Leo Sandoval <lsandova@redhat.com>
|
||||
Date: Thu, 13 Nov 2025 11:57:52 -0600
|
||||
Subject: [PATCH] blsuki: do not register blscfg command
|
||||
|
||||
The blscfg command is already defined on commands/blscfg.c so do not
|
||||
register it on blsuki.c. Also, the 'uki' command is only intended for
|
||||
EFI system so remove the other platforms from the module.
|
||||
|
||||
Signed-off-by: Leo Sandoval <lsandova@redhat.com>
|
||||
---
|
||||
grub-core/Makefile.core.def | 2 --
|
||||
grub-core/commands/blsuki.c | 4 ----
|
||||
2 files changed, 6 deletions(-)
|
||||
|
||||
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
|
||||
index 885dd436de..a545ee430b 100644
|
||||
--- a/grub-core/Makefile.core.def
|
||||
+++ b/grub-core/Makefile.core.def
|
||||
@@ -893,8 +893,6 @@ module = {
|
||||
common = lib/gnulib/filevercmp.c;
|
||||
enable = powerpc_ieee1275;
|
||||
enable = efi;
|
||||
- enable = i386_pc;
|
||||
- enable = emu;
|
||||
cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)';
|
||||
cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB)';
|
||||
};
|
||||
diff --git a/grub-core/commands/blsuki.c b/grub-core/commands/blsuki.c
|
||||
index cb00f936a7..bcd0114d85 100644
|
||||
--- a/grub-core/commands/blsuki.c
|
||||
+++ b/grub-core/commands/blsuki.c
|
||||
@@ -1475,10 +1475,6 @@ static grub_extcmd_t uki_cmd;
|
||||
|
||||
GRUB_MOD_INIT(blsuki)
|
||||
{
|
||||
- bls_cmd = grub_register_extcmd ("blscfg", grub_cmd_blscfg, 0,
|
||||
- N_("[-p|--path] [-f|--enable-fallback] DIR [-d|--show-default] [-n|--show-non-default] [-e|--entry] FILE"),
|
||||
- N_("Import Boot Loader Specification snippets."),
|
||||
- bls_opt);
|
||||
#ifdef GRUB_MACHINE_EFI
|
||||
uki_cmd = grub_register_extcmd ("uki", grub_cmd_uki, 0,
|
||||
N_("[-p|--path] DIR [-f|--enable-fallback] [-d|--show-default] [-n|--show-non-default] [-e|--entry] FILE"),
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Chang via Grub-devel <grub-devel@gnu.org>
|
||||
Date: Fri, 17 Oct 2025 17:01:32 +0800
|
||||
Subject: [PATCH] misc: add z length modifier support
|
||||
|
||||
Add support for the 'z' length modifier in the printf code. This allows
|
||||
printing of size_t and ssize_t values using %zu, %zd and related
|
||||
formats. The parser maps 'z' to the correct integer width based on
|
||||
sizeof (size_t).
|
||||
|
||||
Signed-off-by: Michael Chang <mchang@suse.com>
|
||||
Reviewed-by: Neal Gompa <ngompa13@gmail.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/kern/misc.c | 20 ++++++++++++++++++++
|
||||
1 file changed, 20 insertions(+)
|
||||
|
||||
diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
|
||||
index c1c77c300c..2568a5489b 100644
|
||||
--- a/grub-core/kern/misc.c
|
||||
+++ b/grub-core/kern/misc.c
|
||||
@@ -30,6 +30,7 @@
|
||||
#if DEBUG_WITH_TIMESTAMPS
|
||||
#include <grub/time.h>
|
||||
#endif
|
||||
+#include <stddef.h>
|
||||
|
||||
union printf_arg
|
||||
{
|
||||
@@ -883,6 +884,9 @@ parse_printf_arg_fmt (const char *fmt0, struct printf_args *args,
|
||||
COMPILE_TIME_ASSERT (sizeof (long) <= sizeof (long long));
|
||||
COMPILE_TIME_ASSERT (sizeof (long long) == sizeof (void *)
|
||||
|| sizeof (int) == sizeof (void *));
|
||||
+ COMPILE_TIME_ASSERT (sizeof (size_t) == sizeof (unsigned)
|
||||
+ || sizeof (size_t) == sizeof (unsigned long)
|
||||
+ || sizeof (size_t) == sizeof (unsigned long long));
|
||||
|
||||
fmt = fmt0;
|
||||
while ((c = *fmt++) != 0)
|
||||
@@ -917,11 +921,17 @@ parse_printf_arg_fmt (const char *fmt0, struct printf_args *args,
|
||||
fmt++;
|
||||
|
||||
c = *fmt++;
|
||||
+ if (c == 'z')
|
||||
+ {
|
||||
+ c = *fmt++;
|
||||
+ goto do_count;
|
||||
+ }
|
||||
if (c == 'l')
|
||||
c = *fmt++;
|
||||
if (c == 'l')
|
||||
c = *fmt++;
|
||||
|
||||
+ do_count:
|
||||
switch (c)
|
||||
{
|
||||
case 'p':
|
||||
@@ -1018,6 +1028,14 @@ parse_printf_arg_fmt (const char *fmt0, struct printf_args *args,
|
||||
continue;
|
||||
}
|
||||
|
||||
+ if (c == 'z')
|
||||
+ {
|
||||
+ c = *fmt++;
|
||||
+ if (sizeof (size_t) == sizeof (unsigned long))
|
||||
+ longfmt = 1;
|
||||
+ else if (sizeof (size_t) == sizeof (unsigned long long))
|
||||
+ longfmt = 2;
|
||||
+ }
|
||||
if (c == 'l')
|
||||
{
|
||||
c = *fmt++;
|
||||
@@ -1194,6 +1212,8 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0,
|
||||
}
|
||||
|
||||
c = *fmt++;
|
||||
+ if (c == 'z')
|
||||
+ c = *fmt++;
|
||||
if (c == 'l')
|
||||
c = *fmt++;
|
||||
if (c == 'l')
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Chang via Grub-devel <grub-devel@gnu.org>
|
||||
Date: Fri, 17 Oct 2025 17:01:33 +0800
|
||||
Subject: [PATCH] tests: add z modifier printf tests
|
||||
|
||||
Add unit tests for %zd, %zu and %zx to verify size_t and ssize_t
|
||||
formatting matches system snprintf.
|
||||
|
||||
Signed-off-by: Michael Chang <mchang@suse.com>
|
||||
Reviewed-by: Neal Gompa <ngompa13@gmail.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
tests/printf_unit_test.c | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
diff --git a/tests/printf_unit_test.c b/tests/printf_unit_test.c
|
||||
index 098c29fd9c..f2de187b03 100644
|
||||
--- a/tests/printf_unit_test.c
|
||||
+++ b/tests/printf_unit_test.c
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <string.h>
|
||||
#include <grub/test.h>
|
||||
#include <grub/misc.h>
|
||||
+#include <stdint.h>
|
||||
|
||||
#define MSG "printf test failed: %s, %s", real, expected
|
||||
|
||||
@@ -73,6 +74,15 @@ printf_test (void)
|
||||
grub_snprintf (real, sizeof (real), "%%0%dd ", 1);
|
||||
snprintf (expected, sizeof (expected), "%%0%dd ", 1);
|
||||
grub_test_assert (strcmp (real, expected) == 0, MSG);
|
||||
+ grub_snprintf (real, sizeof (real), "%zd %zd %zd", (ssize_t) -1, (ssize_t) (SIZE_MAX >> 1), (ssize_t) 42);
|
||||
+ snprintf (expected, sizeof (expected), "%zd %zd %zd", (ssize_t) -1, (ssize_t) (SIZE_MAX >> 1), (ssize_t) 42);
|
||||
+ grub_test_assert (strcmp (real, expected) == 0, MSG);
|
||||
+ grub_snprintf (real, sizeof (real), "%zu %zu %zu", (size_t) 0, (size_t) SIZE_MAX, (size_t) 42);
|
||||
+ snprintf (expected, sizeof (expected), "%zu %zu %zu", (size_t) 0, (size_t) SIZE_MAX, (size_t) 42);
|
||||
+ grub_test_assert (strcmp (real, expected) == 0, MSG);
|
||||
+ grub_snprintf (real, sizeof (real), "%zx %zx %zx", (ssize_t) (SIZE_MAX >> 1), (size_t) SIZE_MAX, (size_t) 0xdeadbeefU);
|
||||
+ snprintf (expected, sizeof (expected), "%zx %zx %zx", (ssize_t) (SIZE_MAX >> 1), (size_t) SIZE_MAX, (size_t) 0xdeadbeefU);
|
||||
+ grub_test_assert (strcmp (real, expected) == 0, MSG);
|
||||
}
|
||||
|
||||
GRUB_UNIT_TEST ("printf_unit_test", printf_test);
|
||||
|
|
@ -1,219 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Chang via Grub-devel <grub-devel@gnu.org>
|
||||
Date: Fri, 17 Oct 2025 17:01:34 +0800
|
||||
Subject: [PATCH] util/grub-editenv: add fs_envblk open helper
|
||||
|
||||
This patch adds the logic to locate and open an environment block that
|
||||
is stored in a reserved area on the device. It introduces the function
|
||||
fs_envblk_open() together with helper routines to read the block pointed
|
||||
to by the env_block variable, and to create the block on disk when it
|
||||
does not exist yet. When a block is created, the code records its
|
||||
location inside the file based envblk by setting env_block in block list
|
||||
syntax of offset plus size in sectors.
|
||||
|
||||
The env_block variable acts as a link from the file envblk to the raw
|
||||
disk region so that later runs of grub-editenv can follow it and access
|
||||
the external block. The helper is exposed through a small ops table
|
||||
attached to fs_envblk so that later patches can call
|
||||
fs_envblk->ops->open() without touching core code again. At this stage
|
||||
variables are still stored in the file envblk and no redirection has
|
||||
been applied.
|
||||
|
||||
In relation to this, the fs_envblk_spec table defines the file-system
|
||||
specific layout of the reserved raw blocks used for environment storage.
|
||||
It is prepared to facilitate integration in grub-editenv, with Btrfs to
|
||||
be added in the future once its reserved area is defined.
|
||||
|
||||
An fs_envblk_init() helper is added to prepare it for using the ops with
|
||||
its associated data context if the feature is available. It is not used
|
||||
yet, but will be used later when a filesystem and its device are probed
|
||||
to initialize the fs_envblk handle and enable access to the feature.
|
||||
|
||||
Signed-off-by: Michael Chang <mchang@suse.com>
|
||||
Reviewed-by: Neal Gompa <ngompa13@gmail.com>
|
||||
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
||||
---
|
||||
util/grub-editenv.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 170 insertions(+)
|
||||
|
||||
diff --git a/util/grub-editenv.c b/util/grub-editenv.c
|
||||
index 948eec8a11..a544452e78 100644
|
||||
--- a/util/grub-editenv.c
|
||||
+++ b/util/grub-editenv.c
|
||||
@@ -123,6 +123,176 @@ block, use `rm %s'."),
|
||||
NULL, help_filter, NULL
|
||||
};
|
||||
|
||||
+struct fs_envblk_spec {
|
||||
+ const char *fs_name;
|
||||
+ off_t offset;
|
||||
+ size_t size;
|
||||
+};
|
||||
+typedef struct fs_envblk_spec fs_envblk_spec_t;
|
||||
+
|
||||
+static grub_envblk_t fs_envblk_open (grub_envblk_t envblk);
|
||||
+
|
||||
+struct fs_envblk_ops {
|
||||
+ grub_envblk_t (*open) (grub_envblk_t);
|
||||
+};
|
||||
+typedef struct fs_envblk_ops fs_envblk_ops_t;
|
||||
+
|
||||
+struct fs_envblk {
|
||||
+ fs_envblk_spec_t *spec;
|
||||
+ fs_envblk_ops_t *ops;
|
||||
+ const char *dev;
|
||||
+};
|
||||
+typedef struct fs_envblk *fs_envblk_t;
|
||||
+
|
||||
+static fs_envblk_ops_t fs_envblk_ops = {
|
||||
+ .open = fs_envblk_open
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * fs_envblk_spec describes the file-system specific layout of reserved raw
|
||||
+ * blocks used as environment blocks.
|
||||
+ */
|
||||
+static fs_envblk_spec_t fs_envblk_spec[] = {
|
||||
+ { NULL, 0, 0 }
|
||||
+};
|
||||
+
|
||||
+static fs_envblk_t fs_envblk = NULL;
|
||||
+
|
||||
+static void __attribute__ ((unused))
|
||||
+fs_envblk_init (const char *fs_name, const char *dev)
|
||||
+{
|
||||
+ fs_envblk_spec_t *p;
|
||||
+
|
||||
+ if (fs_name == NULL || dev == NULL)
|
||||
+ return;
|
||||
+
|
||||
+ for (p = fs_envblk_spec; p->fs_name != NULL; p++)
|
||||
+ {
|
||||
+ if (strcmp (fs_name, p->fs_name) == 0)
|
||||
+ {
|
||||
+ if (fs_envblk == NULL)
|
||||
+ fs_envblk = xmalloc (sizeof (*fs_envblk));
|
||||
+ fs_envblk->spec = p;
|
||||
+ fs_envblk->dev = xstrdup (dev);
|
||||
+ fs_envblk->ops = &fs_envblk_ops;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+read_env_block_var (const char *varname, const char *value, void *hook_data)
|
||||
+{
|
||||
+ grub_envblk_t *p_envblk = (grub_envblk_t *) hook_data;
|
||||
+ off_t off;
|
||||
+ size_t sz;
|
||||
+ char *p, *buf;
|
||||
+ FILE *fp;
|
||||
+
|
||||
+ if (p_envblk == NULL || fs_envblk == NULL)
|
||||
+ return 1;
|
||||
+
|
||||
+ if (strcmp (varname, "env_block") != 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ off = strtol (value, &p, 10);
|
||||
+ if (*p == '+')
|
||||
+ sz = strtol (p + 1, &p, 10);
|
||||
+ else
|
||||
+ return 0;
|
||||
+
|
||||
+ if (*p != '\0' || sz == 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ off <<= GRUB_DISK_SECTOR_BITS;
|
||||
+ sz <<= GRUB_DISK_SECTOR_BITS;
|
||||
+
|
||||
+ fp = grub_util_fopen (fs_envblk->dev, "rb");
|
||||
+ if (fp == NULL)
|
||||
+ grub_util_error (_("cannot open `%s': %s"), fs_envblk->dev, strerror (errno));
|
||||
+
|
||||
+ if (fseek (fp, off, SEEK_SET) < 0)
|
||||
+ grub_util_error (_("cannot seek `%s': %s"), fs_envblk->dev, strerror (errno));
|
||||
+
|
||||
+ buf = xmalloc (sz);
|
||||
+ if ((fread (buf, 1, sz, fp)) != sz)
|
||||
+ grub_util_error (_("cannot read `%s': %s"), fs_envblk->dev, strerror (errno));
|
||||
+
|
||||
+ fclose (fp);
|
||||
+
|
||||
+ *p_envblk = grub_envblk_open (buf, sz);
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+create_env_on_block (void)
|
||||
+{
|
||||
+ FILE *fp;
|
||||
+ char *buf;
|
||||
+ const char *device;
|
||||
+ off_t offset;
|
||||
+ size_t size;
|
||||
+
|
||||
+ if (fs_envblk == NULL)
|
||||
+ return;
|
||||
+
|
||||
+ device = fs_envblk->dev;
|
||||
+ offset = fs_envblk->spec->offset;
|
||||
+ size = fs_envblk->spec->size;
|
||||
+
|
||||
+ fp = grub_util_fopen (device, "r+b");
|
||||
+ if (fp == NULL)
|
||||
+ grub_util_error (_("cannot open `%s': %s"), device, strerror (errno));
|
||||
+
|
||||
+ buf = xmalloc (size);
|
||||
+ memcpy (buf, GRUB_ENVBLK_SIGNATURE, sizeof (GRUB_ENVBLK_SIGNATURE) - 1);
|
||||
+ memset (buf + sizeof (GRUB_ENVBLK_SIGNATURE) - 1, '#', size - sizeof (GRUB_ENVBLK_SIGNATURE) + 1);
|
||||
+
|
||||
+ if (fseek (fp, offset, SEEK_SET) < 0)
|
||||
+ grub_util_error (_("cannot seek `%s': %s"), device, strerror (errno));
|
||||
+
|
||||
+ if (fwrite (buf, 1, size, fp) != size)
|
||||
+ grub_util_error (_("cannot write to `%s': %s"), device, strerror (errno));
|
||||
+
|
||||
+ grub_util_file_sync (fp);
|
||||
+ free (buf);
|
||||
+ fclose (fp);
|
||||
+}
|
||||
+
|
||||
+static grub_envblk_t
|
||||
+fs_envblk_open (grub_envblk_t envblk)
|
||||
+{
|
||||
+ grub_envblk_t envblk_on_block = NULL;
|
||||
+ char *val;
|
||||
+ off_t offset;
|
||||
+ size_t size;
|
||||
+
|
||||
+ if (envblk == NULL)
|
||||
+ return NULL;
|
||||
+
|
||||
+ offset = fs_envblk->spec->offset;
|
||||
+ size = fs_envblk->spec->size;
|
||||
+
|
||||
+ grub_envblk_iterate (envblk, &envblk_on_block, read_env_block_var);
|
||||
+
|
||||
+ if (envblk_on_block != NULL && grub_envblk_size (envblk_on_block) == size)
|
||||
+ return envblk_on_block;
|
||||
+
|
||||
+ create_env_on_block ();
|
||||
+
|
||||
+ offset = offset >> GRUB_DISK_SECTOR_BITS;
|
||||
+ size = (size + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS;
|
||||
+
|
||||
+ val = xasprintf ("%lld+%zu", (long long) offset, size);
|
||||
+ if (grub_envblk_set (envblk, "env_block", val) == 0)
|
||||
+ grub_util_error ("%s", _("environment block too small"));
|
||||
+ grub_envblk_iterate (envblk, &envblk_on_block, read_env_block_var);
|
||||
+ free (val);
|
||||
+
|
||||
+ return envblk_on_block;
|
||||
+}
|
||||
+
|
||||
static grub_envblk_t
|
||||
open_envblk_file (const char *name)
|
||||
{
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Chang via Grub-devel <grub-devel@gnu.org>
|
||||
Date: Fri, 17 Oct 2025 17:01:35 +0800
|
||||
Subject: [PATCH] util/grub-editenv: add fs_envblk write helper
|
||||
|
||||
This patch adds the function fs_envblk_write to update the reserved
|
||||
environment block on disk. The helper takes an in memory envblk buffer
|
||||
and writes it back to the device at the location defined by the
|
||||
fs_envblk specification. It performs size checks and uses file sync to
|
||||
ensure that the updated data is flushed.
|
||||
|
||||
The helper is also added into the fs_envblk ops table, together with the
|
||||
open helper from the previous patch. With this change the basic input
|
||||
and output path for an external environment block is complete. The
|
||||
choice of which variables should be written externally will be handled
|
||||
by later patches.
|
||||
|
||||
Signed-off-by: Michael Chang <mchang@suse.com>
|
||||
Reviewed-by: Neal Gompa <ngompa13@gmail.com>
|
||||
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
util/grub-editenv.c | 38 +++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 37 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/util/grub-editenv.c b/util/grub-editenv.c
|
||||
index a544452e78..f4b69bb19f 100644
|
||||
--- a/util/grub-editenv.c
|
||||
+++ b/util/grub-editenv.c
|
||||
@@ -131,9 +131,11 @@ struct fs_envblk_spec {
|
||||
typedef struct fs_envblk_spec fs_envblk_spec_t;
|
||||
|
||||
static grub_envblk_t fs_envblk_open (grub_envblk_t envblk);
|
||||
+static void fs_envblk_write (grub_envblk_t envblk);
|
||||
|
||||
struct fs_envblk_ops {
|
||||
grub_envblk_t (*open) (grub_envblk_t);
|
||||
+ void (*write) (grub_envblk_t);
|
||||
};
|
||||
typedef struct fs_envblk_ops fs_envblk_ops_t;
|
||||
|
||||
@@ -145,7 +147,8 @@ struct fs_envblk {
|
||||
typedef struct fs_envblk *fs_envblk_t;
|
||||
|
||||
static fs_envblk_ops_t fs_envblk_ops = {
|
||||
- .open = fs_envblk_open
|
||||
+ .open = fs_envblk_open,
|
||||
+ .write = fs_envblk_write
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -381,6 +384,39 @@ write_envblk (const char *name, grub_envblk_t envblk)
|
||||
fclose (fp);
|
||||
}
|
||||
|
||||
+static void
|
||||
+fs_envblk_write (grub_envblk_t envblk)
|
||||
+{
|
||||
+ FILE *fp;
|
||||
+ const char *device;
|
||||
+ off_t offset;
|
||||
+ size_t size;
|
||||
+
|
||||
+ if (envblk == NULL)
|
||||
+ return;
|
||||
+
|
||||
+ device = fs_envblk->dev;
|
||||
+ offset = fs_envblk->spec->offset;
|
||||
+ size = fs_envblk->spec->size;
|
||||
+
|
||||
+ if (grub_envblk_size (envblk) > size)
|
||||
+ grub_util_error ("%s", _("environment block too small"));
|
||||
+
|
||||
+ fp = grub_util_fopen (device, "r+b");
|
||||
+
|
||||
+ if (fp == NULL)
|
||||
+ grub_util_error (_("cannot open `%s': %s"), device, strerror (errno));
|
||||
+
|
||||
+ if (fseek (fp, offset, SEEK_SET) < 0)
|
||||
+ grub_util_error (_("cannot seek `%s': %s"), device, strerror (errno));
|
||||
+
|
||||
+ if (fwrite (grub_envblk_buffer (envblk), 1, grub_envblk_size (envblk), fp) != grub_envblk_size (envblk))
|
||||
+ grub_util_error (_("cannot write to `%s': %s"), device, strerror (errno));
|
||||
+
|
||||
+ grub_util_file_sync (fp);
|
||||
+ fclose (fp);
|
||||
+}
|
||||
+
|
||||
static void
|
||||
set_variables (const char *name, int argc, char *argv[])
|
||||
{
|
||||
|
|
@ -1,118 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Chang via Grub-devel <grub-devel@gnu.org>
|
||||
Date: Fri, 17 Oct 2025 17:01:36 +0800
|
||||
Subject: [PATCH] util/grub-editenv: wire set_variables to optional fs_envblk
|
||||
|
||||
This patch changes set_variables() so that it can use an external
|
||||
environment block when one is present. The variable next_entry is
|
||||
written into the external block, env_block is treated as read only, and
|
||||
all other variables are written into the normal file based envblk.
|
||||
|
||||
A cleanup step is added to handle cases where GRUB at runtime writes
|
||||
variables into the external block because file based updates are not
|
||||
safe on a copy on write filesystem such as Btrfs. For example, the
|
||||
savedefault command can update saved_entry, and on Btrfs GRUB will place
|
||||
that update in the external block instead of the file envblk. If an
|
||||
older copy remains in the external block, it would override the newer
|
||||
value from the file envblk when GRUB first loads the file and then
|
||||
applies the external block on top of it. To avoid this, whenever a
|
||||
variable is updated in the file envblk, any same named key in the
|
||||
external block is deleted.
|
||||
|
||||
Signed-off-by: Michael Chang <mchang@suse.com>
|
||||
Reviewed-by: Neal Gompa <ngompa13@gmail.com>
|
||||
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
util/grub-editenv.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 56 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/util/grub-editenv.c b/util/grub-editenv.c
|
||||
index f4b69bb19f..be844bf902 100644
|
||||
--- a/util/grub-editenv.c
|
||||
+++ b/util/grub-editenv.c
|
||||
@@ -417,12 +417,35 @@ fs_envblk_write (grub_envblk_t envblk)
|
||||
fclose (fp);
|
||||
}
|
||||
|
||||
+struct var_lookup_ctx {
|
||||
+ const char *varname;
|
||||
+ bool found;
|
||||
+};
|
||||
+typedef struct var_lookup_ctx var_lookup_ctx_t;
|
||||
+
|
||||
+static int
|
||||
+var_lookup_iter (const char *varname, const char *value __attribute__ ((unused)), void *hook_data)
|
||||
+{
|
||||
+ var_lookup_ctx_t *ctx = (var_lookup_ctx_t *) hook_data;
|
||||
+
|
||||
+ if (grub_strcmp (ctx->varname, varname) == 0)
|
||||
+ {
|
||||
+ ctx->found = true;
|
||||
+ return 1;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static void
|
||||
set_variables (const char *name, int argc, char *argv[])
|
||||
{
|
||||
grub_envblk_t envblk;
|
||||
+ grub_envblk_t envblk_on_block = NULL;
|
||||
|
||||
envblk = open_envblk_file (name);
|
||||
+ if (fs_envblk != NULL)
|
||||
+ envblk_on_block = fs_envblk->ops->open (envblk);
|
||||
+
|
||||
while (argc)
|
||||
{
|
||||
char *p;
|
||||
@@ -433,15 +456,46 @@ set_variables (const char *name, int argc, char *argv[])
|
||||
|
||||
*(p++) = 0;
|
||||
|
||||
- if (! grub_envblk_set (envblk, argv[0], p))
|
||||
- grub_util_error ("%s", _("environment block too small"));
|
||||
+ if ((strcmp (argv[0], "next_entry") == 0) && envblk_on_block != NULL)
|
||||
+ {
|
||||
+ if (grub_envblk_set (envblk_on_block, argv[0], p) == 0)
|
||||
+ grub_util_error ("%s", _("environment block too small"));
|
||||
+ goto next;
|
||||
+ }
|
||||
|
||||
+ if (strcmp (argv[0], "env_block") == 0)
|
||||
+ {
|
||||
+ grub_util_warn (_("can't set env_block as it's read-only"));
|
||||
+ goto next;
|
||||
+ }
|
||||
+
|
||||
+ if (grub_envblk_set (envblk, argv[0], p) == 0)
|
||||
+ grub_util_error ("%s", _("environment block too small"));
|
||||
+
|
||||
+ if (envblk_on_block != NULL)
|
||||
+ {
|
||||
+ var_lookup_ctx_t ctx = {
|
||||
+ .varname = argv[0],
|
||||
+ .found = false
|
||||
+ };
|
||||
+
|
||||
+ grub_envblk_iterate (envblk_on_block, &ctx, var_lookup_iter);
|
||||
+ if (ctx.found == true)
|
||||
+ grub_envblk_delete (envblk_on_block, argv[0]);
|
||||
+ }
|
||||
+ next:
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
write_envblk (name, envblk);
|
||||
grub_envblk_close (envblk);
|
||||
+
|
||||
+ if (envblk_on_block != NULL)
|
||||
+ {
|
||||
+ fs_envblk->ops->write (envblk_on_block);
|
||||
+ grub_envblk_close (envblk_on_block);
|
||||
+ }
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Chang via Grub-devel <grub-devel@gnu.org>
|
||||
Date: Fri, 17 Oct 2025 17:01:37 +0800
|
||||
Subject: [PATCH] util/grub-editenv: wire unset_variables to optional fs_envblk
|
||||
|
||||
This patch updates unset_variables() so that removals are also applied
|
||||
to the external environment block when it is present. The code opens the
|
||||
external block, deletes the same named keys there, and then writes the
|
||||
external block back using fs_envblk_write(). The file based envblk is
|
||||
still updated and written as before.
|
||||
|
||||
Signed-off-by: Michael Chang <mchang@suse.com>
|
||||
Reviewed-by: Neal Gompa <ngompa13@gmail.com>
|
||||
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
util/grub-editenv.c | 14 ++++++++++++++
|
||||
1 file changed, 14 insertions(+)
|
||||
|
||||
diff --git a/util/grub-editenv.c b/util/grub-editenv.c
|
||||
index be844bf902..7ff1da9b40 100644
|
||||
--- a/util/grub-editenv.c
|
||||
+++ b/util/grub-editenv.c
|
||||
@@ -502,18 +502,32 @@ static void
|
||||
unset_variables (const char *name, int argc, char *argv[])
|
||||
{
|
||||
grub_envblk_t envblk;
|
||||
+ grub_envblk_t envblk_on_block = NULL;
|
||||
|
||||
envblk = open_envblk_file (name);
|
||||
+
|
||||
+ if (fs_envblk != NULL)
|
||||
+ envblk_on_block = fs_envblk->ops->open (envblk);
|
||||
+
|
||||
while (argc)
|
||||
{
|
||||
grub_envblk_delete (envblk, argv[0]);
|
||||
|
||||
+ if (envblk_on_block != NULL)
|
||||
+ grub_envblk_delete (envblk_on_block, argv[0]);
|
||||
+
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
write_envblk (name, envblk);
|
||||
grub_envblk_close (envblk);
|
||||
+
|
||||
+ if (envblk_on_block != NULL)
|
||||
+ {
|
||||
+ fs_envblk->ops->write (envblk_on_block);
|
||||
+ grub_envblk_close (envblk_on_block);
|
||||
+ }
|
||||
}
|
||||
|
||||
struct get_int_value_params {
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Chang via Grub-devel <grub-devel@gnu.org>
|
||||
Date: Fri, 17 Oct 2025 17:01:38 +0800
|
||||
Subject: [PATCH] util/grub-editenv: wire list_variables to optional fs_envblk
|
||||
|
||||
This patch updates list_variables() so that it also prints entries from
|
||||
the external environment block when one is present. The function first
|
||||
lists all variables from the file based envblk, then iterates over the
|
||||
external envblk and prints those as well.
|
||||
|
||||
The output format remains the same as before. The change makes it
|
||||
possible to inspect variables regardless of whether they are stored in
|
||||
the file envblk or in the reserved block.
|
||||
|
||||
Signed-off-by: Michael Chang <mchang@suse.com>
|
||||
Reviewed-by: Neal Gompa <ngompa13@gmail.com>
|
||||
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
||||
Reviewed-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
util/grub-editenv.c | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
diff --git a/util/grub-editenv.c b/util/grub-editenv.c
|
||||
index 7ff1da9b40..170d8f139a 100644
|
||||
--- a/util/grub-editenv.c
|
||||
+++ b/util/grub-editenv.c
|
||||
@@ -358,10 +358,17 @@ static void
|
||||
list_variables (const char *name)
|
||||
{
|
||||
grub_envblk_t envblk;
|
||||
+ grub_envblk_t envblk_on_block = NULL;
|
||||
|
||||
envblk = open_envblk_file (name);
|
||||
+ grub_envblk_iterate (envblk, &envblk_on_block, read_env_block_var);
|
||||
grub_envblk_iterate (envblk, NULL, print_var);
|
||||
grub_envblk_close (envblk);
|
||||
+ if (envblk_on_block != NULL)
|
||||
+ {
|
||||
+ grub_envblk_iterate (envblk_on_block, NULL, print_var);
|
||||
+ grub_envblk_close (envblk_on_block);
|
||||
+ }
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1,176 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Chang via Grub-devel <grub-devel@gnu.org>
|
||||
Date: Fri, 17 Oct 2025 17:01:39 +0800
|
||||
Subject: [PATCH] util/grub-editenv: add probe call for external envblk
|
||||
|
||||
This patch adds the probe_fs_envblk() function to identify the root
|
||||
filesystem and invoke fs_envblk_init() with the probed filesystem type
|
||||
and device. This checks if the feature is available and initializes the
|
||||
handle, fs_envblk, to access the external environment block. It avoids
|
||||
configurations with diskfilter or cryptodisk where filesystem blocks may
|
||||
be remapped or encrypted.
|
||||
|
||||
The probe is only invoked when grub-editenv is working on the default
|
||||
environment file path. This restriction ensures that probing and
|
||||
possible raw device access are not triggered for arbitrary user supplied
|
||||
paths, but only for the standard grubenv file. In that case the code
|
||||
checks if the filename equals DEFAULT_ENVBLK_PATH and then calls
|
||||
probe_fs_envblk with fs_envblk_spec. The result is stored in the global
|
||||
fs_envblk handle. At this stage the external environment block is only
|
||||
detected and recorded, and the behavior of grub-editenv is unchanged.
|
||||
|
||||
Signed-off-by: Michael Chang <mchang@suse.com>
|
||||
Reviewed-by: Neal Gompa <ngompa13@gmail.com>
|
||||
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
||||
---
|
||||
util/grub-editenv.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 113 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/util/grub-editenv.c b/util/grub-editenv.c
|
||||
index 170d8f139a..201dc7ccd4 100644
|
||||
--- a/util/grub-editenv.c
|
||||
+++ b/util/grub-editenv.c
|
||||
@@ -23,8 +23,11 @@
|
||||
#include <grub/util/misc.h>
|
||||
#include <grub/lib/envblk.h>
|
||||
#include <grub/i18n.h>
|
||||
-#include <grub/emu/hostfile.h>
|
||||
+#include <grub/emu/hostdisk.h>
|
||||
#include <grub/util/install.h>
|
||||
+#include <grub/emu/getroot.h>
|
||||
+#include <grub/fs.h>
|
||||
+#include <grub/crypto.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
@@ -161,7 +164,7 @@ static fs_envblk_spec_t fs_envblk_spec[] = {
|
||||
|
||||
static fs_envblk_t fs_envblk = NULL;
|
||||
|
||||
-static void __attribute__ ((unused))
|
||||
+static void
|
||||
fs_envblk_init (const char *fs_name, const char *dev)
|
||||
{
|
||||
fs_envblk_spec_t *p;
|
||||
@@ -582,6 +585,111 @@ incr_variables (const char *name, int argc, char *argv[])
|
||||
grub_envblk_close (envblk);
|
||||
}
|
||||
|
||||
+static bool
|
||||
+is_abstraction (grub_device_t dev)
|
||||
+{
|
||||
+ if (dev == NULL || dev->disk == NULL)
|
||||
+ return false;
|
||||
+
|
||||
+ if (dev->disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID ||
|
||||
+ dev->disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID)
|
||||
+ return true;
|
||||
+
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+probe_fs_envblk (fs_envblk_spec_t *spec)
|
||||
+{
|
||||
+ char **grub_devices = NULL;
|
||||
+ char **curdev, **curdrive;
|
||||
+ size_t ndev = 0;
|
||||
+ char **grub_drives = NULL;
|
||||
+ grub_device_t grub_dev = NULL;
|
||||
+ grub_fs_t grub_fs = NULL;
|
||||
+ bool have_abstraction = false;
|
||||
+
|
||||
+ grub_util_biosdisk_init (DEFAULT_DEVICE_MAP);
|
||||
+ grub_init_all ();
|
||||
+ grub_gcry_init_all ();
|
||||
+
|
||||
+ grub_lvm_fini ();
|
||||
+ grub_mdraid09_fini ();
|
||||
+ grub_mdraid1x_fini ();
|
||||
+ grub_diskfilter_fini ();
|
||||
+ grub_diskfilter_init ();
|
||||
+ grub_mdraid09_init ();
|
||||
+ grub_mdraid1x_init ();
|
||||
+ grub_lvm_init ();
|
||||
+
|
||||
+ grub_devices = grub_guess_root_devices (DEFAULT_DIRECTORY);
|
||||
+
|
||||
+ if (grub_devices == NULL || grub_devices[0] == NULL)
|
||||
+ {
|
||||
+ grub_util_warn (_("cannot find a device for %s (is /dev mounted?)"), DEFAULT_DIRECTORY);
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ for (curdev = grub_devices; *curdev != NULL; curdev++, ndev++)
|
||||
+ grub_util_pull_device (*curdev);
|
||||
+
|
||||
+ grub_drives = xcalloc ((ndev + 1), sizeof (grub_drives[0]));
|
||||
+
|
||||
+ for (curdev = grub_devices, curdrive = grub_drives; *curdev != NULL; curdev++,
|
||||
+ curdrive++)
|
||||
+ {
|
||||
+ *curdrive = grub_util_get_grub_dev (*curdev);
|
||||
+ if (*curdrive == NULL)
|
||||
+ {
|
||||
+ grub_util_warn (_("cannot find a GRUB drive for %s. Check your device.map"),
|
||||
+ *curdev);
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ }
|
||||
+ *curdrive = NULL;
|
||||
+
|
||||
+ grub_dev = grub_device_open (grub_drives[0]);
|
||||
+ if (grub_dev == NULL)
|
||||
+ {
|
||||
+ grub_util_warn (_("cannot open device %s: %s"), grub_drives[0], grub_errmsg);
|
||||
+ grub_errno = GRUB_ERR_NONE;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ grub_fs = grub_fs_probe (grub_dev);
|
||||
+ if (grub_fs == NULL)
|
||||
+ {
|
||||
+ grub_util_warn (_("cannot probe fs for %s: %s"), grub_drives[0], grub_errmsg);
|
||||
+ grub_errno = GRUB_ERR_NONE;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ have_abstraction = is_abstraction (grub_dev);
|
||||
+ for (curdrive = grub_drives + 1; *curdrive != NULL && have_abstraction == false; curdrive++)
|
||||
+ {
|
||||
+ grub_device_t dev = grub_device_open (*curdrive);
|
||||
+
|
||||
+ if (dev == NULL)
|
||||
+ continue;
|
||||
+ have_abstraction = is_abstraction (dev);
|
||||
+ grub_device_close (dev);
|
||||
+ }
|
||||
+
|
||||
+ if (have_abstraction == false)
|
||||
+ fs_envblk_init (grub_fs->name, grub_devices[0]);
|
||||
+
|
||||
+ cleanup:
|
||||
+ if (grub_devices != NULL)
|
||||
+ for (curdev = grub_devices; *curdev != NULL; curdev++)
|
||||
+ free (*curdev);
|
||||
+ free (grub_devices);
|
||||
+ free (grub_drives);
|
||||
+ grub_device_close (grub_dev);
|
||||
+ grub_gcry_fini_all ();
|
||||
+ grub_fini_all ();
|
||||
+ grub_util_biosdisk_fini ();
|
||||
+}
|
||||
+
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
@@ -613,6 +721,9 @@ main (int argc, char *argv[])
|
||||
command = argv[curindex++];
|
||||
}
|
||||
|
||||
+ if (strcmp (filename, DEFAULT_ENVBLK_PATH) == 0)
|
||||
+ probe_fs_envblk (fs_envblk_spec);
|
||||
+
|
||||
if (strcmp (command, "create") == 0)
|
||||
grub_util_create_envblk_file (filename);
|
||||
else if (strcmp (command, "list") == 0)
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Chang via Grub-devel <grub-devel@gnu.org>
|
||||
Date: Fri, 17 Oct 2025 17:01:40 +0800
|
||||
Subject: [PATCH] btrfs: add environment block to reserved header area
|
||||
|
||||
This patch reserves space for the GRUB environment block inside the
|
||||
Btrfs header. The block is placed at an offset of GRUB_ENV_BTRFS_OFFSET
|
||||
, 256 KiB from the start of the device, and occupies one sector. To
|
||||
protect the space, overflow guard sectors are placed before and after
|
||||
the reserved block.
|
||||
|
||||
The Btrfs header already defines regions for bootloader use. By adding
|
||||
this entry, GRUB gains a fixed and safe location to store the
|
||||
environment block without conflicting with other structures in the
|
||||
header.
|
||||
|
||||
Add Btrfs and its reserved area information to the fs_envblk_spec table.
|
||||
With the groundworks done in previous patches, the function is now
|
||||
complete and working in grub-editenv.
|
||||
|
||||
Signed-off-by: Michael Chang <mchang@suse.com>
|
||||
Reviewed-by: Neal Gompa <ngompa13@gmail.com>
|
||||
---
|
||||
grub-core/fs/btrfs.c | 10 +++++++++-
|
||||
include/grub/fs.h | 2 ++
|
||||
util/grub-editenv.c | 9 ++++++++-
|
||||
3 files changed, 19 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
|
||||
index 3228e17886..261c413e9f 100644
|
||||
--- a/grub-core/fs/btrfs.c
|
||||
+++ b/grub-core/fs/btrfs.c
|
||||
@@ -2650,11 +2650,16 @@ struct embed_region {
|
||||
* https://btrfs.wiki.kernel.org/index.php/Manpage/btrfs(5)#BOOTLOADER_SUPPORT
|
||||
* The first 1 MiB on each device is unused with the exception of primary
|
||||
* superblock that is on the offset 64 KiB and spans 4 KiB.
|
||||
+ *
|
||||
+ * Note: If this table is modified, also update
|
||||
+ * util/grub-editenv.c::fs_envblk_spec, which describes the file-system
|
||||
+ * specific layout of reserved raw blocks used as environment blocks so that
|
||||
+ * both stay consistent.
|
||||
*/
|
||||
|
||||
static const struct {
|
||||
struct embed_region available;
|
||||
- struct embed_region used[6];
|
||||
+ struct embed_region used[9];
|
||||
} btrfs_head = {
|
||||
.available = {0, GRUB_DISK_KiB_TO_SECTORS (1024)}, /* The first 1 MiB. */
|
||||
.used = {
|
||||
@@ -2662,6 +2667,9 @@ static const struct {
|
||||
{GRUB_DISK_KiB_TO_SECTORS (64) - 1, 1}, /* Overflow guard. */
|
||||
{GRUB_DISK_KiB_TO_SECTORS (64), GRUB_DISK_KiB_TO_SECTORS (4)}, /* 4 KiB superblock. */
|
||||
{GRUB_DISK_KiB_TO_SECTORS (68), 1}, /* Overflow guard. */
|
||||
+ {(GRUB_ENV_BTRFS_OFFSET >> GRUB_DISK_SECTOR_BITS) - 1, 1}, /* Overflow guard. */
|
||||
+ {(GRUB_ENV_BTRFS_OFFSET >> GRUB_DISK_SECTOR_BITS), 1}, /* Environment Block. */
|
||||
+ {(GRUB_ENV_BTRFS_OFFSET >> GRUB_DISK_SECTOR_BITS) + 1, 1}, /* Overflow guard. */
|
||||
{GRUB_DISK_KiB_TO_SECTORS (1024) - 1, 1}, /* Overflow guard. */
|
||||
{0, 0} /* Array terminator. */
|
||||
}
|
||||
diff --git a/include/grub/fs.h b/include/grub/fs.h
|
||||
index df4c93b16f..89e4d2b9bc 100644
|
||||
--- a/include/grub/fs.h
|
||||
+++ b/include/grub/fs.h
|
||||
@@ -132,4 +132,6 @@ grub_fs_unregister (grub_fs_t fs)
|
||||
|
||||
grub_fs_t EXPORT_FUNC(grub_fs_probe) (grub_device_t device);
|
||||
|
||||
+#define GRUB_ENV_BTRFS_OFFSET (256 * 1024)
|
||||
+
|
||||
#endif /* ! GRUB_FS_HEADER */
|
||||
diff --git a/util/grub-editenv.c b/util/grub-editenv.c
|
||||
index 201dc7ccd4..3c3f9d09f3 100644
|
||||
--- a/util/grub-editenv.c
|
||||
+++ b/util/grub-editenv.c
|
||||
@@ -156,9 +156,16 @@ static fs_envblk_ops_t fs_envblk_ops = {
|
||||
|
||||
/*
|
||||
* fs_envblk_spec describes the file-system specific layout of reserved raw
|
||||
- * blocks used as environment blocks.
|
||||
+ * blocks used as environment blocks. At present only Btrfs is supported. Other
|
||||
+ * file-systems may be added if they provide a similar facility and avoid the
|
||||
+ * limitation of writing to COW.
|
||||
+ *
|
||||
+ * Note: If this table is modified, also update
|
||||
+ * grub-core/fs/btrfs.c::btrfs_head, which defines the layout in the Btrfs
|
||||
+ * header and exports GRUB_ENV_BTRFS_OFFSET, so that both stay consistent.
|
||||
*/
|
||||
static fs_envblk_spec_t fs_envblk_spec[] = {
|
||||
+ { "btrfs", GRUB_ENV_BTRFS_OFFSET, GRUB_DISK_SECTOR_SIZE },
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Chang via Grub-devel <grub-devel@gnu.org>
|
||||
Date: Fri, 17 Oct 2025 17:01:41 +0800
|
||||
Subject: [PATCH] 00_header.in: wire grub.cfg to use env_block when present
|
||||
|
||||
This patch extends the generated grub.cfg so that it can use the
|
||||
external environment block when the variable env_block is defined.
|
||||
During boot, if env_block is set, grub.cfg builds a device path for it,
|
||||
exports the variable, and then loads its contents in addition to the
|
||||
normal grubenv file.
|
||||
|
||||
When GRUB writes variables such as next_entry or saved_entry, the save
|
||||
commands are changed to write into env_block if it is set, and to fall
|
||||
back to the grubenv file otherwise. In this way the external environment
|
||||
block is used automatically, and existing commands like savedefault or
|
||||
save_env do not need to change.
|
||||
|
||||
Signed-off-by: Michael Chang <mchang@suse.com>
|
||||
Reviewed-by: Neal Gompa <ngompa13@gmail.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
util/grub.d/00_header.in | 26 +++++++++++++++++++++++---
|
||||
1 file changed, 23 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in
|
||||
index 3e1b77265d..a5d43929b8 100644
|
||||
--- a/util/grub.d/00_header.in
|
||||
+++ b/util/grub.d/00_header.in
|
||||
@@ -58,6 +58,13 @@ if [ -f \${config_directory}/grubenv ]; then
|
||||
elif [ -s \$prefix/grubenv ]; then
|
||||
load_env
|
||||
fi
|
||||
+
|
||||
+if [ "\${env_block}" ] ; then
|
||||
+ set env_block="(\${root})\${env_block}"
|
||||
+ export env_block
|
||||
+ load_env -f "\${env_block}"
|
||||
+fi
|
||||
+
|
||||
EOF
|
||||
if [ "x$GRUB_BUTTON_CMOS_ADDRESS" != "x" ]; then
|
||||
cat <<EOF
|
||||
@@ -66,7 +73,11 @@ if cmostest $GRUB_BUTTON_CMOS_ADDRESS ; then
|
||||
elif [ "\${next_entry}" ] ; then
|
||||
set default="\${next_entry}"
|
||||
set next_entry=
|
||||
- save_env next_entry
|
||||
+ if [ "\${env_block}" ] ; then
|
||||
+ save_env -f "\${env_block}" next_entry
|
||||
+ else
|
||||
+ save_env next_entry
|
||||
+ fi
|
||||
set boot_once=true
|
||||
else
|
||||
set default="${GRUB_DEFAULT}"
|
||||
@@ -77,7 +88,11 @@ else
|
||||
if [ "\${next_entry}" ] ; then
|
||||
set default="\${next_entry}"
|
||||
set next_entry=
|
||||
- save_env next_entry
|
||||
+ if [ "\${env_block}" ] ; then
|
||||
+ save_env -f "\${env_block}" next_entry
|
||||
+ else
|
||||
+ save_env next_entry
|
||||
+ fi
|
||||
set boot_once=true
|
||||
else
|
||||
set default="${GRUB_DEFAULT}"
|
||||
@@ -105,7 +120,12 @@ fi
|
||||
function savedefault {
|
||||
if [ -z "\${boot_once}" ]; then
|
||||
saved_entry="\${chosen}"
|
||||
- save_env saved_entry
|
||||
+ if [ "\${env_block}" ] ; then
|
||||
+ save_env -f "\${env_block}" saved_entry
|
||||
+ else
|
||||
+ save_env saved_entry
|
||||
+ fi
|
||||
+
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Chang via Grub-devel <grub-devel@gnu.org>
|
||||
Date: Fri, 17 Oct 2025 17:01:43 +0800
|
||||
Subject: [PATCH] btrfs: update doc link for bootloader support
|
||||
|
||||
The old wiki link is obsolete and no longer updated, change it to the
|
||||
current documentation.
|
||||
|
||||
Signed-off-by: Michael Chang <mchang@suse.com>
|
||||
Reviewed-by: Neal Gompa <ngompa13@gmail.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/btrfs.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
|
||||
index 261c413e9f..2222c57abd 100644
|
||||
--- a/grub-core/fs/btrfs.c
|
||||
+++ b/grub-core/fs/btrfs.c
|
||||
@@ -2647,7 +2647,8 @@ struct embed_region {
|
||||
};
|
||||
|
||||
/*
|
||||
- * https://btrfs.wiki.kernel.org/index.php/Manpage/btrfs(5)#BOOTLOADER_SUPPORT
|
||||
+ * https://btrfs.readthedocs.io/en/latest/btrfs-man5.html#man-btrfs5-bootloader-support
|
||||
+ * or invoke "man 5 btrfs" and visit the "bootloader support" subsection.
|
||||
* The first 1 MiB on each device is unused with the exception of primary
|
||||
* superblock that is on the offset 64 KiB and spans 4 KiB.
|
||||
*
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Leo Sandoval <lsandova@redhat.com>
|
||||
Date: Mon, 27 Oct 2025 11:18:45 -0600
|
||||
Subject: [PATCH] docs: add Btrfs env block and special env vars
|
||||
|
||||
Update grub.texi to describe the external environment block in the
|
||||
reserved area of Btrfs header used for grub-reboot and savedefault,
|
||||
and add a section documenting the saved_entry, next_entry, and
|
||||
env_block variables.
|
||||
|
||||
Signed-off-by: Michael Chang <mchang@suse.com>
|
||||
Reviewed-by: Neal Gompa <ngompa13@gmail.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
docs/grub.texi | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 55 insertions(+)
|
||||
|
||||
diff --git a/docs/grub.texi b/docs/grub.texi
|
||||
index 531e847f32..d669972337 100644
|
||||
--- a/docs/grub.texi
|
||||
+++ b/docs/grub.texi
|
||||
@@ -3265,6 +3265,7 @@ GRUB. Others may be used freely in GRUB configuration files.
|
||||
@menu
|
||||
* Special environment variables::
|
||||
* Environment block::
|
||||
+* Special environment block variables::
|
||||
@end menu
|
||||
|
||||
|
||||
@@ -3881,9 +3882,63 @@ For safety reasons, this storage is only available when installed on a plain
|
||||
disk (no LVM or RAID), using a non-checksumming filesystem (no ZFS), and
|
||||
using BIOS or EFI functions (no ATA, USB or IEEE1275).
|
||||
|
||||
+On Btrfs filesystems, a reserved area in the filesystem header may be used to
|
||||
+store the environment block. This static block avoids the problems of updating
|
||||
+a normal file on a copy-on-write filesystem, where writing raw block is not
|
||||
+stable and requires metadata update. The reserved area provides a fixed
|
||||
+location that GRUB can update directly, allowing commands such as
|
||||
+@command{grub-reboot} and @samp{GRUB_SAVEDEFAULT} to function correctly on
|
||||
+Btrfs volumes.
|
||||
+
|
||||
@command{grub2-mkconfig} uses this facility to implement
|
||||
@samp{GRUB_SAVEDEFAULT} (@pxref{Simple configuration}).
|
||||
|
||||
+@node Special environment block variables
|
||||
+@section Special environment block variables
|
||||
+
|
||||
+These special variables are usually written to the environment block
|
||||
+(@pxref{Environment block}) to customize the behavior of @file{grub.cfg}
|
||||
+generated by @command{grub-mkconfig}.
|
||||
+
|
||||
+@menu
|
||||
+* saved_entry::
|
||||
+* next_entry::
|
||||
+* env_block::
|
||||
+@end menu
|
||||
+
|
||||
+@node saved_entry
|
||||
+@subsection saved_entry
|
||||
+
|
||||
+The @var{saved_entry} variable sets the default boot entry in @file{grub.cfg}
|
||||
+created by @command{grub-mkconfig}. It can be set with
|
||||
+@command{grub-set-default} to choose a default entry, or at runtime with the
|
||||
+@code{savedefault} function in grub.cfg to save the current entry as the new
|
||||
+default. This may require write access by GRUB.
|
||||
+
|
||||
+@node next_entry
|
||||
+@subsection next_entry
|
||||
+
|
||||
+The @var{next_entry} variable sets the boot entry for the next boot only. After
|
||||
+it is used, GRUB clears the value so it is not reused. This requires write
|
||||
+access to the environment block (@pxref{Environment block}) at runtime. The
|
||||
+@command{grub-reboot} command is usually used instead of changing this variable
|
||||
+directly.
|
||||
+
|
||||
+@node env_block
|
||||
+@subsection env_block
|
||||
+
|
||||
+If the filesystem is Btrfs and the disk is not an abstracted device such as
|
||||
+LVM, RAID, or encryption, the reserved space in the Btrfs header can be used as
|
||||
+the environment block (@pxref{Environment block}). This provides a fixed raw
|
||||
+block that GRUB can reliably write to. The @var{env_block} records this
|
||||
+location in GRUB blocklist syntax (@pxref{Block list syntax}) so that
|
||||
+@command{grub-editenv} and @file{grub.cfg} know how to access and use the
|
||||
+external raw block.
|
||||
+
|
||||
+This variable is initialized when @file{grubenv} is first created by
|
||||
+@command{grub-editenv} and is treated as read-only to avoid being overwritten
|
||||
+with an unpredictable value.
|
||||
+
|
||||
@node Modules
|
||||
@chapter Modules
|
||||
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Rasmus Villemoes <rasmus.villemoes@prevas.dk>
|
||||
Date: Thu, 29 Aug 2024 13:01:02 +0200
|
||||
Subject: [PATCH] kern/fs: Honour file->read_hook() in grub_fs_blocklist_read()
|
||||
|
||||
Unlike files accessed via a normal file system, the file->read_hook() is
|
||||
not honoured when using blocklist notation.
|
||||
|
||||
This means that when trying to use a dedicated, 1 KiB, raw partition
|
||||
for the environment block and hence does something like
|
||||
|
||||
save_env --file=(hd0,gpt9)0+2 X Y Z
|
||||
|
||||
this fails with "sparse file not allowed", which is rather unexpected,
|
||||
as I've explicitly said exactly which blocks should be used. Adding
|
||||
a little debugging reveals that grub_file_size(file) is 1024 as expected,
|
||||
but total_length is 0, simply because the callback was never invoked, so
|
||||
blocklists is an empty list.
|
||||
|
||||
Fix that by honouring the ->read_hook() set by the caller, also when
|
||||
a "file" is specified with blocklist notation.
|
||||
|
||||
Signed-off-by: Rasmus Villemoes <rasmus.villemoes@prevas.dk>
|
||||
Reviewed-by: Vladimir Serbinenko <phcoder@gmail.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/kern/fs.c | 12 ++++++++++--
|
||||
1 file changed, 10 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/grub-core/kern/fs.c b/grub-core/kern/fs.c
|
||||
index f25bace620..9f6f4ef9da 100644
|
||||
--- a/grub-core/kern/fs.c
|
||||
+++ b/grub-core/kern/fs.c
|
||||
@@ -216,12 +216,15 @@ grub_fs_blocklist_read (grub_file_t file, char *buf, grub_size_t len)
|
||||
grub_disk_addr_t sector;
|
||||
grub_off_t offset;
|
||||
grub_ssize_t ret = 0;
|
||||
+ grub_disk_t disk = file->device->disk;
|
||||
|
||||
if (len > file->size - file->offset)
|
||||
len = file->size - file->offset;
|
||||
|
||||
sector = (file->offset >> GRUB_DISK_SECTOR_BITS);
|
||||
offset = (file->offset & (GRUB_DISK_SECTOR_SIZE - 1));
|
||||
+ disk->read_hook = file->read_hook;
|
||||
+ disk->read_hook_data = file->read_hook_data;
|
||||
for (p = file->data; p->length && len > 0; p++)
|
||||
{
|
||||
if (sector < p->length)
|
||||
@@ -233,9 +236,12 @@ grub_fs_blocklist_read (grub_file_t file, char *buf, grub_size_t len)
|
||||
>> GRUB_DISK_SECTOR_BITS) > p->length - sector)
|
||||
size = ((p->length - sector) << GRUB_DISK_SECTOR_BITS) - offset;
|
||||
|
||||
- if (grub_disk_read (file->device->disk, p->offset + sector, offset,
|
||||
+ if (grub_disk_read (disk, p->offset + sector, offset,
|
||||
size, buf) != GRUB_ERR_NONE)
|
||||
- return -1;
|
||||
+ {
|
||||
+ ret = -1;
|
||||
+ break;
|
||||
+ }
|
||||
|
||||
ret += size;
|
||||
len -= size;
|
||||
@@ -245,6 +251,8 @@ grub_fs_blocklist_read (grub_file_t file, char *buf, grub_size_t len)
|
||||
else
|
||||
sector -= p->length;
|
||||
}
|
||||
+ disk->read_hook = NULL;
|
||||
+ disk->read_hook_data = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Neal Gompa <ngompa@fedoraproject.org>
|
||||
Date: Wed, 26 Nov 2025 08:20:26 -0500
|
||||
Subject: [PATCH] util/grub.d/00_header.in: Prefer $dev instead of $root for
|
||||
$env_block
|
||||
|
||||
In UEFI environments where GRUB loads a stub grub.cfg on the EFI
|
||||
System Partition (ESP) that points to the real one on the operating
|
||||
system volume, the $root value is set to the ESP instead of the
|
||||
operating system volume.
|
||||
|
||||
This is particularly problematic for setups where the operating
|
||||
system boot data is on a Btrfs volume and the external environment
|
||||
block in the Btrfs bootloader space is used for grubenv data.
|
||||
|
||||
Using $dev in its place resolves this problem, since the stub
|
||||
grub.cfg populates this variable. Use it if it exists, and
|
||||
fall back to $root accordingly.
|
||||
|
||||
This is unlikely to be upstreamable, as it depends on the method
|
||||
Fedora Linux and derivatives use to load the GRUB configuration.
|
||||
|
||||
Signed-off-by: Neal Gompa <ngompa@fedoraproject.org>
|
||||
---
|
||||
util/grub.d/00_header.in | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in
|
||||
index a5d43929b8..01f1f4144e 100644
|
||||
--- a/util/grub.d/00_header.in
|
||||
+++ b/util/grub.d/00_header.in
|
||||
@@ -60,7 +60,11 @@ elif [ -s \$prefix/grubenv ]; then
|
||||
fi
|
||||
|
||||
if [ "\${env_block}" ] ; then
|
||||
- set env_block="(\${root})\${env_block}"
|
||||
+ if [ "\${dev}" ]; then
|
||||
+ set env_block="(\${dev})\${env_block}"
|
||||
+ else
|
||||
+ set env_block="(\${root})\${env_block}"
|
||||
+ fi
|
||||
export env_block
|
||||
load_env -f "\${env_block}"
|
||||
fi
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Neal Gompa <ngompa@fedoraproject.org>
|
||||
Date: Wed, 26 Nov 2025 08:37:57 -0500
|
||||
Subject: [PATCH] grub.d: Support the external environment block for automatic
|
||||
hidden menu
|
||||
|
||||
This allows the automatic hidden menu (and boot counting) mechanism
|
||||
to use an external environment block if it exists and is configured
|
||||
to be used.
|
||||
|
||||
This is particularly important for supporting this mechanism on
|
||||
systems with the operating system boot data on a Btrfs volume.
|
||||
|
||||
This is unlikely to be upstreamable, as it depends on Fedora's GRUB
|
||||
hidden menu and boot counting patch sets.
|
||||
|
||||
Signed-off-by: Neal Gompa <ngompa@fedoraproject.org>
|
||||
---
|
||||
util/grub.d/08_fallback_counting.in | 6 +++++-
|
||||
util/grub.d/10_reset_boot_success.in | 6 +++++-
|
||||
util/grub.d/12_menu_auto_hide.in | 6 +++++-
|
||||
util/grub.d/14_menu_show_once.in | 6 +++++-
|
||||
4 files changed, 20 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/util/grub.d/08_fallback_counting.in b/util/grub.d/08_fallback_counting.in
|
||||
index 2e2c3ff7d3..272cdb6533 100644
|
||||
--- a/util/grub.d/08_fallback_counting.in
|
||||
+++ b/util/grub.d/08_fallback_counting.in
|
||||
@@ -19,6 +19,10 @@ if [ -n "\${boot_counter}" -a "\${boot_success}" = "0" ]; then
|
||||
else
|
||||
decrement boot_counter
|
||||
fi
|
||||
- save_env boot_counter
|
||||
+ if [ "\${env_block}" ]; then
|
||||
+ save_env -f "\${env_block}" boot_counter
|
||||
+ else
|
||||
+ save_env boot_counter
|
||||
+ fi
|
||||
fi
|
||||
EOF
|
||||
diff --git a/util/grub.d/10_reset_boot_success.in b/util/grub.d/10_reset_boot_success.in
|
||||
index e73f4137b3..ca04f9b699 100644
|
||||
--- a/util/grub.d/10_reset_boot_success.in
|
||||
+++ b/util/grub.d/10_reset_boot_success.in
|
||||
@@ -21,5 +21,9 @@ elif [ "\${boot_indeterminate}" = "1" ]; then
|
||||
fi
|
||||
# Reset boot_success for current boot
|
||||
set boot_success=0
|
||||
-save_env boot_success boot_indeterminate
|
||||
+if [ "\${env_block}" ]; then
|
||||
+ save_env -f "\${env_block}" boot_success boot_indeterminate
|
||||
+else
|
||||
+ save_env boot_success boot_indeterminate
|
||||
+fi
|
||||
EOF
|
||||
diff --git a/util/grub.d/12_menu_auto_hide.in b/util/grub.d/12_menu_auto_hide.in
|
||||
index 6a7c0fa0d4..c2c207232e 100644
|
||||
--- a/util/grub.d/12_menu_auto_hide.in
|
||||
+++ b/util/grub.d/12_menu_auto_hide.in
|
||||
@@ -16,7 +16,11 @@ cat << EOF
|
||||
if [ x\$feature_timeout_style = xy ] ; then
|
||||
if [ "\${menu_show_once}" ]; then
|
||||
unset menu_show_once
|
||||
- save_env menu_show_once
|
||||
+ if [ "\${env_block}" ]; then
|
||||
+ save_env -f "\${env_block}" menu_show_once
|
||||
+ else
|
||||
+ save_env menu_show_once
|
||||
+ fi
|
||||
set timeout_style=menu
|
||||
set timeout=60
|
||||
elif [ "\${menu_auto_hide}" -a "\${menu_hide_ok}" = "1" ]; then
|
||||
diff --git a/util/grub.d/14_menu_show_once.in b/util/grub.d/14_menu_show_once.in
|
||||
index 1cd7f36142..41b37b5ec7 100755
|
||||
--- a/util/grub.d/14_menu_show_once.in
|
||||
+++ b/util/grub.d/14_menu_show_once.in
|
||||
@@ -7,7 +7,11 @@ if [ x\$feature_timeout_style = xy ]; then
|
||||
set timeout_style=menu
|
||||
set timeout="\${menu_show_once_timeout}"
|
||||
unset menu_show_once_timeout
|
||||
- save_env menu_show_once_timeout
|
||||
+ if [ "\${env_block}" ]; then
|
||||
+ save_env -f "\${env_block}" menu_show_once_timeout
|
||||
+ else
|
||||
+ save_env menu_show_once_timeout
|
||||
+ fi
|
||||
fi
|
||||
fi
|
||||
EOF
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Neal Gompa <ngompa@fedoraproject.org>
|
||||
Date: Wed, 26 Nov 2025 08:48:10 -0500
|
||||
Subject: [PATCH] grub-editenv: Make automatic hidden menu and boot counting
|
||||
use envblk when available
|
||||
|
||||
This ensures the automatic hidden menu and boot counting settings
|
||||
are set in the right place when an external environment block is used.
|
||||
|
||||
This is unlikely to be upstreamable, as it depends on Fedora's GRUB
|
||||
hidden menu and boot counting patch sets.
|
||||
|
||||
Signed-off-by: Neal Gompa <ngompa@fedoraproject.org>
|
||||
---
|
||||
util/grub-editenv.c | 8 +++++++-
|
||||
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/util/grub-editenv.c b/util/grub-editenv.c
|
||||
index 3c3f9d09f3..48611e4e17 100644
|
||||
--- a/util/grub-editenv.c
|
||||
+++ b/util/grub-editenv.c
|
||||
@@ -473,7 +473,13 @@ set_variables (const char *name, int argc, char *argv[])
|
||||
|
||||
*(p++) = 0;
|
||||
|
||||
- if ((strcmp (argv[0], "next_entry") == 0) && envblk_on_block != NULL)
|
||||
+ if (((strcmp (argv[0], "next_entry") == 0) ||
|
||||
+ (strcmp (argv[0], "boot_counter") == 0) ||
|
||||
+ (strcmp (argv[0], "boot_indeterminate") == 0) ||
|
||||
+ (strcmp (argv[0], "boot_success") == 0) ||
|
||||
+ (strcmp (argv[0], "menu_show_once") == 0) ||
|
||||
+ (strcmp (argv[0], "menu_show_once_timeout") == 0))
|
||||
+ && envblk_on_block != NULL)
|
||||
{
|
||||
if (grub_envblk_set (envblk_on_block, argv[0], p) == 0)
|
||||
grub_util_error ("%s", _("environment block too small"));
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Leo Sandoval <lsandova@redhat.com>
|
||||
Date: Fri, 28 Nov 2025 11:30:19 -0600
|
||||
Subject: [PATCH] Increase EFI max allocation to max usable address
|
||||
|
||||
Signed-off-by: Leo Sandoval <lsandova@redhat.com>
|
||||
---
|
||||
include/grub/x86_64/efi/memory.h | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/include/grub/x86_64/efi/memory.h b/include/grub/x86_64/efi/memory.h
|
||||
index e81cfb3221..547e3f82f8 100644
|
||||
--- a/include/grub/x86_64/efi/memory.h
|
||||
+++ b/include/grub/x86_64/efi/memory.h
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#if defined (__code_model_large__)
|
||||
#define GRUB_EFI_MAX_USABLE_ADDRESS __UINTPTR_MAX__
|
||||
-#define GRUB_EFI_MAX_ALLOCATION_ADDRESS 0x7fffffff
|
||||
+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS
|
||||
#else
|
||||
#define GRUB_EFI_MAX_USABLE_ADDRESS 0x7fffffff
|
||||
#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS
|
||||
|
|
@ -25,11 +25,11 @@ case "$COMMAND" in
|
|||
|
||||
if [ -e "${ROOTPREFIX}${LINUX}" -a -n "${INITRD}" ]; then
|
||||
if [ ! -e "${ROOTPREFIX}${INITRD}" ]; then
|
||||
echo "Error: ${ROOTPREFIX}${INITRD} not found."
|
||||
echo "Error: ${INITRD} not found"
|
||||
exit 1
|
||||
fi
|
||||
if ! lsinitrd ${ROOTPREFIX}${INITRD} > /dev/null; then
|
||||
echo "Error: ${ROOTPREFIX}${INITRD} appears to be corrupt."
|
||||
echo "Error: ${INITRD} appears to be corrupt."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
|
@ -15,6 +15,10 @@ EFI_HOME=$2
|
|||
BOOT_UUID=$(grub2-probe --target=fs_uuid "${GRUB_HOME}")
|
||||
GRUB_DIR=$(grub2-mkrelpath "${GRUB_HOME}")
|
||||
|
||||
echo "Generating grub stub config for drive " "${BOOT_UUID}"
|
||||
echo "GRUB_DIR=" "${GRUB_DIR}"
|
||||
echo "EFI_HOME=" "${EFI_HOME}"
|
||||
|
||||
cat << EOF > "${EFI_HOME}"/grub.cfg.stb
|
||||
search --no-floppy --root-dev-only --fs-uuid --set=dev ${BOOT_UUID}
|
||||
set prefix=(\$dev)${GRUB_DIR}
|
||||
|
|
@ -23,4 +27,3 @@ configfile \$prefix/grub.cfg
|
|||
EOF
|
||||
|
||||
mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg
|
||||
chmod 0600 ${EFI_HOME}/grub.cfg
|
||||
|
|
|
|||
30
grub.macros
30
grub.macros
|
|
@ -1,12 +1,6 @@
|
|||
# vim:filetype=spec
|
||||
# Modules always contain just 32-bit code
|
||||
%global evr %{epoch}:%{version}-%{release}
|
||||
%global _libdir %{_exec_prefix}/lib
|
||||
|
||||
%global os_id %(eval echo $(grep ^ID= /etc/os-release | sed -e 's/^ID=//' -e 's/rhel/redhat/'))
|
||||
%global grub_evr_dir %{_libdir}/efi/grub2/%{evr}
|
||||
%global grub_efi_dir %{grub_evr_dir}/EFI/%{os_id}
|
||||
|
||||
%global _binaries_in_noarch_packages_terminate_build 0
|
||||
#%%undefine _missing_build_ids_terminate_build
|
||||
%{expand:%%{!?buildsubdir:%%global buildsubdir grub-%{tarversion}}}
|
||||
|
|
@ -286,6 +280,8 @@
|
|||
%global grubelfname core.elf
|
||||
%endif
|
||||
|
||||
%global evr %{epoch}:%{version}-%{release}
|
||||
|
||||
%ifarch x86_64
|
||||
%global with_efi_common 1
|
||||
%global with_legacy_modules 1
|
||||
|
|
@ -518,7 +514,7 @@ install -m 644 %{1}.conf ${RPM_BUILD_ROOT}/etc/dnf/protected.d/ \
|
|||
rm -f %{1}.conf \
|
||||
%{nil}
|
||||
|
||||
%global grub_modules " all_video boot blscfg btrfs blsuki \\\
|
||||
%global grub_modules " all_video boot blscfg btrfs \\\
|
||||
cat configfile cryptodisk \\\
|
||||
echo ext2 f2fs fat font \\\
|
||||
gcry_rijndael gcry_rsa gcry_serpent \\\
|
||||
|
|
@ -708,9 +704,8 @@ find . '(' -iname gdb_grub \\\
|
|||
')' \\\
|
||||
-exec cp {} $RPM_BUILD_ROOT/usr/lib/grub/%{grubaltefiarch}/ \\\; \
|
||||
find $RPM_BUILD_ROOT -type f -iname "*.mod*" -exec chmod a-x {} '\;' \
|
||||
install -d -m 0700 ${RPM_BUILD_ROOT}%{grub_efi_dir}/ \
|
||||
install -m 700 %{2} $RPM_BUILD_ROOT%{grub_efi_dir}/%{2} \
|
||||
install -m 700 %{3} $RPM_BUILD_ROOT%{grub_efi_dir}/%{3} \
|
||||
install -m 700 %{2} $RPM_BUILD_ROOT%{efi_esp_dir}/%{2} \
|
||||
install -m 700 %{3} $RPM_BUILD_ROOT%{efi_esp_dir}/%{3} \
|
||||
%{expand:%%do_install_protected_file grub2-%{alt_package_arch}} \
|
||||
cd .. \
|
||||
%{nil}
|
||||
|
|
@ -727,9 +722,8 @@ fi \
|
|||
find $RPM_BUILD_ROOT -iname "*.module" -exec chmod a-x {} '\;' \
|
||||
ln -s ../boot/grub2/grub.cfg \\\
|
||||
$RPM_BUILD_ROOT%{_sysconfdir}/grub2-efi.cfg \
|
||||
install -d -m 0700 ${RPM_BUILD_ROOT}%{grub_efi_dir}/ \
|
||||
install -m 700 %{2} $RPM_BUILD_ROOT%{grub_efi_dir}/%{2} \
|
||||
install -m 700 %{3} $RPM_BUILD_ROOT%{grub_efi_dir}/%{3} \
|
||||
install -m 700 %{2} $RPM_BUILD_ROOT%{efi_esp_dir}/%{2} \
|
||||
install -m 700 %{3} $RPM_BUILD_ROOT%{efi_esp_dir}/%{3} \
|
||||
%ifarch %{arm} \
|
||||
install -D -m 700 %{2} $RPM_BUILD_ROOT%{efi_esp_boot}/BOOTARM.EFI \
|
||||
%endif \
|
||||
|
|
@ -879,9 +873,7 @@ ln -s ../boot/grub2/grub.cfg \\\
|
|||
%defattr(-,root,root,-) \
|
||||
%config(noreplace) %{_sysconfdir}/grub2.cfg \
|
||||
%config(noreplace) %{_sysconfdir}/grub2-efi.cfg \
|
||||
%ghost %attr(0700,root,root) %{efi_esp_dir}/%{2} \
|
||||
%dir %attr(0700,root,root) %{grub_efi_dir} \
|
||||
%attr(0700,root,root) %{grub_efi_dir}/%{2} \
|
||||
%attr(0700,root,root) %verify(not mtime) %{efi_esp_dir}/%{2} \
|
||||
%ifarch %{arm} \
|
||||
%attr(0700,root,root) %verify(not mtime) %{efi_esp_boot}/BOOTARM.EFI \
|
||||
%endif \
|
||||
|
|
@ -889,8 +881,7 @@ ln -s ../boot/grub2/grub.cfg \\\
|
|||
%attr(0700,root,root)/usr/bin/gen_grub_cfgstub \
|
||||
%dir %attr(0700,root,root)/boot/loader/entries \
|
||||
%ghost %config(noreplace) %attr(0600,root,root)/boot/grub2/grub.cfg \
|
||||
%ghost %config(noreplace) %attr(0700,root,root)%{efi_esp_dir}/grub.cfg \
|
||||
%ghost %config(noreplace) %attr(0600,root,root)%{grub_efi_dir}/grub.cfg \
|
||||
%ghost %config(noreplace) %verify(not mtime) %attr(0700,root,root)%{efi_esp_dir}/grub.cfg \
|
||||
%config(noreplace) %verify(not size mode md5 mtime) /boot/grub2/grubenv \
|
||||
%attr(0644,root,root) %config(noreplace) /etc/dnf/protected.d/grub2-%{1}.conf \
|
||||
%{expand:%if 0%{?without_efi_modules} \
|
||||
|
|
@ -908,8 +899,7 @@ ln -s ../boot/grub2/grub.cfg \\\
|
|||
\
|
||||
%{expand:%%files %{1}-cdboot} \
|
||||
%defattr(-,root,root,-) \
|
||||
%ghost %attr(0700,root,root) %{efi_esp_dir}/%{3} \
|
||||
%attr(0700,root,root) %{grub_efi_dir}/%{3} \
|
||||
%attr(0700,root,root) %verify(not mtime) %{efi_esp_dir}/%{3} \
|
||||
%attr(0700,root,root)/boot/grub2/fonts \
|
||||
%{nil}
|
||||
|
||||
|
|
|
|||
27
grub.patches
27
grub.patches
|
|
@ -378,29 +378,4 @@ Patch0378: 0378-cryptocheck-Add-quiet-option.patch
|
|||
Patch0379: 0379-loader-efi-chainloader-Fix-double-free.patch
|
||||
Patch0380: 0380-loader-efi-chainloader-Fix-null-pointer-dereference.patch
|
||||
Patch0381: 0381-osdep-linux-getroot-Detect-DDF-container-similar-to-.patch
|
||||
Patch0382: 0382-Set-correctly-the-memory-attributes-for-the-kernel-P.patch
|
||||
Patch0383: 0383-Include-function-name-on-debug-print-function.patch
|
||||
Patch0384: 0384-kern-misc-Implement-grub_strtok.patch
|
||||
Patch0385: 0385-blsuki-Add-blscfg-command-to-parse-Boot-Loader-Speci.patch
|
||||
Patch0386: 0386-util-misc.c-Change-offset-type-for-grub_util_write_i.patch
|
||||
Patch0387: 0387-blsuki-Check-for-mounted-boot-in-emu.patch
|
||||
Patch0388: 0388-blsuki-Add-uki-command-to-load-Unified-Kernel-Image-.patch
|
||||
Patch0389: 0389-posix_wrap-Tweaks-in-preparation-for-libtasn1.patch
|
||||
Patch0390: 0390-blsuki-do-not-register-blscfg-command.patch
|
||||
Patch0391: 0391-misc-add-z-length-modifier-support.patch
|
||||
Patch0392: 0392-tests-add-z-modifier-printf-tests.patch
|
||||
Patch0393: 0393-util-grub-editenv-add-fs_envblk-open-helper.patch
|
||||
Patch0394: 0394-util-grub-editenv-add-fs_envblk-write-helper.patch
|
||||
Patch0395: 0395-util-grub-editenv-wire-set_variables-to-optional-fs_.patch
|
||||
Patch0396: 0396-util-grub-editenv-wire-unset_variables-to-optional-f.patch
|
||||
Patch0397: 0397-util-grub-editenv-wire-list_variables-to-optional-fs.patch
|
||||
Patch0398: 0398-util-grub-editenv-add-probe-call-for-external-envblk.patch
|
||||
Patch0399: 0399-btrfs-add-environment-block-to-reserved-header-area.patch
|
||||
Patch0400: 0400-00_header.in-wire-grub.cfg-to-use-env_block-when-pre.patch
|
||||
Patch0401: 0401-btrfs-update-doc-link-for-bootloader-support.patch
|
||||
Patch0402: 0402-docs-add-Btrfs-env-block-and-special-env-vars.patch
|
||||
Patch0403: 0403-kern-fs-Honour-file-read_hook-in-grub_fs_blocklist_r.patch
|
||||
Patch0404: 0404-util-grub.d-00_header.in-Prefer-dev-instead-of-root-.patch
|
||||
Patch0405: 0405-grub.d-Support-the-external-environment-block-for-au.patch
|
||||
Patch0406: 0406-grub-editenv-Make-automatic-hidden-menu-and-boot-cou.patch
|
||||
Patch0407: 0407-Increase-EFI-max-allocation-to-max-usable-address.patch
|
||||
Patch0382: 0382-Set-correctly-the-memory-attributes-for-the-kernel-P.patch
|
||||
58
grub2.spec
58
grub2.spec
|
|
@ -17,7 +17,7 @@
|
|||
Name: grub2
|
||||
Epoch: 1
|
||||
Version: 2.12
|
||||
Release: 50%{?dist}
|
||||
Release: 40%{?dist}
|
||||
Summary: Bootloader with support for Linux, Multiboot and more
|
||||
License: GPL-3.0-or-later
|
||||
URL: http://www.gnu.org/software/grub/
|
||||
|
|
@ -36,7 +36,7 @@ Source10: 20-grub.install
|
|||
Source11: grub.patches
|
||||
Source12: sbat.csv.in
|
||||
Source13: gen_grub_cfgstub
|
||||
Source14: 95-set-boot-entry.install
|
||||
Source14: 55-set-boot-entry.install
|
||||
|
||||
%include %{SOURCE1}
|
||||
|
||||
|
|
@ -387,7 +387,7 @@ fi
|
|||
%posttrans common
|
||||
set -eu
|
||||
|
||||
EFI_HOME=%{grub_efi_dir}
|
||||
EFI_HOME=%{efi_esp_dir}
|
||||
GRUB_HOME=/boot/grub2
|
||||
ESP_PATH=/boot/efi
|
||||
|
||||
|
|
@ -421,23 +421,12 @@ if test -f ${EFI_HOME}/grubenv; then
|
|||
mv --force ${EFI_HOME}/grubenv ${GRUB_HOME}/grubenv
|
||||
fi
|
||||
|
||||
%if 0%{with_efi_arch}
|
||||
%posttrans efi-%{efiarch}
|
||||
set -eu
|
||||
|
||||
# On image mode, bootupd takes care of installing bootloader updates to the ESP
|
||||
if [[ ! -e "/run/ostree-booted" ]]; then
|
||||
cp -a %{grub_efi_dir}/. %{efi_esp_dir} || :
|
||||
fi
|
||||
|
||||
%endif
|
||||
|
||||
%files common -f grub.lang
|
||||
%dir %{_libdir}/grub/
|
||||
%dir %{_datarootdir}/grub/
|
||||
%attr(0700,root,root) %dir %{_sysconfdir}/grub.d
|
||||
%{_prefix}/lib/kernel/install.d/20-grub.install
|
||||
%{_prefix}/lib/kernel/install.d/95-set-boot-entry.install
|
||||
%{_prefix}/lib/kernel/install.d/55-set-boot-entry.install
|
||||
%{_prefix}/lib/kernel/install.d/99-grub-mkconfig.install
|
||||
%dir %{_datarootdir}/grub
|
||||
%exclude %{_datarootdir}/grub/*
|
||||
|
|
@ -446,7 +435,8 @@ fi
|
|||
%dir /boot/grub2/themes/system
|
||||
%attr(0700,root,root) %dir /boot/grub2
|
||||
%exclude /boot/grub2/*
|
||||
%exclude %{grub_efi_dir}/*
|
||||
%dir %attr(0700,root,root) %{efi_esp_dir}
|
||||
%exclude %{efi_esp_dir}/*
|
||||
%ghost %config(noreplace) %verify(not size mode md5 mtime) /boot/grub2/grubenv
|
||||
%license COPYING
|
||||
%doc THANKS
|
||||
|
|
@ -608,45 +598,11 @@ fi
|
|||
%endif
|
||||
|
||||
%changelog
|
||||
* Wed Dec 10 2025 Joel Capitao <jcapitao@redhat.com> - 2.12-50
|
||||
- Do not include EFI dir in common subpackage
|
||||
- Resolves: rhbz#2420430
|
||||
|
||||
* Thu Nov 27 2025 Leo Sandoval <lsandova@redhat.com> - 2.12-49
|
||||
- Increase EFI max allocation to max usable address
|
||||
- Resolves: #2263643
|
||||
|
||||
* Fri Nov 21 2025 Leo Sandoval <lsandova@redhat.com> - 2.12-48
|
||||
- Add support for external environment block on Btrfs
|
||||
|
||||
* Thu Nov 13 2025 Leo Sandoval <lsandova@redhat.com> - 2.12-47
|
||||
- blsuki: do not register blscfg command
|
||||
|
||||
* Tue Nov 4 2025 Tom Callaway <spot@fedoraproject.org> - 2.12-46
|
||||
- rebuild for new fuse3
|
||||
|
||||
* Wed Oct 15 2025 Leo Sandoval <lsandova@redhat.com> - 2.12-45
|
||||
- Include upstream blsuki related patches
|
||||
|
||||
* Mon Sep 15 2025 Leo Sandoval <lsandova@redhat.com> - 2.12-44
|
||||
- Include function name on debug print function
|
||||
|
||||
* Fri Aug 29 2025 Nicolas Frayer <nfrayer@redhat.com> - 2.12-43
|
||||
- gen_grub_cfgstub: Removed output messages
|
||||
|
||||
* Wed Aug 20 2025 Jan Stancek <jstancek@redhat.com> - 2.12-42
|
||||
- move 55-set-boot-entry.install to 95
|
||||
- Related: #2389020
|
||||
|
||||
* Mon Aug 11 2025 Marta Lewandowska <mlewando@redhat.com> - 2.12-41
|
||||
- Phase 1 of the bootloader updates proposal implementation
|
||||
- https://fedoraproject.org/wiki/Changes/BootLoaderUpdatesPhase1
|
||||
|
||||
* Wed Aug 6 2025 Jan Stancek <jstancek@redhat.com> - 2.12-40
|
||||
- 55-set-boot-entry.install: fix initrd check
|
||||
- Resolves: #2386118
|
||||
|
||||
* Fri Aug 1 2025 FeRD (Frank Dana) <ferdnyc@gmail.com> - 2.12-39
|
||||
* Tue Jul 15 2025 FeRD (Frank Dana) <ferdnyc@gmail.com> - 2.12-39
|
||||
- kernel-install: Suppress warnings about missing /etc/default/grub
|
||||
file when attempting to grep its contents
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue