Sync from SUSE:SLFO:Main grub2 revision 1dac218436a6d596013e239f4ee7d9e4

This commit is contained in:
Adrian Schröter 2024-05-03 13:19:28 +02:00
commit 5a5e453693
229 changed files with 63390 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

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 fe7ed9104cef56f9e532a0c9a7164393d5d69ae1 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 17 Nov 2023 12:32:59 +0800
Subject: [PATCH 1/4] 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 c79d4125a..d90ca06dc 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.42.1

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:
@@ -1454,8 +1493,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");
@@ -1669,21 +1707,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)
{
@@ -1708,11 +1738,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