SHA256
1
0
forked from pool/grub2

Accepting request 1188943 from home:michael-chang:branches:Base:System

- Fix error in grub-install when root is on tmpfs (bsc#1226100)
    * 0001-grub-install-bailout-root-device-probing.patch
- Fix incorrect Platform tag in rpm header (bsc#1217967)

OBS-URL: https://build.opensuse.org/request/show/1188943
OBS-URL: https://build.opensuse.org/package/show/Base:System/grub2?expand=0&rev=508
This commit is contained in:
Michael Chang 2024-07-22 08:21:46 +00:00 committed by Git OBS Bridge
commit de8c74037b
235 changed files with 67792 additions and 0 deletions

23
.gitattributes vendored Normal file
View File

@ -0,0 +1,23 @@
## Default LFS
*.7z filter=lfs diff=lfs merge=lfs -text
*.bsp filter=lfs diff=lfs merge=lfs -text
*.bz2 filter=lfs diff=lfs merge=lfs -text
*.gem filter=lfs diff=lfs merge=lfs -text
*.gz filter=lfs diff=lfs merge=lfs -text
*.jar filter=lfs diff=lfs merge=lfs -text
*.lz filter=lfs diff=lfs merge=lfs -text
*.lzma filter=lfs diff=lfs merge=lfs -text
*.obscpio filter=lfs diff=lfs merge=lfs -text
*.oxt filter=lfs diff=lfs merge=lfs -text
*.pdf filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.rpm filter=lfs diff=lfs merge=lfs -text
*.tbz filter=lfs diff=lfs merge=lfs -text
*.tbz2 filter=lfs diff=lfs merge=lfs -text
*.tgz filter=lfs diff=lfs merge=lfs -text
*.ttf filter=lfs diff=lfs merge=lfs -text
*.txz filter=lfs diff=lfs merge=lfs -text
*.whl filter=lfs diff=lfs merge=lfs -text
*.xz filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.zst filter=lfs diff=lfs merge=lfs -text

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.osc

View File

@ -0,0 +1,51 @@
From 28440c9b5f83b82b4715554fa5c2d3f013b769e6 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Tue, 26 Mar 2024 13:55:53 +0800
Subject: [PATCH] 10_linux: Ensure persistence of root file system mounting
This commit addresses the issue where the by-uuid or by-partuuid device
symlinks might be unavailable in an installation system. Despite the
absence of these symlinks, the resulting system remains fully functional
for mounting the root file system by using persistent names
(root=(UUID|PARTUUID)=).
The patch implemented in this commit aims to prevent fallback to the OS
name as the root= parameter, as persistent names are preferred for
stability and predictability.
To achieve this, the fallback to the OS name won't be triggered if the
corresponding by-uuid or by-partuuid symlinks are missing, ensuring the
use of persistent names. Instead, a warning will be logged for the
missing symlinks, providing visibility into the issue.
Signed-off-by: Michael Chang <mchang@suse.com>
---
util/grub.d/10_linux.in | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index 5531239eb..4d8bdeac2 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -54,14 +54,16 @@ esac
if ( [ "x${GRUB_DEVICE_UUID}" = "x" ] && [ "x${GRUB_DEVICE_PARTUUID}" = "x" ] ) \
|| ( [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \
&& [ "x${GRUB_DISABLE_LINUX_PARTUUID}" = "xtrue" ] ) \
- || ( ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" \
- && ! test -e "/dev/disk/by-partuuid/${GRUB_DEVICE_PARTUUID}" ) \
|| ( test -e "${GRUB_DEVICE}" && uses_abstraction "${GRUB_DEVICE}" lvm ); then
LINUX_ROOT_DEVICE=${GRUB_DEVICE}
elif [ "x${GRUB_DEVICE_UUID}" = "x" ] \
|| [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ]; then
+ test -e "/dev/disk/by-partuuid/${GRUB_DEVICE_PARTUUID}" ||
+ echo "WARN: Use PARTUUID=${GRUB_DEVICE_PARTUUID} despite missing by-partuuid symlink" >&2
LINUX_ROOT_DEVICE=PARTUUID=${GRUB_DEVICE_PARTUUID}
else
+ test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" ||
+ echo "WARN: Use UUID=${GRUB_DEVICE_UUID} despite missing by-uuid symlink" >&2
LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID}
fi
--
2.44.0

View File

@ -0,0 +1,68 @@
From a326e486bdcf99e6be973ba54c0abfb6d2d95b73 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Mon, 17 Jan 2022 17:45:00 +0800
Subject: [PATCH 1/5] Add grub_envblk_buf helper function
This helps in creation and initialization of memory buffer for
environment block of given size.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/lib/envblk.c | 12 ++++++++++++
include/grub/lib/envblk.h | 1 +
util/grub-editenv.c | 4 +---
3 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/grub-core/lib/envblk.c b/grub-core/lib/envblk.c
index 2e4e78b132..24efbe7ffa 100644
--- a/grub-core/lib/envblk.c
+++ b/grub-core/lib/envblk.c
@@ -23,6 +23,18 @@
#include <grub/mm.h>
#include <grub/lib/envblk.h>
+char *
+grub_envblk_buf (grub_size_t size)
+{
+ char *buf;
+
+ buf = grub_malloc (size);
+ grub_memcpy (buf, GRUB_ENVBLK_SIGNATURE, sizeof (GRUB_ENVBLK_SIGNATURE) - 1);
+ grub_memset (buf + sizeof (GRUB_ENVBLK_SIGNATURE) - 1, '#', size - sizeof (GRUB_ENVBLK_SIGNATURE) + 1);
+
+ return buf;
+}
+
grub_envblk_t
grub_envblk_open (char *buf, grub_size_t size)
{
diff --git a/include/grub/lib/envblk.h b/include/grub/lib/envblk.h
index c3e6559217..83f3fcf841 100644
--- a/include/grub/lib/envblk.h
+++ b/include/grub/lib/envblk.h
@@ -31,6 +31,7 @@ struct grub_envblk
};
typedef struct grub_envblk *grub_envblk_t;
+char *grub_envblk_buf (grub_size_t size);
grub_envblk_t grub_envblk_open (char *buf, grub_size_t size);
int grub_envblk_set (grub_envblk_t envblk, const char *name, const char *value);
void grub_envblk_delete (grub_envblk_t envblk, const char *name);
diff --git a/util/grub-editenv.c b/util/grub-editenv.c
index b8219335f7..a02d3f2a63 100644
--- a/util/grub-editenv.c
+++ b/util/grub-editenv.c
@@ -210,9 +210,7 @@ create_envblk_fs (void)
if (! fp)
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);
+ buf = grub_envblk_buf (size);
if (fseek (fp, offset, SEEK_SET) < 0)
grub_util_error (_("cannot seek `%s': %s"), device, strerror (errno));
--
2.34.1

View File

@ -0,0 +1,526 @@
From db4da8095b5ba722d22502c8d090e66816a5577d Mon Sep 17 00:00:00 2001
From: Matthew Garrett <mjg@redhat.com>
Date: Fri, 6 Nov 2020 08:36:36 +0000
Subject: [PATCH 1/9] Add support for Linux EFI stub loading on aarch64.
Add support for Linux EFI stub loading on aarch64.
v1:
Make efi handoff the default loader for arm64 platform.
v2:
The efi shim_lock verifier has been moved to grub core so local
shim_lock protocol is no longer needed here for aarch64 efi to verify
the loaded kernel image. From now on the framework will take care the
verificaion, consolidating the integration of various security verifiers
like secure boot, gpg and tpm.
---
grub-core/Makefile.core.def | 4 +-
grub-core/loader/arm64/efi/linux.c | 443 +++++++++++++++++++++++++++++
include/grub/arm/linux.h | 9 +
include/grub/arm64/linux.h | 10 +
4 files changed, 465 insertions(+), 1 deletion(-)
create mode 100644 grub-core/loader/arm64/efi/linux.c
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1854,7 +1854,7 @@
arm_coreboot = loader/arm/linux.c;
arm_efi = loader/efi/linux.c;
arm_uboot = loader/arm/linux.c;
- arm64 = loader/efi/linux.c;
+ arm64 = loader/arm64/efi/linux.c;
loongarch64 = loader/efi/linux.c;
riscv32 = loader/efi/linux.c;
riscv64 = loader/efi/linux.c;
@@ -1922,7 +1922,7 @@
module = {
name = linuxefi;
- efi = lib/fake_module.c;
+ x86 = lib/fake_module.c;
enable = i386_efi;
enable = x86_64_efi;
};
--- /dev/null
+++ b/grub-core/loader/arm64/efi/linux.c
@@ -0,0 +1,411 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2013 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/>.
+ */
+
+#include <grub/charset.h>
+#include <grub/command.h>
+#include <grub/err.h>
+#include <grub/file.h>
+#include <grub/fdt.h>
+#include <grub/linux.h>
+#include <grub/loader.h>
+#include <grub/mm.h>
+#include <grub/types.h>
+#include <grub/cpu/linux.h>
+#include <grub/efi/efi.h>
+#include <grub/efi/fdtload.h>
+#include <grub/efi/memory.h>
+#include <grub/efi/pe32.h>
+#include <grub/i18n.h>
+#include <grub/lib/cmdline.h>
+#include <grub/verify.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static grub_dl_t my_mod;
+static int loaded;
+
+static void *kernel_addr;
+static grub_uint64_t kernel_size;
+static grub_uint32_t handover_offset;
+
+static char *linux_args;
+static grub_uint32_t cmdline_size;
+
+static grub_addr_t initrd_start;
+static grub_addr_t initrd_end;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+
+typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *);
+
+static grub_err_t
+grub_efi_linux_boot (void *kernel_address, grub_off_t offset,
+ void *kernel_params)
+{
+ handover_func hf;
+
+ hf = (handover_func)((char *)kernel_address + offset);
+ hf (grub_efi_image_handle, grub_efi_system_table, kernel_params);
+
+ return GRUB_ERR_BUG;
+}
+
+#pragma GCC diagnostic pop
+
+static grub_err_t
+grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh)
+{
+ if (lh->magic != GRUB_LINUX_ARMXX_MAGIC_SIGNATURE)
+ return grub_error(GRUB_ERR_BAD_OS, "invalid magic number");
+
+ if ((lh->code0 & 0xffff) != GRUB_PE32_MAGIC)
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ N_("plain image kernel not supported - rebuild with CONFIG_(U)EFI_STUB enabled"));
+
+ grub_dprintf ("linux", "UEFI stub kernel:\n");
+ grub_dprintf ("linux", "PE/COFF header @ %08x\n", lh->hdr_offset);
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+finalize_params_linux (void)
+{
+ grub_efi_loaded_image_t *loaded_image = NULL;
+ int node, retval, len;
+
+ void *fdt;
+
+ fdt = grub_fdt_load (GRUB_EFI_LINUX_FDT_EXTRA_SPACE);
+
+ if (!fdt)
+ goto failure;
+
+ node = grub_fdt_find_subnode (fdt, 0, "chosen");
+ if (node < 0)
+ node = grub_fdt_add_subnode (fdt, 0, "chosen");
+
+ if (node < 1)
+ goto failure;
+
+ /* Set initrd info */
+ if (initrd_start && initrd_end > initrd_start)
+ {
+ grub_dprintf ("linux", "Initrd @ %p-%p\n",
+ (void *) initrd_start, (void *) initrd_end);
+
+ retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-start",
+ initrd_start);
+ if (retval)
+ goto failure;
+ retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-end",
+ initrd_end);
+ if (retval)
+ goto failure;
+ }
+
+ if (grub_fdt_install() != GRUB_ERR_NONE)
+ goto failure;
+
+ grub_dprintf ("linux", "Installed/updated FDT configuration table @ %p\n",
+ fdt);
+
+ /* Convert command line to UCS-2 */
+ loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
+ if (!loaded_image)
+ goto failure;
+
+ loaded_image->load_options_size = len =
+ (grub_strlen (linux_args) + 1) * sizeof (grub_efi_char16_t);
+ loaded_image->load_options =
+ grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
+ if (!loaded_image->load_options)
+ return grub_error(GRUB_ERR_BAD_OS, "failed to create kernel parameters");
+
+ loaded_image->load_options_size =
+ 2 * grub_utf8_to_utf16 (loaded_image->load_options, len,
+ (grub_uint8_t *) linux_args, len, NULL);
+
+ return GRUB_ERR_NONE;
+
+failure:
+ grub_fdt_unload();
+ return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT");
+}
+
+static void
+free_params (void)
+{
+ grub_efi_loaded_image_t *loaded_image = NULL;
+
+ loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
+ if (loaded_image)
+ {
+ if (loaded_image->load_options)
+ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_efi_uintn_t)loaded_image->load_options,
+ GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
+ loaded_image->load_options = NULL;
+ loaded_image->load_options_size = 0;
+ }
+}
+
+grub_err_t
+grub_arch_efi_linux_boot_image (grub_addr_t addr,
+ grub_size_t size __attribute__ ((unused)),
+ char *args)
+{
+ grub_err_t retval;
+
+ retval = finalize_params_linux ();
+ if (retval != GRUB_ERR_NONE)
+ return grub_errno;
+
+ grub_dprintf ("linux", "linux command line: '%s'\n", args);
+
+ retval = grub_efi_linux_boot ((char *)addr, handover_offset, (void *)addr);
+
+ /* Never reached... */
+ free_params();
+ return retval;
+}
+
+static grub_err_t
+grub_linux_boot (void)
+{
+ return (grub_arch_efi_linux_boot_image ((grub_addr_t)kernel_addr, kernel_size, linux_args));
+}
+
+static grub_err_t
+grub_linux_unload (void)
+{
+ grub_dl_unref (my_mod);
+ loaded = 0;
+ if (initrd_start)
+ grub_efi_free_pages ((grub_efi_physical_address_t) initrd_start,
+ GRUB_EFI_BYTES_TO_PAGES (initrd_end - initrd_start));
+ initrd_start = initrd_end = 0;
+ grub_free (linux_args);
+ if (kernel_addr)
+ grub_efi_free_pages ((grub_addr_t) kernel_addr,
+ GRUB_EFI_BYTES_TO_PAGES (kernel_size));
+ grub_fdt_unload ();
+ return GRUB_ERR_NONE;
+}
+
+/*
+ * As per linux/Documentation/arm/Booting
+ * ARM initrd needs to be covered by kernel linear mapping,
+ * so place it in the first 512MB of DRAM.
+ *
+ * As per linux/Documentation/arm64/booting.txt
+ * ARM64 initrd needs to be contained entirely within a 1GB aligned window
+ * of up to 32GB of size that covers the kernel image as well.
+ * Since the EFI stub loader will attempt to load the kernel near start of
+ * RAM, place the buffer in the first 32GB of RAM.
+ */
+#ifdef __arm__
+#define INITRD_MAX_ADDRESS_OFFSET (512U * 1024 * 1024)
+#else /* __aarch64__ */
+#define INITRD_MAX_ADDRESS_OFFSET (32ULL * 1024 * 1024 * 1024)
+#endif
+
+/*
+ * This function returns a pointer to a legally allocated initrd buffer,
+ * or NULL if unsuccessful
+ */
+static void *
+allocate_initrd_mem (int initrd_pages)
+{
+ grub_addr_t max_addr;
+
+ if (grub_efi_get_ram_base (&max_addr) != GRUB_ERR_NONE)
+ return NULL;
+
+ max_addr += INITRD_MAX_ADDRESS_OFFSET - 1;
+
+ return grub_efi_allocate_pages_real (max_addr, initrd_pages,
+ GRUB_EFI_ALLOCATE_MAX_ADDRESS,
+ GRUB_EFI_LOADER_DATA);
+}
+
+static grub_err_t
+grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char *argv[])
+{
+ struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 };
+ int initrd_size, initrd_pages;
+ void *initrd_mem = NULL;
+
+ if (argc == 0)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+ goto fail;
+ }
+
+ if (!loaded)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("you need to load the kernel first"));
+ goto fail;
+ }
+
+ if (grub_initrd_init (argc, argv, &initrd_ctx))
+ goto fail;
+
+ initrd_size = grub_get_initrd_size (&initrd_ctx);
+ grub_dprintf ("linux", "Loading initrd\n");
+
+ initrd_pages = (GRUB_EFI_BYTES_TO_PAGES (initrd_size));
+ initrd_mem = allocate_initrd_mem (initrd_pages);
+
+ if (!initrd_mem)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+ goto fail;
+ }
+
+ if (grub_initrd_load (&initrd_ctx, initrd_mem))
+ goto fail;
+
+ initrd_start = (grub_addr_t) initrd_mem;
+ initrd_end = initrd_start + initrd_size;
+ grub_dprintf ("linux", "[addr=%p, size=0x%x]\n",
+ (void *) initrd_start, initrd_size);
+
+ fail:
+ grub_initrd_close (&initrd_ctx);
+ if (initrd_mem && !initrd_start)
+ grub_efi_free_pages ((grub_addr_t) initrd_mem, initrd_pages);
+
+ return grub_errno;
+}
+
+static grub_err_t
+grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char *argv[])
+{
+ grub_file_t file = 0;
+ struct linux_arch_kernel_header lh;
+ struct grub_armxx_linux_pe_header *pe;
+ grub_err_t err;
+
+ grub_dl_ref (my_mod);
+
+ if (argc == 0)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+ goto fail;
+ }
+
+ file = grub_file_open (argv[0], GRUB_FILE_TYPE_LINUX_KERNEL);
+ if (!file)
+ goto fail;
+
+ kernel_size = grub_file_size (file);
+
+ if (grub_file_read (file, &lh, sizeof (lh)) < (long) sizeof (lh))
+ return grub_errno;
+
+ if (grub_arch_efi_linux_check_image (&lh) != GRUB_ERR_NONE)
+ goto fail;
+
+ grub_loader_unset();
+
+ grub_dprintf ("linux", "kernel file size: %lld\n", (long long) kernel_size);
+ kernel_addr = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (kernel_size));
+ grub_dprintf ("linux", "kernel numpages: %lld\n",
+ (long long) GRUB_EFI_BYTES_TO_PAGES (kernel_size));
+ if (!kernel_addr)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+ goto fail;
+ }
+
+ grub_file_seek (file, 0);
+ if (grub_file_read (file, kernel_addr, kernel_size)
+ < (grub_int64_t) kernel_size)
+ {
+ if (!grub_errno)
+ grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]);
+ goto fail;
+ }
+
+ grub_dprintf ("linux", "kernel @ %p\n", kernel_addr);
+
+ pe = (void *)((unsigned long)kernel_addr + lh.hdr_offset);
+ handover_offset = pe->opt.entry_addr;
+
+ cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE);
+ linux_args = grub_malloc (cmdline_size);
+ if (!linux_args)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+ goto fail;
+ }
+ grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE));
+ err = grub_create_loader_cmdline (argc, argv,
+ linux_args + sizeof (LINUX_IMAGE) - 1,
+ cmdline_size,
+ GRUB_VERIFY_KERNEL_CMDLINE);
+ if (err)
+ goto fail;
+
+ if (grub_errno == GRUB_ERR_NONE)
+ {
+ grub_loader_set (grub_linux_boot, grub_linux_unload, 0);
+ loaded = 1;
+ }
+
+fail:
+ if (file)
+ grub_file_close (file);
+
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ grub_dl_unref (my_mod);
+ loaded = 0;
+ }
+
+ if (linux_args && !loaded)
+ grub_free (linux_args);
+
+ if (kernel_addr && !loaded)
+ grub_efi_free_pages ((grub_addr_t) kernel_addr,
+ GRUB_EFI_BYTES_TO_PAGES (kernel_size));
+
+ return grub_errno;
+}
+
+
+static grub_command_t cmd_linux, cmd_initrd;
+
+GRUB_MOD_INIT (linux)
+{
+ cmd_linux = grub_register_command ("linux", grub_cmd_linux, 0,
+ N_("Load Linux."));
+ cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, 0,
+ N_("Load initrd."));
+ my_mod = mod;
+}
+
+GRUB_MOD_FINI (linux)
+{
+ grub_unregister_command (cmd_linux);
+ grub_unregister_command (cmd_initrd);
+}
--- a/include/grub/arm/linux.h
+++ b/include/grub/arm/linux.h
@@ -20,10 +20,22 @@
#ifndef GRUB_ARM_LINUX_HEADER
#define GRUB_ARM_LINUX_HEADER 1
+#include <grub/efi/pe32.h>
#include "system.h"
#include <grub/efi/pe32.h>
+struct grub_arm_linux_pe_header
+{
+ grub_uint32_t magic;
+ struct grub_pe32_coff_header coff;
+ struct grub_pe32_optional_header opt;
+};
+
+#if defined(__arm__)
+# define grub_armxx_linux_pe_header grub_arm_linux_pe_header
+#endif
+
#if defined GRUB_MACHINE_UBOOT
# include <grub/uboot/uboot.h>
# define LINUX_ADDRESS (start_of_ram + 0x8000)
--- /dev/null
+++ b/include/grub/arm64/linux.h
@@ -0,0 +1,39 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2013 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_ARM64_LINUX_HEADER
+#define GRUB_ARM64_LINUX_HEADER 1
+
+#include <grub/types.h>
+#include <grub/efi/pe32.h>
+
+#define GRUB_LINUX_ARM64_MAGIC_SIGNATURE 0x644d5241 /* 'ARM\x64' */
+
+struct grub_arm64_linux_pe_header
+{
+ grub_uint32_t magic;
+ struct grub_pe32_coff_header coff;
+ struct grub_pe64_optional_header opt;
+};
+
+#if defined(__aarch64__)
+# define GRUB_LINUX_ARMXX_MAGIC_SIGNATURE GRUB_LINUX_ARM64_MAGIC_SIGNATURE
+# define grub_armxx_linux_pe_header grub_arm64_linux_pe_header
+#endif
+
+#endif /* ! GRUB_ARM64_LINUX_HEADER */

View File

@ -0,0 +1,215 @@
From 82d95254ca0496c8843113665bb9a99876101025 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 8 Oct 2021 13:36:45 +0800
Subject: [PATCH 01/11] Factor out grub_efi_linux_boot
Both x86 and arm64 on efi are using handover protocol to boot linux
kernel. To enable better code reuse, factor out grub_efi_linux_boot from
arm64 so that it can be shared with x86 platform for the common fixes.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/Makefile.core.def | 1 +
grub-core/loader/arm64/efi/linux.c | 35 +-----------------
grub-core/loader/efi/linux.c | 58 ++++++++++++++++++++++++++++++
grub-core/loader/i386/efi/linux.c | 13 ++-----
include/grub/efi/linux.h | 29 +++++++++++++++
5 files changed, 92 insertions(+), 44 deletions(-)
create mode 100644 grub-core/loader/efi/linux.c
create mode 100644 include/grub/efi/linux.h
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1860,6 +1860,9 @@
riscv64 = loader/efi/linux.c;
emu = loader/emu/linux.c;
common = loader/linux.c;
+ i386_efi = loader/efi/linux_boot.c;
+ x86_64_efi = loader/efi/linux_boot.c;
+ arm64 = loader/efi/linux_boot.c;
};
module = {
--- a/grub-core/loader/arm64/efi/linux.c
+++ b/grub-core/loader/arm64/efi/linux.c
@@ -33,6 +33,7 @@
#include <grub/i18n.h>
#include <grub/lib/cmdline.h>
#include <grub/verify.h>
+#include <grub/efi/linux.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -51,40 +52,6 @@
static grub_addr_t initrd_start;
static grub_addr_t initrd_end;
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wcast-align"
-
-typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *);
-
-static grub_err_t
-grub_efi_linux_boot (void *kernel_address, grub_off_t offset,
- void *kernel_params)
-{
- grub_efi_loaded_image_t *loaded_image = NULL;
- handover_func hf;
-
- /*
- * Since the EFI loader is not calling the LoadImage() and StartImage()
- * services for loading the kernel and booting respectively, it has to
- * set the Loaded Image base address.
- */
- loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
- if (loaded_image)
- loaded_image->image_base = kernel_addr;
- else
- grub_dprintf ("linux", "Loaded Image base address could not be set\n");
-
- grub_dprintf ("linux", "kernel_addr: %p handover_offset: %p params: %p\n",
- kernel_address, (void *)(grub_efi_uintn_t)offset, kernel_params);
- hf = (handover_func)((char *)kernel_address + offset);
- grub_dprintf ("linux", "handover_func() = %p\n", hf);
- hf (grub_efi_image_handle, grub_efi_system_table, kernel_params);
-
- return GRUB_ERR_BUG;
-}
-
-#pragma GCC diagnostic pop
-
static grub_err_t
grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh)
{
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -26,6 +26,7 @@
#include <grub/i18n.h>
#include <grub/lib/cmdline.h>
#include <grub/efi/efi.h>
+#include <grub/efi/linux.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -40,26 +41,18 @@
#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12)
-typedef void(*handover_func)(void *, grub_efi_system_table_t *, struct linux_kernel_params *);
-
static grub_err_t
grub_linuxefi_boot (void)
{
- handover_func hf;
int offset = 0;
#ifdef __x86_64__
offset = 512;
#endif
-
- hf = (handover_func)((char *)kernel_mem + handover_offset + offset);
-
asm volatile ("cli");
- hf (grub_efi_image_handle, grub_efi_system_table, params);
-
- /* Not reached */
- return GRUB_ERR_NONE;
+ return grub_efi_linux_boot ((char *)kernel_mem, handover_offset + offset,
+ params);
}
static grub_err_t
--- /dev/null
+++ b/include/grub/efi/linux.h
@@ -0,0 +1,29 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2014 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_EFI_LINUX_HEADER
+#define GRUB_EFI_LINUX_HEADER 1
+
+#include <grub/efi/api.h>
+#include <grub/err.h>
+#include <grub/symbol.h>
+
+grub_err_t
+EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_off_t offset,
+ void *kernel_param);
+
+#endif /* ! GRUB_EFI_LINUX_HEADER */
--- /dev/null
+++ b/grub-core/loader/efi/linux_boot.c
@@ -0,0 +1,58 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2014 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/>.
+ */
+
+#include <grub/err.h>
+#include <grub/mm.h>
+#include <grub/types.h>
+#include <grub/cpu/linux.h>
+#include <grub/efi/efi.h>
+#include <grub/efi/pe32.h>
+#include <grub/efi/linux.h>
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+
+typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *);
+
+grub_err_t
+grub_efi_linux_boot (void *kernel_addr, grub_off_t offset,
+ void *kernel_params)
+{
+ grub_efi_loaded_image_t *loaded_image = NULL;
+ handover_func hf;
+
+ /*
+ * Since the EFI loader is not calling the LoadImage() and StartImage()
+ * services for loading the kernel and booting respectively, it has to
+ * set the Loaded Image base address.
+ */
+ loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
+ if (loaded_image)
+ loaded_image->image_base = kernel_addr;
+ else
+ grub_dprintf ("linux", "Loaded Image base address could not be set\n");
+
+ grub_dprintf ("linux", "kernel_addr: %p handover_offset: %p params: %p\n",
+ kernel_addr, (void *)(grub_efi_uintn_t)offset, kernel_params);
+ hf = (handover_func)((char *)kernel_addr + offset);
+ hf (grub_efi_image_handle, grub_efi_system_table, kernel_params);
+
+ return GRUB_ERR_BUG;
+}
+
+#pragma GCC diagnostic pop

View File

@ -0,0 +1,66 @@
From f76317d9dc35dbc576820ba6c2a6a8e41f5338b5 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 19 May 2022 13:08:12 +0800
Subject: [PATCH] Fix infinite boot loop on headless system in qemu
After finishing headless virtual machine installation via serial
console, the reboot fails in grub with infinte boot loop and also
keyboard input for serial console is unresponsive.
The cause of infinte loop boils down to legacy vga driver in grub
crashes when '-dispaly none' is used as qemu's display type described in
the manual as:
"Do not display video output. The guest will still see an emulated
graphics card, but its output will not be displayed tothe QEMU user.
This option differs from the -nographic option in that it only affects
what is done with video output; -nographic also changes the destination
of the serial and parallel port data."
Given there's no sensible way found to skip the emulated device from the
legacy vga module, we ended up removing it from all_video dependency so
it wouldn't be loaded by default. In any case, the vbe module remain
loaded and should fulfill the requirement of most hardwares even twenty
years old or more.
The unresponsive serial input is also fixed by ensuring that console
input is loaded via appended so that they won't fail altogether with
errors by other console device if specifying on the same list.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/genmoddep.awk | 3 +++
util/grub.d/00_header.in | 10 +++++++++-
2 files changed, 12 insertions(+), 1 deletion(-)
--- a/grub-core/genmoddep.awk
+++ b/grub-core/genmoddep.awk
@@ -98,6 +98,9 @@
}
modlist = ""
while (getline <"video.lst") {
+ if ($1 == "vga") {
+ continue;
+ }
modlist = modlist " " $1;
}
printf "all_video:%s\n", modlist;
--- a/util/grub.d/00_header.in
+++ b/util/grub.d/00_header.in
@@ -287,7 +287,15 @@
;;
x*)
cat << EOF
-terminal_output ${GRUB_TERMINAL_OUTPUT}
+
+for i in ${GRUB_TERMINAL_OUTPUT}; do
+ if [ x\${use_append} = xtrue ]; then
+ terminal_output --append \$i
+ elif terminal_output \$i; then
+ use_append=true;
+ fi
+done
+
EOF
;;
esac

View File

@ -0,0 +1,286 @@
From 27b3e919b9b51a4fedeb3a5aef19c87f0cd7b687 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 17 Nov 2023 12:32:59 +0800
Subject: [PATCH] Improve TPM key protection on boot interruptions
The unattended boot process for full disk encryption relies on an
authorized TPM policy to ensure the system's integrity before releasing
the key to grub. Subsequently, grub assumes responsibility for securing
the boot process, directing it towards a trusted default without any
expected interruptions. Any interruption during this process indicates
potential modification attempts, and releasing the obtained key to the
next stage should not occur in such cases.
This commit addresses a vulnerability associated with interrupted boot
processes that could potentially enable malicious modifications to the
default or trusted boot target. To reinforce system security, the code
has been updated to incorporate measures that discard the TPM protected
key in the event of boot interruptions.
Furthermore, this patch aims to enhance code readability by renaming
structures and function names related to cryptographic keys, improving
clarity and maintainability.
By implementing these changes, this enhancement seeks to fortify the
protection of TPM keys, thereby ensuring a more robust defense against
potential unauthorized modifications during the boot process.
Signed-Off-by Michael Chang <mchang@suse.com>
---
grub-core/commands/crypttab.c | 38 ++++++++++++++++++++++++++---------
grub-core/disk/cryptodisk.c | 8 +++++++-
grub-core/loader/linux.c | 6 +++---
grub-core/normal/main.c | 2 +-
grub-core/normal/menu.c | 7 +++++++
grub-core/normal/menu_entry.c | 2 +-
include/grub/crypttab.h | 18 ++++++++++-------
7 files changed, 59 insertions(+), 22 deletions(-)
diff --git a/grub-core/commands/crypttab.c b/grub-core/commands/crypttab.c
index c2217ca98..9397bede9 100644
--- a/grub-core/commands/crypttab.c
+++ b/grub-core/commands/crypttab.c
@@ -9,17 +9,20 @@
GRUB_MOD_LICENSE ("GPLv3+");
-struct grub_key_publisher *kpuber;
+grub_crypto_key_list_t *cryptokey_lst;
grub_err_t
-grub_initrd_publish_key (const char *uuid, const char *key, grub_size_t key_len, const char *path)
+grub_cryptokey_add_or_update (const char *uuid, const char *key, grub_size_t key_len, const char *path, int is_tpmkey)
{
- struct grub_key_publisher *cur = NULL;
+ grub_crypto_key_list_t *cur = NULL;
- FOR_LIST_ELEMENTS (cur, kpuber)
+ FOR_LIST_ELEMENTS (cur, cryptokey_lst)
if (grub_uuidcasecmp (cur->name, uuid, sizeof (cur->name)) == 0)
break;
+ if (!cur && !uuid)
+ return GRUB_ERR_NONE;
+
if (!cur)
cur = grub_zalloc (sizeof (*cur));
if (!cur)
@@ -44,21 +47,24 @@ grub_initrd_publish_key (const char *uuid, const char *key, grub_size_t key_len,
cur->path = grub_strdup (path);
}
+ if (is_tpmkey >= 0)
+ cur->is_tpmkey = is_tpmkey;
+
if (!cur->name)
{
cur->name = grub_strdup (uuid);
- grub_list_push (GRUB_AS_LIST_P (&kpuber), GRUB_AS_LIST (cur));
+ grub_list_push (GRUB_AS_LIST_P (&cryptokey_lst), GRUB_AS_LIST (cur));
}
return GRUB_ERR_NONE;
}
void
-grub_initrd_discard_key (void)
+grub_cryptokey_discard (void)
{
- struct grub_key_publisher *cur, *nxt;
+ grub_crypto_key_list_t *cur, *nxt;
- FOR_LIST_ELEMENTS_SAFE (cur, nxt, kpuber)
+ FOR_LIST_ELEMENTS_SAFE (cur, nxt, cryptokey_lst)
{
grub_list_remove (GRUB_AS_LIST (cur));
grub_memset (cur->key, 0, cur->key_len);
@@ -69,6 +75,20 @@ grub_initrd_discard_key (void)
}
}
+void
+grub_cryptokey_tpmkey_discard (void)
+{
+ grub_crypto_key_list_t *cur = NULL;
+
+ FOR_LIST_ELEMENTS (cur, cryptokey_lst)
+ if (cur->is_tpmkey)
+ break;
+
+ /* Discard all keys if any of them is tpm */
+ if (cur)
+ grub_cryptokey_discard();
+}
+
static grub_err_t
grub_cmd_crypttab_entry (grub_command_t cmd __attribute__ ((unused)),
int argc, char **argv)
@@ -92,7 +112,7 @@ grub_cmd_crypttab_entry (grub_command_t cmd __attribute__ ((unused)),
}
/*FIXME: Validate UUID string*/
- return grub_initrd_publish_key (argv[1], NULL, 0, path);
+ return grub_cryptokey_add_or_update (argv[1], NULL, 0, path, -1);
}
static grub_command_t cmd;
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index aa0d43562..babc94868 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -1071,6 +1071,9 @@ grub_cryptodisk_scan_device_real (const char *name,
struct cryptodisk_read_hook_ctx read_hook_data = {0};
int askpass = 0;
char *part = NULL;
+#ifndef GRUB_UTIL
+ int is_tpmkey = 0;
+#endif
dev = grub_cryptodisk_get_by_source_disk (source);
@@ -1183,6 +1186,9 @@ grub_cryptodisk_scan_device_real (const char *name,
ret = grub_cryptodisk_insert (dev, name, source);
if (ret != GRUB_ERR_NONE)
goto error;
+#ifndef GRUB_UTIL
+ is_tpmkey = 1;
+#endif
goto cleanup;
}
}
@@ -1244,7 +1250,7 @@ grub_cryptodisk_scan_device_real (const char *name,
#ifndef GRUB_UTIL
if (cargs->key_data && dev)
- grub_initrd_publish_key (dev->uuid, (const char *)cargs->key_data, cargs->key_len, NULL);
+ grub_cryptokey_add_or_update (dev->uuid, (const char *)cargs->key_data, cargs->key_len, NULL, is_tpmkey);
#endif
if (askpass)
{
diff --git a/grub-core/loader/linux.c b/grub-core/loader/linux.c
index 9ee8f3790..e5e792958 100644
--- a/grub-core/loader/linux.c
+++ b/grub-core/loader/linux.c
@@ -226,13 +226,13 @@ grub_initrd_init (int argc, char *argv[],
int i;
int newc = 0;
struct dir *root = 0;
- struct grub_key_publisher *pk;
+ grub_crypto_key_list_t *pk;
int numkey = 0;
initrd_ctx->nfiles = 0;
initrd_ctx->components = 0;
- FOR_LIST_ELEMENTS (pk, kpuber)
+ FOR_LIST_ELEMENTS (pk, cryptokey_lst)
if (pk->key && pk->path)
numkey++;
@@ -305,7 +305,7 @@ grub_initrd_init (int argc, char *argv[],
goto overflow;
}
- FOR_LIST_ELEMENTS (pk, kpuber)
+ FOR_LIST_ELEMENTS (pk, cryptokey_lst)
if (pk->key && pk->path)
{
grub_initrd_component (pk->key, pk->key_len, pk->path, initrd_ctx);
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
index a3f711d1d..1b426af69 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -479,7 +479,7 @@ grub_cmdline_run (int nested, int force_auth)
return;
}
- grub_initrd_discard_key ();
+ grub_cryptokey_discard ();
grub_normal_reader_init (nested);
while (1)
diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c
index 14b0ab1ec..1df2638d7 100644
--- a/grub-core/normal/menu.c
+++ b/grub-core/normal/menu.c
@@ -32,6 +32,7 @@
#include <grub/script_sh.h>
#include <grub/gfxterm.h>
#include <grub/dl.h>
+#include <grub/crypttab.h>
/* Time to delay after displaying an error message about a default/fallback
entry failing to boot. */
@@ -708,6 +709,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot, int *notify_boot)
if (grub_key_is_interrupt (key))
{
timeout = -1;
+ grub_cryptokey_tpmkey_discard();
break;
}
@@ -790,6 +792,11 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot, int *notify_boot)
clear_timeout ();
}
+ /* Timeout is interrupted by external input, Forget tpmkey if timeout
+ * is not cut by enter */
+ if (c != '\n' && c != '\r')
+ grub_cryptokey_tpmkey_discard();
+
switch (c)
{
case GRUB_TERM_KEY_HOME:
diff --git a/grub-core/normal/menu_entry.c b/grub-core/normal/menu_entry.c
index 384ab9ce3..e5ba91ea4 100644
--- a/grub-core/normal/menu_entry.c
+++ b/grub-core/normal/menu_entry.c
@@ -1263,7 +1263,7 @@ grub_menu_entry_run (grub_menu_entry_t entry)
return;
}
- grub_initrd_discard_key();
+ grub_cryptokey_discard();
screen = make_screen (entry);
if (! screen)
diff --git a/include/grub/crypttab.h b/include/grub/crypttab.h
index 113c53cfc..f86404686 100644
--- a/include/grub/crypttab.h
+++ b/include/grub/crypttab.h
@@ -4,21 +4,25 @@
#include <grub/types.h>
#include <grub/err.h>
-struct grub_key_publisher
+typedef struct grub_crypto_key_list
{
- struct grub_key_publisher *next;
- struct grub_key_publisher **prev;
+ struct grub_crypto_key_list *next;
+ struct grub_crypto_key_list **prev;
char *name; /* UUID */
char *path;
char *key;
grub_size_t key_len;
-};
+ int is_tpmkey;
+} grub_crypto_key_list_t;
-extern struct grub_key_publisher *EXPORT_VAR (kpuber);
+extern grub_crypto_key_list_t *EXPORT_VAR (cryptokey_lst);
grub_err_t
-grub_initrd_publish_key (const char *uuid, const char *key, grub_size_t key_len, const char *path);
+grub_cryptokey_add_or_update (const char *uuid, const char *key, grub_size_t key_len, const char *path, int is_tpmkey);
void
-grub_initrd_discard_key (void);
+grub_cryptokey_discard (void);
+
+void
+grub_cryptokey_tpmkey_discard (void);
#endif /* ! GRUB_CRYPTTAB_HEADER */
--
2.35.3

View File

@ -0,0 +1,82 @@
From b8457f2e271917c5c83a4fee286bafedf8c5790c Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Tue, 8 Aug 2023 17:57:24 +0800
Subject: [PATCH] Make grub.cfg compatible to old binaries
The new added fwsetup test in the topmost menu is always executed
regardless older grub may not be able to handle and thus trapped in a
boot loop between grub and fwsetup.
This in particular is to make sure a smooth transition if grub is rolled
back to older release and needs to boot newer snapshots.
Also removing dashes in the UUID that every version released in the wild
can handle.
Signed-off-by: Michael Chang <mchang@suse.com>
---
util/grub-probe.c | 20 +++++++++++++++++++-
util/grub.d/30_uefi-firmware.in | 16 ++++++++++------
2 files changed, 29 insertions(+), 7 deletions(-)
diff --git a/util/grub-probe.c b/util/grub-probe.c
index e7efcc268..99c738e44 100644
--- a/util/grub-probe.c
+++ b/util/grub-probe.c
@@ -290,8 +290,26 @@ probe_cryptodisk_uuid (grub_disk_t disk, char delim)
}
if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID)
{
+ grub_size_t i, j;
const char *uu = grub_util_cryptodisk_get_uuid (disk);
- grub_printf ("%s%c", uu, delim);
+ grub_size_t len = grub_strlen (uu);
+ char *p = grub_malloc (len + 1);
+
+ /* Removing dash in the UUID string
+ * This keeps old grub binary to work with newer config in a system,
+ * especially for snapshots. It is a temporary change to make sure smooth
+ * transition from 2.06 to 2.12-rc1 and this hunk can be removed
+ * after 2.12-rc1 release stablized.
+ */
+ for (i = 0, j = 0; i < len; i++)
+ {
+ if (uu[i] != '-')
+ p[j++] = uu[i];
+ }
+ p[j] = '\0';
+
+ grub_printf ("%s%c", p, delim);
+ grub_free (p);
}
}
diff --git a/util/grub.d/30_uefi-firmware.in b/util/grub.d/30_uefi-firmware.in
index 1c2365ddb..96ff112e5 100644
--- a/util/grub.d/30_uefi-firmware.in
+++ b/util/grub.d/30_uefi-firmware.in
@@ -32,11 +32,15 @@ gettext_printf "Adding boot menu entry for UEFI Firmware Settings ...\n" >&2
cat << EOF
if [ "\$grub_platform" = "efi" ]; then
- fwsetup --is-supported
- if [ "\$?" = 0 ]; then
- menuentry '$LABEL' \$menuentry_id_option 'uefi-firmware' {
- fwsetup
- }
- fi
+ menuentry '$LABEL' \$menuentry_id_option 'uefi-firmware' {
+ fwsetup --is-supported
+ if [ "\$?" = 0 ]; then
+ fwsetup
+ else
+ echo "Your firmware doesn't support setup menu entry from a boot loader"
+ echo "Press any key to return ..."
+ read
+ fi
+ }
fi
EOF
--
2.41.0

View File

@ -0,0 +1,150 @@
From 80bb1b17b3f596dbd7331cf9cb20a46c8ef9800b Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Sat, 22 Aug 2020 02:32:43 +0800
Subject: [PATCH] Unify the check to enable btrfs relative path
This unified the test in grub-install and grub-mkconfig that the path to
default or selected btrfs subvolume/snapshot is used if the root file
system is btrfs and the config has enabled btrfs snapshot booting.
Signed-off-by: Michael Chang <mchang@suse.com>
---
util/grub-install.c | 67 +++++++++++++++++++++++++++------------
util/grub-mkconfig_lib.in | 3 +-
2 files changed, 48 insertions(+), 22 deletions(-)
--- a/util/grub-install.c
+++ b/util/grub-install.c
@@ -886,6 +886,7 @@
const char *efi_file = NULL;
char **grub_devices;
grub_fs_t grub_fs;
+ grub_fs_t root_fs;
grub_device_t grub_dev = NULL;
enum grub_install_plat platform;
char *grubdir, *device_map;
@@ -898,6 +899,8 @@
int efidir_is_mac = 0;
int is_prep = 0;
const char *pkgdatadir;
+ char *rootdir_path;
+ char **rootdir_devices;
grub_util_host_init (&argc, &argv);
product_version = xstrdup (PACKAGE_VERSION);
@@ -911,9 +914,6 @@
grub_util_load_config (&config);
- if (config.is_suse_btrfs_snapshot_enabled)
- use_relative_path_on_btrfs = 1;
-
if (!bootloader_id && config.grub_distributor)
{
char *ptr;
@@ -1064,6 +1064,45 @@
grub_hostfs_init ();
grub_host_init ();
+ {
+ char *rootdir_grub_devname;
+ grub_device_t rootdir_grub_dev;
+ char *t = grub_util_path_concat (2, "/", rootdir);
+
+ rootdir_path = grub_canonicalize_file_name (t);
+ if (!rootdir_path)
+ grub_util_error (_("failed to get canonical path of `%s'"), t);
+
+ rootdir_devices = grub_guess_root_devices (rootdir_path);
+ if (!rootdir_devices || !rootdir_devices[0])
+ grub_util_error (_("cannot find a device for %s (is /dev mounted?)"),
+ rootdir_path);
+
+ for (curdev = rootdir_devices; *curdev; curdev++)
+ grub_util_pull_device (*curdev);
+
+ rootdir_grub_devname = grub_util_get_grub_dev (rootdir_devices[0]);
+ if (!rootdir_grub_devname)
+ grub_util_error (_("cannot find a GRUB drive for %s. Check your device.map"),
+ rootdir_devices[0]);
+
+ rootdir_grub_dev = grub_device_open (rootdir_grub_devname);
+ if (! rootdir_grub_dev)
+ grub_util_error ("%s", grub_errmsg);
+
+ root_fs = grub_fs_probe (rootdir_grub_dev);
+ if (!root_fs)
+ grub_util_error ("%s", grub_errmsg);
+
+ if (config.is_suse_btrfs_snapshot_enabled
+ && grub_strncmp(root_fs->name, "btrfs", sizeof ("btrfs") - 1) == 0)
+ use_relative_path_on_btrfs = 1;
+
+ free (t);
+ free (rootdir_grub_devname);
+ grub_device_close (rootdir_grub_dev);
+ }
+
switch (platform)
{
case GRUB_INSTALL_PLATFORM_I386_EFI:
@@ -1478,8 +1517,7 @@
debug_image);
}
- if (config.is_suse_btrfs_snapshot_enabled
- && grub_strncmp(grub_fs->name, "btrfs", sizeof ("btrfs") - 1) == 0)
+ if (use_relative_path_on_btrfs)
{
if (!load_cfg_f)
load_cfg_f = grub_util_fopen (load_cfg, "wb");
@@ -1670,21 +1708,13 @@
#ifdef __linux__
- if (config.is_suse_btrfs_snapshot_enabled
- && grub_strncmp(grub_fs->name, "btrfs", sizeof ("btrfs") - 1) == 0)
+ if (use_relative_path_on_btrfs)
{
char *subvol = NULL;
char *mount_path = NULL;
- char **rootdir_devices = NULL;
- char *t = grub_util_path_concat (2, "/", rootdir);
- char *rootdir_path = grub_canonicalize_file_name (t);
-
- if (rootdir_path && grub_util_is_directory (rootdir_path))
- rootdir_devices = grub_guess_root_devices (rootdir_path);
-
- if (rootdir_devices && rootdir_devices[0])
- if (grub_strcmp (rootdir_devices[0], grub_devices[0]) == 0)
- subvol = grub_util_get_btrfs_subvol (platdir, &mount_path);
+
+ if (grub_strcmp (rootdir_devices[0], grub_devices[0]) == 0)
+ subvol = grub_util_get_btrfs_subvol (platdir, &mount_path);
if (subvol && mount_path)
{
@@ -1709,11 +1739,6 @@
}
}
- free (t);
- free (rootdir_path);
- for (curdev = rootdir_devices; *curdev; curdev++)
- free (*curdev);
- free (rootdir_devices);
free (subvol);
free (mount_path);
}
--- a/util/grub-mkconfig_lib.in
+++ b/util/grub-mkconfig_lib.in
@@ -49,7 +49,8 @@
make_system_path_relative_to_its_root ()
{
- if [ "x${SUSE_BTRFS_SNAPSHOT_BOOTING}" = "xtrue" ] ; then
+ if [ "x${SUSE_BTRFS_SNAPSHOT_BOOTING}" = "xtrue" ] &&
+ [ "x${GRUB_FS}" = "xbtrfs" ] ; then
"${grub_mkrelpath}" -r "$1"
else
"${grub_mkrelpath}" "$1"

View File

@ -0,0 +1,289 @@
From 71575829c303fe8522b46fc96b1f99f1aa4178e7 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 19 Mar 2021 22:58:45 +0800
Subject: [PATCH] Workaround volatile efi boot variable
The efi variable in Microsoft Azure virtual machine is volatile that it cannot
persist across power cycling. If we use efi variable to communicate with efi
boot manager for booting a distribution, the process would silently fail as the
default loader in the efi system partition will start to take over the process
whenever the efi variable evaporated.
That will lead to undefined symbol error one day as the default path didn't
receive any grub update so it cannot keep up with new ABI requirement by
updated grub modules.
The patch will try to workaround the problem by providing grub update to the
default path along with the distribution specific one. To avoid negative side
effects of inadvertently overwritting other loader intended in default path,
care must be taken to ensure that:
1. The workaround only takes place on detected Azure virtual machine
2. The default path is not in use by shim for the secure boot
---
Makefile.util.def | 1 +
.../osdep/basic/efi_removable_fallback.c | 26 +++
grub-core/osdep/efi_removable_fallback.c | 5 +
.../osdep/linux/efi_removable_fallback.c | 151 ++++++++++++++++++
include/grub/util/install.h | 3 +
util/grub-install.c | 19 +++
6 files changed, 205 insertions(+)
create mode 100644 grub-core/osdep/basic/efi_removable_fallback.c
create mode 100644 grub-core/osdep/efi_removable_fallback.c
create mode 100644 grub-core/osdep/linux/efi_removable_fallback.c
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -681,6 +681,9 @@
common = grub-core/osdep/journaled_fs.c;
extra_dist = grub-core/osdep/basic/journaled_fs.c;
extra_dist = grub-core/osdep/linux/journaled_fs.c;
+ common = grub-core/osdep/efi_removable_fallback.c;
+ extra_dist = grub-core/osdep/basic/efi_removable_fallback.c;
+ extra_dist = grub-core/osdep/linux/efi_removable_fallback.c;
ldadd = '$(LIBLZMA)';
ldadd = libgrubmods.a;
--- /dev/null
+++ b/grub-core/osdep/basic/efi_removable_fallback.c
@@ -0,0 +1,26 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2013 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/>.
+ */
+
+#include <grub/util/install.h>
+
+const char *
+grub_install_efi_removable_fallback (const char *efidir, enum grub_install_plat platform)
+{
+ return NULL;
+}
+
--- /dev/null
+++ b/grub-core/osdep/efi_removable_fallback.c
@@ -0,0 +1,5 @@
+#ifdef __linux__
+#include "linux/efi_removable_fallback.c"
+#else
+#include "basic/efi_removable_fallback.c"
+#endif
--- /dev/null
+++ b/grub-core/osdep/linux/efi_removable_fallback.c
@@ -0,0 +1,151 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2013 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/>.
+ */
+
+#include <config.h>
+
+#include <grub/util/install.h>
+#include <grub/emu/exec.h>
+#include <grub/emu/misc.h>
+#include <string.h>
+
+static char *
+get_dmi_id (const char *id)
+{
+ FILE *fp;
+ char *buf = NULL;
+ size_t len = 0;
+
+ char *dmi_entry;
+
+ dmi_entry = grub_util_path_concat (2, "/sys/class/dmi/id", id);
+
+ fp = grub_util_fopen (dmi_entry, "r");
+ if (!fp)
+ {
+ free (dmi_entry);
+ return NULL;
+ }
+
+ if (getline (&buf, &len, fp) == -1)
+ {
+ fclose (fp);
+ free (dmi_entry);
+ return NULL;
+ }
+
+ fclose (fp);
+ free (dmi_entry);
+ return buf;
+}
+
+
+static struct dmi {
+ const char *id;
+ const char *val;
+} azure_dmi [3] = {
+ {"bios_vendor", "Microsoft Corporation"},
+ {"product_name", "Virtual Machine"},
+ {"sys_vendor", "Microsoft Corporation"},
+};
+
+static int
+is_azure (void)
+{
+ int i;
+ int n = sizeof (azure_dmi) / sizeof (struct dmi);
+
+ for (i = 0; i < n; ++i)
+ {
+ char *val;
+
+ val = get_dmi_id (azure_dmi[i].id);
+ if (!val)
+ break;
+ if (strncmp (val, azure_dmi[i].val, strlen (azure_dmi[i].val)) != 0)
+ {
+ free (val);
+ break;
+ }
+ free (val);
+ }
+
+ return (i == n) ? 1 : 0;
+}
+
+static int
+guess_shim_installed (const char *instdir)
+{
+ const char *shim[] = {"fallback.efi", "MokManager.efi", NULL};
+ const char **s;
+
+ for (s = shim; *s ; ++s)
+ {
+ char *p = grub_util_path_concat (2, instdir, *s);
+
+ if (access (p, F_OK) == 0)
+ {
+ free (p);
+ return 1;
+ }
+ free (p);
+ }
+
+ return 0;
+}
+
+const char *
+grub_install_efi_removable_fallback (const char *efidir, enum grub_install_plat platform)
+{
+ char *instdir;
+
+ if (!is_azure ())
+ return NULL;
+
+ instdir = grub_util_path_concat (3, efidir, "EFI", "BOOT");
+
+ if (guess_shim_installed (instdir))
+ {
+ grub_util_info ("skip removable fallback occupied by shim");
+ return NULL;
+ }
+
+ free (instdir);
+
+ switch (platform)
+ {
+ case GRUB_INSTALL_PLATFORM_I386_EFI:
+ return "BOOTIA32.EFI";
+ case GRUB_INSTALL_PLATFORM_X86_64_EFI:
+ return "BOOTX64.EFI";
+ case GRUB_INSTALL_PLATFORM_IA64_EFI:
+ return "BOOTIA64.EFI";
+ case GRUB_INSTALL_PLATFORM_ARM_EFI:
+ return "BOOTARM.EFI";
+ case GRUB_INSTALL_PLATFORM_ARM64_EFI:
+ return "BOOTAA64.EFI";
+ case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
+ return "BOOTRISCV32.EFI";
+ case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
+ return "BOOTRISCV64.EFI";
+ default:
+ grub_util_error ("%s", _("You've found a bug"));
+ break;
+ }
+ return NULL;
+}
+
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -303,4 +303,7 @@
int
grub_install_sync_fs_journal (const char *path);
+
+const char *
+grub_install_efi_removable_fallback (const char *efidir, enum grub_install_plat platform);
#endif
--- a/util/grub-install.c
+++ b/util/grub-install.c
@@ -901,6 +901,7 @@
const char *pkgdatadir;
char *rootdir_path;
char **rootdir_devices;
+ char *efidir_root;
grub_util_host_init (&argc, &argv);
product_version = xstrdup (PACKAGE_VERSION);
@@ -1175,6 +1176,7 @@
}
if (!efidir)
grub_util_error ("%s", _("cannot find EFI directory"));
+ efidir_root = grub_strdup (efidir);
efidir_device_names = grub_guess_root_devices (efidir);
if (!efidir_device_names || !efidir_device_names[0])
grub_util_error (_("cannot find a device for %s (is /dev mounted?)"),
@@ -2217,6 +2219,23 @@
free (grub_efi_cfg);
}
}
+ if (!removable)
+ {
+ const char *f;
+
+ f = grub_install_efi_removable_fallback (efidir_root, platform);
+ if (f)
+ {
+ char *t = grub_util_path_concat (3, efidir_root, "EFI", "BOOT");
+ char *dst = grub_util_path_concat (2, t, f);
+
+ grub_install_mkdir_p (t);
+ fprintf (stderr, _("Install to %s as fallback.\n"), dst);
+ grub_install_copy_file (imgfile, dst, 1);
+ grub_free (t);
+ grub_free (dst);
+ }
+ }
if (!removable && update_nvram)
{
char * efifile_path;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,179 @@
From 10d0f70ac194931c63f2cbd6fdebd6697abae992 Mon Sep 17 00:00:00 2001
From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Date: Mon, 2 Aug 2021 23:10:01 +1000
Subject: [PATCH 1/2] arm64: Fix EFI loader kernel image allocation
We are currently allocating just enough memory for the file size,
which means that the kernel BSS is in limbo (and not even zeroed).
We are also not honoring the alignment specified in the image
PE header.
This makes us use the PE optional header in which the kernel puts the
actual size it needs, including BSS, and make sure we clear it, and
honors the specified alignment for the image.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
grub-core/loader/arm64/efi/linux.c | 92 ++++++++++++++++++++----------
1 file changed, 63 insertions(+), 29 deletions(-)
diff --git a/grub-core/loader/arm64/efi/linux.c b/grub-core/loader/arm64/efi/linux.c
index b73105347..4da49a182 100644
--- a/grub-core/loader/arm64/efi/linux.c
+++ b/grub-core/loader/arm64/efi/linux.c
@@ -39,6 +39,8 @@ GRUB_MOD_LICENSE ("GPLv3+");
static grub_dl_t my_mod;
static int loaded;
+static void *kernel_alloc_addr;
+static grub_uint32_t kernel_alloc_pages;
static void *kernel_addr;
static grub_uint64_t kernel_size;
static grub_uint32_t handover_offset;
@@ -258,9 +260,8 @@ grub_linux_unload (void)
GRUB_EFI_BYTES_TO_PAGES (initrd_end - initrd_start));
initrd_start = initrd_end = 0;
grub_free (linux_args);
- if (kernel_addr)
- grub_efi_free_pages ((grub_addr_t) kernel_addr,
- GRUB_EFI_BYTES_TO_PAGES (kernel_size));
+ if (kernel_alloc_addr)
+ grub_efi_free_pages ((grub_addr_t) kernel_alloc_addr, kernel_alloc_pages);
grub_fdt_unload ();
return GRUB_ERR_NONE;
}
@@ -365,14 +366,35 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
return grub_errno;
}
+static grub_err_t
+parse_pe_header (void *kernel, grub_uint64_t *total_size,
+ grub_uint32_t *entry_offset,
+ grub_uint32_t *alignment)
+{
+ struct linux_arch_kernel_header *lh = kernel;
+ struct grub_armxx_linux_pe_header *pe;
+
+ pe = (void *)((unsigned long)kernel + lh->hdr_offset);
+
+ if (pe->opt.magic != GRUB_PE32_PE64_MAGIC)
+ return grub_error(GRUB_ERR_BAD_OS, "Invalid PE optional header magic");
+
+ *total_size = pe->opt.image_size;
+ *entry_offset = pe->opt.entry_addr;
+ *alignment = pe->opt.section_alignment;
+
+ return GRUB_ERR_NONE;
+}
+
static grub_err_t
grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
grub_file_t file = 0;
- struct linux_arch_kernel_header lh;
- struct grub_armxx_linux_pe_header *pe;
grub_err_t err;
+ grub_off_t filelen;
+ grub_uint32_t align = 0;
+ void *kernel = NULL;
grub_dl_ref (my_mod);
@@ -386,39 +408,49 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
if (!file)
goto fail;
- kernel_size = grub_file_size (file);
+ filelen = grub_file_size (file);
+ kernel = grub_malloc(filelen);
+ if (!kernel)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel load buffer"));
+ goto fail;
+ }
- if (grub_file_read (file, &lh, sizeof (lh)) < (long) sizeof (lh))
- return grub_errno;
+ if (grub_file_read (file, kernel, filelen) < (grub_ssize_t)filelen)
+ {
+ grub_error (GRUB_ERR_FILE_READ_ERROR, N_("Can't read kernel %s"),
+ argv[0]);
+ goto fail;
+ }
- if (grub_arch_efi_linux_check_image (&lh) != GRUB_ERR_NONE)
+ grub_dprintf ("linux", "kernel @ %p\n", kernel_addr);
+
+ if (grub_arch_efi_linux_check_image (kernel) != GRUB_ERR_NONE)
+ goto fail;
+ if (parse_pe_header (kernel, &kernel_size, &handover_offset, &align) != GRUB_ERR_NONE)
goto fail;
+ grub_dprintf ("linux", "kernel mem size : %lld\n", (long long) kernel_size);
+ grub_dprintf ("linux", "kernel entry offset : %d\n", handover_offset);
+ grub_dprintf ("linux", "kernel alignment : 0x%x\n", align);
grub_loader_unset();
- grub_dprintf ("linux", "kernel file size: %lld\n", (long long) kernel_size);
- kernel_addr = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (kernel_size));
- grub_dprintf ("linux", "kernel numpages: %lld\n",
- (long long) GRUB_EFI_BYTES_TO_PAGES (kernel_size));
- if (!kernel_addr)
+ kernel_alloc_pages = GRUB_EFI_BYTES_TO_PAGES (kernel_size + align - 1);
+ kernel_alloc_addr = grub_efi_allocate_any_pages (kernel_alloc_pages);
+ grub_dprintf ("linux", "kernel numpages: %d\n", kernel_alloc_pages);
+ if (!kernel_alloc_addr)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
goto fail;
}
-
- grub_file_seek (file, 0);
- if (grub_file_read (file, kernel_addr, kernel_size)
- < (grub_int64_t) kernel_size)
- {
- if (!grub_errno)
- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]);
- goto fail;
- }
+ kernel_addr = (void *)ALIGN_UP((grub_uint64_t)kernel_alloc_addr, align);
grub_dprintf ("linux", "kernel @ %p\n", kernel_addr);
-
- pe = (void *)((unsigned long)kernel_addr + lh.hdr_offset);
- handover_offset = pe->opt.entry_addr;
+ grub_memcpy (kernel_addr, kernel, grub_min(filelen, kernel_size));
+ if (kernel_size > filelen)
+ grub_memset ((char *)kernel_addr + filelen, 0, kernel_size - filelen);
+ grub_free(kernel);
+ kernel = NULL;
cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE);
linux_args = grub_malloc (cmdline_size);
@@ -442,6 +474,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
}
fail:
+ if (kernel)
+ grub_free (kernel);
+
if (file)
grub_file_close (file);
@@ -454,9 +489,8 @@ fail:
if (linux_args && !loaded)
grub_free (linux_args);
- if (kernel_addr && !loaded)
- grub_efi_free_pages ((grub_addr_t) kernel_addr,
- GRUB_EFI_BYTES_TO_PAGES (kernel_size));
+ if (kernel_alloc_addr && !loaded)
+ grub_efi_free_pages ((grub_addr_t) kernel_alloc_addr, kernel_alloc_pages);
return grub_errno;
}
--
2.31.1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,205 @@
From e9422d6869f1b2d78a7cfbfcae1610953d87705b Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 16 Feb 2023 21:28:07 +0800
Subject: [PATCH 1/2] clean up crypttab and linux modules dependency
The linux module could have quite a few dependency to other modules, the
i386-pc build in particular has many.
linux: normal vbe video boot cmdline relocator mmap
That will be easy to cause loop dependency if one of these modules has
to require function from linux. To avoid falling into the pitfall in
future extension, we move away the key publish related function from
linux to crypttab module in that it is also a right thing to do.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/commands/crypttab.c | 48 +++++++++++++++++++++++++++++-
grub-core/disk/cryptodisk.c | 2 +-
grub-core/loader/linux.c | 55 +----------------------------------
include/grub/crypttab.h | 22 ++++++++++++++
include/grub/linux.h | 3 --
5 files changed, 71 insertions(+), 59 deletions(-)
create mode 100644 include/grub/crypttab.h
--- a/grub-core/commands/crypttab.c
+++ b/grub-core/commands/crypttab.c
@@ -3,10 +3,56 @@
#include <grub/command.h>
#include <grub/misc.h>
#include <grub/i18n.h>
-#include <grub/linux.h>
+#include <grub/mm.h>
+#include <grub/list.h>
+#include <grub/crypttab.h>
GRUB_MOD_LICENSE ("GPLv3+");
+struct grub_key_publisher *kpuber;
+
+grub_err_t
+grub_initrd_publish_key (const char *uuid, const char *key, grub_size_t key_len, const char *path)
+{
+ struct grub_key_publisher *cur = NULL;
+
+ FOR_LIST_ELEMENTS (cur, kpuber)
+ if (grub_uuidcasecmp (cur->name, uuid, sizeof (cur->name)) == 0)
+ break;
+
+ if (!cur)
+ cur = grub_zalloc (sizeof (*cur));
+ if (!cur)
+ return grub_errno;
+
+ if (key && key_len)
+ {
+ grub_free (cur->key);
+ cur->key = grub_malloc (key_len);
+ if (!cur->key)
+ {
+ grub_free (cur);
+ return grub_errno;
+ }
+ grub_memcpy (cur->key, key, key_len);
+ cur->key_len = key_len;
+ }
+
+ if (path)
+ {
+ grub_free (cur->path);
+ cur->path = grub_strdup (path);
+ }
+
+ if (!cur->name)
+ {
+ cur->name = grub_strdup (uuid);
+ grub_list_push (GRUB_AS_LIST_P (&kpuber), GRUB_AS_LIST (cur));
+ }
+
+ return GRUB_ERR_NONE;
+}
+
static grub_err_t
grub_cmd_crypttab_entry (grub_command_t cmd __attribute__ ((unused)),
int argc, char **argv)
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -31,7 +31,7 @@
#ifdef GRUB_UTIL
#include <grub/emu/hostdisk.h>
#else
-#include <grub/linux.h>
+#include <grub/crypttab.h>
#endif
GRUB_MOD_LICENSE ("GPLv3+");
--- a/grub-core/loader/linux.c
+++ b/grub-core/loader/linux.c
@@ -6,6 +6,7 @@
#include <grub/mm.h>
#include <grub/safemath.h>
#include <grub/list.h>
+#include <grub/crypttab.h>
struct newc_head
{
@@ -40,18 +41,6 @@
struct dir *child;
};
-struct grub_key_publisher
-{
- struct grub_key_publisher *next;
- struct grub_key_publisher **prev;
- char *name; /* UUID */
- char *path;
- char *key;
- grub_size_t key_len;
-};
-
-static struct grub_key_publisher *kpuber;
-
static char
hex (grub_uint8_t val)
{
@@ -436,45 +425,3 @@
root = 0;
return GRUB_ERR_NONE;
}
-
-grub_err_t
-grub_initrd_publish_key (const char *uuid, const char *key, grub_size_t key_len, const char *path)
-{
- struct grub_key_publisher *cur = NULL;
-
- FOR_LIST_ELEMENTS (cur, kpuber)
- if (grub_uuidcasecmp (cur->name, uuid, sizeof (cur->name)) == 0)
- break;
-
- if (!cur)
- cur = grub_zalloc (sizeof (*cur));
- if (!cur)
- return grub_errno;
-
- if (key && key_len)
- {
- grub_free (cur->key);
- cur->key = grub_malloc (key_len);
- if (!cur->key)
- {
- grub_free (cur);
- return grub_errno;
- }
- grub_memcpy (cur->key, key, key_len);
- cur->key_len = key_len;
- }
-
- if (path)
- {
- grub_free (cur->path);
- cur->path = grub_strdup (path);
- }
-
- if (!cur->name)
- {
- cur->name = grub_strdup (uuid);
- grub_list_push (GRUB_AS_LIST_P (&kpuber), GRUB_AS_LIST (cur));
- }
-
- return GRUB_ERR_NONE;
-}
--- /dev/null
+++ b/include/grub/crypttab.h
@@ -0,0 +1,22 @@
+#ifndef GRUB_CRYPTTAB_HEADER
+#define GRUB_CRYPTTAB_HEADER 1
+
+#include <grub/types.h>
+#include <grub/err.h>
+
+struct grub_key_publisher
+{
+ struct grub_key_publisher *next;
+ struct grub_key_publisher **prev;
+ char *name; /* UUID */
+ char *path;
+ char *key;
+ grub_size_t key_len;
+};
+
+extern struct grub_key_publisher *EXPORT_VAR (kpuber);
+
+grub_err_t
+grub_initrd_publish_key (const char *uuid, const char *key, grub_size_t key_len, const char *path);
+
+#endif /* ! GRUB_CRYPTTAB_HEADER */
--- a/include/grub/linux.h
+++ b/include/grub/linux.h
@@ -22,6 +22,3 @@
grub_err_t
grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx,
void *target);
-
-grub_err_t
-grub_initrd_publish_key (const char *uuid, const char *key, grub_size_t key_len, const char *path);

View File

@ -0,0 +1,37 @@
From 5846e14a4dbf0c73969a32625d841e4f842ccdea Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Wed, 31 Jan 2024 18:44:27 +0800
Subject: [PATCH] disk: Optimize disk iteration by moving memdisk to the end
When performing file or UUID-based searches, prioritize returning
operating system disk devices over the memdisk. The memdisk, typically
used for internal grub data, is moved to the last position in the search
order. This improves search efficiency and prevents potential unexpected
results.
Signed-off-by: Michael Chang <mchang@suse.com>
---
include/grub/disk.h | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/include/grub/disk.h b/include/grub/disk.h
index bf0958885..f4fd7a00f 100644
--- a/include/grub/disk.h
+++ b/include/grub/disk.h
@@ -244,7 +244,12 @@ grub_disk_dev_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data)
for (pull = 0; pull < GRUB_DISK_PULL_MAX; pull++)
for (p = grub_disk_dev_list; p; p = p->next)
- if (p->disk_iterate && (p->disk_iterate) (hook, hook_data, pull))
+ if (p->id != GRUB_DISK_DEVICE_MEMDISK_ID && p->disk_iterate && (p->disk_iterate) (hook, hook_data, pull))
+ return 1;
+
+ for (pull = 0; pull < GRUB_DISK_PULL_MAX; pull++)
+ for (p = grub_disk_dev_list; p; p = p->next)
+ if (p->id == GRUB_DISK_DEVICE_MEMDISK_ID && p->disk_iterate && (p->disk_iterate) (hook, hook_data, pull))
return 1;
return 0;
--
2.43.0

View File

@ -0,0 +1,103 @@
From 987ab0dfbe7ef42bb6386fb7b428d3b965ba6d2b Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Mon, 7 Sep 2020 17:02:57 +0800
Subject: [PATCH] efi/linux: provide linux command
The linux kernel's efi handover entry point is used to boot efistub of
the linux kernel. Since then the efistub has been improved with many new
features and fixes that ordinary 32-bit entry point cannot provide.
Besides, nearly every x86 efi kernel is built with efistub enabled so it
is of little value to keep 32-bit entry as default to boot kernel
without needed kconfig options enabled.
For all good reasons, making efi handover the default entry point for
booting kernel in x86 efi platform so that linux command works in the
same way to linuxefi. This can also reduce the complexity of providing
general grub configuation for x86 system due to the linux command may
not be available in signed image for UEFI Secure Boot and linuxefi is
not available for leagcy bios booting.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/Makefile.core.def | 6 ++++--
grub-core/gensyminfo.sh.in | 3 +++
grub-core/loader/i386/efi/linux.c | 17 +++++++++++++----
3 files changed, 20 insertions(+), 6 deletions(-)
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1840,7 +1840,9 @@
module = {
name = linux;
- x86 = loader/i386/linux.c;
+ i386_pc = loader/i386/linux.c;
+ i386_efi = loader/i386/efi/linux.c;
+ x86_64_efi = loader/i386/efi/linux.c;
i386_xen_pvh = loader/i386/linux.c;
xen = loader/i386/xen.c;
i386_pc = lib/i386/pc/vesa_modes_table.c;
@@ -1856,8 +1858,6 @@
loongarch64 = loader/efi/linux.c;
riscv32 = loader/efi/linux.c;
riscv64 = loader/efi/linux.c;
- i386_efi = loader/efi/linux.c;
- x86_64_efi = loader/efi/linux.c;
emu = loader/emu/linux.c;
common = loader/linux.c;
};
@@ -1922,7 +1922,7 @@
module = {
name = linuxefi;
- efi = loader/i386/efi/linux.c;
+ efi = lib/fake_module.c;
enable = i386_efi;
enable = x86_64_efi;
};
--- a/grub-core/gensyminfo.sh.in
+++ b/grub-core/gensyminfo.sh.in
@@ -35,3 +35,6 @@
# Print all undefined symbols used by module
@TARGET_NM@ -u @TARGET_NMFLAGS_MINUS_P@ -p $module | sed "s@^\([^ ]*\).*@undefined $modname \1@g"
+
+# Specify linuxefi module should load default linux
+test "$modname" = "linuxefi" && echo "undefined $modname grub_initrd_init" || true
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -333,20 +333,29 @@
}
static grub_command_t cmd_linux, cmd_initrd;
+static grub_command_t cmd_linuxefi, cmd_initrdefi;
-GRUB_MOD_INIT(linuxefi)
+GRUB_MOD_INIT(linux)
{
- cmd_linux =
+ cmd_linuxefi =
grub_register_command ("linuxefi", grub_cmd_linux,
0, N_("Load Linux."));
- cmd_initrd =
+ cmd_initrdefi =
grub_register_command ("initrdefi", grub_cmd_initrd,
0, N_("Load initrd."));
+ cmd_linux =
+ grub_register_command ("linux", grub_cmd_linux,
+ 0, N_("Load Linux."));
+ cmd_initrd =
+ grub_register_command ("initrd", grub_cmd_initrd,
+ 0, N_("Load initrd."));
my_mod = mod;
}
-GRUB_MOD_FINI(linuxefi)
+GRUB_MOD_FINI(linux)
{
+ grub_unregister_command (cmd_linuxefi);
+ grub_unregister_command (cmd_initrdefi);
grub_unregister_command (cmd_linux);
grub_unregister_command (cmd_initrd);
}

View File

@ -0,0 +1,39 @@
From d02304f70b5b9c79761d8084ab9dfc66d84688e2 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Wed, 30 Nov 2022 17:02:50 +0800
Subject: [PATCH] font: Try memdisk fonts with the same name
---
grub-core/font/font.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/grub-core/font/font.c b/grub-core/font/font.c
index 18de52562..92ff415bf 100644
--- a/grub-core/font/font.c
+++ b/grub-core/font/font.c
@@ -451,7 +451,21 @@ grub_font_load (const char *filename)
#endif
if (filename[0] == '(' || filename[0] == '/' || filename[0] == '+')
- file = grub_buffile_open (filename, GRUB_FILE_TYPE_FONT, 1024);
+ {
+ char *n = grub_strdup (filename);
+ char *p = grub_strrchr (n, '/');
+ if (p)
+ {
+ char *q = grub_strrchr (p, '.');
+ if (q)
+ *q = 0;
+ p++;
+ file = try_open_from_prefix ("(memdisk)", p);
+ }
+ grub_free (n);
+ if (!file)
+ file = grub_buffile_open (filename, GRUB_FILE_TYPE_FONT, 1024);
+ }
else
{
file = try_open_from_prefix ("(memdisk)", filename);
--
2.41.0

View File

@ -0,0 +1,48 @@
From 045aae8fe7238aabc217700df4d17d83b7d891f3 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Tue, 23 Jan 2024 12:46:16 +0800
Subject: [PATCH] fs/xfs: always verify the total number of entries is not zero
---
grub-core/fs/xfs.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
index bc2224dbb..1ce5fa4fc 100644
--- a/grub-core/fs/xfs.c
+++ b/grub-core/fs/xfs.c
@@ -900,6 +900,8 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
{
struct grub_xfs_dir2_entry *direntry =
grub_xfs_first_de(dir->data, dirblock);
+ struct grub_xfs_dirblock_tail *tail = grub_xfs_dir_tail (dir->data, dirblock);
+
int entries = -1;
char *end = dirblock + dirblk_size;
@@ -918,18 +920,16 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
*/
if (dir->inode.nextents == grub_cpu_to_be32_compile_time (1))
{
- struct grub_xfs_dirblock_tail *tail = grub_xfs_dir_tail (dir->data, dirblock);
-
end = (char *) tail;
/* Subtract the space used by leaf nodes. */
end -= grub_be_to_cpu32 (tail->leaf_count) * sizeof (struct grub_xfs_dir_leaf_entry);
+ }
- entries = grub_be_to_cpu32 (tail->leaf_count) - grub_be_to_cpu32 (tail->leaf_stale);
+ entries = grub_be_to_cpu32 (tail->leaf_count) - grub_be_to_cpu32 (tail->leaf_stale);
- if (!entries)
- continue;
- }
+ if (!entries)
+ continue;
/* Iterate over all entries within this block. */
while ((char *) direntry < (char *) end)
--
2.43.0

View File

@ -0,0 +1,101 @@
From 83a6f72e1896bd012b7fbca21317e96c2c22b327 Mon Sep 17 00:00:00 2001
From: Michal Suchanek <msuchanek@suse.de>
Date: Wed, 12 Jan 2022 19:25:54 +0100
Subject: [PATCH] grub-install: Add SUSE signed image support for powerpc.
Signed-off-by: Michal Suchanek <msuchanek@suse.de>
---
grub-core/osdep/linux/platform.c | 13 +++++++++++++
include/grub/util/install.h | 3 +++
util/grub-install.c | 29 ++++++++++++++++++++++++++---
3 files changed, 42 insertions(+), 3 deletions(-)
--- a/grub-core/osdep/linux/platform.c
+++ b/grub-core/osdep/linux/platform.c
@@ -154,3 +154,16 @@
grub_util_info ("... not found");
return "i386-pc";
}
+
+int
+grub_install_get_powerpc_secure_boot (void)
+{
+ int32_t ret = -1;
+ FILE *fp = grub_util_fopen ("/proc/device-tree/ibm,secure-boot", "rb");
+ if (fp) {
+ if (fread (&ret , 1, sizeof(ret), fp) > 0)
+ ret = grub_be_to_cpu32(ret);
+ fclose(fp);
+ }
+ return ret;
+}
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -233,6 +233,9 @@
grub_install_get_default_x86_platform (void);
int
+grub_install_get_powerpc_secure_boot (void);
+
+int
grub_install_register_efi (grub_device_t efidir_grub_dev,
const char *efifile_path,
const char *efi_distributor);
--- a/util/grub-install.c
+++ b/util/grub-install.c
@@ -321,10 +321,10 @@
{"suse-enable-tpm", OPTION_SUSE_ENABLE_TPM, 0, 0, N_("install TPM modules"), 0},
{"suse-force-signed", OPTION_SUSE_FORCE_SIGNED, 0, 0,
N_("force installation of signed grub" "%s."
- "This option is only available on ARM64 EFI targets."), 0},
+ "This option is only available on ARM64 EFI and powerpc targets."), 0},
{"suse-inhibit-signed", OPTION_SUSE_INHIBIT_SIGNED, 0, 0,
N_("inhibit installation of signed grub. "
- "This option is only available on ARM64 EFI targets."), 0},
+ "This option is only available on ARM64 EFI and powerpc targets."), 0},
{"debug", OPTION_DEBUG, 0, OPTION_HIDDEN, 0, 2},
{"no-floppy", OPTION_NO_FLOPPY, 0, OPTION_HIDDEN, 0, 2},
{"debug-image", OPTION_DEBUG_IMAGE, N_("STRING"), OPTION_HIDDEN, 0, 2},
@@ -1749,6 +1749,7 @@
char mkimage_target[200];
const char *core_name = NULL;
char *signed_imgfile = NULL;
+ int ppc_sb_state = -1;
switch (platform)
{
@@ -1796,11 +1797,33 @@
grub_install_get_platform_platform (platform));
break;
+
+ case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
+ ppc_sb_state = grub_install_get_powerpc_secure_boot();
+
+ if ((signed_grub_mode >= SIGNED_GRUB_FORCE) || ((signed_grub_mode == SIGNED_GRUB_AUTO) && (ppc_sb_state > 0)))
+ {
+ signed_imgfile = grub_util_path_concat (2, grub_install_source_directory, "grub.elf");
+ if (!grub_util_is_regular (signed_imgfile))
+ {
+ if ((signed_grub_mode >= SIGNED_GRUB_FORCE) || (ppc_sb_state > 1))
+ grub_util_error ("signed image `%s' does not exist\n", signed_imgfile);
+ else
+ {
+ free (signed_imgfile);
+ signed_imgfile = NULL;
+ }
+ }
+ }
+
+ if (signed_imgfile)
+ fprintf (stderr, _("Use signed file in %s for installation.\n"), signed_imgfile);
+
+ /* fallthrough. */
case GRUB_INSTALL_PLATFORM_I386_COREBOOT:
case GRUB_INSTALL_PLATFORM_ARM_COREBOOT:
case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT:
case GRUB_INSTALL_PLATFORM_I386_IEEE1275:
- case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
case GRUB_INSTALL_PLATFORM_I386_XEN:
case GRUB_INSTALL_PLATFORM_X86_64_XEN:
case GRUB_INSTALL_PLATFORM_I386_XEN_PVH:

View File

@ -0,0 +1,298 @@
From db67bd0800c69f94fa3696351e7387515464d30c Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 10 Feb 2022 22:16:58 +0800
Subject: [PATCH] grub-install: bailout root device probing
The root device is probed to test if the filesystem is btrfs in order to setup
boot configs for snapshot booting. However when the root device is a lvm thin
volume, due to lack in grub support, the probing will be errored out and entire
installation process aborts.
Here we call out stat to bailout the situation whenever grub fails to probe
filesystem in it's own right.
stat -f -c %T /
The command is also used by grub-mkconfig for the same purpose.
v2:
Test the root device first before probing to avoid encountering
unexpected errors. If this test fails, the device is considered
irrelevant and of no interest, as it is not useful.
v2.1:
Besides verifying that the target's canonical path can be resolved,
ensure that the target is a block device file.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/osdep/basic/no_platform.c | 5 +++
grub-core/osdep/unix/getroot.c | 67 +++++++++++++++++++++++++++++
grub-core/osdep/unix/platform.c | 34 +++++++++++++++
grub-core/osdep/windows/platform.c | 6 +++
include/grub/emu/getroot.h | 3 ++
include/grub/util/install.h | 3 ++
util/grub-install.c | 45 +++++++++++++++----
7 files changed, 154 insertions(+), 9 deletions(-)
diff --git a/grub-core/osdep/basic/no_platform.c b/grub-core/osdep/basic/no_platform.c
index a173dafe9..dfbdd58e4 100644
--- a/grub-core/osdep/basic/no_platform.c
+++ b/grub-core/osdep/basic/no_platform.c
@@ -51,3 +51,8 @@ grub_install_zipl (const char *d, int i, int f)
grub_util_error ("%s", _("no zIPL routines are available for your platform"));
}
+char *
+grub_install_get_filesystem (const char *path)
+{
+ return NULL;
+}
diff --git a/grub-core/osdep/unix/getroot.c b/grub-core/osdep/unix/getroot.c
index c7aa202ab..f4658b27c 100644
--- a/grub-core/osdep/unix/getroot.c
+++ b/grub-core/osdep/unix/getroot.c
@@ -489,6 +489,73 @@ grub_find_device (const char *dir, dev_t dev)
return 0;
}
+#ifdef __linux__
+int
+grub_can_guess_from_mountinfo (const char *dir_in)
+{
+ char **cur;
+ char **os_dev = NULL;
+ char *dir = grub_canonicalize_file_name (dir_in);
+ int ret = 0;
+
+ if (!dir)
+ return 0;
+
+ os_dev = grub_find_root_devices_from_mountinfo (dir, NULL);
+
+ if (!os_dev)
+ os_dev = find_root_devices_from_libzfs (dir);
+
+ if (!os_dev)
+ {
+ free (dir);
+ return 0;
+ }
+
+ for (cur = os_dev; *cur; cur++)
+ {
+ if (strcmp (*cur, "/dev/root") == 0
+ || strncmp (*cur, "/dev/dm-", sizeof ("/dev/dm-") - 1) == 0)
+ /* Assume known and good names */
+ continue;
+ else
+ {
+ struct stat st;
+
+ char *tmp = grub_canonicalize_file_name (*cur);
+ if (tmp == NULL)
+ break;
+
+ if (strncmp (tmp, "/dev/dm-", sizeof ("/dev/dm-") - 1) == 0)
+ continue;
+
+ if (lstat (tmp, &st) < 0)
+ {
+ free (tmp);
+ break;
+ }
+ free (tmp);
+ if (! S_ISBLK (st.st_mode))
+ /* only block device allowed */
+ break;
+ }
+ }
+
+ if (*cur == NULL)
+ /* no bogus device left, good */
+ ret = 1;
+ else
+ grub_util_info ("`%s' is not os device", *cur);
+
+ for (cur = os_dev; *cur; cur++)
+ free (*cur);
+ free (os_dev);
+ free (dir);
+
+ return ret;
+}
+#endif /* __linux__ */
+
char **
grub_guess_root_devices (const char *dir_in)
{
diff --git a/grub-core/osdep/unix/platform.c b/grub-core/osdep/unix/platform.c
index 90ac93725..01a1114cd 100644
--- a/grub-core/osdep/unix/platform.c
+++ b/grub-core/osdep/unix/platform.c
@@ -250,3 +250,37 @@ grub_install_zipl (const char *dest, int install, int force)
"-z", dest, NULL }))
grub_util_error (_("`%s' failed.\n"), PACKAGE"-zipl-setup");
}
+
+char *
+grub_install_get_filesystem (const char *path)
+{
+ int fd;
+ pid_t pid;
+ FILE *fp;
+ ssize_t len;
+ char *buf = NULL;
+ size_t bufsz = 0;
+
+ pid = grub_util_exec_pipe ((const char * []){ "stat", "-f", "-c", "%T", path, NULL }, &fd);
+ if (!pid)
+ return NULL;
+
+ fp = fdopen (fd, "r");
+ if (!fp)
+ return NULL;
+
+ len = getline (&buf, &bufsz, fp);
+ if (len == -1)
+ {
+ free (buf);
+ fclose (fp);
+ return NULL;
+ }
+
+ fclose (fp);
+
+ if (len > 0 && buf[len - 1] == '\n')
+ buf[len - 1] = '\0';
+
+ return buf;
+}
diff --git a/grub-core/osdep/windows/platform.c b/grub-core/osdep/windows/platform.c
index d352d5abd..0ecc0afa7 100644
--- a/grub-core/osdep/windows/platform.c
+++ b/grub-core/osdep/windows/platform.c
@@ -440,3 +440,9 @@ grub_install_zipl (const char *d, int i, int f)
{
grub_util_error ("%s", _("no zIPL routines are available for your platform"));
}
+
+char *
+grub_install_get_filesystem (const char *path)
+{
+ return NULL;
+}
diff --git a/include/grub/emu/getroot.h b/include/grub/emu/getroot.h
index 9c642ae3f..d7e9928bf 100644
--- a/include/grub/emu/getroot.h
+++ b/include/grub/emu/getroot.h
@@ -35,6 +35,9 @@ enum grub_dev_abstraction_types {
char *grub_find_device (const char *dir, dev_t dev);
void grub_util_pull_device (const char *osname);
+#ifdef __linux__
+int grub_can_guess_from_mountinfo (const char *dir);
+#endif
char **grub_guess_root_devices (const char *dir);
int grub_util_get_dev_abstraction (const char *os_dev);
char *grub_make_system_path_relative_to_its_root (const char *path);
diff --git a/include/grub/util/install.h b/include/grub/util/install.h
index 65f3a9c52..7d83e1c0b 100644
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -251,6 +251,9 @@ grub_install_sgi_setup (const char *install_device,
void
grub_install_zipl (const char *d, int i, int f);
+char *
+grub_install_get_filesystem (const char *path);
+
int
grub_install_compress_gzip (const char *src, const char *dest);
int
diff --git a/util/grub-install.c b/util/grub-install.c
index 5c178ade1..c12772b05 100644
--- a/util/grub-install.c
+++ b/util/grub-install.c
@@ -922,7 +922,6 @@ main (int argc, char *argv[])
const char *efi_file = NULL;
char **grub_devices;
grub_fs_t grub_fs;
- grub_fs_t root_fs;
grub_device_t grub_dev = NULL;
enum grub_install_plat platform;
char *grubdir, *device_map;
@@ -1102,10 +1101,22 @@ main (int argc, char *argv[])
grub_host_init ();
{
- char *rootdir_grub_devname;
- grub_device_t rootdir_grub_dev;
+ grub_device_t rootdir_grub_dev = NULL;
+ char *rootdir_grub_devname = NULL;
+ char *root_fs_name = NULL;
+
char *t = grub_util_path_concat (2, "/", rootdir);
+#ifdef __linux__
+ if (!grub_can_guess_from_mountinfo (t))
+ {
+ free(t);
+ /* We can safely ignore the root probe here; whichever cannot be
+ * reliably detected is irrelevant and of no interest */
+ goto skip_root_probe;
+ }
+#endif
+
rootdir_path = grub_canonicalize_file_name (t);
if (!rootdir_path)
grub_util_error (_("failed to get canonical path of `%s'"), t);
@@ -1124,22 +1135,38 @@ main (int argc, char *argv[])
rootdir_devices[0]);
rootdir_grub_dev = grub_device_open (rootdir_grub_devname);
- if (! rootdir_grub_dev)
- grub_util_error ("%s", grub_errmsg);
+ if (!rootdir_grub_dev)
+ {
+ root_fs_name = grub_install_get_filesystem (t);
+ if (root_fs_name)
+ grub_errno = 0;
+ }
+ else
+ {
+ grub_fs_t root_fs = grub_fs_probe (rootdir_grub_dev);
+ if (root_fs)
+ root_fs_name = grub_strdup (root_fs->name);
+ }
- root_fs = grub_fs_probe (rootdir_grub_dev);
- if (!root_fs)
+ if (!root_fs_name)
grub_util_error ("%s", grub_errmsg);
if (config.is_suse_btrfs_snapshot_enabled
- && grub_strncmp(root_fs->name, "btrfs", sizeof ("btrfs") - 1) == 0)
+ && root_fs_name
+ && grub_strncmp(root_fs_name, "btrfs", sizeof ("btrfs") - 1) == 0)
use_relative_path_on_btrfs = 1;
+ free (root_fs_name);
free (t);
free (rootdir_grub_devname);
- grub_device_close (rootdir_grub_dev);
+ if (rootdir_grub_dev)
+ grub_device_close (rootdir_grub_dev);
}
+#ifdef __linux__
+ skip_root_probe:
+#endif
+
switch (platform)
{
case GRUB_INSTALL_PLATFORM_I386_EFI:
--
2.45.2

View File

@ -0,0 +1,110 @@
From ed0ac581ad3866197fc05c7cf48e39419a51f606 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 18 Mar 2022 13:19:33 +0800
Subject: [PATCH] grub-probe: Deduplicate probed partmap output
If the target device being probed is staked on top of other physical or logical
devices, all containing device's partition map type will be printed once if
--target=partmap is used. This usually results in duplicated output as same
partition map type.
This in turn may clutter grub.cfg with many duplicated insmod part_[a-z]+ if
the /boot is RAIDed because --target=partmap output is used to producing
partmap modules required to access disk device.
Let's deduplicate that to make the grub.cfg looks better and disciplined.
Signed-off-by: Michael Chang <mchang@suse.com>
---
util/grub-probe.c | 59 +++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 55 insertions(+), 4 deletions(-)
diff --git a/util/grub-probe.c b/util/grub-probe.c
index c08e46bbb..fb94f28fd 100644
--- a/util/grub-probe.c
+++ b/util/grub-probe.c
@@ -153,6 +153,50 @@ do_print (const char *x, void *data)
grub_printf ("%s%c", x, delim);
}
+static int
+check_duplicate_partmap (const char *name)
+{
+ static int alloc, used;
+ static char **partmaps;
+ int i;
+
+ if (!name)
+ {
+ if (partmaps)
+ {
+ for (i= 0; i < used; ++i)
+ free (partmaps[i]);
+ free (partmaps);
+ partmaps = NULL;
+ alloc = 0;
+ used = 0;
+ }
+ return 1;
+ }
+
+ for (i= 0; i < used; ++i)
+ if (strcmp (partmaps[i], name) == 0)
+ return 1;
+
+ if (alloc <= used)
+ {
+ alloc = (alloc) ? (alloc << 1) : 4;
+ partmaps = xrealloc (partmaps, alloc * sizeof (*partmaps));
+ }
+
+ partmaps[used++] = strdup (name);
+ return 0;
+}
+
+static void
+do_print_partmap (const char *x, void *data)
+{
+ char delim = *(const char *) data;
+ if (check_duplicate_partmap (x) != 0)
+ return;
+ grub_printf ("%s%c", x, delim);
+}
+
static void
probe_partmap (grub_disk_t disk, char delim)
{
@@ -165,10 +209,14 @@ probe_partmap (grub_disk_t disk, char delim)
}
for (part = disk->partition; part; part = part->parent)
- printf ("%s%c", part->partmap->name, delim);
+ {
+ if (check_duplicate_partmap (part->partmap->name) != 0)
+ continue;
+ printf ("%s%c", part->partmap->name, delim);
+ }
if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID)
- grub_diskfilter_get_partmap (disk, do_print, &delim);
+ grub_diskfilter_get_partmap (disk, do_print_partmap, &delim);
/* In case of LVM/RAID, check the member devices as well. */
if (disk->dev->disk_memberlist)
@@ -674,8 +722,11 @@ probe (const char *path, char **device_names, char delim)
probe_cryptodisk_uuid (dev->disk, delim);
else if (print == PRINT_PARTMAP)
- /* Check if dev->disk itself is contained in a partmap. */
- probe_partmap (dev->disk, delim);
+ {
+ /* Check if dev->disk itself is contained in a partmap. */
+ probe_partmap (dev->disk, delim);
+ check_duplicate_partmap (NULL);
+ }
else if (print == PRINT_PARTUUID)
{
--
2.35.1

View File

@ -0,0 +1,44 @@
From a59b58f6ae327a8f6949991cb5531db01e1ba14d Mon Sep 17 00:00:00 2001
From: Wen Xiong <wenxiong@linux.ibm.com>
Date: Tue, 7 Feb 2023 15:10:15 -0500
Subject: [PATCH] grub2: Can't setup a default boot device correctly on nvme
device in Beta3
The patch in Bug 200486 - SUSE1205666 - SLES15SP5 Beta1: Setup multiple dev path
for a nvmf boot device in grub2 caused the issue. That patch didn't consider
nvme devices carefully.
The new patch will check "nvme-of" instead of "nvme" to call
build_multi_boot_device().
Signed-off-by: Wen Xiong<wenxiong@linux.ibm.com>
---
grub-core/osdep/unix/platform.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/grub-core/osdep/unix/platform.c b/grub-core/osdep/unix/platform.c
index db8fa4b95..fb47c0ffa 100644
--- a/grub-core/osdep/unix/platform.c
+++ b/grub-core/osdep/unix/platform.c
@@ -288,11 +288,15 @@ grub_install_register_ieee1275 (int is_prep, const char *install_device,
}
*ptr = '\0';
}
- else if (grub_strstr(install_device, "nvme"))
- boot_device = build_multi_boot_device(install_device);
- else
+ else {
boot_device = get_ofpathname (install_device);
+ if (grub_strstr(boot_device, "nvme-of")) {
+ free (boot_device);
+ boot_device = build_multi_boot_device(install_device);
+ }
+ }
+
if (grub_util_exec ((const char * []){ "nvsetenv", "boot-device",
boot_device, NULL }))
{
--
2.39.1

View File

@ -0,0 +1,164 @@
From 3e77c5494fd06f430588ae9c304fea370439d531 Mon Sep 17 00:00:00 2001
From: Wen Xiong <Wen Xiong>
Date: Thu, 15 Dec 2022 21:33:41 -0500
Subject: [PATCH] grub2: Set multiple device path for a nvmf boot device
nvmf support native multipath(ANA) by default.
The patch added the support for setting multiple
device path for a nvmf boot device.
localhost:~ grub2-install -v /dev/nvme1n1p1
...
...
...
grub2-install: info: executing nvsetenv boot-device /pci@800000020000132/fibre-channel@0,1/nvme-of/controller@5005076810193675,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec /pci@800000020000132/fibre-channel@0/nvme-of/controller@5005076810193675,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec /pci@800000020000132/fibre-channel@0/nvme-of/controller@50050768101935e5,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec /pci@800000020000132/fibre-channel@0,1/nvme-of/controller@50050768101935e5,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec.
Installation finished. No error reported.
localhost:~ # bootlist -m normal -o
nvme7n1
nvme5n1
nvme1n1
nvme4n1
localhost:~ # bootlist -m normal -r
/pci@800000020000132/fibre-channel@0,1/nvme-of/controller@5005076810193675,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec
/pci@800000020000132/fibre-channel@0/nvme-of/controller@5005076810193675,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec
/pci@800000020000132/fibre-channel@0/nvme-of/controller@50050768101935e5,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec
/pci@800000020000132/fibre-channel@0,1/nvme-of/controller@50050768101935e5,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec
Signed-off-by: Wen Xiong <wenxiong@linux.ibm.com>
---
grub-core/osdep/linux/ofpath.c | 6 ++---
grub-core/osdep/unix/platform.c | 48 +++++++++++++++++++++++++++++++++
include/grub/util/install.h | 3 +++
include/grub/util/ofpath.h | 9 +++++++
4 files changed, 63 insertions(+), 3 deletions(-)
--- a/grub-core/osdep/linux/ofpath.c
+++ b/grub-core/osdep/linux/ofpath.c
@@ -209,7 +209,7 @@
}
}
-static char *
+char *
xrealpath (const char *in)
{
char *out;
@@ -224,7 +224,7 @@
return out;
}
-static char *
+char *
block_device_get_sysfs_path_and_link(const char *devicenode)
{
char *rpath;
@@ -535,7 +535,7 @@
}
-static char *
+char *
nvme_get_syspath(const char *nvmedev)
{
char *sysfs_path, *controller_node;
--- a/grub-core/osdep/unix/platform.c
+++ b/grub-core/osdep/unix/platform.c
@@ -19,6 +19,7 @@
#include <config.h>
#include <grub/util/install.h>
+#include <grub/util/ofpath.h>
#include <grub/emu/hostdisk.h>
#include <grub/util/misc.h>
#include <grub/misc.h>
@@ -131,6 +132,51 @@
return rc;
}
+char *
+build_multi_boot_device(const char *install_device)
+{
+ char *sysfs_path;
+ char *nvme_ns;
+ unsigned int nsid;
+ char *ptr;
+ char *boot_device_string;
+ struct dirent *ep;
+ DIR *dp;
+
+ nvme_ns = strchr(install_device, 'n');
+ nsid = of_path_get_nvme_nsid(nvme_ns);
+ sysfs_path = nvme_get_syspath(nvme_ns);
+ strcat(sysfs_path, "/device");
+ sysfs_path = xrealpath(sysfs_path);
+
+ dp = opendir(sysfs_path);
+ ptr = boot_device_string = xmalloc (1000);
+
+ /* We cannot have a boot list with more than five entries */
+ while((ep = readdir(dp)) != NULL){
+ char *nvme_device;
+
+ if (grub_strstr(ep->d_name, "nvme")) {
+ nvme_device = xasprintf ("%s%s%x ",
+ get_ofpathname(ep->d_name),"/namespace@", nsid);
+ if ((strlen(boot_device_string) + strlen(nvme_device)) >= 200*5 - 1) {
+ grub_util_warn (_("More than five entries cannot be specified in the bootlist"));
+ free(nvme_device);
+ break;
+ }
+
+ strncpy(ptr, nvme_device, strlen(nvme_device));
+ ptr += strlen(nvme_device);
+ free(nvme_device);
+ }
+ }
+
+ *--ptr = '\0';
+ closedir(dp);
+
+ return boot_device_string;
+}
+
int
grub_install_register_efi (const grub_disk_t *efidir_grub_disk,
const char *efifile_path,
@@ -242,6 +288,8 @@
}
*ptr = '\0';
}
+ else if (grub_strstr(install_device, "nvme"))
+ boot_device = build_multi_boot_device(install_device);
else
boot_device = get_ofpathname (install_device);
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -241,6 +241,9 @@
const char *efi_distributor,
const char *force_disk);
+char *
+build_multi_boot_device(const char *install_device);
+
void
grub_install_register_ieee1275 (int is_prep, const char *install_device,
int partno, const char *relpath);
--- a/include/grub/util/ofpath.h
+++ b/include/grub/util/ofpath.h
@@ -32,4 +32,13 @@
char* of_find_fc_host(char* host_wwpn);
+char* nvme_get_syspath(const char *nvmedev);
+
+char* block_device_get_sysfs_path_and_link(const char *devicenode);
+
+char* xrealpath (const char *in);
+
+unsigned int of_path_get_nvme_nsid(const char* devname);
+
+
#endif /* ! GRUB_OFPATH_MACHINE_UTIL_HEADER */

View File

@ -0,0 +1,142 @@
From e9d3202d5cffb89223ff61ac93de86a0cac1b50c Mon Sep 17 00:00:00 2001
From: Diego Domingos <diegodo@linux.vnet.ibm.com>
Date: Thu, 19 Nov 2020 10:47:25 -0300
Subject: [PATCH] ieee1275: Avoiding many unecessary open/close
This patch aims to change the grub_ofdisk_open and grub_ofdisk_close behaviors. Since some devices (Fibre Channel and NVMe) can have a long time for shutdown notification, we should avoid open and close the disks as much as we can.
So, we are changing how those functions works. The grub_ofdisk_close will take care of just changing the disk element status, by doing a soft close, i.e, the firmware will not be called. On the other hand, the grub_ofdisk_open will take care of closing the current disk opened only if the disk requested in the current call is different from the current one. This close will be responsible to request the firmware to actually close the disk.
Yet, this patch modifies the grub_ofdisk_get_block_size function, avoiding open and close calls inside of it.
Thank you Michael Chang (mchang@suse.com) for all support.
Signed-off-by: Diego Domingos <diegodo@linux.vnet.ibm.com>
---
grub-core/disk/ieee1275/ofdisk.c | 64 +++++++++++++++++---------------
1 file changed, 35 insertions(+), 29 deletions(-)
--- a/grub-core/disk/ieee1275/ofdisk.c
+++ b/grub-core/disk/ieee1275/ofdisk.c
@@ -44,7 +44,7 @@
};
static grub_err_t
-grub_ofdisk_get_block_size (const char *device, grub_uint32_t *block_size,
+grub_ofdisk_get_block_size (grub_uint32_t *block_size,
struct ofdisk_hash_ent *op);
#define OFDISK_HASH_SZ 8
@@ -461,6 +461,7 @@
grub_ssize_t actual;
grub_uint32_t block_size = 0;
grub_err_t err;
+ struct ofdisk_hash_ent *op;
if (grub_strncmp (name, "ieee1275/", sizeof ("ieee1275/") - 1) != 0)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
@@ -471,6 +472,35 @@
grub_dprintf ("disk", "Opening `%s'.\n", devpath);
+ op = ofdisk_hash_find (devpath);
+ if (!op)
+ op = ofdisk_hash_add (devpath, NULL);
+ if (!op)
+ {
+ grub_free (devpath);
+ return grub_errno;
+ }
+
+ /* Check if the call to open is the same to the last disk already opened */
+ if (last_devpath && !grub_strcmp(op->open_path,last_devpath))
+ {
+ goto finish;
+ }
+
+ /* If not, we need to close the previous disk and open the new one */
+ else {
+ if (last_ihandle){
+ grub_ieee1275_close (last_ihandle);
+ }
+ last_ihandle = 0;
+ last_devpath = NULL;
+
+ grub_ieee1275_open (op->open_path, &last_ihandle);
+ if (! last_ihandle)
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device");
+ last_devpath = op->open_path;
+ }
+
if (grub_ieee1275_finddevice (devpath, &dev))
{
grub_free (devpath);
@@ -491,25 +521,18 @@
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a block device");
}
+
+ finish:
/* XXX: There is no property to read the number of blocks. There
should be a property `#blocks', but it is not there. Perhaps it
is possible to use seek for this. */
disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN;
{
- struct ofdisk_hash_ent *op;
- op = ofdisk_hash_find (devpath);
- if (!op)
- op = ofdisk_hash_add (devpath, NULL);
- if (!op)
- {
- grub_free (devpath);
- return grub_errno;
- }
disk->id = (unsigned long) op;
disk->data = op->open_path;
- err = grub_ofdisk_get_block_size (devpath, &block_size, op);
+ err = grub_ofdisk_get_block_size (&block_size, op);
if (err)
{
grub_free (devpath);
@@ -528,13 +551,6 @@
static void
grub_ofdisk_close (grub_disk_t disk)
{
- if (disk->data == last_devpath)
- {
- if (last_ihandle)
- grub_ieee1275_close (last_ihandle);
- last_ihandle = 0;
- last_devpath = NULL;
- }
disk->data = 0;
}
@@ -681,7 +697,7 @@
}
static grub_err_t
-grub_ofdisk_get_block_size (const char *device, grub_uint32_t *block_size,
+grub_ofdisk_get_block_size (grub_uint32_t *block_size,
struct ofdisk_hash_ent *op)
{
struct size_args_ieee1275
@@ -694,16 +710,6 @@
grub_ieee1275_cell_t size2;
} args_ieee1275;
- if (last_ihandle)
- grub_ieee1275_close (last_ihandle);
-
- last_ihandle = 0;
- last_devpath = NULL;
-
- grub_ieee1275_open (device, &last_ihandle);
- if (! last_ihandle)
- return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device");
-
*block_size = 0;
if (op->block_size_fails >= 2)

View File

@ -0,0 +1,250 @@
From c125cb45a7885d7bf168a05cfa4da3e681244649 Mon Sep 17 00:00:00 2001
From: Diego Domingos <diegodo@br.ibm.com>
Date: Tue, 15 Feb 2022 13:11:48 -0500
Subject: [PATCH 1/4] ieee1275: add support for NVMeoFC
Implements the functions to scan and discovery of NVMeoFC.
---
grub-core/disk/ieee1275/ofdisk.c | 217 ++++++++++++++++++++++++++++++-
1 file changed, 213 insertions(+), 4 deletions(-)
diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c
index 410f4b849..852bb95be 100644
--- a/grub-core/disk/ieee1275/ofdisk.c
+++ b/grub-core/disk/ieee1275/ofdisk.c
@@ -206,12 +206,10 @@ dev_iterate_real (const char *name, const char *path)
return;
}
+
static void
-dev_iterate (const struct grub_ieee1275_devalias *alias)
+dev_iterate_fcp_disks(const struct grub_ieee1275_devalias *alias)
{
- if (grub_strcmp (alias->type, "fcp") == 0)
- {
-
/* If we are dealing with fcp devices, we need
* to find the WWPNs and LUNs to iterate them */
grub_ieee1275_ihandle_t ihandle;
@@ -323,6 +321,217 @@ dev_iterate (const struct grub_ieee1275_devalias *alias)
grub_free (buf);
return;
+}
+
+static void
+dev_iterate_fcp_nvmeof (const struct grub_ieee1275_devalias *alias)
+{
+
+
+ char *bufptr;
+ grub_ieee1275_ihandle_t ihandle;
+
+
+ // Create the structs for the parameters passing to PFW
+ struct nvme_args_
+ {
+ struct grub_ieee1275_common_hdr common;
+ grub_ieee1275_cell_t method;
+ grub_ieee1275_cell_t ihandle;
+ grub_ieee1275_cell_t catch_result;
+ grub_ieee1275_cell_t nentries;
+ grub_ieee1275_cell_t table;
+ } nvme_discovery_controllers_args, nvme_controllers_args, nvme_namespaces_args;
+
+
+ // Create the structs for the results from PFW
+
+ struct discovery_controllers_table_struct_
+ {
+ grub_uint64_t table[256];
+ grub_uint32_t len;
+ } discovery_controllers_table;
+
+ /* struct nvme_controllers_table_entry
+ * this the return of nvme-controllers method tables, containing:
+ * - 2-byte controller ID
+ * - 256-byte transport address string
+ * - 256-byte field containing null-terminated NVM subsystem NQN string up to 223 characters
+ */
+ struct nvme_controllers_table_entry_
+ {
+ grub_uint16_t id;
+ char wwpn[256];
+ char nqn[256];
+ };
+
+ struct nvme_controllers_table_entry_* nvme_controllers_table = grub_malloc(sizeof(struct nvme_controllers_table_entry_)*256);
+
+ grub_uint32_t nvme_controllers_table_entries;
+
+ struct nvme_controllers_table_entry_real
+ {
+ grub_uint16_t id;
+ char wwpn[256];
+ char nqn[256];
+ };
+
+ /* Allocate memory for building the NVMeoF path */
+ char *buf = grub_malloc (grub_strlen (alias->path) + 512);
+ if (!buf)
+ {
+ grub_ieee1275_close(ihandle);
+ return;
+ }
+
+ /* Copy the alias->path to buf so we can work with */
+ bufptr = grub_stpcpy (buf, alias->path);
+ grub_snprintf (bufptr, 32, "/nvme-of");
+
+ /*
+ * Open the nvme-of layer
+ * Ex. /pci@bus/fibre-channel@@dev,func/nvme-of
+ */
+ if(grub_ieee1275_open (buf, &ihandle))
+ {
+ grub_dprintf("disk", "failed to open the disk while iterating FCP disk path=%s\n", buf);
+ return;
+ }
+
+ /*
+ * Call to nvme-discovery-controllers method from the nvme-of layer
+ * to get a list of the NVMe discovery controllers per the binding
+ */
+
+ INIT_IEEE1275_COMMON (&nvme_discovery_controllers_args.common, "call-method", 2, 2);
+ nvme_discovery_controllers_args.method = (grub_ieee1275_cell_t) "nvme-discovery-controllers";
+ nvme_discovery_controllers_args.ihandle = ihandle;
+
+ if (IEEE1275_CALL_ENTRY_FN (&nvme_discovery_controllers_args) == -1)
+ {
+ grub_dprintf("disk", "failed to get the targets while iterating FCP disk path=%s\n", buf);
+ grub_ieee1275_close(ihandle);
+ return;
+ }
+
+ /* After closing the device, the info is lost. So lets copy each buffer in the buffers table */
+
+ discovery_controllers_table.len = (grub_uint32_t) nvme_discovery_controllers_args.nentries;
+
+ unsigned int i=0;
+ for(i = 0; i < discovery_controllers_table.len; i++){
+ discovery_controllers_table.table[i] = ((grub_uint64_t*)nvme_discovery_controllers_args.table)[i];
+ }
+
+ grub_ieee1275_close(ihandle);
+
+ grub_dprintf("ofdisk","NVMeoF: Found %d discovery controllers\n",discovery_controllers_table.len);
+
+ /* For each nvme discovery controller */
+ int current_buffer_index;
+ for(current_buffer_index = 0; current_buffer_index < (int) discovery_controllers_table.len; current_buffer_index++){
+
+
+ grub_snprintf (bufptr, 64, "/nvme-of/controller@%" PRIxGRUB_UINT64_T ",ffff",
+ discovery_controllers_table.table[current_buffer_index]);
+
+ grub_dprintf("ofdisk","nvmeof controller=%s\n",buf);
+
+ if(grub_ieee1275_open (buf, &ihandle))
+ {
+ grub_dprintf("ofdisk", "failed to open the disk while getting nvme-controllers path=%s\n", buf);
+ continue;
+ }
+
+
+ INIT_IEEE1275_COMMON (&nvme_controllers_args.common, "call-method", 2, 2);
+ nvme_controllers_args.method = (grub_ieee1275_cell_t) "nvme-controllers";
+ nvme_controllers_args.ihandle = ihandle;
+ nvme_controllers_args.catch_result = 0;
+
+
+ if (IEEE1275_CALL_ENTRY_FN (&nvme_controllers_args) == -1)
+ {
+ grub_dprintf("ofdisk", "failed to get the nvme-controllers while iterating FCP disk path\n");
+ grub_ieee1275_close(ihandle);
+ continue;
+ }
+
+
+ /* Copy the buffer list to nvme_controllers_table */
+ nvme_controllers_table_entries = ((grub_uint32_t) nvme_controllers_args.nentries);
+ struct nvme_controllers_table_entry_* nvme_controllers_table_ = (struct nvme_controllers_table_entry_*) nvme_controllers_args.table;
+
+ for(i = 0; i < nvme_controllers_table_entries; i++){
+ nvme_controllers_table[i].id = (grub_uint16_t) nvme_controllers_table_[i].id;
+ grub_strcpy(nvme_controllers_table[i].wwpn, nvme_controllers_table_[i].wwpn);
+ grub_strcpy(nvme_controllers_table[i].nqn, nvme_controllers_table_[i].nqn);
+ }
+
+ grub_ieee1275_close(ihandle);
+
+ int nvme_controller_index;
+ int bufptr_pos2;
+ grub_dprintf("ofdisk","NVMeoF: found %d nvme controllers\n",(int) nvme_controllers_args.nentries);
+
+ /* For each nvme controller */
+ for(nvme_controller_index = 0; nvme_controller_index < (int) nvme_controllers_args.nentries; nvme_controller_index++){
+ /* Open the nvme controller
+ * /pci@bus/fibre-channel@dev,func/nvme-of/controller@transport-addr,ctlr-id:nqn=tgt-subsystem-nqn
+ */
+
+ bufptr_pos2 = grub_snprintf (bufptr, 512, "/nvme-of/controller@%s,ffff:nqn=%s",
+ nvme_controllers_table[nvme_controller_index].wwpn, nvme_controllers_table[nvme_controller_index].nqn);
+
+ grub_dprintf("ofdisk","NVMeoF: nvmeof controller=%s\n",buf);
+
+ if(grub_ieee1275_open (buf, &ihandle)){
+ grub_dprintf("ofdisk","failed to open the path=%s\n",buf);
+ continue;
+ }
+
+ INIT_IEEE1275_COMMON (&nvme_namespaces_args.common, "call-method", 2, 2);
+ nvme_namespaces_args.method = (grub_ieee1275_cell_t) "get-namespace-list";
+ nvme_namespaces_args.ihandle = ihandle;
+ nvme_namespaces_args.catch_result = 0;
+
+ if (IEEE1275_CALL_ENTRY_FN (&nvme_namespaces_args) == -1)
+ {
+ grub_dprintf("ofdisk", "failed to get the nvme-namespace-list while iterating FCP disk path\n");
+ grub_ieee1275_close(ihandle);
+ continue;
+ }
+
+ grub_uint32_t *namespaces = (grub_uint32_t*) nvme_namespaces_args.table;
+ grub_dprintf("ofdisk","NVMeoF: found %d namespaces\n",(int)nvme_namespaces_args.nentries);
+
+ grub_ieee1275_close(ihandle);
+
+ grub_uint32_t namespace_index = 0;
+ for(namespace_index=0; namespace_index < nvme_namespaces_args.nentries; namespace_index++){
+ grub_snprintf (bufptr+bufptr_pos2, 512, "/namespace@%"PRIxGRUB_UINT32_T,namespaces[namespace_index]);
+ grub_dprintf("ofdisk","NVMeoF: namespace=%s\n",buf);
+ dev_iterate_real(buf,buf);
+ }
+
+ dev_iterate_real(buf,buf);
+ }
+ }
+ grub_free(buf);
+ return;
+}
+
+static void
+dev_iterate (const struct grub_ieee1275_devalias *alias)
+{
+ if (grub_strcmp (alias->type, "fcp") == 0)
+ {
+ // Iterate disks
+ dev_iterate_fcp_disks(alias);
+
+ // Iterate NVMeoF
+ dev_iterate_fcp_nvmeof(alias);
+
}
else if (grub_strcmp (alias->type, "vscsi") == 0)
{
--
2.35.3

View File

@ -0,0 +1,146 @@
From a37d0cc089edd66ab35f1a27b0da09dd2f02deb3 Mon Sep 17 00:00:00 2001
From: Diego Domingos <diegodo@br.ibm.com>
Date: Mon, 24 Jun 2019 10:15:56 -0400
Subject: [PATCH] ieee1275: implement FCP methods for WWPN and LUNs
This patch enables the fcp-targets and fcp-luns methods which are
responsible to get WWPNs and LUNs for fibre channel devices.
Those methods are specially necessary if the boot directory and grub
installation are in different FCP disks, allowing the dev_iterate()
to find the WWPNs and LUNs when called by searchfs.uuid tool.
---
grub-core/disk/ieee1275/ofdisk.c | 117 ++++++++++++++++++++++++++++++-
1 file changed, 116 insertions(+), 1 deletion(-)
diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c
index ea7f78ac7..258a6e389 100644
--- a/grub-core/disk/ieee1275/ofdisk.c
+++ b/grub-core/disk/ieee1275/ofdisk.c
@@ -209,7 +209,122 @@ dev_iterate_real (const char *name, const char *path)
static void
dev_iterate (const struct grub_ieee1275_devalias *alias)
{
- if (grub_strcmp (alias->type, "vscsi") == 0)
+ if (grub_strcmp (alias->type, "fcp") == 0)
+ {
+
+ /* If we are dealing with fcp devices, we need
+ * to find the WWPNs and LUNs to iterate them */
+ grub_ieee1275_ihandle_t ihandle;
+ grub_uint64_t *ptr_targets, *ptr_luns, k, l;
+ unsigned int i, j, pos;
+ char *buf, *bufptr;
+
+ struct set_fcp_targets_args
+ {
+ struct grub_ieee1275_common_hdr common;
+ grub_ieee1275_cell_t method;
+ grub_ieee1275_cell_t ihandle;
+ grub_ieee1275_cell_t catch_result;
+ grub_ieee1275_cell_t nentries;
+ grub_ieee1275_cell_t table;
+ } args_targets;
+
+ struct set_fcp_luns_args
+ {
+ struct grub_ieee1275_common_hdr common;
+ grub_ieee1275_cell_t method;
+ grub_ieee1275_cell_t ihandle;
+ grub_ieee1275_cell_t wwpn_h;
+ grub_ieee1275_cell_t wwpn_l;
+ grub_ieee1275_cell_t catch_result;
+ grub_ieee1275_cell_t nentries;
+ grub_ieee1275_cell_t table;
+ } args_luns;
+
+ struct args_ret
+ {
+ grub_uint64_t addr;
+ grub_uint64_t len;
+ };
+
+ if(grub_ieee1275_open (alias->path, &ihandle))
+ {
+ grub_dprintf("disk", "failed to open the disk while iterating FCP disk path=%s\n", alias->path);
+ return;
+ }
+
+ /* Setup the fcp-targets method to call via pfw*/
+ INIT_IEEE1275_COMMON (&args_targets.common, "call-method", 2, 3);
+ args_targets.method = (grub_ieee1275_cell_t) "fcp-targets";
+ args_targets.ihandle = ihandle;
+
+ /* Setup the fcp-luns method to call via pfw */
+ INIT_IEEE1275_COMMON (&args_luns.common, "call-method", 4, 3);
+ args_luns.method = (grub_ieee1275_cell_t) "fcp-luns";
+ args_luns.ihandle = ihandle;
+
+ if (IEEE1275_CALL_ENTRY_FN (&args_targets) == -1)
+ {
+ grub_dprintf("disk", "failed to get the targets while iterating FCP disk path=%s\n", alias->path);
+ grub_ieee1275_close(ihandle);
+ return;
+ }
+
+ buf = grub_malloc (grub_strlen (alias->path) + 32 + 32);
+
+ if (!buf)
+ {
+ grub_ieee1275_close(ihandle);
+ return;
+ }
+
+ bufptr = grub_stpcpy (buf, alias->path);
+
+ /* Iterate over entries returned by pfw. Each entry contains a
+ * pointer to wwpn table and his length. */
+ struct args_ret *targets_table = (struct args_ret *)(args_targets.table);
+ for (i=0; i< args_targets.nentries; i++)
+ {
+ ptr_targets = (grub_uint64_t*)(grub_uint32_t) targets_table[i].addr;
+ /* Iterate over all wwpns in given table */
+ for(k=0;k<targets_table[i].len;k++)
+ {
+ args_luns.wwpn_l = (grub_ieee1275_cell_t) (*ptr_targets);
+ args_luns.wwpn_h = (grub_ieee1275_cell_t) (*ptr_targets >> 32);
+ pos=grub_snprintf (bufptr, 32, "/disk@%" PRIxGRUB_UINT64_T,
+ *ptr_targets++);
+ /* Get the luns for given wwpn target */
+ if (IEEE1275_CALL_ENTRY_FN (&args_luns) == -1)
+ {
+ grub_dprintf("disk", "failed to get the LUNS while iterating FCP disk path=%s\n", buf);
+ grub_ieee1275_close (ihandle);
+ grub_free (buf);
+ return;
+ }
+
+ struct args_ret *luns_table = (struct args_ret *)(args_luns.table);
+
+ /* Iterate over all LUNs */
+ for(j=0;j<args_luns.nentries; j++)
+ {
+ ptr_luns = (grub_uint64_t*) (grub_uint32_t) luns_table[j].addr;
+ for(l=0;l<luns_table[j].len;l++)
+ {
+ grub_snprintf (&bufptr[pos], 30, ",%" PRIxGRUB_UINT64_T,
+ *ptr_luns++);
+ dev_iterate_real(buf,buf);
+ }
+ }
+
+ }
+ }
+
+ grub_ieee1275_close (ihandle);
+ grub_free (buf);
+ return;
+
+ }
+ else if (grub_strcmp (alias->type, "vscsi") == 0)
{
static grub_ieee1275_ihandle_t ihandle;
struct set_color_args
--
2.31.1

View File

@ -0,0 +1,172 @@
From f4728ed5307b6be6377b7bdafcab55fd3676a761 Mon Sep 17 00:00:00 2001
From: Mukesh Kumar Chaurasiya <mchauras@linux.ibm.com>
Date: Mon, 17 Jul 2023 16:02:34 +0530
Subject: [PATCH] ieee1275/ofdisk: retry on open and read failure
Sometimes, when booting from a very busy SAN, the access to the
disk can fail and then grub will eventually drop to grub prompt.
This scenario is more frequent when deploying many machines at
the same time using the same SAN.
This patch aims to force the ofdisk module to retry the open or
read function for network disks excluding after it fails. We use
DEFAULT_RETRY_TIMEOUT, which is 15 seconds to specify the time it'll
retry to access the disk before it definitely fails. The timeout can be
changed by setting the environment variable ofdisk_retry_timeout.
If the environment variable fails to read, grub will consider the
default value of 15 seconds.
Signed-off-by: Diego Domingos <diegodo@linux.vnet.ibm.com>
Signed-off-by: Mukesh Kumar Chaurasiya <mchauras@linux.ibm.com>
---
docs/grub.texi | 8 ++++
grub-core/disk/ieee1275/ofdisk.c | 80 +++++++++++++++++++++++++++++++-
2 files changed, 86 insertions(+), 2 deletions(-)
diff --git a/docs/grub.texi b/docs/grub.texi
index d3f0f6577..c8ebc083d 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -3315,6 +3315,7 @@ These variables have special meaning to GRUB.
* net_default_ip::
* net_default_mac::
* net_default_server::
+* ofdisk_retry_timeout::
* pager::
* prefix::
* pxe_blksize::
@@ -3744,6 +3745,13 @@ The default is the value of @samp{color_normal} (@pxref{color_normal}).
@xref{Network}.
+@node ofdisk_retry_timeout
+@subsection ofdisk_retry_timeout
+
+The time in seconds till which the grub will retry to open or read a disk in
+case of failure to do so. This value defaults to 15 seconds.
+
+
@node pager
@subsection pager
diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c
index 7197d5401..f96bbb58c 100644
--- a/grub-core/disk/ieee1275/ofdisk.c
+++ b/grub-core/disk/ieee1275/ofdisk.c
@@ -24,6 +24,9 @@
#include <grub/ieee1275/ofdisk.h>
#include <grub/i18n.h>
#include <grub/time.h>
+#include <grub/env.h>
+
+#define RETRY_DEFAULT_TIMEOUT 15
static char *last_devpath;
static grub_ieee1275_ihandle_t last_ihandle;
@@ -783,7 +786,7 @@ compute_dev_path (const char *name)
}
static grub_err_t
-grub_ofdisk_open (const char *name, grub_disk_t disk)
+grub_ofdisk_open_real (const char *name, grub_disk_t disk)
{
grub_ieee1275_phandle_t dev;
char *devpath;
@@ -879,6 +882,56 @@ grub_ofdisk_open (const char *name, grub_disk_t disk)
return 0;
}
+static grub_uint64_t
+grub_ofdisk_disk_timeout (grub_disk_t disk)
+{
+ grub_uint64_t retry;
+ const char *timeout = grub_env_get ("ofdisk_retry_timeout");
+
+ if (!(grub_strstr (disk->name, "fibre-channel@") ||
+ grub_strstr (disk->name, "vfc-client")) ||
+ grub_strstr(disk->name, "nvme-of"))
+ {
+ /* Do not retry in case of non network drives */
+ return 0;
+ }
+
+ if (timeout != NULL)
+ {
+ retry = grub_strtoul (timeout, 0, 10);
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ return RETRY_DEFAULT_TIMEOUT;
+ }
+ if (retry)
+ return retry;
+ }
+ return RETRY_DEFAULT_TIMEOUT;
+}
+
+static grub_err_t
+grub_ofdisk_open (const char *name, grub_disk_t disk)
+{
+ grub_err_t err;
+ grub_uint64_t timeout = grub_get_time_ms () + (grub_ofdisk_disk_timeout (disk) * 1000);
+ _Bool cont;
+ do
+ {
+ err = grub_ofdisk_open_real (name, disk);
+ cont = grub_get_time_ms () < timeout;
+ if (err == GRUB_ERR_UNKNOWN_DEVICE && cont)
+ {
+ grub_dprintf ("ofdisk","Failed to open disk %s. Retrying...\n", name);
+ grub_errno = GRUB_ERR_NONE;
+ }
+ else
+ break;
+ grub_millisleep (1000);
+ } while (cont);
+ return err;
+}
+
static void
grub_ofdisk_close (grub_disk_t disk)
{
@@ -915,7 +968,7 @@ grub_ofdisk_prepare (grub_disk_t disk, grub_disk_addr_t sector)
}
static grub_err_t
-grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
+grub_ofdisk_read_real (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf)
{
grub_err_t err;
@@ -934,6 +987,29 @@ grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
return 0;
}
+static grub_err_t
+grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
+ grub_size_t size, char *buf)
+{
+ grub_err_t err;
+ grub_uint64_t timeout = grub_get_time_ms () + (grub_ofdisk_disk_timeout (disk) * 1000);
+ _Bool cont;
+ do
+ {
+ err = grub_ofdisk_read_real (disk, sector, size, buf);
+ cont = grub_get_time_ms () < timeout;
+ if (err == GRUB_ERR_UNKNOWN_DEVICE && cont)
+ {
+ grub_dprintf ("ofdisk","Failed to read disk %s. Retrying...\n", (char*)disk->data);
+ grub_errno = GRUB_ERR_NONE;
+ }
+ else
+ break;
+ grub_millisleep (1000);
+ } while (cont);
+ return err;
+}
+
static grub_err_t
grub_ofdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, const char *buf)
--
2.41.0

View File

@ -0,0 +1,90 @@
From ca30b3c6fd8c848f510445316d0c4a8fca6061ba Mon Sep 17 00:00:00 2001
From: Diego Domingos <diegodo@br.ibm.com>
Date: Wed, 24 Jun 2020 08:17:18 -0400
Subject: [PATCH 1/2] ieee1275/powerpc: implements fibre channel discovery for
ofpathname
grub-ofpathname doesn't work with fibre channel because there is no
function currently implemented for it.
This patch enables it by prividing a function that looks for the port
name, building the entire path for OF devices.
---
grub-core/osdep/linux/ofpath.c | 48 ++++++++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c
index a6153d359..f2bc9fc5c 100644
--- a/grub-core/osdep/linux/ofpath.c
+++ b/grub-core/osdep/linux/ofpath.c
@@ -399,6 +399,37 @@ of_path_of_nvme(const char *sys_devname __attribute__((unused)),
}
#endif
+static void
+of_fc_port_name(const char *path, const char *subpath, char *port_name)
+{
+ char *bname, *basepath, *p;
+ int fd;
+
+ bname = xmalloc(sizeof(char)*150);
+ basepath = xmalloc(strlen(path));
+
+ /* Generate the path to get port name information from the drive */
+ strncpy(basepath,path,subpath-path);
+ basepath[subpath-path-1] = '\0';
+ p = get_basename(basepath);
+ snprintf(bname,sizeof(char)*150,"%s/fc_transport/%s/port_name",basepath,p);
+
+ /* Read the information from the port name */
+ fd = open (bname, O_RDONLY);
+ if (fd < 0)
+ grub_util_error (_("cannot open `%s': %s"), bname, strerror (errno));
+
+ if (read(fd,port_name,sizeof(char)*19) < 0)
+ grub_util_error (_("cannot read `%s': %s"), bname, strerror (errno));
+
+ sscanf(port_name,"0x%s",port_name);
+
+ close(fd);
+
+ free(bname);
+ free(basepath);
+}
+
static int
vendor_is_ATA(const char *path)
{
@@ -577,6 +608,16 @@ of_path_of_scsi(const char *sys_devname __attribute__((unused)), const char *dev
digit_string = trailing_digits (device);
if (strncmp (of_path, "/vdevice/", sizeof ("/vdevice/") - 1) == 0)
{
+ if(strstr(of_path,"vfc-client"))
+ {
+ char * port_name = xmalloc(sizeof(char)*17);
+ of_fc_port_name(sysfs_path, p, port_name);
+
+ snprintf(disk,sizeof(disk),"/%s@%s", disk_name, port_name);
+ free(port_name);
+ }
+ else
+ {
unsigned long id = 0x8000 | (tgt << 8) | (bus << 5) | lun;
if (*digit_string == '\0')
{
@@ -590,6 +631,13 @@ of_path_of_scsi(const char *sys_devname __attribute__((unused)), const char *dev
snprintf(disk, sizeof (disk),
"/%s@%04lx000000000000:%c", disk_name, id, 'a' + (part - 1));
}
+ }
+ } else if (strstr(of_path,"fibre-channel")||(strstr(of_path,"vfc-client"))){
+ char * port_name = xmalloc(sizeof(char)*17);
+ of_fc_port_name(sysfs_path, p, port_name);
+
+ snprintf(disk,sizeof(disk),"/%s@%s", disk_name, port_name);
+ free(port_name);
}
else
{
--
2.26.2

View File

@ -0,0 +1,396 @@
From 6444774dae24f439dae3b4bc8d73449d50f06240 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 31 Dec 2020 21:54:07 +0800
Subject: [PATCH] install: fix software raid1 on esp
While running grub-install on an efi system where efi system partition
is configured as mdadm software raid1, it fails with errors like this:
grub2-install: info: copying `/boot/grub2/x86_64-efi/core.efi' -> `/boot/efi/EFI/opensuse/grubx64.efi'.
grub2-install: info: Registering with EFI: distributor = `opensuse', path = `\EFI\opensuse\grubx64.efi', ESP at mduuid/9182c46b9d469f79b48850b68f3371a5.
grub2-install: info: executing efibootmgr --version </dev/null >/dev/null.
grub2-install: info: executing modprobe -q efivars.
grub2-install: info: executing efibootmgr -c -d.
efibootmgr: option requires an argument -- 'd'
efibootmgr version 14
usage: efibootmgr [options]
This should work with mdadm raid1 with metadata 0.9 and 1.0 whose
superblocks are at the end of device. However
grub_install_register_efi() doesn't seem to work if the target is
multiple devices so that it errors out.
The patch changes grub_install_register_efi() to accept multiple devices
that can be used to creating efi boot entries for probed raid1 member
devices on mounted efi system partition.
This patch also adds check for metadata 0.9 or 1.0 or the validation
will fail to continue the install.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/disk/diskfilter.c | 27 +++----
grub-core/disk/mdraid1x_linux.c | 3 +
grub-core/osdep/basic/no_platform.c | 3 +-
grub-core/osdep/unix/platform.c | 57 +++++++++++----
grub-core/osdep/windows/platform.c | 3 +-
include/grub/diskfilter.h | 3 +-
include/grub/util/install.h | 5 +-
util/grub-install.c | 107 ++++++++++++++++++++++++++--
8 files changed, 171 insertions(+), 37 deletions(-)
--- a/grub-core/disk/diskfilter.c
+++ b/grub-core/disk/diskfilter.c
@@ -159,8 +159,8 @@
for (m = arr->pvs; m; m = m->next)
if (m->disk && m->disk->id == disk->id
&& m->disk->dev->id == disk->dev->id
- && m->part_start == grub_partition_get_start (disk->partition)
- && m->part_size == grub_disk_native_sectors (disk))
+ && grub_partition_get_start (m->disk->partition) == grub_partition_get_start (disk->partition)
+ && grub_disk_native_sectors (m->disk) == grub_disk_native_sectors (disk))
return 0;
}
@@ -1340,19 +1340,23 @@
? (grub_memcmp (pv->id.uuid, id->uuid, id->uuidlen) == 0)
: (pv->id.id == id->id))
{
+ char *part_name = NULL;
struct grub_diskfilter_lv *lv;
/* FIXME: Check whether the update time of the superblocks are
the same. */
- if (pv->disk && grub_disk_native_sectors (disk) >= pv->part_size)
+ if (pv->disk && grub_disk_native_sectors (disk) >= grub_disk_native_sectors (pv->disk))
return GRUB_ERR_NONE;
- pv->disk = grub_disk_open (disk->name);
+ if (disk->partition)
+ {
+ char *p = grub_partition_get_name (disk->partition);
+ if (p)
+ part_name = grub_xasprintf ("%s,%s", disk->name, p);
+ grub_free (p);
+ }
+ pv->disk = grub_disk_open (part_name ? : disk->name);
+ grub_free (part_name);
if (!pv->disk)
return grub_errno;
- /* This could happen to LVM on RAID, pv->disk points to the
- raid device, we shouldn't change it. */
- pv->start_sector -= pv->part_start;
- pv->part_start = grub_partition_get_start (disk->partition);
- pv->part_size = grub_disk_native_sectors (disk);
#ifdef GRUB_UTIL
{
@@ -1369,7 +1373,6 @@
#endif
if (start_sector != (grub_uint64_t)-1)
pv->start_sector = start_sector;
- pv->start_sector += pv->part_start;
/* Add the device to the array. */
for (lv = array->lvs; lv; lv = lv->next)
if (!lv->became_readable_at && lv->fullname && is_lv_readable (lv, 0))
@@ -1457,8 +1460,8 @@
{
if (pv->disk && pv->disk->id == disk->id
&& pv->disk->dev->id == disk->dev->id
- && pv->part_start == grub_partition_get_start (disk->partition)
- && pv->part_size == grub_disk_native_sectors (disk))
+ && grub_partition_get_start (pv->disk->partition) == grub_partition_get_start (disk->partition)
+ && grub_disk_native_sectors (pv->disk) == grub_disk_native_sectors (disk))
{
if (vg_out)
*vg_out = vg;
--- a/grub-core/disk/mdraid1x_linux.c
+++ b/grub-core/disk/mdraid1x_linux.c
@@ -208,6 +208,9 @@
grub_le_to_cpu32 (sb.chunksize),
grub_le_to_cpu32 (sb.layout),
grub_le_to_cpu32 (sb.level));
+#ifdef GRUB_UTIL
+ array->mdraid1x_minor_version = minor_version;
+#endif
return array;
}
--- a/grub-core/osdep/basic/no_platform.c
+++ b/grub-core/osdep/basic/no_platform.c
@@ -33,7 +33,8 @@
void
grub_install_register_efi (grub_device_t efidir_grub_dev,
const char *efifile_path,
- const char *efi_distributor)
+ const char *efi_distributor,
+ const char *force_disk)
{
grub_util_error ("%s", _("no EFI routines are available for your platform"));
}
--- a/grub-core/osdep/unix/platform.c
+++ b/grub-core/osdep/unix/platform.c
@@ -132,15 +132,14 @@
}
int
-grub_install_register_efi (grub_device_t efidir_grub_dev,
+grub_install_register_efi (const grub_disk_t *efidir_grub_disk,
const char *efifile_path,
- const char *efi_distributor)
+ const char *efi_distributor,
+ const char *force_disk)
{
- const char * efidir_disk;
- int efidir_part;
int ret;
- efidir_disk = grub_util_biosdisk_get_osdev (efidir_grub_dev->disk);
- efidir_part = efidir_grub_dev->disk->partition ? efidir_grub_dev->disk->partition->number + 1 : 1;
+ const grub_disk_t *curdisk;
+ int ndev = 0;
if (grub_util_exec_redirect_null ((const char * []){ "efibootmgr", "--version", NULL }))
{
@@ -158,22 +157,50 @@
if (ret)
return ret;
- char *efidir_part_str = xasprintf ("%d", efidir_part);
+ for (curdisk = efidir_grub_disk; *curdisk; curdisk++)
+ ndev++;
- if (!verbosity)
- ret = grub_util_exec ((const char * []){ "efibootmgr", "-q",
+ for (curdisk = efidir_grub_disk; *curdisk; curdisk++)
+ {
+ const char * efidir_disk;
+ int efidir_part;
+ char *efidir_part_str;
+ char *new_efi_distributor = NULL;
+ grub_disk_t disk = *curdisk;
+
+ efidir_disk = force_disk ? : grub_util_biosdisk_get_osdev (disk);
+ if (!efidir_disk)
+ grub_util_error (_("%s: no device for efi"), disk->name);
+
+ efidir_part = disk->partition ? disk->partition->number + 1 : 1;
+ efidir_part_str = xasprintf ("%d", efidir_part);
+ if (ndev > 1)
+ {
+ const char *p = grub_strrchr (efidir_disk, '/');
+ new_efi_distributor = xasprintf ("%s (%s%d)\n",
+ efi_distributor,
+ p ? p + 1: efidir_disk,
+ efidir_part);
+ }
+
+ if (!verbosity)
+ ret = grub_util_exec ((const char * []){ "efibootmgr", "-q",
"-c", "-d", efidir_disk,
"-p", efidir_part_str, "-w",
- "-L", efi_distributor, "-l",
+ "-L", new_efi_distributor ? : efi_distributor, "-l",
efifile_path, NULL });
- else
- ret = grub_util_exec ((const char * []){ "efibootmgr",
+ else
+ ret = grub_util_exec ((const char * []){ "efibootmgr",
"-c", "-d", efidir_disk,
"-p", efidir_part_str, "-w",
- "-L", efi_distributor, "-l",
+ "-L", new_efi_distributor ? : efi_distributor, "-l",
efifile_path, NULL });
- free (efidir_part_str);
- return ret;
+ free (efidir_part_str);
+ free (new_efi_distributor);
+ if (ret)
+ return ret;
+ }
+ return 0;
}
void
--- a/grub-core/osdep/windows/platform.c
+++ b/grub-core/osdep/windows/platform.c
@@ -204,7 +204,8 @@
int
grub_install_register_efi (grub_device_t efidir_grub_dev,
const char *efifile_path,
- const char *efi_distributor)
+ const char *efi_distributor,
+ const char *force_disk)
{
grub_uint16_t *boot_order, *new_boot_order;
grub_uint16_t *distributor16;
--- a/include/grub/diskfilter.h
+++ b/include/grub/diskfilter.h
@@ -49,6 +49,7 @@
#ifdef GRUB_UTIL
struct grub_diskfilter *driver;
+ grub_uint8_t mdraid1x_minor_version;
#endif
};
@@ -66,8 +67,6 @@
/* Optional. */
char *name;
grub_disk_t disk;
- grub_disk_addr_t part_start;
- grub_disk_addr_t part_size;
grub_disk_addr_t start_sector; /* Sector number where the data area starts. */
struct grub_diskfilter_pv *next;
/* Optional. */
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -236,9 +236,10 @@
grub_install_get_powerpc_secure_boot (void);
int
-grub_install_register_efi (grub_device_t efidir_grub_dev,
+grub_install_register_efi (const grub_disk_t *efidir_grub_disk,
const char *efifile_path,
- const char *efi_distributor);
+ const char *efi_distributor,
+ const char *force_disk);
void
grub_install_register_ieee1275 (int is_prep, const char *install_device,
--- a/util/grub-install.c
+++ b/util/grub-install.c
@@ -1719,6 +1719,40 @@
}
}
prefix_drive = xasprintf ("(%s)", grub_drives[0]);
+
+ if (platform == GRUB_INSTALL_PLATFORM_X86_64_EFI
+ && grub_dev->disk
+ && grub_dev->disk->partition
+ && grub_fs->fs_uuid)
+ {
+ int raid_level;
+ char *uuid = NULL;
+ char *escaped_relpath = NULL;
+
+ raid_level = probe_raid_level (grub_dev->disk);
+ if (raid_level != 1)
+ goto out;
+
+ escaped_relpath = escape (relative_grubdir);
+ if (!escaped_relpath)
+ goto out;
+
+ if (grub_fs->fs_uuid (grub_dev, &uuid) || !uuid)
+ {
+ grub_print_error ();
+ grub_errno = 0;
+ goto out;
+ }
+
+ if (!load_cfg_f)
+ load_cfg_f = grub_util_fopen (load_cfg, "wb");
+ have_load_cfg = 1;
+ fprintf (load_cfg_f, "search --no-floppy --fs-uuid --set=root --hint='%s' %s\n", grub_drives[0], uuid);
+ fprintf (load_cfg_f, "set prefix=($root)'%s'\n", escaped_relpath);
+ grub_install_push_module ("search");
+ out:
+ grub_free (escaped_relpath);
+ }
}
#ifdef __linux__
@@ -2258,9 +2292,13 @@
{
/* Try to make this image bootable using the EFI Boot Manager, if available. */
int ret;
- ret = grub_install_register_efi (efidir_grub_dev,
+ grub_disk_t efidir_grub_disk[2];
+ efidir_grub_disk[0] = efidir_grub_dev->disk;
+ efidir_grub_disk[1] = NULL;
+ ret = grub_install_register_efi (efidir_grub_disk,
"\\System\\Library\\CoreServices",
- efi_distributor);
+ efi_distributor,
+ NULL);
if (ret)
grub_util_error (_("efibootmgr failed to register the boot entry: %s"),
strerror (ret));
@@ -2314,7 +2352,11 @@
{
char * efifile_path;
char * part;
+ int raid_level;
int ret;
+ grub_disk_t *efidir_grub_disk;
+ grub_disk_memberlist_t list = NULL, cur;
+ char * force_disk = NULL;
/* Try to make this image bootable using the EFI Boot Manager, if available. */
if (!efi_distributor || efi_distributor[0] == '\0')
@@ -2331,8 +2373,65 @@
efidir_grub_dev->disk->name,
(part ? ",": ""), (part ? : ""));
grub_free (part);
- ret = grub_install_register_efi (efidir_grub_dev,
- efifile_path, efi_distributor);
+
+ raid_level = probe_raid_level (efidir_grub_dev->disk);
+ if (raid_level >= 0 && raid_level != 1)
+ grub_util_warn (_("unsupported raid level %d detected for efi system partition"), raid_level);
+ if (raid_level == 1 && !efidir_grub_dev->disk->partition)
+ {
+ const char *raidname = NULL;
+
+ if (efidir_grub_dev->disk->dev->disk_raidname)
+ raidname = efidir_grub_dev->disk->dev->disk_raidname (efidir_grub_dev->disk);
+ if (raidname
+ && (grub_strncmp (raidname, "mdraid09", sizeof ("mdraid09")) == 0
+ || (grub_strcmp (raidname, "mdraid1x") == 0
+ && ((struct grub_diskfilter_lv *) efidir_grub_dev->disk->data)->vg->mdraid1x_minor_version == 0)))
+ {
+ if (efidir_grub_dev->disk->dev->disk_memberlist)
+ list = efidir_grub_dev->disk->dev->disk_memberlist (efidir_grub_dev->disk);
+ }
+ else
+ {
+ grub_util_warn (_("this array has metadata at the start and may not be suitable as a efi system partition."
+ " please ensure that your firmware understands md/v1.x metadata, or use --metadata=0.90"
+ " to create the array."));
+ /* Try to continue regardless metadata, nothing to lose here */
+ if (efidir_grub_dev->disk->dev->disk_memberlist)
+ list = efidir_grub_dev->disk->dev->disk_memberlist (efidir_grub_dev->disk);
+ }
+ }
+ else if (raid_level == 1)
+ force_disk = grub_util_get_os_disk (install_device);
+ if (list)
+ {
+ int i;
+ int ndisk = 0;
+
+ for (cur = list; cur; cur = cur->next)
+ ++ndisk;
+ efidir_grub_disk = xcalloc (ndisk + 1, sizeof (*efidir_grub_disk));
+ for (cur = list, i = 0; i < ndisk; cur = cur->next, i++)
+ efidir_grub_disk[i] = cur->disk;
+ efidir_grub_disk[ndisk] = NULL;
+ }
+ else
+ {
+ efidir_grub_disk = xcalloc (2, sizeof (*efidir_grub_disk));
+ efidir_grub_disk[0] = efidir_grub_dev->disk;
+ efidir_grub_disk[1] = NULL;
+ }
+ ret = grub_install_register_efi (efidir_grub_disk,
+ efifile_path, efi_distributor,
+ force_disk);
+ while (list)
+ {
+ cur = list;
+ list = list->next;
+ grub_free (cur);
+ }
+ grub_free (force_disk);
+ grub_free (efidir_grub_disk);
if (ret)
grub_util_error (_("efibootmgr failed to register the boot entry: %s"),
strerror (ret));

View File

@ -0,0 +1,109 @@
From c2475f1337dff2e2a3e45514119d5186e55753c1 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 13 Aug 2020 09:36:45 +0800
Subject: [PATCH] kern/mm.c : Make grub_calloc inline
To circumvent the situation that symbol 'grub_calloc' not found would
happen if system is using stray grub (ie not managed by system update)
as stage1 that can be too old to load updated modules.
---
grub-core/kern/mm.c | 28 ----------------------------
include/grub/mm.h | 32 +++++++++++++++++++++++++++++++-
2 files changed, 31 insertions(+), 29 deletions(-)
--- a/grub-core/kern/mm.c
+++ b/grub-core/kern/mm.c
@@ -63,14 +63,10 @@
#include <config.h>
#include <grub/mm.h>
-#include <grub/misc.h>
-#include <grub/err.h>
#include <grub/types.h>
#include <grub/disk.h>
#include <grub/dl.h>
-#include <grub/i18n.h>
#include <grub/mm_private.h>
-#include <grub/safemath.h>
#ifdef MM_DEBUG
# undef grub_calloc
@@ -553,30 +549,6 @@
return 0;
}
-/*
- * Allocate NMEMB instances of SIZE bytes and return the pointer, or error on
- * integer overflow.
- */
-void *
-grub_calloc (grub_size_t nmemb, grub_size_t size)
-{
- void *ret;
- grub_size_t sz = 0;
-
- if (grub_mul (nmemb, size, &sz))
- {
- grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
- return NULL;
- }
-
- ret = grub_memalign (0, sz);
- if (!ret)
- return NULL;
-
- grub_memset (ret, 0, sz);
- return ret;
-}
-
/* Allocate SIZE bytes and return the pointer. */
void *
grub_malloc (grub_size_t size)
--- a/include/grub/mm.h
+++ b/include/grub/mm.h
@@ -47,7 +47,6 @@
#endif
void grub_mm_init_region (void *addr, grub_size_t size);
-void *EXPORT_FUNC(grub_calloc) (grub_size_t nmemb, grub_size_t size);
void *EXPORT_FUNC(grub_malloc) (grub_size_t size);
void *EXPORT_FUNC(grub_zalloc) (grub_size_t size);
void EXPORT_FUNC(grub_free) (void *ptr);
@@ -55,6 +54,37 @@
#ifndef GRUB_MACHINE_EMU
void *EXPORT_FUNC(grub_memalign) (grub_size_t align, grub_size_t size);
#endif
+#if !defined(GRUB_UTIL) && !defined (GRUB_MACHINE_EMU)
+#include <grub/misc.h>
+#include <grub/err.h>
+#include <grub/i18n.h>
+#include <grub/safemath.h>
+/*
+ * Allocate NMEMB instances of SIZE bytes and return the pointer, or error on
+ * integer overflow.
+ */
+static inline void *
+grub_calloc (grub_size_t nmemb, grub_size_t size)
+{
+ void *ret;
+ grub_size_t sz = 0;
+
+ if (grub_mul (nmemb, size, &sz))
+ {
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
+ return NULL;
+ }
+
+ ret = grub_memalign (0, sz);
+ if (!ret)
+ return NULL;
+
+ grub_memset (ret, 0, sz);
+ return ret;
+}
+#else
+void *EXPORT_FUNC(grub_calloc) (grub_size_t nmemb, grub_size_t size);
+#endif
void grub_mm_check_real (const char *file, int line);
#define grub_mm_check() grub_mm_check_real (GRUB_FILE, __LINE__);

View File

@ -0,0 +1,197 @@
From bf09618c47c6632b763960e265436294ab98dd43 Mon Sep 17 00:00:00 2001
From: Hernan Gatta <hegatta@linux.microsoft.com>
Date: Tue, 1 Feb 2022 05:02:53 -0800
Subject: [PATCH 1/5] key_protector: Add key protectors framework
A key protector encapsulates functionality to retrieve an unlocking key
for a fully-encrypted disk from a specific source. A key protector
module registers itself with the key protectors framework when it is
loaded and unregisters when unloaded. Additionally, a key protector may
accept parameters that describe how it should operate.
The key protectors framework, besides offering registration and
unregistration functions, also offers a one-stop routine for finding and
invoking a key protector by name. If a key protector with the specified
name exists and if an unlocking key is successfully retrieved by it, the
function returns to the caller the retrieved key and its length.
Cc: Vladimir Serbinenko <phcoder@gmail.com>
Signed-off-by: Hernan Gatta <hegatta@linux.microsoft.com>
Signed-off-by: Gary Lin <glin@suse.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
---
grub-core/Makefile.am | 1 +
grub-core/Makefile.core.def | 5 +++
grub-core/disk/key_protector.c | 78 ++++++++++++++++++++++++++++++++++
include/grub/key_protector.h | 46 ++++++++++++++++++++
4 files changed, 130 insertions(+)
create mode 100644 grub-core/disk/key_protector.c
create mode 100644 include/grub/key_protector.h
diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index f18550c1c..9d3d5f519 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -90,6 +90,7 @@ endif
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/parser.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/partition.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/key_protector.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/stack_protector.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index bc893e547..4307b8e2d 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1302,6 +1302,11 @@ module = {
common = disk/raid6_recover.c;
};
+module = {
+ name = key_protector;
+ common = disk/key_protector.c;
+};
+
module = {
name = scsi;
common = disk/scsi.c;
diff --git a/grub-core/disk/key_protector.c b/grub-core/disk/key_protector.c
new file mode 100644
index 000000000..b84afe1c7
--- /dev/null
+++ b/grub-core/disk/key_protector.c
@@ -0,0 +1,78 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2022 Microsoft Corporation
+ *
+ * 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/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/list.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/key_protector.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+struct grub_key_protector *grub_key_protectors = NULL;
+
+grub_err_t
+grub_key_protector_register (struct grub_key_protector *protector)
+{
+ if (protector == NULL || protector->name == NULL || grub_strlen (protector->name) == 0)
+ return GRUB_ERR_BAD_ARGUMENT;
+
+ if (grub_key_protectors &&
+ grub_named_list_find (GRUB_AS_NAMED_LIST (grub_key_protectors),
+ protector->name))
+ return GRUB_ERR_BAD_ARGUMENT;
+
+ grub_list_push (GRUB_AS_LIST_P (&grub_key_protectors),
+ GRUB_AS_LIST (protector));
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_key_protector_unregister (struct grub_key_protector *protector)
+{
+ if (protector == NULL)
+ return GRUB_ERR_BAD_ARGUMENT;
+
+ grub_list_remove (GRUB_AS_LIST (protector));
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_key_protector_recover_key (const char *protector, grub_uint8_t **key,
+ grub_size_t *key_size)
+{
+ struct grub_key_protector *kp = NULL;
+
+ if (grub_key_protectors == NULL)
+ return GRUB_ERR_OUT_OF_RANGE;
+
+ if (protector == NULL || grub_strlen (protector) == 0)
+ return GRUB_ERR_BAD_ARGUMENT;
+
+ kp = grub_named_list_find (GRUB_AS_NAMED_LIST (grub_key_protectors),
+ protector);
+ if (kp == NULL)
+ return grub_error (GRUB_ERR_OUT_OF_RANGE,
+ N_("A key protector with name '%s' could not be found. "
+ "Is the name spelled correctly and is the "
+ "corresponding module loaded?"), protector);
+
+ return kp->recover_key (key, key_size);
+}
diff --git a/include/grub/key_protector.h b/include/grub/key_protector.h
new file mode 100644
index 000000000..6e6a6fb24
--- /dev/null
+++ b/include/grub/key_protector.h
@@ -0,0 +1,46 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2022 Microsoft Corporation
+ *
+ * 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_PROTECTOR_HEADER
+#define GRUB_PROTECTOR_HEADER 1
+
+#include <grub/err.h>
+#include <grub/types.h>
+
+struct grub_key_protector
+{
+ struct grub_key_protector *next;
+ struct grub_key_protector **prev;
+
+ const char *name;
+
+ grub_err_t (*recover_key) (grub_uint8_t **key, grub_size_t *key_size);
+};
+
+grub_err_t
+grub_key_protector_register (struct grub_key_protector *protector);
+
+grub_err_t
+grub_key_protector_unregister (struct grub_key_protector *protector);
+
+grub_err_t
+grub_key_protector_recover_key (const char *protector,
+ grub_uint8_t **key,
+ grub_size_t *key_size);
+
+#endif /* ! GRUB_PROTECTOR_HEADER */
--
2.35.3

View File

@ -0,0 +1,43 @@
From d683bed5c76c54e6bc5c26eef2f8d7136a3c75c4 Mon Sep 17 00:00:00 2001
From: Ard Biesheuvel <ardb@kernel.org>
Date: Thu, 11 Aug 2022 16:51:57 +0200
Subject: [PATCH] loader/arm64/efi/linux: Remove magic number header field
check
The "ARM\x64" magic number in the file header identifies an image as one
that implements the bare metal boot protocol, allowing the loader to
simply move the file to a suitably aligned address in memory, with
sufficient headroom for the trailing .bss segment (the required memory
size is described in the header as well).
Note of this matters for GRUB, as it only supports EFI boot. EFI does
not care about this magic number, and nor should GRUB: this prevents us
from booting other PE linux images, such as the generic EFI zboot
decompressor, which is a pure PE/COFF image, and does not implement the
bare metal boot protocol.
So drop the magic number check.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/loader/arm64/efi/linux.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/grub-core/loader/arm64/efi/linux.c b/grub-core/loader/arm64/efi/linux.c
index 33df0e1fd..a9f5e05e4 100644
--- a/grub-core/loader/arm64/efi/linux.c
+++ b/grub-core/loader/arm64/efi/linux.c
@@ -57,9 +57,6 @@ static grub_addr_t initrd_end;
static grub_err_t
grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh)
{
- if (lh->magic != GRUB_LINUX_ARMXX_MAGIC_SIGNATURE)
- return grub_error(GRUB_ERR_BAD_OS, "invalid magic number");
-
if ((lh->code0 & 0xffff) != GRUB_PE32_MAGIC)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
N_("plain image kernel not supported - rebuild with CONFIG_(U)EFI_STUB enabled"));
--
2.43.0

View File

@ -0,0 +1,142 @@
From 06af22d6c893b0249712e9a486e0cbae15160e5c Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Mon, 23 Oct 2023 16:11:53 +0800
Subject: [PATCH] luks2: Use grub-tpm2 token for TPM2-protected volume unlock
This commit enables the use of the grub-tpm2 token for unlocking LUKS2
volumes protected by TPM2. The token tracks keyslots associated with a
sealed key, making the unsealing process more efficient and secure.
Signed-Off-by Michael Chang <mchang@suse.com>
---
grub-core/disk/luks2.c | 81 ++++++++++++++++++++++++++++++++++++++++--
1 file changed, 79 insertions(+), 2 deletions(-)
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index d5106402f..fe5ba777a 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -124,6 +124,14 @@ struct grub_luks2_digest
};
typedef struct grub_luks2_digest grub_luks2_digest_t;
+struct grub_luks2_token_tpm
+{
+ grub_uint64_t idx;
+ grub_uint64_t keyslots;
+ const char *timestamp;
+};
+typedef struct grub_luks2_token_tpm grub_luks2_token_tpm_t;
+
gcry_err_code_t AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src,
grub_uint8_t * dst, grub_size_t blocksize,
grub_size_t blocknumbers);
@@ -257,6 +265,39 @@ luks2_parse_digest (grub_luks2_digest_t *out, const grub_json_t *digest)
return GRUB_ERR_NONE;
}
+static grub_err_t
+luks2_parse_token_tpm (grub_luks2_token_tpm_t *out, const grub_json_t *token)
+{
+ grub_json_t keyslots, o;
+ grub_size_t i, size;
+ grub_uint64_t bit;
+ const char *type;
+
+ if (grub_json_getstring (&type, token, "type"))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid token type");
+ else if (grub_strcmp (type, "grub-tpm2"))
+ return GRUB_ERR_NONE;
+
+ if (grub_json_getvalue (&keyslots, token, "keyslots") ||
+ grub_json_getstring (&out->timestamp, token, "timestamp"))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Missing token parameters");
+
+ if (grub_json_getsize (&size, &keyslots))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "Token references no keyslots");
+
+ out->keyslots = 0;
+ for (i = 0; i < size; i++)
+ {
+ if (grub_json_getchild (&o, &keyslots, i) ||
+ grub_json_getuint64 (&bit, &o, NULL))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid keyslot");
+ out->keyslots |= (1 << bit);
+ }
+
+ return GRUB_ERR_NONE;
+}
+
static grub_err_t
luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_segment_t *s,
const grub_json_t *root, grub_size_t keyslot_json_idx)
@@ -561,13 +602,14 @@ luks2_recover_key (grub_disk_t source,
{
grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN];
char cipher[32], *json_header = NULL, *ptr;
- grub_size_t candidate_key_len = 0, json_idx, size;
+ grub_size_t candidate_key_len = 0, json_idx, size, tsize;
grub_luks2_header_t header;
grub_luks2_keyslot_t keyslot;
grub_luks2_digest_t digest;
grub_luks2_segment_t segment;
+ grub_luks2_token_tpm_t token_tpm;
gcry_err_code_t gcry_ret;
- grub_json_t *json = NULL, keyslots;
+ grub_json_t *json = NULL, keyslots, tokens;
grub_err_t ret;
if (cargs->key_data == NULL || cargs->key_len == 0)
@@ -605,6 +647,37 @@ luks2_recover_key (grub_disk_t source,
goto err;
}
+ token_tpm.keyslots = 0;
+ tsize = 0;
+ if (cargs->protectors)
+ {
+ int i;
+ for (i = 0; cargs->protectors[i]; i++)
+ if (grub_strcmp(cargs->protectors[i], "tpm2") == 0)
+ break;
+
+ if (!cargs->protectors[i] ||
+ cargs->key_cache[i].invalid ||
+ grub_json_getvalue (&tokens, json, "tokens") ||
+ grub_json_getsize (&tsize, &tokens))
+ grub_dprintf ("luks2", "No valid token or not a tpm2 protector\n");
+ }
+
+ for (json_idx = 0; json_idx < tsize; json_idx++)
+ {
+ grub_json_t token;
+
+ if (grub_json_getchild (&token, &tokens, json_idx) ||
+ grub_json_getuint64 (&token_tpm.idx, &token, NULL) ||
+ grub_json_getchild (&token, &token, 0) ||
+ luks2_parse_token_tpm (&token_tpm, &token))
+ {
+ grub_dprintf ("luks2", "Could not parse token index %" PRIuGRUB_SIZE "\n", json_idx);
+ grub_errno = GRUB_ERR_NONE;
+ continue;
+ }
+ }
+
if (grub_disk_native_sectors (source) == GRUB_DISK_SIZE_UNKNOWN)
{
/* FIXME: Allow use of source disk, and maybe cause errors in read. */
@@ -641,6 +714,10 @@ luks2_recover_key (grub_disk_t source,
continue;
}
+ if (token_tpm.keyslots &&
+ !(token_tpm.keyslots & (1 << keyslot.idx)))
+ continue;
+
grub_dprintf ("luks2", "Trying keyslot \"%" PRIuGRUB_UINT64_T "\"\n", keyslot.idx);
/* Sector size should be one of 512, 1024, 2048, or 4096. */
--
2.42.0

View File

@ -0,0 +1,60 @@
From d35ff22516b161f6d472f7f5371a89597b072d04 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Mon, 6 May 2024 10:34:22 +0800
Subject: [PATCH] net/drivers/ieee1275/ofnet: Remove 200 ms timeout in
get_card_packet() to reduce input latency
When GRUB image is netbooted on ppc64le, the keyboard input exhibits
significant latency, reports even say that characters are processed
about once per second. This issue makes interactively trying to debug
a ppc64le config very difficult.
It seems that the latency is largely caused by a 200 ms timeout in the
idle event loop, during which the network card interface is consistently
polled for incoming packets. Often, no packets arrive during this
period, so the timeout nearly always expires, which blocks the response
to key inputs.
Furthermore, this 200 ms timeout might not need to be enforced at this
basic layer, considering that GRUB performs synchronous reads and its
timeout management is actually handled by higher layers, not directly in
the card instance. Additionally, the idle polling, which reacts to
unsolicited packets like ICMP and SLAAC, would be fine at a less frequent
polling interval, rather than needing a timeout for receiving a response.
For these reasons, we believe the timeout in get_card_packet() should be
effectively removed. According to test results, the delay has disappeared,
and it is now much easier to use interactively.
Signed-Off-by: Michael Chang <mchang@suse.com>
Tested-by: Tony Jones <tonyj@suse.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/net/drivers/ieee1275/ofnet.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c
index 78f03df8e..3bf48b3f0 100644
--- a/grub-core/net/drivers/ieee1275/ofnet.c
+++ b/grub-core/net/drivers/ieee1275/ofnet.c
@@ -82,15 +82,11 @@ get_card_packet (struct grub_net_card *dev)
grub_ssize_t actual;
int rc;
struct grub_ofnetcard_data *data = dev->data;
- grub_uint64_t start_time;
struct grub_net_buff *nb;
- start_time = grub_get_time_ms ();
- do
- rc = grub_ieee1275_read (data->handle, dev->rcvbuf, dev->rcvbufsize, &actual);
- while ((actual <= 0 || rc < 0) && (grub_get_time_ms () - start_time < 200));
+ rc = grub_ieee1275_read (data->handle, dev->rcvbuf, dev->rcvbufsize, &actual);
- if (actual <= 0)
+ if (actual <= 0 || rc < 0)
return NULL;
nb = grub_netbuff_alloc (actual + 2);
--
2.45.2

View File

@ -0,0 +1,170 @@
From 84b95a121a4401be854614419ded3d383e14ac1f Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 22 Mar 2024 17:38:45 +0800
Subject: [PATCH] ofdisk: Enhance canonical path handling for bootpath
This commit addresses an issue where redundant canonical path
translation is performed on the bootpath, potentially leading to
incorrect results and subsequent boot failures, particularly in cases
where firmware translations are inconsistent.
To mitigate this, the commit introduces a check to determine if the
bootpath is already in canonical form, avoiding unnecessary translation.
Additionally, improvements have been made to enhance the resilience of
device iteration, enhancing compatibility with cross-device booting
scenarios and addressing potential issues related to firmware-based
canonical path retrieval.
These changes aim to improve the reliability and stability of the boot
process.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/disk/ieee1275/ofdisk.c | 75 +++++++++++++++++++++++---------
1 file changed, 55 insertions(+), 20 deletions(-)
diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c
index c5c20a5ec..36ee5314d 100644
--- a/grub-core/disk/ieee1275/ofdisk.c
+++ b/grub-core/disk/ieee1275/ofdisk.c
@@ -35,8 +35,13 @@ static grub_ieee1275_ihandle_t last_ihandle;
#define IEEE1275_DISK_ALIAS "/disk@"
#define IEEE1275_NVMEOF_DISK_ALIAS "/nvme-of/controller@"
+/* Used to check boot_type, print debug message if doesn't match, this can be
+ * useful to measure boot delays */
static char *boot_type;
+/* Used to restrict fcp to a physical boot path */
static char *boot_parent;
+/* Knowing the nvmeof in advance to avoid blind open test during iteration to
+ * validate a path */
static int is_boot_nvmeof;
struct ofdisk_hash_ent
@@ -540,20 +545,30 @@ dev_iterate (const struct grub_ieee1275_devalias *alias)
{
if (grub_strcmp (alias->type, "fcp") == 0)
{
- if (boot_type &&
- grub_strcmp (boot_type, alias->type) != 0)
+ if (boot_parent &&
+ grub_strcmp (boot_parent, alias->path) != 0)
{
- grub_dprintf ("ofdisk", "Skipped device: %s, type %s did not match boot_type %s\n",
- alias->path, alias->type, boot_type);
+ grub_dprintf ("ofdisk", "Skipped device: %s, doesn't match boot_parent %s\n",
+ alias->path, boot_parent);
goto iter_children;
}
- if (grub_strcmp (boot_parent, alias->path) == 0)
+ /* Allow set boot_parent and boot_type to NULL to force iteration */
+ if (!boot_parent)
{
- if (is_boot_nvmeof)
- dev_iterate_fcp_nvmeof(alias);
- else
- dev_iterate_fcp_disks(alias);
+ grub_dprintf ("ofdisk", "iterate %s\n", alias->path);
+ dev_iterate_fcp_nvmeof(alias);
+ dev_iterate_fcp_disks(alias);
+ }
+ else if (is_boot_nvmeof)
+ {
+ grub_dprintf ("ofdisk", "iterate nvmeof: %s\n", alias->path);
+ dev_iterate_fcp_nvmeof(alias);
+ }
+ else
+ {
+ grub_dprintf ("ofdisk", "iterate fcp: %s\n", alias->path);
+ dev_iterate_fcp_disks(alias);
}
}
else if (grub_strcmp (alias->type, "vscsi") == 0)
@@ -575,9 +590,8 @@ dev_iterate (const struct grub_ieee1275_devalias *alias)
if (boot_type &&
grub_strcmp (boot_type, alias->type) != 0)
{
- grub_dprintf ("ofdisk", "Skipped device: %s, type %s did not match boot_type %s\n",
+ grub_dprintf ("ofdisk", "WARN: device: %s, type %s not match boot_type %s\n",
alias->path, alias->type, boot_type);
- return;
}
if (grub_ieee1275_open (alias->path, &ihandle))
@@ -646,9 +660,8 @@ dev_iterate (const struct grub_ieee1275_devalias *alias)
if (boot_type &&
grub_strcmp (boot_type, alias->type) != 0)
{
- grub_dprintf ("ofdisk", "Skipped device: %s, type %s did not match boot_type %s\n",
+ grub_dprintf ("ofdisk", "WARN: device: %s, type %s not match boot_type %s\n",
alias->path, alias->type, boot_type);
- goto iter_children;
}
buf = grub_malloc (grub_strlen (alias->path) +
@@ -1116,13 +1129,37 @@ get_parent_devname (const char *devname, int *is_nvmeof)
return parent;
}
+
+static int
+is_canonical (const char *path)
+{
+ if (grub_strstr (path, IEEE1275_DISK_ALIAS) ||
+ grub_strstr (path, IEEE1275_NVMEOF_DISK_ALIAS))
+ return 1;
+ else
+ return 0;
+}
+
static char *
get_boot_device_parent (const char *bootpath, int *is_nvmeof)
{
- char *dev, *canon, *parent;
+ char *canon, *parent;
+
+ if (is_canonical (bootpath))
+ {
+ early_log ("Use %s as canonical\n", bootpath);
+ canon = grub_strdup (bootpath);
+ }
+ else
+ {
+ char *dev;
- dev = grub_ieee1275_get_aliasdevname (bootpath);
- canon = grub_ieee1275_canonicalise_devname (dev);
+ dev = grub_ieee1275_get_aliasdevname (bootpath);
+ canon = grub_ieee1275_canonicalise_devname (dev);
+ early_log ("bootpath: %s \n", bootpath);
+ early_log ("alias: %s\n", dev);
+ early_log ("canonical: %s\n", canon);
+ }
if (!canon)
{
@@ -1131,8 +1168,6 @@ get_boot_device_parent (const char *bootpath, int *is_nvmeof)
grub_print_error ();
return NULL;
}
- else
- early_log ("%s is canonical %s\n", bootpath, canon);
parent = get_parent_devname (canon, is_nvmeof);
early_log ("%s is parent of %s\n", parent, canon);
@@ -1179,9 +1214,9 @@ insert_bootpath (void)
boot_parent = get_boot_device_parent (bootpath, &is_boot_nvmeof);
boot_type = grub_ieee1275_get_device_type (boot_parent);
if (boot_type)
- early_log ("the boot device type %s is used for root device discovery, others excluded\n", boot_type);
+ early_log ("the boot device type: %s\n", boot_type);
else
- early_log ("unknown boot device type, will use all devices to discover root and may be slow\n");
+ early_log ("the boot device type is unknown\n");
}
grub_free (type);
grub_free (bootpath);
--
2.44.0

View File

@ -0,0 +1,238 @@
From b353ca96bf002a9262fdf74637f39615d003d069 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 8 Dec 2023 11:51:57 +0800
Subject: [PATCH 1/2] ofdisk: enhance boot time by focusing on boot disk
relevance
After a historical review, it's clear that a boot delay regression
coincided with the introduction of the fcp iterating patch. Reverting
this patch has shown promising signs in mitigating the issue. In order
to improve the efficiency, a more refined discovery process is proposed,
aiming to exclude device types differing from the boot disk to curtail
unnecessary iterations.
This patch extends prior efforts by exclusively targeting root device
discovery linked to the boot disk, verifying device types to prevent
process elongation.
It is worth noting that grub's opportunistic approach to assembling the
root device, seeking accessible results in parallel during iteration,
sometimes allows even a partially assembled RAID, albeit in a degraded
mode. However, delays stem from unrelated devices appearing before the
actual boot device.
To streamline the boot process, the patch utilizes parent nodes in
conjunction with block device nodes to extract essential boot-related
information. This refined identification method efficiently limits the
application's scope to devices connected to the chosen boot device,
notably optimizing subsequent device iteration. By adeptly filtering out
devices not linked to the same FCP (Fibre Channel Protocol) device, it
significantly enhances boot efficiency, ensuring a more streamlined and
efficient boot process.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/disk/ieee1275/ofdisk.c | 136 +++++++++++++++++++++++++++++--
1 file changed, 131 insertions(+), 5 deletions(-)
--- a/grub-core/disk/ieee1275/ofdisk.c
+++ b/grub-core/disk/ieee1275/ofdisk.c
@@ -31,6 +31,13 @@
static char *last_devpath;
static grub_ieee1275_ihandle_t last_ihandle;
+#define IEEE1275_DISK_ALIAS "/disk@"
+#define IEEE1275_NVMEOF_DISK_ALIAS "/nvme-of/controller@"
+
+static char *boot_type;
+static char *boot_parent;
+static int is_boot_nvmeof;
+
struct ofdisk_hash_ent
{
char *devpath;
@@ -529,12 +536,21 @@
{
if (grub_strcmp (alias->type, "fcp") == 0)
{
- // Iterate disks
- dev_iterate_fcp_disks(alias);
-
- // Iterate NVMeoF
- dev_iterate_fcp_nvmeof(alias);
+ if (boot_type &&
+ grub_strcmp (boot_type, alias->type) != 0)
+ {
+ grub_dprintf ("ofdisk", "Skipped device: %s, type %s did not match boot_type %s\n",
+ alias->path, alias->type, boot_type);
+ goto iter_children;
+ }
+ if (grub_strcmp (boot_parent, alias->path) == 0)
+ {
+ if (is_boot_nvmeof)
+ dev_iterate_fcp_nvmeof(alias);
+ else
+ dev_iterate_fcp_disks(alias);
+ }
}
else if (grub_strcmp (alias->type, "vscsi") == 0)
{
@@ -552,6 +568,14 @@
char *buf, *bufptr;
unsigned i;
+ if (boot_type &&
+ grub_strcmp (boot_type, alias->type) != 0)
+ {
+ grub_dprintf ("ofdisk", "Skipped device: %s, type %s did not match boot_type %s\n",
+ alias->path, alias->type, boot_type);
+ return;
+ }
+
if (grub_ieee1275_open (alias->path, &ihandle))
return;
@@ -615,6 +639,14 @@
grub_uint16_t table_size;
grub_ieee1275_ihandle_t ihandle;
+ if (boot_type &&
+ grub_strcmp (boot_type, alias->type) != 0)
+ {
+ grub_dprintf ("ofdisk", "Skipped device: %s, type %s did not match boot_type %s\n",
+ alias->path, alias->type, boot_type);
+ goto iter_children;
+ }
+
buf = grub_malloc (grub_strlen (alias->path) +
sizeof ("/disk@7766554433221100"));
if (!buf)
@@ -674,6 +706,7 @@
return;
}
+ iter_children:
{
struct grub_ieee1275_devalias child;
@@ -1046,6 +1079,68 @@
.next = 0
};
+static char *
+get_parent_devname (const char *devname, int *is_nvmeof)
+{
+ char *parent, *pptr;
+
+ if (is_nvmeof)
+ *is_nvmeof = 0;
+
+ parent = grub_strdup (devname);
+
+ if (parent == NULL)
+ {
+ grub_print_error ();
+ return NULL;
+ }
+
+ pptr = grub_strstr (parent, IEEE1275_DISK_ALIAS);
+
+ if (pptr != NULL)
+ {
+ *pptr = '\0';
+ return parent;
+ }
+
+ pptr = grub_strstr (parent, IEEE1275_NVMEOF_DISK_ALIAS);
+
+ if (pptr != NULL)
+ {
+ *pptr = '\0';
+ if (is_nvmeof)
+ *is_nvmeof = 1;
+ return parent;
+ }
+
+ return parent;
+}
+
+static char *
+get_boot_device_parent (const char *bootpath, int *is_nvmeof)
+{
+ char *dev, *canon, *parent;
+
+ dev = grub_ieee1275_get_aliasdevname (bootpath);
+ canon = grub_ieee1275_canonicalise_devname (dev);
+
+ if (!canon)
+ {
+ /* This should not happen. */
+ grub_error (GRUB_ERR_BAD_DEVICE, "canonicalise devname failed");
+ grub_print_error ();
+ return NULL;
+ }
+ else
+ grub_dprintf ("ofdisk", "%s is canonical %s\n", bootpath, canon);
+
+ parent = get_parent_devname (canon, is_nvmeof);
+ grub_dprintf ("ofdisk", "%s is parent of %s\n", parent, canon);
+
+ grub_free (canon);
+ return parent;
+}
+
static void
insert_bootpath (void)
{
@@ -1081,6 +1176,12 @@
char *device = grub_ieee1275_get_devname (bootpath);
op = ofdisk_hash_add (device, NULL);
op->is_boot = 1;
+ boot_parent = get_boot_device_parent (bootpath, &is_boot_nvmeof);
+ boot_type = grub_ieee1275_get_device_type (boot_parent);
+ if (boot_type)
+ grub_dprintf ("ofdisk", "the boot device type %s is used for root device discovery, others excluded\n", boot_type);
+ else
+ grub_dprintf ("ofdisk", "unknown boot device type, will use all devices to discover root and may be slow\n");
}
grub_free (type);
grub_free (bootpath);
@@ -1097,12 +1198,37 @@
grub_disk_dev_unregister (&grub_ofdisk_dev);
}
+static const char *
+grub_env_get_boot_type (struct grub_env_var *var __attribute__ ((unused)),
+ const char *val __attribute__ ((unused)))
+{
+ static char *ret;
+
+ if (!ret)
+ ret = grub_xasprintf("boot: %s type: %s is_nvmeof: %d",
+ boot_parent,
+ boot_type ? : "unknown",
+ is_boot_nvmeof);
+
+ return ret;
+}
+
+static char *
+grub_env_set_boot_type (struct grub_env_var *var __attribute__ ((unused)),
+ const char *val __attribute__ ((unused)))
+{
+ /* READ ONLY */
+ return NULL;
+}
+
void
grub_ofdisk_init (void)
{
grub_disk_firmware_fini = grub_ofdisk_fini;
insert_bootpath ();
+ grub_register_variable_hook ("ofdisk_boot_type", grub_env_get_boot_type,
+ grub_env_set_boot_type );
grub_disk_dev_register (&grub_ofdisk_dev);
}

View File

@ -0,0 +1,58 @@
From b0f9dcabe96e5689ecfba9b6abcd27e685eabd48 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Wed, 11 May 2022 09:56:11 -0400
Subject: [PATCH] ofdisk: improve boot time by lookup boot disk first
While booting lvm, grub will try to build up logical volumes via hooks
to disk iteration where on-disk metadata can be read and parsed. However
the process can become very slow on multipath as reachable disks are
duplicated by multiple I/O paths and they all get inspected.
Fortunately grub allows lvm to be lazy binding and opportunistic that
root volume can be created when it's needed using a smaller set of
discovered disks. The disk iteration can also be controlled by pull
methods to only returning specified disks. That said we may be able to
take advantage of existing design to cause less overhead in lvm
construction.
This patch will return boot disks in OpenFirmware so they can be used
first. If lvm managed to create root volume out of those boot disks then
it is all very nice as they are readily available. Otherwise disk
scanning will be performed to present all discoverable disks to grub as
what it was done in the past. The result maybe again time consuming but
we have nothing to lose here.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/disk/ieee1275/ofdisk.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
--- a/grub-core/disk/ieee1275/ofdisk.c
+++ b/grub-core/disk/ieee1275/ofdisk.c
@@ -491,10 +491,11 @@
{
unsigned i;
- if (pull != GRUB_DISK_PULL_NONE)
+ if (pull > GRUB_DISK_PULL_REMOVABLE)
return 0;
- scan ();
+ if (pull == GRUB_DISK_PULL_REMOVABLE)
+ scan ();
for (i = 0; i < ARRAY_SIZE (ofdisk_hash); i++)
{
@@ -532,6 +533,12 @@
if (!ent->is_boot && ent->is_removable)
continue;
+ if (pull == GRUB_DISK_PULL_NONE && !ent->is_boot)
+ continue;
+
+ if (pull == GRUB_DISK_PULL_REMOVABLE && ent->is_boot)
+ continue;
+
if (hook (ent->grub_shortest, hook_data))
return 1;
}

View File

@ -0,0 +1,52 @@
From 468628bdc39800341e7aa6ff7795cc0d93cfaf3f Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Tue, 11 Apr 2023 10:59:34 +0800
Subject: [PATCH 1/2] openfw: Ensure get_devargs and get_devname functions are
consistent
Commit 165c9b234 changed the logic of ieee1275_get_devargs() to use the
first or second occurrence of a colon as a separator between device name
and arguments. However, this didn't align with the complementary
function ieee1275_get_devname, which uses the first occurrence of a
colon after the namespace keyword as arguments for the nvme-of device.
This commit addresses the inconsistency by ensuring that both functions
follow a common logic. Now, get_devargs and get_devname functions are
consistent with each other, making it easier to understand and maintain
the codebase.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/kern/ieee1275/openfw.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c
index e2ffec32d..3bbd07d95 100644
--- a/grub-core/kern/ieee1275/openfw.c
+++ b/grub-core/kern/ieee1275/openfw.c
@@ -354,13 +354,16 @@ static char *
grub_ieee1275_get_devargs (const char *path)
{
char *colon = grub_strchr (path, ':');
- char *colon_check = colon;
- /* Find the last occurence of colon */
- while(colon_check){
- colon = colon_check;
- colon_check = grub_strchr (colon+1, ':');
- }
+ /* Use the same logic in grub_ieee1275_get_devname for nvme-of arguments */
+ if (grub_strstr(path, "nvme-of"))
+ {
+ char *namespace_split = grub_strstr(path,"/namespace@");
+ if (namespace_split)
+ colon = grub_strchr (namespace_split, ':');
+ else
+ colon = NULL;
+ }
if (! colon)
return 0;
--
2.39.2

View File

@ -0,0 +1,60 @@
From 72a582b1c3954f9b917a4d687c95fc94faf551c6 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Wed, 24 Jan 2024 18:03:51 +0800
Subject: [PATCH] squash! ieee1275/ofpath: enable NVMeoF logical device
translation
Fixes build error on gcc-14:
[ 73s] In file included from ../grub-core/osdep/ofpath.c:2:
[ 73s] ../grub-core/osdep/linux/ofpath.c: In function 'of_find_fc_host':
[ 73s] ../grub-core/osdep/linux/ofpath.c:427:22: error: allocation of insufficient size '8' for type 'struct ofpath_files_list_root' with size '16' [-Werror=alloc-size]
[ 73s] 427 | portnames_file_list=malloc(sizeof(portnames_file_list));
[ 73s] | ^
[ 73s] ../grub-core/osdep/linux/ofpath.c: In function 'of_path_of_nvme':
[ 73s] ../grub-core/osdep/linux/ofpath.c:589:21: error: allocation of insufficient size '8' for type 'struct ofpath_nvmeof_info' with size '32' [-Werror=alloc-size]
[ 73s] 589 | nvmeof_info = malloc(sizeof(nvmeof_info));
[ 73s] | ^
[ 73s] ../grub-core/osdep/linux/ofpath.c:618:21: error: allocation of insufficient size '8' for type 'struct ofpath_nvmeof_info' with size '32' [-Werror=alloc-size]
[ 73s] 618 | nvmeof_info = malloc(sizeof(nvmeof_info));
[ 73s] | ^
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/osdep/linux/ofpath.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c
index 7129099db..55ed7ddf2 100644
--- a/grub-core/osdep/linux/ofpath.c
+++ b/grub-core/osdep/linux/ofpath.c
@@ -424,7 +424,7 @@ of_find_fc_host(char* host_wwpn){
struct ofpath_files_list_root* portnames_file_list;
- portnames_file_list=malloc(sizeof(portnames_file_list));
+ portnames_file_list=malloc(sizeof(*portnames_file_list));
portnames_file_list->items=0;
portnames_file_list->first=NULL;
@@ -586,7 +586,7 @@ of_path_of_nvme(const char *sys_devname __attribute__((unused)),
/* If is a NVMeoF */
if(strstr(sysfs_path,"nvme-fabrics")){
struct ofpath_nvmeof_info* nvmeof_info;
- nvmeof_info = malloc(sizeof(nvmeof_info));
+ nvmeof_info = malloc(sizeof(*nvmeof_info));
of_path_get_nvmeof_adapter_info(sysfs_path, nvmeof_info);
@@ -615,7 +615,7 @@ of_path_of_nvme(const char *sys_devname __attribute__((unused)),
sysfs_path = nvme_get_syspath (device);
if(strstr(sysfs_path,"nvme-fabrics")){
struct ofpath_nvmeof_info* nvmeof_info;
- nvmeof_info = malloc(sizeof(nvmeof_info));
+ nvmeof_info = malloc(sizeof(*nvmeof_info));
of_path_get_nvmeof_adapter_info(sysfs_path, nvmeof_info);
--
2.43.0

View File

@ -0,0 +1,40 @@
From 60d1d3b959e72c2cbd014be311c350a9b11b1289 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Tue, 7 Sep 2021 10:06:50 +0800
Subject: [PATCH] templates: Follow the path of usr merged kernel config
The background for usr merge can be found at:
https://www.freedesktop.org/wiki/Software/systemd/TheCaseForTheUsrMerge/
This patch adapts related mkconfig scripts to follow the usr merge for
looking up kernel configs.
Signed-off-by: Michael Chang <mchang@suse.com>
---
util/grub.d/10_linux.in | 2 +-
util/grub.d/20_linux_xen.in | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -351,7 +351,7 @@
fi
config=
- for i in "${dirname}/config-${version}" "${dirname}/config-${alt_version}" "/etc/kernels/kernel-config-${version}" ; do
+ for i in "${dirname}/config-${version}" "${dirname}/config-${alt_version}" "/etc/kernels/kernel-config-${version}" "/usr/lib/modules/${version}/config" ; do
if test -e "${i}" ; then
config="${i}"
break
--- a/util/grub.d/20_linux_xen.in
+++ b/util/grub.d/20_linux_xen.in
@@ -307,7 +307,7 @@
version=$(echo $basename | sed -e "s,^[^0-9]*-,,g")
dirname=$(dirname $i)
config=
- for j in "${dirname}/config-${version}" "${dirname}/config-${alt_version}" "/etc/kernels/kernel-config-${version}" ; do
+ for j in "${dirname}/config-${version}" "${dirname}/config-${alt_version}" "/etc/kernels/kernel-config-${version}" "/usr/lib/modules/${version}/config" ; do
if test -e "${j}" ; then
config="${j}"
break

View File

@ -0,0 +1,97 @@
From f41a45b080cb9c6f59879a3e23f9ec2380015a16 Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Thu, 25 Apr 2024 16:21:45 +0800
Subject: [PATCH] tpm2: Add extra RSA SRK types
Since fde-tools may set RSA3072 and RSA4096 as the SRK type, grub2 has
to support those parameters.
Signed-off-by: Gary Lin <glin@suse.com>
---
grub-core/tpm2/args.c | 12 ++++++++++++
grub-core/tpm2/module.c | 16 ++++++++++++++--
util/grub-protect.c | 4 ++--
3 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/grub-core/tpm2/args.c b/grub-core/tpm2/args.c
index c11280ab9..d140364d2 100644
--- a/grub-core/tpm2/args.c
+++ b/grub-core/tpm2/args.c
@@ -92,6 +92,18 @@ grub_tpm2_protector_parse_asymmetric (const char *value,
srk_type->type = TPM_ALG_RSA;
srk_type->detail.rsa_bits = 2048;
}
+ else if (grub_strcasecmp (value, "RSA") == 0 ||
+ grub_strcasecmp (value, "RSA3072") == 0)
+ {
+ srk_type->type = TPM_ALG_RSA;
+ srk_type->detail.rsa_bits = 3072;
+ }
+ else if (grub_strcasecmp (value, "RSA") == 0 ||
+ grub_strcasecmp (value, "RSA4096") == 0)
+ {
+ srk_type->type = TPM_ALG_RSA;
+ srk_type->detail.rsa_bits = 4096;
+ }
else
return grub_error (GRUB_ERR_OUT_OF_RANGE,
N_("Value '%s' is not a valid asymmetric key type"),
diff --git a/grub-core/tpm2/module.c b/grub-core/tpm2/module.c
index b754b38df..8b72ed6fa 100644
--- a/grub-core/tpm2/module.c
+++ b/grub-core/tpm2/module.c
@@ -136,8 +136,8 @@ static const struct grub_arg_option grub_tpm2_protector_init_cmd_options[] =
.arg = NULL,
.type = ARG_TYPE_STRING,
.doc =
- N_("In SRK mode, the type of SRK: RSA (RSA2048) and ECC (ECC_NIST_P256)"
- "(default: ECC)"),
+ N_("In SRK mode, the type of SRK: RSA (RSA2048), RSA3072, RSA4096, "
+ "and ECC (ECC_NIST_P256). (default: ECC)"),
},
/* NV Index-mode options */
{
@@ -541,6 +541,10 @@ srk_type_to_name (grub_srk_type_t srk_type)
{
case 2048:
return "RSA2048";
+ case 3072:
+ return "RSA3072";
+ case 4096:
+ return "RSA4096";
}
}
@@ -561,6 +565,14 @@ grub_tpm2_protector_load_key (const struct grub_tpm2_protector_context *ctx,
.type = TPM_ALG_ECC,
.detail.ecc_curve = TPM_ECC_NIST_P256,
},
+ {
+ .type = TPM_ALG_RSA,
+ .detail.rsa_bits = 4096,
+ },
+ {
+ .type = TPM_ALG_RSA,
+ .detail.rsa_bits = 3072,
+ },
{
.type = TPM_ALG_RSA,
.detail.rsa_bits = 2048,
diff --git a/util/grub-protect.c b/util/grub-protect.c
index 869f45861..00be03ca0 100644
--- a/util/grub-protect.c
+++ b/util/grub-protect.c
@@ -199,8 +199,8 @@ static struct argp_option grub_protect_options[] =
.arg = "TYPE",
.flags = 0,
.doc =
- N_("The type of SRK: RSA (RSA2048) and ECC (ECC_NIST_P256)."
- "(default: ECC)"),
+ N_("The type of SRK: RSA (RSA2048), RSA3072, RSA4096, "
+ "and ECC (ECC_NIST_P256). (default: ECC)"),
.group = 0
},
{
--
2.35.3

View File

@ -0,0 +1,82 @@
From 947009d79e3f17b10a7753bdde8d3a4a7b757bed Mon Sep 17 00:00:00 2001
From: Patrick Colp <patrick.colp@oracle.com>
Date: Mon, 31 Jul 2023 07:01:45 -0700
Subject: [PATCH 1/4] tpm2: Implement NV index
Currently with the TPM2 protector, only SRK mode is supported and
NV index support is just a stub. Implement the NV index option.
Note: This only extends support on the unseal path. grub2_protect
has not been updated. tpm2-tools can be used to insert a key into
the NV index.
An example of inserting a key using tpm2-tools:
# Get random key.
tpm2_getrandom 32 > key.dat
# Create primary object.
tpm2_createprimary -C o -g sha256 -G ecc -c primary.ctx
# Create policy object. `pcrs.dat` contains the PCR values to seal against.
tpm2_startauthsession -S session.dat
tpm2_policypcr -S session.dat -l sha256:7,11 -f pcrs.dat -L policy.dat
tpm2_flushcontext session.dat
# Seal key into TPM.
cat key.dat | tpm2_create -C primary.ctx -u key.pub -r key.priv -L policy.dat -i-
tpm2_load -C primary.ctx -u key.pub -r key.priv -n sealing.name -c sealing.ctx
tpm2_evictcontrol -C o -c sealing.ctx 0x81000000
Then to unseal the key in grub, add this to grub.cfg:
tpm2_key_protector_init --mode=nv --nvindex=0x81000000 --pcrs=7,11
cryptomount -u <UUID> --protector tpm2
Signed-off-by: Patrick Colp <patrick.colp@oracle.com>
Signed-off-by: Gary Lin <glin@suse.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
---
grub-core/tpm2/module.c | 25 ++++++++++++++++++++-----
1 file changed, 20 insertions(+), 5 deletions(-)
diff --git a/grub-core/tpm2/module.c b/grub-core/tpm2/module.c
index e83b02865..b754b38df 100644
--- a/grub-core/tpm2/module.c
+++ b/grub-core/tpm2/module.c
@@ -1035,12 +1035,27 @@ static grub_err_t
grub_tpm2_protector_nv_recover (const struct grub_tpm2_protector_context *ctx,
grub_uint8_t **key, grub_size_t *key_size)
{
- (void)ctx;
- (void)key;
- (void)key_size;
+ TPM_HANDLE sealed_handle = ctx->nv;
+ tpm2key_policy_t policy_seq = NULL;
+ grub_err_t err;
+
+ /* Create a basic policy sequence based on the given PCR selection */
+ err = grub_tpm2_protector_simple_policy_seq (ctx, &policy_seq);
+ if (err != GRUB_ERR_NONE)
+ goto exit;
+
+ err = grub_tpm2_protector_unseal (policy_seq, sealed_handle, key, key_size);
+
+ /* Pop error messages on success */
+ if (err == GRUB_ERR_NONE)
+ while (grub_error_pop ());
+
+exit:
+ TPM2_FlushContext (sealed_handle);
- return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
- N_("NV Index mode is not implemented yet"));
+ grub_tpm2key_free_policy_seq (policy_seq);
+
+ return err;
}
static grub_err_t
--
2.35.3

View File

@ -0,0 +1,171 @@
From 26a66098d5fa50b9462c8c815429a4c18f20310b Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Thu, 6 Apr 2023 16:00:25 +0800
Subject: [PATCH] tpm2: Support authorized policy
This commit handles the TPM2_PolicyAuthorize command from the key file
in TPM 2.0 Key File format.
TPM2_PolicyAuthorize is the essential command to support authorized
policy which allows the users to sign TPM policies with their own keys.
Per TPM 2.0 Key File(*1), CommandPolicy for TPM2_PolicyAuthorize
comprises 'TPM2B_PUBLIC pubkey', 'TPM2B_DIGEST policy_ref', and
'TPMT_SIGNATURE signature'. To verify the signature, the current policy
digest is hashed with the hash algorithm written in 'signature', and then
'signature' is verified with the hashed policy digest and 'pubkey'. Once
TPM accepts 'signature', TPM2_PolicyAuthorize is invoked to authorize the
signed policy.
To create the key file with authorized policy, here are the pcr-oracle(*2)
commands:
# Generate the RSA key and create the authorized policy file
$ pcr-oracle \
--rsa-generate-key \
--private-key policy-key.pem \
--auth authorized.policy \
create-authorized-policy 0,2,4,7,9
# Seal the secret with the authorized policy
$ pcr-oracle \
--key-format tpm2.0 \
--auth authorized.policy \
--input disk-secret.txt \
--output sealed.key \
seal-secret
# Sign the predicted PCR policy
$ pcr-oracle \
--key-format tpm2.0 \
--private-key policy-key.pem \
--from eventlog \
--stop-event "grub-file=grub.cfg" \
--after \
--input sealed.key \
--output sealed.tpm \
sign 0,2,4,7,9
Then specify the key file and the key protector to grub.cfg in the EFI
system partition:
tpm2_key_protector_init -a RSA --tpm2key=(hd0,gpt1)/boot/grub2/sealed.tpm
cryptomount -u <PART_UUID> -P tpm2
For any change in the boot components, just run the 'sign' command again
to update the signature in sealed.tpm, and TPM can unseal the key file
with the updated PCR policy.
(*1) https://www.hansenpartnership.com/draft-bottomley-tpm2-keys.html
(*2) https://github.com/okirch/pcr-oracle
Signed-off-by: Gary Lin <glin@suse.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
---
grub-core/tpm2/module.c | 84 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 84 insertions(+)
diff --git a/grub-core/tpm2/module.c b/grub-core/tpm2/module.c
index 3db25ceca..e83b02865 100644
--- a/grub-core/tpm2/module.c
+++ b/grub-core/tpm2/module.c
@@ -650,6 +650,87 @@ grub_tpm2_protector_policypcr (TPMI_SH_AUTH_SESSION session,
return GRUB_ERR_NONE;
}
+static grub_err_t
+grub_tpm2_protector_policyauthorize (TPMI_SH_AUTH_SESSION session,
+ struct grub_tpm2_buffer *cmd_buf)
+{
+ TPM2B_PUBLIC pubkey;
+ TPM2B_DIGEST policy_ref;
+ TPMT_SIGNATURE signature;
+ TPM2B_DIGEST pcr_policy;
+ TPM2B_DIGEST pcr_policy_hash;
+ TPMI_ALG_HASH sig_hash;
+ TPMT_TK_VERIFIED verification_ticket;
+ TPM_HANDLE pubkey_handle = 0;
+ TPM2B_NAME pubname;
+ TPM_RC rc;
+ grub_err_t err;
+
+ grub_tpm2_mu_TPM2B_PUBLIC_Unmarshal (cmd_buf, &pubkey);
+ grub_tpm2_mu_TPM2B_DIGEST_Unmarshal (cmd_buf, &policy_ref);
+ grub_tpm2_mu_TPMT_SIGNATURE_Unmarshal (cmd_buf, &signature);
+ if (cmd_buf->error != 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("Failed to unmarshal the buffer for TPM2_PolicyAuthorize"));
+
+ /* Retrieve Policy Digest */
+ rc = TPM2_PolicyGetDigest (session, NULL, &pcr_policy, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ return grub_error (GRUB_ERR_BAD_DEVICE,
+ N_("Failed to get policy digest (TPM2_PolicyGetDigest: 0x%x)."),
+ rc);
+
+ /* Calculate the digest of the polcy for VerifySignature */
+ sig_hash = TPMT_SIGNATURE_get_hash_alg (&signature);
+ if (sig_hash == TPM_ALG_NULL)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("Failed to get the hash algorithm of the signature"));
+
+ rc = TPM2_Hash (NULL, (TPM2B_MAX_BUFFER *)&pcr_policy, sig_hash,
+ TPM_RH_NULL, &pcr_policy_hash, NULL, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ return grub_error (GRUB_ERR_BAD_DEVICE,
+ N_("Failed to create PCR policy hash (TPM2_Hash: 0x%x)"),
+ rc);
+
+ /* Load the public key */
+ rc = TPM2_LoadExternal (NULL, NULL, &pubkey, TPM_RH_OWNER,
+ &pubkey_handle, &pubname, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ return grub_error (GRUB_ERR_BAD_DEVICE,
+ N_("Failed to load public key (TPM2_LoadExternal: 0x%x)"),
+ rc);
+
+ /* Verify the signature against the public key and the policy digest */
+ rc = TPM2_VerifySignature (pubkey_handle, NULL, &pcr_policy_hash, &signature,
+ &verification_ticket, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ err = grub_error (GRUB_ERR_BAD_DEVICE,
+ N_("Failed to verify signature (TPM2_VerifySignature: 0x%x)"),
+ rc);
+ goto error;
+ }
+
+ /* Authorize the signed policy with the public key and the verification ticket */
+ rc = TPM2_PolicyAuthorize (session, NULL, &pcr_policy, &policy_ref, &pubname,
+ &verification_ticket, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ err = grub_error (GRUB_ERR_BAD_DEVICE,
+ N_("Failed to authorize PCR policy (TPM2_PolicyAuthorize: 0x%x)"),
+ rc);
+ goto error;
+ }
+
+ err = GRUB_ERR_NONE;
+
+error:
+ TPM2_FlushContext (pubkey_handle);
+
+ return err;
+}
+
static grub_err_t
grub_tpm2_protector_enforce_policy (tpm2key_policy_t policy, TPMI_SH_AUTH_SESSION session)
{
@@ -669,6 +750,9 @@ grub_tpm2_protector_enforce_policy (tpm2key_policy_t policy, TPMI_SH_AUTH_SESSIO
case TPM_CC_PolicyPCR:
err = grub_tpm2_protector_policypcr (session, &buf);
break;
+ case TPM_CC_PolicyAuthorize:
+ err = grub_tpm2_protector_policyauthorize (session, &buf);
+ break;
default:
return grub_error (GRUB_ERR_BAD_ARGUMENT,
N_("Unknown TPM Command: 0x%x"), policy->cmd_code);
--
2.35.3

View File

@ -0,0 +1,188 @@
From 200dc727d1fdf3bac7aa725569b60a54b3841867 Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Fri, 22 Mar 2024 16:23:38 +0800
Subject: [PATCH] util/bash-completion: Fix for bash-completion 2.12
_split_longopt() was the bash-completion private API and removed since
bash-completion 2.12. This commit initializes the bash-completion
general variables with _init_completion() to avoid the potential
'command not found' error.
Although bash-completion 2.12 introduces _comp_initialize() to deprecate
_init_completion(), _init_completion() is still chosen for the better
backward compatibility.
Signed-off-by: Gary Lin <glin@suse.com>
---
.../bash-completion.d/grub-completion.bash.in | 61 +++++++------------
1 file changed, 22 insertions(+), 39 deletions(-)
diff --git a/util/bash-completion.d/grub-completion.bash.in b/util/bash-completion.d/grub-completion.bash.in
index 4c88ee901..749a5d3cf 100644
--- a/util/bash-completion.d/grub-completion.bash.in
+++ b/util/bash-completion.d/grub-completion.bash.in
@@ -151,13 +151,10 @@ __grub_list_modules () {
# grub-set-default & grub-reboot
#
__grub_set_entry () {
- local cur prev split=false
+ local cur prev words cword split
+ _init_completion -s || return
COMPREPLY=()
- cur=`_get_cword`
- prev=${COMP_WORDS[COMP_CWORD-1]}
-
- _split_longopt && split=true
case "$prev" in
--boot-directory)
@@ -180,11 +177,10 @@ __grub_set_entry () {
# grub-editenv
#
__grub_editenv () {
- local cur prev
+ local cur prev words cword
+ _init_completion || return
COMPREPLY=()
- cur=`_get_cword`
- prev=${COMP_WORDS[COMP_CWORD-1]}
case "$prev" in
create|list|set|unset)
@@ -201,10 +197,10 @@ __grub_editenv () {
# grub-mkconfig
#
__grub_mkconfig () {
- local cur prev
+ local cur prev words cword
+ _init_completion || return
COMPREPLY=()
- cur=`_get_cword`
if [[ "$cur" == -* ]]; then
__grubcomp "$(__grub_get_options_from_help)"
@@ -217,13 +213,10 @@ __grub_mkconfig () {
# grub-setup
#
__grub_setup () {
- local cur prev split=false
+ local cur prev words cword split
+ _init_completion -s || return
COMPREPLY=()
- cur=`_get_cword`
- prev=${COMP_WORDS[COMP_CWORD-1]}
-
- _split_longopt && split=true
case "$prev" in
-d|--directory)
@@ -246,15 +239,12 @@ __grub_setup () {
# grub-install
#
__grub_install () {
- local cur prev last split=false
+ local cur prev words cword split last
+ _init_completion -s || return
COMPREPLY=()
- cur=`_get_cword`
- prev=${COMP_WORDS[COMP_CWORD-1]}
last=$(__grub_get_last_option)
- _split_longopt && split=true
-
case "$prev" in
--boot-directory)
_filedir -d
@@ -287,10 +277,10 @@ __grub_install () {
# grub-mkfont
#
__grub_mkfont () {
- local cur
+ local cur prev words cword
+ _init_completion || return
COMPREPLY=()
- cur=`_get_cword`
if [[ "$cur" == -* ]]; then
__grubcomp "$(__grub_get_options_from_help)"
@@ -304,11 +294,10 @@ __grub_mkfont () {
# grub-mkrescue
#
__grub_mkrescue () {
- local cur prev last
+ local cur prev words cword last
+ _init_completion || return
COMPREPLY=()
- cur=`_get_cword`
- prev=${COMP_WORDS[COMP_CWORD-1]}
last=$(__grub_get_last_option)
if [[ "$cur" == -* ]]; then
@@ -330,13 +319,10 @@ __grub_mkrescue () {
# grub-mkimage
#
__grub_mkimage () {
- local cur prev split=false
+ local cur prev words cword split
+ _init_completion -s || return
COMPREPLY=()
- cur=`_get_cword`
- prev=${COMP_WORDS[COMP_CWORD-1]}
-
- _split_longopt && split=true
case "$prev" in
-d|--directory|-p|--prefix)
@@ -367,10 +353,10 @@ __grub_mkimage () {
# grub-mkpasswd-pbkdf2
#
__grub_mkpasswd_pbkdf2 () {
- local cur
+ local cur prev words cword
+ _init_completion || return
COMPREPLY=()
- cur=`_get_cword`
if [[ "$cur" == -* ]]; then
__grubcomp "$(__grub_get_options_from_help)"
@@ -384,13 +370,10 @@ __grub_mkpasswd_pbkdf2 () {
# grub-probe
#
__grub_probe () {
- local cur prev split=false
+ local cur prev words cword split
+ _init_completion -s || return
COMPREPLY=()
- cur=`_get_cword`
- prev=${COMP_WORDS[COMP_CWORD-1]}
-
- _split_longopt && split=true
case "$prev" in
-t|--target)
@@ -417,10 +400,10 @@ __grub_probe () {
# grub-script-check
#
__grub_script_check () {
- local cur
+ local cur prev words cword
+ _init_completion || return
COMPREPLY=()
- cur=`_get_cword`
if [[ "$cur" == -* ]]; then
__grubcomp "$(__grub_get_options_from_help)"
--
2.35.3

View File

@ -0,0 +1,33 @@
From 6ce53d4db8430de5526ea4c48beac8139ba60925 Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Mon, 20 May 2024 14:19:58 +0800
Subject: [PATCH] util: enable grub-protect only for EFI systems
Add 'enable = efi;' back to the grub-protect section to enable the
utility only for EFI systems.
The restriction was relaxed in the upstreaming patch to enable the
grub-emu TPM2 testcases. Since we already build the utility natively for
the architectures with EFI support, there is no need to build the
program again for grub-emu.
Signed-off-by: Gary Lin <glin@suse.com>
---
Makefile.util.def | 1 +
1 file changed, 1 insertion(+)
diff --git a/Makefile.util.def b/Makefile.util.def
index 90850125d..5085152b0 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -210,6 +210,7 @@ program = {
program = {
name = grub-protect;
mansection = 1;
+ enable = efi;
common = grub-core/kern/emu/argp_common.c;
common = grub-core/osdep/init.c;
--
2.35.3

View File

@ -0,0 +1,83 @@
From 6c06378c1bf6ae21788427e62ab0011b7f1bc2f0 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 25 Nov 2022 16:11:24 +0800
Subject: [PATCH] xen_boot: add missing grub_arch_efi_linux_load_image_header
The new xen_boot module has used grub_arch_efi_linux_load_image_header
exported by grub-core/loader/arm64/linux.c. It is not a problem for
upstream but many downstream projects may not use it and take
grub-core/loader/arm64/efi/linux.c as a replacement as PE entry is the
preferred way in combination with shim loader.
This patch did a trivial workaround just adding back the dropped
defintion to the xen_boot itself.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/loader/arm64/xen_boot.c | 50 +++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
diff --git a/grub-core/loader/arm64/xen_boot.c b/grub-core/loader/arm64/xen_boot.c
index 26e1472c9..b82a2db89 100644
--- a/grub-core/loader/arm64/xen_boot.c
+++ b/grub-core/loader/arm64/xen_boot.c
@@ -84,6 +84,56 @@ static int loaded;
static struct xen_boot_binary *xen_hypervisor;
static struct xen_boot_binary *module_head;
+/* The function is exported by grub-core/loader/arm64/linux.c that is not built
+ * because we use PE entry provided by grub-core/loader/arm64/efi/linux.c
+ */
+static bool initrd_use_loadfile2 = false;
+
+grub_err_t
+grub_arch_efi_linux_load_image_header (grub_file_t file,
+ struct linux_arch_kernel_header * lh)
+{
+ grub_file_seek (file, 0);
+ if (grub_file_read (file, lh, sizeof (*lh)) < (grub_ssize_t) sizeof (*lh))
+ return grub_error(GRUB_ERR_FILE_READ_ERROR, "failed to read Linux image header");
+
+ if ((lh->code0 & 0xffff) != GRUB_PE32_MAGIC)
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ N_("plain image kernel not supported - rebuild with CONFIG_(U)EFI_STUB enabled"));
+
+ grub_dprintf ("linux", "UEFI stub kernel:\n");
+ grub_dprintf ("linux", "PE/COFF header @ %08x\n", lh->hdr_offset);
+
+ /*
+ * The PE/COFF spec permits the COFF header to appear anywhere in the file, so
+ * we need to double check whether it was where we expected it, and if not, we
+ * must load it from the correct offset into the pe_image_header field of
+ * struct linux_arch_kernel_header.
+ */
+ if ((grub_uint8_t *) lh + lh->hdr_offset != (grub_uint8_t *) &lh->pe_image_header)
+ {
+ if (grub_file_seek (file, lh->hdr_offset) == (grub_off_t) -1
+ || grub_file_read (file, &lh->pe_image_header,
+ sizeof (struct grub_pe_image_header))
+ != sizeof (struct grub_pe_image_header))
+ return grub_error (GRUB_ERR_FILE_READ_ERROR, "failed to read COFF image header");
+ }
+
+ /*
+ * Linux kernels built for any architecture are guaranteed to support the
+ * LoadFile2 based initrd loading protocol if the image version is >= 1.
+ */
+ if (lh->pe_image_header.optional_header.major_image_version >= 1)
+ initrd_use_loadfile2 = true;
+ else
+ initrd_use_loadfile2 = false;
+
+ grub_dprintf ("linux", "LoadFile2 initrd loading %sabled\n",
+ initrd_use_loadfile2 ? "en" : "dis");
+
+ return GRUB_ERR_NONE;
+}
+
static __inline grub_addr_t
xen_boot_address_align (grub_addr_t start, grub_size_t align)
{
--
2.41.0

View File

@ -0,0 +1,58 @@
From b5c3492f31a98f5ef0f9bec2c0665ad0b71ad5cb Mon Sep 17 00:00:00 2001
From: Sebastian Krahmer <krahmer@suse.com>
Date: Tue, 28 Nov 2017 17:24:38 +0800
Subject: [PATCH] AUDIT-0: http boot tracker bug
Fixing a memory leak in case of error, and a integer overflow, leading to a
heap overflow due to overly large chunk sizes.
We need to check against some maximum value, otherwise values like 0xffffffff
will eventually lead in the allocation functions to small sized buffers, since
the len is rounded up to the next reasonable alignment. The following memcpy
will then smash the heap, leading to RCE.
This is no big issue for pure http boot, since its going to execute an
untrusted kernel anyway, but it will break trusted boot scenarios, where only
signed code is allowed to be executed.
v2: Fix GCC 13 build failure (bsc#1201089)
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/net/efi/net.c | 4 +++-
grub-core/net/http.c | 5 ++++-
2 files changed, 7 insertions(+), 2 deletions(-)
--- a/grub-core/net/efi/net.c
+++ b/grub-core/net/efi/net.c
@@ -654,8 +654,10 @@
rd = efi_net_interface (read, file, chunk, sz);
- if (rd <= 0)
+ if (rd <= 0) {
+ grub_free (chunk);
return rd;
+ }
if (buf)
{
--- a/grub-core/net/http.c
+++ b/grub-core/net/http.c
@@ -30,6 +30,7 @@
GRUB_MOD_LICENSE ("GPLv3+");
#define HTTP_PORT ((grub_uint16_t) 80)
+#define HTTP_MAX_CHUNK_SIZE GRUB_INT_MAX
typedef struct http_data
{
@@ -82,6 +83,8 @@
if (data->in_chunk_len == 2)
{
data->chunk_rem = grub_strtoul (ptr, 0, 16);
+ if (data->chunk_rem > HTTP_MAX_CHUNK_SIZE)
+ return GRUB_ERR_NET_PACKET_TOO_BIG;
grub_errno = GRUB_ERR_NONE;
if (data->chunk_rem == 0)
{

View File

@ -0,0 +1,411 @@
From 439de947262b0d8d4a02ca5afb1ef4f15853962c Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Fri, 9 Dec 2016 15:40:29 -0500
Subject: [PATCH 2/9] Add BLS support to grub-mkconfig
GRUB now has BootLoaderSpec support, the user can choose to use this by
setting GRUB_ENABLE_BLSCFG to true in /etc/default/grub. On this setup,
the boot menu entries are not added to the grub.cfg, instead BLS config
files are parsed by blscfg command and the entries created dynamically.
A 10_linux_bls grub.d snippet to generate menu entries from BLS files
is also added that can be used on platforms where the bootloader doesn't
have BLS support and only can parse a normal grub configuration file.
Portions of the 10_linux_bls were taken from the ostree-grub-generator
script that's included in the OSTree project.
Fixes to support multi-devices and generate a BLS section even if no
kernels are found in the boot directory were proposed by Yclept Nemo
and Tom Gundersen respectively.
Signed-off-by: Peter Jones <pjones@redhat.com>
[javierm: remove outdated URL for BLS document]
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
[iwienand@redhat.com: skip machine ID check when updating entries]
Signed-off-by: Ian Wienand <iwienand@redhat.com>
[rharwood: commit message composits, drop man pages]
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
---
util/grub-mkconfig.in | 9 +-
util/grub-mkconfig_lib.in | 22 +++-
util/grub.d/10_linux.in | 244 +++++++++++++++++++++++++++++++++++++-
3 files changed, 269 insertions(+), 6 deletions(-)
diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
index cf5b79342..7af15df94 100644
--- a/util/grub-mkconfig.in
+++ b/util/grub-mkconfig.in
@@ -49,6 +49,8 @@ grub_script_check="${bindir}/@grub_script_check@"
export TEXTDOMAIN=@PACKAGE@
export TEXTDOMAINDIR="@localedir@"
+export GRUB_GRUBENV_UPDATE="yes"
+
. "${pkgdatadir}/grub-mkconfig_lib"
# Usage: usage
@@ -58,6 +60,7 @@ usage () {
gettext "Generate a grub config file"; echo
echo
print_option_help "-o, --output=$(gettext FILE)" "$(gettext "output generated config to FILE [default=stdout]")"
+ print_option_help "--no-grubenv-update" "$(gettext "do not update variables in the grubenv file")"
print_option_help "-h, --help" "$(gettext "print this message and exit")"
print_option_help "-V, --version" "$(gettext "print the version information and exit")"
echo
@@ -93,6 +96,9 @@ do
--output=*)
grub_cfg=`echo "$option" | sed 's/--output=//'`
;;
+ --no-grubenv-update)
+ GRUB_GRUBENV_UPDATE="no"
+ ;;
-*)
gettext_printf "Unrecognized option \`%s'\n" "$option" 1>&2
usage
@@ -300,7 +306,8 @@ export GRUB_DEFAULT \
GRUB_DISABLE_SUBMENU \
SUSE_BTRFS_SNAPSHOT_BOOTING \
SUSE_CMDLINE_XENEFI \
- SUSE_REMOVE_LINUX_ROOT_PARAM
+ SUSE_REMOVE_LINUX_ROOT_PARAM \
+ GRUB_ENABLE_BLSCFG
if test "x${grub_cfg}" != "x"; then
rm -f "${grub_cfg}.new"
diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in
index 22fb7668f..5db4337c6 100644
--- a/util/grub-mkconfig_lib.in
+++ b/util/grub-mkconfig_lib.in
@@ -30,6 +30,9 @@ fi
if test "x$grub_file" = x; then
grub_file="${bindir}/@grub_file@"
fi
+if test "x$grub_editenv" = x; then
+ grub_editenv="${bindir}/@grub_editenv@"
+fi
if test "x$grub_mkrelpath" = x; then
grub_mkrelpath="${bindir}/@grub_mkrelpath@"
fi
@@ -123,8 +126,19 @@ EOF
fi
}
+prepare_grub_to_access_device_with_variable ()
+{
+ device_variable="$1"
+ shift
+ prepare_grub_to_access_device "$@"
+ unset "device_variable"
+}
+
prepare_grub_to_access_device ()
{
+ if [ -z "$device_variable" ]; then
+ device_variable="root"
+ fi
old_ifs="$IFS"
IFS='
'
@@ -159,18 +173,18 @@ prepare_grub_to_access_device ()
# otherwise set root as per value in device.map.
fs_hint="`"${grub_probe}" --device $@ --target=compatibility_hint`"
if [ "x$fs_hint" != x ]; then
- echo "set root='$fs_hint'"
+ echo "set ${device_variable}='$fs_hint'"
fi
if [ "x${GRUB_DISABLE_UUID}" != "xtrue" ] && fs_uuid="`"${grub_probe}" --device $@ --target=fs_uuid 2> /dev/null`" ; then
hints="`"${grub_probe}" --device $@ --target=hints_string 2> /dev/null`" || hints=
if [ "x$hints" != x ]; then
echo "if [ x\$feature_platform_search_hint = xy ]; then"
- echo " search --no-floppy --fs-uuid --set=root ${hints} ${fs_uuid}"
+ echo " search --no-floppy --fs-uuid --set=${device_variable} ${hints} ${fs_uuid}"
echo "else"
- echo " search --no-floppy --fs-uuid --set=root ${fs_uuid}"
+ echo " search --no-floppy --fs-uuid --set=${device_variable} ${fs_uuid}"
echo "fi"
else
- echo "search --no-floppy --fs-uuid --set=root ${fs_uuid}"
+ echo "search --no-floppy --fs-uuid --set=${device_variable} ${fs_uuid}"
fi
fi
IFS="$old_ifs"
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index 5531239eb..49eccbeaf 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -91,6 +91,244 @@ if [ "x$SUSE_REMOVE_LINUX_ROOT_PARAM" = "xtrue" ]; then
LINUX_ROOT_DEVICE=""
fi
+populate_header_warn()
+{
+if [ "x${BLS_POPULATE_MENU}" = "xtrue" ]; then
+ bls_parser="10_linux script"
+else
+ bls_parser="blscfg command"
+fi
+cat <<EOF
+
+# This section was generated by a script. Do not modify the generated file - all changes
+# will be lost the next time file is regenerated. Instead edit the BootLoaderSpec files.
+#
+# The $bls_parser parses the BootLoaderSpec files stored in /boot/loader/entries and
+# populates the boot menu. Please refer to the Boot Loader Specification documentation
+# for the files format: https://systemd.io/BOOT_LOADER_SPECIFICATION/.
+
+EOF
+}
+
+read_config()
+{
+ config_file=${1}
+ title=""
+ initrd=""
+ options=""
+ linux=""
+ grub_arg=""
+
+ while read -r line
+ do
+ record=$(echo ${line} | cut -f 1 -d ' ')
+ value=$(echo ${line} | cut -s -f2- -d ' ')
+ case "${record}" in
+ "title")
+ title=${value}
+ ;;
+ "initrd")
+ initrd=${value}
+ ;;
+ "linux")
+ linux=${value}
+ ;;
+ "options")
+ options=${value}
+ ;;
+ "grub_arg")
+ grub_arg=${value}
+ ;;
+ esac
+ done < ${config_file}
+}
+
+blsdir="/boot/loader/entries"
+
+get_sorted_bls()
+{
+ if ! [ -d "${blsdir}" ]; then
+ return
+ fi
+
+ local IFS=$'\n'
+
+ files=($(for bls in ${blsdir}/*.conf; do
+ if ! [[ -e "${bls}" ]] ; then
+ continue
+ fi
+ bls="${bls%.conf}"
+ bls="${bls##*/}"
+ echo "${bls}"
+ done | ${kernel_sort} 2>/dev/null | tac)) || :
+
+ echo "${files[@]}"
+}
+
+update_bls_cmdline()
+{
+ local cmdline="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
+ local -a files=($(get_sorted_bls))
+
+ for bls in "${files[@]}"; do
+ local options="${cmdline}"
+ if [ -z "${bls##*debug*}" ]; then
+ options="${options} ${GRUB_CMDLINE_LINUX_DEBUG}"
+ fi
+ options="$(echo "${options}" | sed -e 's/\//\\\//g')"
+ sed -i -e "s/^options.*/options ${options}/" "${blsdir}/${bls}.conf"
+ done
+}
+
+populate_menu()
+{
+ local -a files=($(get_sorted_bls))
+
+ gettext_printf "Generating boot entries from BLS files...\n" >&2
+
+ for bls in "${files[@]}"; do
+ read_config "${blsdir}/${bls}.conf"
+
+ menu="${menu}menuentry '${title}' ${grub_arg} --id=${bls} {\n"
+ menu="${menu}\t linux ${linux} ${options}\n"
+ if [ -n "${initrd}" ] ; then
+ menu="${menu}\t initrd ${boot_prefix}${initrd}\n"
+ fi
+ menu="${menu}}\n\n"
+ done
+ # The printf command seems to be more reliable across shells for special character (\n, \t) evaluation
+ printf "$menu"
+}
+
+# Make BLS the default if GRUB_ENABLE_BLSCFG was not set and grubby is not installed.
+if [ -z "${GRUB_ENABLE_BLSCFG}" ] && ! command -v new-kernel-pkg >/dev/null; then
+ GRUB_ENABLE_BLSCFG="true"
+fi
+
+if [ "x${GRUB_ENABLE_BLSCFG}" = "xtrue" ]; then
+ if [ x$dirname = x/ ]; then
+ if [ -z "${prepare_root_cache}" ]; then
+ prepare_grub_to_access_device ${GRUB_DEVICE}
+ fi
+ else
+ if [ -z "${prepare_boot_cache}" ]; then
+ prepare_grub_to_access_device ${GRUB_DEVICE_BOOT}
+ fi
+ fi
+
+ if [ -d /sys/firmware/efi ]; then
+ bootefi_device="`${grub_probe} --target=device /boot/efi/`"
+ prepare_grub_to_access_device_with_variable boot ${bootefi_device}
+ else
+ boot_device="`${grub_probe} --target=device /boot/`"
+ prepare_grub_to_access_device_with_variable boot ${boot_device}
+ fi
+
+ arch="$(uname -m)"
+ if [ "x${arch}" = "xppc64le" ] && [ -d /sys/firmware/opal ]; then
+
+ BLS_POPULATE_MENU="true"
+ petitboot_path="/sys/firmware/devicetree/base/ibm,firmware-versions/petitboot"
+
+ if test -e ${petitboot_path}; then
+ read -r -d '' petitboot_version < ${petitboot_path}
+ petitboot_version="$(echo ${petitboot_version//v})"
+
+ if test -n ${petitboot_version}; then
+ major_version="$(echo ${petitboot_version} | cut -d . -f1)"
+ minor_version="$(echo ${petitboot_version} | cut -d . -f2)"
+
+ re='^[0-9]+$'
+ if [[ $major_version =~ $re ]] && [[ $minor_version =~ $re ]] &&
+ ([[ ${major_version} -gt 1 ]] ||
+ [[ ${major_version} -eq 1 &&
+ ${minor_version} -ge 8 ]]); then
+ BLS_POPULATE_MENU="false"
+ fi
+ fi
+ fi
+ fi
+
+ populate_header_warn
+
+ cat << EOF
+# The kernelopts variable should be defined in the grubenv file. But to ensure that menu
+# entries populated from BootLoaderSpec files that use this variable work correctly even
+# without a grubenv file, define a fallback kernelopts variable if this has not been set.
+#
+# The kernelopts variable in the grubenv file can be modified using the grubby tool or by
+# executing the grub2-mkconfig tool. For the latter, the values of the GRUB_CMDLINE_LINUX
+# and GRUB_CMDLINE_LINUX_DEFAULT options from /etc/default/grub file are used to set both
+# the kernelopts variable in the grubenv file and the fallback kernelopts variable.
+if [ -z "\${kernelopts}" ]; then
+ set kernelopts="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
+fi
+EOF
+
+ update_bls_cmdline
+
+ if [ "x${BLS_POPULATE_MENU}" = "xtrue" ]; then
+ populate_menu
+ else
+ cat << EOF
+
+insmod blscfg
+blscfg
+EOF
+ fi
+
+ if [ "x${GRUB_GRUBENV_UPDATE}" = "xyes" ]; then
+ blsdir="/boot/loader/entries"
+ [ -d "${blsdir}" ] && GRUB_BLS_FS="$(${grub_probe} --target=fs ${blsdir})"
+ if [ "x${GRUB_BLS_FS}" = "xbtrfs" ] || [ "x${GRUB_BLS_FS}" = "xzfs" ]; then
+ blsdir=$(make_system_path_relative_to_its_root "${blsdir}")
+ if [ "x${blsdir}" != "x/loader/entries" ] && [ "x${blsdir}" != "x/boot/loader/entries" ]; then
+ ${grub_editenv} - set blsdir="${blsdir}"
+ fi
+ fi
+
+ if [ -n "${GRUB_EARLY_INITRD_LINUX_CUSTOM}" ]; then
+ ${grub_editenv} - set early_initrd="${GRUB_EARLY_INITRD_LINUX_CUSTOM}"
+ fi
+
+ if [ -n "${GRUB_DEFAULT_DTB}" ]; then
+ ${grub_editenv} - set devicetree="${GRUB_DEFAULT_DTB}"
+ fi
+
+ if [ -n "${GRUB_SAVEDEFAULT}" ]; then
+ ${grub_editenv} - set save_default="${GRUB_SAVEDEFAULT}"
+ fi
+ fi
+
+ exit 0
+fi
+
+mktitle ()
+{
+ local title_type
+ local version
+ local OS_NAME
+ local OS_VERS
+
+ title_type=$1 && shift
+ version=$1 && shift
+
+ OS_NAME="$(eval $(grep ^NAME= /etc/os-release) ; echo ${NAME})"
+ OS_VERS="$(eval $(grep ^VERSION= /etc/os-release) ; echo ${VERSION})"
+
+ case $title_type in
+ recovery)
+ title=$(printf '%s (%s) %s (recovery mode)' \
+ "${OS_NAME}" "${version}" "${OS_VERS}")
+ ;;
+ *)
+ title=$(printf '%s (%s) %s' \
+ "${OS_NAME}" "${version}" "${OS_VERS}")
+ ;;
+ esac
+ echo -n ${title}
+}
+
title_correction_code=
hotkey=1
@@ -124,6 +362,7 @@ linux_entry ()
if [ -z "$boot_device_id" ]; then
boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")"
fi
+
if [ x$type != xsimple ] ; then
case $type in
recovery)
@@ -298,6 +537,7 @@ fi
is_top_level=true
for linux in ${reverse_sorted_list}; do
gettext_printf "Found linux image: %s\n" "$linux" >&2
+
basename=`basename $linux`
dirname=`dirname $linux`
rel_dirname=`make_system_path_relative_to_its_root $dirname`
@@ -348,7 +588,9 @@ for linux in ${reverse_sorted_list}; do
for i in ${initrd}; do
initrd_display="${initrd_display} ${dirname}/${i}"
done
- gettext_printf "Found initrd image: %s\n" "$(echo $initrd_display)" >&2
+ if [ "x${GRUB_ENABLE_BLSCFG}" != "xtrue" ]; then
+ gettext_printf "Found initrd image: %s\n" "$(echo $initrd_display)" >&2
+ fi
fi
config=
--
2.44.0

View File

@ -0,0 +1,53 @@
From c0d00403a297d6023eab6189ba87dc8a3f6d1e85 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Mon, 7 Feb 2022 20:44:40 +0800
Subject: [PATCH 2/5] Add grub_disk_write_tail helper function
This helps in writing data to partition where the end of buffer is
aligned to end of partition.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/lib/disk.c | 18 ++++++++++++++++++
include/grub/disk.h | 3 +++
2 files changed, 21 insertions(+)
--- a/grub-core/lib/disk.c
+++ b/grub-core/lib/disk.c
@@ -52,6 +52,24 @@
}
grub_err_t
+grub_disk_write_tail (grub_disk_t disk, grub_size_t size, const void *buf)
+{
+ grub_partition_t part;
+ grub_disk_addr_t sector;
+ grub_off_t offset;
+
+ if (!disk->partition)
+ return GRUB_ERR_NONE;
+
+ part = disk->partition;
+ sector = part->len;
+ sector -= (size + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS;
+ offset = size & (GRUB_DISK_SECTOR_SIZE - 1);
+
+ return grub_disk_write (disk, sector, offset, size, buf);
+}
+
+grub_err_t
grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector,
grub_off_t offset, grub_size_t size, const void *buf)
{
--- a/include/grub/disk.h
+++ b/include/grub/disk.h
@@ -252,6 +252,9 @@
grub_off_t offset,
grub_size_t size,
void *buf);
+grub_err_t grub_disk_write_tail (grub_disk_t disk,
+ grub_size_t size,
+ const void *buf);
grub_err_t grub_disk_write (grub_disk_t disk,
grub_disk_addr_t sector,
grub_off_t offset,

View File

@ -0,0 +1,57 @@
From 337b3d963d28b3544e8817428fb68ca559613a39 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 9 Sep 2021 10:59:28 -0400
Subject: [PATCH 2/2] Arm: check for the PE magic for the compiled arch
In "arm64: Fix EFI loader kernel image allocation", Ben fixed the kernel
alignment to match the alignment given in the PE header. In doing so, a
check for valid PE magic was added, which was hard-coded to the value
seen on Aarch64 (GRUB_PE32_PE64_MAGIC).
Unfortunately, this code is shared between 64-bit and 32-bit, and so
that value broke 32-bit Arm systems.
This patch adds a constant definition for GRUB_PE32_PEXX_MAGIC, which is
either GRUB_PE32_PE64_MAGIC or GRUB_PE32_PE32_MAGIC, depending on which
platform is being built, and uses it in the header magic check.
Resolves: rhbz#2000756
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/loader/arm64/efi/linux.c | 2 +-
include/grub/arm/linux.h | 1 +
include/grub/arm64/linux.h | 1 +
3 files changed, 3 insertions(+), 1 deletion(-)
--- a/grub-core/loader/arm64/efi/linux.c
+++ b/grub-core/loader/arm64/efi/linux.c
@@ -376,7 +376,7 @@
pe = (void *)((unsigned long)kernel + lh->hdr_offset);
- if (pe->opt.magic != GRUB_PE32_PE64_MAGIC)
+ if (pe->opt.magic != GRUB_PE32_PEXX_MAGIC)
return grub_error(GRUB_ERR_BAD_OS, "Invalid PE optional header magic");
*total_size = pe->opt.image_size;
--- a/include/grub/arm/linux.h
+++ b/include/grub/arm/linux.h
@@ -33,6 +33,7 @@
};
#if defined(__arm__)
+# define GRUB_PE32_PEXX_MAGIC GRUB_PE32_PE32_MAGIC
# define grub_armxx_linux_pe_header grub_arm_linux_pe_header
#endif
--- a/include/grub/arm64/linux.h
+++ b/include/grub/arm64/linux.h
@@ -33,6 +33,7 @@
#if defined(__aarch64__)
# define GRUB_LINUX_ARMXX_MAGIC_SIGNATURE GRUB_LINUX_ARM64_MAGIC_SIGNATURE
+# define GRUB_PE32_PEXX_MAGIC GRUB_PE32_PE64_MAGIC
# define grub_armxx_linux_pe_header grub_arm64_linux_pe_header
#endif

View File

@ -0,0 +1,92 @@
From e72dcb40356f56efd86ab88c2f5cb7411d1e898b Mon Sep 17 00:00:00 2001
From: Matthew Garrett <mjg59@coreos.com>
Date: Tue, 14 Jul 2015 16:58:51 -0700
Subject: [PATCH 02/11] Fix race in EFI validation
---
grub-core/loader/i386/efi/linux.c | 40 +++++++------------------------
1 file changed, 9 insertions(+), 31 deletions(-)
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
index 06814cae3..1e09c88ab 100644
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -154,7 +154,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_file_t file = 0;
struct linux_i386_kernel_header lh;
grub_ssize_t len, start, filelen;
- void *kernel;
+ void *kernel = NULL;
grub_err_t err;
grub_dl_ref (my_mod);
@@ -185,10 +185,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
- grub_file_seek (file, 0);
-
- grub_free(kernel);
-
params = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(16384));
if (! params)
@@ -199,13 +195,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_memset (params, 0, 16384);
- if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
- {
- if (!grub_errno)
- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
- argv[0]);
- goto fail;
- }
+ grub_memcpy (&lh, kernel, sizeof (lh));
if (lh.boot_flag != grub_cpu_to_le16 (0xaa55))
{
@@ -271,26 +261,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
- if (grub_file_seek (file, start) == (grub_off_t) -1)
- {
- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
- argv[0]);
- goto fail;
- }
-
- if (grub_file_read (file, kernel_mem, len) != len && !grub_errno)
- {
- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
- argv[0]);
- }
-
- if (grub_errno == GRUB_ERR_NONE)
- {
- grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
- loaded = 1;
- lh.code32_start = (grub_uint32_t)(grub_addr_t) kernel_mem;
- }
+ grub_memcpy (kernel_mem, (char *)kernel + start, len);
+ grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
+ loaded=1;
+ lh.code32_start = (grub_uint32_t)(grub_uint64_t) kernel_mem;
/* Grub linuxefi erroneously initialize linux's boot_params with non-zero values. (bsc#1025563)
From https://www.kernel.org/doc/Documentation/x86/boot.txt:
@@ -307,6 +282,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
if (file)
grub_file_close (file);
+ if (kernel)
+ grub_free (kernel);
+
if (grub_errno != GRUB_ERR_NONE)
{
grub_dl_unref (my_mod);
--
2.31.1

View File

@ -0,0 +1,57 @@
From f01314a822dbe9ad39b2f7d0f3717ef6e4c24f4a Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 15 Apr 2022 21:45:04 +0800
Subject: [PATCH 2/2] Mark environmet blocks as used for image embedding.
Now that grub will attempt to use full btrfs bootloader area, the
embedded image could have overlapped with environment blocks if it's
size grows too much. Let's define a dedicated area for environment
blocks to the used block mappings for the embedding process so it can be
skipped.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/fs/btrfs.c | 3 ++-
include/grub/fs.h | 2 ++
util/grub-editenv.c | 2 +-
3 files changed, 5 insertions(+), 2 deletions(-)
--- a/grub-core/fs/btrfs.c
+++ b/grub-core/fs/btrfs.c
@@ -2637,7 +2637,7 @@
static const struct {
struct embed_region available;
- struct embed_region used[6];
+ struct embed_region used[7];
} btrfs_head = {
.available = {0, GRUB_DISK_KiB_TO_SECTORS (1024)}, /* The first 1 MiB. */
.used = {
@@ -2645,6 +2645,7 @@
{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_DISK_KiB_TO_SECTORS (ENV_BTRFS_OFFSET) - 1, 3}, /* Environment Block. */
{GRUB_DISK_KiB_TO_SECTORS (1024) - 1, 1}, /* Overflow guard. */
{0, 0} /* Array terminator. */
}
--- a/include/grub/fs.h
+++ b/include/grub/fs.h
@@ -128,4 +128,6 @@
grub_fs_t EXPORT_FUNC(grub_fs_probe) (grub_device_t device);
+#define ENV_BTRFS_OFFSET (256)
+
#endif /* ! GRUB_FS_HEADER */
--- a/util/grub-editenv.c
+++ b/util/grub-editenv.c
@@ -128,7 +128,7 @@
int offset;
int size;
} fs_envblk_spec[] = {
- { "btrfs", 256 * 1024, GRUB_DISK_SECTOR_SIZE },
+ { "btrfs", ENV_BTRFS_OFFSET * 1024, GRUB_DISK_SECTOR_SIZE },
{ NULL, 0, 0 }
};

View File

@ -0,0 +1,59 @@
From 9f18541245858f53fea72d8d60304f9015d88b5f Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 17 Mar 2023 22:00:23 +0800
Subject: [PATCH 2/2] Restrict cryptsetup key file permission for better
security
GRUB's default permission 777 for concatenated initrd files was too
permissive for the cryptsetup key file, causing a complaint from
systemd-cryptsetup during boot. This commit replaces the 0777 permission
with a more secure 0400 permission for the key file.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/loader/linux.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
--- a/grub-core/loader/linux.c
+++ b/grub-core/loader/linux.c
@@ -32,6 +32,7 @@
char *buf;
char *newc_name;
grub_off_t size;
+ grub_uint32_t mode;
};
struct dir
@@ -203,6 +204,7 @@
grub_memcpy (comp->buf, buf, bufsz);
initrd_ctx->nfiles++;
comp->size = bufsz;
+ comp->mode = 0100400;
if (grub_add (initrd_ctx->size, comp->size,
&initrd_ctx->size))
goto overflow;
@@ -272,6 +274,7 @@
grub_initrd_close (initrd_ctx);
return grub_errno;
}
+ initrd_ctx->components[i].mode = 0100777;
name_len = grub_strlen (initrd_ctx->components[i].newc_name) + 1;
if (grub_add (initrd_ctx->size,
ALIGN_UP (sizeof (struct newc_head) + name_len, 4),
@@ -374,6 +377,7 @@
if (initrd_ctx->components[i].newc_name)
{
grub_size_t dir_size;
+ grub_uint32_t mode = initrd_ctx->components[i].mode;
if (insert_dir (initrd_ctx->components[i].newc_name, &root, ptr,
&dir_size))
@@ -385,7 +389,7 @@
ptr += dir_size;
ptr = make_header (ptr, initrd_ctx->components[i].newc_name,
grub_strlen (initrd_ctx->components[i].newc_name) + 1,
- 0100777,
+ mode,
initrd_ctx->components[i].size);
newc = 1;
}

View File

@ -0,0 +1,197 @@
From 912384e63c1e3b6aa9d90effb71cd535a17da1e2 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Sat, 18 Nov 2023 19:02:31 +0800
Subject: [PATCH 2/4] Restrict file access on cryptodisk print
When the encrypted partition is automatically unlocked by TPM, granting
access to the system upon validation of its known good state, there's a
potential vulnerability. Grub gains access to file systems that were
previously inaccessible to the public, enabling certain commands from
the grub console to print content. This arises due to grub lacking
restrictions similar to those imposed by password authentication, which
typically occurs before privileged access is granted.
Although the automatic unlocking process ensures system integrity and a
secure environment for grub to operate in, it doesn't directly address
the issue of authentication for viewing encrypted partition content.
This commit addresses this security loophole by implementing a file
filter upon adding a TPM key. The newly added file filter will
specifically verify if the disk is encrypted, denying access and
returning an "Access Denied: prohibited to view encrypted data" error
message to alert the user.
Since the policy to filter out unwanted commands from leaking encrypted
content is irreversible, it is advisable to make the loaded module
persistent to prevent its removal.
This enhancement aims to bolster security measures and prevent
unauthorized access to encrypted data.
Signed-Off-by Michael Chang <mchang@suse.com>
---
grub-core/commands/crypttab.c | 35 ++++++++++++++++++++++++++++++++++-
grub-core/disk/diskfilter.c | 35 +++++++++++++++++++++++++++++++++++
include/grub/disk.h | 10 ++++++++++
include/grub/file.h | 1 +
4 files changed, 80 insertions(+), 1 deletion(-)
diff --git a/grub-core/commands/crypttab.c b/grub-core/commands/crypttab.c
index 9397bede9..d3acc4b59 100644
--- a/grub-core/commands/crypttab.c
+++ b/grub-core/commands/crypttab.c
@@ -6,11 +6,39 @@
#include <grub/mm.h>
#include <grub/list.h>
#include <grub/crypttab.h>
+#include <grub/file.h>
GRUB_MOD_LICENSE ("GPLv3+");
grub_crypto_key_list_t *cryptokey_lst;
+static grub_file_t
+grub_nocat_open (grub_file_t io, enum grub_file_type type)
+{
+ grub_disk_t disk;
+
+ /* Network device */
+ if (!io->device->disk)
+ return io;
+
+ disk = io->device->disk;
+
+ if (grub_disk_is_crypto (disk))
+ {
+ switch (type & GRUB_FILE_TYPE_MASK)
+ {
+ case GRUB_FILE_TYPE_CAT:
+ case GRUB_FILE_TYPE_HEXCAT:
+ grub_error (GRUB_ERR_ACCESS_DENIED, N_("prohibited to view encrypted data"));
+ return NULL;
+ default:
+ break;
+ }
+ }
+
+ return io;
+}
+
grub_err_t
grub_cryptokey_add_or_update (const char *uuid, const char *key, grub_size_t key_len, const char *path, int is_tpmkey)
{
@@ -48,7 +76,11 @@ grub_cryptokey_add_or_update (const char *uuid, const char *key, grub_size_t key
}
if (is_tpmkey >= 0)
- cur->is_tpmkey = is_tpmkey;
+ {
+ cur->is_tpmkey = is_tpmkey;
+ if (is_tpmkey)
+ grub_file_filter_register (GRUB_FILE_FILTER_NOCAT, grub_nocat_open);
+ }
if (!cur->name)
{
@@ -121,6 +153,7 @@ GRUB_MOD_INIT(crypttab)
{
cmd = grub_register_command ("crypttab_entry", grub_cmd_crypttab_entry,
N_("VOLUME-NAME ENCRYPTED-DEVICE KEY-FILE") , N_("No description"));
+ grub_dl_set_persistent (mod);
}
GRUB_MOD_FINI(crypttab)
diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c
index 5c5fabe1a..b0c1c880d 100644
--- a/grub-core/disk/diskfilter.c
+++ b/grub-core/disk/diskfilter.c
@@ -558,6 +558,39 @@ find_lv (const char *name)
return NULL;
}
+static int
+grub_diskfilter_has_cryptodisk (const struct grub_diskfilter_lv *lv)
+{
+ struct grub_diskfilter_pv *pv;
+
+ if (!lv)
+ return 0;
+
+ if (lv->vg->pvs)
+ for (pv = lv->vg->pvs; pv; pv = pv->next)
+ {
+ if (!pv->disk)
+ {
+ grub_dprintf ("diskfilter", _("Couldn't find physical volume `%s'."
+ " Some modules may be missing from core image."),
+ pv->name);
+ continue;
+ }
+
+ switch (pv->disk->dev->id)
+ {
+ case GRUB_DISK_DEVICE_CRYPTODISK_ID:
+ return 1;
+ case GRUB_DISK_DEVICE_DISKFILTER_ID:
+ return grub_diskfilter_has_cryptodisk (pv->disk->data);
+ default:
+ break;
+ }
+ }
+
+ return 0;
+}
+
static grub_err_t
grub_diskfilter_open (const char *name, grub_disk_t disk)
{
@@ -589,6 +622,8 @@ grub_diskfilter_open (const char *name, grub_disk_t disk)
disk->total_sectors = lv->size;
disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE;
+ disk->is_crypto_diskfilter = grub_diskfilter_has_cryptodisk (lv);
+
return 0;
}
diff --git a/include/grub/disk.h b/include/grub/disk.h
index 3b3db6222..63982f16c 100644
--- a/include/grub/disk.h
+++ b/include/grub/disk.h
@@ -147,6 +147,8 @@ struct grub_disk
/* Device-specific data. */
void *data;
+
+ int is_crypto_diskfilter;
};
typedef struct grub_disk *grub_disk_t;
@@ -314,4 +316,12 @@ void grub_mdraid1x_fini (void);
void grub_diskfilter_fini (void);
#endif
+static inline int
+grub_disk_is_crypto (grub_disk_t disk)
+{
+ return ((disk->is_crypto_diskfilter ||
+ disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID) ?
+ 1 : 0);
+}
+
#endif /* ! GRUB_DISK_HEADER */
diff --git a/include/grub/file.h b/include/grub/file.h
index fde58f0fa..fcfd32ce2 100644
--- a/include/grub/file.h
+++ b/include/grub/file.h
@@ -185,6 +185,7 @@ extern grub_disk_read_hook_t EXPORT_VAR(grub_file_progress_hook);
/* Filters with lower ID are executed first. */
typedef enum grub_file_filter_id
{
+ GRUB_FILE_FILTER_NOCAT,
GRUB_FILE_FILTER_VERIFY,
GRUB_FILE_FILTER_GZIO,
GRUB_FILE_FILTER_XZIO,
--
2.42.1

View File

@ -0,0 +1,40 @@
From e27acddebd30175587155613042abffd2e9a5de8 Mon Sep 17 00:00:00 2001
From: Mark Salter <msalter@redhat.com>
Date: Mon, 17 Apr 2017 08:44:29 -0400
Subject: [PATCH 2/9] arm64: make sure fdt has #address-cells and #size-cells
properties
Recent upstream changes to kexec-tools relies on #address-cells
and #size-cells properties in the FDT. If grub2 needs to create
a chosen node, it is likely because firmware did not provide one.
In that case, set #address-cells and #size-cells properties to
make sure they exist.
---
grub-core/loader/arm64/efi/linux.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
--- a/grub-core/loader/arm64/efi/linux.c
+++ b/grub-core/loader/arm64/efi/linux.c
@@ -99,7 +99,21 @@
node = grub_fdt_find_subnode (fdt, 0, "chosen");
if (node < 0)
- node = grub_fdt_add_subnode (fdt, 0, "chosen");
+ {
+ /*
+ * If we have to create a chosen node, Make sure we
+ * have #address-cells and #size-cells properties.
+ */
+ retval = grub_fdt_set_prop32(fdt, 0, "#address-cells", 2);
+ if (retval)
+ goto failure;
+
+ retval = grub_fdt_set_prop32(fdt, 0, "#size-cells", 2);
+ if (retval)
+ goto failure;
+
+ node = grub_fdt_add_subnode (fdt, 0, "chosen");
+ }
if (node < 1)
goto failure;

View File

@ -0,0 +1,47 @@
From 42cb0ebbffd660608612f9e32150a6596c6933c4 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Mon, 17 Aug 2020 17:25:56 +0800
Subject: [PATCH 2/2] cmdline: Provide cmdline functions as module
The command line processing is needed by many loader modules, hence we should
make it a sharable one rather than belonging to linux loader. This can cut the
dependency to linux module among multiple loaders like multiboot linuxefi and
so on to make custom boot image much more flexible to compose.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/Makefile.core.def | 6 +++++-
grub-core/lib/cmdline.c | 3 +++
2 files changed, 8 insertions(+), 1 deletion(-)
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1860,7 +1860,6 @@
x86_64_efi = loader/efi/linux.c;
emu = loader/emu/linux.c;
common = loader/linux.c;
- common = lib/cmdline.c;
};
module = {
@@ -2611,3 +2610,8 @@
efi = commands/bli.c;
enable = efi;
};
+
+module = {
+ name = cmdline;
+ common = lib/cmdline.c;
+};
--- a/grub-core/lib/cmdline.c
+++ b/grub-core/lib/cmdline.c
@@ -19,6 +19,9 @@
#include <grub/lib/cmdline.h>
#include <grub/misc.h>
+#include <grub/dl.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
static unsigned int check_arg (char *c, int *has_space)
{

View File

@ -0,0 +1,43 @@
From e62b26f9765e309691e014f322d4b02b220956a1 Mon Sep 17 00:00:00 2001
From: Patrick Colp <patrick.colp@oracle.com>
Date: Sun, 30 Jul 2023 12:58:18 -0700
Subject: [PATCH 2/4] cryptodisk: Fallback to passphrase
If a protector is specified, but it fails to unlock the disk, fall back
to asking for the passphrase. However, an error was set indicating that
the protector(s) failed. Later code (e.g., LUKS code) fails as
`grub_errno` is now set. Print the existing errors out first, before
proceeding with the passphrase.
Signed-off-by: Patrick Colp <patrick.colp@oracle.com>
Signed-off-by: Gary Lin <glin@suse.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
---
grub-core/disk/cryptodisk.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index af4104178..f9842f776 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -1193,11 +1193,16 @@ grub_cryptodisk_scan_device_real (const char *name,
source->name, source->partition != NULL ? "," : "",
part != NULL ? part : N_("UNKNOWN"), dev->uuid);
grub_free (part);
- goto error;
}
if (!cargs->key_len)
{
+ if (grub_errno)
+ {
+ grub_print_error ();
+ grub_errno = GRUB_ERR_NONE;
+ }
+
/* Get the passphrase from the user, if no key data. */
askpass = 1;
part = grub_partition_get_name (source->partition);
--
2.35.3

View File

@ -0,0 +1,88 @@
From 2271da7522d8406c528d2a9079d810e140f8041a Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 3 Feb 2023 19:40:31 +0800
Subject: [PATCH 2/2] discard cached key before entering grub shell and editor
mode
The cached key is cleared in case of anyone poking around it by means of
the interactive shell offerings.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/commands/crypttab.c | 16 ++++++++++++++++
grub-core/normal/main.c | 2 ++
grub-core/normal/menu_entry.c | 3 +++
include/grub/crypttab.h | 2 ++
4 files changed, 23 insertions(+)
--- a/grub-core/commands/crypttab.c
+++ b/grub-core/commands/crypttab.c
@@ -53,6 +53,22 @@
return GRUB_ERR_NONE;
}
+void
+grub_initrd_discard_key (void)
+{
+ struct grub_key_publisher *cur, *nxt;
+
+ FOR_LIST_ELEMENTS_SAFE (cur, nxt, kpuber)
+ {
+ grub_list_remove (GRUB_AS_LIST (cur));
+ grub_memset (cur->key, 0, cur->key_len);
+ grub_free (cur->name);
+ grub_free (cur->path);
+ grub_free (cur->key);
+ grub_free (cur);
+ }
+}
+
static grub_err_t
grub_cmd_crypttab_entry (grub_command_t cmd __attribute__ ((unused)),
int argc, char **argv)
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -37,6 +37,7 @@
#ifdef GRUB_MACHINE_IEEE1275
#include <grub/ieee1275/ieee1275.h>
#endif
+#include <grub/crypttab.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -478,6 +479,7 @@
return;
}
+ grub_initrd_discard_key ();
grub_normal_reader_init (nested);
while (1)
--- a/grub-core/normal/menu_entry.c
+++ b/grub-core/normal/menu_entry.c
@@ -28,6 +28,7 @@
#include <grub/i18n.h>
#include <grub/charset.h>
#include <grub/safemath.h>
+#include <grub/crypttab.h>
enum update_mode
{
@@ -1262,6 +1263,8 @@
return;
}
+ grub_initrd_discard_key();
+
screen = make_screen (entry);
if (! screen)
return;
--- a/include/grub/crypttab.h
+++ b/include/grub/crypttab.h
@@ -19,4 +19,6 @@
grub_err_t
grub_initrd_publish_key (const char *uuid, const char *key, grub_size_t key_len, const char *path);
+void
+grub_initrd_discard_key (void);
#endif /* ! GRUB_CRYPTTAB_HEADER */

View File

@ -0,0 +1,373 @@
From 9e61624db77e5073961126457f599bc70e877fd1 Mon Sep 17 00:00:00 2001
From: Diego Domingos <diegodo@br.ibm.com>
Date: Tue, 15 Mar 2022 15:59:41 -0400
Subject: [PATCH 2/4] ieee1275/ofpath: enable NVMeoF logical device translation
This patch add code to enable the translation of logical devices to the of NVMeoFC paths.
---
grub-core/osdep/linux/ofpath.c | 260 +++++++++++++++++++++++++++++++--
include/grub/util/ofpath.h | 29 ++++
2 files changed, 280 insertions(+), 9 deletions(-)
diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c
index 89beceef4..212782d3f 100644
--- a/grub-core/osdep/linux/ofpath.c
+++ b/grub-core/osdep/linux/ofpath.c
@@ -137,7 +137,7 @@ trim_newline (char *path)
*end-- = '\0';
}
-#define MAX_DISK_CAT 64
+#define MAX_DISK_CAT 512
static char *
find_obppath (const char *sysfs_path_orig)
@@ -313,6 +313,69 @@ get_basename(char *p)
return ret;
}
+
+void
+add_filename_to_pile(char *filename, struct ofpath_files_list_root* root){
+ struct ofpath_files_list_node* file;
+
+ file = malloc(sizeof(struct ofpath_files_list_node));
+
+ file->filename = filename;
+
+ if(root->first == NULL){
+ root->items = 1;
+ root->first = file;
+ file->next = NULL;
+ } else {
+ root->items++;
+ file->next = root->first;
+ root->first = file;
+ }
+}
+
+
+void
+find_file(char* filename, char* directory, struct ofpath_files_list_root* root, int max_depth, int depth){
+ struct dirent *ep;
+ struct stat statbuf;
+ DIR *dp;
+
+ if(depth > max_depth){
+ return;
+ }
+
+ if((dp = opendir(directory)) == NULL){
+
+ return;
+ }
+
+ while((ep = readdir(dp)) != NULL){
+
+ char* full_path = malloc(1024*sizeof(char));
+ snprintf(full_path,1024,"%s/%s",directory,ep->d_name);
+
+ lstat(full_path,&statbuf);
+
+ if(S_ISLNK(statbuf.st_mode)){
+
+ continue;
+ }
+
+ if(!strcmp(ep->d_name,".") || !strcmp(ep->d_name,"..")){
+ continue;
+ }
+
+ if(!strcmp(ep->d_name,filename)){
+ add_filename_to_pile(full_path, root);
+ }
+
+ find_file(filename, full_path, root, max_depth, depth+1);
+
+ }
+ closedir(dp);
+}
+
+
static char *
of_path_of_vdisk(const char *sys_devname __attribute__((unused)),
const char *device,
@@ -351,7 +414,142 @@ of_path_of_ide(const char *sys_devname __attribute__((unused)), const char *devi
return ret;
}
-#ifdef __sparc__
+char*
+of_find_fc_host(char* host_wwpn){
+
+ FILE* fp;
+ char *buf;
+ char portname_filename[sizeof("port_name")] = "port_name";
+ char devices_path[sizeof("/sys/devices")] = "/sys/devices";
+
+ struct ofpath_files_list_root* portnames_file_list;
+
+ portnames_file_list=malloc(sizeof(portnames_file_list));
+ portnames_file_list->items=0;
+ portnames_file_list->first=NULL;
+
+ find_file(portname_filename, devices_path, portnames_file_list, 10, 0);
+
+ struct ofpath_files_list_node* node = portnames_file_list->first;
+ while(node != NULL){
+ fp = fopen(node->filename,"r");
+ buf = malloc(sizeof(char)*512);
+ fscanf(fp, "%s", buf);
+ fclose(fp);
+ if((strcmp(buf,host_wwpn) == 0) && grub_strstr(node->filename, "fc_host")){
+ return node->filename;
+ }
+ node = node->next;
+ }
+
+ return NULL;
+}
+
+void
+of_path_get_nvmeof_adapter_info(char* sysfs_path,
+ struct ofpath_nvmeof_info* nvmeof_info){
+
+ FILE *fp;
+ char *buf, *buf2, *buf3;
+
+ nvmeof_info->host_wwpn = malloc(sizeof(char)*256);
+ nvmeof_info->target_wwpn = malloc(sizeof(char)*256);
+ nvmeof_info->nqn = malloc(sizeof(char)*256);
+
+ buf = malloc(sizeof(char)*512);
+ snprintf(buf,512,"%s/subsysnqn",sysfs_path);
+ fp = fopen(buf,"r");
+ fscanf(fp, "%s", nvmeof_info->nqn);
+ fclose(fp);
+
+ snprintf(buf,512,"%s/cntlid",sysfs_path);
+ fp = fopen(buf,"r");
+ fscanf(fp, "%u", &(nvmeof_info->cntlid));
+ fclose(fp);
+
+ //snprintf(buf,512,"%s/nsid",sysfs_path);
+ //fp = fopen(buf,"r");
+ //fscanf(fp, "%u", &(nvmeof_info->nsid));
+ //fclose(fp);
+
+ snprintf(buf,512,"%s/address",sysfs_path);
+ fp = fopen(buf,"r");
+ buf2 = malloc(sizeof(char)*512);
+ fscanf(fp, "%s", buf2);
+ fclose(fp);
+
+ nvmeof_info->host_wwpn = strrchr(buf2,'-')+1;
+
+ buf3=strchr(buf2,'-')+1;
+ buf3=strchr(buf3,'-')+1;
+ nvmeof_info->target_wwpn = buf3;
+ buf3 = strchr(nvmeof_info->target_wwpn,',');
+ *buf3 = '\0';
+
+
+ free(buf);
+
+ return;
+}
+
+#define MAX_NVME_NSID_DIGITS 6
+
+static char *
+of_path_get_nvme_controller_name_node(const char* devname)
+{
+ char *controller_node, *end;
+
+ controller_node = strdup(devname);
+
+ end = grub_strchr(controller_node+1, 'n');
+
+ if(end != NULL){
+ *end = '\0';
+ }
+
+ return controller_node;
+}
+
+unsigned int
+of_path_get_nvme_nsid(const char* devname)
+{
+ unsigned int nsid;
+ char *sysfs_path, *buf;
+ FILE *fp;
+
+ buf=malloc(sizeof(char)*512);
+
+ sysfs_path = block_device_get_sysfs_path_and_link (devname);
+
+ snprintf(buf,512,"%s/%s/nsid",sysfs_path,devname);
+ fp = fopen(buf,"r");
+ fscanf(fp, "%u", &(nsid));
+ fclose(fp);
+
+ free(sysfs_path);
+ free(buf);
+
+ return nsid;
+
+}
+
+static char *
+nvme_get_syspath(const char *nvmedev)
+{
+ char *sysfs_path, *controller_node;
+ sysfs_path = block_device_get_sysfs_path_and_link (nvmedev);
+
+ if(strstr(sysfs_path,"nvme-subsystem")){
+ controller_node = of_path_get_nvme_controller_name_node(nvmedev);
+ strcat(sysfs_path,"/");
+ strcat(sysfs_path,controller_node);
+ sysfs_path = xrealpath(sysfs_path);
+ }
+
+ return sysfs_path;
+}
+
+
static char *
of_path_of_nvme(const char *sys_devname __attribute__((unused)),
const char *device,
@@ -360,6 +558,7 @@ of_path_of_nvme(const char *sys_devname __attribute__((unused)),
{
char *sysfs_path, *of_path, disk[MAX_DISK_CAT];
const char *digit_string, *part_end;
+ int chars_written;
digit_string = trailing_digits (device);
part_end = devicenode + strlen (devicenode) - 1;
@@ -379,15 +578,61 @@ of_path_of_nvme(const char *sys_devname __attribute__((unused)),
/* Remove the p. */
*end = '\0';
sscanf (digit_string, "%d", &part);
- snprintf (disk, sizeof (disk), "/disk@1:%c", 'a' + (part - 1));
- sysfs_path = block_device_get_sysfs_path_and_link (nvmedev);
+
+ sysfs_path = nvme_get_syspath(nvmedev);
+
+ /* If is a NVMeoF */
+ if(strstr(sysfs_path,"nvme-fabrics")){
+ struct ofpath_nvmeof_info* nvmeof_info;
+ nvmeof_info = malloc(sizeof(nvmeof_info));
+
+ of_path_get_nvmeof_adapter_info(sysfs_path, nvmeof_info);
+
+ sysfs_path = of_find_fc_host(nvmeof_info->host_wwpn);
+
+ chars_written = snprintf(disk,sizeof(disk),"/nvme-of/controller@%s,%x:nqn=%s",
+ nvmeof_info->target_wwpn,
+ 0xffff,
+ nvmeof_info->nqn);
+
+ unsigned int nsid = of_path_get_nvme_nsid(nvmedev);
+
+ if(nsid){
+ snprintf(disk+chars_written,sizeof(disk) - chars_written,
+ "/namespace@%x:%d",nsid, part);
+ }
+
+ } else {
+ snprintf (disk, sizeof (disk), "/disk@1:%c", 'a' + (part - 1));
+ }
free (nvmedev);
}
else
{
/* We do not have the parition. */
- snprintf (disk, sizeof (disk), "/disk@1");
- sysfs_path = block_device_get_sysfs_path_and_link (device);
+ sysfs_path = nvme_get_syspath (device);
+ if(strstr(sysfs_path,"nvme-fabrics")){
+ struct ofpath_nvmeof_info* nvmeof_info;
+ nvmeof_info = malloc(sizeof(nvmeof_info));
+
+ of_path_get_nvmeof_adapter_info(sysfs_path, nvmeof_info);
+
+ sysfs_path = of_find_fc_host(nvmeof_info->host_wwpn);
+
+ chars_written = snprintf(disk,sizeof(disk),"/nvme-of/controller@%s,%x:nqn=%s",
+ nvmeof_info->target_wwpn,
+ 0xffff,
+ nvmeof_info->nqn);
+
+ unsigned int nsid = of_path_get_nvme_nsid(device);
+ if(nsid){
+ snprintf(disk+chars_written,sizeof(disk) - chars_written,
+ "/namespace@%x",nsid);
+ }
+ } else {
+ snprintf (disk, sizeof (disk), "/disk@1");
+ }
+
}
of_path = find_obppath (sysfs_path);
@@ -398,7 +643,6 @@ of_path_of_nvme(const char *sys_devname __attribute__((unused)),
free (sysfs_path);
return of_path;
}
-#endif
static void
of_fc_port_name(const char *path, const char *subpath, char *port_name)
@@ -840,11 +1084,9 @@ grub_util_devname_to_ofpath (const char *sys_devname)
/* All the models I've seen have a devalias "floppy".
New models have no floppy at all. */
ofpath = xstrdup ("floppy");
-#ifdef __sparc__
else if (device[0] == 'n' && device[1] == 'v' && device[2] == 'm'
&& device[3] == 'e')
ofpath = of_path_of_nvme (name_buf, device, devnode, devicenode);
-#endif
else
{
grub_util_warn (_("unknown device type %s"), device);
diff --git a/include/grub/util/ofpath.h b/include/grub/util/ofpath.h
index b43c523cb..a0ec30620 100644
--- a/include/grub/util/ofpath.h
+++ b/include/grub/util/ofpath.h
@@ -3,4 +3,33 @@
char *grub_util_devname_to_ofpath (const char *devname);
+struct ofpath_files_list_node {
+ char* filename;
+ struct ofpath_files_list_node* next;
+};
+
+struct ofpath_files_list_root {
+ int items;
+ struct ofpath_files_list_node* first;
+};
+
+struct ofpath_nvmeof_info {
+ char* host_wwpn;
+ char* target_wwpn;
+ char* nqn;
+ int cntlid;
+ int nsid;
+};
+
+void of_path_get_nvmeof_adapter_info(char* sysfs_path,
+ struct ofpath_nvmeof_info* nvmeof_info);
+
+unsigned int of_path_get_nvme_nsid(const char* devname);
+
+void add_filename_to_pile(char *filename, struct ofpath_files_list_root* root);
+
+void find_file(char* filename, char* directory, struct ofpath_files_list_root* root, int max_depth, int depth);
+
+char* of_find_fc_host(char* host_wwpn);
+
#endif /* ! GRUB_OFPATH_MACHINE_UTIL_HEADER */
--
2.35.3

View File

@ -0,0 +1,107 @@
From 8b31ebfa42eb5af0633191d26fcdcea8c539e521 Mon Sep 17 00:00:00 2001
From: Diego Domingos <diegodo@br.ibm.com>
Date: Wed, 24 Jun 2020 08:22:50 -0400
Subject: [PATCH 2/2] ieee1275/powerpc: enables device mapper discovery
this patch enables the device mapper discovery on ofpath.c. Currently,
when we are dealing with a device like /dev/dm-* the ofpath returns null
since there is no function implemented to handle this case.
This patch implements a function that will look into /sys/block/dm-*
devices and search recursively inside slaves directory to find the root
disk.
v2:
Fix gcc-12 error: pointer 'device_path' may be used after 'free'
[-Werror=use-after-free]
---
grub-core/osdep/linux/ofpath.c | 64 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 63 insertions(+), 1 deletion(-)
--- a/grub-core/osdep/linux/ofpath.c
+++ b/grub-core/osdep/linux/ofpath.c
@@ -37,6 +37,7 @@
#include <fcntl.h>
#include <errno.h>
#include <ctype.h>
+#include <dirent.h>
#ifdef __sparc__
typedef enum
@@ -754,13 +755,74 @@
return new;
}
+static char *
+get_slave_from_dm(const char * device){
+ char *curr_device, *tmp;
+ char *directory;
+ char *ret = NULL;
+
+ directory = grub_strdup (device);
+ tmp = get_basename(directory);
+ curr_device = grub_strdup (tmp);
+ *tmp = '\0';
+
+ /* Recursively check for slaves devices so we can find the root device */
+ while ((curr_device[0] == 'd') && (curr_device[1] == 'm') && (curr_device[2] == '-')){
+ DIR *dp;
+ struct dirent *ep;
+ char* device_path;
+
+ device_path = grub_xasprintf ("/sys/block/%s/slaves", curr_device);
+ dp = opendir(device_path);
+ free(device_path);
+
+ if (dp != NULL)
+ {
+ ep = readdir (dp);
+ while (ep != NULL){
+
+ /* avoid some system directories */
+ if (!strcmp(ep->d_name,"."))
+ goto next_dir;
+ if (!strcmp(ep->d_name,".."))
+ goto next_dir;
+
+ free (curr_device);
+ free (ret);
+ curr_device = grub_strdup (ep->d_name);
+ ret = grub_xasprintf ("%s%s", directory, curr_device);
+ break;
+
+ next_dir:
+ ep = readdir (dp);
+ continue;
+ }
+ closedir (dp);
+ }
+ else
+ grub_util_warn (_("cannot open directory `/sys/block/%s/slaves'"), curr_device);
+ }
+
+ free (directory);
+ free (curr_device);
+
+ return ret;
+}
+
char *
grub_util_devname_to_ofpath (const char *sys_devname)
{
- char *name_buf, *device, *devnode, *devicenode, *ofpath;
+ char *name_buf, *device, *devnode, *devicenode, *ofpath, *realname;
name_buf = xrealpath (sys_devname);
+ realname = get_slave_from_dm (name_buf);
+ if (realname)
+ {
+ free (name_buf);
+ name_buf = realname;
+ }
+
device = get_basename (name_buf);
devnode = strip_trailing_digits (name_buf);
devicenode = strip_trailing_digits (device);

View File

@ -0,0 +1,164 @@
From 8959b9d97b00f791ffe02b5e3ec3fdf6bff25838 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Tue, 12 Dec 2023 15:34:18 +0800
Subject: [PATCH 2/2] ofdisk: add early_log support
The command ofdisk_early_msg can be used to review debug message logged
before output console is initialized.
For eg:
grub> ofdisk_early_msg
/vdevice/v-scsi@71000002/disk@8000000000000000 is canonical
/vdevice/v-scsi@71000002/disk@8000000000000000
/vdevice/v-scsi@71000002 is parent of
/vdevice/v-scsi@71000002/disk@80000000
00000000
the boot device type vscsi is used for root device discovery, others excluded
We can use it in conjunction with the $ofdisk_boot_type variable to get
better understanding the boot device information.
grub> echo $ofdisk_boot_type
boot: /vdevice/v-scsi@71000002 type: vscsi is_nvmeof? 0
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/disk/ieee1275/ofdisk.c | 75 +++++++++++++++++++++++++++++---
1 file changed, 70 insertions(+), 5 deletions(-)
--- a/grub-core/disk/ieee1275/ofdisk.c
+++ b/grub-core/disk/ieee1275/ofdisk.c
@@ -25,6 +25,7 @@
#include <grub/i18n.h>
#include <grub/time.h>
#include <grub/env.h>
+#include <grub/command.h>
#define RETRY_DEFAULT_TIMEOUT 15
@@ -60,6 +61,9 @@
#define OFDISK_HASH_SZ 8
static struct ofdisk_hash_ent *ofdisk_hash[OFDISK_HASH_SZ];
+static void early_log (const char *fmt, ...);
+static void print_early_log (void);
+
static int
ofdisk_hash_fn (const char *devpath)
{
@@ -1132,10 +1136,10 @@
return NULL;
}
else
- grub_dprintf ("ofdisk", "%s is canonical %s\n", bootpath, canon);
+ early_log ("%s is canonical %s\n", bootpath, canon);
parent = get_parent_devname (canon, is_nvmeof);
- grub_dprintf ("ofdisk", "%s is parent of %s\n", parent, canon);
+ early_log ("%s is parent of %s\n", parent, canon);
grub_free (canon);
return parent;
@@ -1179,9 +1183,9 @@
boot_parent = get_boot_device_parent (bootpath, &is_boot_nvmeof);
boot_type = grub_ieee1275_get_device_type (boot_parent);
if (boot_type)
- grub_dprintf ("ofdisk", "the boot device type %s is used for root device discovery, others excluded\n", boot_type);
+ early_log ("the boot device type %s is used for root device discovery, others excluded\n", boot_type);
else
- grub_dprintf ("ofdisk", "unknown boot device type, will use all devices to discover root and may be slow\n");
+ early_log ("unknown boot device type, will use all devices to discover root and may be slow\n");
}
grub_free (type);
grub_free (bootpath);
@@ -1205,7 +1209,7 @@
static char *ret;
if (!ret)
- ret = grub_xasprintf("boot: %s type: %s is_nvmeof: %d",
+ ret = grub_xasprintf("boot: %s type: %s is_nvmeof? %d",
boot_parent,
boot_type ? : "unknown",
is_boot_nvmeof);
@@ -1221,6 +1225,17 @@
return NULL;
}
+static grub_err_t
+grub_cmd_early_msg (struct grub_command *cmd __attribute__ ((unused)),
+ int argc __attribute__ ((unused)),
+ char *argv[] __attribute__ ((unused)))
+{
+ print_early_log ();
+ return 0;
+}
+
+static grub_command_t cmd_early_msg;
+
void
grub_ofdisk_init (void)
{
@@ -1230,6 +1245,9 @@
grub_register_variable_hook ("ofdisk_boot_type", grub_env_get_boot_type,
grub_env_set_boot_type );
+ cmd_early_msg =
+ grub_register_command ("ofdisk_early_msg", grub_cmd_early_msg,
+ 0, N_("Show early boot message in ofdisk."));
grub_disk_dev_register (&grub_ofdisk_dev);
}
@@ -1278,3 +1296,50 @@
return 0;
}
+
+struct ofdisk_early_msg
+{
+ struct ofdisk_early_msg *next;
+ char *msg;
+};
+
+static struct ofdisk_early_msg *early_msg_head;
+static struct ofdisk_early_msg **early_msg_last = &early_msg_head;
+
+static void
+early_log (const char *fmt, ...)
+{
+ struct ofdisk_early_msg *n;
+ va_list args;
+
+ grub_error_push ();
+ n = grub_malloc (sizeof (*n));
+ if (!n)
+ {
+ grub_errno = 0;
+ grub_error_pop ();
+ return;
+ }
+ n->next = 0;
+
+ va_start (args, fmt);
+ n->msg = grub_xvasprintf (fmt, args);
+ va_end (args);
+
+ *early_msg_last = n;
+ early_msg_last = &n->next;
+
+ grub_errno = 0;
+ grub_error_pop ();
+}
+
+static void
+print_early_log (void)
+{
+ struct ofdisk_early_msg *cur;
+
+ if (!early_msg_head)
+ grub_printf ("no early log is available\n");
+ for (cur = early_msg_head; cur; cur = cur->next)
+ grub_printf ("%s\n", cur->msg);
+}

View File

@ -0,0 +1,205 @@
From 990902e28c390217d25ea474e5ef163d79eadc7f Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 31 Mar 2023 15:19:58 +0800
Subject: [PATCH 2/2] prep_loadenv: Fix regex for Open Firmware device
specifier with encoded commas
The Open Firmware device specifier allows for comma-separated properties
of a component, but this conflicts with the way that grub separates
device and partition in its device specifier. To address this, grub
encodes commas in Open Firmware device strings with a leading backslash
as an established convention.
However, the regular expression used to extract the boot device
substring from the $cmdpath environment variable did not properly retain
commas with leading backslashes as part of the device. This could cause
the comma to be incorrectly interpreted as a partition delimiter and
result in a broken name for the boot disk.
To fix this issue, we have updated the regular expression to properly
handle the encoded comma in the Open Firmware device specifier, ensuring
that the correct boot device is identified and used.
v2:
Fix the issue of freeing an uninitialized pointer in early_prep_loadenv.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/commands/prep_loadenv.c | 108 ++++++++++++++++++++++--------
1 file changed, 79 insertions(+), 29 deletions(-)
--- a/grub-core/commands/prep_loadenv.c
+++ b/grub-core/commands/prep_loadenv.c
@@ -15,7 +15,7 @@
GRUB_MOD_LICENSE ("GPLv3+");
static char *
-match_substr (regmatch_t *match, const char *str)
+match_substr (const regmatch_t *match, const char *str)
{
if (match->rm_so != -1)
{
@@ -185,24 +185,18 @@
return err;
}
-static grub_err_t
-boot_disk_prep_partname (char **name)
+static regmatch_t *
+regex_match_str (const char *pattern, const char *str, grub_size_t *nmatch)
{
regex_t regex;
int ret;
grub_size_t s;
char *comperr;
- const char *cmdpath;
regmatch_t *matches = NULL;
grub_err_t err = GRUB_ERR_NONE;
- *name = NULL;
-
- cmdpath = grub_env_get ("cmdpath");
- if (!cmdpath)
- return GRUB_ERR_NONE;
-
- ret = regcomp (&regex, "\\(([^,]+)(,?.*)?\\)(.*)", REG_EXTENDED);
+ *nmatch = 0;
+ ret = regcomp (&regex, pattern, REG_EXTENDED);
if (ret)
goto fail;
@@ -210,22 +204,11 @@
if (! matches)
goto fail;
- ret = regexec (&regex, cmdpath, regex.re_nsub + 1, matches, 0);
- if (!ret)
+ ret = regexec (&regex, str, regex.re_nsub + 1, matches, 0);
+ if (ret == 0)
{
- char *devname = devname = match_substr (matches + 1, cmdpath);
- if (!devname)
- {
- err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "%s contains no disk name", cmdpath);
- goto out;
- }
-
- err = prep_partname (devname, name);
- out:
- grub_free (devname);
- regfree (&regex);
- grub_free (matches);
- return err;
+ *nmatch = regex.re_nsub + 1;
+ return matches;
}
fail:
@@ -235,13 +218,60 @@
if (!comperr)
{
regfree (&regex);
- return grub_errno;
+ return NULL;
}
regerror (ret, &regex, comperr, s);
err = grub_error (GRUB_ERR_TEST_FAILURE, "%s", comperr);
regfree (&regex);
grub_free (comperr);
- return err;
+ return NULL;
+}
+
+static grub_err_t
+boot_disk_prep_partname (const char *varname, char **name)
+{
+ const char *cmdpath;
+ regmatch_t *matches;
+ grub_size_t nmatch;
+ char *devname = NULL;
+
+ *name = NULL;
+
+ if (varname)
+ cmdpath = grub_env_get (varname);
+ else
+ cmdpath = grub_env_get ("cmdpath");
+ if (!cmdpath)
+ return GRUB_ERR_NONE;
+
+ matches = regex_match_str("\\((.*)\\)(.*)", cmdpath, &nmatch);
+ if (matches && nmatch >= 2)
+ devname = match_substr (matches + 1, cmdpath);
+ if (devname == NULL)
+ goto quit;
+ grub_free (matches);
+
+ matches = regex_match_str ("(.*[^\\])(,.*)", devname, &nmatch);
+ if (matches && nmatch >= 2)
+ {
+ char *n = match_substr (matches + 1, devname);
+ grub_free (devname);
+ devname = n;
+ }
+ else
+ grub_errno = GRUB_ERR_NONE;
+ if (devname)
+ {
+ grub_printf ("search prep from disk `%s'\n", devname);
+ prep_partname (devname, name);
+ }
+
+ quit:
+ grub_free (devname);
+ grub_free (matches);
+ if (grub_errno)
+ grub_print_error ();
+ return GRUB_ERR_NONE;
}
static grub_err_t
@@ -274,13 +304,31 @@
return GRUB_ERR_NONE;
}
+static grub_err_t
+grub_cmd_prep_partname (grub_command_t cmd __attribute__ ((unused)),
+ int argc,
+ char **argv)
+{
+ char *prep = NULL;
+ const char *varname = NULL;
+
+ if (argc > 0)
+ varname = argv[0];
+
+ boot_disk_prep_partname(varname, &prep);
+ if (prep)
+ grub_printf ("prep: %s\n", prep);
+
+ return GRUB_ERR_NONE;
+}
+
static void
early_prep_loadenv (void)
{
grub_err_t err;
- char *prep;
+ char *prep = NULL;
- err = boot_disk_prep_partname (&prep);
+ err = boot_disk_prep_partname (NULL, &prep);
if (err == GRUB_ERR_NONE && prep)
err = prep_read_envblk (prep);
if (err == GRUB_ERR_BAD_FILE_TYPE || err == GRUB_ERR_FILE_NOT_FOUND)
@@ -296,6 +344,10 @@
{
early_env_hook = early_prep_loadenv;
cmd_prep_load =
+ grub_register_command("prep_partname", grub_cmd_prep_partname,
+ "VARNAME",
+ N_("Get partition name of PReP."));
+ cmd_prep_load =
grub_register_command("prep_load_env", grub_cmd_prep_loadenv,
"DEVICE",
N_("Load variables from environment block file."));

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,385 @@
From 90153f1c9631498723450d84e014e25865fecc1b Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 15 Mar 2018 14:12:40 -0400
Subject: [PATCH 3/9] Add grub2-switch-to-blscfg
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
[jhlavac: Use ${etcdefaultgrub} instead of /etc/default/grub]
Signed-off-by: Jan Hlavac <jhlavac@redhat.com>
[rharwood: skip on ostree installations, migrate man to h2m]
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
---
Makefile.util.def | 7 +
docs/man/grub-switch-to-blscfg.h2m | 2 +
util/grub-switch-to-blscfg.in | 317 +++++++++++++++++++++++++++++
util/grub.d/10_linux.in | 2 +-
4 files changed, 327 insertions(+), 1 deletion(-)
create mode 100644 docs/man/grub-switch-to-blscfg.h2m
create mode 100644 util/grub-switch-to-blscfg.in
diff --git a/Makefile.util.def b/Makefile.util.def
index 6bb30c165..ffedea24a 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -1460,6 +1460,13 @@ program = {
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
};
+script = {
+ name = grub-switch-to-blscfg;
+ common = util/grub-switch-to-blscfg.in;
+ mansection = 8;
+ installdir = sbin;
+};
+
program = {
name = grub-glue-efi;
mansection = 1;
diff --git a/docs/man/grub-switch-to-blscfg.h2m b/docs/man/grub-switch-to-blscfg.h2m
new file mode 100644
index 000000000..fa341426a
--- /dev/null
+++ b/docs/man/grub-switch-to-blscfg.h2m
@@ -0,0 +1,2 @@
+[NAME]
+grub-switch-to-blscfg \- switch to using BLS config files
diff --git a/util/grub-switch-to-blscfg.in b/util/grub-switch-to-blscfg.in
new file mode 100644
index 000000000..a851424be
--- /dev/null
+++ b/util/grub-switch-to-blscfg.in
@@ -0,0 +1,317 @@
+#! /bin/sh
+#
+# Set a default boot entry for GRUB.
+# Copyright (C) 2004,2009 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/>.
+
+#set -eu
+
+# Initialize some variables.
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+sbindir=@sbindir@
+bindir=@bindir@
+sysconfdir="@sysconfdir@"
+PACKAGE_NAME=@PACKAGE_NAME@
+PACKAGE_VERSION=@PACKAGE_VERSION@
+datarootdir="@datarootdir@"
+datadir="@datadir@"
+if [ ! -v pkgdatadir ]; then
+ pkgdatadir="${datadir}/@PACKAGE@"
+fi
+
+self=`basename $0`
+
+grub_get_kernel_settings="${sbindir}/@grub_get_kernel_settings@"
+grub_editenv=${bindir}/@grub_editenv@
+etcdefaultgrub=/etc/default/grub
+
+eval "$("${grub_get_kernel_settings}")" || true
+
+EFIDIR=$(grep ^ID= /etc/os-release | sed -e 's/^ID=//' -e 's/rhel/redhat/' -e 's/\"//g')
+if [ -d /sys/firmware/efi/efivars/ ]; then
+ startlink=/etc/grub2-efi.cfg
+ grubdir=`echo "/@bootdirname@/efi/EFI/${EFIDIR}/" | sed 's,//*,/,g'`
+else
+ startlink=/etc/grub2.cfg
+ grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'`
+fi
+
+blsdir=`echo "/@bootdirname@/loader/entries" | sed 's,//*,/,g'`
+
+backupsuffix=.bak
+
+arch="$(uname -m)"
+
+export TEXTDOMAIN=@PACKAGE@
+export TEXTDOMAINDIR="@localedir@"
+
+. "${pkgdatadir}/grub-mkconfig_lib"
+
+# Usage: usage
+# Print the usage.
+usage () {
+ gettext_printf "Usage: %s\n" "$self"
+ gettext "Switch to BLS config files.\n"; echo
+ echo
+ print_option_help "-h, --help" "$(gettext "print this message and exit")"
+ print_option_help "-V, --version" "$(gettext "print the version information and exit")"
+ echo
+ print_option_help "--backup-suffix=$(gettext "SUFFIX")" "$backupsuffix"
+ print_option_help "--bls-directory=$(gettext "DIR")" "$blsdir"
+ print_option_help "--config-file=$(gettext "FILE")" "$startlink"
+ print_option_help "--grub-defaults=$(gettext "FILE")" "$etcdefaultgrub"
+ print_option_help "--grub-directory=$(gettext "DIR")" "$grubdir"
+ # echo
+ # gettext "Report bugs to <bug-grub@gnu.org>."; echo
+}
+
+argument () {
+ opt=$1
+ shift
+
+ if test $# -eq 0; then
+ gettext_printf "%s: option requires an argument -- \`%s'\n" "$self" "$opt" 1>&2
+ exit 1
+ fi
+ echo $1
+}
+
+# Check the arguments.
+while test $# -gt 0
+do
+ option=$1
+ shift
+
+ case "$option" in
+ -h | --help)
+ usage
+ exit 0 ;;
+ -V | --version)
+ echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}"
+ exit 0 ;;
+
+ --backup-suffix)
+ backupsuffix=`argument $option "$@"`
+ shift
+ ;;
+ --backup-suffix=*)
+ backupsuffix=`echo "$option" | sed 's/--backup-suffix=//'`
+ ;;
+
+ --bls-directory)
+ blsdir=`argument $option "$@"`
+ shift
+ ;;
+ --bls-directory=*)
+ blsdir=`echo "$option" | sed 's/--bls-directory=//'`
+ ;;
+
+ --config-file)
+ startlink=`argument $option "$@"`
+ shift
+ ;;
+ --config-file=*)
+ startlink=`echo "$option" | sed 's/--config-file=//'`
+ ;;
+
+ --grub-defaults)
+ etcdefaultgrub=`argument $option "$@"`
+ shift
+ ;;
+ --grub-defaults=*)
+ etcdefaultgrub=`echo "$option" | sed 's/--grub-defaults=//'`
+ ;;
+
+ --grub-directory)
+ grubdir=`argument $option "$@"`
+ shift
+ ;;
+ --grub-directory=*)
+ grubdir=`echo "$option" | sed 's/--grub-directory=//'`
+ ;;
+
+ *)
+ gettext_printf "Unrecognized option \`%s'\n" "$option" 1>&2
+ usage
+ exit 1
+ ;;
+ esac
+done
+
+find_grub_cfg() {
+ local candidate=""
+ while [ -e "${candidate}" -o $# -gt 0 ]
+ do
+ if [ ! -e "${candidate}" ] ; then
+ candidate="$1"
+ shift
+ fi
+
+ if [ -L "${candidate}" ]; then
+ candidate="$(realpath "${candidate}")"
+ fi
+
+ if [ -f "${candidate}" ]; then
+ export GRUB_CONFIG_FILE="${candidate}"
+ return 0
+ fi
+ done
+ return 1
+}
+
+if ! find_grub_cfg ${startlink} ${grubdir}/grub.cfg ; then
+ gettext_printf "Couldn't find config file\n" 1>&2
+ exit 1
+fi
+
+if [ ! -d "${blsdir}" ]; then
+ install -m 700 -d "${blsdir}"
+fi
+
+if [ -f /etc/machine-id ]; then
+ MACHINE_ID=$(cat /etc/machine-id)
+else
+ MACHINE_ID=$(dmesg | sha256sum)
+fi
+
+mkbls() {
+ local kernelver=$1 && shift
+ local datetime=$1 && shift
+ local kernelopts=$1 && shift
+
+ local debugname=""
+ local debugid=""
+ local flavor=""
+
+ if [ "$kernelver" == *\+* ] ; then
+ local flavor=-"${kernelver##*+}"
+ if [ "${flavor}" == "-debug" ]; then
+ local debugname=" with debugging"
+ local debugid="-debug"
+ fi
+ fi
+ (
+ source /etc/os-release
+
+ cat <<EOF
+title ${NAME} (${kernelver}) ${VERSION}${debugname}
+version ${kernelver}${debugid}
+linux /vmlinuz-${kernelver}
+initrd /initramfs-${kernelver}.img
+options ${kernelopts}
+grub_users \$grub_users
+grub_arg --unrestricted
+grub_class kernel${flavor}
+EOF
+ ) | cat
+}
+
+copy_bls() {
+ for kernelver in $(cd /lib/modules/ ; ls -1) "" ; do
+ bls_target="${blsdir}/${MACHINE_ID}-${kernelver}.conf"
+ linux="/vmlinuz-${kernelver}"
+ linux_path="/boot${linux}"
+ kernel_dir="/lib/modules/${kernelver}"
+
+ if [ ! -d "${kernel_dir}" ] ; then
+ continue
+ fi
+ if [ ! -f "${linux_path}" ]; then
+ continue
+ fi
+
+ linux_relpath="$("${grub_mkrelpath}" "${linux_path}")"
+ bootprefix="${linux_relpath%%"${linux}"}"
+ cmdline="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
+
+ mkbls "${kernelver}" \
+ "$(date -u +%Y%m%d%H%M%S -d "$(stat -c '%y' "${kernel_dir}")")" \
+ "${bootprefix}" "${cmdline}" >"${bls_target}"
+
+ if [ "x$GRUB_LINUX_MAKE_DEBUG" = "xtrue" ]; then
+ bls_debug="$(echo ${bls_target} | sed -e "s/${kernelver}/${kernelver}~debug/")"
+ cp -aT "${bls_target}" "${bls_debug}"
+ title="$(grep '^title[ \t]' "${bls_debug}" | sed -e 's/^title[ \t]*//')"
+ options="$(echo "${cmdline} ${GRUB_CMDLINE_LINUX_DEBUG}" | sed -e 's/\//\\\//g')"
+ sed -i -e "s/^title.*/title ${title}${GRUB_LINUX_DEBUG_TITLE_POSTFIX}/" "${bls_debug}"
+ sed -i -e "s/^options.*/options ${options}/" "${bls_debug}"
+ fi
+ done
+
+ if [ -f "/boot/vmlinuz-0-rescue-${MACHINE_ID}" ]; then
+ mkbls "0-rescue-${MACHINE_ID}" "0" "${bootprefix}" >"${blsdir}/${MACHINE_ID}-0-rescue.conf"
+ fi
+}
+
+# The grub2 EFI binary is not copied to the ESP as a part of an ostree
+# transaction. Make sure a grub2 version with BLS support is installed
+# but only do this if the blsdir is not set, to make sure that the BLS
+# parsing module will search for the BLS snippets in the default path.
+if test -f /run/ostree-booted && test -d /sys/firmware/efi/efivars && \
+ ! ${grub_editenv} - list | grep -q blsdir && \
+ mountpoint -q /boot; then
+ grub_binary="$(find /usr/lib/ostree-boot/efi/EFI/${EFIDIR}/ -name grub*.efi)"
+ install -m 700 ${grub_binary} ${grubdir} || exit 1
+ # Create a hidden file to indicate that grub2 now has BLS support.
+ touch /boot/grub2/.grub2-blscfg-supported
+fi
+
+GENERATE=0
+if grep '^GRUB_ENABLE_BLSCFG=.*' "${etcdefaultgrub}" \
+ | grep -vq '^GRUB_ENABLE_BLSCFG="*true"*\s*$' ; then
+ if ! sed -i"${backupsuffix}" \
+ -e 's,^GRUB_ENABLE_BLSCFG=.*,GRUB_ENABLE_BLSCFG=true,' \
+ "${etcdefaultgrub}" ; then
+ gettext_printf "Updating %s failed\n" "${etcdefaultgrub}"
+ exit 1
+ fi
+ GENERATE=1
+elif ! grep -q '^GRUB_ENABLE_BLSCFG=.*' "${etcdefaultgrub}" ; then
+ if ! echo 'GRUB_ENABLE_BLSCFG=true' >> "${etcdefaultgrub}" ; then
+ gettext_printf "Updating %s failed\n" "${etcdefaultgrub}"
+ exit 1
+ fi
+ GENERATE=1
+fi
+
+if [ "${GENERATE}" -eq 1 ] ; then
+ copy_bls
+
+ if [ $arch = "x86_64" ] && [ ! -d /sys/firmware/efi ]; then
+ mod_dir="i386-pc"
+ elif [ $arch = "ppc64" -o $arch = "ppc64le" ] && [ ! -d /sys/firmware/opal ]; then
+ mod_dir="powerpc-ieee1275"
+ fi
+
+ if [ -n "${mod_dir}" ]; then
+ for mod in blscfg increment; do
+ install -m 700 ${prefix}/lib/grub/${mod_dir}/${mod}.mod ${grubdir}/$mod_dir/ || exit 1
+ done
+ fi
+
+ cp -af "${GRUB_CONFIG_FILE}" "${GRUB_CONFIG_FILE}${backupsuffix}"
+ if ! grub2-mkconfig -o "${GRUB_CONFIG_FILE}" ; then
+ install -m 700 "${GRUB_CONFIG_FILE}${backupsuffix}" "${GRUB_CONFIG_FILE}"
+ sed -i"${backupsuffix}" \
+ -e 's,^GRUB_ENABLE_BLSCFG=.*,GRUB_ENABLE_BLSCFG=false,' \
+ "${etcdefaultgrub}"
+ gettext_printf "Updating %s failed\n" "${GRUB_CONFIG_FILE}"
+ exit 1
+ fi
+fi
+
+# Bye.
+exit 0
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index 49eccbeaf..45eefb332 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -147,7 +147,7 @@ blsdir="/boot/loader/entries"
get_sorted_bls()
{
- if ! [ -d "${blsdir}" ]; then
+ if ! [ -d "${blsdir}" ] || [ -f /run/ostree-booted ] || [ -d /ostree/repo ]; then
return
fi
--
2.44.0

View File

@ -0,0 +1,277 @@
From 25069a23257ba9c6db644bbe6114dafb879063e5 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 8 Jul 2019 12:32:37 +0200
Subject: [PATCH 03/11] Handle multi-arch (64-on-32) boot in linuxefi loader.
Allow booting 64-bit kernels on 32-bit EFI on x86.
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/loader/efi/linux.c | 11 ++-
grub-core/loader/i386/efi/linux.c | 127 +++++++++++++++++++-----------
include/grub/i386/linux.h | 7 +-
3 files changed, 97 insertions(+), 48 deletions(-)
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -44,14 +44,10 @@
static grub_err_t
grub_linuxefi_boot (void)
{
- int offset = 0;
-
-#ifdef __x86_64__
- offset = 512;
-#endif
asm volatile ("cli");
- return grub_efi_linux_boot ((char *)kernel_mem, handover_offset + offset,
+ return grub_efi_linux_boot ((char *)kernel_mem,
+ handover_offset,
params);
}
@@ -147,14 +143,20 @@
return grub_errno;
}
+#define MIN(a, b) \
+ ({ typeof (a) _a = (a); \
+ typeof (b) _b = (b); \
+ _a < _b ? _a : _b; })
+
static grub_err_t
grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
grub_file_t file = 0;
- struct linux_i386_kernel_header lh;
- grub_ssize_t len, start, filelen;
+ struct linux_i386_kernel_header *lh = NULL;
+ grub_ssize_t start, filelen;
void *kernel = NULL;
+ int setup_header_end_offset;
grub_err_t err;
grub_dl_ref (my_mod);
@@ -185,45 +187,79 @@
goto fail;
}
- params = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(16384));
-
+ params = grub_efi_allocate_pages_max (0x3fffffff,
+ BYTES_TO_PAGES(sizeof(*params)));
if (! params)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters");
goto fail;
}
- grub_memset (params, 0, 16384);
+ grub_dprintf ("linux", "params = %p\n", params);
- grub_memcpy (&lh, kernel, sizeof (lh));
+ grub_memset (params, 0, sizeof(*params));
- if (lh.boot_flag != grub_cpu_to_le16 (0xaa55))
+ setup_header_end_offset = *((grub_uint8_t *)kernel + 0x201);
+ grub_dprintf ("linux", "copying %lu bytes from %p to %p\n",
+ MIN((grub_size_t)0x202+setup_header_end_offset,
+ sizeof (*params)) - 0x1f1,
+ (grub_uint8_t *)kernel + 0x1f1,
+ (grub_uint8_t *)params + 0x1f1);
+ grub_memcpy ((grub_uint8_t *)params + 0x1f1,
+ (grub_uint8_t *)kernel + 0x1f1,
+ MIN((grub_size_t)0x202+setup_header_end_offset,sizeof (*params)) - 0x1f1);
+ lh = (struct linux_i386_kernel_header *)params;
+ grub_dprintf ("linux", "lh is at %p\n", lh);
+ grub_dprintf ("linux", "checking lh->boot_flag\n");
+ if (lh->boot_flag != grub_cpu_to_le16 (0xaa55))
{
grub_error (GRUB_ERR_BAD_OS, N_("invalid magic number"));
goto fail;
}
- if (lh.setup_sects > GRUB_LINUX_MAX_SETUP_SECTS)
+ grub_dprintf ("linux", "checking lh->setup_sects\n");
+ if (lh->setup_sects > GRUB_LINUX_MAX_SETUP_SECTS)
{
grub_error (GRUB_ERR_BAD_OS, N_("too many setup sectors"));
goto fail;
}
- if (lh.version < grub_cpu_to_le16 (0x020b))
+ grub_dprintf ("linux", "checking lh->version\n");
+ if (lh->version < grub_cpu_to_le16 (0x020b))
{
grub_error (GRUB_ERR_BAD_OS, N_("kernel too old"));
goto fail;
}
- if (!lh.handover_offset)
+ grub_dprintf ("linux", "checking lh->handover_offset\n");
+ if (!lh->handover_offset)
{
grub_error (GRUB_ERR_BAD_OS, N_("kernel doesn't support EFI handover"));
goto fail;
}
- linux_cmdline = grub_efi_allocate_pages_max(0x3fffffff,
- BYTES_TO_PAGES(lh.cmdline_size + 1));
+#if defined(__x86_64__) || defined(__aarch64__)
+ grub_dprintf ("linux", "checking lh->xloadflags\n");
+ if (!(lh->xloadflags & LINUX_XLF_KERNEL_64))
+ {
+ grub_error (GRUB_ERR_BAD_OS, N_("kernel doesn't support 64-bit CPUs"));
+ goto fail;
+ }
+#endif
+#if defined(__i386__)
+ if ((lh->xloadflags & LINUX_XLF_KERNEL_64) &&
+ !(lh->xloadflags & LINUX_XLF_EFI_HANDOVER_32))
+ {
+ grub_error (GRUB_ERR_BAD_OS,
+ N_("kernel doesn't support 32-bit handover"));
+ goto fail;
+ }
+#endif
+
+ grub_dprintf ("linux", "setting up cmdline\n");
+ linux_cmdline = grub_efi_allocate_pages_max(0x3fffffff,
+ BYTES_TO_PAGES(lh->cmdline_size + 1));
if (!linux_cmdline)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate cmdline"));
@@ -233,27 +269,26 @@
grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE));
err = grub_create_loader_cmdline (argc, argv,
linux_cmdline + sizeof (LINUX_IMAGE) - 1,
- lh.cmdline_size - (sizeof (LINUX_IMAGE) - 1),
+ lh->cmdline_size - (sizeof (LINUX_IMAGE) - 1),
GRUB_VERIFY_KERNEL_CMDLINE);
if (err)
goto fail;
- lh.cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linux_cmdline;
+ grub_dprintf ("linux", "cmdline:%s\n", linux_cmdline);
+ grub_dprintf ("linux", "setting lh->cmd_line_ptr\n");
+ lh->cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linux_cmdline;
- handover_offset = lh.handover_offset;
+ grub_dprintf ("linux", "computing handover offset\n");
+ handover_offset = lh->handover_offset;
- start = (lh.setup_sects + 1) * 512;
- len = grub_file_size(file) - start;
+ start = (lh->setup_sects + 1) * 512;
- kernel_mem = grub_efi_allocate_fixed (lh.pref_address,
- BYTES_TO_PAGES(lh.init_size));
+ kernel_mem = grub_efi_allocate_pages_max(lh->pref_address,
+ BYTES_TO_PAGES(lh->init_size));
if (!kernel_mem)
- {
- grub_errno = GRUB_ERR_NONE;
- kernel_mem = grub_efi_allocate_pages_max(0x3fffffff,
- BYTES_TO_PAGES(lh.init_size));
- }
+ kernel_mem = grub_efi_allocate_pages_max(0x3fffffff,
+ BYTES_TO_PAGES(lh->init_size));
if (!kernel_mem)
{
@@ -261,21 +296,23 @@
goto fail;
}
- grub_memcpy (kernel_mem, (char *)kernel + start, len);
+ grub_dprintf ("linux", "kernel_mem = %lx\n", (unsigned long) kernel_mem);
+
grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
loaded=1;
+ grub_dprintf ("linux", "setting lh->code32_start to %p\n", kernel_mem);
+ lh->code32_start = (grub_uint32_t)(grub_addr_t) kernel_mem;
- lh.code32_start = (grub_uint32_t)(grub_uint64_t) kernel_mem;
- /* Grub linuxefi erroneously initialize linux's boot_params with non-zero values. (bsc#1025563)
+ grub_memcpy (kernel_mem, (char *)kernel + start, filelen - start);
- From https://www.kernel.org/doc/Documentation/x86/boot.txt:
- The memory for struct boot_params could be allocated anywhere (even above 4G)
- and initialized to all zero.
- Then, the setup header at offset 0x01f1 of kernel image on should be
- loaded into struct boot_params and examined. */
- grub_memcpy (&params->setup_sects, &lh.setup_sects, sizeof (lh) - 0x01f1);
+ grub_dprintf ("linux", "setting lh->type_of_loader\n");
+ lh->type_of_loader = 0x6;
- params->type_of_loader = 0x21;
+ grub_dprintf ("linux", "setting lh->ext_loader_{type,ver}\n");
+ params->ext_loader_type = 0;
+ params->ext_loader_ver = 2;
+ grub_dprintf("linux", "kernel_mem: %p handover_offset: %08x\n",
+ kernel_mem, handover_offset);
fail:
@@ -291,8 +328,10 @@
loaded = 0;
}
- if (linux_cmdline && !loaded)
- grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)linux_cmdline, BYTES_TO_PAGES(lh.cmdline_size + 1));
+ if (linux_cmdline && lh && !loaded)
+ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)
+ linux_cmdline,
+ BYTES_TO_PAGES(lh->cmdline_size + 1));
if (kernel_mem && !loaded)
grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)kernel_mem, BYTES_TO_PAGES(kernel_size));
--- a/include/grub/i386/linux.h
+++ b/include/grub/i386/linux.h
@@ -148,6 +148,11 @@
grub_uint32_t kernel_alignment;
grub_uint8_t relocatable;
grub_uint8_t min_alignment;
+#define LINUX_XLF_KERNEL_64 (1<<0)
+#define LINUX_XLF_CAN_BE_LOADED_ABOVE_4G (1<<1)
+#define LINUX_XLF_EFI_HANDOVER_32 (1<<2)
+#define LINUX_XLF_EFI_HANDOVER_64 (1<<3)
+#define LINUX_XLF_EFI_KEXEC (1<<4)
grub_uint16_t xloadflags;
grub_uint32_t cmdline_size;
grub_uint32_t hardware_subarch;
--- a/grub-core/loader/efi/linux_boot.c
+++ b/grub-core/loader/efi/linux_boot.c
@@ -30,11 +30,16 @@
typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *);
grub_err_t
-grub_efi_linux_boot (void *kernel_addr, grub_off_t offset,
+grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset,
void *kernel_params)
{
grub_efi_loaded_image_t *loaded_image = NULL;
handover_func hf;
+ int offset = 0;
+
+#ifdef __x86_64__
+ offset = 512;
+#endif
/*
* Since the EFI loader is not calling the LoadImage() and StartImage()
@@ -48,8 +53,8 @@
grub_dprintf ("linux", "Loaded Image base address could not be set\n");
grub_dprintf ("linux", "kernel_addr: %p handover_offset: %p params: %p\n",
- kernel_addr, (void *)(grub_efi_uintn_t)offset, kernel_params);
- hf = (handover_func)((char *)kernel_addr + offset);
+ kernel_addr, (void *)(grub_efi_uintn_t)handover_offset, kernel_params);
+ hf = (handover_func)((char *)kernel_addr + handover_offset + offset);
hf (grub_efi_image_handle, grub_efi_system_table, kernel_params);
return GRUB_ERR_BUG;

View File

@ -0,0 +1,57 @@
From 3526c4e467ee01a3cfd2f4d627433d078a1ab780 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 27 Aug 2018 13:14:06 -0400
Subject: [PATCH 3/9] Make grub_error() more verbose
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/kern/efi/mm.c | 17 ++++++++++++++---
grub-core/kern/err.c | 13 +++++++++++--
include/grub/err.h | 5 ++++-
3 files changed, 29 insertions(+), 6 deletions(-)
--- a/grub-core/kern/err.c
+++ b/grub-core/kern/err.c
@@ -33,15 +33,24 @@
static int grub_error_stack_pos;
static int grub_error_stack_assert;
+#ifdef grub_error
+#undef grub_error
+#endif
+
grub_err_t
-grub_error (grub_err_t n, const char *fmt, ...)
+grub_error (grub_err_t n, const char *file, 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);
+ if (m < 0)
+ m = 0;
+
va_start (ap, fmt);
- grub_vsnprintf (grub_errmsg, sizeof (grub_errmsg), _(fmt), ap);
+ grub_vsnprintf (grub_errmsg + m, sizeof (grub_errmsg) - m, _(fmt), ap);
va_end (ap);
return n;
--- a/include/grub/err.h
+++ b/include/grub/err.h
@@ -86,8 +86,11 @@
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 *fmt, ...)
- __attribute__ ((format (GNU_PRINTF, 2, 3)));
+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)));
+
+#define grub_error(n, fmt, ...) grub_error (n, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
+
void EXPORT_FUNC(grub_fatal) (const char *fmt, ...) __attribute__ ((noreturn));
void EXPORT_FUNC(grub_error_push) (void);
int EXPORT_FUNC(grub_error_pop) (void);

View File

@ -0,0 +1,117 @@
From 6c8d390809956d355fed8bc830f64e86838e3e82 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Sat, 18 Nov 2023 21:42:00 +0800
Subject: [PATCH 3/4] Restrict 'ls' and auto file completion on cryptodisk
print
The 'ls' command allows file listing, while file completion assists in
providing matched file names by partially inputting via the TAB key.
Both functionalities should be restricted when the disk is automatically
unlocked for the same reasons as highlighted in the previous patch
addressing the limitation on file access to the cryptodisk.
Given that no file is explicitly opened for listing, employing file
filters becomes impractical. Consequently, this patch focuses on
modifying relevant routines separately to incorporate necessary checks.
The objective is to introduce measures that prevent 'ls' and auto file
completion from accessing encrypted data when the disk is automatically
unlocked.
By implementing these modifications, any attempt to utilize 'ls' or file
completion on the cryptodisk will result in an "Access Denied:
prohibited to browse encrypted data" error message, thus effectively
alerting the user about the restricted access.
While protecting content within disk files from viewing is essential,
it's equally crucial to restrict access to in-memory content. This
includes prohibiting access to the decrypted in-memory copies of disk
files.
This enhancement aims to fortify security protocols by extending
restrictions to additional functionalities beyond direct file access.
Signed-Off-by Michael Chang <mchang@suse.com>
---
grub-core/commands/ls.c | 8 ++++++++
grub-core/commands/minicmd.c | 6 ++++++
grub-core/kern/corecmd.c | 8 ++++++++
grub-core/normal/completion.c | 8 ++++++++
4 files changed, 30 insertions(+)
diff --git a/grub-core/commands/ls.c b/grub-core/commands/ls.c
index 8e98c73cc..aeb336a73 100644
--- a/grub-core/commands/ls.c
+++ b/grub-core/commands/ls.c
@@ -183,6 +183,14 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human)
if (! dev)
goto fail;
+ if (dev->disk &&
+ grub_disk_is_crypto (dev->disk) &&
+ grub_file_filters[GRUB_FILE_FILTER_NOCAT])
+ {
+ grub_error (GRUB_ERR_ACCESS_DENIED, N_("prohibited to browse encrypted content"));
+ goto fail;
+ }
+
fs = grub_fs_probe (dev);
path = grub_strchr (dirname, ')');
if (! path)
diff --git a/grub-core/commands/minicmd.c b/grub-core/commands/minicmd.c
index fa498931e..8f2ac0539 100644
--- a/grub-core/commands/minicmd.c
+++ b/grub-core/commands/minicmd.c
@@ -101,6 +101,12 @@ grub_mini_cmd_dump (struct grub_command *cmd __attribute__ ((unused)),
if (argc == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no address specified");
+ /* NOCAT filter is applied to prevent cat alike command from revealing file
+ * content, the dump command should also be prohibited to revealing memory
+ * content as well */
+ if (grub_file_filters[GRUB_FILE_FILTER_NOCAT])
+ return grub_error (GRUB_ERR_ACCESS_DENIED, N_("prohibited by security policy"));
+
#if GRUB_CPU_SIZEOF_VOID_P == GRUB_CPU_SIZEOF_LONG
#define grub_strtoaddr grub_strtoul
#else
diff --git a/grub-core/kern/corecmd.c b/grub-core/kern/corecmd.c
index 62d434ba9..b639bc3ae 100644
--- a/grub-core/kern/corecmd.c
+++ b/grub-core/kern/corecmd.c
@@ -135,6 +135,14 @@ grub_core_cmd_ls (struct grub_command *cmd __attribute__ ((unused)),
if (! dev)
goto fail;
+ if (dev->disk &&
+ grub_disk_is_crypto (dev->disk) &&
+ grub_file_filters[GRUB_FILE_FILTER_NOCAT])
+ {
+ grub_error (GRUB_ERR_ACCESS_DENIED, N_("prohibited to browse encrypted content"));
+ goto fail;
+ }
+
fs = grub_fs_probe (dev);
path = grub_strchr (argv[0], ')');
if (! path)
diff --git a/grub-core/normal/completion.c b/grub-core/normal/completion.c
index 18cadfa85..d003ec37d 100644
--- a/grub-core/normal/completion.c
+++ b/grub-core/normal/completion.c
@@ -259,6 +259,14 @@ complete_file (void)
goto fail;
}
+ if (dev->disk &&
+ grub_disk_is_crypto (dev->disk) &&
+ grub_file_filters[GRUB_FILE_FILTER_NOCAT])
+ {
+ grub_error (GRUB_ERR_ACCESS_DENIED, N_("prohibited to browse encrypted content"));
+ goto fail;
+ }
+
fs = grub_fs_probe (dev);
if (! fs)
{
--
2.42.1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,38 @@
From 370e435b6ada53314888f04dcd8f096fc11cfadb Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Thu, 3 Aug 2023 15:52:52 +0800
Subject: [PATCH 3/4] cryptodisk: wipe out the cached keys from protectors
An attacker may insert a malicious disk with the same crypto UUID and
trick grub2 to mount the fake root. Even though the key from the key
protector fails to unlock the fake root, it's not wiped out cleanly so
the attacker could dump the memory to retrieve the secret key. To defend
such attack, wipe out the cached key when we don't need it.
Cc: Fabian Vogt <fvogt@suse.com>
Signed-off-by: Gary Lin <glin@suse.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
---
grub-core/disk/cryptodisk.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index f9842f776..aa0d43562 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -1355,7 +1355,11 @@ grub_cryptodisk_clear_key_cache (struct grub_cryptomount_args *cargs)
return;
for (i = 0; cargs->protectors[i]; i++)
- grub_free (cargs->key_cache[i].key);
+ {
+ if (cargs->key_cache[i].key)
+ grub_memset (cargs->key_cache[i].key, 0, cargs->key_cache[i].key_len);
+ grub_free (cargs->key_cache[i].key);
+ }
grub_free (cargs->key_cache);
}
--
2.35.3

View File

@ -0,0 +1,137 @@
From c31fc5aa0ded9ce1e774d0a3526cfee19be1b77f Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Mon, 7 Feb 2022 20:49:01 +0800
Subject: [PATCH 3/5] grub-install: support prep environment block
The grub-install can be instructed to create environment block at end of
PReP paritition with probed device identities and properties in
variables to facilitate root device discovery. So far these variables
are defined for this purpose:
ENV_FS_UUID - The filesystem uuid for the grub root device
ENV_CRYPTO_UUID - The crytodisk uuid for the grub root device separated
by space
ENV_GRUB_DIR - The path to grub prefix directory
ENV_HINT - The recommended hint string for searching root device
The size of environment block is defined in GRUB_ENVBLK_PREP_SIZE which
is 4096 bytes and can be extended in the future.
v2: Improve detection of ENV_CRYPTO_UUID by traversing all members of
the logical disk and utilize a space as a separator when multiple UUIDs
are found (bsc#1216075).
Signed-off-by: Michael Chang <mchang@suse.com>
---
include/grub/lib/envblk.h | 3 +++
util/grub-install.c | 38 ++++++++++++++++++++++++++++++++++++++
2 files changed, 41 insertions(+)
--- a/include/grub/lib/envblk.h
+++ b/include/grub/lib/envblk.h
@@ -24,6 +24,9 @@
#ifndef ASM_FILE
+#include <grub/disk.h>
+#define GRUB_ENVBLK_PREP_SIZE (GRUB_DISK_SECTOR_SIZE << 3)
+
struct grub_envblk
{
char *buf;
--- a/util/grub-install.c
+++ b/util/grub-install.c
@@ -43,6 +43,7 @@
#include <grub/util/ofpath.h>
#include <grub/hfsplus.h>
#include <grub/time.h>
+#include <grub/lib/envblk.h>
#include <string.h>
@@ -609,6 +610,41 @@
}
}
+static char *
+cryptodisk_uuids (grub_disk_t disk, int in_recurse)
+{
+ grub_disk_memberlist_t list = NULL, tmp;
+ static char *ret;
+
+ if (!in_recurse)
+ ret = NULL;
+
+ if (disk->dev->disk_memberlist)
+ list = disk->dev->disk_memberlist (disk);
+
+ while (list)
+ {
+ ret = cryptodisk_uuids (list->disk, 1);
+ tmp = list->next;
+ free (list);
+ list = tmp;
+ }
+
+ if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID)
+ {
+ if (!ret)
+ ret = grub_strdup (grub_util_cryptodisk_get_uuid (disk));
+ else
+ {
+ char *s = grub_xasprintf ("%s %s", grub_util_cryptodisk_get_uuid (disk), ret);
+ grub_free (ret);
+ ret = s;
+ }
+ }
+
+ return ret;
+}
+
static int
is_same_disk (const char *a, const char *b)
{
@@ -2138,6 +2174,43 @@
if (write_to_disk (ins_dev, imgfile))
grub_util_error ("%s", _("failed to copy Grub to the PReP partition"));
grub_set_install_backup_ponr ();
+
+ if ((signed_grub_mode >= SIGNED_GRUB_FORCE) || ((signed_grub_mode == SIGNED_GRUB_AUTO) && (ppc_sb_state > 0)))
+ {
+ char *uuid = NULL;
+ grub_envblk_t envblk = NULL;
+ char *buf;
+ char *cryptouuid = NULL;
+
+ if (grub_dev->disk)
+ cryptouuid = cryptodisk_uuids (grub_dev->disk, 0);
+
+ if (grub_fs->fs_uuid && grub_fs->fs_uuid (grub_dev, &uuid))
+ {
+ grub_print_error ();
+ grub_errno = 0;
+ uuid = NULL;
+ }
+ buf = grub_envblk_buf (GRUB_ENVBLK_PREP_SIZE);
+ envblk = grub_envblk_open (buf, GRUB_ENVBLK_PREP_SIZE);
+ if (uuid)
+ grub_envblk_set (envblk, "ENV_FS_UUID", uuid);
+ if (cryptouuid)
+ grub_envblk_set (envblk, "ENV_CRYPTO_UUID", cryptouuid);
+ if (relative_grubdir)
+ grub_envblk_set (envblk, "ENV_GRUB_DIR", relative_grubdir);
+ if (have_abstractions)
+ grub_envblk_set (envblk, "ENV_HINT", grub_dev->disk->name);
+ if (use_relative_path_on_btrfs)
+ grub_envblk_set (envblk, "btrfs_relative_path", "1");
+ if (envblk)
+ {
+ fprintf (stderr, _("Write environment block to PReP.\n"));
+ if (grub_disk_write_tail (ins_dev->disk, envblk->size, envblk->buf))
+ grub_util_error ("%s", _("failed to write environment block to the PReP partition"));
+ }
+ grub_envblk_close (envblk);
+ }
grub_device_close (ins_dev);
if (update_nvram)
grub_install_register_ieee1275 (1, grub_util_get_os_disk (install_device),

View File

@ -0,0 +1,62 @@
From 1729400ab816804a28ebf50cb1310607b2c4b75e Mon Sep 17 00:00:00 2001
From: Diego Domingos <diegodo@br.ibm.com>
Date: Fri, 25 Feb 2022 12:49:51 -0500
Subject: [PATCH 3/4] ieee1275: change the logic of ieee1275_get_devargs()
Usually grub will parse the PFW arguments by searching for the first occurence of the character ':'.
However, we can have this char more than once on NQN.
This patch changes the logic to find the last occurence of this char so we can get the proper values
for NVMeoFC
---
grub-core/kern/ieee1275/openfw.c | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c
index f819bd106..655a71310 100644
--- a/grub-core/kern/ieee1275/openfw.c
+++ b/grub-core/kern/ieee1275/openfw.c
@@ -354,6 +354,13 @@ static char *
grub_ieee1275_get_devargs (const char *path)
{
char *colon = grub_strchr (path, ':');
+ char *colon_check = colon;
+
+ /* Find the last occurence of colon */
+ while(colon_check){
+ colon = colon_check;
+ colon_check = grub_strchr (colon+1, ':');
+ }
if (! colon)
return 0;
@@ -368,6 +375,18 @@ grub_ieee1275_get_devname (const char *path)
char *colon = grub_strchr (path, ':');
int pathlen = grub_strlen (path);
struct grub_ieee1275_devalias curalias;
+
+ /* Check some special cases */
+ if(grub_strstr(path, "nvme-of")){
+ char *namespace_split = grub_strstr(path,"/namespace@");
+ if(namespace_split){
+ colon = grub_strchr (namespace_split, ':');
+ } else {
+ colon = NULL;
+ }
+
+ }
+
if (colon)
pathlen = (int)(colon - path);
@@ -693,7 +712,7 @@ grub_ieee1275_get_boot_dev (void)
return NULL;
}
- bootpath = (char *) grub_malloc ((grub_size_t) bootpath_size + 64);
+ bootpath = (char *) grub_malloc ((grub_size_t) bootpath_size + 64 + 256);
if (! bootpath)
{
grub_print_error ();
--
2.35.3

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,298 @@
From cf6b16f113b1b5e6efce79b569be1de3e504de8f Mon Sep 17 00:00:00 2001
From: Rashmica Gupta <rashmica.g@gmail.com>
Date: Thu, 11 Jun 2020 11:26:23 +1000
Subject: [PATCH 04/23] Add suport for signing grub with an appended signature
Add infrastructure to allow firmware to verify the integrity of grub
by use of a Linux-kernel-module-style appended signature. We initially
target powerpc-ieee1275, but the code should be extensible to other
platforms.
Usually these signatures are appended to a file without modifying the
ELF file itself. (This is what the 'sign-file' tool does, for example.)
The verifier loads the signed file from the file system and looks at the
end of the file for the appended signature. However, on powerpc-ieee1275
platforms, the bootloader is often stored directly in the PReP partition
as raw bytes without a file-system. This makes determining the location
of an appended signature more difficult.
To address this, we add a new ELF note.
The name field of shall be the string "Appended-Signature", zero-padded
to 4 byte alignment. The type field shall be 0x41536967 (the ASCII values
for the string "ASig"). It must be the final section in the ELF binary.
The description shall contain the appended signature structure as defined
by the Linux kernel. The description will also be padded to be a multiple
of 4 bytes. The padding shall be added before the appended signature
structure (not at the end) so that the final bytes of a signed ELF file
are the appended signature magic.
A subsequent patch documents how to create a grub core.img validly signed
under this scheme.
Signed-off-by: Daniel Axtens <dja@axtens.net>
Signed-off-by: Rashmica Gupta <rashmica.g@gmail.com>
---
You can experiment with this code with a patched version of SLOF
that verifies these signatures. You can find one at:
https://github.com/daxtens/SLOF
I will be proposing this for inclusion in a future Power Architecture
Platform Reference (PAPR).
---
include/grub/util/install.h | 8 ++++++--
include/grub/util/mkimage.h | 4 ++--
util/grub-install-common.c | 15 +++++++++++---
util/grub-mkimage.c | 11 +++++++++++
util/grub-mkimagexx.c | 39 ++++++++++++++++++++++++++++++++++++-
util/mkimage.c | 13 +++++++------
6 files changed, 76 insertions(+), 14 deletions(-)
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -67,6 +67,9 @@
N_("SBAT metadata"), 0 }, \
{ "disable-shim-lock", GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, 0, 0, \
N_("disable shim_lock verifier"), 0 }, \
+ { "appended-signature-size", GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE,\
+ "SIZE", 0, N_("Add a note segment reserving SIZE bytes for an appended signature"), \
+ 1}, \
{ "verbose", 'v', 0, 0, \
N_("print verbose messages."), 1 }
@@ -130,7 +133,8 @@
GRUB_INSTALL_OPTIONS_INSTALL_CORE_COMPRESS,
GRUB_INSTALL_OPTIONS_DTB,
GRUB_INSTALL_OPTIONS_SBAT,
- GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK
+ GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK,
+ GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE
};
extern char *grub_install_source_directory;
@@ -190,7 +194,7 @@
size_t npubkeys,
char *config_path,
const struct grub_install_image_target_desc *image_target,
- int note,
+ int note, size_t appsig_size,
grub_compression_t comp, const char *dtb_file,
const char *sbat_path, const int disable_shim_lock);
--- a/include/grub/util/mkimage.h
+++ b/include/grub/util/mkimage.h
@@ -51,12 +51,12 @@
const struct grub_install_image_target_desc *image_target);
void
grub_mkimage_generate_elf32 (const struct grub_install_image_target_desc *image_target,
- int note, char **core_img, size_t *core_size,
+ int note, size_t appsig_size, char **core_img, size_t *core_size,
Elf32_Addr target_addr,
struct grub_mkimage_layout *layout);
void
grub_mkimage_generate_elf64 (const struct grub_install_image_target_desc *image_target,
- int note, char **core_img, size_t *core_size,
+ int note, size_t appsig_size, char **core_img, size_t *core_size,
Elf64_Addr target_addr,
struct grub_mkimage_layout *layout);
--- a/util/grub-install-common.c
+++ b/util/grub-install-common.c
@@ -466,10 +466,12 @@
static char *sbat;
static int disable_shim_lock;
static grub_compression_t compression;
+static size_t appsig_size;
int
grub_install_parse (int key, char *arg)
{
+ const char *end;
switch (key)
{
case GRUB_INSTALL_OPTIONS_INSTALL_CORE_COMPRESS:
@@ -567,6 +569,12 @@
grub_util_error (_("Unrecognized compression `%s'"), arg);
case GRUB_INSTALL_OPTIONS_GRUB_MKIMAGE:
return 1;
+ case GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE:
+ grub_errno = 0;
+ appsig_size = grub_strtol(arg, &end, 10);
+ if (grub_errno)
+ return 0;
+ return 1;
default:
return 0;
}
@@ -679,9 +687,11 @@
*p = '\0';
grub_util_info ("grub-mkimage --directory '%s' --prefix '%s' --output '%s'"
- " --format '%s' --compression '%s'%s%s%s\n",
+ " --format '%s' --compression '%s'"
+ " --appended-signature-size %zu%s%s%s\n",
dir, prefix, outname,
mkimage_target, compnames[compression],
+ appsig_size,
note ? " --note" : "",
disable_shim_lock ? " --disable-shim-lock" : "", s);
free (s);
@@ -693,7 +703,7 @@
grub_install_generate_image (dir, prefix, fp, outname,
modules.entries, memdisk_path,
pubkeys, npubkeys, config_path, tgt,
- note, compression, dtb, sbat,
+ note, appsig_size, compression, dtb, sbat,
disable_shim_lock);
while (dc--)
grub_install_pop_module ();
--- a/util/grub-mkimage.c
+++ b/util/grub-mkimage.c
@@ -84,6 +84,7 @@
{"sbat", 's', N_("FILE"), 0, N_("SBAT metadata"), 0},
{"disable-shim-lock", GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, 0, 0, N_("disable shim_lock verifier"), 0},
{"verbose", 'v', 0, 0, N_("print verbose messages."), 0},
+ {"appended-signature-size", 'S', N_("SIZE"), 0, N_("Add a note segment reserving SIZE bytes for an appended signature"), 0},
{ 0, 0, 0, 0, 0, 0 }
};
@@ -128,6 +129,7 @@
char *sbat;
int note;
int disable_shim_lock;
+ size_t appsig_size;
const struct grub_install_image_target_desc *image_target;
grub_compression_t comp;
};
@@ -138,6 +140,7 @@
/* Get the input argument from argp_parse, which we
know is a pointer to our arguments structure. */
struct arguments *arguments = state->input;
+ const char* end;
switch (key)
{
@@ -170,6 +173,13 @@
arguments->note = 1;
break;
+ case 'S':
+ grub_errno = 0;
+ arguments->appsig_size = grub_strtol(arg, &end, 10);
+ if (grub_errno)
+ return 0;
+ break;
+
case 'm':
if (arguments->memdisk)
free (arguments->memdisk);
@@ -324,6 +334,7 @@
arguments.memdisk, arguments.pubkeys,
arguments.npubkeys, arguments.config,
arguments.image_target, arguments.note,
+ arguments.appsig_size,
arguments.comp, arguments.dtb,
arguments.sbat, arguments.disable_shim_lock);
--- a/util/grub-mkimagexx.c
+++ b/util/grub-mkimagexx.c
@@ -85,6 +85,15 @@
struct grub_ieee1275_note_desc descriptor;
};
+#define GRUB_APPENDED_SIGNATURE_NOTE_NAME "Appended-Signature"
+#define GRUB_APPENDED_SIGNATURE_NOTE_TYPE 0x41536967 /* "ASig" */
+
+struct grub_appended_signature_note
+{
+ Elf32_Nhdr header;
+ char name[ALIGN_UP(sizeof (GRUB_APPENDED_SIGNATURE_NOTE_NAME), 4)];
+};
+
#define GRUB_XEN_NOTE_NAME "Xen"
struct fixup_block_list
@@ -208,7 +217,7 @@
void
SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc *image_target,
- int note, char **core_img, size_t *core_size,
+ int note, size_t appsig_size, char **core_img, size_t *core_size,
Elf_Addr target_addr,
struct grub_mkimage_layout *layout)
{
@@ -222,6 +231,12 @@
int shnum = 4;
int string_size = sizeof (".text") + sizeof ("mods") + 1;
+ if (appsig_size)
+ {
+ phnum++;
+ footer_size += ALIGN_UP(sizeof (struct grub_appended_signature_note) + appsig_size, 4);
+ }
+
if (image_target->id != IMAGE_LOONGSON_ELF)
phnum += 2;
@@ -485,6 +500,28 @@
phdr->p_offset = grub_host_to_target32 (header_size + program_size);
}
+ if (appsig_size) {
+ int note_size = ALIGN_UP(sizeof (struct grub_appended_signature_note) + appsig_size, 4);
+ struct grub_appended_signature_note *note_ptr = (struct grub_appended_signature_note *)
+ (elf_img + program_size + header_size + (note ? sizeof (struct grub_ieee1275_note) : 0));
+
+ note_ptr->header.n_namesz = grub_host_to_target32 (sizeof (GRUB_APPENDED_SIGNATURE_NOTE_NAME));
+ /* needs to sit at the end, so we round this up and sign some zero padding */
+ note_ptr->header.n_descsz = grub_host_to_target32 (ALIGN_UP(appsig_size, 4));
+ note_ptr->header.n_type = grub_host_to_target32 (GRUB_APPENDED_SIGNATURE_NOTE_TYPE);
+ strcpy (note_ptr->name, GRUB_APPENDED_SIGNATURE_NOTE_NAME);
+
+ phdr++;
+ phdr->p_type = grub_host_to_target32 (PT_NOTE);
+ phdr->p_flags = grub_host_to_target32 (PF_R);
+ phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
+ phdr->p_vaddr = 0;
+ phdr->p_paddr = 0;
+ phdr->p_filesz = grub_host_to_target32 (note_size);
+ phdr->p_memsz = 0;
+ phdr->p_offset = grub_host_to_target32 (header_size + program_size + (note ? sizeof (struct grub_ieee1275_note) : 0));
+ }
+
{
char *str_start = (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr)
+ shnum * sizeof (*shdr));
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -885,8 +885,9 @@
char *memdisk_path, char **pubkey_paths,
size_t npubkeys, char *config_path,
const struct grub_install_image_target_desc *image_target,
- int note, grub_compression_t comp, const char *dtb_path,
- const char *sbat_path, int disable_shim_lock)
+ int note, size_t appsig_size, grub_compression_t comp,
+ const char *dtb_path, const char *sbat_path,
+ int disable_shim_lock)
{
char *kernel_img, *core_img;
size_t total_module_size, core_size;
@@ -1810,11 +1811,11 @@
else
target_addr = image_target->link_addr;
if (image_target->voidp_sizeof == 4)
- grub_mkimage_generate_elf32 (image_target, note, &core_img, &core_size,
- target_addr, &layout);
+ grub_mkimage_generate_elf32 (image_target, note, appsig_size, &core_img,
+ &core_size, target_addr, &layout);
else
- grub_mkimage_generate_elf64 (image_target, note, &core_img, &core_size,
- target_addr, &layout);
+ grub_mkimage_generate_elf64 (image_target, note, appsig_size, &core_img,
+ &core_size, target_addr, &layout);
}
break;
}

View File

@ -0,0 +1,279 @@
From 3cf4fdf8d17423dea4e5913ab14fb6305f3c2571 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 18 Feb 2022 21:43:38 +0800
Subject: [PATCH 4/5] Introduce prep_load_env command
This command will accept grub disk device and perform load_env for
environment block located at end of PReP partition which belongs to that
input disk device. All variables read from that environment block are
exported to grub as environment variables.
Please note there's no support for whitelist variables and also
--skip-sig option compared to ordinary load_env command.
v2:
To avoid disrupting the boot process with errors, it's important to log
any errors that may occur and always return GRUB_ERR_NONE.
v3:
Making the new module powerpc_ieee1275 specific.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/Makefile.core.def | 5 +
grub-core/commands/prep_loadenv.c | 227 ++++++++++++++++++++++++++++++
2 files changed, 232 insertions(+)
create mode 100644 grub-core/commands/prep_loadenv.c
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2679,3 +2679,9 @@
common = lib/libtasn1_wrap/tests/Test_strings.c;
common = lib/libtasn1_wrap/wrap_tests.c;
};
+
+module = {
+ name = prep_loadenv;
+ common = commands/prep_loadenv.c;
+ enable = powerpc_ieee1275;
+};
--- /dev/null
+++ b/grub-core/commands/prep_loadenv.c
@@ -0,0 +1,237 @@
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/file.h>
+#include <grub/disk.h>
+#include <grub/misc.h>
+#include <grub/err.h>
+#include <grub/env.h>
+#include <grub/partition.h>
+#include <grub/lib/envblk.h>
+#include <grub/extcmd.h>
+#include <grub/i18n.h>
+#include <grub/gpt_partition.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static char *
+match_substr (regmatch_t *match, const char *str)
+{
+ if (match->rm_so != -1)
+ {
+ char *substr;
+ regoff_t sz = match->rm_eo - match->rm_so;
+
+ if (!sz)
+ return NULL;
+ substr = grub_malloc (1 + sz);
+ if (!substr)
+ {
+ grub_print_error ();
+ return NULL;
+ }
+ grub_memcpy (substr, str + match->rm_so, sz);
+ substr[sz] = '\0';
+ return substr;
+ }
+
+ return NULL;
+}
+
+static int
+is_prep_partition (grub_device_t dev)
+{
+ if (!dev->disk)
+ return 0;
+ if (!dev->disk->partition)
+ return 0;
+ if (grub_strcmp (dev->disk->partition->partmap->name, "msdos") == 0)
+ return (dev->disk->partition->msdostype == 0x41);
+
+ if (grub_strcmp (dev->disk->partition->partmap->name, "gpt") == 0)
+ {
+ struct grub_gpt_partentry gptdata;
+ grub_partition_t p = dev->disk->partition;
+ int ret = 0;
+ dev->disk->partition = dev->disk->partition->parent;
+
+ if (grub_disk_read (dev->disk, p->offset, p->index,
+ sizeof (gptdata), &gptdata) == 0)
+ {
+ const grub_guid_t template = {
+ grub_cpu_to_le32_compile_time (0x9e1a2d38),
+ grub_cpu_to_le16_compile_time (0xc612),
+ grub_cpu_to_le16_compile_time (0x4316),
+ { 0xaa, 0x26, 0x8b, 0x49, 0x52, 0x1e, 0x5a, 0x8b }
+ };
+
+ ret = grub_memcmp (&template, &gptdata.type,
+ sizeof (template)) == 0;
+ }
+ dev->disk->partition = p;
+ return ret;
+ }
+
+ return 0;
+}
+
+static int
+part_hook (grub_disk_t disk, const grub_partition_t partition, void *data)
+{
+ char **ret = data;
+ char *partition_name, *devname;
+ grub_device_t dev;
+
+ partition_name = grub_partition_get_name (partition);
+ if (! partition_name)
+ return 2;
+
+ devname = grub_xasprintf ("%s,%s", disk->name, partition_name);
+ grub_free (partition_name);
+ if (!devname)
+ return 2;
+
+ dev = grub_device_open (devname);
+ if (!dev)
+ {
+ grub_free (devname);
+ return 2;
+ }
+ if (is_prep_partition (dev))
+ {
+ *ret = devname;
+ return 1;
+ }
+ grub_free (devname);
+ grub_device_close (dev);
+ return 0;
+}
+
+static int
+set_var (const char *name, const char *value,
+ void *hook_data __attribute__ ((unused)))
+{
+ grub_env_set (name, value);
+ grub_env_export (name);
+ return 0;
+}
+
+static grub_err_t
+prep_read_envblk (const char *devname)
+{
+ char *buf = NULL;
+ grub_device_t dev = NULL;
+ grub_envblk_t envblk = NULL;
+
+ dev = grub_device_open (devname);
+ if (!dev)
+ return grub_errno;
+
+ if (!dev->disk || !dev->disk->partition)
+ {
+ grub_error (GRUB_ERR_BAD_DEVICE, "disk device required");
+ goto fail;
+ }
+
+ buf = grub_malloc (GRUB_ENVBLK_PREP_SIZE);
+ if (!buf)
+ goto fail;
+
+ if (grub_disk_read (dev->disk, dev->disk->partition->len - (GRUB_ENVBLK_PREP_SIZE >> GRUB_DISK_SECTOR_BITS), 0, GRUB_ENVBLK_PREP_SIZE, buf))
+ goto fail;
+
+ envblk = grub_envblk_open (buf, GRUB_ENVBLK_PREP_SIZE);
+ if (!envblk)
+ {
+ grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid environment block");
+ goto fail;
+ }
+ grub_envblk_iterate (envblk, NULL, set_var);
+
+ fail:
+ if (envblk)
+ grub_envblk_close (envblk);
+ else
+ grub_free (buf);
+ if (dev)
+ grub_device_close (dev);
+ return grub_errno;
+}
+
+static grub_err_t
+prep_partname (const char *devname, char **prep)
+{
+ grub_device_t dev = NULL;
+ grub_err_t err;
+ int ret;
+
+ dev = grub_device_open (devname);
+ if (!dev)
+ return grub_errno;
+
+ /* Only needed for disk device */
+ if (!dev->disk)
+ {
+ err = GRUB_ERR_NONE;
+ goto out;
+ }
+
+ ret = grub_partition_iterate (dev->disk, part_hook, prep);
+ if (ret == 1 && *prep)
+ {
+ err = GRUB_ERR_NONE;
+ goto out;
+ }
+ else if (ret == 0 && grub_errno == GRUB_ERR_NONE)
+ err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "no prep partition");
+ else
+ err = grub_errno;
+
+ out:
+ grub_device_close (dev);
+ return err;
+}
+
+static grub_err_t
+grub_cmd_prep_loadenv (grub_command_t cmd __attribute__ ((unused)),
+ int argc,
+ char **argv)
+{
+ char *devname, *prep = NULL;
+ grub_err_t err;
+
+ if (argc < 1)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
+
+ devname = grub_file_get_device_name(argv[0]);
+ if (!devname)
+ return grub_errno;
+
+ err = prep_partname (devname, &prep);
+ if (prep == NULL || err != GRUB_ERR_NONE)
+ goto out;
+
+ err = prep_read_envblk (prep);
+
+ out:
+ grub_free (devname);
+ grub_free (prep);
+
+ if (err)
+ grub_print_error ();
+ return GRUB_ERR_NONE;
+}
+
+static grub_command_t cmd_prep_load;
+
+GRUB_MOD_INIT(prep_loadenv)
+{
+ cmd_prep_load =
+ grub_register_command("prep_load_env", grub_cmd_prep_loadenv,
+ "DEVICE",
+ N_("Load variables from environment block file."));
+}
+
+GRUB_MOD_FINI(prep_loadenv)
+{
+ grub_unregister_command (cmd_prep_load);
+}

View File

@ -0,0 +1,91 @@
From 6547d22fc9e20720d1a896be82b2d50d842f86b0 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Mon, 20 Nov 2023 09:25:53 +0800
Subject: [PATCH 4/4] Key revocation on out of bound file access
After successful disk unlocking, grub now takes on the responsibility of
safeguarding passwords or TPM keys exclusively within authenticated
cryptodisk files. Any attempt to access boot-related files outside this
trust realm triggers immediate key revocation, preventing potential
compromise by out of bound access.
This patch strengthens security measures by restricting grub's access to
system boot files, except for essential internal processes like memdisk
and procfs, ensuring key protection against potential breaches due to
inadvertent customizations in grub.cfg.
Signed-Off-by Michael Chang <mchang@suse.com>
---
grub-core/commands/crypttab.c | 36 +++++++++++++++++++++++++++++++++++
include/grub/file.h | 1 +
2 files changed, 37 insertions(+)
diff --git a/grub-core/commands/crypttab.c b/grub-core/commands/crypttab.c
index d3acc4b59..e09296c57 100644
--- a/grub-core/commands/crypttab.c
+++ b/grub-core/commands/crypttab.c
@@ -121,6 +121,41 @@ grub_cryptokey_tpmkey_discard (void)
grub_cryptokey_discard();
}
+static grub_file_t
+grub_distrust_open (grub_file_t io,
+ enum grub_file_type type __attribute__ ((unused)))
+{
+ grub_disk_t disk = io->device->disk;
+
+ if (io->device->disk &&
+ (io->device->disk->dev->id == GRUB_DISK_DEVICE_MEMDISK_ID
+ || io->device->disk->dev->id == GRUB_DISK_DEVICE_PROCFS_ID))
+ return io;
+
+ /* Ensure second stage files is in a protected location or grub won't hand
+ * over the key and discards it */
+ switch (type & GRUB_FILE_TYPE_MASK)
+ {
+ case GRUB_FILE_TYPE_ACPI_TABLE:
+ case GRUB_FILE_TYPE_CONFIG:
+ case GRUB_FILE_TYPE_DEVICE_TREE_IMAGE:
+ case GRUB_FILE_TYPE_FONT:
+ case GRUB_FILE_TYPE_GRUB_MODULE:
+ case GRUB_FILE_TYPE_GRUB_MODULE_LIST:
+ case GRUB_FILE_TYPE_LINUX_KERNEL:
+ case GRUB_FILE_TYPE_LINUX_INITRD:
+ case GRUB_FILE_TYPE_LOADENV:
+ case GRUB_FILE_TYPE_THEME:
+ if (!disk || !grub_disk_is_crypto (disk))
+ grub_cryptokey_discard ();
+ break;
+ default:
+ break;
+ }
+
+ return io;
+}
+
static grub_err_t
grub_cmd_crypttab_entry (grub_command_t cmd __attribute__ ((unused)),
int argc, char **argv)
@@ -153,6 +188,7 @@ GRUB_MOD_INIT(crypttab)
{
cmd = grub_register_command ("crypttab_entry", grub_cmd_crypttab_entry,
N_("VOLUME-NAME ENCRYPTED-DEVICE KEY-FILE") , N_("No description"));
+ grub_file_filter_register (GRUB_FILE_FILTER_DISTRUST, grub_distrust_open);
grub_dl_set_persistent (mod);
}
diff --git a/include/grub/file.h b/include/grub/file.h
index fcfd32ce2..daf23a9c9 100644
--- a/include/grub/file.h
+++ b/include/grub/file.h
@@ -185,6 +185,7 @@ extern grub_disk_read_hook_t EXPORT_VAR(grub_file_progress_hook);
/* Filters with lower ID are executed first. */
typedef enum grub_file_filter_id
{
+ GRUB_FILE_FILTER_DISTRUST,
GRUB_FILE_FILTER_NOCAT,
GRUB_FILE_FILTER_VERIFY,
GRUB_FILE_FILTER_GZIO,
--
2.42.1

View File

@ -0,0 +1,183 @@
From 384763d7990f769839ca74d6756fbd85580873d4 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 11 Jul 2019 17:17:02 +0200
Subject: [PATCH 04/11] Try to pick better locations for kernel and initrd
- Don't limit allocations on 64-bit platforms to < 0x[37f]fffffff if
we're using the "large" code model ; use __UINTPTR_MAX__.
- Get the comparison right to check the address we've allocated.
- Fix the allocation for the command line as well.
*But*, when we did this some systems started failing badly; coudln't
parse partition tables, etc. What's going on here is the disk controller
is silently failing DMAs to addresses above 4GB, so we're trying to parse
uninitialized (or HW zeroed) ram when looking for the partition table,
etc.
So to limit this, we make grub_malloc() pick addresses below 4GB on
x86_64, but the direct EFI page allocation functions can get addresses
above that.
Additionally, we now try to locate kernel+initrd+cmdline+etc below
0x7fffffff, and if they're too big to fit any memory window there, then
we try a higher address.
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/kern/efi/mm.c | 8 ++++----
grub-core/loader/i386/efi/linux.c | 25 +++++++++++++++++--------
include/grub/arm/efi/memory.h | 1 +
include/grub/arm64/efi/memory.h | 1 +
include/grub/i386/efi/memory.h | 1 +
include/grub/ia64/efi/memory.h | 1 +
include/grub/x86_64/efi/memory.h | 4 +++-
7 files changed, 28 insertions(+), 13 deletions(-)
--- a/grub-core/kern/efi/mm.c
+++ b/grub-core/kern/efi/mm.c
@@ -121,7 +121,7 @@
grub_efi_boot_services_t *b;
grub_efi_physical_address_t address = max;
- if (max > 0xffffffff)
+ if (max > GRUB_EFI_MAX_USABLE_ADDRESS)
return 0;
b = grub_efi_system_table->boot_services;
@@ -481,7 +481,7 @@
{
if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY
#if 1
- && desc->physical_start <= GRUB_EFI_MAX_USABLE_ADDRESS
+ && desc->physical_start <= GRUB_EFI_MAX_ALLOCATION_ADDRESS
#endif
&& desc->physical_start + PAGES_TO_BYTES (desc->num_pages) > 0x100000
&& desc->num_pages != 0)
@@ -499,9 +499,9 @@
#if 1
if (BYTES_TO_PAGES (filtered_desc->physical_start)
+ filtered_desc->num_pages
- > BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_USABLE_ADDRESS))
+ > BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_ALLOCATION_ADDRESS))
filtered_desc->num_pages
- = (BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_USABLE_ADDRESS)
+ = (BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_ALLOCATION_ADDRESS)
- BYTES_TO_PAGES (filtered_desc->physical_start));
#endif
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -27,6 +27,7 @@
#include <grub/lib/cmdline.h>
#include <grub/efi/efi.h>
#include <grub/efi/linux.h>
+#include <grub/cpu/efi/memory.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -102,8 +103,9 @@
size += ALIGN_UP (grub_file_size (files[i]), 4);
}
- initrd_mem = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(size));
-
+ initrd_mem = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS, BYTES_TO_PAGES(size));
+ if (!initrd_mem)
+ initrd_mem = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS, BYTES_TO_PAGES(size));
if (!initrd_mem)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate initrd"));
@@ -187,8 +189,11 @@
goto fail;
}
- params = grub_efi_allocate_pages_max (0x3fffffff,
+ params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS,
BYTES_TO_PAGES(sizeof(*params)));
+ if (!params)
+ params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS,
+ BYTES_TO_PAGES(sizeof(*params)));
if (! params)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters");
@@ -258,8 +263,11 @@
#endif
grub_dprintf ("linux", "setting up cmdline\n");
- linux_cmdline = grub_efi_allocate_pages_max(0x3fffffff,
- BYTES_TO_PAGES(lh->cmdline_size + 1));
+ linux_cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS,
+ BYTES_TO_PAGES(lh->cmdline_size + 1));
+ if (!linux_cmdline)
+ linux_cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_USABLE_ADDRESS,
+ BYTES_TO_PAGES(lh->cmdline_size + 1));
if (!linux_cmdline)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate cmdline"));
@@ -285,11 +293,12 @@
kernel_mem = grub_efi_allocate_pages_max(lh->pref_address,
BYTES_TO_PAGES(lh->init_size));
-
if (!kernel_mem)
- kernel_mem = grub_efi_allocate_pages_max(0x3fffffff,
+ kernel_mem = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS,
+ BYTES_TO_PAGES(lh->init_size));
+ if (!kernel_mem)
+ kernel_mem = grub_efi_allocate_pages_max(GRUB_EFI_MAX_USABLE_ADDRESS,
BYTES_TO_PAGES(lh->init_size));
-
if (!kernel_mem)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate kernel"));
--- a/include/grub/arm/efi/memory.h
+++ b/include/grub/arm/efi/memory.h
@@ -2,5 +2,6 @@
#include <grub/efi/memory.h>
#define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffff
+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS
#endif /* ! GRUB_MEMORY_CPU_HEADER */
--- a/include/grub/arm64/efi/memory.h
+++ b/include/grub/arm64/efi/memory.h
@@ -2,5 +2,6 @@
#include <grub/efi/memory.h>
#define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffffffffULL
+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS
#endif /* ! GRUB_MEMORY_CPU_HEADER */
--- a/include/grub/i386/efi/memory.h
+++ b/include/grub/i386/efi/memory.h
@@ -2,5 +2,6 @@
#include <grub/efi/memory.h>
#define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffff
+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS
#endif /* ! GRUB_MEMORY_CPU_HEADER */
--- a/include/grub/ia64/efi/memory.h
+++ b/include/grub/ia64/efi/memory.h
@@ -2,5 +2,6 @@
#include <grub/efi/memory.h>
#define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffff
+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS
#endif /* ! GRUB_MEMORY_CPU_HEADER */
--- a/include/grub/x86_64/efi/memory.h
+++ b/include/grub/x86_64/efi/memory.h
@@ -2,9 +2,11 @@
#include <grub/efi/memory.h>
#if defined (__code_model_large__)
-#define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffff
+#define GRUB_EFI_MAX_USABLE_ADDRESS __UINTPTR_MAX__
+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS 0x7fffffff
#else
#define GRUB_EFI_MAX_USABLE_ADDRESS 0x7fffffff
+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS
#endif
#endif /* ! GRUB_MEMORY_CPU_HEADER */

View File

@ -0,0 +1,301 @@
From 5d417346956bc3108183020a8a9f20ddda034b48 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 11 Jul 2019 14:38:57 +0200
Subject: [PATCH 4/9] arm/arm64 loader: Better memory allocation and error
messages.
On mustang, our memory map looks like:
Type Physical start - end #Pages Size Attributes
reserved 0000004000000000-00000040001fffff 00000200 2MiB UC WC WT WB
conv-mem 0000004000200000-0000004393ffffff 00393e00 14654MiB UC WC WT WB
ldr-code 0000004394000000-00000043f7ffffff 00064000 1600MiB UC WC WT WB
BS-data 00000043f8000000-00000043f801ffff 00000020 128KiB UC WC WT WB
conv-mem 00000043f8020000-00000043fa15bfff 0000213c 34032KiB UC WC WT WB
ldr-code 00000043fa15c000-00000043fa2a1fff 00000146 1304KiB UC WC WT WB
ldr-data 00000043fa2a2000-00000043fa3e8fff 00000147 1308KiB UC WC WT WB
conv-mem 00000043fa3e9000-00000043fa3e9fff 00000001 4KiB UC WC WT WB
ldr-data 00000043fa3ea000-00000043fa3eafff 00000001 4KiB UC WC WT WB
ldr-code 00000043fa3eb000-00000043fa4affff 000000c5 788KiB UC WC WT WB
BS-code 00000043fa4b0000-00000043fa59ffff 000000f0 960KiB UC WC WT WB
RT-code 00000043fa5a0000-00000043fa5affff 00000010 64KiB RT UC WC WT WB
RT-data 00000043fa5b0000-00000043fa5bffff 00000010 64KiB RT UC WC WT WB
RT-code 00000043fa5c0000-00000043fa5cffff 00000010 64KiB RT UC WC WT WB
ldr-data 00000043fa5d0000-00000043fa5d0fff 00000001 4KiB UC WC WT WB
BS-code 00000043fa5d1000-00000043fa5ddfff 0000000d 52KiB UC WC WT WB
reserved 00000043fa5de000-00000043fa60ffff 00000032 200KiB UC WC WT WB
ACPI-rec 00000043fa610000-00000043fa6affff 000000a0 640KiB UC WC WT WB
ACPI-nvs 00000043fa6b0000-00000043fa6bffff 00000010 64KiB UC WC WT WB
ACPI-rec 00000043fa6c0000-00000043fa70ffff 00000050 320KiB UC WC WT WB
RT-code 00000043fa710000-00000043fa72ffff 00000020 128KiB RT UC WC WT WB
RT-data 00000043fa730000-00000043fa78ffff 00000060 384KiB RT UC WC WT WB
RT-code 00000043fa790000-00000043fa79ffff 00000010 64KiB RT UC WC WT WB
RT-data 00000043fa7a0000-00000043fa99ffff 00000200 2MiB RT UC WC WT WB
RT-code 00000043fa9a0000-00000043fa9affff 00000010 64KiB RT UC WC WT WB
RT-data 00000043fa9b0000-00000043fa9cffff 00000020 128KiB RT UC WC WT WB
BS-code 00000043fa9d0000-00000043fa9d9fff 0000000a 40KiB UC WC WT WB
reserved 00000043fa9da000-00000043fa9dbfff 00000002 8KiB UC WC WT WB
conv-mem 00000043fa9dc000-00000043fc29dfff 000018c2 25352KiB UC WC WT WB
BS-data 00000043fc29e000-00000043fc78afff 000004ed 5044KiB UC WC WT WB
conv-mem 00000043fc78b000-00000043fca01fff 00000277 2524KiB UC WC WT WB
BS-data 00000043fca02000-00000043fcea3fff 000004a2 4744KiB UC WC WT WB
conv-mem 00000043fcea4000-00000043fcea4fff 00000001 4KiB UC WC WT WB
BS-data 00000043fcea5000-00000043fd192fff 000002ee 3000KiB UC WC WT WB
conv-mem 00000043fd193000-00000043fd2b0fff 0000011e 1144KiB UC WC WT WB
BS-data 00000043fd2b1000-00000043ff80ffff 0000255f 38268KiB UC WC WT WB
BS-code 00000043ff810000-00000043ff99ffff 00000190 1600KiB UC WC WT WB
RT-code 00000043ff9a0000-00000043ff9affff 00000010 64KiB RT UC WC WT WB
conv-mem 00000043ff9b0000-00000043ff9bffff 00000010 64KiB UC WC WT WB
RT-data 00000043ff9c0000-00000043ff9effff 00000030 192KiB RT UC WC WT WB
conv-mem 00000043ff9f0000-00000043ffa05fff 00000016 88KiB UC WC WT WB
BS-data 00000043ffa06000-00000043ffffffff 000005fa 6120KiB UC WC WT WB
MMIO 0000000010510000-0000000010510fff 00000001 4KiB RT
MMIO 0000000010548000-0000000010549fff 00000002 8KiB RT
MMIO 0000000017000000-0000000017001fff 00000002 8KiB RT
MMIO 000000001c025000-000000001c025fff 00000001 4KiB RT
This patch adds a requirement when we're trying to find the base of ram, that
the memory we choose is actually /allocatable/ conventional memory, not merely
write-combining. On this machine that means we wind up with an allocation
around 0x4392XXXXXX, which is a reasonable address.
This also changes grub_efi_allocate_pages_real() so that if 0 is allocated, it
tries to allocate again starting with the same max address it did the first
time, rather than interposing GRUB_EFI_MAX_USABLE_ADDRESS there, so that any
per-platform constraints on its given address are maintained.
Signed-off-by: Peter Jones <pjones@redhat.com>
squash! arm/arm64 loader: Better memory allocation and error messages.
Use PRIxGRUB_* conversion specifier in printf's format string to
correspond properly to the data type of arguments.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/kern/efi/mm.c | 33 ++++++++++---
grub-core/loader/arm64/efi/linux.c | 78 ++++++++++++++++++++++--------
2 files changed, 84 insertions(+), 27 deletions(-)
--- a/grub-core/kern/efi/mm.c
+++ b/grub-core/kern/efi/mm.c
@@ -153,6 +153,7 @@
{
grub_efi_status_t status;
grub_efi_boot_services_t *b;
+ grub_efi_physical_address_t ret = address;
/* Limit the memory access to less than 4GB for 32-bit platforms. */
if (address > GRUB_EFI_MAX_USABLE_ADDRESS)
@@ -169,19 +170,22 @@
}
b = grub_efi_system_table->boot_services;
- status = b->allocate_pages (alloctype, memtype, pages, &address);
+ status = b->allocate_pages (alloctype, memtype, pages, &ret);
if (status != GRUB_EFI_SUCCESS)
{
+ grub_dprintf ("efi",
+ "allocate_pages(%d, %d, 0x%0" PRIxGRUB_SIZE ", 0x%016" PRIxGRUB_UINT64_T ") = 0x%016" PRIxGRUB_SIZE "\n",
+ alloctype, memtype, pages, address, status);
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
return NULL;
}
- if (address == 0)
+ if (ret == 0)
{
/* Uggh, the address 0 was allocated... This is too annoying,
so reallocate another one. */
- address = GRUB_EFI_MAX_USABLE_ADDRESS;
- status = b->allocate_pages (alloctype, memtype, pages, &address);
+ ret = address;
+ status = b->allocate_pages (alloctype, memtype, pages, &ret);
grub_efi_free_pages (0, pages);
if (status != GRUB_EFI_SUCCESS)
{
@@ -190,9 +194,9 @@
}
}
- grub_efi_store_alloc (address, pages);
+ grub_efi_store_alloc (ret, pages);
- return (void *) ((grub_addr_t) address);
+ return (void *) ((grub_addr_t) ret);
}
void *
@@ -711,8 +715,21 @@
for (desc = memory_map, *base_addr = GRUB_EFI_MAX_USABLE_ADDRESS;
(grub_addr_t) desc < ((grub_addr_t) memory_map + memory_map_size);
desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
- if (desc->attribute & GRUB_EFI_MEMORY_WB)
- *base_addr = grub_min (*base_addr, desc->physical_start);
+ {
+ if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY &&
+ (desc->attribute & GRUB_EFI_MEMORY_WB))
+ {
+ *base_addr = grub_min (*base_addr, desc->physical_start);
+ grub_dprintf ("efi", "setting base_addr=0x%016" PRIxGRUB_ADDR "\n", *base_addr);
+ }
+ else
+ {
+ grub_dprintf ("efi", "ignoring address 0x%016" PRIxGRUB_UINT64_T "\n", desc->physical_start);
+ }
+ }
+
+ if (*base_addr == GRUB_EFI_MAX_USABLE_ADDRESS)
+ grub_dprintf ("efi", "base_addr 0x%016" PRIxGRUB_ADDR " is probably wrong.\n", *base_addr);
grub_free(memory_map);
--- a/grub-core/loader/arm64/efi/linux.c
+++ b/grub-core/loader/arm64/efi/linux.c
@@ -89,13 +89,15 @@
{
grub_efi_loaded_image_t *loaded_image = NULL;
int node, retval, len;
-
+ grub_err_t err = GRUB_ERR_NONE;
void *fdt;
fdt = grub_fdt_load (GRUB_EFI_LINUX_FDT_EXTRA_SPACE);
-
if (!fdt)
- goto failure;
+ {
+ err = grub_error(GRUB_ERR_BAD_OS, "failed to load FDT");
+ goto failure;
+ }
node = grub_fdt_find_subnode (fdt, 0, "chosen");
if (node < 0)
@@ -106,17 +108,26 @@
*/
retval = grub_fdt_set_prop32(fdt, 0, "#address-cells", 2);
if (retval)
- goto failure;
+ {
+ err = grub_error(retval, "Could not find #address-cells");
+ goto failure;
+ }
retval = grub_fdt_set_prop32(fdt, 0, "#size-cells", 2);
if (retval)
- goto failure;
+ {
+ err = grub_error(retval, "Could not find #size-cells");
+ goto failure;
+ }
node = grub_fdt_add_subnode (fdt, 0, "chosen");
}
if (node < 1)
- goto failure;
+ {
+ err = grub_error(grub_errno, "failed to load chosen fdt node.");
+ goto failure;
+ }
/* Set initrd info */
if (initrd_start && initrd_end > initrd_start)
@@ -127,15 +138,26 @@
retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-start",
initrd_start);
if (retval)
- goto failure;
+ {
+ err = grub_error(retval, "Failed to set linux,initrd-start property");
+ goto failure;
+ }
+
retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-end",
initrd_end);
if (retval)
- goto failure;
+ {
+ err = grub_error(retval, "Failed to set linux,initrd-end property");
+ goto failure;
+ }
}
- if (grub_fdt_install() != GRUB_ERR_NONE)
- goto failure;
+ retval = grub_fdt_install();
+ if (retval != GRUB_ERR_NONE)
+ {
+ err = grub_error(retval, "Failed to install fdt");
+ goto failure;
+ }
grub_dprintf ("linux", "Installed/updated FDT configuration table @ %p\n",
fdt);
@@ -143,14 +165,20 @@
/* Convert command line to UCS-2 */
loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
if (!loaded_image)
- goto failure;
+ {
+ err = grub_error(grub_errno, "Failed to install fdt");
+ goto failure;
+ }
loaded_image->load_options_size = len =
(grub_strlen (linux_args) + 1) * sizeof (grub_efi_char16_t);
loaded_image->load_options =
grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
if (!loaded_image->load_options)
- return grub_error(GRUB_ERR_BAD_OS, "failed to create kernel parameters");
+ {
+ err = grub_error(GRUB_ERR_BAD_OS, "failed to create kernel parameters");
+ goto failure;
+ }
loaded_image->load_options_size =
2 * grub_utf8_to_utf16 (loaded_image->load_options, len,
@@ -160,7 +188,7 @@
failure:
grub_fdt_unload();
- return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT");
+ return err;
}
static void
@@ -246,16 +274,28 @@
static void *
allocate_initrd_mem (int initrd_pages)
{
- grub_addr_t max_addr;
+ grub_addr_t max_addr = 0;
+ grub_err_t err;
+ void *ret;
+
+ err = grub_efi_get_ram_base (&max_addr);
+ if (err != GRUB_ERR_NONE)
+ {
+ grub_error (err, "grub_efi_get_ram_base() failed");
+ return NULL;
+ }
- if (grub_efi_get_ram_base (&max_addr) != GRUB_ERR_NONE)
- return NULL;
+ grub_dprintf ("linux", "max_addr: 0x%016lx, INITRD_MAX_ADDRESS_OFFSET: 0x%016llx\n",
+ max_addr, INITRD_MAX_ADDRESS_OFFSET);
max_addr += INITRD_MAX_ADDRESS_OFFSET - 1;
+ grub_dprintf ("linux", "calling grub_efi_allocate_pages_real (0x%016lx, 0x%08x, EFI_ALLOCATE_MAX_ADDRESS, EFI_LOADER_DATA)", max_addr, initrd_pages);
- return grub_efi_allocate_pages_real (max_addr, initrd_pages,
- GRUB_EFI_ALLOCATE_MAX_ADDRESS,
- GRUB_EFI_LOADER_DATA);
+ ret = grub_efi_allocate_pages_real (max_addr, initrd_pages,
+ GRUB_EFI_ALLOCATE_MAX_ADDRESS,
+ GRUB_EFI_LOADER_DATA);
+ grub_dprintf ("linux", "got 0x%016llx\n", (unsigned long long)ret);
+ return ret;
}
static grub_err_t

View File

@ -0,0 +1,30 @@
From 2fccb958910afaaf03cbec1a6b98ad197d088ad4 Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Thu, 25 Aug 2022 17:57:55 -0400
Subject: [PATCH 4/9] blscfg: Don't root device in emu builds
Otherwise, we end up looking for kernel/initrd in /boot/boot which
doesn't work at all. Non-emu builds need to be looking in
($root)/boot/, which is what this is for.
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
---
grub-core/commands/blscfg.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/grub-core/commands/blscfg.c b/grub-core/commands/blscfg.c
index 7132555df..150ca96f4 100644
--- a/grub-core/commands/blscfg.c
+++ b/grub-core/commands/blscfg.c
@@ -41,7 +41,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
#define GRUB_BLS_CONFIG_PATH "/loader/entries/"
#ifdef GRUB_MACHINE_EMU
-#define GRUB_BOOT_DEVICE "/boot"
+#define GRUB_BOOT_DEVICE ""
#else
#define GRUB_BOOT_DEVICE "($root)"
#endif
--
2.44.0

View File

@ -0,0 +1,356 @@
From 7ce7b7889ce73174a0d8091978254ecf2d2e205f Mon Sep 17 00:00:00 2001
From: Hernan Gatta <hegatta@linux.microsoft.com>
Date: Tue, 1 Feb 2022 05:02:56 -0800
Subject: [PATCH 4/5] cryptodisk: Support key protectors
Add a new parameter to cryptomount to support the key protectors framework: -P.
The parameter is used to automatically retrieve a key from specified key
protectors. The parameter may be repeated to specify any number of key
protectors. These are tried in order until one provides a usable key for any
given disk.
Signed-off-by: Hernan Gatta <hegatta@linux.microsoft.com>
Signed-off-by: Michael Chang <mchang@suse.com>
Signed-off-by: Gary Lin <glin@suse.com>
Reviewed-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
---
Makefile.util.def | 1 +
grub-core/disk/cryptodisk.c | 172 +++++++++++++++++++++++++++++-------
include/grub/cryptodisk.h | 16 ++++
3 files changed, 158 insertions(+), 31 deletions(-)
diff --git a/Makefile.util.def b/Makefile.util.def
index 3b9435307..252d70af2 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -40,6 +40,7 @@ library = {
common = grub-core/disk/luks.c;
common = grub-core/disk/luks2.c;
common = grub-core/disk/geli.c;
+ common = grub-core/disk/key_protector.c;
common = grub-core/disk/cryptodisk.c;
common = grub-core/disk/AFSplitter.c;
common = grub-core/lib/pbkdf2.c;
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 2246af51b..b7648ffb7 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -26,6 +26,7 @@
#include <grub/file.h>
#include <grub/procfs.h>
#include <grub/partition.h>
+#include <grub/key_protector.h>
#ifdef GRUB_UTIL
#include <grub/emu/hostdisk.h>
@@ -44,7 +45,8 @@ enum
OPTION_KEYFILE,
OPTION_KEYFILE_OFFSET,
OPTION_KEYFILE_SIZE,
- OPTION_HEADER
+ OPTION_HEADER,
+ OPTION_PROTECTOR
};
static const struct grub_arg_option options[] =
@@ -58,6 +60,8 @@ static const struct grub_arg_option options[] =
{"keyfile-offset", 'O', 0, N_("Key file offset (bytes)"), 0, ARG_TYPE_INT},
{"keyfile-size", 'S', 0, N_("Key file data size (bytes)"), 0, ARG_TYPE_INT},
{"header", 'H', 0, N_("Read header from file"), 0, ARG_TYPE_STRING},
+ {"protector", 'P', GRUB_ARG_OPTION_REPEATABLE,
+ N_("Unlock volume(s) using key protector(s)."), 0, ARG_TYPE_STRING},
{0, 0, 0, 0, 0, 0}
};
@@ -1061,6 +1065,7 @@ grub_cryptodisk_scan_device_real (const char *name,
grub_err_t ret = GRUB_ERR_NONE;
grub_cryptodisk_t dev;
grub_cryptodisk_dev_t cr;
+ int i;
struct cryptodisk_read_hook_ctx read_hook_data = {0};
int askpass = 0;
char *part = NULL;
@@ -1113,41 +1118,112 @@ grub_cryptodisk_scan_device_real (const char *name,
goto error_no_close;
if (!dev)
continue;
+ break;
+ }
- if (!cargs->key_len)
- {
- /* Get the passphrase from the user, if no key data. */
- askpass = 1;
- part = grub_partition_get_name (source->partition);
- grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
- source->partition != NULL ? "," : "",
- part != NULL ? part : N_("UNKNOWN"),
- dev->uuid);
- grub_free (part);
-
- cargs->key_data = grub_malloc (GRUB_CRYPTODISK_MAX_PASSPHRASE);
- if (cargs->key_data == NULL)
- goto error_no_close;
-
- if (!grub_password_get ((char *) cargs->key_data, GRUB_CRYPTODISK_MAX_PASSPHRASE))
- {
- grub_error (GRUB_ERR_BAD_ARGUMENT, "passphrase not supplied");
- goto error;
- }
- cargs->key_len = grub_strlen ((char *) cargs->key_data);
- }
+ if (dev == NULL)
+ {
+ grub_error (GRUB_ERR_BAD_MODULE,
+ "no cryptodisk module can handle this device");
+ goto error_no_close;
+ }
- ret = cr->recover_key (source, dev, cargs);
- if (ret != GRUB_ERR_NONE)
- goto error;
+ if (cargs->protectors)
+ {
+ for (i = 0; cargs->protectors[i]; i++)
+ {
+ if (cargs->key_cache[i].invalid)
+ continue;
+
+ if (cargs->key_cache[i].key == NULL)
+ {
+ ret = grub_key_protector_recover_key (cargs->protectors[i],
+ &cargs->key_cache[i].key,
+ &cargs->key_cache[i].key_len);
+ if (ret != GRUB_ERR_NONE)
+ {
+ if (grub_errno)
+ {
+ grub_print_error ();
+ grub_errno = GRUB_ERR_NONE;
+ }
+
+ grub_dprintf ("cryptodisk",
+ "failed to recover a key from key protector "
+ "%s, will not try it again for any other "
+ "disks, if any, during this invocation of "
+ "cryptomount\n",
+ cargs->protectors[i]);
+
+ cargs->key_cache[i].invalid = 1;
+ continue;
+ }
+ }
+
+ cargs->key_data = cargs->key_cache[i].key;
+ cargs->key_len = cargs->key_cache[i].key_len;
+
+ ret = cr->recover_key (source, dev, cargs);
+ if (ret != GRUB_ERR_NONE)
+ {
+ part = grub_partition_get_name (source->partition);
+ grub_dprintf ("cryptodisk",
+ "recovered a key from key protector %s but it "
+ "failed to unlock %s%s%s (%s)\n",
+ cargs->protectors[i], source->name,
+ source->partition != NULL ? "," : "",
+ part != NULL ? part : N_("UNKNOWN"), dev->uuid);
+ grub_free (part);
+ continue;
+ }
+ else
+ {
+ ret = grub_cryptodisk_insert (dev, name, source);
+ if (ret != GRUB_ERR_NONE)
+ goto error;
+ goto cleanup;
+ }
+ }
- ret = grub_cryptodisk_insert (dev, name, source);
- if (ret != GRUB_ERR_NONE)
+ part = grub_partition_get_name (source->partition);
+ grub_error (GRUB_ERR_ACCESS_DENIED,
+ N_("no key protector provided a usable key for %s%s%s (%s)"),
+ source->name, source->partition != NULL ? "," : "",
+ part != NULL ? part : N_("UNKNOWN"), dev->uuid);
+ grub_free (part);
goto error;
+ }
+
+ if (!cargs->key_len)
+ {
+ /* Get the passphrase from the user, if no key data. */
+ askpass = 1;
+ part = grub_partition_get_name (source->partition);
+ grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
+ source->partition != NULL ? "," : "",
+ part != NULL ? part : N_("UNKNOWN"), dev->uuid);
+ grub_free (part);
+
+ cargs->key_data = grub_malloc (GRUB_CRYPTODISK_MAX_PASSPHRASE);
+ if (cargs->key_data == NULL)
+ goto error;
+
+ if (!grub_password_get ((char *) cargs->key_data, GRUB_CRYPTODISK_MAX_PASSPHRASE))
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "passphrase not supplied");
+ goto error;
+ }
+ cargs->key_len = grub_strlen ((char *) cargs->key_data);
+ }
+
+ ret = cr->recover_key (source, dev, cargs);
+ if (ret != GRUB_ERR_NONE)
+ goto error;
+
+ ret = grub_cryptodisk_insert (dev, name, source);
+ if (ret != GRUB_ERR_NONE)
+ goto error;
- goto cleanup;
- }
- grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk module can handle this device");
goto cleanup;
error:
@@ -1259,6 +1335,20 @@ grub_cryptodisk_scan_device (const char *name,
return ret;
}
+static void
+grub_cryptodisk_clear_key_cache (struct grub_cryptomount_args *cargs)
+{
+ int i;
+
+ if (cargs->key_cache == NULL || cargs->protectors == NULL)
+ return;
+
+ for (i = 0; cargs->protectors[i]; i++)
+ grub_free (cargs->key_cache[i].key);
+
+ grub_free (cargs->key_cache);
+}
+
static grub_err_t
grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
{
@@ -1271,6 +1361,10 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
if (grub_cryptodisk_list == NULL)
return grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk modules loaded");
+ if (state[OPTION_PASSWORD].set && state[OPTION_PROTECTOR].set) /* password and key protector */
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "a password and a key protector cannot both be set");
+
if (state[OPTION_PASSWORD].set) /* password */
{
cargs.key_data = (grub_uint8_t *) state[OPTION_PASSWORD].arg;
@@ -1363,6 +1457,15 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
return grub_errno;
}
+ if (state[OPTION_PROTECTOR].set) /* key protector(s) */
+ {
+ cargs.key_cache = grub_zalloc (state[OPTION_PROTECTOR].set * sizeof (*cargs.key_cache));
+ if (cargs.key_cache == NULL)
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY,
+ "no memory for key protector key cache");
+ cargs.protectors = state[OPTION_PROTECTOR].args;
+ }
+
if (state[OPTION_UUID].set) /* uuid */
{
int found_uuid;
@@ -1371,6 +1474,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
dev = grub_cryptodisk_get_by_uuid (args[0]);
if (dev)
{
+ grub_cryptodisk_clear_key_cache (&cargs);
grub_dprintf ("cryptodisk",
"already mounted as crypto%lu\n", dev->id);
return GRUB_ERR_NONE;
@@ -1379,6 +1483,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
cargs.check_boot = state[OPTION_BOOT].set;
cargs.search_uuid = args[0];
found_uuid = grub_device_iterate (&grub_cryptodisk_scan_device, &cargs);
+ grub_cryptodisk_clear_key_cache (&cargs);
if (found_uuid)
return GRUB_ERR_NONE;
@@ -1398,6 +1503,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
{
cargs.check_boot = state[OPTION_BOOT].set;
grub_device_iterate (&grub_cryptodisk_scan_device, &cargs);
+ grub_cryptodisk_clear_key_cache (&cargs);
return GRUB_ERR_NONE;
}
else
@@ -1421,6 +1527,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
disk = grub_disk_open (diskname);
if (!disk)
{
+ grub_cryptodisk_clear_key_cache (&cargs);
if (disklast)
*disklast = ')';
return grub_errno;
@@ -1431,12 +1538,14 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
{
grub_dprintf ("cryptodisk", "already mounted as crypto%lu\n", dev->id);
grub_disk_close (disk);
+ grub_cryptodisk_clear_key_cache (&cargs);
if (disklast)
*disklast = ')';
return GRUB_ERR_NONE;
}
dev = grub_cryptodisk_scan_device_real (diskname, disk, &cargs);
+ grub_cryptodisk_clear_key_cache (&cargs);
grub_disk_close (disk);
if (disklast)
@@ -1590,6 +1699,7 @@ GRUB_MOD_INIT (cryptodisk)
cmd = grub_register_extcmd ("cryptomount", grub_cmd_cryptomount, 0,
N_("[ [-p password] | [-k keyfile"
" [-O keyoffset] [-S keysize] ] ] [-H file]"
+ " [-P protector [-P protector ...]]"
" <SOURCE|-u UUID|-a|-b>"),
N_("Mount a crypto device."), options);
grub_procfs_register ("luks_script", &luks_script);
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index d94df68b6..0b41e249e 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -70,6 +70,18 @@ typedef gcry_err_code_t
(*grub_cryptodisk_rekey_func_t) (struct grub_cryptodisk *dev,
grub_uint64_t zoneno);
+struct grub_cryptomount_cached_key
+{
+ grub_uint8_t *key;
+ grub_size_t key_len;
+
+ /*
+ * The key protector associated with this cache entry failed, so avoid it
+ * even if the cached entry (an instance of this structure) is empty.
+ */
+ int invalid;
+};
+
struct grub_cryptomount_args
{
/* scan: Flag to indicate that only bootable volumes should be decrypted */
@@ -81,6 +93,10 @@ struct grub_cryptomount_args
/* recover_key: Length of key_data */
grub_size_t key_len;
grub_file_t hdr_file;
+ /* recover_key: Names of the key protectors to use (NULL-terminated) */
+ char **protectors;
+ /* recover_key: Key cache to avoid invoking the same key protector twice */
+ struct grub_cryptomount_cached_key *key_cache;
};
typedef struct grub_cryptomount_args *grub_cryptomount_args_t;
--
2.35.3

View File

@ -0,0 +1,91 @@
From 91a99dffbe78b91a0c18b32ebecf755ba9d74032 Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Thu, 10 Aug 2023 10:19:29 +0800
Subject: [PATCH 4/4] diskfilter: look up cryptodisk devices first
When using disk auto-unlocking with TPM 2.0, the typical grub.cfg may
look like this:
tpm2_key_protector_init --tpm2key=(hd0,gpt1)/boot/grub2/sealed.tpm
cryptomount -u <PART-UUID> -P tpm2
search --fs-uuid --set=root <FS-UUID>
Since the disk search order is based on the order of module loading, the
attacker could insert a malicious disk with the same FS-UUID root to
trick grub2 to boot into the malicious root and further dump memory to
steal the unsealed key.
Do defend against such an attack, we can specify the hint provided by
'grub-probe' to search the encrypted partition first:
search --fs-uuid --set=root --hint='cryptouuid/<PART-UUID>' <FS-UUID>
However, for LVM on an encrypted partition, the search hint provided by
'grub-probe' is:
--hint='lvmid/<VG-UUID>/<LV-UUID>'
It doesn't guarantee to look up the logical volume from the encrypted
partition, so the attacker may have the chance to fool grub2 to boot
into the malicious disk.
To minimize the attack surface, this commit tweaks the disk device search
in diskfilter to look up cryptodisk devices first and then others, so
that the auto-unlocked disk will be found first, not the attacker's disk.
Cc: Fabian Vogt <fvogt@suse.com>
Signed-off-by: Gary Lin <glin@suse.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
---
grub-core/disk/diskfilter.c | 35 ++++++++++++++++++++++++++---------
1 file changed, 26 insertions(+), 9 deletions(-)
diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c
index 41e177549..c45bef1ca 100644
--- a/grub-core/disk/diskfilter.c
+++ b/grub-core/disk/diskfilter.c
@@ -322,15 +322,32 @@ scan_devices (const char *arname)
int need_rescan;
for (pull = 0; pull < GRUB_DISK_PULL_MAX; pull++)
- for (p = grub_disk_dev_list; p; p = p->next)
- if (p->id != GRUB_DISK_DEVICE_DISKFILTER_ID
- && p->disk_iterate)
- {
- if ((p->disk_iterate) (scan_disk_hook, NULL, pull))
- return;
- if (arname && is_lv_readable (find_lv (arname), 1))
- return;
- }
+ {
+ /* look up the crytodisk devices first */
+ for (p = grub_disk_dev_list; p; p = p->next)
+ if (p->id == GRUB_DISK_DEVICE_CRYPTODISK_ID
+ && p->disk_iterate)
+ {
+ if ((p->disk_iterate) (scan_disk_hook, NULL, pull))
+ return;
+ if (arname && is_lv_readable (find_lv (arname), 1))
+ return;
+ break;
+ }
+
+ /* check the devices other than crytodisk */
+ for (p = grub_disk_dev_list; p; p = p->next)
+ if (p->id == GRUB_DISK_DEVICE_CRYPTODISK_ID)
+ continue;
+ else if (p->id != GRUB_DISK_DEVICE_DISKFILTER_ID
+ && p->disk_iterate)
+ {
+ if ((p->disk_iterate) (scan_disk_hook, NULL, pull))
+ return;
+ if (arname && is_lv_readable (find_lv (arname), 1))
+ return;
+ }
+ }
scan_depth = 0;
need_rescan = 1;
--
2.35.3

View File

@ -0,0 +1,116 @@
From ca482c7c1efe5faf792bf0912a116ea8e0642e24 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Wed, 15 Apr 2015 14:48:30 +0800
Subject: [PATCH 4/8] efinet: UEFI IPv6 PXE support
When grub2 image is booted from UEFI IPv6 PXE, the DHCPv6 Reply packet is
cached in firmware buffer which can be obtained by PXE Base Code protocol. The
network interface can be setup through the parameters in that obtained packet.
Signed-off-by: Michael Chang <mchang@suse.com>
Signed-off-by: Ken Lin <ken.lin@hpe.com>
---
grub-core/net/drivers/efi/efinet.c | 24 +++++++++++++----
include/grub/efi/api.h | 55 +++++++++++++++++++++++++++++++++++++-
2 files changed, 73 insertions(+), 6 deletions(-)
--- a/grub-core/net/drivers/efi/efinet.c
+++ b/grub-core/net/drivers/efi/efinet.c
@@ -400,6 +400,18 @@
continue;
pxe_mode = pxe->mode;
+ if (pxe_mode->using_ipv6)
+ {
+ grub_net_configure_by_dhcpv6_reply (card->name, card, 0,
+ (struct grub_net_dhcp6_packet *)
+ &pxe_mode->dhcp_ack,
+ sizeof (pxe_mode->dhcp_ack),
+ 1, device, path);
+ if (grub_errno)
+ grub_print_error ();
+ }
+ else
+ {
inter = grub_net_configure_by_dhcp_ack (card->name, card, 0,
(struct grub_net_bootp_packet *)
&pxe_mode->dhcp_ack,
@@ -428,6 +440,7 @@
vlan_dp = (grub_efi_device_path_t *) ((grub_efi_uint8_t *) vlan_dp + vlan_dp_len);
}
}
+ }
return;
}
}
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -1523,14 +1523,67 @@
typedef grub_uint8_t grub_efi_pxe_packet_t[1472];
+typedef struct {
+ grub_uint8_t addr[4];
+} grub_efi_pxe_ipv4_address_t;
+
+typedef struct {
+ grub_uint8_t addr[16];
+} grub_efi_pxe_ipv6_address_t;
+
+typedef struct {
+ grub_uint8_t addr[32];
+} grub_efi_pxe_mac_address_t;
+
+typedef union {
+ grub_uint32_t addr[4];
+ grub_efi_pxe_ipv4_address_t v4;
+ grub_efi_pxe_ipv6_address_t v6;
+} grub_efi_pxe_ip_address_t;
+
+#define GRUB_EFI_PXE_BASE_CODE_MAX_IPCNT 8
+typedef struct {
+ grub_uint8_t filters;
+ grub_uint8_t ip_cnt;
+ grub_uint16_t reserved;
+ grub_efi_pxe_ip_address_t ip_list[GRUB_EFI_PXE_BASE_CODE_MAX_IPCNT];
+} grub_efi_pxe_ip_filter_t;
+
+typedef struct {
+ grub_efi_pxe_ip_address_t ip_addr;
+ grub_efi_pxe_mac_address_t mac_addr;
+} grub_efi_pxe_arp_entry_t;
+
+typedef struct {
+ grub_efi_pxe_ip_address_t ip_addr;
+ grub_efi_pxe_ip_address_t subnet_mask;
+ grub_efi_pxe_ip_address_t gw_addr;
+} grub_efi_pxe_route_entry_t;
+
+
+#define GRUB_EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES 8
+#define GRUB_EFI_PXE_BASE_CODE_MAX_ROUTE_ENTRIES 8
+
typedef struct grub_efi_pxe_mode
{
- grub_uint8_t unused[52];
+ grub_uint8_t started;
+ grub_uint8_t ipv6_available;
+ grub_uint8_t ipv6_supported;
+ grub_uint8_t using_ipv6;
+ grub_uint8_t unused[16];
+ grub_efi_pxe_ip_address_t station_ip;
+ grub_efi_pxe_ip_address_t subnet_mask;
grub_efi_pxe_packet_t dhcp_discover;
grub_efi_pxe_packet_t dhcp_ack;
grub_efi_pxe_packet_t proxy_offer;
grub_efi_pxe_packet_t pxe_discover;
grub_efi_pxe_packet_t pxe_reply;
+ grub_efi_pxe_packet_t pxe_bis_reply;
+ grub_efi_pxe_ip_filter_t ip_filter;
+ grub_uint32_t arp_cache_entries;
+ grub_efi_pxe_arp_entry_t arp_cache[GRUB_EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES];
+ grub_uint32_t route_table_entries;
+ grub_efi_pxe_route_entry_t route_table[GRUB_EFI_PXE_BASE_CODE_MAX_ROUTE_ENTRIES];
} grub_efi_pxe_mode_t;
typedef struct grub_efi_pxe

View File

@ -0,0 +1,28 @@
From 7717cd9c27f18703287403af1a955588e3d0261f Mon Sep 17 00:00:00 2001
From: mamatha <mainamdar@in.ibm.com>
Date: Sat, 24 Sep 2022 11:22:39 +0530
Subject: [PATCH 4/4] ofpath controller name update
patch to update ofpath controller name
Signed-off-by: mamatha <mainamdar@in.ibm.com>
---
grub-core/osdep/linux/ofpath.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c
index 212782d3f..7d31cfd0f 100644
--- a/grub-core/osdep/linux/ofpath.c
+++ b/grub-core/osdep/linux/ofpath.c
@@ -483,6 +483,8 @@ of_path_get_nvmeof_adapter_info(char* sysfs_path,
buf3=strchr(buf2,'-')+1;
buf3=strchr(buf3,'-')+1;
nvmeof_info->target_wwpn = buf3;
+ buf3=strchr(buf3,'x')+1;
+ nvmeof_info->target_wwpn = buf3;
buf3 = strchr(nvmeof_info->target_wwpn,',');
*buf3 = '\0';
--
2.35.3

View File

@ -0,0 +1,121 @@
From 6d33393fd3c538aaead2698777c02d6d6d0221c9 Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Tue, 7 Mar 2023 18:59:40 -0500
Subject: [PATCH 5/9] blscfg: check for mounted /boot in emu
Irritatingly, BLS defines paths relatives to the mountpoint of the
filesystem which contains its snippets, not / or any other fixed
location. So grub2-emu needs to know whether /boot is a separate
filesysem from / and conditionally prepend a path.
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
---
grub-core/commands/blscfg.c | 54 +++++++++++++++++++++++++++++++++----
1 file changed, 49 insertions(+), 5 deletions(-)
diff --git a/grub-core/commands/blscfg.c b/grub-core/commands/blscfg.c
index 150ca96f4..6495891b9 100644
--- a/grub-core/commands/blscfg.c
+++ b/grub-core/commands/blscfg.c
@@ -40,8 +40,9 @@ GRUB_MOD_LICENSE ("GPLv3+");
#include "loadenv.h"
#define GRUB_BLS_CONFIG_PATH "/loader/entries/"
+
#ifdef GRUB_MACHINE_EMU
-#define GRUB_BOOT_DEVICE ""
+#define GRUB_BOOT_DEVICE "/boot"
#else
#define GRUB_BOOT_DEVICE "($root)"
#endif
@@ -54,8 +55,50 @@ struct keyval
static struct bls_entry *entries = NULL;
+/* Cache probing in frob_boot_device(). Used for linux entry also.
+ * Always true in non-emu, meaning to prefix things with GRUB_BOOT_DEVICE. */
+static int separate_boot = -1;
+
#define FOR_BLS_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 *frob_boot_device(char *tmp)
+{
+#ifdef GRUB_MACHINE_EMU
+ grub_file_t f;
+ char *line = NULL;
+
+ if (separate_boot != -1)
+ goto probed;
+
+ separate_boot = 0;
+
+ f = grub_file_open ("/proc/mounts", GRUB_FILE_TYPE_CONFIG);
+ if (f == NULL)
+ goto probed;
+
+ while ((line = grub_file_getline (f)))
+ {
+ if (grub_strstr (line, " " GRUB_BOOT_DEVICE " "))
+ {
+ separate_boot = 1;
+ grub_free (line);
+ break;
+ }
+
+ grub_free(line);
+ }
+
+ grub_file_close (f);
+ probed:
+ if (!separate_boot)
+ return grub_stpcpy (tmp, " ");
+#endif
+
+ return grub_stpcpy (tmp, " " GRUB_BOOT_DEVICE);
+}
+
static int bls_add_keyval(struct bls_entry *entry, char *key, char *val)
{
char *k, *v;
@@ -842,7 +885,7 @@ static void create_entry (struct bls_entry *entry)
for (i = 0; early_initrds != NULL && early_initrds[i] != NULL; i++)
{
grub_dprintf ("blscfg", "adding early initrd %s\n", early_initrds[i]);
- tmp = grub_stpcpy (tmp, " " GRUB_BOOT_DEVICE);
+ tmp = frob_boot_device (tmp);
tmp = grub_stpcpy (tmp, initrd_prefix);
tmp = grub_stpcpy (tmp, early_initrds[i]);
grub_free(early_initrds[i]);
@@ -851,7 +894,7 @@ static void create_entry (struct bls_entry *entry)
for (i = 0; initrds != NULL && initrds[i] != NULL; i++)
{
grub_dprintf ("blscfg", "adding initrd %s\n", initrds[i]);
- tmp = grub_stpcpy (tmp, " " GRUB_BOOT_DEVICE);
+ tmp = frob_boot_device (tmp);
tmp = grub_stpcpy (tmp, initrds[i]);
}
tmp = grub_stpcpy (tmp, "\n");
@@ -888,7 +931,7 @@ static void create_entry (struct bls_entry *entry)
}
char *tmp = dt;
tmp = grub_stpcpy (dt, "devicetree");
- tmp = grub_stpcpy (tmp, " " GRUB_BOOT_DEVICE);
+ tmp = frob_boot_device (tmp);
if (add_dt_prefix)
tmp = grub_stpcpy (tmp, prefix);
tmp = grub_stpcpy (tmp, devicetree);
@@ -907,7 +950,8 @@ static void create_entry (struct bls_entry *entry)
"linux %s%s%s%s\n"
"%s%s",
savedefault ? "savedefault\n" : "",
- GRUB_BOOT_DEVICE, clinux, options ? " " : "", options ? options : "",
+ separate_boot ? GRUB_BOOT_DEVICE : "",
+ clinux, options ? " " : "", options ? options : "",
initrd ? initrd : "", dt ? dt : "");
grub_normal_add_menu_entry (argc, argv, classes, id, users, hotkey, NULL, src, 0, 0, &index, entry);
--
2.44.0

View File

@ -0,0 +1,59 @@
From f7b9580133cf346d77f345d175fa5cb8a591be16 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <dja@axtens.net>
Date: Sat, 15 Aug 2020 02:00:57 +1000
Subject: [PATCH 05/23] docs/grub: Document signing grub under UEFI
Before adding information about how grub is signed with an appended
signature scheme, it's worth adding some information about how it
can currently be signed for UEFI.
Signed-off-by: Daniel Axtens <dja@axtens.net>
---
docs/grub.texi | 22 +++++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -6345,6 +6345,7 @@
* Secure Boot Advanced Targeting:: Embedded information for generation number based revocation
* Measured Boot:: Measuring boot components
* Lockdown:: Lockdown when booting on a secure setup
+* Signing GRUB itself:: Ensuring the integrity of the GRUB core image
@end menu
@node Authentication and authorisation
@@ -6423,7 +6424,7 @@
GRUB's @file{core.img} can optionally provide enforcement that all files
subsequently read from disk are covered by a valid digital signature.
-This document does @strong{not} cover how to ensure that your
+This section does @strong{not} cover how to ensure that your
platform's firmware (e.g., Coreboot) validates @file{core.img}.
If environment variable @code{check_signatures}
@@ -6586,6 +6587,25 @@
The @samp{lockdown} variable is set to @samp{y} when the GRUB is locked down.
Otherwise it does not exit.
+@node Signing GRUB itself
+@section Signing GRUB itself
+
+To ensure a complete secure-boot chain, there must be a way for the code that
+loads GRUB to verify the integrity of the core image.
+
+This is ultimately platform-specific and individual platforms can define their
+own mechanisms. However, there are general-purpose mechanisms that can be used
+with GRUB.
+
+@section Signing GRUB for UEFI secure boot
+
+On UEFI platforms, @file{core.img} is a PE binary. Therefore, it can be signed
+with a tool such as @command{pesign} or @command{sbsign}. Refer to the
+suggestions in @pxref{UEFI secure boot and shim} to ensure that the final
+image works under UEFI secure boot and can maintain the secure-boot chain. It
+will also be necessary to enrol the public key used into a relevant firmware
+key database.
+
@node Platform limitations
@chapter Platform limitations

View File

@ -0,0 +1,164 @@
From 496b6b20cbce3fc27228d1d8290089fb7107b8de Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 18 Feb 2022 21:51:16 +0800
Subject: [PATCH 5/5] export environment at start up
If the prep_loadenv module is built into the core image, it will read
the environment block automatically during start up and export all
variables. The will ease integration with those without early scripts to
running the command.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/Makefile.core.def | 2 +
grub-core/commands/prep_loadenv.c | 77 +++++++++++++++++++++++++++++++
grub-core/kern/env.c | 2 +
grub-core/kern/main.c | 3 ++
include/grub/env.h | 1 +
5 files changed, 85 insertions(+)
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2678,4 +2678,6 @@
name = prep_loadenv;
common = commands/prep_loadenv.c;
enable = powerpc_ieee1275;
+ cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)';
+ cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB)';
};
--- a/grub-core/commands/prep_loadenv.c
+++ b/grub-core/commands/prep_loadenv.c
@@ -10,6 +10,7 @@
#include <grub/extcmd.h>
#include <grub/i18n.h>
#include <grub/gpt_partition.h>
+#include <regex.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -185,6 +186,65 @@
}
static grub_err_t
+boot_disk_prep_partname (char **name)
+{
+ regex_t regex;
+ int ret;
+ grub_size_t s;
+ char *comperr;
+ const char *cmdpath;
+ regmatch_t *matches = NULL;
+ grub_err_t err = GRUB_ERR_NONE;
+
+ *name = NULL;
+
+ cmdpath = grub_env_get ("cmdpath");
+ if (!cmdpath)
+ return GRUB_ERR_NONE;
+
+ ret = regcomp (&regex, "\\(([^,]+)(,?.*)?\\)(.*)", REG_EXTENDED);
+ if (ret)
+ goto fail;
+
+ matches = grub_calloc (regex.re_nsub + 1, sizeof (*matches));
+ if (! matches)
+ goto fail;
+
+ ret = regexec (&regex, cmdpath, regex.re_nsub + 1, matches, 0);
+ if (!ret)
+ {
+ char *devname = devname = match_substr (matches + 1, cmdpath);
+ if (!devname)
+ {
+ err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "%s contains no disk name", cmdpath);
+ goto out;
+ }
+
+ err = prep_partname (devname, name);
+ out:
+ grub_free (devname);
+ regfree (&regex);
+ grub_free (matches);
+ return err;
+ }
+
+ fail:
+ grub_free (matches);
+ s = regerror (ret, &regex, 0, 0);
+ comperr = grub_malloc (s);
+ if (!comperr)
+ {
+ regfree (&regex);
+ return grub_errno;
+ }
+ regerror (ret, &regex, comperr, s);
+ err = grub_error (GRUB_ERR_TEST_FAILURE, "%s", comperr);
+ regfree (&regex);
+ grub_free (comperr);
+ return err;
+}
+
+static grub_err_t
grub_cmd_prep_loadenv (grub_command_t cmd __attribute__ ((unused)),
int argc,
char **argv)
@@ -214,10 +274,27 @@
return GRUB_ERR_NONE;
}
+static void
+early_prep_loadenv (void)
+{
+ grub_err_t err;
+ char *prep;
+
+ err = boot_disk_prep_partname (&prep);
+ if (err == GRUB_ERR_NONE && prep)
+ err = prep_read_envblk (prep);
+ if (err == GRUB_ERR_BAD_FILE_TYPE || err == GRUB_ERR_FILE_NOT_FOUND)
+ grub_error_pop ();
+ if (err != GRUB_ERR_NONE)
+ grub_print_error ();
+ grub_free (prep);
+}
+
static grub_command_t cmd_prep_load;
GRUB_MOD_INIT(prep_loadenv)
{
+ early_env_hook = early_prep_loadenv;
cmd_prep_load =
grub_register_command("prep_load_env", grub_cmd_prep_loadenv,
"DEVICE",
--- a/grub-core/kern/env.c
+++ b/grub-core/kern/env.c
@@ -28,6 +28,8 @@
/* The current context. */
struct grub_env_context *grub_current_context = &initial_context;
+void (*early_env_hook) (void) = NULL;
+
/* Return the hash representation of the string S. */
static unsigned int
grub_env_hashval (const char *s)
--- a/grub-core/kern/main.c
+++ b/grub-core/kern/main.c
@@ -309,6 +309,9 @@
grub_boot_time ("Before execution of embedded config.");
+ if (early_env_hook != NULL)
+ early_env_hook ();
+
if (load_config)
grub_parser_execute (load_config);
--- a/include/grub/env.h
+++ b/include/grub/env.h
@@ -69,5 +69,6 @@
grub_err_t
grub_env_extractor_close (int source);
+extern void (*EXPORT_VAR (early_env_hook)) (void);
#endif /* ! GRUB_ENV_HEADER */

View File

@ -0,0 +1,48 @@
From 2c997c8c058b41d3a59a81f2bf654288b7cdf8f2 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Tue, 5 May 2015 14:19:24 +0800
Subject: [PATCH 5/8] grub.texi: Add net_bootp6 doument
Update grub documentation for net_bootp6 command.
Signed-off-by: Michael Chang <mchang@suse.com>
Signed-off-by: Ken Lin <ken.lin@hpe.com>
---
docs/grub.texi | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -5894,6 +5894,7 @@
* net_add_dns:: Add a DNS server
* net_add_route:: Add routing entry
* net_bootp:: Perform a bootp/DHCP autoconfiguration
+* net_bootp6:: Perform a DHCPv6 autoconfiguration
* net_del_addr:: Remove IP address from interface
* net_del_dns:: Remove a DNS server
* net_del_route:: Remove a route entry
@@ -5951,6 +5952,24 @@
@end deffn
+
+@node net_bootp6
+@subsection net_bootp6
+
+@deffn Command net_bootp6 [@var{card}]
+Perform configuration of @var{card} using DHCPv6 protocol. If no card name is
+specified, try to configure all existing cards. If configuration was
+successful, interface with name @var{card}@samp{:dhcp6} and configured address
+is added to @var{card}.
+
+@table @samp
+@item 1 (Domain Name Server)
+Adds all servers from option value to the list of servers used during name
+resolution.
+@end table
+
+@end deffn
+
@node net_del_addr
@subsection net_del_addr

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,105 @@
From a33acb675fe0d0464637175e4f06176e4c329025 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Fri, 12 Jul 2019 09:53:32 +0200
Subject: [PATCH 05/11] x86-efi: Use bounce buffers for reading to addresses >
4GB
Lots of machines apparently can't DMA correctly above 4GB during UEFI,
so use bounce buffers for the initramfs read.
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/loader/i386/efi/linux.c | 52 ++++++++++++++++++++++++++-----
1 file changed, 45 insertions(+), 7 deletions(-)
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
index f3abbd025..d6bed4fb4 100644
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -35,11 +35,16 @@ static grub_dl_t my_mod;
static int loaded;
static void *kernel_mem;
static grub_uint64_t kernel_size;
-static grub_uint8_t *initrd_mem;
+static void *initrd_mem;
static grub_uint32_t handover_offset;
struct linux_kernel_params *params;
static char *linux_cmdline;
+#define MIN(a, b) \
+ ({ typeof (a) _a = (a); \
+ typeof (b) _b = (b); \
+ _a < _b ? _a : _b; })
+
#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12)
static grub_err_t
@@ -68,6 +73,44 @@ grub_linuxefi_unload (void)
return GRUB_ERR_NONE;
}
+#define BOUNCE_BUFFER_MAX 0x10000000ull
+
+static grub_ssize_t
+read(grub_file_t file, grub_uint8_t *bufp, grub_size_t len)
+{
+ grub_ssize_t bufpos = 0;
+ static grub_size_t bbufsz = 0;
+ static char *bbuf = NULL;
+
+ if (bbufsz == 0)
+ bbufsz = MIN(BOUNCE_BUFFER_MAX, len);
+
+ while (!bbuf && bbufsz)
+ {
+ bbuf = grub_malloc(bbufsz);
+ if (!bbuf)
+ bbufsz >>= 1;
+ }
+ if (!bbuf)
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate bounce buffer"));
+
+ while (bufpos < (long long)len)
+ {
+ grub_ssize_t sz;
+
+ sz = grub_file_read (file, bbuf, MIN(bbufsz, len - bufpos));
+ if (sz < 0)
+ return sz;
+ if (sz == 0)
+ break;
+
+ grub_memcpy(bufp + bufpos, bbuf, sz);
+ bufpos += sz;
+ }
+
+ return bufpos;
+}
+
static grub_err_t
grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
@@ -120,7 +163,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
for (i = 0; i < nfiles; i++)
{
grub_ssize_t cursize = grub_file_size (files[i]);
- if (grub_file_read (files[i], ptr, cursize) != cursize)
+ if (read (files[i], ptr, cursize) != cursize)
{
if (!grub_errno)
grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
@@ -145,11 +188,6 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
return grub_errno;
}
-#define MIN(a, b) \
- ({ typeof (a) _a = (a); \
- typeof (b) _b = (b); \
- _a < _b ? _a : _b; })
-
static grub_err_t
grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
--
2.31.1

View File

@ -0,0 +1,168 @@
From 6523d493b0772316a3fbb249eb070ada5d266a98 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Wed, 28 Jun 2023 14:32:40 +0800
Subject: [PATCH 6/9] Follow the device where blscfg is discovered
Previously, the code assumed that GRUB_BOOT_DEVICE "($root)" was always
the correct device for the discovered bls menu. However, this assumption
could lead to inaccuracies when attempting to load bls for devices other
than $root.
This patch introduces a more robust approach by utilizing the `struct
find_entry_info *info->devid` parameter, representing the device used to
discover the bls directory. This change ensures consistency in
subsequent translations to native GRUB commands, eliminating potential
discrepancies in device identification during the blscfg process.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/commands/blscfg.c | 40 +++++++++++++++++++++++++------------
include/grub/menu.h | 1 +
2 files changed, 28 insertions(+), 13 deletions(-)
diff --git a/grub-core/commands/blscfg.c b/grub-core/commands/blscfg.c
index 6495891b9..c872bcef0 100644
--- a/grub-core/commands/blscfg.c
+++ b/grub-core/commands/blscfg.c
@@ -55,15 +55,18 @@ struct keyval
static struct bls_entry *entries = NULL;
-/* Cache probing in frob_boot_device(). Used for linux entry also.
- * Always true in non-emu, meaning to prefix things with GRUB_BOOT_DEVICE. */
-static int separate_boot = -1;
-
#define FOR_BLS_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 *frob_boot_device(char *tmp)
+#ifdef GRUB_MACHINE_EMU
+/* Cache probing in frob_boot_device(). Used for linux entry also.
+ * Unused in non-emu, meaning to prefix things with device of parent blsdir. */
+static int separate_boot = -1;
+static char *frob_boot_device(char *tmp, const char *bootdev UNUSED)
+#else
+static char *frob_boot_device(char *tmp, const char *bootdev)
+#endif
{
#ifdef GRUB_MACHINE_EMU
grub_file_t f;
@@ -94,9 +97,11 @@ static char *frob_boot_device(char *tmp)
probed:
if (!separate_boot)
return grub_stpcpy (tmp, " ");
-#endif
-
return grub_stpcpy (tmp, " " GRUB_BOOT_DEVICE);
+#else
+ tmp = grub_stpcpy (tmp, " ");
+ return grub_stpcpy (tmp, bootdev);
+#endif
}
static int bls_add_keyval(struct bls_entry *entry, char *key, char *val)
@@ -568,6 +573,9 @@ static int read_entry (
if (rc < 0)
break;
}
+
+ if (info->devid)
+ entry->devid = grub_strdup(info->devid);
if (!rc)
bls_add_entry(entry);
@@ -772,6 +780,7 @@ static void create_entry (struct bls_entry *entry)
char *id = entry->filename;
char *dotconf = id;
char *hotkey = NULL;
+ char *bootdev = entry->devid ? grub_xasprintf("(%s)", entry->devid) : grub_strdup (GRUB_BOOT_DEVICE);
char *users = NULL;
char **classes = NULL;
@@ -865,12 +874,12 @@ static void create_entry (struct bls_entry *entry)
char *tmp;
for (i = 0; early_initrds != NULL && early_initrds[i] != NULL; i++)
- initrd_size += sizeof (" " GRUB_BOOT_DEVICE) \
+ initrd_size += sizeof (" ") + grub_strlen (bootdev) \
+ grub_strlen(initrd_prefix) \
+ grub_strlen (early_initrds[i]) + 1;
for (i = 0; initrds != NULL && initrds[i] != NULL; i++)
- initrd_size += sizeof (" " GRUB_BOOT_DEVICE) \
+ initrd_size += sizeof (" ") + grub_strlen (bootdev) \
+ grub_strlen (initrds[i]) + 1;
initrd_size += 1;
@@ -885,7 +894,7 @@ static void create_entry (struct bls_entry *entry)
for (i = 0; early_initrds != NULL && early_initrds[i] != NULL; i++)
{
grub_dprintf ("blscfg", "adding early initrd %s\n", early_initrds[i]);
- tmp = frob_boot_device (tmp);
+ tmp = frob_boot_device (tmp, bootdev);
tmp = grub_stpcpy (tmp, initrd_prefix);
tmp = grub_stpcpy (tmp, early_initrds[i]);
grub_free(early_initrds[i]);
@@ -894,7 +903,7 @@ static void create_entry (struct bls_entry *entry)
for (i = 0; initrds != NULL && initrds[i] != NULL; i++)
{
grub_dprintf ("blscfg", "adding initrd %s\n", initrds[i]);
- tmp = frob_boot_device (tmp);
+ tmp = frob_boot_device (tmp, bootdev);
tmp = grub_stpcpy (tmp, initrds[i]);
}
tmp = grub_stpcpy (tmp, "\n");
@@ -916,7 +925,7 @@ static void create_entry (struct bls_entry *entry)
}
}
- dt_size = sizeof("devicetree " GRUB_BOOT_DEVICE) + grub_strlen(devicetree) + 1;
+ dt_size = sizeof("devicetree ") + grub_strlen(bootdev) + grub_strlen(devicetree) + 1;
if (add_dt_prefix)
{
@@ -931,7 +940,7 @@ static void create_entry (struct bls_entry *entry)
}
char *tmp = dt;
tmp = grub_stpcpy (dt, "devicetree");
- tmp = frob_boot_device (tmp);
+ tmp = frob_boot_device (tmp, bootdev);
if (add_dt_prefix)
tmp = grub_stpcpy (tmp, prefix);
tmp = grub_stpcpy (tmp, devicetree);
@@ -950,7 +959,11 @@ static void create_entry (struct bls_entry *entry)
"linux %s%s%s%s\n"
"%s%s",
savedefault ? "savedefault\n" : "",
+#ifdef GRUB_MACHINE_EMU
separate_boot ? GRUB_BOOT_DEVICE : "",
+#else
+ bootdev,
+#endif
clinux, options ? " " : "", options ? options : "",
initrd ? initrd : "", dt ? dt : "");
@@ -969,6 +982,7 @@ finish:
grub_free (args);
grub_free (argv);
grub_free (src);
+ grub_free (bootdev);
}
struct find_entry_info {
diff --git a/include/grub/menu.h b/include/grub/menu.h
index 43080828c..76b191c33 100644
--- a/include/grub/menu.h
+++ b/include/grub/menu.h
@@ -28,6 +28,7 @@ struct bls_entry
int nkeyvals;
char *filename;
int visible;
+ const char *devid;
};
struct grub_menu_entry_class
--
2.44.0

View File

@ -0,0 +1,98 @@
From 8191aae462f8b755972a0a801f4adbdd6ecaa66c Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 14 Jul 2016 18:45:14 +0800
Subject: [PATCH 6/8] bootp: Add processing DHCPACK packet from HTTP Boot
The vendor class identifier with the string "HTTPClient" is used to denote the
packet as responding to HTTP boot request. In DHCP4 config, the filename for
HTTP boot is the URL of the boot file while for PXE boot it is the path to the
boot file. As a consequence, the next-server becomes obseleted because the HTTP
URL already contains the server address for the boot file. For DHCP6 config,
there's no difference definition in existing config as dhcp6.bootfile-url can
be used to specify URL for both HTTP and PXE boot file.
This patch adds processing for "HTTPClient" vendor class identifier in DHCPACK
packet by treating it as HTTP format, not as the PXE format.
Signed-off-by: Michael Chang <mchang@suse.com>
Signed-off-by: Ken Lin <ken.lin@hpe.com>
---
grub-core/net/bootp.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++--
include/grub/net.h | 1 +
2 files changed, 66 insertions(+), 2 deletions(-)
--- a/grub-core/net/bootp.c
+++ b/grub-core/net/bootp.c
@@ -352,6 +352,53 @@
if (!inter)
return 0;
+ /* FIXME: Introduce new http flag for better synergy with existing tftp code base */
+ if (size > OFFSET_OF (vendor, bp))
+ {
+ char *cidvar;
+ const char *cid;
+
+ opt = find_dhcp_option (bp, size, GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER, &opt_len);
+ if (opt && opt_len)
+ grub_env_set_net_property (name, "vendor_class_identifier", (const char *) opt, opt_len);
+ cidvar = grub_xasprintf ("net_%s_%s", name, "vendor_class_identifier");
+ cid = grub_env_get (cidvar);
+ grub_free (cidvar);
+
+ if (cid && grub_strcmp (cid, "HTTPClient") == 0)
+ {
+ char *proto, *ip, *pa;
+
+ /* FIXME: Provide better URL function that returns in place pointers
+ * so that we don't have to free them.
+ */
+ if (!dissect_url (bp->boot_file, &proto, &ip, &pa))
+ return inter;
+
+ if (is_def)
+ {
+ grub_net_default_server = grub_strdup (ip);
+ grub_env_set ("net_default_interface", name);
+ grub_env_export ("net_default_interface");
+ }
+ if (device && !*device)
+ {
+ *device = grub_xasprintf ("%s,%s", proto, ip);
+ grub_print_error ();
+ }
+
+ boot_file = pa;
+ boot_file_len = grub_strlen (pa);
+
+ /* FIXME: Don't use malloc buffer here */
+ grub_free (proto);
+ grub_free (ip);
+
+ /* FIXME: NEED TO FREE boot_file */
+ goto boot_file;
+ }
+ }
+
opt = find_dhcp_option (bp, size, GRUB_NET_DHCP_OVERLOAD, &opt_len);
if (opt && opt_len == 1)
overload = *opt;
@@ -428,6 +475,8 @@
}
}
+boot_file:
+
if (boot_file)
{
grub_env_set_net_property (name, "boot_file", boot_file, boot_file_len);
--- a/include/grub/net.h
+++ b/include/grub/net.h
@@ -530,6 +530,7 @@
GRUB_NET_DHCP_MESSAGE_TYPE = 53,
GRUB_NET_DHCP_SERVER_IDENTIFIER = 54,
GRUB_NET_DHCP_PARAMETER_REQUEST_LIST = 55,
+ GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER = 60,
GRUB_NET_BOOTP_CLIENT_ID = 61,
GRUB_NET_DHCP_TFTP_SERVER_NAME = 66,
GRUB_NET_DHCP_BOOTFILE_NAME = 67,

View File

@ -0,0 +1,66 @@
From ac539a315495792cd75fe8ab1c474f26e0a78852 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <dja@axtens.net>
Date: Sat, 15 Aug 2020 02:19:36 +1000
Subject: [PATCH 06/23] docs/grub: Document signing grub with an appended
signature
Signing grub for firmware that verifies an appended signature is a
bit fiddly. I don't want people to have to figure it out from scratch
so document it here.
Signed-off-by: Daniel Axtens <dja@axtens.net>
---
docs/grub.texi | 42 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -6606,6 +6606,48 @@
will also be necessary to enrol the public key used into a relevant firmware
key database.
+@section Signing GRUB with an appended signature
+
+The @file{core.img} itself can be signed with a Linux kernel module-style
+appended signature.
+
+To support IEEE1275 platforms where the boot image is often loaded directly
+from a disk partition rather than from a file system, the @file{core.img}
+can specify the size and location of the appended signature with an ELF
+note added by @command{grub-install}.
+
+An image can be signed this way using the @command{sign-file} command from
+the Linux kernel:
+
+@example
+@group
+# grub.key is your private key and certificate.der is your public key
+
+# Determine the size of the appended signature. It depends on the signing
+# certificate and the hash algorithm
+touch empty
+sign-file SHA256 grub.key certificate.der empty empty.sig
+SIG_SIZE=`stat -c '%s' empty.sig`
+rm empty empty.sig
+
+# Build a grub image with $SIG_SIZE reserved for the signature
+grub-install --appended-signature-size $SIG_SIZE --modules="..." ...
+
+# Replace the reserved size with a signature:
+# cut off the last $SIG_SIZE bytes with truncate's minus modifier
+truncate -s -$SIG_SIZE /boot/grub/powerpc-ieee1275/core.elf core.elf.unsigned
+# sign the trimmed file with an appended signature, restoring the correct size
+sign-file SHA256 grub.key certificate.der core.elf.unsigned core.elf.signed
+
+# Don't forget to install the signed image as required
+# (e.g. on powerpc-ieee1275, to the PReP partition)
+@end group
+@end example
+
+As with UEFI secure boot, it is necessary to build in the required modules,
+or sign them separately.
+
+
@node Platform limitations
@chapter Platform limitations

View File

@ -0,0 +1,59 @@
From 3741c6807923ae97b0d87e61c59c8de8af544484 Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
Date: Thu, 23 Apr 2020 15:06:46 +0200
Subject: [PATCH 6/9] efi: Set image base address before jumping to the PE/COFF
entry point
Upstream GRUB uses the EFI LoadImage() and StartImage() to boot the Linux
kernel. But our custom EFI loader that supports Secure Boot instead uses
the EFI handover protocol (for x86) or jumping directly to the PE/COFF
entry point (for aarch64).
This is done to allow the bootloader to verify the images using the shim
lock protocol to avoid booting untrusted binaries.
Since the bootloader loads the kernel from the boot media instead of using
LoadImage(), it is responsible to set the Loaded Image base address before
booting the kernel.
Otherwise the kernel EFI stub will complain that it was not set correctly
and print the following warning message:
EFI stub: ERROR: FIRMWARE BUG: efi_loaded_image_t::image_base has bogus value
Resolves: rhbz#1825411
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
---
grub-core/loader/arm64/efi/linux.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
Index: grub-2.06~rc1/grub-core/loader/arm64/efi/linux.c
===================================================================
--- grub-2.06~rc1.orig/grub-core/loader/arm64/efi/linux.c
+++ grub-2.06~rc1/grub-core/loader/arm64/efi/linux.c
@@ -58,9 +58,24 @@ static grub_err_t
grub_efi_linux_boot (void *kernel_address, grub_off_t offset,
void *kernel_params)
{
+ grub_efi_loaded_image_t *loaded_image = NULL;
handover_func hf;
+ /*
+ * Since the EFI loader is not calling the LoadImage() and StartImage()
+ * services for loading the kernel and booting respectively, it has to
+ * set the Loaded Image base address.
+ */
+ loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
+ if (loaded_image)
+ loaded_image->image_base = kernel_addr;
+ else
+ grub_dprintf ("linux", "Loaded Image base address could not be set\n");
+
+ grub_dprintf ("linux", "kernel_addr: %p handover_offset: %p params: %p\n",
+ kernel_address, (void *)(grub_efi_uintn_t)offset, kernel_params);
hf = (handover_func)((char *)kernel_address + offset);
+ grub_dprintf ("linux", "handover_func() = %p\n", hf);
hf (grub_efi_image_handle, grub_efi_system_table, kernel_params);
return GRUB_ERR_BUG;

View File

@ -0,0 +1,133 @@
From 24b5c0a3788c5c02b72ea61312f5cf8c39429db1 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 13 Sep 2018 14:42:34 -0400
Subject: [PATCH 06/11] x86-efi: Re-arrange grub_cmd_linux() a little bit.
This just helps the next patch be easier to read.
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/loader/i386/efi/linux.c | 73 +++++++++++++++++--------------
1 file changed, 40 insertions(+), 33 deletions(-)
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
index d6bed4fb4..096a52eb5 100644
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -227,32 +227,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
- params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS,
- BYTES_TO_PAGES(sizeof(*params)));
- if (!params)
- params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS,
- BYTES_TO_PAGES(sizeof(*params)));
- if (! params)
- {
- grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters");
- goto fail;
- }
-
- grub_dprintf ("linux", "params = %p\n", params);
-
- grub_memset (params, 0, sizeof(*params));
+ lh = (struct linux_i386_kernel_header *)kernel;
+ grub_dprintf ("linux", "original lh is at %p\n", kernel);
- setup_header_end_offset = *((grub_uint8_t *)kernel + 0x201);
- grub_dprintf ("linux", "copying %lu bytes from %p to %p\n",
- MIN((grub_size_t)0x202+setup_header_end_offset,
- sizeof (*params)) - 0x1f1,
- (grub_uint8_t *)kernel + 0x1f1,
- (grub_uint8_t *)params + 0x1f1);
- grub_memcpy ((grub_uint8_t *)params + 0x1f1,
- (grub_uint8_t *)kernel + 0x1f1,
- MIN((grub_size_t)0x202+setup_header_end_offset,sizeof (*params)) - 0x1f1);
- lh = (struct linux_i386_kernel_header *)params;
- grub_dprintf ("linux", "lh is at %p\n", lh);
grub_dprintf ("linux", "checking lh->boot_flag\n");
if (lh->boot_flag != grub_cpu_to_le16 (0xaa55))
{
@@ -300,6 +277,34 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
}
#endif
+ params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS,
+ BYTES_TO_PAGES(sizeof(*params)));
+ if (!params)
+ params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS,
+ BYTES_TO_PAGES(sizeof(*params)));
+ if (! params)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters");
+ goto fail;
+ }
+
+ grub_dprintf ("linux", "params = %p\n", params);
+
+ grub_memset (params, 0, sizeof(*params));
+
+ setup_header_end_offset = *((grub_uint8_t *)kernel + 0x201);
+ grub_dprintf ("linux", "copying %" PRIuGRUB_SIZE " bytes from %p to %p\n",
+ MIN((grub_size_t)0x202+setup_header_end_offset,
+ sizeof (*params)) - 0x1f1,
+ (grub_uint8_t *)kernel + 0x1f1,
+ (grub_uint8_t *)params + 0x1f1);
+ grub_memcpy ((grub_uint8_t *)params + 0x1f1,
+ (grub_uint8_t *)kernel + 0x1f1,
+ MIN((grub_size_t)0x202+setup_header_end_offset,sizeof (*params)) - 0x1f1);
+
+ lh = (struct linux_i386_kernel_header *)params;
+ grub_dprintf ("linux", "new lh is at %p\n", lh);
+
grub_dprintf ("linux", "setting up cmdline\n");
linux_cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS,
BYTES_TO_PAGES(lh->cmdline_size + 1));
@@ -324,8 +329,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_dprintf ("linux", "setting lh->cmd_line_ptr\n");
lh->cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linux_cmdline;
- grub_dprintf ("linux", "computing handover offset\n");
handover_offset = lh->handover_offset;
+ grub_dprintf("linux", "handover_offset: %08x\n", handover_offset);
start = (lh->setup_sects + 1) * 512;
@@ -342,24 +347,26 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate kernel"));
goto fail;
}
-
- grub_dprintf ("linux", "kernel_mem = %lx\n", (unsigned long) kernel_mem);
+ grub_dprintf("linux", "kernel_mem = %p\n", kernel_mem);
grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
- loaded=1;
+
+ loaded = 1;
+
grub_dprintf ("linux", "setting lh->code32_start to %p\n", kernel_mem);
lh->code32_start = (grub_uint32_t)(grub_addr_t) kernel_mem;
grub_memcpy (kernel_mem, (char *)kernel + start, filelen - start);
- grub_dprintf ("linux", "setting lh->type_of_loader\n");
lh->type_of_loader = 0x6;
+ grub_dprintf ("linux", "setting lh->type_of_loader = 0x%02x\n",
+ lh->type_of_loader);
- grub_dprintf ("linux", "setting lh->ext_loader_{type,ver}\n");
params->ext_loader_type = 0;
params->ext_loader_ver = 2;
- grub_dprintf("linux", "kernel_mem: %p handover_offset: %08x\n",
- kernel_mem, handover_offset);
+ grub_dprintf ("linux",
+ "setting lh->ext_loader_{type,ver} = {0x%02x,0x%02x}\n",
+ params->ext_loader_type, params->ext_loader_ver);
fail:
--
2.31.1

View File

@ -0,0 +1,43 @@
From 4773f90bdefb72dde55fb5961f7f37b467307016 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <dja@axtens.net>
Date: Thu, 30 Jul 2020 00:13:21 +1000
Subject: [PATCH 07/23] dl: provide a fake grub_dl_set_persistent for the emu
target
Trying to start grub-emu with a module that calls grub_dl_set_persistent
will crash because grub-emu fakes modules and passes NULL to the module
init function.
Provide an empty function for the emu case.
Fixes: ee7808e2197c (dl: Add support for persistent modules)
Signed-off-by: Daniel Axtens <dja@axtens.net>
---
include/grub/dl.h | 11 +++++++++++
1 file changed, 11 insertions(+)
--- a/include/grub/dl.h
+++ b/include/grub/dl.h
@@ -242,11 +242,22 @@
return 0;
}
+#ifdef GRUB_MACHINE_EMU
+/*
+ * Under grub-emu, modules are faked and NULL is passed to GRUB_MOD_INIT.
+ * So we fake this out to avoid a NULL deref.
+ */
+static inline void
+grub_dl_set_persistent (grub_dl_t mod __attribute__((unused)))
+{
+}
+#else
static inline void
grub_dl_set_persistent (grub_dl_t mod)
{
mod->persistent = 1;
}
+#endif
static inline int
grub_dl_is_persistent (grub_dl_t mod)

View File

@ -0,0 +1,387 @@
From 369df8e3006000a4acacc674f5882d8729781811 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Sun, 10 Jul 2016 23:46:31 +0800
Subject: [PATCH 7/8] efinet: Setting network from UEFI device path
The PXE Base Code protocol used to obtain cached PXE DHCPACK packet is no
longer provided for HTTP Boot. Instead, we have to get the HTTP boot
information from the device path nodes defined in following UEFI Specification
sections.
9.3.5.12 IPv4 Device Path
9.3.5.13 IPv6 Device Path
9.3.5.23 Uniform Resource Identifiers (URI) Device Path
This patch basically does:
include/grub/efi/api.h:
Add new structure of Uniform Resource Identifiers (URI) Device Path
grub-core/net/drivers/efi/efinet.c:
Check if PXE Base Code is available, if not it will try to obtain the netboot
information from the device path where the image booted from. The DHCPACK
packet is recoverd from the information in device patch and feed into the same
DHCP packet processing functions to ensure the network interface is setting up
the same way it used to be.
Signed-off-by: Michael Chang <mchang@suse.com>
Signed-off-by: Ken Lin <ken.lin@hpe.com>
---
grub-core/net/drivers/efi/efinet.c | 268 +++++++++++++++++++++++++++++++++++--
include/grub/efi/api.h | 11 ++
2 files changed, 270 insertions(+), 9 deletions(-)
--- a/grub-core/net/drivers/efi/efinet.c
+++ b/grub-core/net/drivers/efi/efinet.c
@@ -23,6 +23,7 @@
#include <grub/efi/api.h>
#include <grub/efi/efi.h>
#include <grub/i18n.h>
+#include <grub/net/netbuff.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -341,6 +342,221 @@
grub_free (handles);
}
+static struct grub_net_buff *
+grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *use_ipv6)
+{
+ grub_efi_uint16_t uri_len;
+ grub_efi_device_path_t *ldp, *ddp;
+ grub_efi_uri_device_path_t *uri_dp;
+ struct grub_net_buff *nb;
+ grub_err_t err;
+
+ ddp = grub_efi_duplicate_device_path (dp);
+ ldp = grub_efi_find_last_device_path (ddp);
+
+ if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
+ || GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_URI_DEVICE_PATH_SUBTYPE)
+ {
+ grub_free (ddp);
+ return NULL;
+ }
+
+ uri_len = GRUB_EFI_DEVICE_PATH_LENGTH (ldp) > 4 ? GRUB_EFI_DEVICE_PATH_LENGTH (ldp) - 4 : 0;
+
+ if (!uri_len)
+ {
+ grub_free (ddp);
+ return NULL;
+ }
+
+ uri_dp = (grub_efi_uri_device_path_t *) ldp;
+
+ ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
+ ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
+ ldp->length = sizeof (*ldp);
+
+ ldp = grub_efi_find_last_device_path (ddp);
+
+ if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
+ || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE
+ && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE))
+ {
+ grub_free (ddp);
+ return NULL;
+ }
+
+ nb = grub_netbuff_alloc (512);
+ if (!nb)
+ return NULL;
+
+ if (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE)
+ {
+ grub_efi_ipv4_device_path_t *ipv4 = (grub_efi_ipv4_device_path_t *) ldp;
+ struct grub_net_bootp_packet *bp;
+ grub_uint8_t *ptr;
+
+ bp = (struct grub_net_bootp_packet *) nb->tail;
+ err = grub_netbuff_put (nb, sizeof (*bp) + 4);
+ if (err)
+ {
+ grub_free (ddp);
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+
+ if (sizeof(bp->boot_file) < uri_len)
+ {
+ grub_free (ddp);
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+ grub_memcpy (bp->boot_file, uri_dp->uri, uri_len);
+ grub_memcpy (&bp->your_ip, ipv4->local_ip_address, sizeof (bp->your_ip));
+ grub_memcpy (&bp->server_ip, ipv4->remote_ip_address, sizeof (bp->server_ip));
+
+ bp->vendor[0] = GRUB_NET_BOOTP_RFC1048_MAGIC_0;
+ bp->vendor[1] = GRUB_NET_BOOTP_RFC1048_MAGIC_1;
+ bp->vendor[2] = GRUB_NET_BOOTP_RFC1048_MAGIC_2;
+ bp->vendor[3] = GRUB_NET_BOOTP_RFC1048_MAGIC_3;
+
+ ptr = nb->tail;
+ err = grub_netbuff_put (nb, sizeof (ipv4->subnet_mask) + 2);
+ if (err)
+ {
+ grub_free (ddp);
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+ *ptr++ = GRUB_NET_BOOTP_NETMASK;
+ *ptr++ = sizeof (ipv4->subnet_mask);
+ grub_memcpy (ptr, ipv4->subnet_mask, sizeof (ipv4->subnet_mask));
+
+ ptr = nb->tail;
+ err = grub_netbuff_put (nb, sizeof (ipv4->gateway_ip_address) + 2);
+ if (err)
+ {
+ grub_free (ddp);
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+ *ptr++ = GRUB_NET_BOOTP_ROUTER;
+ *ptr++ = sizeof (ipv4->gateway_ip_address);
+ grub_memcpy (ptr, ipv4->gateway_ip_address, sizeof (ipv4->gateway_ip_address));
+
+ ptr = nb->tail;
+ err = grub_netbuff_put (nb, sizeof ("HTTPClient") + 1);
+ if (err)
+ {
+ grub_free (ddp);
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+ *ptr++ = GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER;
+ *ptr++ = sizeof ("HTTPClient") - 1;
+ grub_memcpy (ptr, "HTTPClient", sizeof ("HTTPClient") - 1);
+
+ ptr = nb->tail;
+ err = grub_netbuff_put (nb, 1);
+ if (err)
+ {
+ grub_free (ddp);
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+ *ptr = GRUB_NET_BOOTP_END;
+ *use_ipv6 = 0;
+
+ ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
+ ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
+ ldp->length = sizeof (*ldp);
+ ldp = grub_efi_find_last_device_path (ddp);
+
+ if (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE)
+ {
+ grub_efi_mac_address_device_path_t *mac = (grub_efi_mac_address_device_path_t *) ldp;
+ bp->hw_type = mac->if_type;
+ bp->hw_len = sizeof (bp->mac_addr);
+ grub_memcpy (bp->mac_addr, mac->mac_address, bp->hw_len);
+ }
+ }
+ else
+ {
+ grub_efi_ipv6_device_path_t *ipv6 = (grub_efi_ipv6_device_path_t *) ldp;
+
+ struct grub_net_dhcp6_packet *d6p;
+ struct grub_net_dhcp6_option *opt;
+ struct grub_net_dhcp6_option_iana *iana;
+ struct grub_net_dhcp6_option_iaaddr *iaaddr;
+
+ d6p = (struct grub_net_dhcp6_packet *)nb->tail;
+ err = grub_netbuff_put (nb, sizeof(*d6p));
+ if (err)
+ {
+ grub_free (ddp);
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+ d6p->message_type = GRUB_NET_DHCP6_REPLY;
+
+ opt = (struct grub_net_dhcp6_option *)nb->tail;
+ err = grub_netbuff_put (nb, sizeof(*opt));
+ if (err)
+ {
+ grub_free (ddp);
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IA_NA);
+ opt->len = grub_cpu_to_be16_compile_time (sizeof(*iana) + sizeof(*opt) + sizeof(*iaaddr));
+
+ err = grub_netbuff_put (nb, sizeof(*iana));
+ if (err)
+ {
+ grub_free (ddp);
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+
+ opt = (struct grub_net_dhcp6_option *)nb->tail;
+ err = grub_netbuff_put (nb, sizeof(*opt));
+ if (err)
+ {
+ grub_free (ddp);
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IAADDR);
+ opt->len = grub_cpu_to_be16_compile_time (sizeof (*iaaddr));
+
+ iaaddr = (struct grub_net_dhcp6_option_iaaddr *)nb->tail;
+ err = grub_netbuff_put (nb, sizeof(*iaaddr));
+ if (err)
+ {
+ grub_free (ddp);
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+ grub_memcpy (iaaddr->addr, ipv6->local_ip_address, sizeof(ipv6->local_ip_address));
+
+ opt = (struct grub_net_dhcp6_option *)nb->tail;
+ err = grub_netbuff_put (nb, sizeof(*opt) + uri_len);
+ if (err)
+ {
+ grub_free (ddp);
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_BOOTFILE_URL);
+ opt->len = grub_cpu_to_be16 (uri_len);
+ grub_memcpy (opt->data, uri_dp->uri, uri_len);
+
+ *use_ipv6 = 1;
+ }
+
+ grub_free (ddp);
+ return nb;
+}
+
static void
grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
char **path)
@@ -361,6 +577,11 @@
grub_efi_device_path_t *cdp;
struct grub_efi_pxe *pxe;
struct grub_efi_pxe_mode *pxe_mode;
+ grub_uint8_t *packet_buf;
+ grub_size_t packet_bufsz ;
+ int ipv6;
+ struct grub_net_buff *nb = NULL;
+
if (card->driver != &efidriver)
continue;
cdp = grub_efi_get_device_path (card->efi_handle);
@@ -380,11 +601,21 @@
ldp = grub_efi_find_last_device_path (dp);
if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
|| (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE
- && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE))
+ && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE
+ && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_URI_DEVICE_PATH_SUBTYPE))
continue;
dup_dp = grub_efi_duplicate_device_path (dp);
if (!dup_dp)
continue;
+
+ if (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_URI_DEVICE_PATH_SUBTYPE)
+ {
+ dup_ldp = grub_efi_find_last_device_path (dup_dp);
+ dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
+ dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
+ dup_ldp->length = sizeof (*dup_ldp);
+ }
+
dup_ldp = grub_efi_find_last_device_path (dup_dp);
dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
@@ -396,16 +627,31 @@
}
pxe = grub_efi_open_protocol (hnd, &pxe_io_guid,
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
- if (! pxe)
- continue;
- pxe_mode = pxe->mode;
+ if (!pxe)
+ {
+ nb = grub_efinet_create_dhcp_ack_from_device_path (dp, &ipv6);
+ if (!nb)
+ {
+ grub_print_error ();
+ continue;
+ }
+ packet_buf = nb->head;
+ packet_bufsz = nb->tail - nb->head;
+ }
+ else
+ {
+ pxe_mode = pxe->mode;
+ packet_buf = (grub_uint8_t *) &pxe_mode->dhcp_ack;
+ packet_bufsz = sizeof (pxe_mode->dhcp_ack);
+ ipv6 = pxe_mode->using_ipv6;
+ }
- if (pxe_mode->using_ipv6)
+ if (ipv6)
{
grub_net_configure_by_dhcpv6_reply (card->name, card, 0,
(struct grub_net_dhcp6_packet *)
- &pxe_mode->dhcp_ack,
- sizeof (pxe_mode->dhcp_ack),
+ packet_buf,
+ packet_bufsz,
1, device, path);
if (grub_errno)
grub_print_error ();
@@ -414,8 +660,8 @@
{
inter = grub_net_configure_by_dhcp_ack (card->name, card, 0,
(struct grub_net_bootp_packet *)
- &pxe_mode->dhcp_ack,
- sizeof (pxe_mode->dhcp_ack),
+ packet_buf,
+ packet_bufsz,
1, device, path);
if (inter != NULL)
@@ -441,6 +687,10 @@
}
}
}
+
+ if (nb)
+ grub_netbuff_free (nb);
+
return;
}
}
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -876,6 +876,8 @@
grub_efi_uint16_t remote_port;
grub_efi_uint16_t protocol;
grub_efi_uint8_t static_ip_address;
+ grub_efi_ipv4_address_t gateway_ip_address;
+ grub_efi_ipv4_address_t subnet_mask;
} GRUB_PACKED;
typedef struct grub_efi_ipv4_device_path grub_efi_ipv4_device_path_t;
@@ -939,6 +941,15 @@
} GRUB_PACKED;
typedef struct grub_efi_vlan_device_path grub_efi_vlan_device_path_t;
+#define GRUB_EFI_URI_DEVICE_PATH_SUBTYPE 24
+
+struct grub_efi_uri_device_path
+{
+ grub_efi_device_path_t header;
+ grub_efi_uint8_t uri[0];
+} GRUB_PACKED;
+typedef struct grub_efi_uri_device_path grub_efi_uri_device_path_t;
+
#define GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE 10
/* Media Device Path. */

View File

@ -0,0 +1,279 @@
From 96e5a28d120856057fe7fc9b281f11f8933063b7 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 30 Jun 2023 14:37:41 +0800
Subject: [PATCH 7/9] grub-switch-to-blscfg: adapt to openSUSE
A few tweaks to make it 'just works' for openSUSE:
- remove RHEL specific $grub_get_kernel_settings and all reference to it.
- make $grubdir and $startlink to the path in openSUSE
- change the bls template to openSUSE
- make $cmdline account for btrfs subvolumes, among others
- remove RHEL specific $GRUB_LINUX_MAKE_DEBUG and all related code
- remove ostree specific hack
- ignore increment.mod
- fix error in dash shell script
- fix kernel flavor parsing in openSUSE
Signed-off-by: Michael Chang <mchang@suse.com>
---
util/grub-switch-to-blscfg.in | 156 ++++++++++++++++++++--------------
1 file changed, 94 insertions(+), 62 deletions(-)
diff --git a/util/grub-switch-to-blscfg.in b/util/grub-switch-to-blscfg.in
index a851424be..145c22add 100644
--- a/util/grub-switch-to-blscfg.in
+++ b/util/grub-switch-to-blscfg.in
@@ -28,27 +28,24 @@ PACKAGE_NAME=@PACKAGE_NAME@
PACKAGE_VERSION=@PACKAGE_VERSION@
datarootdir="@datarootdir@"
datadir="@datadir@"
-if [ ! -v pkgdatadir ]; then
+if [ -z "${pkgdatadir+x}" ]; then
pkgdatadir="${datadir}/@PACKAGE@"
fi
self=`basename $0`
-grub_get_kernel_settings="${sbindir}/@grub_get_kernel_settings@"
grub_editenv=${bindir}/@grub_editenv@
-etcdefaultgrub=/etc/default/grub
+grub_probe="${sbindir}/@grub_probe@"
+etcdefaultgrub=${sysconfdir}/default/grub
-eval "$("${grub_get_kernel_settings}")" || true
-
-EFIDIR=$(grep ^ID= /etc/os-release | sed -e 's/^ID=//' -e 's/rhel/redhat/' -e 's/\"//g')
-if [ -d /sys/firmware/efi/efivars/ ]; then
- startlink=/etc/grub2-efi.cfg
- grubdir=`echo "/@bootdirname@/efi/EFI/${EFIDIR}/" | sed 's,//*,/,g'`
-else
- startlink=/etc/grub2.cfg
- grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'`
+if test -f "$etcdefaultgrub" ; then
+ # shellcheck source=/etc/default/grub
+ . "$etcdefaultgrub"
fi
+grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'`
+startlink="${grubdir}/grub.cfg"
+
blsdir=`echo "/@bootdirname@/loader/entries" | sed 's,//*,/,g'`
backupsuffix=.bak
@@ -58,19 +55,80 @@ arch="$(uname -m)"
export TEXTDOMAIN=@PACKAGE@
export TEXTDOMAINDIR="@localedir@"
+# shellcheck source=/usr/share/grub2/grub-mkconfig_lib
. "${pkgdatadir}/grub-mkconfig_lib"
+# FIXME: Abort if grub_probe fails
+
+GRUB_DEVICE="`${grub_probe} --target=device /`"
+GRUB_DEVICE_UUID="`${grub_probe} --device ${GRUB_DEVICE} --target=fs_uuid 2> /dev/null`" || true
+GRUB_DEVICE_PARTUUID="`${grub_probe} --device ${GRUB_DEVICE} --target=partuuid 2> /dev/null`" || true
+GRUB_FS="`${grub_probe} --device ${GRUB_DEVICE} --target=fs 2> /dev/null || echo unknown`"
+
+# loop-AES arranges things so that /dev/loop/X can be our root device, but
+# the initrds that Linux uses don't like that.
+case ${GRUB_DEVICE} in
+ /dev/loop/*|/dev/loop[0-9])
+ GRUB_DEVICE=$(losetup "${GRUB_DEVICE}" | sed -e "s/^[^(]*(\([^)]\+\)).*/\1/")
+ ;;
+esac
+
+# Default to disabling partition uuid support to maintian compatibility with
+# older kernels.
+GRUB_DISABLE_LINUX_PARTUUID=${GRUB_DISABLE_LINUX_PARTUUID-true}
+
+# btrfs may reside on multiple devices. We cannot pass them as value of root= parameter
+# and mounting btrfs requires user space scanning, so force UUID in this case.
+if ( [ "x${GRUB_DEVICE_UUID}" = "x" ] && [ "x${GRUB_DEVICE_PARTUUID}" = "x" ] ) \
+ || ( [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \
+ && [ "x${GRUB_DISABLE_LINUX_PARTUUID}" = "xtrue" ] ) \
+ || ( ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" \
+ && ! test -e "/dev/disk/by-partuuid/${GRUB_DEVICE_PARTUUID}" ) \
+ || ( test -e "${GRUB_DEVICE}" && uses_abstraction "${GRUB_DEVICE}" lvm ); then
+ LINUX_ROOT_DEVICE=${GRUB_DEVICE}
+elif [ "x${GRUB_DEVICE_UUID}" = "x" ] \
+ || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ]; then
+ LINUX_ROOT_DEVICE=PARTUUID=${GRUB_DEVICE_PARTUUID}
+else
+ LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID}
+fi
+
+if [ "x$GRUB_CONMODE" != "x" ]; then
+ GRUB_CMDLINE_LINUX="conmode=${GRUB_CONMODE} ${GRUB_CMDLINE_LINUX}"
+fi
+
+case x"$GRUB_FS" in
+ xbtrfs)
+ if [ "x${SUSE_BTRFS_SNAPSHOT_BOOTING}" != "xtrue" ]; then
+ rootsubvol="`make_system_path_relative_to_its_root /`"
+ rootsubvol="${rootsubvol#/}"
+ if [ "x${rootsubvol}" != x ] && [ "x$SUSE_REMOVE_LINUX_ROOT_PARAM" != "xtrue" ]; then
+ GRUB_CMDLINE_LINUX="rootflags=subvol=${rootsubvol} ${GRUB_CMDLINE_LINUX}"
+ fi
+ fi
+ ;;
+ xzfs)
+ rpool=`${grub_probe} --device ${GRUB_DEVICE} --target=fs_label 2>/dev/null || true`
+ bootfs="`make_system_path_relative_to_its_root / | sed -e "s,@$,,"`"
+ LINUX_ROOT_DEVICE="ZFS=${rpool}${bootfs%/}"
+ ;;
+esac
+
+if [ "x$SUSE_REMOVE_LINUX_ROOT_PARAM" = "xtrue" ]; then
+ LINUX_ROOT_DEVICE=""
+fi
+
# Usage: usage
# Print the usage.
usage () {
gettext_printf "Usage: %s\n" "$self"
- gettext "Switch to BLS config files.\n"; echo
+ gettext "Switch to BLS config files. Only for testing purpose !!!\n"; echo
echo
print_option_help "-h, --help" "$(gettext "print this message and exit")"
print_option_help "-V, --version" "$(gettext "print the version information and exit")"
echo
print_option_help "--backup-suffix=$(gettext "SUFFIX")" "$backupsuffix"
- print_option_help "--bls-directory=$(gettext "DIR")" "$blsdir"
+ print_option_help "--bls-directory=$(gettext "DIR")" "Noop, always $blsdir"
print_option_help "--config-file=$(gettext "FILE")" "$startlink"
print_option_help "--grub-defaults=$(gettext "FILE")" "$etcdefaultgrub"
print_option_help "--grub-directory=$(gettext "DIR")" "$grubdir"
@@ -112,11 +170,15 @@ do
;;
--bls-directory)
- blsdir=`argument $option "$@"`
+ # blsdir=`argument $option "$@"`
+ gettext_printf "WARN: --bls-directory is currently disabled, it's always $blsdir !!!\n"
+ gettext_printf "WARN: use kernel-install instead if you want to test bls directory on ESP !!!\n"
shift
;;
--bls-directory=*)
- blsdir=`echo "$option" | sed 's/--bls-directory=//'`
+ # blsdir=`echo "$option" | sed 's/--bls-directory=//'`
+ gettext_printf "WARN: --bls-directory is currently disabled, it's always $blsdir !!!\n"
+ gettext_printf "WARN: use kernel-install instead if you want to test bls directory on ESP !!!\n"
;;
--config-file)
@@ -172,7 +234,7 @@ find_grub_cfg() {
return 1
}
-if ! find_grub_cfg ${startlink} ${grubdir}/grub.cfg ; then
+if ! find_grub_cfg "${startlink}" ; then
gettext_printf "Couldn't find config file\n" 1>&2
exit 1
fi
@@ -190,27 +252,24 @@ fi
mkbls() {
local kernelver=$1 && shift
local datetime=$1 && shift
+ local prefix=$1 && shift
local kernelopts=$1 && shift
- local debugname=""
- local debugid=""
local flavor=""
- if [ "$kernelver" == *\+* ] ; then
- local flavor=-"${kernelver##*+}"
- if [ "${flavor}" == "-debug" ]; then
- local debugname=" with debugging"
- local debugid="-debug"
- fi
- fi
+ case "$kernelver" in
+ *-*-*)
+ flavor=-"${kernelver##*-}"
+ ;;
+ esac
(
- source /etc/os-release
+ . /etc/os-release
cat <<EOF
-title ${NAME} (${kernelver}) ${VERSION}${debugname}
-version ${kernelver}${debugid}
-linux /vmlinuz-${kernelver}
-initrd /initramfs-${kernelver}.img
+title ${NAME} (${kernelver}) ${VERSION}
+version ${kernelver}
+linux ${prefix}/vmlinuz-${kernelver}
+initrd ${prefix}/initrd-${kernelver}
options ${kernelopts}
grub_users \$grub_users
grub_arg --unrestricted
@@ -233,42 +292,15 @@ copy_bls() {
continue
fi
- linux_relpath="$("${grub_mkrelpath}" "${linux_path}")"
- bootprefix="${linux_relpath%%"${linux}"}"
+ bootprefix="$(make_system_path_relative_to_its_root /boot)"
cmdline="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
mkbls "${kernelver}" \
"$(date -u +%Y%m%d%H%M%S -d "$(stat -c '%y' "${kernel_dir}")")" \
"${bootprefix}" "${cmdline}" >"${bls_target}"
-
- if [ "x$GRUB_LINUX_MAKE_DEBUG" = "xtrue" ]; then
- bls_debug="$(echo ${bls_target} | sed -e "s/${kernelver}/${kernelver}~debug/")"
- cp -aT "${bls_target}" "${bls_debug}"
- title="$(grep '^title[ \t]' "${bls_debug}" | sed -e 's/^title[ \t]*//')"
- options="$(echo "${cmdline} ${GRUB_CMDLINE_LINUX_DEBUG}" | sed -e 's/\//\\\//g')"
- sed -i -e "s/^title.*/title ${title}${GRUB_LINUX_DEBUG_TITLE_POSTFIX}/" "${bls_debug}"
- sed -i -e "s/^options.*/options ${options}/" "${bls_debug}"
- fi
done
-
- if [ -f "/boot/vmlinuz-0-rescue-${MACHINE_ID}" ]; then
- mkbls "0-rescue-${MACHINE_ID}" "0" "${bootprefix}" >"${blsdir}/${MACHINE_ID}-0-rescue.conf"
- fi
}
-# The grub2 EFI binary is not copied to the ESP as a part of an ostree
-# transaction. Make sure a grub2 version with BLS support is installed
-# but only do this if the blsdir is not set, to make sure that the BLS
-# parsing module will search for the BLS snippets in the default path.
-if test -f /run/ostree-booted && test -d /sys/firmware/efi/efivars && \
- ! ${grub_editenv} - list | grep -q blsdir && \
- mountpoint -q /boot; then
- grub_binary="$(find /usr/lib/ostree-boot/efi/EFI/${EFIDIR}/ -name grub*.efi)"
- install -m 700 ${grub_binary} ${grubdir} || exit 1
- # Create a hidden file to indicate that grub2 now has BLS support.
- touch /boot/grub2/.grub2-blscfg-supported
-fi
-
GENERATE=0
if grep '^GRUB_ENABLE_BLSCFG=.*' "${etcdefaultgrub}" \
| grep -vq '^GRUB_ENABLE_BLSCFG="*true"*\s*$' ; then
@@ -297,9 +329,7 @@ if [ "${GENERATE}" -eq 1 ] ; then
fi
if [ -n "${mod_dir}" ]; then
- for mod in blscfg increment; do
- install -m 700 ${prefix}/lib/grub/${mod_dir}/${mod}.mod ${grubdir}/$mod_dir/ || exit 1
- done
+ install -m 700 "${pkgdatadir}/${mod_dir}/blscfg.mod" "${grubdir}/$mod_dir/" || exit 1
fi
cp -af "${GRUB_CONFIG_FILE}" "${GRUB_CONFIG_FILE}${backupsuffix}"
@@ -311,6 +341,8 @@ if [ "${GENERATE}" -eq 1 ] ; then
gettext_printf "Updating %s failed\n" "${GRUB_CONFIG_FILE}"
exit 1
fi
+else
+ gettext_printf "Do nothing because \$GRUB_ENABLE_BLSCFG is already true in %s\n" "${GRUB_CONFIG_FILE}"
fi
# Bye.
--
2.45.2

View File

@ -0,0 +1,249 @@
From 2a84f1a50c6f8770808fd4ec590eb8cff4228aed Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Wed, 12 Sep 2018 16:03:55 -0400
Subject: [PATCH 07/11] x86-efi: Make our own allocator for kernel stuff
This helps enable allocations above 4GB.
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/loader/i386/efi/linux.c | 155 ++++++++++++++++++------------
1 file changed, 94 insertions(+), 61 deletions(-)
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
index 096a52eb5..d284db5d1 100644
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -47,6 +47,65 @@ static char *linux_cmdline;
#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12)
+struct allocation_choice {
+ grub_efi_physical_address_t addr;
+ grub_efi_allocate_type_t alloc_type;
+};
+
+static struct allocation_choice max_addresses[] =
+ {
+ { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
+ { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
+ { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
+ { 0, 0 }
+ };
+
+static inline void
+kernel_free(void *addr, grub_efi_uintn_t size)
+{
+ if (addr && size)
+ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)addr,
+ BYTES_TO_PAGES(size));
+}
+
+static void *
+kernel_alloc(grub_efi_uintn_t size, const char * const errmsg)
+{
+ void *addr = 0;
+ unsigned int i;
+ grub_efi_physical_address_t prev_max = 0;
+
+ for (i = 0; max_addresses[i].addr != 0 && addr == 0; i++)
+ {
+ grub_uint64_t max = max_addresses[i].addr;
+ grub_efi_uintn_t pages;
+
+ if (max == prev_max)
+ continue;
+
+ pages = BYTES_TO_PAGES(size);
+ grub_dprintf ("linux", "Trying to allocate %" PRIuGRUB_SIZE" pages from %p\n",
+ pages, (void *)(grub_addr_t)max);
+
+ prev_max = max;
+ addr = grub_efi_allocate_pages_real (max, pages,
+ max_addresses[i].alloc_type,
+ GRUB_EFI_LOADER_DATA);
+ if (addr)
+ grub_dprintf ("linux", "Allocated at %p\n", addr);
+ }
+
+ while (grub_error_pop ())
+ {
+ ;
+ }
+
+ if (addr == NULL)
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, "%s", errmsg);
+
+ return addr;
+}
+
static grub_err_t
grub_linuxefi_boot (void)
{
@@ -62,14 +121,12 @@ grub_linuxefi_unload (void)
{
grub_dl_unref (my_mod);
loaded = 0;
- if (initrd_mem)
- grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)initrd_mem, BYTES_TO_PAGES(params->ramdisk_size));
- if (linux_cmdline)
- grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)linux_cmdline, BYTES_TO_PAGES(params->cmdline_size + 1));
- if (kernel_mem)
- grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)kernel_mem, BYTES_TO_PAGES(kernel_size));
- if (params)
- grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)params, BYTES_TO_PAGES(16384));
+
+ kernel_free(initrd_mem, params->ramdisk_size);
+ kernel_free(linux_cmdline, params->cmdline_size + 1);
+ kernel_free(kernel_mem, kernel_size);
+ kernel_free(params, sizeof(*params));
+
return GRUB_ERR_NONE;
}
@@ -146,17 +203,13 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
size += ALIGN_UP (grub_file_size (files[i]), 4);
}
- initrd_mem = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS, BYTES_TO_PAGES(size));
- if (!initrd_mem)
- initrd_mem = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS, BYTES_TO_PAGES(size));
- if (!initrd_mem)
- {
- grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate initrd"));
- goto fail;
- }
+ initrd_mem = kernel_alloc(size, N_("can't allocate initrd"));
+ if (initrd_mem == NULL)
+ goto fail;
+ grub_dprintf ("linux", "initrd_mem = %p\n", initrd_mem);
params->ramdisk_size = size;
- params->ramdisk_image = (grub_uint32_t)(grub_addr_t) initrd_mem;
+ params->ramdisk_image = initrd_mem;
ptr = initrd_mem;
@@ -214,7 +267,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
filelen = grub_file_size (file);
kernel = grub_malloc(filelen);
-
if (!kernel)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer"));
@@ -258,7 +310,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
-#if defined(__x86_64__) || defined(__aarch64__)
+#if defined(__x86_64__)
grub_dprintf ("linux", "checking lh->xloadflags\n");
if (!(lh->xloadflags & LINUX_XLF_KERNEL_64))
{
@@ -277,17 +329,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
}
#endif
- params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS,
- BYTES_TO_PAGES(sizeof(*params)));
+ params = kernel_alloc (sizeof(*params), "cannot allocate kernel parameters");
if (!params)
- params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS,
- BYTES_TO_PAGES(sizeof(*params)));
- if (! params)
- {
- grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters");
- goto fail;
- }
-
+ goto fail;
grub_dprintf ("linux", "params = %p\n", params);
grub_memset (params, 0, sizeof(*params));
@@ -306,16 +350,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_dprintf ("linux", "new lh is at %p\n", lh);
grub_dprintf ("linux", "setting up cmdline\n");
- linux_cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS,
- BYTES_TO_PAGES(lh->cmdline_size + 1));
+ linux_cmdline = kernel_alloc (lh->cmdline_size + 1, N_("can't allocate cmdline"));
if (!linux_cmdline)
- linux_cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_USABLE_ADDRESS,
- BYTES_TO_PAGES(lh->cmdline_size + 1));
- if (!linux_cmdline)
- {
- grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate cmdline"));
- goto fail;
- }
+ goto fail;
+ grub_dprintf ("linux", "linux_cmdline = %p\n", linux_cmdline);
grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE));
err = grub_create_loader_cmdline (argc, argv,
@@ -326,27 +364,24 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail;
grub_dprintf ("linux", "cmdline:%s\n", linux_cmdline);
- grub_dprintf ("linux", "setting lh->cmd_line_ptr\n");
- lh->cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linux_cmdline;
+ grub_dprintf ("linux", "setting lh->cmd_line_ptr to 0x%08x\n",
+ linux_cmdline);
+ lh->cmd_line_ptr = linux_cmdline;
handover_offset = lh->handover_offset;
- grub_dprintf("linux", "handover_offset: %08x\n", handover_offset);
+ grub_dprintf("linux", "handover_offset: 0x%08x\n", handover_offset);
start = (lh->setup_sects + 1) * 512;
- kernel_mem = grub_efi_allocate_pages_max(lh->pref_address,
- BYTES_TO_PAGES(lh->init_size));
- if (!kernel_mem)
- kernel_mem = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS,
- BYTES_TO_PAGES(lh->init_size));
- if (!kernel_mem)
- kernel_mem = grub_efi_allocate_pages_max(GRUB_EFI_MAX_USABLE_ADDRESS,
- BYTES_TO_PAGES(lh->init_size));
- if (!kernel_mem)
+ grub_dprintf ("linux", "lh->pref_address: %p\n", (void *)(grub_addr_t)lh->pref_address);
+ if (lh->pref_address < (grub_uint64_t)GRUB_EFI_MAX_ALLOCATION_ADDRESS)
{
- grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate kernel"));
- goto fail;
+ max_addresses[0].addr = lh->pref_address;
+ max_addresses[0].alloc_type = GRUB_EFI_ALLOCATE_ADDRESS;
}
+ kernel_mem = kernel_alloc (lh->init_size, N_("can't allocate kernel"));
+ if (!kernel_mem)
+ goto fail;
grub_dprintf("linux", "kernel_mem = %p\n", kernel_mem);
grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
@@ -382,16 +417,14 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
loaded = 0;
}
- if (linux_cmdline && lh && !loaded)
- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)
- linux_cmdline,
- BYTES_TO_PAGES(lh->cmdline_size + 1));
-
- if (kernel_mem && !loaded)
- grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)kernel_mem, BYTES_TO_PAGES(kernel_size));
+ if (!loaded)
+ {
+ if (lh)
+ kernel_free (linux_cmdline, lh->cmdline_size + 1);
- if (params && !loaded)
- grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)params, BYTES_TO_PAGES(16384));
+ kernel_free (kernel_mem, kernel_size);
+ kernel_free (params, sizeof(*params));
+ }
return grub_errno;
}
--
2.31.1

View File

@ -0,0 +1,75 @@
From 2b0e6effc31ec166bbbe35a3cd2b4c73051f38bb Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 16 Jun 2023 15:54:50 +0800
Subject: [PATCH 8/9] blscfg: reading bls fragments if boot present
The Boot Loader Specification (BLS) designates the EFI System Partition
(ESP) as a primary location for $BOOT, where boot menu entries can be
stored. The specification encourages boot loaders to retrieve menu
entries from the ESP, even when XBOOTLDR is present.
This commit aligns with the BLS specification by introducing the
capability to search for the ESP in addition to the default root
partition or any specified location via blscfg's command line. The $boot
environment variable is utilized as a reference to the ESP device for
the blscfg command. Initialization of $boot in grub.cfg is demonstrated
as follows:
insmod part_gpt
insmod fat
search --no-floppy --fs-uuid --set=boot F414-5A9F
If $boot is unset, no additional search for the BLS location will be
performed.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/commands/blscfg.c | 10 ++++++++++
util/grub.d/10_linux.in | 3 ++-
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/grub-core/commands/blscfg.c b/grub-core/commands/blscfg.c
index c872bcef0..cbe2a289e 100644
--- a/grub-core/commands/blscfg.c
+++ b/grub-core/commands/blscfg.c
@@ -1186,6 +1186,7 @@ grub_cmd_blscfg (grub_extcmd_context_t ctxt UNUSED,
char *entry_id = NULL;
bool show_default = true;
bool show_non_default = true;
+ const char *boot = NULL;
if (argc == 1) {
if (grub_strcmp (args[0], "default") == 0) {
@@ -1205,6 +1206,15 @@ grub_cmd_blscfg (grub_extcmd_context_t ctxt UNUSED,
if (r)
return r;
+ boot = grub_env_get("boot");
+ path = (boot) ? grub_xasprintf("(%s)" GRUB_BLS_CONFIG_PATH, boot) : NULL;
+ if (path)
+ {
+ bls_load_entries(path);
+ grub_print_error();
+ }
+ grub_free(path);
+
return bls_create_entries(show_default, show_non_default, entry_id);
}
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index 45eefb332..edf0fca55 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -201,7 +201,8 @@ populate_menu()
}
# Make BLS the default if GRUB_ENABLE_BLSCFG was not set and grubby is not installed.
-if [ -z "${GRUB_ENABLE_BLSCFG}" ] && ! command -v new-kernel-pkg >/dev/null; then
+# FIXME: The test should be aligned to openSUSE, grubby is not our default tool
+if [ -z "${GRUB_ENABLE_BLSCFG}" ] && ! command -v new-kernel-pkg >/dev/null && false; then
GRUB_ENABLE_BLSCFG="true"
fi
--
2.44.0

View File

@ -0,0 +1,331 @@
From 0c7ae6d7527d08e54a6eeebddb6c5c697c4b37d2 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 14 Jul 2016 17:48:45 +0800
Subject: [PATCH 8/8] efinet: Setting DNS server from UEFI protocol
In the URI device path node, any name rahter than address can be used for
looking up the resources so that DNS service become needed to get answer of the
name's address. Unfortunately the DNS is not defined in any of the device path
nodes so that we use the EFI_IP4_CONFIG2_PROTOCOL and EFI_IP6_CONFIG_PROTOCOL
to obtain it.
These two protcols are defined the sections of UEFI specification.
27.5 EFI IPv4 Configuration II Protocol
27.7 EFI IPv6 Configuration Protocol
include/grub/efi/api.h:
Add new structure and protocol UUID of EFI_IP4_CONFIG2_PROTOCOL and
EFI_IP6_CONFIG_PROTOCOL.
grub-core/net/drivers/efi/efinet.c:
Use the EFI_IP4_CONFIG2_PROTOCOL and EFI_IP6_CONFIG_PROTOCOL to obtain the list
of DNS server address for IPv4 and IPv6 respectively. The address of DNS
servers is structured into DHCPACK packet and feed into the same DHCP packet
processing functions to ensure the network interface is setting up the same way
it used to be.
Signed-off-by: Michael Chang <mchang@suse.com>
Signed-off-by: Ken Lin <ken.lin@hpe.com>
---
grub-core/net/drivers/efi/efinet.c | 163 +++++++++++++++++++++++++++++++++++++
include/grub/efi/api.h | 76 +++++++++++++++++
2 files changed, 239 insertions(+)
--- a/grub-core/net/drivers/efi/efinet.c
+++ b/grub-core/net/drivers/efi/efinet.c
@@ -30,6 +30,8 @@
/* GUID. */
static grub_guid_t net_io_guid = GRUB_EFI_SIMPLE_NETWORK_GUID;
static grub_guid_t pxe_io_guid = GRUB_EFI_PXE_GUID;
+static grub_guid_t ip4_config_guid = GRUB_EFI_IP4_CONFIG2_PROTOCOL_GUID;
+static grub_guid_t ip6_config_guid = GRUB_EFI_IP6_CONFIG_PROTOCOL_GUID;
static grub_err_t
send_card_buffer (struct grub_net_card *dev,
@@ -342,6 +344,125 @@
grub_free (handles);
}
+static grub_efi_handle_t
+grub_efi_locate_device_path (grub_efi_guid_t *protocol, grub_efi_device_path_t *device_path,
+ grub_efi_device_path_t **r_device_path)
+{
+ grub_efi_handle_t handle;
+ grub_efi_status_t status;
+
+ status = grub_efi_system_table->boot_services->locate_device_path (
+ protocol, &device_path, &handle);
+
+ if (status != GRUB_EFI_SUCCESS)
+ return 0;
+
+ if (r_device_path)
+ *r_device_path = device_path;
+
+ return handle;
+}
+
+static grub_efi_ipv4_address_t *
+grub_dns_server_ip4_address (grub_efi_device_path_t *dp, grub_efi_uintn_t *num_dns)
+{
+ grub_efi_handle_t hnd;
+ grub_efi_status_t status;
+ grub_efi_ip4_config2_protocol_t *conf;
+ grub_efi_ipv4_address_t *addrs;
+ grub_efi_uintn_t data_size = 1 * sizeof (grub_efi_ipv4_address_t);
+
+ hnd = grub_efi_locate_device_path (&ip4_config_guid, dp, NULL);
+
+ if (!hnd)
+ return 0;
+
+ conf = grub_efi_open_protocol (hnd, &ip4_config_guid,
+ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+ if (!conf)
+ return 0;
+
+ addrs = grub_malloc (data_size);
+ if (!addrs)
+ return 0;
+
+ status = conf->get_data (conf,
+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER,
+ &data_size, addrs);
+
+ if (status == GRUB_EFI_BUFFER_TOO_SMALL)
+ {
+ grub_free (addrs);
+ addrs = grub_malloc (data_size);
+ if (!addrs)
+ return 0;
+
+ status = conf->get_data (conf,
+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER,
+ &data_size, addrs);
+ }
+
+ if (status != GRUB_EFI_SUCCESS)
+ {
+ grub_free (addrs);
+ return 0;
+ }
+
+ *num_dns = data_size / sizeof (grub_efi_ipv4_address_t);
+ return addrs;
+}
+
+static grub_efi_ipv6_address_t *
+grub_dns_server_ip6_address (grub_efi_device_path_t *dp, grub_efi_uintn_t *num_dns)
+{
+ grub_efi_handle_t hnd;
+ grub_efi_status_t status;
+ grub_efi_ip6_config_protocol_t *conf;
+ grub_efi_ipv6_address_t *addrs;
+ grub_efi_uintn_t data_size = 1 * sizeof (grub_efi_ipv6_address_t);
+
+ hnd = grub_efi_locate_device_path (&ip6_config_guid, dp, NULL);
+
+ if (!hnd)
+ return 0;
+
+ conf = grub_efi_open_protocol (hnd, &ip6_config_guid,
+ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+ if (!conf)
+ return 0;
+
+ addrs = grub_malloc (data_size);
+ if (!addrs)
+ return 0;
+
+ status = conf->get_data (conf,
+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER,
+ &data_size, addrs);
+
+ if (status == GRUB_EFI_BUFFER_TOO_SMALL)
+ {
+ grub_free (addrs);
+ addrs = grub_malloc (data_size);
+ if (!addrs)
+ return 0;
+
+ status = conf->get_data (conf,
+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER,
+ &data_size, addrs);
+ }
+
+ if (status != GRUB_EFI_SUCCESS)
+ {
+ grub_free (addrs);
+ return 0;
+ }
+
+ *num_dns = data_size / sizeof (grub_efi_ipv6_address_t);
+ return addrs;
+}
+
static struct grub_net_buff *
grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *use_ipv6)
{
@@ -394,6 +515,8 @@
grub_efi_ipv4_device_path_t *ipv4 = (grub_efi_ipv4_device_path_t *) ldp;
struct grub_net_bootp_packet *bp;
grub_uint8_t *ptr;
+ grub_efi_ipv4_address_t *dns;
+ grub_efi_uintn_t num_dns;
bp = (struct grub_net_bootp_packet *) nb->tail;
err = grub_netbuff_put (nb, sizeof (*bp) + 4);
@@ -455,6 +578,25 @@
*ptr++ = sizeof ("HTTPClient") - 1;
grub_memcpy (ptr, "HTTPClient", sizeof ("HTTPClient") - 1);
+ dns = grub_dns_server_ip4_address (dp, &num_dns);
+ if (dns)
+ {
+ grub_efi_uintn_t size_dns = sizeof (*dns) * num_dns;
+
+ ptr = nb->tail;
+ err = grub_netbuff_put (nb, size_dns + 2);
+ if (err)
+ {
+ grub_free (ddp);
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+ *ptr++ = GRUB_NET_BOOTP_DNS;
+ *ptr++ = size_dns;
+ grub_memcpy (ptr, dns, size_dns);
+ grub_free (dns);
+ }
+
ptr = nb->tail;
err = grub_netbuff_put (nb, 1);
if (err)
@@ -487,6 +629,8 @@
struct grub_net_dhcp6_option *opt;
struct grub_net_dhcp6_option_iana *iana;
struct grub_net_dhcp6_option_iaaddr *iaaddr;
+ grub_efi_ipv6_address_t *dns;
+ grub_efi_uintn_t num_dns;
d6p = (struct grub_net_dhcp6_packet *)nb->tail;
err = grub_netbuff_put (nb, sizeof(*d6p));
@@ -550,6 +694,25 @@
opt->len = grub_cpu_to_be16 (uri_len);
grub_memcpy (opt->data, uri_dp->uri, uri_len);
+ dns = grub_dns_server_ip6_address (dp, &num_dns);
+ if (dns)
+ {
+ grub_efi_uintn_t size_dns = sizeof (*dns) * num_dns;
+
+ opt = (struct grub_net_dhcp6_option *)nb->tail;
+ err = grub_netbuff_put (nb, sizeof(*opt) + size_dns);
+ if (err)
+ {
+ grub_free (ddp);
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_DNS_SERVERS);
+ opt->len = grub_cpu_to_be16 (size_dns);
+ grub_memcpy (opt->data, dns, size_dns);
+ grub_free (dns);
+ }
+
*use_ipv6 = 1;
}
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -379,6 +379,16 @@
{0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f } \
}
+#define GRUB_EFI_IP4_CONFIG2_PROTOCOL_GUID \
+ { 0x5b446ed1, 0xe30b, 0x4faa, \
+ { 0x87, 0x1a, 0x36, 0x54, 0xec, 0xa3, 0x60, 0x80 } \
+ }
+
+#define GRUB_EFI_IP6_CONFIG_PROTOCOL_GUID \
+ { 0x937fe521, 0x95ae, 0x4d1a, \
+ { 0x89, 0x29, 0x48, 0xbc, 0xd9, 0x0a, 0xd3, 0x1a } \
+ }
+
struct grub_efi_sal_system_table
{
grub_uint32_t signature;
@@ -1879,4 +1889,70 @@
} GRUB_PACKED;
typedef struct initrd_media_device_path initrd_media_device_path_t;
+enum grub_efi_ip4_config2_data_type {
+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_INTERFACEINFO,
+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_POLICY,
+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS,
+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_GATEWAY,
+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER,
+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MAXIMUM
+};
+typedef enum grub_efi_ip4_config2_data_type grub_efi_ip4_config2_data_type_t;
+
+struct grub_efi_ip4_config2_protocol
+{
+ grub_efi_status_t (__grub_efi_api *set_data) (struct grub_efi_ip4_config2_protocol *this,
+ grub_efi_ip4_config2_data_type_t data_type,
+ grub_efi_uintn_t data_size,
+ void *data);
+
+ grub_efi_status_t (__grub_efi_api *get_data) (struct grub_efi_ip4_config2_protocol *this,
+ grub_efi_ip4_config2_data_type_t data_type,
+ grub_efi_uintn_t *data_size,
+ void *data);
+
+ grub_efi_status_t (__grub_efi_api *register_data_notify) (struct grub_efi_ip4_config2_protocol *this,
+ grub_efi_ip4_config2_data_type_t data_type,
+ grub_efi_event_t event);
+
+ grub_efi_status_t (__grub_efi_api *unregister_datanotify) (struct grub_efi_ip4_config2_protocol *this,
+ grub_efi_ip4_config2_data_type_t data_type,
+ grub_efi_event_t event);
+};
+typedef struct grub_efi_ip4_config2_protocol grub_efi_ip4_config2_protocol_t;
+
+enum grub_efi_ip6_config_data_type {
+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_INTERFACEINFO,
+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_ALT_INTERFACEID,
+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_POLICY,
+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_DUP_ADDR_DETECT_TRANSMITS,
+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_MANUAL_ADDRESS,
+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_GATEWAY,
+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER,
+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_MAXIMUM
+};
+typedef enum grub_efi_ip6_config_data_type grub_efi_ip6_config_data_type_t;
+
+struct grub_efi_ip6_config_protocol
+{
+ grub_efi_status_t (__grub_efi_api *set_data) (struct grub_efi_ip6_config_protocol *this,
+ grub_efi_ip6_config_data_type_t data_type,
+ grub_efi_uintn_t data_size,
+ void *data);
+
+ grub_efi_status_t (__grub_efi_api *get_data) (struct grub_efi_ip6_config_protocol *this,
+ grub_efi_ip6_config_data_type_t data_type,
+ grub_efi_uintn_t *data_size,
+ void *data);
+
+ grub_efi_status_t (__grub_efi_api *register_data_notify) (struct grub_efi_ip6_config_protocol *this,
+ grub_efi_ip6_config_data_type_t data_type,
+ grub_efi_event_t event);
+
+ grub_efi_status_t (__grub_efi_api *unregister_datanotify) (struct grub_efi_ip6_config_protocol *this,
+ grub_efi_ip6_config_data_type_t data_type,
+ grub_efi_event_t event);
+};
+typedef struct grub_efi_ip6_config_protocol grub_efi_ip6_config_protocol_t;
+
#endif /* ! GRUB_EFI_API_HEADER */

Some files were not shown because too many files have changed in this diff Show More