RHEL 9.0.0 Alpha bootstrap

The content of this branch was automatically imported from Fedora ELN
with the following as its source:
https://src.fedoraproject.org/rpms/grub2#f7e054f3d693af43a903faf33b70673f7aca4508
This commit is contained in:
Petr Šabata 2020-10-15 09:48:35 +02:00
parent 4b3e8abe96
commit 100e37f2e6
285 changed files with 60043 additions and 0 deletions

15
.git.diff.order Normal file
View File

@ -0,0 +1,15 @@
*.dec
*.dsc.inc
*.dsc
*.fdf
*.inf
*.vfr
*.ac
*.def
*.c
*.h
*.S
*.mk
Makefile.*
Make.*
Makefile

1
.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
po/exclude.pot binary

13
.gitignore vendored
View File

@ -0,0 +1,13 @@
grub-*.tar.?z
*.rpm
clog
/unifont-5.1.20080820.pcf.gz
/theme.tar.bz2
kojilogs
/grub-*/
.build*.log
.*.git/
tmp/
.*.sw?
results_grub2/
/gnulib-*.tar.?z

View File

@ -0,0 +1,984 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Matthew Garrett <mjg@redhat.com>
Date: Fri, 5 Jul 2019 18:36:44 +0200
Subject: [PATCH] Add support for Linux EFI stub loading.
Also:
commit 71c843745f22f81e16d259e2e19c99bf3c1855c1
Author: Colin Watson <cjwatson@ubuntu.com>
Date: Tue Oct 23 10:40:49 2012 -0400
Don't allow insmod when secure boot is enabled.
Hi,
Fedora's patch to forbid insmod in UEFI Secure Boot environments is fine
as far as it goes. However, the insmod command is not the only way that
modules can be loaded. In particular, the 'normal' command, which
implements the usual GRUB menu and the fully-featured command prompt,
will implicitly load commands not currently loaded into memory. This
permits trivial Secure Boot violations by writing commands implementing
whatever you want to do and pointing $prefix at the malicious code.
I'm currently test-building this patch (replacing your current
grub-2.00-no-insmod-on-sb.patch), but this should be more correct. It
moves the check into grub_dl_load_file.
---
grub-core/Makefile.core.def | 16 +-
grub-core/kern/dl.c | 21 +++
grub-core/kern/efi/efi.c | 28 ++++
grub-core/kern/efi/mm.c | 32 ++++
grub-core/loader/arm64/linux.c | 118 +++++++-------
grub-core/loader/arm64/xen_boot.c | 1 -
grub-core/loader/efi/linux.c | 70 ++++++++
grub-core/loader/i386/efi/linux.c | 335 ++++++++++++++++++++++++++++++++++++++
grub-core/loader/i386/pc/linux.c | 10 +-
include/grub/arm/linux.h | 9 +
include/grub/arm64/linux.h | 10 ++
include/grub/efi/efi.h | 7 +-
include/grub/efi/linux.h | 31 ++++
13 files changed, 619 insertions(+), 69 deletions(-)
create mode 100644 grub-core/loader/efi/linux.c
create mode 100644 grub-core/loader/i386/efi/linux.c
create mode 100644 include/grub/efi/linux.h
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 474a63e68c5..581d9dfc3b3 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1709,13 +1709,6 @@ module = {
enable = i386_pc;
};
-
-module = {
- name = linux16;
- common = loader/i386/pc/linux.c;
- enable = x86;
-};
-
module = {
name = ntldr;
i386_pc = loader/i386/pc/ntldr.c;
@@ -1771,7 +1764,9 @@ module = {
module = {
name = linux;
- x86 = loader/i386/linux.c;
+ i386_pc = loader/i386/pc/linux.c;
+ x86_64_efi = loader/i386/efi/linux.c;
+ i386_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;
@@ -1786,9 +1781,14 @@ module = {
arm64 = loader/arm64/linux.c;
riscv32 = loader/riscv/linux.c;
riscv64 = loader/riscv/linux.c;
+ emu = loader/emu/linux.c;
+ fdt = lib/fdt.c;
+
common = loader/linux.c;
common = lib/cmdline.c;
enable = noemu;
+
+ efi = loader/efi/linux.c;
};
module = {
diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
index 48eb5e7b627..896bebfd57e 100644
--- a/grub-core/kern/dl.c
+++ b/grub-core/kern/dl.c
@@ -38,6 +38,14 @@
#define GRUB_MODULES_MACHINE_READONLY
#endif
+#ifdef GRUB_MACHINE_EMU
+#include <sys/mman.h>
+#endif
+
+#ifdef GRUB_MACHINE_EFI
+#include <grub/efi/efi.h>
+#endif
+
#pragma GCC diagnostic ignored "-Wcast-align"
@@ -686,6 +694,19 @@ grub_dl_load_file (const char *filename)
void *core = 0;
grub_dl_t mod = 0;
+#ifdef GRUB_MACHINE_EFI
+ if (grub_efi_secure_boot ())
+ {
+#if 0
+ /* This is an error, but grub2-mkconfig still generates a pile of
+ * insmod commands, so emitting it would be mostly just obnoxious. */
+ grub_error (GRUB_ERR_ACCESS_DENIED,
+ "Secure Boot forbids loading module from %s", filename);
+#endif
+ return 0;
+ }
+#endif
+
grub_boot_time ("Loading module %s", filename);
file = grub_file_open (filename, GRUB_FILE_TYPE_GRUB_MODULE);
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
index 6e1ceb90516..a0faa40ecf0 100644
--- a/grub-core/kern/efi/efi.c
+++ b/grub-core/kern/efi/efi.c
@@ -273,6 +273,34 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
return NULL;
}
+grub_efi_boolean_t
+grub_efi_secure_boot (void)
+{
+ grub_efi_guid_t efi_var_guid = GRUB_EFI_GLOBAL_VARIABLE_GUID;
+ grub_size_t datasize;
+ char *secure_boot = NULL;
+ char *setup_mode = NULL;
+ grub_efi_boolean_t ret = 0;
+
+ secure_boot = grub_efi_get_variable("SecureBoot", &efi_var_guid, &datasize);
+
+ if (datasize != 1 || !secure_boot)
+ goto out;
+
+ setup_mode = grub_efi_get_variable("SetupMode", &efi_var_guid, &datasize);
+
+ if (datasize != 1 || !setup_mode)
+ goto out;
+
+ if (*secure_boot && !*setup_mode)
+ ret = 1;
+
+ out:
+ grub_free (secure_boot);
+ grub_free (setup_mode);
+ return ret;
+}
+
#pragma GCC diagnostic ignored "-Wcast-align"
/* Search the mods section from the PE32/PE32+ image. This code uses
diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
index b02fab1b102..a9e37108c6d 100644
--- a/grub-core/kern/efi/mm.c
+++ b/grub-core/kern/efi/mm.c
@@ -113,6 +113,38 @@ grub_efi_drop_alloc (grub_efi_physical_address_t address,
}
}
+/* Allocate pages below a specified address */
+void *
+grub_efi_allocate_pages_max (grub_efi_physical_address_t max,
+ grub_efi_uintn_t pages)
+{
+ grub_efi_status_t status;
+ grub_efi_boot_services_t *b;
+ grub_efi_physical_address_t address = max;
+
+ if (max > 0xffffffff)
+ return 0;
+
+ b = grub_efi_system_table->boot_services;
+ status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, GRUB_EFI_LOADER_DATA, pages, &address);
+
+ if (status != GRUB_EFI_SUCCESS)
+ return 0;
+
+ if (address == 0)
+ {
+ /* Uggh, the address 0 was allocated... This is too annoying,
+ so reallocate another one. */
+ address = max;
+ status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, GRUB_EFI_LOADER_DATA, pages, &address);
+ grub_efi_free_pages (0, pages);
+ if (status != GRUB_EFI_SUCCESS)
+ return 0;
+ }
+
+ return (void *) ((grub_addr_t) address);
+}
+
/* Allocate pages. Return the pointer to the first of allocated pages. */
void *
grub_efi_allocate_pages_real (grub_efi_physical_address_t address,
diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
index ef3e9f9444c..a312c668685 100644
--- a/grub-core/loader/arm64/linux.c
+++ b/grub-core/loader/arm64/linux.c
@@ -29,6 +29,7 @@
#include <grub/efi/efi.h>
#include <grub/efi/fdtload.h>
#include <grub/efi/memory.h>
+#include <grub/efi/linux.h>
#include <grub/efi/pe32.h>
#include <grub/i18n.h>
#include <grub/lib/cmdline.h>
@@ -41,6 +42,7 @@ 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;
@@ -67,7 +69,8 @@ grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh)
static grub_err_t
finalize_params_linux (void)
{
- int node, retval;
+ grub_efi_loaded_image_t *loaded_image = NULL;
+ int node, retval, len;
void *fdt;
@@ -102,79 +105,70 @@ finalize_params_linux (void)
if (grub_fdt_install() != GRUB_ERR_NONE)
goto failure;
- return GRUB_ERR_NONE;
-
-failure:
- grub_fdt_unload();
- return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT");
-}
-
-grub_err_t
-grub_arch_efi_linux_boot_image (grub_addr_t addr, grub_size_t size, char *args)
-{
- grub_efi_memory_mapped_device_path_t *mempath;
- grub_efi_handle_t image_handle;
- grub_efi_boot_services_t *b;
- grub_efi_status_t status;
- grub_efi_loaded_image_t *loaded_image;
- int len;
-
- mempath = grub_malloc (2 * sizeof (grub_efi_memory_mapped_device_path_t));
- if (!mempath)
- return grub_errno;
-
- mempath[0].header.type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE;
- mempath[0].header.subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE;
- mempath[0].header.length = grub_cpu_to_le16_compile_time (sizeof (*mempath));
- mempath[0].memory_type = GRUB_EFI_LOADER_DATA;
- mempath[0].start_address = addr;
- mempath[0].end_address = addr + size;
-
- mempath[1].header.type = GRUB_EFI_END_DEVICE_PATH_TYPE;
- mempath[1].header.subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
- mempath[1].header.length = sizeof (grub_efi_device_path_t);
-
- b = grub_efi_system_table->boot_services;
- status = b->load_image (0, grub_efi_image_handle,
- (grub_efi_device_path_t *) mempath,
- (void *) addr, size, &image_handle);
- if (status != GRUB_EFI_SUCCESS)
- return grub_error (GRUB_ERR_BAD_OS, "cannot load image");
-
- grub_dprintf ("linux", "linux command line: '%s'\n", args);
+ grub_dprintf ("linux", "Installed/updated FDT configuration table @ %p\n",
+ fdt);
/* Convert command line to UCS-2 */
- loaded_image = grub_efi_get_loaded_image (image_handle);
+ loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
+ if (!loaded_image)
+ goto failure;
+
loaded_image->load_options_size = len =
- (grub_strlen (args) + 1) * sizeof (grub_efi_char16_t);
+ (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_errno;
+ 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 *) args, len, NULL);
+ (grub_uint8_t *) linux_args, len, NULL);
- grub_dprintf ("linux", "starting image %p\n", image_handle);
- status = b->start_image (image_handle, 0, NULL);
+ return GRUB_ERR_NONE;
- /* When successful, not reached */
- b->unload_image (image_handle);
- grub_efi_free_pages ((grub_addr_t) loaded_image->load_options,
- GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
+failure:
+ grub_fdt_unload();
+ return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT");
+}
- return grub_errno;
+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, 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)
{
- if (finalize_params_linux () != GRUB_ERR_NONE)
- return grub_errno;
-
- return (grub_arch_efi_linux_boot_image((grub_addr_t)kernel_addr,
- kernel_size, linux_args));
+ return (grub_arch_efi_linux_boot_image((grub_addr_t)kernel_addr, linux_args));
}
static grub_err_t
@@ -288,6 +282,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
{
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);
@@ -333,6 +328,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_dprintf ("linux", "kernel @ %p\n", kernel_addr);
+ if (!grub_linuxefi_secure_validate (kernel_addr, kernel_size))
+ {
+ grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]);
+ goto fail;
+ }
+
+ 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)
diff --git a/grub-core/loader/arm64/xen_boot.c b/grub-core/loader/arm64/xen_boot.c
index 22cc25eccd9..d9b7a9ba400 100644
--- a/grub-core/loader/arm64/xen_boot.c
+++ b/grub-core/loader/arm64/xen_boot.c
@@ -266,7 +266,6 @@ xen_boot (void)
return err;
return grub_arch_efi_linux_boot_image (xen_hypervisor->start,
- xen_hypervisor->size,
xen_hypervisor->cmdline);
}
diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
new file mode 100644
index 00000000000..c24202a5dd1
--- /dev/null
+++ b/grub-core/loader/efi/linux.c
@@ -0,0 +1,70 @@
+/*
+ * 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>
+
+#define SHIM_LOCK_GUID \
+ { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }
+
+struct grub_efi_shim_lock
+{
+ grub_efi_status_t (*verify) (void *buffer, grub_uint32_t size);
+};
+typedef struct grub_efi_shim_lock grub_efi_shim_lock_t;
+
+grub_efi_boolean_t
+grub_linuxefi_secure_validate (void *data, grub_uint32_t size)
+{
+ grub_efi_guid_t guid = SHIM_LOCK_GUID;
+ grub_efi_shim_lock_t *shim_lock;
+
+ shim_lock = grub_efi_locate_protocol(&guid, NULL);
+
+ if (!shim_lock)
+ return 1;
+
+ if (shim_lock->verify(data, size) == GRUB_EFI_SUCCESS)
+ return 1;
+
+ return 0;
+}
+
+#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)
+{
+ handover_func hf;
+
+ 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
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
new file mode 100644
index 00000000000..bb2616a8092
--- /dev/null
+++ b/grub-core/loader/i386/efi/linux.c
@@ -0,0 +1,335 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2012 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/loader.h>
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/types.h>
+#include <grub/mm.h>
+#include <grub/cpu/linux.h>
+#include <grub/command.h>
+#include <grub/i18n.h>
+#include <grub/lib/cmdline.h>
+#include <grub/efi/efi.h>
+#include <grub/efi/linux.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+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 grub_uint32_t handover_offset;
+struct linux_kernel_params *params;
+static char *linux_cmdline;
+
+#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12)
+
+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,
+ params);
+}
+
+static grub_err_t
+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));
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char *argv[])
+{
+ grub_file_t *files = 0;
+ int i, nfiles = 0;
+ grub_size_t size = 0;
+ grub_uint8_t *ptr;
+
+ 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;
+ }
+
+ files = grub_zalloc (argc * sizeof (files[0]));
+ if (!files)
+ goto fail;
+
+ for (i = 0; i < argc; i++)
+ {
+ files[i] = grub_file_open (argv[i], GRUB_FILE_TYPE_LINUX_INITRD | GRUB_FILE_TYPE_NO_DECOMPRESS);
+ if (! files[i])
+ goto fail;
+ nfiles++;
+ size += ALIGN_UP (grub_file_size (files[i]), 4);
+ }
+
+ initrd_mem = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(size));
+ if (!initrd_mem)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate initrd"));
+ goto fail;
+ }
+
+ params->ramdisk_size = size;
+ params->ramdisk_image = (grub_uint32_t)(grub_addr_t) initrd_mem;
+
+ ptr = initrd_mem;
+
+ 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 (!grub_errno)
+ grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
+ argv[i]);
+ goto fail;
+ }
+ ptr += cursize;
+ grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4));
+ ptr += ALIGN_UP_OVERHEAD (cursize, 4);
+ }
+
+ params->ramdisk_size = size;
+
+ fail:
+ for (i = 0; i < nfiles; i++)
+ grub_file_close (files[i]);
+ grub_free (files);
+
+ if (initrd_mem && grub_errno)
+ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)initrd_mem,
+ BYTES_TO_PAGES(size));
+
+ 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_i386_kernel_header lh;
+ grub_ssize_t len, start, filelen;
+ void *kernel = NULL;
+
+ 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;
+
+ filelen = grub_file_size (file);
+
+ kernel = grub_malloc(filelen);
+
+ if (!kernel)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer"));
+ goto fail;
+ }
+
+ if (grub_file_read (file, kernel, filelen) != filelen)
+ {
+ grub_error (GRUB_ERR_FILE_READ_ERROR, N_("Can't read kernel %s"), argv[0]);
+ goto fail;
+ }
+
+ if (! grub_linuxefi_secure_validate (kernel, filelen))
+ {
+ grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"),
+ argv[0]);
+ goto fail;
+ }
+
+ params = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(16384));
+
+ if (! params)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters");
+ goto fail;
+ }
+
+ grub_memset (params, 0, 16384);
+
+ grub_memcpy (&lh, kernel, sizeof (lh));
+
+ 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_error (GRUB_ERR_BAD_OS, N_("too many setup sectors"));
+ goto fail;
+ }
+
+ 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_error (GRUB_ERR_BAD_OS, N_("kernel doesn't support EFI handover"));
+ goto fail;
+ }
+
+ 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"));
+ goto fail;
+ }
+
+ grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE));
+ grub_create_loader_cmdline (argc, argv,
+ linux_cmdline + sizeof (LINUX_IMAGE) - 1,
+ lh.cmdline_size - (sizeof (LINUX_IMAGE) - 1),
+ GRUB_VERIFY_KERNEL_CMDLINE);
+
+ lh.cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linux_cmdline;
+
+ handover_offset = lh.handover_offset;
+
+ start = (lh.setup_sects + 1) * 512;
+ len = grub_file_size(file) - start;
+
+ 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,
+ BYTES_TO_PAGES(lh.init_size));
+
+ if (!kernel_mem)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate kernel"));
+ goto fail;
+ }
+
+ 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_memcpy (params, &lh, 2 * 512);
+
+ params->type_of_loader = 0x21;
+
+ fail:
+
+ if (file)
+ grub_file_close (file);
+
+ if (kernel)
+ grub_free (kernel);
+
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ grub_dl_unref (my_mod);
+ 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 (kernel_mem && !loaded)
+ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)kernel_mem,
+ BYTES_TO_PAGES(kernel_size));
+
+ if (params && !loaded)
+ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)params,
+ BYTES_TO_PAGES(16384));
+
+ return grub_errno;
+}
+
+static grub_command_t cmd_linux, cmd_initrd;
+static grub_command_t cmd_linuxefi, cmd_initrdefi;
+
+GRUB_MOD_INIT(linux)
+{
+ cmd_linux =
+ grub_register_command ("linux", grub_cmd_linux,
+ 0, N_("Load Linux."));
+ cmd_linuxefi =
+ grub_register_command ("linuxefi", grub_cmd_linux,
+ 0, N_("Load Linux."));
+ cmd_initrd =
+ grub_register_command ("initrd", grub_cmd_initrd,
+ 0, N_("Load initrd."));
+ cmd_initrdefi =
+ grub_register_command ("initrdefi", grub_cmd_initrd,
+ 0, N_("Load initrd."));
+ my_mod = mod;
+}
+
+GRUB_MOD_FINI(linux)
+{
+ grub_unregister_command (cmd_linux);
+ grub_unregister_command (cmd_linuxefi);
+ grub_unregister_command (cmd_initrd);
+ grub_unregister_command (cmd_initrdefi);
+}
diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c
index 47ea2945e4f..eea25ea39ca 100644
--- a/grub-core/loader/i386/pc/linux.c
+++ b/grub-core/loader/i386/pc/linux.c
@@ -470,14 +470,20 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
return grub_errno;
}
-static grub_command_t cmd_linux, cmd_initrd;
+static grub_command_t cmd_linux, cmd_linux16, cmd_initrd, cmd_initrd16;
GRUB_MOD_INIT(linux16)
{
cmd_linux =
+ grub_register_command ("linux", grub_cmd_linux,
+ 0, N_("Load Linux."));
+ cmd_linux16 =
grub_register_command ("linux16", grub_cmd_linux,
0, N_("Load Linux."));
cmd_initrd =
+ grub_register_command ("initrd", grub_cmd_initrd,
+ 0, N_("Load initrd."));
+ cmd_initrd16 =
grub_register_command ("initrd16", grub_cmd_initrd,
0, N_("Load initrd."));
my_mod = mod;
@@ -486,5 +492,7 @@ GRUB_MOD_INIT(linux16)
GRUB_MOD_FINI(linux16)
{
grub_unregister_command (cmd_linux);
+ grub_unregister_command (cmd_linux16);
grub_unregister_command (cmd_initrd);
+ grub_unregister_command (cmd_initrd16);
}
diff --git a/include/grub/arm/linux.h b/include/grub/arm/linux.h
index 2e98a668969..775297db869 100644
--- a/include/grub/arm/linux.h
+++ b/include/grub/arm/linux.h
@@ -20,6 +20,7 @@
#ifndef GRUB_ARM_LINUX_HEADER
#define GRUB_ARM_LINUX_HEADER 1
+#include <grub/efi/pe32.h>
#include "system.h"
#define GRUB_LINUX_ARM_MAGIC_SIGNATURE 0x016f2818
@@ -34,9 +35,17 @@ struct linux_arm_kernel_header {
grub_uint32_t hdr_offset;
};
+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_LINUX_ARMXX_MAGIC_SIGNATURE GRUB_LINUX_ARM_MAGIC_SIGNATURE
# define linux_arch_kernel_header linux_arm_kernel_header
+# define grub_armxx_linux_pe_header grub_arm_linux_pe_header
#endif
#if defined GRUB_MACHINE_UBOOT
diff --git a/include/grub/arm64/linux.h b/include/grub/arm64/linux.h
index 4269adc6dae..a3be9dd7003 100644
--- a/include/grub/arm64/linux.h
+++ b/include/grub/arm64/linux.h
@@ -19,6 +19,8 @@
#ifndef GRUB_ARM64_LINUX_HEADER
#define GRUB_ARM64_LINUX_HEADER 1
+#include <grub/efi/pe32.h>
+
#define GRUB_LINUX_ARM64_MAGIC_SIGNATURE 0x644d5241 /* 'ARM\x64' */
/* From linux/Documentation/arm64/booting.txt */
@@ -36,9 +38,17 @@ struct linux_arm64_kernel_header
grub_uint32_t hdr_offset; /* Offset of PE/COFF header */
};
+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 linux_arch_kernel_header linux_arm64_kernel_header
+# define grub_armxx_linux_pe_header grub_arm64_linux_pe_header
#endif
#endif /* ! GRUB_ARM64_LINUX_HEADER */
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
index e90e00dc431..6840bfee9b7 100644
--- a/include/grub/efi/efi.h
+++ b/include/grub/efi/efi.h
@@ -47,6 +47,9 @@ EXPORT_FUNC(grub_efi_allocate_fixed) (grub_efi_physical_address_t address,
grub_efi_uintn_t pages);
void *
EXPORT_FUNC(grub_efi_allocate_any_pages) (grub_efi_uintn_t pages);
+void *
+EXPORT_FUNC(grub_efi_allocate_pages_max) (grub_efi_physical_address_t max,
+ grub_efi_uintn_t pages);
void EXPORT_FUNC(grub_efi_free_pages) (grub_efi_physical_address_t address,
grub_efi_uintn_t pages);
grub_efi_uintn_t EXPORT_FUNC(grub_efi_find_mmap_size) (void);
@@ -82,6 +85,7 @@ EXPORT_FUNC (grub_efi_set_variable) (const char *var,
const grub_efi_guid_t *guid,
void *data,
grub_size_t datasize);
+grub_efi_boolean_t EXPORT_FUNC (grub_efi_secure_boot) (void);
int
EXPORT_FUNC (grub_efi_compare_device_paths) (const grub_efi_device_path_t *dp1,
const grub_efi_device_path_t *dp2);
@@ -95,8 +99,7 @@ void *EXPORT_FUNC(grub_efi_get_firmware_fdt)(void);
grub_err_t EXPORT_FUNC(grub_efi_get_ram_base)(grub_addr_t *);
#include <grub/cpu/linux.h>
grub_err_t grub_arch_efi_linux_check_image(struct linux_arch_kernel_header *lh);
-grub_err_t grub_arch_efi_linux_boot_image(grub_addr_t addr, grub_size_t size,
- char *args);
+grub_err_t grub_arch_efi_linux_boot_image(grub_addr_t addr, char *args);
#endif
grub_addr_t grub_efi_modules_addr (void);
diff --git a/include/grub/efi/linux.h b/include/grub/efi/linux.h
new file mode 100644
index 00000000000..d9ede36773b
--- /dev/null
+++ b/include/grub/efi/linux.h
@@ -0,0 +1,31 @@
+/*
+ * 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_efi_boolean_t
+EXPORT_FUNC(grub_linuxefi_secure_validate) (void *data, grub_uint32_t size);
+grub_err_t
+EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_off_t offset,
+ void *kernel_param);
+
+#endif /* ! GRUB_EFI_LINUX_HEADER */

View File

@ -0,0 +1,114 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Matthew Garrett <mjg59@coreos.com>
Date: Fri, 5 Jul 2019 20:54:51 +0200
Subject: [PATCH] Rework linux command
We want a single buffer that contains the entire kernel image in order to
perform a TPM measurement. Allocate one and copy the entire kernel into it
before pulling out the individual blocks later on.
---
grub-core/loader/i386/linux.c | 36 +++++++++++++++++++++++-------------
1 file changed, 23 insertions(+), 13 deletions(-)
diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
index d0501e22957..b255c950526 100644
--- a/grub-core/loader/i386/linux.c
+++ b/grub-core/loader/i386/linux.c
@@ -641,13 +641,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
{
grub_file_t file = 0;
struct linux_i386_kernel_header lh;
+ grub_uint8_t *linux_params_ptr;
grub_uint8_t setup_sects;
- grub_size_t real_size, prot_size, prot_file_size;
+ grub_size_t real_size, prot_size, prot_file_size, kernel_offset;
grub_ssize_t len;
int i;
grub_size_t align, min_align;
int relocatable;
grub_uint64_t preferred_address = GRUB_LINUX_BZIMAGE_ADDR;
+ grub_uint8_t *kernel = NULL;
grub_dl_ref (my_mod);
@@ -661,7 +663,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
if (! file)
goto fail;
- if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
+ len = grub_file_size (file);
+ kernel = grub_malloc (len);
+ if (!kernel)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer"));
+ goto fail;
+ }
+
+ if (grub_file_read (file, kernel, len) != len)
{
if (!grub_errno)
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
@@ -669,6 +679,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
+ grub_memcpy (&lh, kernel, sizeof (lh));
+ kernel_offset = sizeof (lh);
+
if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55))
{
grub_error (GRUB_ERR_BAD_OS, "invalid magic number");
@@ -760,6 +773,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
preferred_address))
goto fail;
+
grub_memset (&linux_params, 0, sizeof (linux_params));
grub_memcpy (&linux_params.setup_sects, &lh.setup_sects, sizeof (lh) - 0x1F1);
@@ -782,13 +796,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
/* We've already read lh so there is no need to read it second time. */
len -= sizeof(lh);
- if (grub_file_read (file, (char *) &linux_params + sizeof (lh), len) != len)
- {
- if (!grub_errno)
- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
- argv[0]);
- goto fail;
- }
+ linux_params_ptr = (void *)&linux_params;
+ grub_memcpy (linux_params_ptr + sizeof (lh), kernel + kernel_offset, len);
+ kernel_offset += len;
linux_params.type_of_loader = GRUB_LINUX_BOOT_LOADER_TYPE;
@@ -847,7 +857,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
/* The other parameters are filled when booting. */
- grub_file_seek (file, real_size + GRUB_DISK_SECTOR_SIZE);
+ kernel_offset = real_size + GRUB_DISK_SECTOR_SIZE;
grub_dprintf ("linux", "bzImage, setup=0x%x, size=0x%x\n",
(unsigned) real_size, (unsigned) prot_size);
@@ -1001,9 +1011,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
}
len = prot_file_size;
- if (grub_file_read (file, prot_mode_mem, len) != len && !grub_errno)
- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
- argv[0]);
+ grub_memcpy (prot_mode_mem, kernel + kernel_offset, len);
if (grub_errno == GRUB_ERR_NONE)
{
@@ -1014,6 +1022,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
fail:
+ grub_free (kernel);
+
if (file)
grub_file_close (file);

View File

@ -0,0 +1,97 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Matthew Garrett <mjg59@coreos.com>
Date: Fri, 5 Jul 2019 21:12:00 +0200
Subject: [PATCH] Rework linux16 command
We want a single buffer that contains the entire kernel image in order to
perform a TPM measurement. Allocate one and copy the entire kernel int it
before pulling out the individual blocks later on.
---
grub-core/loader/i386/pc/linux.c | 33 +++++++++++++++++++++------------
1 file changed, 21 insertions(+), 12 deletions(-)
diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c
index eea25ea39ca..73fb91e0570 100644
--- a/grub-core/loader/i386/pc/linux.c
+++ b/grub-core/loader/i386/pc/linux.c
@@ -123,13 +123,14 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_file_t file = 0;
struct linux_i386_kernel_header lh;
grub_uint8_t setup_sects;
- grub_size_t real_size;
+ grub_size_t real_size, kernel_offset = 0;
grub_ssize_t len;
int i;
char *grub_linux_prot_chunk;
int grub_linux_is_bzimage;
grub_addr_t grub_linux_prot_target;
grub_err_t err;
+ grub_uint8_t *kernel = NULL;
grub_dl_ref (my_mod);
@@ -143,7 +144,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
if (! file)
goto fail;
- if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
+ len = grub_file_size (file);
+ kernel = grub_malloc (len);
+ if (!kernel)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer"));
+ goto fail;
+ }
+
+ if (grub_file_read (file, kernel, len) != len)
{
if (!grub_errno)
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
@@ -151,6 +160,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
+ grub_memcpy (&lh, kernel, sizeof (lh));
+ kernel_offset = sizeof (lh);
+
if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55))
{
grub_error (GRUB_ERR_BAD_OS, "invalid magic number");
@@ -314,13 +326,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_memmove (grub_linux_real_chunk, &lh, sizeof (lh));
len = real_size + GRUB_DISK_SECTOR_SIZE - sizeof (lh);
- if (grub_file_read (file, grub_linux_real_chunk + sizeof (lh), len) != len)
- {
- if (!grub_errno)
- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
- argv[0]);
- goto fail;
- }
+ grub_memcpy (grub_linux_real_chunk + sizeof (lh), kernel + kernel_offset,
+ len);
+ kernel_offset += len;
if (lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_I386_MAGIC_SIGNATURE)
|| grub_le_to_cpu16 (lh.version) < 0x0200)
@@ -358,9 +366,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
}
len = grub_linux16_prot_size;
- if (grub_file_read (file, grub_linux_prot_chunk, len) != len && !grub_errno)
- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
- argv[0]);
+ grub_memcpy (grub_linux_prot_chunk, kernel + kernel_offset, len);
+ kernel_offset += len;
if (grub_errno == GRUB_ERR_NONE)
{
@@ -370,6 +377,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
fail:
+ grub_free (kernel);
+
if (file)
grub_file_close (file);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,516 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Tue, 6 Oct 2015 16:09:25 -0400
Subject: [PATCH] Make any of the loaders that link in efi mode honor secure
boot.
And in this case "honor" means "even if somebody does link this in, they
won't register commands if SB is enabled."
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/Makefile.core.def | 1 +
grub-core/commands/iorw.c | 7 +++++
grub-core/commands/memrw.c | 7 +++++
grub-core/kern/dl.c | 1 +
grub-core/kern/efi/efi.c | 34 --------------------
grub-core/kern/efi/sb.c | 64 ++++++++++++++++++++++++++++++++++++++
grub-core/loader/efi/appleloader.c | 7 +++++
grub-core/loader/efi/chainloader.c | 1 +
grub-core/loader/i386/bsd.c | 7 +++++
grub-core/loader/i386/linux.c | 7 +++++
grub-core/loader/i386/pc/linux.c | 7 +++++
grub-core/loader/multiboot.c | 7 +++++
grub-core/loader/xnu.c | 7 +++++
include/grub/efi/efi.h | 1 -
include/grub/efi/sb.h | 29 +++++++++++++++++
include/grub/ia64/linux.h | 0
include/grub/mips/linux.h | 0
include/grub/powerpc/linux.h | 0
include/grub/sparc64/linux.h | 0
grub-core/Makefile.am | 1 +
20 files changed, 153 insertions(+), 35 deletions(-)
create mode 100644 grub-core/kern/efi/sb.c
create mode 100644 include/grub/efi/sb.h
create mode 100644 include/grub/ia64/linux.h
create mode 100644 include/grub/mips/linux.h
create mode 100644 include/grub/powerpc/linux.h
create mode 100644 include/grub/sparc64/linux.h
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 581d9dfc3b3..eb1088fd654 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -207,6 +207,7 @@ kernel = {
i386_multiboot = kern/i386/pc/acpi.c;
i386_coreboot = kern/acpi.c;
i386_multiboot = kern/acpi.c;
+ common = kern/efi/sb.c;
x86 = kern/i386/tsc.c;
x86 = kern/i386/tsc_pit.c;
diff --git a/grub-core/commands/iorw.c b/grub-core/commands/iorw.c
index a0c164e54f0..41a7f3f0466 100644
--- a/grub-core/commands/iorw.c
+++ b/grub-core/commands/iorw.c
@@ -23,6 +23,7 @@
#include <grub/env.h>
#include <grub/cpu/io.h>
#include <grub/i18n.h>
+#include <grub/efi/sb.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -118,6 +119,9 @@ grub_cmd_write (grub_command_t cmd, int argc, char **argv)
GRUB_MOD_INIT(memrw)
{
+ if (grub_efi_secure_boot())
+ return;
+
cmd_read_byte =
grub_register_extcmd ("inb", grub_cmd_read, 0,
N_("PORT"), N_("Read 8-bit value from PORT."),
@@ -146,6 +150,9 @@ GRUB_MOD_INIT(memrw)
GRUB_MOD_FINI(memrw)
{
+ if (grub_efi_secure_boot())
+ return;
+
grub_unregister_extcmd (cmd_read_byte);
grub_unregister_extcmd (cmd_read_word);
grub_unregister_extcmd (cmd_read_dword);
diff --git a/grub-core/commands/memrw.c b/grub-core/commands/memrw.c
index 98769eadb34..088cbe9e2bc 100644
--- a/grub-core/commands/memrw.c
+++ b/grub-core/commands/memrw.c
@@ -22,6 +22,7 @@
#include <grub/extcmd.h>
#include <grub/env.h>
#include <grub/i18n.h>
+#include <grub/efi/sb.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -120,6 +121,9 @@ grub_cmd_write (grub_command_t cmd, int argc, char **argv)
GRUB_MOD_INIT(memrw)
{
+ if (grub_efi_secure_boot())
+ return;
+
cmd_read_byte =
grub_register_extcmd ("read_byte", grub_cmd_read, 0,
N_("ADDR"), N_("Read 8-bit value from ADDR."),
@@ -148,6 +152,9 @@ GRUB_MOD_INIT(memrw)
GRUB_MOD_FINI(memrw)
{
+ if (grub_efi_secure_boot())
+ return;
+
grub_unregister_extcmd (cmd_read_byte);
grub_unregister_extcmd (cmd_read_word);
grub_unregister_extcmd (cmd_read_dword);
diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
index 896bebfd57e..d7718d26abc 100644
--- a/grub-core/kern/dl.c
+++ b/grub-core/kern/dl.c
@@ -32,6 +32,7 @@
#include <grub/env.h>
#include <grub/cache.h>
#include <grub/i18n.h>
+#include <grub/efi/sb.h>
/* Platforms where modules are in a readonly area of memory. */
#if defined(GRUB_MACHINE_QEMU)
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
index 3487b0623a4..6e1ceb90516 100644
--- a/grub-core/kern/efi/efi.c
+++ b/grub-core/kern/efi/efi.c
@@ -273,40 +273,6 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
return NULL;
}
-grub_efi_boolean_t
-grub_efi_secure_boot (void)
-{
- grub_efi_guid_t efi_var_guid = GRUB_EFI_GLOBAL_VARIABLE_GUID;
- grub_size_t datasize;
- char *secure_boot = NULL;
- char *setup_mode = NULL;
- grub_efi_boolean_t ret = 0;
-
- secure_boot = grub_efi_get_variable("SecureBoot", &efi_var_guid, &datasize);
- if (datasize != 1 || !secure_boot)
- {
- grub_dprintf ("secureboot", "No SecureBoot variable\n");
- goto out;
- }
- grub_dprintf ("secureboot", "SecureBoot: %d\n", *secure_boot);
-
- setup_mode = grub_efi_get_variable("SetupMode", &efi_var_guid, &datasize);
- if (datasize != 1 || !setup_mode)
- {
- grub_dprintf ("secureboot", "No SetupMode variable\n");
- goto out;
- }
- grub_dprintf ("secureboot", "SetupMode: %d\n", *setup_mode);
-
- if (*secure_boot && !*setup_mode)
- ret = 1;
-
- out:
- grub_free (secure_boot);
- grub_free (setup_mode);
- return ret;
-}
-
#pragma GCC diagnostic ignored "-Wcast-align"
/* Search the mods section from the PE32/PE32+ image. This code uses
diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c
new file mode 100644
index 00000000000..d74778b0cac
--- /dev/null
+++ b/grub-core/kern/efi/sb.c
@@ -0,0 +1,64 @@
+/*
+ * 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>
+#include <grub/efi/sb.h>
+
+int
+grub_efi_secure_boot (void)
+{
+#ifdef GRUB_MACHINE_EFI
+ grub_efi_guid_t efi_var_guid = GRUB_EFI_GLOBAL_VARIABLE_GUID;
+ grub_size_t datasize;
+ char *secure_boot = NULL;
+ char *setup_mode = NULL;
+ grub_efi_boolean_t ret = 0;
+
+ secure_boot = grub_efi_get_variable("SecureBoot", &efi_var_guid, &datasize);
+ if (datasize != 1 || !secure_boot)
+ {
+ grub_dprintf ("secureboot", "No SecureBoot variable\n");
+ goto out;
+ }
+ grub_dprintf ("secureboot", "SecureBoot: %d\n", *secure_boot);
+
+ setup_mode = grub_efi_get_variable("SetupMode", &efi_var_guid, &datasize);
+ if (datasize != 1 || !setup_mode)
+ {
+ grub_dprintf ("secureboot", "No SetupMode variable\n");
+ goto out;
+ }
+ grub_dprintf ("secureboot", "SetupMode: %d\n", *setup_mode);
+
+ if (*secure_boot && !*setup_mode)
+ ret = 1;
+
+ out:
+ grub_free (secure_boot);
+ grub_free (setup_mode);
+ return ret;
+#else
+ return 0;
+#endif
+}
diff --git a/grub-core/loader/efi/appleloader.c b/grub-core/loader/efi/appleloader.c
index 74888c463ba..69c2a10d351 100644
--- a/grub-core/loader/efi/appleloader.c
+++ b/grub-core/loader/efi/appleloader.c
@@ -24,6 +24,7 @@
#include <grub/misc.h>
#include <grub/efi/api.h>
#include <grub/efi/efi.h>
+#include <grub/efi/sb.h>
#include <grub/command.h>
#include <grub/i18n.h>
@@ -227,6 +228,9 @@ static grub_command_t cmd;
GRUB_MOD_INIT(appleloader)
{
+ if (grub_efi_secure_boot())
+ return;
+
cmd = grub_register_command ("appleloader", grub_cmd_appleloader,
N_("[OPTS]"),
/* TRANSLATORS: This command is used on EFI to
@@ -238,5 +242,8 @@ GRUB_MOD_INIT(appleloader)
GRUB_MOD_FINI(appleloader)
{
+ if (grub_efi_secure_boot())
+ return;
+
grub_unregister_command (cmd);
}
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
index ef87b06cf70..5aa3a5dc7dd 100644
--- a/grub-core/loader/efi/chainloader.c
+++ b/grub-core/loader/efi/chainloader.c
@@ -34,6 +34,7 @@
#include <grub/efi/disk.h>
#include <grub/efi/pe32.h>
#include <grub/efi/linux.h>
+#include <grub/efi/sb.h>
#include <grub/command.h>
#include <grub/i18n.h>
#include <grub/net.h>
diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c
index 3730ed38247..5b9b92d6ba5 100644
--- a/grub-core/loader/i386/bsd.c
+++ b/grub-core/loader/i386/bsd.c
@@ -39,6 +39,7 @@
#ifdef GRUB_MACHINE_PCBIOS
#include <grub/machine/int.h>
#endif
+#include <grub/efi/sb.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -2130,6 +2131,9 @@ static grub_command_t cmd_netbsd_module_elf, cmd_openbsd_ramdisk;
GRUB_MOD_INIT (bsd)
{
+ if (grub_efi_secure_boot())
+ return;
+
/* Net and OpenBSD kernels are often compressed. */
grub_dl_load ("gzio");
@@ -2169,6 +2173,9 @@ GRUB_MOD_INIT (bsd)
GRUB_MOD_FINI (bsd)
{
+ if (grub_efi_secure_boot())
+ return;
+
grub_unregister_extcmd (cmd_freebsd);
grub_unregister_extcmd (cmd_openbsd);
grub_unregister_extcmd (cmd_netbsd);
diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
index b255c950526..376c726928a 100644
--- a/grub-core/loader/i386/linux.c
+++ b/grub-core/loader/i386/linux.c
@@ -36,6 +36,7 @@
#include <grub/lib/cmdline.h>
#include <grub/linux.h>
#include <grub/machine/kernel.h>
+#include <grub/efi/sb.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -1131,6 +1132,9 @@ static grub_command_t cmd_linux, cmd_initrd;
GRUB_MOD_INIT(linux)
{
+ if (grub_efi_secure_boot())
+ return;
+
cmd_linux = grub_register_command ("linux", grub_cmd_linux,
0, N_("Load Linux."));
cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd,
@@ -1140,6 +1144,9 @@ GRUB_MOD_INIT(linux)
GRUB_MOD_FINI(linux)
{
+ if (grub_efi_secure_boot())
+ return;
+
grub_unregister_command (cmd_linux);
grub_unregister_command (cmd_initrd);
}
diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c
index 73fb91e0570..fe3e1d41d09 100644
--- a/grub-core/loader/i386/pc/linux.c
+++ b/grub-core/loader/i386/pc/linux.c
@@ -35,6 +35,7 @@
#include <grub/i386/floppy.h>
#include <grub/lib/cmdline.h>
#include <grub/linux.h>
+#include <grub/efi/sb.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -483,6 +484,9 @@ static grub_command_t cmd_linux, cmd_linux16, cmd_initrd, cmd_initrd16;
GRUB_MOD_INIT(linux16)
{
+ if (grub_efi_secure_boot())
+ return;
+
cmd_linux =
grub_register_command ("linux", grub_cmd_linux,
0, N_("Load Linux."));
@@ -500,6 +504,9 @@ GRUB_MOD_INIT(linux16)
GRUB_MOD_FINI(linux16)
{
+ if (grub_efi_secure_boot())
+ return;
+
grub_unregister_command (cmd_linux);
grub_unregister_command (cmd_linux16);
grub_unregister_command (cmd_initrd);
diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c
index 4a98d708259..3e6ad166dc9 100644
--- a/grub-core/loader/multiboot.c
+++ b/grub-core/loader/multiboot.c
@@ -50,6 +50,7 @@
#include <grub/video.h>
#include <grub/memory.h>
#include <grub/i18n.h>
+#include <grub/efi/sb.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -444,6 +445,9 @@ static grub_command_t cmd_multiboot, cmd_module;
GRUB_MOD_INIT(multiboot)
{
+ if (grub_efi_secure_boot())
+ return;
+
cmd_multiboot =
#ifdef GRUB_USE_MULTIBOOT2
grub_register_command ("multiboot2", grub_cmd_multiboot,
@@ -464,6 +468,9 @@ GRUB_MOD_INIT(multiboot)
GRUB_MOD_FINI(multiboot)
{
+ if (grub_efi_secure_boot())
+ return;
+
grub_unregister_command (cmd_multiboot);
grub_unregister_command (cmd_module);
}
diff --git a/grub-core/loader/xnu.c b/grub-core/loader/xnu.c
index 7f74d1d6fc9..e0f47e72b06 100644
--- a/grub-core/loader/xnu.c
+++ b/grub-core/loader/xnu.c
@@ -34,6 +34,7 @@
#include <grub/env.h>
#include <grub/i18n.h>
#include <grub/verify.h>
+#include <grub/efi/sb.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -1478,6 +1479,9 @@ static grub_extcmd_t cmd_splash;
GRUB_MOD_INIT(xnu)
{
+ if (grub_efi_secure_boot())
+ return;
+
cmd_kernel = grub_register_command ("xnu_kernel", grub_cmd_xnu_kernel, 0,
N_("Load XNU image."));
cmd_kernel64 = grub_register_command ("xnu_kernel64", grub_cmd_xnu_kernel64,
@@ -1518,6 +1522,9 @@ GRUB_MOD_INIT(xnu)
GRUB_MOD_FINI(xnu)
{
+ if (grub_efi_secure_boot())
+ return;
+
#ifndef GRUB_MACHINE_EMU
grub_unregister_command (cmd_resume);
#endif
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
index 6840bfee9b7..090c8621066 100644
--- a/include/grub/efi/efi.h
+++ b/include/grub/efi/efi.h
@@ -85,7 +85,6 @@ EXPORT_FUNC (grub_efi_set_variable) (const char *var,
const grub_efi_guid_t *guid,
void *data,
grub_size_t datasize);
-grub_efi_boolean_t EXPORT_FUNC (grub_efi_secure_boot) (void);
int
EXPORT_FUNC (grub_efi_compare_device_paths) (const grub_efi_device_path_t *dp1,
const grub_efi_device_path_t *dp2);
diff --git a/include/grub/efi/sb.h b/include/grub/efi/sb.h
new file mode 100644
index 00000000000..9629fbb0f9e
--- /dev/null
+++ b/include/grub/efi/sb.h
@@ -0,0 +1,29 @@
+/* sb.h - declare functions for EFI Secure Boot support */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2006,2007,2008,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/>.
+ */
+
+#ifndef GRUB_EFI_SB_HEADER
+#define GRUB_EFI_SB_HEADER 1
+
+#include <grub/types.h>
+#include <grub/dl.h>
+
+/* Functions. */
+int EXPORT_FUNC (grub_efi_secure_boot) (void);
+
+#endif /* ! GRUB_EFI_SB_HEADER */
diff --git a/include/grub/ia64/linux.h b/include/grub/ia64/linux.h
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/include/grub/mips/linux.h b/include/grub/mips/linux.h
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/include/grub/powerpc/linux.h b/include/grub/powerpc/linux.h
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/include/grub/sparc64/linux.h b/include/grub/sparc64/linux.h
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index 3ea8e7ff45f..c6ba5b2d763 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -71,6 +71,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/command.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/device.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/disk.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/dl.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/sb.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/env.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/env_private.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/err.h

View File

@ -0,0 +1,264 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 8 Jul 2019 12:32:37 +0200
Subject: [PATCH] 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 | 9 +++-
grub-core/loader/i386/efi/linux.c | 110 ++++++++++++++++++++++++++------------
include/grub/i386/linux.h | 7 ++-
3 files changed, 89 insertions(+), 37 deletions(-)
diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
index c8ecce6dfd0..0622dfa48d4 100644
--- a/grub-core/loader/efi/linux.c
+++ b/grub-core/loader/efi/linux.c
@@ -69,12 +69,17 @@ grub_linuxefi_secure_validate (void *data, grub_uint32_t size)
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)
{
handover_func hf;
+ int offset = 0;
- hf = (handover_func)((char *)kernel_addr + offset);
+#ifdef __x86_64__
+ offset = 512;
+#endif
+
+ hf = (handover_func)((char *)kernel_addr + handover_offset + offset);
hf (grub_efi_image_handle, grub_efi_system_table, kernel_params);
return GRUB_ERR_BUG;
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
index 6b24cbb9483..3017d0f3e52 100644
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -44,14 +44,10 @@ static char *linux_cmdline;
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);
}
@@ -153,14 +149,20 @@ 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[])
{
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;
int rc;
grub_dl_ref (my_mod);
@@ -200,48 +202,79 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
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_dprintf ("linux", "params = %lx\n", (unsigned long) params);
+ grub_dprintf ("linux", "params = %p\n", params);
- grub_memset (params, 0, 16384);
+ grub_memset (params, 0, sizeof(*params));
- grub_memcpy (&lh, kernel, sizeof (lh));
-
- 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;
}
+#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));
-
+ BYTES_TO_PAGES(lh->cmdline_size + 1));
if (!linux_cmdline)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate cmdline"));
@@ -254,22 +287,24 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE));
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);
- 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_pages_max(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)
kernel_mem = grub_efi_allocate_pages_max(0x3fffffff,
- BYTES_TO_PAGES(lh.init_size));
+ BYTES_TO_PAGES(lh->init_size));
if (!kernel_mem)
{
@@ -277,14 +312,21 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
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_memcpy (params, &lh, 2 * 512);
+ grub_memcpy (kernel_mem, (char *)kernel + start, filelen - start);
- params->type_of_loader = 0x21;
+ grub_dprintf ("linux", "setting lh->type_of_loader\n");
+ lh->type_of_loader = 0x6;
+
+ 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);
@@ -301,10 +343,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
loaded = 0;
}
- if (linux_cmdline && !loaded)
+ 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));
+ 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,
diff --git a/include/grub/i386/linux.h b/include/grub/i386/linux.h
index ce30e7fb01b..a093679cb80 100644
--- a/include/grub/i386/linux.h
+++ b/include/grub/i386/linux.h
@@ -136,7 +136,12 @@ struct linux_i386_kernel_header
grub_uint32_t kernel_alignment;
grub_uint8_t relocatable;
grub_uint8_t min_alignment;
- grub_uint8_t pad[2];
+#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;
grub_uint64_t hardware_subarch_data;

View File

@ -0,0 +1,470 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 8 Jul 2019 12:55:29 +0200
Subject: [PATCH] re-write .gitignore
---
.gitignore | 366 +++++++++++++++-----------------------
docs/.gitignore | 5 +
grub-core/.gitignore | 16 ++
grub-core/lib/.gitignore | 1 +
include/grub/gcrypt/.gitignore | 2 +
po/.gitignore | 5 +
util/bash-completion.d/.gitignore | 2 +
7 files changed, 171 insertions(+), 226 deletions(-)
create mode 100644 docs/.gitignore
create mode 100644 grub-core/.gitignore
create mode 100644 grub-core/lib/.gitignore
create mode 100644 include/grub/gcrypt/.gitignore
create mode 100644 po/.gitignore
create mode 100644 util/bash-completion.d/.gitignore
diff --git a/.gitignore b/.gitignore
index 819cd185d44..b45a633f3d1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,237 +1,151 @@
+# things ./autogen.sh will create
+/Makefile.utilgcry.def
+/ABOUT-NLS
+/aclocal.m4
+/autom4te.cache
+/build-aux
+/configure
+/gnulib
+/grub-core/lib/gnulib/
+/Makefile
+
+# things very common editors create that we never want
*~
-00_header
-10_*
-20_linux_xen
-30_os-prober
-40_custom
-41_custom
-*.1
-*.8
-ABOUT-NLS
-aclocal.m4
-ahci_test
-ascii.bitmaps
-ascii.h
-autom4te.cache
-build-aux
-build-grub-gen-asciih
-build-grub-gen-widthspec
-build-grub-mkfont
-cdboot_test
-cmp_test
-config.cache
-config.guess
-config.h
-config-util.h
-config-util.h.in
-config.log
-config.status
-config.sub
-configure
-core_compress_test
-DISTLIST
-docs/*.info
-docs/stamp-vti
-docs/version.texi
-ehci_test
-example_grub_script_test
-example_scripted_test
-example_unit_test
+.*.sw?
+*.patch
+
+# stuff you're likely to make while building test trees
+grub.cfg
+/build*/
+
+# built objects across the whole tree
+Makefile.in
+*.a
+*.am
+*.efi
*.exec
-*.exec.exe
-fddboot_test
-genkernsyms.sh
-gensymlist.sh
-gentrigtables
-gentrigtables.exe
-gettext_strings_test
-/gnulib
-grub-bin2h
-/grub-bios-setup
-/grub-bios-setup.exe
-grub_cmd_date
-grub_cmd_echo
-grub_cmd_regexp
-grub_cmd_set_date
-grub_cmd_sleep
-/grub-editenv
-/grub-editenv.exe
-grub-emu
-grub-emu-lite
-grub-emu.exe
-grub-emu-lite.exe
-grub_emu_init.c
-grub_emu_init.h
-/grub-file
-/grub-file.exe
-grub-fstest
-grub-fstest.exe
-grub_fstest_init.c
-grub_fstest_init.h
-grub_func_test
-grub-install
-grub-install.exe
-grub-kbdcomp
-/grub-macbless
-/grub-macbless.exe
-grub-macho2img
-/grub-menulst2cfg
-/grub-menulst2cfg.exe
-/grub-mk*
-grub-mount
-/grub-ofpathname
-/grub-ofpathname.exe
-grub-core/build-grub-pe2elf.exe
-/grub-probe
-/grub-probe.exe
-grub_probe_init.c
-grub_probe_init.h
-/grub-reboot
-grub_script_blanklines
-grub_script_blockarg
-grub_script_break
-grub-script-check
-grub-script-check.exe
-grub_script_check_init.c
-grub_script_check_init.h
-grub_script_comments
-grub_script_continue
-grub_script_dollar
-grub_script_echo1
-grub_script_echo_keywords
-grub_script_escape_comma
-grub_script_eval
-grub_script_expansion
-grub_script_final_semicolon
-grub_script_for1
-grub_script_functions
-grub_script_gettext
-grub_script_if
-grub_script_leading_whitespace
-grub_script_no_commands
-grub_script_not
-grub_script_return
-grub_script_setparams
-grub_script_shift
-grub_script_strcmp
-grub_script_test
-grub_script_vars1
-grub_script_while1
-grub_script.tab.c
-grub_script.tab.h
-grub_script.yy.c
-grub_script.yy.h
-grub-set-default
-grub_setup_init.c
-grub_setup_init.h
-grub-shell
-grub-shell-tester
-grub-sparc64-setup
-grub-sparc64-setup.exe
-/grub-syslinux2cfg
-/grub-syslinux2cfg.exe
-gzcompress_test
-hddboot_test
-help_test
-*.img
*.image
-*.image.exe
-include/grub/cpu
-include/grub/machine
-INSTALL.grub
-install-sh
-lib/libgcrypt-grub
-libgrub_a_init.c
-*.log
+*.img
+*.info
*.lst
-lzocompress_test
*.marker
-Makefile
/m4
*.mod
-mod-*.c
-missing
-netboot_test
+*.module
*.o
-*.a
-ohci_test
-partmap_test
-pata_test
*.pf2
-*.pp
-po/*.mo
-po/grub.pot
-po/Makefile.in.in
-po/Makevars
-po/Makevars.template
-po/POTFILES
-po/Rules-quot
-po/stamp-po
-printf_test
-priority_queue_unit_test
-pseries_test
-stamp-h
-stamp-h1
-stamp-h.in
-symlist.c
-symlist.h
-trigtables.c
-*.trs
-uhci_test
-update-grub_lib
-unidata.c
-xzcompress_test
-Makefile.in
-GPATH
-GRTAGS
-GSYMS
-GTAGS
-compile
-depcomp
-mdate-sh
-texinfo.tex
-grub-core/lib/libgcrypt-grub
-.deps
-.deps-util
-.deps-core
+*.yy.[ch]
+.deps/
+.deps-core/
+.deps-util/
.dirstamp
-Makefile.util.am
-contrib
-grub-core/bootinfo.txt
-grub-core/Makefile.core.am
-grub-core/Makefile.gcry.def
-grub-core/contrib
-grub-core/gdb_grub
-grub-core/genmod.sh
-grub-core/gensyminfo.sh
-grub-core/gmodule.pl
-grub-core/grub.chrp
-grub-core/modinfo.sh
-grub-core/*.module
-grub-core/*.module.exe
-grub-core/*.pp
-grub-core/kernel.img.bin
-util/bash-completion.d/grub
-grub-core/lib/gnulib
-grub-core/rs_decoder.h
-widthspec.bin
-widthspec.h
-docs/stamp-1
-docs/version-dev.texi
-Makefile.utilgcry.def
-po/*.po
-po/*.gmo
-po/LINGUAS
-po/remove-potcdate.sed
-include/grub/gcrypt/gcrypt.h
-include/grub/gcrypt/g10lib.h
-po/POTFILES.in
-po/POTFILES-shell.in
-/grub-glue-efi
-/grub-render-label
-/grub-glue-efi.exe
-/grub-render-label.exe
+
+# next are things you get if you do ./configure in the topdir (for e.g.
+# "make dist" invocation.
+/config-util.h
+/config.h
+/include/grub/cpu
+/include/grub/machine
+/INSTALL
+/INSTALL.grub
+/po/Makefile.in.in
+/po/Makevars
+/po/Makevars.template
+/po/POTFILES
+/po/Rules-quot
+/stamp-h
+/stamp-h1
+bootstrap.log
+config.log
+config.status
+
+# stuff "make dist" creates
+ChangeLog
+grub-*.tar
+grub-*.tar.*
+
+# stuff "make" creates
+/[[:digit:]][[:digit:]]_?*
+/ascii.h
+/build-grub-gen-asciih
+/build-grub-gen-widthspec
+/build-grub-mkfont
+/config-util.h.in
/garbage-gen
-/garbage-gen.exe
-/grub-fs-tester
-grub-core/build-grub-module-verifier
+/grub*-bios-setup
+/grub*-bios-setup.8
+/grub*-editenv
+/grub*-editenv.1
+/grub*-file
+/grub*-file.1
+/grub*-fs-tester
+/grub*-fstest
+/grub*-fstest.1
+/grub*-get-kernel-settings
+/grub*-get-kernel-settings.3
+/grub*-glue-efi
+/grub*-glue-efi.1
+/grub*-install
+/grub*-install.8
+/grub*-kbdcomp
+/grub*-kbdcomp.1
+/grub*-macbless
+/grub*-macbless.8
+/grub*-menulst2cfg
+/grub*-menulst2cfg.1
+/grub*-mount
+/grub*-mount.1
+/grub*-mkconfig
+/grub*-mkconfig.8
+/grub*-mkconfig_lib
+/grub*-mkfont
+/grub*-mkfont.1
+/grub*-mkimage
+/grub*-mkimage.1
+/grub*-mklayout
+/grub*-mklayout.1
+/grub*-mknetdir
+/grub*-mknetdir.1
+/grub*-mkpasswd-pbkdf2
+/grub*-mkpasswd-pbkdf2.1
+/grub*-mkrelpath
+/grub*-mkrelpath.1
+/grub*-mkrescue
+/grub*-mkrescue.1
+/grub*-mkstandalone
+/grub*-mkstandalone.1
+/grub*-ofpathname
+/grub*-ofpathname.8
+/grub*-probe
+/grub*-probe.8
+/grub*-reboot
+/grub*-reboot.8
+/grub*-render-label
+/grub*-render-label.1
+/grub*-rpm-sort
+/grub*-rpm-sort.8
+/grub*-script-check
+/grub*-script-check.1
+/grub*-set-bootflag
+/grub*-set-bootflag.1
+/grub*-set-default
+/grub*-set-default.8
+/grub*-set-password
+/grub*-set-password.8
+/grub*-shell
+/grub*-shell-tester
+/grub*-sparc64-setup
+/grub*-sparc64-setup.8
+/grub*-syslinux2cfg
+/grub*-syslinux2cfg.1
+/grub*-switch-to-blscfg
+/grub*-switch-to-blscfg.8
+/grub_fstest.pp
+/grub_fstest_init.c
+/grub_fstest_init.lst
+/grub_script.tab.[ch]
+/libgrub.pp
+/libgrub_a_init.c
+/libgrub_a_init.lst
+/stamp-h.in
+/widthspec.h
diff --git a/docs/.gitignore b/docs/.gitignore
new file mode 100644
index 00000000000..e1d849ef95b
--- /dev/null
+++ b/docs/.gitignore
@@ -0,0 +1,5 @@
+/*.in
+/Makefile
+/stamp-1
+/stamp-vti
+/version*.texi
diff --git a/grub-core/.gitignore b/grub-core/.gitignore
new file mode 100644
index 00000000000..2acce281159
--- /dev/null
+++ b/grub-core/.gitignore
@@ -0,0 +1,16 @@
+/*.lst
+/Makefile
+/Makefile.gcry.def
+/unidata.c
+/build-grub-module-verifier
+/gdb_grub
+/genmod.sh
+/gensyminfo.sh
+/gentrigtables
+/gmodule.pl
+/grub_script.tab.[ch]
+/modinfo.sh
+/rs_decoder.h
+/symlist.c
+/symlist.h
+/trigtables.c
diff --git a/grub-core/lib/.gitignore b/grub-core/lib/.gitignore
new file mode 100644
index 00000000000..68154591404
--- /dev/null
+++ b/grub-core/lib/.gitignore
@@ -0,0 +1 @@
+/libgcrypt-grub/
diff --git a/include/grub/gcrypt/.gitignore b/include/grub/gcrypt/.gitignore
new file mode 100644
index 00000000000..8fbf5646246
--- /dev/null
+++ b/include/grub/gcrypt/.gitignore
@@ -0,0 +1,2 @@
+g10lib.h
+gcrypt.h
diff --git a/po/.gitignore b/po/.gitignore
new file mode 100644
index 00000000000..f507e7741e3
--- /dev/null
+++ b/po/.gitignore
@@ -0,0 +1,5 @@
+/Makefile
+/POTFILES*.in
+/grub.pot
+/remove-potcdate.sed
+/stamp-po
diff --git a/util/bash-completion.d/.gitignore b/util/bash-completion.d/.gitignore
new file mode 100644
index 00000000000..6813a527ad3
--- /dev/null
+++ b/util/bash-completion.d/.gitignore
@@ -0,0 +1,2 @@
+Makefile
+grub

View File

@ -0,0 +1,172 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
Date: Thu, 20 Sep 2012 18:07:39 -0300
Subject: [PATCH] IBM client architecture (CAS) reboot support
This is an implementation of IBM client architecture (CAS) reboot for GRUB.
There are cases where the POWER firmware must reboot in order to support
specific features requested by a kernel. The kernel calls
ibm,client-architecture-support and it may either return or reboot with the new
feature set. eg:
Calling ibm,client-architecture-support.../
Elapsed time since release of system processors: 70959 mins 50 secs
Welcome to GRUB!
Instead of return to the GRUB menu, it will check if the flag for CAS reboot is
set. If so, grub will automatically boot the last booted kernel using the same
parameters
---
grub-core/kern/ieee1275/openfw.c | 63 ++++++++++++++++++++++++++++++++++++++++
grub-core/normal/main.c | 19 ++++++++++++
grub-core/script/execute.c | 7 +++++
include/grub/ieee1275/ieee1275.h | 2 ++
4 files changed, 91 insertions(+)
diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c
index 4d493ab7661..3a6689abb11 100644
--- a/grub-core/kern/ieee1275/openfw.c
+++ b/grub-core/kern/ieee1275/openfw.c
@@ -591,3 +591,66 @@ grub_ieee1275_get_boot_dev (void)
return bootpath;
}
+
+/* Check if it's a CAS reboot. If so, set the script to be executed. */
+int
+grub_ieee1275_cas_reboot (char *script)
+{
+ grub_uint32_t ibm_ca_support_reboot;
+ grub_uint32_t ibm_fw_nbr_reboots;
+ char property_value[10];
+ grub_ssize_t actual;
+ grub_ieee1275_ihandle_t options;
+
+ if (grub_ieee1275_finddevice ("/options", &options) < 0)
+ return -1;
+
+ /* Check two properties, one is enough to get cas reboot value */
+ ibm_ca_support_reboot = 0;
+ if (grub_ieee1275_get_integer_property (grub_ieee1275_chosen,
+ "ibm,client-architecture-support-reboot",
+ &ibm_ca_support_reboot,
+ sizeof (ibm_ca_support_reboot),
+ &actual) >= 0)
+ grub_dprintf("ieee1275", "ibm,client-architecture-support-reboot: %u\n",
+ ibm_ca_support_reboot);
+
+ ibm_fw_nbr_reboots = 0;
+ if (grub_ieee1275_get_property (options, "ibm,fw-nbr-reboots",
+ property_value, sizeof (property_value),
+ &actual) >= 0)
+ {
+ property_value[sizeof (property_value) - 1] = 0;
+ ibm_fw_nbr_reboots = (grub_uint8_t) grub_strtoul (property_value, 0, 10);
+ grub_dprintf("ieee1275", "ibm,fw-nbr-reboots: %u\n", ibm_fw_nbr_reboots);
+ }
+
+ if (ibm_ca_support_reboot || ibm_fw_nbr_reboots)
+ {
+ if (! grub_ieee1275_get_property_length (options, "boot-last-label", &actual))
+ {
+ if (actual > 1024)
+ script = grub_realloc (script, actual + 1);
+ grub_ieee1275_get_property (options, "boot-last-label", script, actual,
+ &actual);
+ return 0;
+ }
+ }
+
+ grub_ieee1275_set_boot_last_label ("");
+
+ return -1;
+}
+
+int grub_ieee1275_set_boot_last_label (const char *text)
+{
+ grub_ieee1275_ihandle_t options;
+ grub_ssize_t actual;
+
+ grub_dprintf("ieee1275", "set boot_last_label (size: %u)\n", grub_strlen(text));
+ if (! grub_ieee1275_finddevice ("/options", &options) &&
+ options != (grub_ieee1275_ihandle_t) -1)
+ grub_ieee1275_set_property (options, "boot-last-label", text,
+ grub_strlen (text), &actual);
+ return 0;
+}
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
index 1b03dfd57b9..222e239c1be 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -33,6 +33,9 @@
#include <grub/charset.h>
#include <grub/script_sh.h>
#include <grub/bufio.h>
+#ifdef GRUB_MACHINE_IEEE1275
+#include <grub/ieee1275/ieee1275.h>
+#endif
GRUB_MOD_LICENSE ("GPLv3+");
@@ -275,6 +278,22 @@ grub_normal_execute (const char *config, int nested, int batch)
{
menu = read_config_file (config);
+#ifdef GRUB_MACHINE_IEEE1275
+ int boot;
+ boot = 0;
+ char *script;
+ script = grub_malloc (1024);
+ if (! grub_ieee1275_cas_reboot (script))
+ {
+ char *dummy[1] = { NULL };
+ if (! grub_script_execute_sourcecode (script))
+ boot = 1;
+ }
+ grub_free (script);
+ if (boot)
+ grub_command_execute ("boot", 0, 0);
+#endif
+
/* Ignore any error. */
grub_errno = GRUB_ERR_NONE;
}
diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c
index ee299fd0ea6..0d05d6b0709 100644
--- a/grub-core/script/execute.c
+++ b/grub-core/script/execute.c
@@ -28,6 +28,9 @@
#include <grub/extcmd.h>
#include <grub/i18n.h>
#include <grub/verify.h>
+#ifdef GRUB_MACHINE_IEEE1275
+#include <grub/ieee1275/ieee1275.h>
+#endif
/* Max digits for a char is 3 (0xFF is 255), similarly for an int it
is sizeof (int) * 3, and one extra for a possible -ve sign. */
@@ -878,6 +881,10 @@ grub_script_execute_sourcecode (const char *source)
grub_err_t ret = 0;
struct grub_script *parsed_script;
+#ifdef GRUB_MACHINE_IEEE1275
+ grub_ieee1275_set_boot_last_label (source);
+#endif
+
while (source)
{
char *line;
diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h
index 73e2f464475..0a599607f31 100644
--- a/include/grub/ieee1275/ieee1275.h
+++ b/include/grub/ieee1275/ieee1275.h
@@ -254,6 +254,8 @@ int EXPORT_FUNC(grub_ieee1275_devalias_next) (struct grub_ieee1275_devalias *ali
void EXPORT_FUNC(grub_ieee1275_children_peer) (struct grub_ieee1275_devalias *alias);
void EXPORT_FUNC(grub_ieee1275_children_first) (const char *devpath,
struct grub_ieee1275_devalias *alias);
+int EXPORT_FUNC(grub_ieee1275_cas_reboot) (char *script);
+int EXPORT_FUNC(grub_ieee1275_set_boot_last_label) (const char *text);
char *EXPORT_FUNC(grub_ieee1275_get_boot_dev) (void);

View File

@ -0,0 +1,29 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
Date: Wed, 24 Apr 2013 10:51:48 -0300
Subject: [PATCH] for ppc, reset console display attr when clear screen
v2: Also use \x0c instead of a literal ^L to make future patches less
awkward.
This should fix this bugzilla:
https://bugzilla.redhat.com/show_bug.cgi?id=908519
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/term/terminfo.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/grub-core/term/terminfo.c b/grub-core/term/terminfo.c
index d317efa368d..29df35e6d20 100644
--- a/grub-core/term/terminfo.c
+++ b/grub-core/term/terminfo.c
@@ -151,7 +151,7 @@ grub_terminfo_set_current (struct grub_term_output *term,
/* Clear the screen. Using serial console, screen(1) only recognizes the
* ANSI escape sequence. Using video console, Apple Open Firmware
* (version 3.1.1) only recognizes the literal ^L. So use both. */
- data->cls = grub_strdup (" \e[2J");
+ data->cls = grub_strdup ("\x0c\e[2J\e[m");
data->reverse_video_on = grub_strdup ("\e[7m");
data->reverse_video_off = grub_strdup ("\e[m");
if (grub_strcmp ("ieee1275", str) == 0)

View File

@ -0,0 +1,62 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
Date: Tue, 11 Jun 2013 15:14:05 -0300
Subject: [PATCH] Disable GRUB video support for IBM power machines
Should fix the problem in bugzilla:
https://bugzilla.redhat.com/show_bug.cgi?id=973205
---
grub-core/kern/ieee1275/cmain.c | 5 ++++-
grub-core/video/ieee1275.c | 9 ++++++---
include/grub/ieee1275/ieee1275.h | 2 ++
3 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/grub-core/kern/ieee1275/cmain.c b/grub-core/kern/ieee1275/cmain.c
index 20cbbd761ec..04df9d2c667 100644
--- a/grub-core/kern/ieee1275/cmain.c
+++ b/grub-core/kern/ieee1275/cmain.c
@@ -90,7 +90,10 @@ grub_ieee1275_find_options (void)
}
if (rc >= 0 && grub_strncmp (tmp, "IBM", 3) == 0)
- grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS);
+ {
+ grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS);
+ grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_DISABLE_VIDEO_SUPPORT);
+ }
/* Old Macs have no key repeat, newer ones have fully working one.
The ones inbetween when repeated key generates an escaoe sequence
diff --git a/grub-core/video/ieee1275.c b/grub-core/video/ieee1275.c
index 17a3dbbb575..b8e4b3feb32 100644
--- a/grub-core/video/ieee1275.c
+++ b/grub-core/video/ieee1275.c
@@ -352,9 +352,12 @@ static struct grub_video_adapter grub_video_ieee1275_adapter =
GRUB_MOD_INIT(ieee1275_fb)
{
- find_display ();
- if (display)
- grub_video_register (&grub_video_ieee1275_adapter);
+ if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_DISABLE_VIDEO_SUPPORT))
+ {
+ find_display ();
+ if (display)
+ grub_video_register (&grub_video_ieee1275_adapter);
+ }
}
GRUB_MOD_FINI(ieee1275_fb)
diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h
index 0a599607f31..b5a1d49bbc3 100644
--- a/include/grub/ieee1275/ieee1275.h
+++ b/include/grub/ieee1275/ieee1275.h
@@ -148,6 +148,8 @@ enum grub_ieee1275_flag
GRUB_IEEE1275_FLAG_CURSORONOFF_ANSI_BROKEN,
GRUB_IEEE1275_FLAG_RAW_DEVNAMES,
+
+ GRUB_IEEE1275_FLAG_DISABLE_VIDEO_SUPPORT
};
extern int EXPORT_FUNC(grub_ieee1275_test_flag) (enum grub_ieee1275_flag flag);

View File

@ -0,0 +1,26 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Marcel Kolaja <mkolaja@redhat.com>
Date: Tue, 21 Jan 2014 10:57:08 -0500
Subject: [PATCH] Honor a symlink when generating configuration by
grub2-mkconfig
Honor a symlink when generating configuration by grub2-mkconfig, so that
the -o option follows it rather than overwriting it with a regular file.
---
util/grub-mkconfig.in | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
index 9f477ff0546..523d4e029bb 100644
--- a/util/grub-mkconfig.in
+++ b/util/grub-mkconfig.in
@@ -287,7 +287,8 @@ and /etc/grub.d/* files or please file a bug report with
exit 1
else
# none of the children aborted with error, install the new grub.cfg
- mv -f ${grub_cfg}.new ${grub_cfg}
+ cat ${grub_cfg}.new > ${grub_cfg}
+ rm -f ${grub_cfg}.new
fi
fi

View File

@ -0,0 +1,52 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Wed, 3 Apr 2013 14:35:34 -0400
Subject: [PATCH] Move bash completion script (#922997)
Apparently these go in a new place now.
---
configure.ac | 11 +++++++++++
util/bash-completion.d/Makefile.am | 1 -
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/configure.ac b/configure.ac
index 7656f2434e5..d283af64c8c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -305,6 +305,14 @@ AC_SUBST(grubdirname)
AC_DEFINE_UNQUOTED(GRUB_DIR_NAME, "$grubdirname",
[Default grub directory name])
+PKG_PROG_PKG_CONFIG
+AS_IF([$($PKG_CONFIG --exists bash-completion)], [
+ bashcompletiondir=$($PKG_CONFIG --variable=completionsdir bash-completion)
+] , [
+ bashcompletiondir=${datadir}/bash-completion/completions
+])
+AC_SUBST(bashcompletiondir)
+
#
# Checks for build programs.
#
@@ -516,6 +524,9 @@ HOST_CFLAGS="$HOST_CFLAGS $grub_cv_cc_w_extra_flags"
# Check for target programs.
#
+# This makes sure pkg.m4 is available.
+m4_pattern_forbid([^_?PKG_[A-Z_]+$],[*** pkg.m4 missing, please install pkg-config])
+
# Find tools for the target.
if test "x$target_alias" != x && test "x$host_alias" != "x$target_alias"; then
tmp_ac_tool_prefix="$ac_tool_prefix"
diff --git a/util/bash-completion.d/Makefile.am b/util/bash-completion.d/Makefile.am
index 136287cf1bf..61108f05429 100644
--- a/util/bash-completion.d/Makefile.am
+++ b/util/bash-completion.d/Makefile.am
@@ -6,7 +6,6 @@ EXTRA_DIST = $(bash_completion_source)
CLEANFILES = $(bash_completion_script) config.log
-bashcompletiondir = $(sysconfdir)/bash_completion.d
bashcompletion_DATA = $(bash_completion_script)
$(bash_completion_script): $(bash_completion_source) $(top_builddir)/config.status

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,141 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Fri, 5 Sep 2014 10:07:04 -0400
Subject: [PATCH] Allow "fallback" to include entries by title, not just
number.
Resolves: rhbz#1026084
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/normal/menu.c | 85 +++++++++++++++++++++++++++++++++----------------
1 file changed, 58 insertions(+), 27 deletions(-)
diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c
index d5e0c79a70e..9175ad297d8 100644
--- a/grub-core/normal/menu.c
+++ b/grub-core/normal/menu.c
@@ -163,16 +163,41 @@ grub_menu_set_timeout (int timeout)
}
}
+static int
+menuentry_eq (const char *id, const char *spec)
+{
+ const char *ptr1, *ptr2;
+ ptr1 = id;
+ ptr2 = spec;
+ while (1)
+ {
+ if (*ptr2 == '>' && ptr2[1] != '>' && *ptr1 == 0)
+ return ptr2 - spec;
+ if (*ptr2 == '>' && ptr2[1] != '>')
+ return 0;
+ if (*ptr2 == '>')
+ ptr2++;
+ if (*ptr1 != *ptr2)
+ return 0;
+ if (*ptr1 == 0)
+ return ptr1 - id;
+ ptr1++;
+ ptr2++;
+ }
+ return 0;
+}
+
/* Get the first entry number from the value of the environment variable NAME,
which is a space-separated list of non-negative integers. The entry number
which is returned is stripped from the value of NAME. If no entry number
can be found, -1 is returned. */
static int
-get_and_remove_first_entry_number (const char *name)
+get_and_remove_first_entry_number (grub_menu_t menu, const char *name)
{
const char *val;
char *tail;
int entry;
+ int sz = 0;
val = grub_env_get (name);
if (! val)
@@ -182,9 +207,39 @@ get_and_remove_first_entry_number (const char *name)
entry = (int) grub_strtoul (val, &tail, 0);
+ if (grub_errno == GRUB_ERR_BAD_NUMBER)
+ {
+ /* See if the variable matches the title of a menu entry. */
+ grub_menu_entry_t e = menu->entry_list;
+ int i;
+
+ for (i = 0; e; i++)
+ {
+ sz = menuentry_eq (e->title, val);
+ if (sz < 1)
+ sz = menuentry_eq (e->id, val);
+
+ if (sz >= 1)
+ {
+ entry = i;
+ break;
+ }
+ e = e->next;
+ }
+
+ if (sz > 0)
+ grub_errno = GRUB_ERR_NONE;
+
+ if (! e)
+ entry = -1;
+ }
+
if (grub_errno == GRUB_ERR_NONE)
{
- /* Skip whitespace to find the next digit. */
+ if (sz > 0)
+ tail += sz;
+
+ /* Skip whitespace to find the next entry. */
while (*tail && grub_isspace (*tail))
tail++;
grub_env_set (name, tail);
@@ -347,7 +402,7 @@ grub_menu_execute_with_fallback (grub_menu_t menu,
grub_menu_execute_entry (entry, 1);
/* Deal with fallback entries. */
- while ((fallback_entry = get_and_remove_first_entry_number ("fallback"))
+ while ((fallback_entry = get_and_remove_first_entry_number (menu, "fallback"))
>= 0)
{
grub_print_error ();
@@ -465,30 +520,6 @@ grub_menu_register_viewer (struct grub_menu_viewer *viewer)
viewers = viewer;
}
-static int
-menuentry_eq (const char *id, const char *spec)
-{
- const char *ptr1, *ptr2;
- ptr1 = id;
- ptr2 = spec;
- while (1)
- {
- if (*ptr2 == '>' && ptr2[1] != '>' && *ptr1 == 0)
- return 1;
- if (*ptr2 == '>' && ptr2[1] != '>')
- return 0;
- if (*ptr2 == '>')
- ptr2++;
- if (*ptr1 != *ptr2)
- return 0;
- if (*ptr1 == 0)
- return 1;
- ptr1++;
- ptr2++;
- }
-}
-
-
/* Get the entry number from the variable NAME. */
static int
get_entry_number (grub_menu_t menu, const char *name)

View File

@ -0,0 +1,106 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 4 Sep 2014 16:49:25 -0400
Subject: [PATCH] Add GRUB_DISABLE_UUID.
This will cause "search --fs-uuid --set=root ..." not to be generated by
grub2-mkconfig, and instead simply attempt to use the grub device name
as it understands it.
Signed-off-by: Peter Jones <pjones@redhat.com>
---
docs/grub.texi | 7 +++++++
util/grub-mkconfig.in | 22 +++++++++++++++++++---
util/grub-mkconfig_lib.in | 4 ++--
3 files changed, 28 insertions(+), 5 deletions(-)
diff --git a/docs/grub.texi b/docs/grub.texi
index 87795075a87..6f524305085 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -1441,6 +1441,13 @@ enable the use of partition UUIDs, set this option to @samp{false}.
If this option is set to @samp{true}, disable the generation of recovery
mode menu entries.
+@item GRUB_DISABLE_UUID
+Normally, @command{grub-mkconfig} will generate menu entries that use
+universally-unique identifiers (UUIDs) to identify various filesystems to
+search for files. This is usually more reliable, but in some cases it may
+not be appropriate. To disable this use of UUIDs, set this option to
+@samp{true}.
+
@item GRUB_VIDEO_BACKEND
If graphical video support is required, either because the @samp{gfxterm}
graphical terminal is in use or because @samp{GRUB_GFXPAYLOAD_LINUX} is set,
diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
index 523d4e029bb..9ecbcfb5b43 100644
--- a/util/grub-mkconfig.in
+++ b/util/grub-mkconfig.in
@@ -133,12 +133,12 @@ fi
# Device containing our userland. Typically used for root= parameter.
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_DEVICE_UUID_GENERATED="`${grub_probe} --device ${GRUB_DEVICE} --target=fs_uuid 2> /dev/null`" || true
+GRUB_DEVICE_PARTUUID_GENERATED="`${grub_probe} --device ${GRUB_DEVICE} --target=partuuid 2> /dev/null`" || true
# Device containing our /boot partition. Usually the same as GRUB_DEVICE.
GRUB_DEVICE_BOOT="`${grub_probe} --target=device /boot`"
-GRUB_DEVICE_BOOT_UUID="`${grub_probe} --device ${GRUB_DEVICE_BOOT} --target=fs_uuid 2> /dev/null`" || true
+GRUB_DEVICE_BOOT_UUID_GENERATED="`${grub_probe} --device ${GRUB_DEVICE_BOOT} --target=fs_uuid 2> /dev/null`" || true
# Filesystem for the device containing our userland. Used for stuff like
# choosing Hurd filesystem module.
@@ -158,6 +158,21 @@ if test -f ${sysconfdir}/default/grub ; then
. ${sysconfdir}/default/grub
fi
+if [ "x$GRUB_DISABLE_UUID" != "xtrue" ]; then
+ if [ -z "$GRUB_DEVICE_UUID" ]; then
+ GRUB_DEVICE_UUID="$GRUB_DEVICE_UUID_GENERATED"
+ fi
+ if [ -z "$GRUB_DEVICE_BOOT_UUID" ]; then
+ GRUB_DEVICE_BOOT_UUID="$GRUB_DEVICE_BOOT_UUID_GENERATED"
+ fi
+ if [ -z "$GRUB_DEVICE_UUID" ]; then
+ GRUB_DEVICE_UUID="$GRUB_DEVICE_UUID_GENERATED"
+ fi
+ if [ -z "$GRUB_DEVICE_PART_UUID" ]; then
+ GRUB_DEVICE_PART_UUID="$GRUB_DEVICE_PART_UUID_GENERATED"
+ fi
+fi
+
# XXX: should this be deprecated at some point?
if [ "x${GRUB_TERMINAL}" != "x" ] ; then
GRUB_TERMINAL_INPUT="${GRUB_TERMINAL}"
@@ -227,6 +242,7 @@ export GRUB_DEFAULT \
GRUB_DISABLE_LINUX_UUID \
GRUB_DISABLE_LINUX_PARTUUID \
GRUB_DISABLE_RECOVERY \
+ GRUB_DISABLE_UUID \
GRUB_VIDEO_BACKEND \
GRUB_GFXMODE \
GRUB_BACKGROUND \
diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in
index 0f801cab3e4..1001a12232b 100644
--- a/util/grub-mkconfig_lib.in
+++ b/util/grub-mkconfig_lib.in
@@ -156,7 +156,7 @@ prepare_grub_to_access_device ()
if [ "x$fs_hint" != x ]; then
echo "set root='$fs_hint'"
fi
- if fs_uuid="`"${grub_probe}" --device $@ --target=fs_uuid 2> /dev/null`" ; then
+ 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=
echo "if [ x\$feature_platform_search_hint = xy ]; then"
echo " search --no-floppy --fs-uuid --set=root ${hints} ${fs_uuid}"
@@ -173,7 +173,7 @@ grub_get_device_id ()
IFS='
'
device="$1"
- if fs_uuid="`"${grub_probe}" --device ${device} --target=fs_uuid 2> /dev/null`" ; then
+ if [ "x$GRUB_DISABLE_UUID" != "xtrue" ] && fs_uuid="`"${grub_probe}" --device ${device} --target=fs_uuid 2> /dev/null`" ; then
echo "$fs_uuid";
else
echo $device |sed 's, ,_,g'

View File

@ -0,0 +1,267 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Wed, 26 Feb 2014 21:49:12 -0500
Subject: [PATCH] Make "exit" take a return code.
This adds "exit" with a return code. With this patch, any "exit"
command /may/ include a return code, and on platforms that support
returning with an exit status, we will do so. By default we return the
same exit status we did before this patch.
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/commands/minicmd.c | 20 ++++++++++++++++----
grub-core/kern/efi/efi.c | 9 +++++++--
grub-core/kern/emu/main.c | 2 +-
grub-core/kern/emu/misc.c | 5 +++--
grub-core/kern/i386/coreboot/init.c | 2 +-
grub-core/kern/i386/qemu/init.c | 2 +-
grub-core/kern/ieee1275/init.c | 2 +-
grub-core/kern/mips/arc/init.c | 2 +-
grub-core/kern/mips/loongson/init.c | 2 +-
grub-core/kern/mips/qemu_mips/init.c | 2 +-
grub-core/kern/misc.c | 11 ++++++++++-
grub-core/kern/uboot/init.c | 6 +++---
grub-core/kern/xen/init.c | 2 +-
include/grub/misc.h | 2 +-
14 files changed, 48 insertions(+), 21 deletions(-)
diff --git a/grub-core/commands/minicmd.c b/grub-core/commands/minicmd.c
index 6bbce3128cf..6d66b7c453a 100644
--- a/grub-core/commands/minicmd.c
+++ b/grub-core/commands/minicmd.c
@@ -179,12 +179,24 @@ grub_mini_cmd_lsmod (struct grub_command *cmd __attribute__ ((unused)),
}
/* exit */
-static grub_err_t __attribute__ ((noreturn))
+static grub_err_t
grub_mini_cmd_exit (struct grub_command *cmd __attribute__ ((unused)),
- int argc __attribute__ ((unused)),
- char *argv[] __attribute__ ((unused)))
+ int argc, char *argv[])
{
- grub_exit ();
+ int retval = -1;
+ unsigned long n;
+
+ if (argc < 0 || argc > 1)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
+
+ if (argc == 1)
+ {
+ n = grub_strtoul (argv[0], 0, 10);
+ if (n != ~0UL)
+ retval = n;
+ }
+
+ grub_exit (retval);
/* Not reached. */
}
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
index 6e1ceb90516..370ce03c5d7 100644
--- a/grub-core/kern/efi/efi.c
+++ b/grub-core/kern/efi/efi.c
@@ -164,11 +164,16 @@ grub_reboot (void)
}
void
-grub_exit (void)
+grub_exit (int retval)
{
+ int rc = GRUB_EFI_LOAD_ERROR;
+
+ if (retval == 0)
+ rc = GRUB_EFI_SUCCESS;
+
grub_machine_fini (GRUB_LOADER_FLAG_NORETURN);
efi_call_4 (grub_efi_system_table->boot_services->exit,
- grub_efi_image_handle, GRUB_EFI_SUCCESS, 0, 0);
+ grub_efi_image_handle, rc, 0, 0);
for (;;) ;
}
diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c
index 425bb960347..55ea5a11ccd 100644
--- a/grub-core/kern/emu/main.c
+++ b/grub-core/kern/emu/main.c
@@ -67,7 +67,7 @@ grub_reboot (void)
}
void
-grub_exit (void)
+grub_exit (int retval __attribute__((unused)))
{
grub_reboot ();
}
diff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c
index 65db79baa10..19cd007d448 100644
--- a/grub-core/kern/emu/misc.c
+++ b/grub-core/kern/emu/misc.c
@@ -139,9 +139,10 @@ xasprintf (const char *fmt, ...)
#if !defined (GRUB_MACHINE_EMU) || defined (GRUB_UTIL)
void
-grub_exit (void)
+__attribute__ ((noreturn))
+grub_exit (int rc)
{
- exit (1);
+ exit (rc < 0 ? 1 : rc);
}
#endif
diff --git a/grub-core/kern/i386/coreboot/init.c b/grub-core/kern/i386/coreboot/init.c
index 3314f027fec..36f9134b7b7 100644
--- a/grub-core/kern/i386/coreboot/init.c
+++ b/grub-core/kern/i386/coreboot/init.c
@@ -41,7 +41,7 @@ extern grub_uint8_t _end[];
extern grub_uint8_t _edata[];
void __attribute__ ((noreturn))
-grub_exit (void)
+grub_exit (int rc __attribute__((unused)))
{
/* We can't use grub_fatal() in this function. This would create an infinite
loop, since grub_fatal() calls grub_abort() which in turn calls grub_exit(). */
diff --git a/grub-core/kern/i386/qemu/init.c b/grub-core/kern/i386/qemu/init.c
index 271b6fbfabd..9fafe98f015 100644
--- a/grub-core/kern/i386/qemu/init.c
+++ b/grub-core/kern/i386/qemu/init.c
@@ -42,7 +42,7 @@ extern grub_uint8_t _end[];
extern grub_uint8_t _edata[];
void __attribute__ ((noreturn))
-grub_exit (void)
+grub_exit (int rc __attribute__((unused)))
{
/* We can't use grub_fatal() in this function. This would create an infinite
loop, since grub_fatal() calls grub_abort() which in turn calls grub_exit(). */
diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
index d483e35eed2..e71d1584164 100644
--- a/grub-core/kern/ieee1275/init.c
+++ b/grub-core/kern/ieee1275/init.c
@@ -71,7 +71,7 @@ grub_addr_t grub_ieee1275_original_stack;
#endif
void
-grub_exit (void)
+grub_exit (int rc __attribute__((unused)))
{
grub_ieee1275_exit ();
}
diff --git a/grub-core/kern/mips/arc/init.c b/grub-core/kern/mips/arc/init.c
index 3834a149093..86b3a25ec40 100644
--- a/grub-core/kern/mips/arc/init.c
+++ b/grub-core/kern/mips/arc/init.c
@@ -276,7 +276,7 @@ grub_halt (void)
}
void
-grub_exit (void)
+grub_exit (int rc __attribute__((unused)))
{
GRUB_ARC_FIRMWARE_VECTOR->exit ();
diff --git a/grub-core/kern/mips/loongson/init.c b/grub-core/kern/mips/loongson/init.c
index 7b96531b983..dff598ca7b0 100644
--- a/grub-core/kern/mips/loongson/init.c
+++ b/grub-core/kern/mips/loongson/init.c
@@ -304,7 +304,7 @@ grub_halt (void)
}
void
-grub_exit (void)
+grub_exit (int rc __attribute__((unused)))
{
grub_halt ();
}
diff --git a/grub-core/kern/mips/qemu_mips/init.c b/grub-core/kern/mips/qemu_mips/init.c
index be88b77d22d..8b6c55ffc01 100644
--- a/grub-core/kern/mips/qemu_mips/init.c
+++ b/grub-core/kern/mips/qemu_mips/init.c
@@ -75,7 +75,7 @@ grub_machine_fini (int flags __attribute__ ((unused)))
}
void
-grub_exit (void)
+grub_exit (int rc __attribute__((unused)))
{
grub_halt ();
}
diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
index 3b633d51f4c..cd63a8cea73 100644
--- a/grub-core/kern/misc.c
+++ b/grub-core/kern/misc.c
@@ -1095,9 +1095,18 @@ grub_abort (void)
grub_getkey ();
}
- grub_exit ();
+ grub_exit (1);
}
+#if defined (__clang__) && !defined (GRUB_UTIL)
+/* clang emits references to abort(). */
+void __attribute__ ((noreturn))
+abort (void)
+{
+ grub_abort ();
+}
+#endif
+
void
grub_fatal (const char *fmt, ...)
{
diff --git a/grub-core/kern/uboot/init.c b/grub-core/kern/uboot/init.c
index 3e338645c57..be2a5be1d07 100644
--- a/grub-core/kern/uboot/init.c
+++ b/grub-core/kern/uboot/init.c
@@ -39,9 +39,9 @@ extern grub_size_t grub_total_module_size;
static unsigned long timer_start;
void
-grub_exit (void)
+grub_exit (int rc)
{
- grub_uboot_return (0);
+ grub_uboot_return (rc < 0 ? 1 : rc);
}
static grub_uint64_t
@@ -78,7 +78,7 @@ grub_machine_init (void)
if (!ver)
{
/* Don't even have a console to log errors to... */
- grub_exit ();
+ grub_exit (-1);
}
else if (ver > API_SIG_VERSION)
{
diff --git a/grub-core/kern/xen/init.c b/grub-core/kern/xen/init.c
index 782ca72952a..708b060f324 100644
--- a/grub-core/kern/xen/init.c
+++ b/grub-core/kern/xen/init.c
@@ -584,7 +584,7 @@ grub_machine_init (void)
}
void
-grub_exit (void)
+grub_exit (int rc __attribute__((unused)))
{
struct sched_shutdown arg;
diff --git a/include/grub/misc.h b/include/grub/misc.h
index ee48eb7a726..f9135b62e35 100644
--- a/include/grub/misc.h
+++ b/include/grub/misc.h
@@ -334,7 +334,7 @@ int EXPORT_FUNC(grub_vsnprintf) (char *str, grub_size_t n, const char *fmt,
char *EXPORT_FUNC(grub_xasprintf) (const char *fmt, ...)
__attribute__ ((format (GNU_PRINTF, 1, 2))) WARN_UNUSED_RESULT;
char *EXPORT_FUNC(grub_xvasprintf) (const char *fmt, va_list args) WARN_UNUSED_RESULT;
-void EXPORT_FUNC(grub_exit) (void) __attribute__ ((noreturn));
+void EXPORT_FUNC(grub_exit) (int rc) __attribute__ ((noreturn));
grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n,
grub_uint64_t d,
grub_uint64_t *r);

View File

@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Wed, 22 Jul 2015 11:21:01 -0400
Subject: [PATCH] Mark po/exclude.pot as binary so git won't try to diff
nonprintables.
Signed-off-by: Peter Jones <pjones@redhat.com>
---
.gitattributes | 1 +
1 file changed, 1 insertion(+)
create mode 100644 .gitattributes
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000000..33ffaa40460
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+po/exclude.pot binary

View File

@ -0,0 +1,81 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 7 Dec 2015 14:20:49 -0500
Subject: [PATCH] Make efi machines load an env block from a variable
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/Makefile.core.def | 1 +
grub-core/kern/efi/init.c | 34 +++++++++++++++++++++++++++++++++-
2 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index eb1088fd654..41b5e16a3ce 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -203,6 +203,7 @@ kernel = {
efi = term/efi/console.c;
efi = kern/acpi.c;
efi = kern/efi/acpi.c;
+ efi = lib/envblk.c;
i386_coreboot = kern/i386/pc/acpi.c;
i386_multiboot = kern/i386/pc/acpi.c;
i386_coreboot = kern/acpi.c;
diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c
index 3dfdf2d22b0..71d2279a0c1 100644
--- a/grub-core/kern/efi/init.c
+++ b/grub-core/kern/efi/init.c
@@ -25,9 +25,40 @@
#include <grub/env.h>
#include <grub/mm.h>
#include <grub/kernel.h>
+#include <grub/lib/envblk.h>
grub_addr_t grub_modbase;
+#define GRUB_EFI_GRUB_VARIABLE_GUID \
+ { 0x91376aff, 0xcba6, 0x42be, \
+ { 0x94, 0x9d, 0x06, 0xfd, 0xe8, 0x11, 0x28, 0xe8 } \
+ }
+
+/* Helper for grub_efi_env_init */
+static int
+set_var (const char *name, const char *value,
+ void *whitelist __attribute__((__unused__)))
+{
+ grub_env_set (name, value);
+ return 0;
+}
+
+static void
+grub_efi_env_init (void)
+{
+ grub_efi_guid_t efi_grub_guid = GRUB_EFI_GRUB_VARIABLE_GUID;
+ struct grub_envblk envblk_s = { NULL, 0 };
+ grub_envblk_t envblk = &envblk_s;
+
+ envblk_s.buf = grub_efi_get_variable ("GRUB_ENV", &efi_grub_guid,
+ &envblk_s.size);
+ if (!envblk_s.buf || envblk_s.size < 1)
+ return;
+
+ grub_envblk_iterate (envblk, NULL, set_var);
+ grub_free (envblk_s.buf);
+}
+
void
grub_efi_init (void)
{
@@ -42,10 +73,11 @@ grub_efi_init (void)
efi_call_4 (grub_efi_system_table->boot_services->set_watchdog_timer,
0, 0, 0, NULL);
+ grub_efi_env_init ();
grub_efidisk_init ();
}
-void (*grub_efi_net_config) (grub_efi_handle_t hnd,
+void (*grub_efi_net_config) (grub_efi_handle_t hnd,
char **device,
char **path);

View File

@ -0,0 +1,140 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
Date: Mon, 8 Jul 2019 14:10:58 +0200
Subject: [PATCH] DHCP client ID and UUID options added.
---
grub-core/net/bootp.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++-----
include/grub/net.h | 2 ++
2 files changed, 79 insertions(+), 8 deletions(-)
diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
index 04cfbb04504..0e6e41a1699 100644
--- a/grub-core/net/bootp.c
+++ b/grub-core/net/bootp.c
@@ -95,6 +95,49 @@ enum
/* Max timeout when waiting for BOOTP/DHCP reply */
#define GRUB_DHCP_MAX_PACKET_TIMEOUT 32
+static char *
+grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)),
+ const char *val __attribute__ ((unused)))
+{
+ return NULL;
+}
+
+static void
+set_env_limn_ro (const char *intername, const char *suffix,
+ const char *value, grub_size_t len)
+{
+ char *varname, *varvalue;
+ char *ptr;
+ varname = grub_xasprintf ("net_%s_%s", intername, suffix);
+ if (!varname)
+ return;
+ for (ptr = varname; *ptr; ptr++)
+ if (*ptr == ':')
+ *ptr = '_';
+ varvalue = grub_malloc (len + 1);
+ if (!varvalue)
+ {
+ grub_free (varname);
+ return;
+ }
+
+ grub_memcpy (varvalue, value, len);
+ varvalue[len] = 0;
+ grub_env_set (varname, varvalue);
+ grub_register_variable_hook (varname, 0, grub_env_write_readonly);
+ grub_env_export (varname);
+ grub_free (varname);
+ grub_free (varvalue);
+}
+
+static char
+hexdigit (grub_uint8_t val)
+{
+ if (val < 10)
+ return val + '0';
+ return val + 'a' - 10;
+}
+
static const void *
find_dhcp_option (const struct grub_net_bootp_packet *bp, grub_size_t size,
grub_uint8_t opt_code, grub_uint8_t *opt_len)
@@ -152,6 +195,9 @@ again:
if (i + taglength >= size)
return NULL;
+ grub_dprintf("net", "DHCP option %u (0x%02x) found with length %u.\n",
+ tagtype, tagtype, taglength);
+
/* FIXME RFC 3396 options concatentation */
if (tagtype == opt_code)
{
@@ -354,6 +400,37 @@ grub_net_configure_by_dhcp_ack (const char *name,
}
grub_net_add_ipv4_local (inter, mask);
+ opt = find_dhcp_option (bp, size, GRUB_NET_BOOTP_CLIENT_ID, &opt_len);
+ if (opt)
+ {
+ set_env_limn_ro (name, "clientid", (char *) opt, opt_len);
+ }
+
+ opt = find_dhcp_option (bp, size, GRUB_NET_BOOTP_CLIENT_UUID, &opt_len);
+ if (opt && opt_len == 17)
+ {
+ /* The format is 9cfe245e-d0c8-bd45-a79f-54ea5fbd3d97 */
+
+ opt += 1;
+ opt_len -= 1;
+
+ char *val = grub_malloc (2 * opt_len + 4 + 1);
+ int i = 0;
+ int j = 0;
+ for (i = 0; i < opt_len; i++)
+ {
+ val[2 * i + j] = hexdigit (opt[i] >> 4);
+ val[2 * i + 1 + j] = hexdigit (opt[i] & 0xf);
+
+ if ((i == 3) || (i == 5) || (i == 7) || (i == 9))
+ {
+ j++;
+ val[2 * i + 1+ j] = '-';
+ }
+ }
+ set_env_limn_ro (name, "clientuuid", (char *) val, 2 * opt_len + 4);
+ }
+
/* We do not implement dead gateway detection and the first entry SHOULD
be preferred one */
opt = find_dhcp_option (bp, size, GRUB_NET_BOOTP_ROUTER, &opt_len);
@@ -631,14 +708,6 @@ grub_net_process_dhcp (struct grub_net_buff *nb,
}
}
-static char
-hexdigit (grub_uint8_t val)
-{
- if (val < 10)
- return val + '0';
- return val + 'a' - 10;
-}
-
static grub_err_t
grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)),
int argc, char **args)
diff --git a/include/grub/net.h b/include/grub/net.h
index 4a9069a1474..556c54e579f 100644
--- a/include/grub/net.h
+++ b/include/grub/net.h
@@ -462,6 +462,8 @@ enum
GRUB_NET_BOOTP_DOMAIN = 0x0f,
GRUB_NET_BOOTP_ROOT_PATH = 0x11,
GRUB_NET_BOOTP_EXTENSIONS_PATH = 0x12,
+ GRUB_NET_BOOTP_CLIENT_ID = 0x3d,
+ GRUB_NET_BOOTP_CLIENT_UUID = 0x61,
GRUB_NET_DHCP_REQUESTED_IP_ADDRESS = 50,
GRUB_NET_DHCP_OVERLOAD = 52,
GRUB_NET_DHCP_MESSAGE_TYPE = 53,

View File

@ -0,0 +1,38 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Prarit Bhargava <prarit@redhat.com>
Date: Wed, 12 Mar 2014 10:58:16 -0400
Subject: [PATCH] Fix bad test on GRUB_DISABLE_SUBMENU.
The file /etc/grub.d/10_linux does
if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xy ]; then
when it should do
if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xtrue ]; then
which results in submenus in /boot/grub2/grub.cfg when
GRUB_DISABLE_SUBMENU="yes".
Resolves: rhbz#1063414
---
util/grub.d/10_linux.in | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index 4532266be68..58defdbd83f 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -261,7 +261,11 @@ while [ "x$list" != "x" ] ; do
fi
fi
- if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xy ]; then
+ if [ "x${GRUB_DISABLE_SUBMENU}" = "xyes" ] || [ "x${GRUB_DISABLE_SUBMENU}" = "xy" ]; then
+ GRUB_DISABLE_SUBMENU="true"
+ fi
+
+ if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xtrue ]; then
linux_entry "${OS}" "${version}" simple \
"${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"

View File

@ -0,0 +1,46 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Matthew Garrett <matthew.garrett@nebula.com>
Date: Wed, 12 Jun 2013 11:51:49 -0400
Subject: [PATCH] Add support for UEFI operating systems returned by os-prober
os-prober returns UEFI operating systems in the form:
path:long-name:name
where path is the path under the EFI directory on the ESP. This is in
contrast to legacy OSes, where path is the device string. Handle this case.
---
util/grub.d/30_os-prober.in | 21 ++++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
index 515a68c7aa0..9b8f5968e2d 100644
--- a/util/grub.d/30_os-prober.in
+++ b/util/grub.d/30_os-prober.in
@@ -328,8 +328,23 @@ EOF
EOF
;;
*)
- # TRANSLATORS: %s is replaced by OS name.
- gettext_printf "%s is not yet supported by grub-mkconfig.\n" " ${LONGNAME}" >&2
- ;;
+ case ${DEVICE} in
+ *.efi)
+ cat << EOF
+menuentry '$(echo "${LONGNAME}" | grub_quote)' {
+EOF
+ save_default_entry | grub_add_tab
+ cat << EOF
+ chainloader /EFI/${DEVICE}
+ boot
+}
+EOF
+ ;;
+ *)
+ echo -n " "
+ # TRANSLATORS: %s is replaced by OS name.
+ gettext_printf "%s is not yet supported by grub-mkconfig.\n" "${LONGNAME}" >&2
+ ;;
+ esac
esac
done

View File

@ -0,0 +1,151 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mark Hamzy <hamzy@us.ibm.com>
Date: Wed, 28 Mar 2012 14:46:41 -0500
Subject: [PATCH] Migrate PPC from Yaboot to Grub2
Add configuration support for serial terminal consoles. This will set the
maximum screen size so that text is not overwritten.
---
Makefile.util.def | 7 +++
util/grub.d/20_ppc_terminfo.in | 114 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 121 insertions(+)
create mode 100644 util/grub.d/20_ppc_terminfo.in
diff --git a/Makefile.util.def b/Makefile.util.def
index 969d32f0097..8717774d510 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -496,6 +496,13 @@ script = {
condition = COND_HOST_LINUX;
};
+script = {
+ name = '20_ppc_terminfo';
+ common = util/grub.d/20_ppc_terminfo.in;
+ installdir = grubconf;
+ condition = COND_HOST_LINUX;
+};
+
script = {
name = '30_os-prober';
common = util/grub.d/30_os-prober.in;
diff --git a/util/grub.d/20_ppc_terminfo.in b/util/grub.d/20_ppc_terminfo.in
new file mode 100644
index 00000000000..10d66586820
--- /dev/null
+++ b/util/grub.d/20_ppc_terminfo.in
@@ -0,0 +1,114 @@
+#! /bin/sh
+set -e
+
+# grub-mkconfig helper script.
+# Copyright (C) 2006,2007,2008,2009,2010 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/>.
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+libdir=@libdir@
+. "@datadir@/@PACKAGE@/grub-mkconfig_lib"
+
+export TEXTDOMAIN=@PACKAGE@
+export TEXTDOMAINDIR=@localedir@
+
+X=80
+Y=24
+TERMINAL=ofconsole
+
+argument () {
+ opt=$1
+ shift
+
+ if test $# -eq 0; then
+ echo "$0: option requires an argument -- '$opt'" 1>&2
+ exit 1
+ fi
+ echo $1
+}
+
+check_terminfo () {
+
+ while test $# -gt 0
+ do
+ option=$1
+ shift
+
+ case "$option" in
+ terminfo | TERMINFO)
+ ;;
+
+ -g)
+ NEWXY=`argument $option "$@"`
+ NEWX=`echo $NEWXY | cut -d x -f 1`
+ NEWY=`echo $NEWXY | cut -d x -f 2`
+
+ if [ ${NEWX} -ge 80 ] ; then
+ X=${NEWX}
+ else
+ echo "Warning: ${NEWX} is less than the minimum size of 80"
+ fi
+
+ if [ ${NEWY} -ge 24 ] ; then
+ Y=${NEWY}
+ else
+ echo "Warning: ${NEWY} is less than the minimum size of 24"
+ fi
+
+ shift
+ ;;
+
+ *)
+# # accept console or ofconsole
+# if [ "$option" != "console" -a "$option" != "ofconsole" ] ; then
+# echo "Error: GRUB_TERMINFO unknown console: $option"
+# exit 1
+# fi
+# # perfer console
+# TERMINAL=console
+ # accept ofconsole
+ if [ "$option" != "ofconsole" ] ; then
+ echo "Error: GRUB_TERMINFO unknown console: $option"
+ exit 1
+ fi
+ # perfer console
+ TERMINAL=ofconsole
+ ;;
+ esac
+
+ done
+
+}
+
+if ! uname -m | grep -q ppc ; then
+ exit 0
+fi
+
+if [ "x${GRUB_TERMINFO}" != "x" ] ; then
+ F1=`echo ${GRUB_TERMINFO} | cut -d " " -f 1`
+
+ if [ "${F1}" != "terminfo" ] ; then
+ echo "Error: GRUB_TERMINFO is set to \"${GRUB_TERMINFO}\" The first word should be terminfo."
+ exit 1
+ fi
+
+ check_terminfo ${GRUB_TERMINFO}
+fi
+
+cat << EOF
+ terminfo -g ${X}x${Y} ${TERMINAL}
+EOF

View File

@ -0,0 +1,78 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
Date: Wed, 19 Sep 2012 21:22:55 -0300
Subject: [PATCH] Add fw_path variable (revised)
This patch makes grub look for its config file on efi where the app was
found. It was originally written by Matthew Garrett, and adapted to fix the
"No modules are loaded on grub2 network boot" issue:
https://bugzilla.redhat.com/show_bug.cgi?id=857936
---
grub-core/kern/main.c | 13 ++++++-------
grub-core/normal/main.c | 25 ++++++++++++++++++++++++-
2 files changed, 30 insertions(+), 8 deletions(-)
diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c
index 9cad0c4485c..8ab7794c47b 100644
--- a/grub-core/kern/main.c
+++ b/grub-core/kern/main.c
@@ -127,16 +127,15 @@ grub_set_prefix_and_root (void)
grub_machine_get_bootlocation (&fwdevice, &fwpath);
- if (fwdevice)
+ if (fwdevice && fwpath)
{
- char *cmdpath;
+ char *fw_path;
- cmdpath = grub_xasprintf ("(%s)%s", fwdevice, fwpath ? : "");
- if (cmdpath)
+ fw_path = grub_xasprintf ("(%s)/%s", fwdevice, fwpath);
+ if (fw_path)
{
- grub_env_set ("cmdpath", cmdpath);
- grub_env_export ("cmdpath");
- grub_free (cmdpath);
+ grub_env_set ("fw_path", fw_path);
+ grub_free (fw_path);
}
}
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
index 222e239c1be..394bfbea868 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -338,7 +338,30 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)),
/* Guess the config filename. It is necessary to make CONFIG static,
so that it won't get broken by longjmp. */
char *config;
- const char *prefix;
+ const char *prefix, *fw_path;
+
+ fw_path = grub_env_get ("fw_path");
+ if (fw_path)
+ {
+ config = grub_xasprintf ("%s/grub.cfg", fw_path);
+ if (config)
+ {
+ grub_file_t file;
+
+ file = grub_file_open (config, GRUB_FILE_TYPE_CONFIG);
+ if (file)
+ {
+ grub_file_close (file);
+ grub_enter_normal_mode (config);
+ }
+ else
+ {
+ /* Ignore all errors. */
+ grub_errno = 0;
+ }
+ grub_free (config);
+ }
+ }
prefix = grub_env_get ("prefix");
if (prefix)

View File

@ -0,0 +1,179 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 1 Oct 2012 13:24:37 -0400
Subject: [PATCH] Pass "\x[[:hex:]][[:hex:]]" straight through unmolested.
---
grub-core/commands/wildcard.c | 16 +++++++++++++++-
grub-core/lib/cmdline.c | 34 ++++++++++++++++++++++++++++++++--
grub-core/script/execute.c | 43 +++++++++++++++++++++++++++++++++++++------
3 files changed, 84 insertions(+), 9 deletions(-)
diff --git a/grub-core/commands/wildcard.c b/grub-core/commands/wildcard.c
index 4a106ca040b..560d437cdc6 100644
--- a/grub-core/commands/wildcard.c
+++ b/grub-core/commands/wildcard.c
@@ -462,6 +462,12 @@ check_file (const char *dir, const char *basename)
return ctx.found;
}
+static int
+is_hex(char c)
+{
+ return ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
+}
+
static void
unescape (char *out, const char *in, const char *end)
{
@@ -470,7 +476,15 @@ unescape (char *out, const char *in, const char *end)
for (optr = out, iptr = in; iptr < end;)
{
- if (*iptr == '\\' && iptr + 1 < end)
+ if (*iptr == '\\' && iptr + 3 < end && iptr[1] == 'x' && is_hex(iptr[2]) && is_hex(iptr[3]))
+ {
+ *optr++ = *iptr++;
+ *optr++ = *iptr++;
+ *optr++ = *iptr++;
+ *optr++ = *iptr++;
+ continue;
+ }
+ else if (*iptr == '\\' && iptr + 1 < end)
{
*optr++ = iptr[1];
iptr += 2;
diff --git a/grub-core/lib/cmdline.c b/grub-core/lib/cmdline.c
index ed0b149dca5..e0fb0a9e48a 100644
--- a/grub-core/lib/cmdline.c
+++ b/grub-core/lib/cmdline.c
@@ -20,6 +20,12 @@
#include <grub/lib/cmdline.h>
#include <grub/misc.h>
+static int
+is_hex(char c)
+{
+ return ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
+}
+
static unsigned int check_arg (char *c, int *has_space)
{
int space = 0;
@@ -27,7 +33,13 @@ static unsigned int check_arg (char *c, int *has_space)
while (*c)
{
- if (*c == '\\' || *c == '\'' || *c == '"')
+ if (*c == '\\' && *(c+1) == 'x' && is_hex(*(c+2)) && is_hex(*(c+3)))
+ {
+ size += 4;
+ c += 4;
+ continue;
+ }
+ else if (*c == '\\' || *c == '\'' || *c == '"')
size++;
else if (*c == ' ')
space = 1;
@@ -86,7 +98,25 @@ grub_create_loader_cmdline (int argc, char *argv[], char *buf,
while (*c)
{
- if (*c == '\\' || *c == '\'' || *c == '"')
+ if (*c == ' ')
+ {
+ *buf++ = '\\';
+ *buf++ = 'x';
+ *buf++ = '2';
+ *buf++ = '0';
+ c++;
+ continue;
+ }
+ else if (*c == '\\' && *(c+1) == 'x' &&
+ is_hex(*(c+2)) && is_hex(*(c+3)))
+ {
+ *buf++ = *c++;
+ *buf++ = *c++;
+ *buf++ = *c++;
+ *buf++ = *c++;
+ continue;
+ }
+ else if (*c == '\\' || *c == '\'' || *c == '"')
*buf++ = '\\';
*buf++ = *c;
diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c
index 0d05d6b0709..ba38b5e8aef 100644
--- a/grub-core/script/execute.c
+++ b/grub-core/script/execute.c
@@ -56,6 +56,12 @@ static struct grub_script_scope *scope = 0;
/* Wildcard translator for GRUB script. */
struct grub_script_wildcard_translator *grub_wildcard_translator;
+static int
+is_hex(char c)
+{
+ return ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
+}
+
static char*
wildcard_escape (const char *s)
{
@@ -72,7 +78,15 @@ wildcard_escape (const char *s)
i = 0;
while ((ch = *s++))
{
- if (ch == '*' || ch == '\\' || ch == '?')
+ if (ch == '\\' && s[0] == 'x' && is_hex(s[1]) && is_hex(s[2]))
+ {
+ p[i++] = ch;
+ p[i++] = *s++;
+ p[i++] = *s++;
+ p[i++] = *s++;
+ continue;
+ }
+ else if (ch == '*' || ch == '\\' || ch == '?')
p[i++] = '\\';
p[i++] = ch;
}
@@ -96,7 +110,14 @@ wildcard_unescape (const char *s)
i = 0;
while ((ch = *s++))
{
- if (ch == '\\')
+ if (ch == '\\' && s[0] == 'x' && is_hex(s[1]) && is_hex(s[2]))
+ {
+ p[i++] = '\\';
+ p[i++] = *s++;
+ p[i++] = *s++;
+ p[i++] = *s++;
+ }
+ else if (ch == '\\')
p[i++] = *s++;
else
p[i++] = ch;
@@ -398,10 +419,20 @@ parse_string (const char *str,
switch (*ptr)
{
case '\\':
- escaped = !escaped;
- if (!escaped && put)
- *(put++) = '\\';
- ptr++;
+ if (!escaped && put && *(ptr+1) == 'x' && is_hex(*(ptr+2)) && is_hex(*(ptr+3)))
+ {
+ *(put++) = *ptr++;
+ *(put++) = *ptr++;
+ *(put++) = *ptr++;
+ *(put++) = *ptr++;
+ }
+ else
+ {
+ escaped = !escaped;
+ if (!escaped && put)
+ *(put++) = '\\';
+ ptr++;
+ }
break;
case '$':
if (escaped)

View File

@ -0,0 +1,55 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
Date: Tue, 27 Nov 2012 16:58:39 -0200
Subject: [PATCH] Add %X option to printf functions.
---
grub-core/kern/misc.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
index cd63a8cea73..2656a670e09 100644
--- a/grub-core/kern/misc.c
+++ b/grub-core/kern/misc.c
@@ -588,7 +588,7 @@ grub_divmod64 (grub_uint64_t n, grub_uint64_t d, grub_uint64_t *r)
static inline char *
grub_lltoa (char *str, int c, unsigned long long n)
{
- unsigned base = (c == 'x') ? 16 : 10;
+ unsigned base = ((c == 'x') || (c == 'X')) ? 16 : 10;
char *p;
if ((long long) n < 0 && c == 'd')
@@ -603,7 +603,7 @@ grub_lltoa (char *str, int c, unsigned long long n)
do
{
unsigned d = (unsigned) (n & 0xf);
- *p++ = (d > 9) ? d + 'a' - 10 : d + '0';
+ *p++ = (d > 9) ? d + ((c == 'x') ? 'a' : 'A') - 10 : d + '0';
}
while (n >>= 4);
else
@@ -676,6 +676,7 @@ parse_printf_args (const char *fmt0, struct printf_args *args,
{
case 'p':
case 'x':
+ case 'X':
case 'u':
case 'd':
case 'c':
@@ -762,6 +763,7 @@ parse_printf_args (const char *fmt0, struct printf_args *args,
switch (c)
{
case 'x':
+ case 'X':
case 'u':
args->ptr[curn].type = UNSIGNED_INT + longfmt;
break;
@@ -900,6 +902,7 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0,
c = 'x';
/* Fall through. */
case 'x':
+ case 'X':
case 'u':
case 'd':
{

View File

@ -0,0 +1,200 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
Date: Tue, 27 Nov 2012 17:22:07 -0200
Subject: [PATCH] Search for specific config file for netboot
This patch implements a search for a specific configuration when the config
file is on a remoteserver. It uses the following order:
1) DHCP client UUID option.
2) MAC address (in lower case hexadecimal with dash separators);
3) IP (in upper case hexadecimal) or IPv6;
4) The original grub.cfg file.
This procedure is similar to what is used by pxelinux and yaboot:
http://www.syslinux.org/wiki/index.php/PXELINUX#config
This should close the bugzilla:
https://bugzilla.redhat.com/show_bug.cgi?id=873406
---
grub-core/net/net.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++
grub-core/normal/main.c | 18 ++++++--
include/grub/net.h | 3 ++
3 files changed, 135 insertions(+), 4 deletions(-)
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
index d5d726a315e..06454564b8f 100644
--- a/grub-core/net/net.c
+++ b/grub-core/net/net.c
@@ -1735,6 +1735,124 @@ grub_net_restore_hw (void)
return GRUB_ERR_NONE;
}
+grub_err_t
+grub_net_search_configfile (char *config)
+{
+ grub_size_t config_len;
+ char *suffix;
+
+ auto int search_through (grub_size_t num_tries, grub_size_t slice_size);
+ int search_through (grub_size_t num_tries, grub_size_t slice_size)
+ {
+ while (num_tries-- > 0)
+ {
+ grub_dprintf ("net", "probe %s\n", config);
+
+ grub_file_t file;
+ file = grub_file_open (config, GRUB_FILE_TYPE_CONFIG);
+
+ if (file)
+ {
+ grub_file_close (file);
+ grub_dprintf ("net", "found!\n");
+ return 0;
+ }
+ else
+ {
+ if (grub_errno == GRUB_ERR_IO)
+ grub_errno = GRUB_ERR_NONE;
+ }
+
+ if (grub_strlen (suffix) < slice_size)
+ break;
+
+ config[grub_strlen (config) - slice_size] = '\0';
+ }
+
+ return 1;
+ }
+
+ config_len = grub_strlen (config);
+ config[config_len] = '-';
+ suffix = config + config_len + 1;
+
+ struct grub_net_network_level_interface *inf;
+ FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
+ {
+ /* By the Client UUID. */
+
+ char client_uuid_var[sizeof ("net_") + grub_strlen (inf->name) +
+ sizeof ("_clientuuid") + 1];
+ grub_snprintf (client_uuid_var, sizeof (client_uuid_var),
+ "net_%s_clientuuid", inf->name);
+
+ const char *client_uuid;
+ client_uuid = grub_env_get (client_uuid_var);
+
+ if (client_uuid)
+ {
+ grub_strcpy (suffix, client_uuid);
+ if (search_through (1, 0) == 0) return GRUB_ERR_NONE;
+ }
+
+ /* By the MAC address. */
+
+ /* Add ethernet type */
+ grub_strcpy (suffix, "01-");
+
+ grub_net_hwaddr_to_str (&inf->hwaddress, suffix + 3);
+
+ char *ptr;
+ for (ptr = suffix; *ptr; ptr++)
+ if (*ptr == ':')
+ *ptr = '-';
+
+ if (search_through (1, 0) == 0) return GRUB_ERR_NONE;
+
+ /* By IP address */
+
+ switch ((&inf->address)->type)
+ {
+ case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
+ {
+ grub_uint32_t n = grub_be_to_cpu32 ((&inf->address)->ipv4);
+ grub_snprintf (suffix, GRUB_NET_MAX_STR_ADDR_LEN, "%02X%02X%02X%02X", \
+ ((n >> 24) & 0xff), ((n >> 16) & 0xff), \
+ ((n >> 8) & 0xff), ((n >> 0) & 0xff));
+
+ if (search_through (8, 1) == 0) return GRUB_ERR_NONE;
+ break;
+ }
+ case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6:
+ {
+ char buf[GRUB_NET_MAX_STR_ADDR_LEN];
+ struct grub_net_network_level_address base;
+ base.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
+ grub_memcpy (&base.ipv6, ((&inf->address)->ipv6), 16);
+ grub_net_addr_to_str (&base, buf);
+
+ for (ptr = buf; *ptr; ptr++)
+ if (*ptr == ':')
+ *ptr = '-';
+
+ grub_snprintf (suffix, GRUB_NET_MAX_STR_ADDR_LEN, "%s", buf);
+ if (search_through (1, 0) == 0) return GRUB_ERR_NONE;
+ break;
+ }
+ case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV:
+ return grub_error (GRUB_ERR_BUG, "shouldn't reach here");
+ default:
+ return grub_error (GRUB_ERR_BUG,
+ "unsupported address type %d", (&inf->address)->type);
+ }
+ }
+
+ /* Remove the remaining minus sign at the end. */
+ config[config_len] = '\0';
+
+ return GRUB_ERR_NONE;
+}
+
static struct grub_preboot *fini_hnd;
static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute;
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
index 394bfbea868..9ef98481f70 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -33,6 +33,7 @@
#include <grub/charset.h>
#include <grub/script_sh.h>
#include <grub/bufio.h>
+#include <grub/net.h>
#ifdef GRUB_MACHINE_IEEE1275
#include <grub/ieee1275/ieee1275.h>
#endif
@@ -365,10 +366,19 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)),
prefix = grub_env_get ("prefix");
if (prefix)
- {
- config = grub_xasprintf ("%s/grub.cfg", prefix);
- if (! config)
- goto quit;
+ {
+ grub_size_t config_len;
+ config_len = grub_strlen (prefix) +
+ sizeof ("/grub.cfg-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX");
+ config = grub_malloc (config_len);
+
+ if (! config)
+ goto quit;
+
+ grub_snprintf (config, config_len, "%s/grub.cfg", prefix);
+
+ if (grub_strncmp (prefix + 1, "tftp", sizeof ("tftp") - 1) == 0)
+ grub_net_search_configfile (config);
grub_enter_normal_mode (config);
grub_free (config);
diff --git a/include/grub/net.h b/include/grub/net.h
index 556c54e579f..ff6d347f7da 100644
--- a/include/grub/net.h
+++ b/include/grub/net.h
@@ -578,4 +578,7 @@ extern char *grub_net_default_server;
#define VLANTAG_IDENTIFIER 0x8100
+grub_err_t
+grub_net_search_configfile (char *config);
+
#endif /* ! GRUB_NET_HEADER */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,68 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Tue, 14 Jan 2014 13:12:23 -0500
Subject: [PATCH] Add devicetree loading
Signed-off-by: Peter Jones <pjones@redhat.com>
Switch to use APM Mustang device tree, for hardware testing.
Signed-off-by: David A. Marlin <d.marlin@redhat.com>
Use the default device tree from the grub default file
instead of hardcoding a value.
Signed-off-by: David A. Marlin <dmarlin@redhat.com>
---
util/grub-mkconfig.in | 3 ++-
util/grub.d/10_linux.in | 15 +++++++++++++++
2 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
index 9ecbcfb5b43..c645351dd2a 100644
--- a/util/grub-mkconfig.in
+++ b/util/grub-mkconfig.in
@@ -254,7 +254,8 @@ export GRUB_DEFAULT \
GRUB_ENABLE_CRYPTODISK \
GRUB_BADRAM \
GRUB_OS_PROBER_SKIP_LIST \
- GRUB_DISABLE_SUBMENU
+ GRUB_DISABLE_SUBMENU \
+ GRUB_DEFAULT_DTB
if test "x${grub_cfg}" != "x"; then
rm -f "${grub_cfg}.new"
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index 58defdbd83f..dd3128440c4 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -153,6 +153,13 @@ EOF
sed "s/^/$submenu_indentation/" << EOF
echo '$(echo "$message" | grub_quote)'
initrd $(echo $initrd_path)
+EOF
+ fi
+ if test -n "${fdt}" ; then
+ message="$(gettext_printf "Loading fdt ...")"
+ sed "s/^/$submenu_indentation/" << EOF
+ echo '$(echo "$message" | grub_quote)'
+ devicetree ${rel_dirname}/${fdt}
EOF
fi
sed "s/^/$submenu_indentation/" << EOF
@@ -236,6 +243,14 @@ while [ "x$list" != "x" ] ; do
gettext_printf "Found initrd image: %s\n" "$(echo $initrd_display)" >&2
fi
+ fdt=
+ for i in "dtb-${version}" "dtb-${alt_version}"; do
+ if test -f "${dirname}/${i}/${GRUB_DEFAULT_DTB}" ; then
+ fdt="${i}/${GRUB_DEFAULT_DTB}"
+ break
+ fi
+ done
+
config=
for i in "${dirname}/config-${version}" "${dirname}/config-${alt_version}" "/etc/kernels/kernel-config-${version}" ; do
if test -e "${i}" ; then

View File

@ -0,0 +1,176 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Jon McCann <william.jon.mccann@gmail.com>
Date: Wed, 15 May 2013 13:30:20 -0400
Subject: [PATCH] Don't write messages to the screen
Writing messages to the screen before the menus or boot splash
happens so quickly it looks like something is wrong and isn't
very appealing.
---
grub-core/gettext/gettext.c | 25 +++++--------------------
grub-core/kern/main.c | 5 -----
grub-core/boot/i386/pc/boot.S | 3 ---
grub-core/boot/i386/pc/diskboot.S | 5 -----
util/grub.d/10_linux.in | 7 -------
5 files changed, 5 insertions(+), 40 deletions(-)
diff --git a/grub-core/gettext/gettext.c b/grub-core/gettext/gettext.c
index 4d02e62c109..84d520cd494 100644
--- a/grub-core/gettext/gettext.c
+++ b/grub-core/gettext/gettext.c
@@ -434,16 +434,12 @@ static char *
grub_gettext_env_write_lang (struct grub_env_var *var
__attribute__ ((unused)), const char *val)
{
- grub_err_t err;
+ grub_err_t __attribute__((__unused__)) err;
err = grub_gettext_init_ext (&main_context, val, grub_env_get ("locale_dir"),
grub_env_get ("prefix"));
- if (err)
- grub_print_error ();
err = grub_gettext_init_ext (&secondary_context, val,
grub_env_get ("secondary_locale_dir"), 0);
- if (err)
- grub_print_error ();
return grub_strdup (val);
}
@@ -451,23 +447,19 @@ grub_gettext_env_write_lang (struct grub_env_var *var
void
grub_gettext_reread_prefix (const char *val)
{
- grub_err_t err;
+ grub_err_t __attribute__((__unused__)) err;
err = grub_gettext_init_ext (&main_context, grub_env_get ("lang"),
grub_env_get ("locale_dir"),
val);
- if (err)
- grub_print_error ();
}
static char *
read_main (struct grub_env_var *var
__attribute__ ((unused)), const char *val)
{
- grub_err_t err;
+ grub_err_t __attribute__((__unused__)) err;
err = grub_gettext_init_ext (&main_context, grub_env_get ("lang"), val,
grub_env_get ("prefix"));
- if (err)
- grub_print_error ();
return grub_strdup (val);
}
@@ -475,12 +467,9 @@ static char *
read_secondary (struct grub_env_var *var
__attribute__ ((unused)), const char *val)
{
- grub_err_t err;
+ grub_err_t __attribute__((__unused__)) err;
err = grub_gettext_init_ext (&secondary_context, grub_env_get ("lang"), val,
0);
- if (err)
- grub_print_error ();
-
return grub_strdup (val);
}
@@ -500,18 +489,14 @@ grub_cmd_translate (grub_command_t cmd __attribute__ ((unused)),
GRUB_MOD_INIT (gettext)
{
const char *lang;
- grub_err_t err;
+ grub_err_t __attribute__((__unused__)) err;
lang = grub_env_get ("lang");
err = grub_gettext_init_ext (&main_context, lang, grub_env_get ("locale_dir"),
grub_env_get ("prefix"));
- if (err)
- grub_print_error ();
err = grub_gettext_init_ext (&secondary_context, lang,
grub_env_get ("secondary_locale_dir"), 0);
- if (err)
- grub_print_error ();
grub_register_variable_hook ("locale_dir", NULL, read_main);
grub_register_variable_hook ("secondary_locale_dir", NULL, read_secondary);
diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c
index 8ab7794c47b..da47b18b50e 100644
--- a/grub-core/kern/main.c
+++ b/grub-core/kern/main.c
@@ -268,11 +268,6 @@ grub_main (void)
grub_boot_time ("After machine init.");
- /* Hello. */
- grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
- grub_printf ("Welcome to GRUB!\n\n");
- grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
-
grub_load_config ();
grub_boot_time ("Before loading embedded modules.");
diff --git a/grub-core/boot/i386/pc/boot.S b/grub-core/boot/i386/pc/boot.S
index 2bd0b2d2866..ea167fe1206 100644
--- a/grub-core/boot/i386/pc/boot.S
+++ b/grub-core/boot/i386/pc/boot.S
@@ -249,9 +249,6 @@ real_start:
/* save drive reference first thing! */
pushw %dx
- /* print a notification message on the screen */
- MSG(notification_string)
-
/* set %si to the disk address packet */
movw $disk_address_packet, %si
diff --git a/grub-core/boot/i386/pc/diskboot.S b/grub-core/boot/i386/pc/diskboot.S
index c1addc0df29..68d31de0c4c 100644
--- a/grub-core/boot/i386/pc/diskboot.S
+++ b/grub-core/boot/i386/pc/diskboot.S
@@ -50,11 +50,6 @@ _start:
/* save drive reference first thing! */
pushw %dx
- /* print a notification message on the screen */
- pushw %si
- MSG(notification_string)
- popw %si
-
/* this sets up for the first run through "bootloop" */
movw $LOCAL(firstlist), %di
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index dd3128440c4..ceb413fc2e3 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -138,27 +138,20 @@ linux_entry ()
fi
printf '%s\n' "${prepare_boot_cache}" | sed "s/^/$submenu_indentation/"
fi
- message="$(gettext_printf "Loading Linux %s ..." ${version})"
sed "s/^/$submenu_indentation/" << EOF
- echo '$(echo "$message" | grub_quote)'
linux ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args}
EOF
if test -n "${initrd}" ; then
- # TRANSLATORS: ramdisk isn't identifier. Should be translated.
- message="$(gettext_printf "Loading initial ramdisk ...")"
initrd_path=
for i in ${initrd}; do
initrd_path="${initrd_path} ${rel_dirname}/${i}"
done
sed "s/^/$submenu_indentation/" << EOF
- echo '$(echo "$message" | grub_quote)'
initrd $(echo $initrd_path)
EOF
fi
if test -n "${fdt}" ; then
- message="$(gettext_printf "Loading fdt ...")"
sed "s/^/$submenu_indentation/" << EOF
- echo '$(echo "$message" | grub_quote)'
devicetree ${rel_dirname}/${fdt}
EOF
fi

View File

@ -0,0 +1,42 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Jon McCann <william.jon.mccann@gmail.com>
Date: Wed, 15 May 2013 13:53:48 -0400
Subject: [PATCH] Don't print GNU GRUB header
No one cares.
---
grub-core/normal/main.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
index a326b192c89..09d0dfe76f1 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -208,15 +208,16 @@ read_config_file (const char *config)
/* Initialize the screen. */
void
grub_normal_init_page (struct grub_term_output *term,
- int y)
+ int y __attribute__((__unused__)))
{
+ grub_term_cls (term);
+
+#if 0
grub_ssize_t msg_len;
int posx;
char *msg_formatted;
grub_uint32_t *unicode_msg;
grub_uint32_t *last_position;
-
- grub_term_cls (term);
msg_formatted = grub_xasprintf (_("GNU GRUB version %s"), PACKAGE_VERSION);
if (!msg_formatted)
@@ -241,6 +242,7 @@ grub_normal_init_page (struct grub_term_output *term,
grub_putcode ('\n', term);
grub_putcode ('\n', term);
grub_free (unicode_msg);
+#endif
}
static void

View File

@ -0,0 +1,23 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Jon McCann <william.jon.mccann@gmail.com>
Date: Wed, 15 May 2013 17:49:45 -0400
Subject: [PATCH] Don't add '*' to highlighted row
It is already highlighted.
---
grub-core/normal/menu_text.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c
index e22bb91f6e8..a3d1f23f68f 100644
--- a/grub-core/normal/menu_text.c
+++ b/grub-core/normal/menu_text.c
@@ -242,7 +242,7 @@ print_entry (int y, int highlight, grub_menu_entry_t entry,
unicode_title[i] = ' ';
if (data->geo.num_entries > 1)
- grub_putcode (highlight ? '*' : ' ', data->term);
+ grub_putcode (' ', data->term);
grub_print_ucs4_menu (unicode_title,
unicode_title + len,

View File

@ -0,0 +1,68 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Jon McCann <william.jon.mccann@gmail.com>
Date: Fri, 7 Jun 2013 11:09:04 -0400
Subject: [PATCH] Message string cleanups
Make use of terminology consistent. Remove jargon.
---
grub-core/normal/menu_text.c | 21 +++++++++------------
1 file changed, 9 insertions(+), 12 deletions(-)
diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c
index a3d1f23f68f..64a83862f66 100644
--- a/grub-core/normal/menu_text.c
+++ b/grub-core/normal/menu_text.c
@@ -157,9 +157,8 @@ print_message (int nested, int edit, struct grub_term_output *term, int dry_run)
if (edit)
{
- ret += grub_print_message_indented_real (_("Minimum Emacs-like screen editing is \
-supported. TAB lists completions. Press Ctrl-x or F10 to boot, Ctrl-c or F2 for a \
-command-line or ESC to discard edits and return to the GRUB menu."),
+ ret += grub_print_message_indented_real (_("Press Ctrl-x or F10 to start, Ctrl-c or F2 for a \
+command prompt or Escape to discard edits and return to the menu. Pressing Tab lists possible completions."),
STANDARD_MARGIN, STANDARD_MARGIN,
term, dry_run);
}
@@ -167,8 +166,8 @@ command-line or ESC to discard edits and return to the GRUB menu."),
{
char *msg_translated;
- msg_translated = grub_xasprintf (_("Use the %C and %C keys to select which "
- "entry is highlighted."),
+ msg_translated = grub_xasprintf (_("Use the %C and %C keys to change the "
+ "selection."),
GRUB_UNICODE_UPARROW,
GRUB_UNICODE_DOWNARROW);
if (!msg_translated)
@@ -181,17 +180,15 @@ command-line or ESC to discard edits and return to the GRUB menu."),
if (nested)
{
ret += grub_print_message_indented_real
- (_("Press enter to boot the selected OS, "
- "`e' to edit the commands before booting "
- "or `c' for a command-line. ESC to return previous menu."),
+ (_("Press 'e' to edit the selected item, "
+ "or 'c' for a command prompt. Press Escape to return to the previous menu."),
STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
}
else
{
ret += grub_print_message_indented_real
- (_("Press enter to boot the selected OS, "
- "`e' to edit the commands before booting "
- "or `c' for a command-line."),
+ (_("Press 'e' to edit the selected item, "
+ "or 'c' for a command prompt."),
STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
}
}
@@ -443,7 +440,7 @@ menu_text_print_timeout (int timeout, void *dataptr)
|| data->timeout_msg == TIMEOUT_TERSE_NO_MARGIN)
msg_translated = grub_xasprintf (_("%ds"), timeout);
else
- msg_translated = grub_xasprintf (_("The highlighted entry will be executed automatically in %ds."), timeout);
+ msg_translated = grub_xasprintf (_("The selected entry will be started automatically in %ds."), timeout);
if (!msg_translated)
{
grub_print_error ();

View File

@ -0,0 +1,29 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Jon McCann <william.jon.mccann@gmail.com>
Date: Fri, 7 Jun 2013 14:08:23 -0400
Subject: [PATCH] Fix border spacing now that we aren't displaying it
---
grub-core/normal/menu_text.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c
index 64a83862f66..1062d64ee29 100644
--- a/grub-core/normal/menu_text.c
+++ b/grub-core/normal/menu_text.c
@@ -331,12 +331,12 @@ grub_menu_init_page (int nested, int edit,
int empty_lines = 1;
int version_msg = 1;
- geo->border = 1;
- geo->first_entry_x = 1 /* margin */ + 1 /* border */;
+ geo->border = 0;
+ geo->first_entry_x = 0 /* margin */ + 0 /* border */;
geo->entry_width = grub_term_width (term) - 5;
geo->first_entry_y = 2 /* two empty lines*/
- + 1 /* GNU GRUB version text */ + 1 /* top border */;
+ + 0 /* GNU GRUB version text */ + 1 /* top border */;
geo->timeout_lines = 2;

View File

@ -0,0 +1,25 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Jon McCann <william.jon.mccann@gmail.com>
Date: Fri, 7 Jun 2013 14:08:49 -0400
Subject: [PATCH] Use the correct indentation for the term help text
That is consistent with the menu help text
---
grub-core/normal/main.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
index 09d0dfe76f1..7f61c5b618b 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -432,8 +432,8 @@ grub_normal_reader_init (int nested)
grub_normal_init_page (term, 1);
grub_term_setcursor (term, 1);
- if (grub_term_width (term) > 3 + STANDARD_MARGIN + 20)
- grub_print_message_indented (msg_formatted, 3, STANDARD_MARGIN, term);
+ if (grub_term_width (term) > 2 * STANDARD_MARGIN + 20)
+ grub_print_message_indented (msg_formatted, STANDARD_MARGIN, STANDARD_MARGIN, term);
else
grub_print_message_indented (msg_formatted, 0, 0, term);
grub_putcode ('\n', term);

View File

@ -0,0 +1,23 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Jon McCann <william.jon.mccann@gmail.com>
Date: Fri, 7 Jun 2013 14:30:55 -0400
Subject: [PATCH] Indent menu entries
---
grub-core/normal/menu_text.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c
index 1062d64ee29..ecc60f99fc3 100644
--- a/grub-core/normal/menu_text.c
+++ b/grub-core/normal/menu_text.c
@@ -239,7 +239,8 @@ print_entry (int y, int highlight, grub_menu_entry_t entry,
unicode_title[i] = ' ';
if (data->geo.num_entries > 1)
- grub_putcode (' ', data->term);
+ for (i = 0; i < STANDARD_MARGIN; i++)
+ grub_putcode (' ', data->term);
grub_print_ucs4_menu (unicode_title,
unicode_title + len,

34
0036-Fix-margins.patch Normal file
View File

@ -0,0 +1,34 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Jon McCann <william.jon.mccann@gmail.com>
Date: Fri, 7 Jun 2013 14:59:36 -0400
Subject: [PATCH] Fix margins
---
grub-core/normal/menu_text.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c
index ecc60f99fc3..0e43f2c10cc 100644
--- a/grub-core/normal/menu_text.c
+++ b/grub-core/normal/menu_text.c
@@ -333,17 +333,15 @@ grub_menu_init_page (int nested, int edit,
int version_msg = 1;
geo->border = 0;
- geo->first_entry_x = 0 /* margin */ + 0 /* border */;
- geo->entry_width = grub_term_width (term) - 5;
+ geo->first_entry_x = 0; /* no margin */
+ geo->entry_width = grub_term_width (term) - 1;
- geo->first_entry_y = 2 /* two empty lines*/
- + 0 /* GNU GRUB version text */ + 1 /* top border */;
+ geo->first_entry_y = 3; /* three empty lines*/
geo->timeout_lines = 2;
/* 3 lines for timeout message and bottom margin. 2 lines for the border. */
geo->num_entries = grub_term_height (term) - geo->first_entry_y
- - 1 /* bottom border */
- 1 /* empty line before info message*/
- geo->timeout_lines /* timeout */
- 1 /* empty final line */;

View File

@ -0,0 +1,24 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Fri, 21 Jun 2013 14:44:08 -0400
Subject: [PATCH] Use -2 instead of -1 for our right-hand margin, so
linewrapping works (#976643).
Signed-off-by: Peter Jones <grub2-owner@fedoraproject.org>
---
grub-core/normal/menu_text.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c
index 0e43f2c10cc..537d4bf86ff 100644
--- a/grub-core/normal/menu_text.c
+++ b/grub-core/normal/menu_text.c
@@ -334,7 +334,7 @@ grub_menu_init_page (int nested, int edit,
geo->border = 0;
geo->first_entry_x = 0; /* no margin */
- geo->entry_width = grub_term_width (term) - 1;
+ geo->entry_width = grub_term_width (term) - 2;
geo->first_entry_y = 3; /* three empty lines*/

View File

@ -0,0 +1,23 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 28 Oct 2013 10:09:27 -0400
Subject: [PATCH] Enable pager by default. (#985860)
Signed-off-by: Peter Jones <pjones@redhat.com>
---
util/grub.d/00_header.in | 2 ++
1 file changed, 2 insertions(+)
diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in
index 93a90233ead..858b526c925 100644
--- a/util/grub.d/00_header.in
+++ b/util/grub.d/00_header.in
@@ -43,6 +43,8 @@ if [ "x${GRUB_DEFAULT_BUTTON}" = "xsaved" ] ; then GRUB_DEFAULT_BUTTON='${saved_
if [ "x${GRUB_TIMEOUT_BUTTON}" = "x" ] ; then GRUB_TIMEOUT_BUTTON="$GRUB_TIMEOUT" ; fi
cat << EOF
+set pager=1
+
if [ -s \$prefix/grubenv ]; then
load_env
fi

View File

@ -0,0 +1,24 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 28 Oct 2013 10:13:27 -0400
Subject: [PATCH] F10 doesn't work on serial, so don't tell the user to hit it
(#987443)
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/normal/menu_text.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c
index 537d4bf86ff..452d55bf9ff 100644
--- a/grub-core/normal/menu_text.c
+++ b/grub-core/normal/menu_text.c
@@ -157,7 +157,7 @@ print_message (int nested, int edit, struct grub_term_output *term, int dry_run)
if (edit)
{
- ret += grub_print_message_indented_real (_("Press Ctrl-x or F10 to start, Ctrl-c or F2 for a \
+ ret += grub_print_message_indented_real (_("Press Ctrl-x to start, Ctrl-c for a \
command prompt or Escape to discard edits and return to the menu. Pressing Tab lists possible completions."),
STANDARD_MARGIN, STANDARD_MARGIN,
term, dry_run);

View File

@ -0,0 +1,42 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 14 Mar 2011 14:27:42 -0400
Subject: [PATCH] Don't say "GNU/Linux" in generated menus.
---
util/grub.d/10_linux.in | 4 ++--
util/grub.d/20_linux_xen.in | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index ceb413fc2e3..2b402d85a52 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -29,9 +29,9 @@ export TEXTDOMAINDIR="@localedir@"
CLASS="--class gnu-linux --class gnu --class os"
if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
- OS=GNU/Linux
+ OS="$(sed 's, release .*$,,g' /etc/system-release)"
else
- OS="${GRUB_DISTRIBUTOR} GNU/Linux"
+ OS="${GRUB_DISTRIBUTOR}"
CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1|LC_ALL=C sed 's,[^[:alnum:]_],_,g') ${CLASS}"
fi
diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in
index 96179ea613c..47e0d3f5cd6 100644
--- a/util/grub.d/20_linux_xen.in
+++ b/util/grub.d/20_linux_xen.in
@@ -29,9 +29,9 @@ export TEXTDOMAINDIR="@localedir@"
CLASS="--class gnu-linux --class gnu --class os --class xen"
if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
- OS=GNU/Linux
+ OS="$(sed 's, release .*$,,g' /etc/system-release)"
else
- OS="${GRUB_DISTRIBUTOR} GNU/Linux"
+ OS="${GRUB_DISTRIBUTOR}"
CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1|LC_ALL=C sed 's,[^[:alnum:]_],_,g') ${CLASS}"
fi

View File

@ -0,0 +1,71 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Jon McCann <william.jon.mccann@gmail.com>
Date: Wed, 15 May 2013 16:47:33 -0400
Subject: [PATCH] Don't draw a border around the menu
It looks cleaner without it.
---
grub-core/normal/menu_text.c | 43 -------------------------------------------
1 file changed, 43 deletions(-)
diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c
index 452d55bf9ff..1ed2bd92cf8 100644
--- a/grub-core/normal/menu_text.c
+++ b/grub-core/normal/menu_text.c
@@ -108,47 +108,6 @@ grub_print_message_indented (const char *msg, int margin_left, int margin_right,
grub_print_message_indented_real (msg, margin_left, margin_right, term, 0);
}
-static void
-draw_border (struct grub_term_output *term, const struct grub_term_screen_geometry *geo)
-{
- int i;
-
- grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL);
-
- grub_term_gotoxy (term, (struct grub_term_coordinate) { geo->first_entry_x - 1,
- geo->first_entry_y - 1 });
- grub_putcode (GRUB_UNICODE_CORNER_UL, term);
- for (i = 0; i < geo->entry_width + 1; i++)
- grub_putcode (GRUB_UNICODE_HLINE, term);
- grub_putcode (GRUB_UNICODE_CORNER_UR, term);
-
- for (i = 0; i < geo->num_entries; i++)
- {
- grub_term_gotoxy (term, (struct grub_term_coordinate) { geo->first_entry_x - 1,
- geo->first_entry_y + i });
- grub_putcode (GRUB_UNICODE_VLINE, term);
- grub_term_gotoxy (term,
- (struct grub_term_coordinate) { geo->first_entry_x + geo->entry_width + 1,
- geo->first_entry_y + i });
- grub_putcode (GRUB_UNICODE_VLINE, term);
- }
-
- grub_term_gotoxy (term,
- (struct grub_term_coordinate) { geo->first_entry_x - 1,
- geo->first_entry_y - 1 + geo->num_entries + 1 });
- grub_putcode (GRUB_UNICODE_CORNER_LL, term);
- for (i = 0; i < geo->entry_width + 1; i++)
- grub_putcode (GRUB_UNICODE_HLINE, term);
- grub_putcode (GRUB_UNICODE_CORNER_LR, term);
-
- grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL);
-
- grub_term_gotoxy (term,
- (struct grub_term_coordinate) { geo->first_entry_x - 1,
- (geo->first_entry_y - 1 + geo->num_entries
- + GRUB_TERM_MARGIN + 1) });
-}
-
static int
print_message (int nested, int edit, struct grub_term_output *term, int dry_run)
{
@@ -406,8 +365,6 @@ grub_menu_init_page (int nested, int edit,
grub_term_normal_color = grub_color_menu_normal;
grub_term_highlight_color = grub_color_menu_highlight;
- if (geo->border)
- draw_border (term, geo);
grub_term_normal_color = old_color_normal;
grub_term_highlight_color = old_color_highlight;
geo->timeout_y = geo->first_entry_y + geo->num_entries

View File

@ -0,0 +1,40 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Jon McCann <william.jon.mccann@gmail.com>
Date: Fri, 7 Jun 2013 10:52:32 -0400
Subject: [PATCH] Use the standard margin for the timeout string
So that it aligns with the other messages
---
grub-core/normal/menu_text.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c
index 1ed2bd92cf8..7681f7d2893 100644
--- a/grub-core/normal/menu_text.c
+++ b/grub-core/normal/menu_text.c
@@ -372,7 +372,7 @@ grub_menu_init_page (int nested, int edit,
if (bottom_message)
{
grub_term_gotoxy (term,
- (struct grub_term_coordinate) { GRUB_TERM_MARGIN,
+ (struct grub_term_coordinate) { STANDARD_MARGIN,
geo->timeout_y });
print_message (nested, edit, term, 0);
@@ -407,14 +407,14 @@ menu_text_print_timeout (int timeout, void *dataptr)
if (data->timeout_msg == TIMEOUT_UNKNOWN)
{
data->timeout_msg = grub_print_message_indented_real (msg_translated,
- 3, 1, data->term, 1)
+ STANDARD_MARGIN, 1, data->term, 1)
<= data->geo.timeout_lines ? TIMEOUT_NORMAL : TIMEOUT_TERSE;
if (data->timeout_msg == TIMEOUT_TERSE)
{
grub_free (msg_translated);
msg_translated = grub_xasprintf (_("%ds"), timeout);
if (grub_term_width (data->term) < 10)
- data->timeout_msg = TIMEOUT_TERSE_NO_MARGIN;
+ data->timeout_msg = STANDARD_MARGIN;
}
}

View File

@ -0,0 +1,22 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Fedora Ninjas <grub2-owner@fedoraproject.org>
Date: Mon, 13 Jan 2014 21:50:59 -0500
Subject: [PATCH] Add .eh_frame to list of relocations stripped
---
conf/Makefile.common | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/conf/Makefile.common b/conf/Makefile.common
index 6cd71cbb2ab..4ba729e14d8 100644
--- a/conf/Makefile.common
+++ b/conf/Makefile.common
@@ -38,7 +38,7 @@ CFLAGS_KERNEL = $(CFLAGS_PLATFORM) -ffreestanding
LDFLAGS_KERNEL = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC)
CPPFLAGS_KERNEL = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) -DGRUB_KERNEL=1
CCASFLAGS_KERNEL = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM)
-STRIPFLAGS_KERNEL = -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version -R .MIPS.abiflags -R .ARM.exidx
+STRIPFLAGS_KERNEL = -R .eh_frame -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version -R .MIPS.abiflags -R .ARM.exidx
CFLAGS_MODULE = $(CFLAGS_PLATFORM) -ffreestanding
LDFLAGS_MODULE = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -Wl,-r,-d

View File

@ -0,0 +1,33 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Mon, 30 Jun 2014 14:16:46 -0400
Subject: [PATCH] Don't munge raw spaces when we're doing our cmdline escaping
(#923374)
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/lib/cmdline.c | 11 +----------
1 file changed, 1 insertion(+), 10 deletions(-)
diff --git a/grub-core/lib/cmdline.c b/grub-core/lib/cmdline.c
index e0fb0a9e48a..8e2294d8ff6 100644
--- a/grub-core/lib/cmdline.c
+++ b/grub-core/lib/cmdline.c
@@ -98,16 +98,7 @@ grub_create_loader_cmdline (int argc, char *argv[], char *buf,
while (*c)
{
- if (*c == ' ')
- {
- *buf++ = '\\';
- *buf++ = 'x';
- *buf++ = '2';
- *buf++ = '0';
- c++;
- continue;
- }
- else if (*c == '\\' && *(c+1) == 'x' &&
+ if (*c == '\\' && *(c+1) == 'x' &&
is_hex(*(c+2)) && is_hex(*(c+3)))
{
*buf++ = *c++;

View File

@ -0,0 +1,28 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Tue, 11 Feb 2014 11:14:50 -0500
Subject: [PATCH] Don't require a password to boot entries generated by
grub-mkconfig.
When we set a password, we just want that to mean you can't /edit/ an entry.
Resolves: rhbz#1030176
Signed-off-by: Peter Jones <pjones@redhat.com>
---
util/grub.d/10_linux.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index 2b402d85a52..d35b0f406bc 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -26,7 +26,7 @@ datarootdir="@datarootdir@"
export TEXTDOMAIN=@PACKAGE@
export TEXTDOMAINDIR="@localedir@"
-CLASS="--class gnu-linux --class gnu --class os"
+CLASS="--class gnu-linux --class gnu --class os --unrestricted"
if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
OS="$(sed 's, release .*$,,g' /etc/system-release)"

View File

@ -0,0 +1,49 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Tue, 18 Feb 2014 09:37:49 -0500
Subject: [PATCH] Don't emit "Booting ..." message.
UI team still hates this stuff, so we're disabling it for RHEL 7.
Resolves: rhbz#1023142
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/normal/menu.c | 4 +++-
grub-core/normal/menu_entry.c | 3 ---
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c
index 9175ad297d8..783bde55b9e 100644
--- a/grub-core/normal/menu.c
+++ b/grub-core/normal/menu.c
@@ -839,12 +839,14 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
/* Callback invoked immediately before a menu entry is executed. */
static void
-notify_booting (grub_menu_entry_t entry,
+notify_booting (grub_menu_entry_t __attribute__((unused)) entry,
void *userdata __attribute__((unused)))
{
+#if 0
grub_printf (" ");
grub_printf_ (N_("Booting `%s'"), entry->title);
grub_printf ("\n\n");
+#endif
}
/* Callback invoked when a default menu entry executed because of a timeout
diff --git a/grub-core/normal/menu_entry.c b/grub-core/normal/menu_entry.c
index cdf3590a364..5785f67ee1c 100644
--- a/grub-core/normal/menu_entry.c
+++ b/grub-core/normal/menu_entry.c
@@ -1167,9 +1167,6 @@ run (struct screen *screen)
char *dummy[1] = { NULL };
grub_cls ();
- grub_printf (" ");
- grub_printf_ (N_("Booting a command list"));
- grub_printf ("\n\n");
errs_before = grub_err_printed_errors;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,41 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Fedora Ninjas <grub2-owner@fedoraproject.org>
Date: Wed, 19 Feb 2014 15:58:43 -0500
Subject: [PATCH] use fw_path prefix when fallback searching for grub config
When PXE booting via UEFI firmware, grub was searching for grub.cfg
in the fw_path directory where the grub application was found. If
that didn't exist, a fallback search would look for config file names
based on MAC and IP address. However, the search would look in the
prefix directory which may not be the same fw_path. This patch
changes that behavior to use the fw_path directory for the fallback
search. Only if fw_path is NULL will the prefix directory be searched.
Signed-off-by: Mark Salter <msalter@redhat.com>
---
grub-core/normal/main.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
index 7f61c5b618b..8add30e605f 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -349,7 +349,7 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)),
char *config;
const char *prefix, *fw_path;
- fw_path = grub_env_get ("fw_path");
+ prefix = fw_path = grub_env_get ("fw_path");
if (fw_path)
{
config = grub_xasprintf ("%s/grub.cfg", fw_path);
@@ -372,7 +372,8 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)),
}
}
- prefix = grub_env_get ("prefix");
+ if (! prefix)
+ prefix = grub_env_get ("prefix");
if (prefix)
{
grub_size_t config_len;

View File

@ -0,0 +1,113 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 8 Jul 2019 17:33:22 +0200
Subject: [PATCH] Try mac/guid/etc before grub.cfg on tftp config files.
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/normal/main.c | 84 ++++++++++++++++++++++++++-----------------------
1 file changed, 45 insertions(+), 39 deletions(-)
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
index 8add30e605f..d93bee613ac 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -347,53 +347,59 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)),
/* Guess the config filename. It is necessary to make CONFIG static,
so that it won't get broken by longjmp. */
char *config;
- const char *prefix, *fw_path;
-
- prefix = fw_path = grub_env_get ("fw_path");
- if (fw_path)
- {
- config = grub_xasprintf ("%s/grub.cfg", fw_path);
- if (config)
- {
- grub_file_t file;
-
- file = grub_file_open (config, GRUB_FILE_TYPE_CONFIG);
- if (file)
- {
- grub_file_close (file);
- grub_enter_normal_mode (config);
- }
- else
- {
- /* Ignore all errors. */
- grub_errno = 0;
- }
- grub_free (config);
- }
- }
+ const char *prefix;
+ prefix = grub_env_get ("fw_path");
if (! prefix)
prefix = grub_env_get ("prefix");
+
if (prefix)
{
- grub_size_t config_len;
- config_len = grub_strlen (prefix) +
- sizeof ("/grub.cfg-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX");
- config = grub_malloc (config_len);
-
- if (! config)
- goto quit;
-
- grub_snprintf (config, config_len, "%s/grub.cfg", prefix);
-
if (grub_strncmp (prefix + 1, "tftp", sizeof ("tftp") - 1) == 0)
- grub_net_search_configfile (config);
+ {
+ grub_size_t config_len;
+ config_len = grub_strlen (prefix) +
+ sizeof ("/grub.cfg-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX");
+ config = grub_malloc (config_len);
- grub_enter_normal_mode (config);
- grub_free (config);
- }
+ if (! config)
+ goto quit;
+
+ grub_snprintf (config, config_len, "%s/grub.cfg", prefix);
+
+ grub_net_search_configfile (config);
+
+ grub_enter_normal_mode (config);
+ grub_free (config);
+ config = NULL;
+ }
+
+ if (!config)
+ {
+ config = grub_xasprintf ("%s/grub.cfg", prefix);
+ if (config)
+ {
+ grub_file_t file;
+
+ file = grub_file_open (config, GRUB_FILE_TYPE_CONFIG);
+ if (file)
+ {
+ grub_file_close (file);
+ grub_enter_normal_mode (config);
+ }
+ else
+ {
+ /* Ignore all errors. */
+ grub_errno = 0;
+ }
+ grub_free (config);
+ }
+ }
+ }
else
- grub_enter_normal_mode (0);
+ {
+ grub_enter_normal_mode (0);
+ }
}
else
grub_enter_normal_mode (argv[0]);

View File

@ -0,0 +1,56 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Tue, 18 Feb 2014 11:34:00 -0500
Subject: [PATCH] Fix convert function to support NVMe devices
This is adapted from the patch at
https://bugzilla.redhat.com/show_bug.cgi?id=1019660 , which is against
the now very old version of convert_system_partition_to_system_disk().
As such, it certainly not the right thing for upstream, but should
function for now.
Resolves: rhbz#1019660
Signed-off-by: Peter Jones <grub2-owner@fedoraproject.org>
---
util/getroot.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/util/getroot.c b/util/getroot.c
index 847406fbab0..fa3460d6cd8 100644
--- a/util/getroot.c
+++ b/util/getroot.c
@@ -153,6 +153,7 @@ convert_system_partition_to_system_disk (const char *os_dev, int *is_part)
{
#if GRUB_UTIL_FD_STAT_IS_FUNCTIONAL
struct stat st;
+ char *path = xmalloc(PATH_MAX);
if (stat (os_dev, &st) < 0)
{
@@ -165,6 +166,24 @@ convert_system_partition_to_system_disk (const char *os_dev, int *is_part)
*is_part = 0;
+ if (realpath(os_dev, path))
+ {
+ if ((strncmp ("/dev/nvme", path, 9) == 0))
+ {
+ char *p = path + 5;
+ p = strchr(p, 'p');
+ if (p)
+ {
+ *is_part = 1;
+ *p = '\0';
+ }
+ return path;
+ }
+ }
+
+ grub_free (path);
+ *is_part = 0;
+
if (grub_util_device_is_mapped_stat (&st))
return grub_util_devmapper_part_to_disk (&st, is_part, os_dev);

View File

@ -0,0 +1,82 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 8 Jul 2019 21:46:52 +0200
Subject: [PATCH] Add grub_util_readlink()
Add grub_util_readlink(). This requires pulling in stat and readlink from
gnulib, which pulls in stat and related headers, but after that the
implementation is straightforward.
Signed-off-by: Peter Jones <pjones@redhat.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
---
grub-core/osdep/windows/hostdisk.c | 6 ++++++
include/grub/osdep/hostfile_aros.h | 6 ++++++
include/grub/osdep/hostfile_unix.h | 6 ++++++
include/grub/osdep/hostfile_windows.h | 2 ++
4 files changed, 20 insertions(+)
diff --git a/grub-core/osdep/windows/hostdisk.c b/grub-core/osdep/windows/hostdisk.c
index 355100789a7..87a106c9b82 100644
--- a/grub-core/osdep/windows/hostdisk.c
+++ b/grub-core/osdep/windows/hostdisk.c
@@ -365,6 +365,12 @@ grub_util_mkdir (const char *dir)
free (windows_name);
}
+ssize_t
+grub_util_readlink (const char *name, char *buf, size_t bufsize)
+{
+ return readlink(name, buf, bufsize);
+}
+
int
grub_util_rename (const char *from, const char *to)
{
diff --git a/include/grub/osdep/hostfile_aros.h b/include/grub/osdep/hostfile_aros.h
index a059c0fa40a..161fbb7bdfd 100644
--- a/include/grub/osdep/hostfile_aros.h
+++ b/include/grub/osdep/hostfile_aros.h
@@ -68,6 +68,12 @@ grub_util_rename (const char *from, const char *to)
return rename (from, to);
}
+static inline ssize_t
+grub_util_readlink (const char *name, char *buf, size_t bufsize)
+{
+ return readlink(name, buf, bufsize);
+}
+
#define grub_util_mkdir(a) mkdir ((a), 0755)
struct grub_util_fd
diff --git a/include/grub/osdep/hostfile_unix.h b/include/grub/osdep/hostfile_unix.h
index 9ffe46fa3ca..17cd3aa8b30 100644
--- a/include/grub/osdep/hostfile_unix.h
+++ b/include/grub/osdep/hostfile_unix.h
@@ -71,6 +71,12 @@ grub_util_rename (const char *from, const char *to)
return rename (from, to);
}
+static inline ssize_t
+grub_util_readlink (const char *name, char *buf, size_t bufsize)
+{
+ return readlink(name, buf, bufsize);
+}
+
#define grub_util_mkdir(a) mkdir ((a), 0755)
#if defined (__NetBSD__)
diff --git a/include/grub/osdep/hostfile_windows.h b/include/grub/osdep/hostfile_windows.h
index bf6451b6db4..8c92d0591bb 100644
--- a/include/grub/osdep/hostfile_windows.h
+++ b/include/grub/osdep/hostfile_windows.h
@@ -41,6 +41,8 @@ typedef struct grub_util_fd_dir *grub_util_fd_dir_t;
int
grub_util_rename (const char *from, const char *to);
+ssize_t
+grub_util_readlink (const char *name, char *buf, size_t bufsize);
int
grub_util_unlink (const char *name);
void

View File

@ -0,0 +1,104 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Wed, 3 Sep 2014 10:38:00 -0400
Subject: [PATCH] Make editenv chase symlinks including those across devices.
This lets us make /boot/grub2/grubenv a symlink to
/boot/efi/EFI/fedora/grubenv even though they're different mount points,
which allows /usr/bin/grub2-editenv to be the same across platforms
(i.e. UEFI vs BIOS).
Signed-off-by: Peter Jones <pjones@redhat.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
---
Makefile.util.def | 11 +++++++++++
util/editenv.c | 46 ++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 55 insertions(+), 2 deletions(-)
diff --git a/Makefile.util.def b/Makefile.util.def
index 8717774d510..1f298d05f3d 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -240,8 +240,19 @@ program = {
common = util/grub-editenv.c;
common = util/editenv.c;
+ common = util/grub-install-common.c;
common = grub-core/osdep/init.c;
+ common = grub-core/osdep/compress.c;
+ extra_dist = grub-core/osdep/unix/compress.c;
+ extra_dist = grub-core/osdep/basic/compress.c;
+ common = util/mkimage.c;
+ common = util/grub-mkimage32.c;
+ common = util/grub-mkimage64.c;
+ common = grub-core/osdep/config.c;
+ common = util/config.c;
+ common = util/resolve.c;
+ ldadd = '$(LIBLZMA)';
ldadd = libgrubmods.a;
ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
diff --git a/util/editenv.c b/util/editenv.c
index eb2d0c03a98..e61dc1283a4 100644
--- a/util/editenv.c
+++ b/util/editenv.c
@@ -37,6 +37,7 @@ grub_util_create_envblk_file (const char *name)
FILE *fp;
char *buf;
char *namenew;
+ char *rename_target = xstrdup(name);
buf = xmalloc (DEFAULT_ENVBLK_SIZE);
@@ -60,7 +61,48 @@ grub_util_create_envblk_file (const char *name)
free (buf);
fclose (fp);
- if (grub_util_rename (namenew, name) < 0)
- grub_util_error (_("cannot rename the file %s to %s"), namenew, name);
+ ssize_t size = 1;
+ while (1)
+ {
+ char *linkbuf;
+ ssize_t retsize;
+
+ linkbuf = xmalloc(size+1);
+ retsize = grub_util_readlink (rename_target, linkbuf, size);
+ if (retsize < 0 && (errno == ENOENT || errno == EINVAL))
+ {
+ free (linkbuf);
+ break;
+ }
+ else if (retsize < 0)
+ {
+ grub_util_error (_("cannot rename the file %s to %s: %m"), namenew, name);
+ free (linkbuf);
+ free (namenew);
+ return;
+ }
+ else if (retsize == size)
+ {
+ free(linkbuf);
+ size += 128;
+ continue;
+ }
+
+ free (rename_target);
+ linkbuf[retsize] = '\0';
+ rename_target = linkbuf;
+ }
+
+ int rc = grub_util_rename (namenew, rename_target);
+ if (rc < 0 && errno == EXDEV)
+ {
+ rc = grub_install_copy_file (namenew, rename_target, 1);
+ grub_util_unlink (namenew);
+ }
+
+ if (rc < 0)
+ grub_util_error (_("cannot rename the file %s to %s: %m"), namenew, name);
+
free (namenew);
+ free (rename_target);
}

View File

@ -0,0 +1,29 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 4 Sep 2014 14:23:23 -0400
Subject: [PATCH] Generate OS and CLASS in 10_linux from /etc/os-release
This makes us use pretty names in the titles we generate in
grub2-mkconfig when GRUB_DISTRIBUTOR isn't set.
Resolves: rhbz#996794
Signed-off-by: Peter Jones <pjones@redhat.com>
---
util/grub.d/10_linux.in | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index d35b0f406bc..d12d2d784dc 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -29,7 +29,8 @@ export TEXTDOMAINDIR="@localedir@"
CLASS="--class gnu-linux --class gnu --class os --unrestricted"
if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
- OS="$(sed 's, release .*$,,g' /etc/system-release)"
+ OS="$(eval $(grep PRETTY_NAME /etc/os-release) ; echo ${PRETTY_NAME})"
+ CLASS="--class $(eval $(grep '^ID_LIKE=\|^ID=' /etc/os-release) ; [ -n "${ID_LIKE}" ] && echo ${ID_LIKE} || echo ${ID}) ${CLASS}"
else
OS="${GRUB_DISTRIBUTOR}"
CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1|LC_ALL=C sed 's,[^[:alnum:]_],_,g') ${CLASS}"

View File

@ -0,0 +1,30 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 4 Sep 2014 15:52:08 -0400
Subject: [PATCH] Minimize the sort ordering for .debug and -rescue- kernels.
Resolves: rhbz#1065360
Signed-off-by: Peter Jones <pjones@redhat.com>
---
util/grub-mkconfig_lib.in | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in
index 1001a12232b..1a4a57898f9 100644
--- a/util/grub-mkconfig_lib.in
+++ b/util/grub-mkconfig_lib.in
@@ -249,6 +249,14 @@ version_test_gt ()
*.old:*.old) ;;
*.old:*) version_test_gt_a="`echo "$version_test_gt_a" | sed -e 's/\.old$//'`" ; version_test_gt_cmp=gt ;;
*:*.old) version_test_gt_b="`echo "$version_test_gt_b" | sed -e 's/\.old$//'`" ; version_test_gt_cmp=ge ;;
+ *-rescue*:*-rescue*) ;;
+ *?debug:*?debug) ;;
+ *-rescue*:*?debug) return 1 ;;
+ *?debug:*-rescue*) return 0 ;;
+ *-rescue*:*) return 1 ;;
+ *:*-rescue*) return 0 ;;
+ *?debug:*) return 1 ;;
+ *:*?debug) return 0 ;;
esac
version_test_numeric "$version_test_gt_a" "$version_test_gt_cmp" "$version_test_gt_b"
return "$?"

View File

@ -0,0 +1,208 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Tue, 9 Jul 2019 10:35:16 +0200
Subject: [PATCH] Try $prefix if $fw_path doesn't work.
Related: rhbz#1148652
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/kern/ieee1275/init.c | 28 +++++-----
grub-core/net/net.c | 2 +-
grub-core/normal/main.c | 120 ++++++++++++++++++++---------------------
3 files changed, 75 insertions(+), 75 deletions(-)
diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
index e71d1584164..0cd2a627231 100644
--- a/grub-core/kern/ieee1275/init.c
+++ b/grub-core/kern/ieee1275/init.c
@@ -127,23 +127,25 @@ grub_machine_get_bootlocation (char **device, char **path)
grub_free (canon);
}
else
- *device = grub_ieee1275_encode_devname (bootpath);
- grub_free (type);
-
- filename = grub_ieee1275_get_filename (bootpath);
- if (filename)
{
- char *lastslash = grub_strrchr (filename, '\\');
-
- /* Truncate at last directory. */
- if (lastslash)
+ filename = grub_ieee1275_get_filename (bootpath);
+ if (filename)
{
- *lastslash = '\0';
- grub_translate_ieee1275_path (filename);
+ char *lastslash = grub_strrchr (filename, '\\');
- *path = filename;
- }
+ /* Truncate at last directory. */
+ if (lastslash)
+ {
+ *lastslash = '\0';
+ grub_translate_ieee1275_path (filename);
+
+ *path = filename;
+ }
+ }
+ *device = grub_ieee1275_encode_devname (bootpath);
}
+
+ grub_free (type);
grub_free (bootpath);
}
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
index 06454564b8f..4b7972b8e7e 100644
--- a/grub-core/net/net.c
+++ b/grub-core/net/net.c
@@ -1850,7 +1850,7 @@ grub_net_search_configfile (char *config)
/* Remove the remaining minus sign at the end. */
config[config_len] = '\0';
- return GRUB_ERR_NONE;
+ return GRUB_ERR_FILE_NOT_FOUND;
}
static struct grub_preboot *fini_hnd;
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
index d93bee613ac..2fe6743399d 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -337,74 +337,72 @@ grub_enter_normal_mode (const char *config)
grub_boot_time ("Exiting normal mode");
}
+static grub_err_t
+grub_try_normal (const char *variable)
+{
+ char *config;
+ const char *prefix;
+ grub_err_t err = GRUB_ERR_FILE_NOT_FOUND;
+
+ prefix = grub_env_get (variable);
+ if (!prefix)
+ return GRUB_ERR_FILE_NOT_FOUND;
+
+ if (grub_strncmp (prefix + 1, "tftp", sizeof ("tftp") - 1) == 0)
+ {
+ grub_size_t config_len;
+ config_len = grub_strlen (prefix) +
+ sizeof ("/grub.cfg-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX");
+ config = grub_malloc (config_len);
+
+ if (! config)
+ return GRUB_ERR_FILE_NOT_FOUND;
+
+ grub_snprintf (config, config_len, "%s/grub.cfg", prefix);
+ err = grub_net_search_configfile (config);
+ }
+
+ if (err != GRUB_ERR_NONE)
+ {
+ config = grub_xasprintf ("%s/grub.cfg", prefix);
+ if (config)
+ {
+ grub_file_t file;
+ file = grub_file_open (config, GRUB_FILE_TYPE_CONFIG);
+ if (file)
+ {
+ grub_file_close (file);
+ err = GRUB_ERR_NONE;
+ }
+ }
+ }
+
+ if (err == GRUB_ERR_NONE)
+ grub_enter_normal_mode (config);
+
+ grub_errno = 0;
+ grub_free (config);
+ return err;
+}
+
/* Enter normal mode from rescue mode. */
static grub_err_t
grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)),
int argc, char *argv[])
{
- if (argc == 0)
- {
- /* Guess the config filename. It is necessary to make CONFIG static,
- so that it won't get broken by longjmp. */
- char *config;
- const char *prefix;
-
- prefix = grub_env_get ("fw_path");
- if (! prefix)
- prefix = grub_env_get ("prefix");
-
- if (prefix)
- {
- if (grub_strncmp (prefix + 1, "tftp", sizeof ("tftp") - 1) == 0)
- {
- grub_size_t config_len;
- config_len = grub_strlen (prefix) +
- sizeof ("/grub.cfg-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX");
- config = grub_malloc (config_len);
-
- if (! config)
- goto quit;
-
- grub_snprintf (config, config_len, "%s/grub.cfg", prefix);
-
- grub_net_search_configfile (config);
-
- grub_enter_normal_mode (config);
- grub_free (config);
- config = NULL;
- }
-
- if (!config)
- {
- config = grub_xasprintf ("%s/grub.cfg", prefix);
- if (config)
- {
- grub_file_t file;
-
- file = grub_file_open (config, GRUB_FILE_TYPE_CONFIG);
- if (file)
- {
- grub_file_close (file);
- grub_enter_normal_mode (config);
- }
- else
- {
- /* Ignore all errors. */
- grub_errno = 0;
- }
- grub_free (config);
- }
- }
- }
- else
- {
- grub_enter_normal_mode (0);
- }
- }
- else
+ if (argc)
grub_enter_normal_mode (argv[0]);
+ else
+ {
+ /* Guess the config filename. */
+ grub_err_t err;
+ err = grub_try_normal ("fw_path");
+ if (err == GRUB_ERR_FILE_NOT_FOUND)
+ err = grub_try_normal ("prefix");
+ if (err == GRUB_ERR_FILE_NOT_FOUND)
+ grub_enter_normal_mode (0);
+ }
-quit:
return 0;
}

View File

@ -0,0 +1,66 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Robert Marshall <rmarshall@redhat.com>
Date: Mon, 16 Mar 2015 16:34:51 -0400
Subject: [PATCH] Update info with grub.cfg netboot selection order (#1148650)
Added documentation to the grub info page that specifies the order
netboot clients will use to select a grub configuration file.
Resolves rhbz#1148650
---
docs/grub.texi | 42 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
diff --git a/docs/grub.texi b/docs/grub.texi
index 6f524305085..221064b5679 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -2493,6 +2493,48 @@ grub-mknetdir --net-directory=/srv/tftp --subdir=/boot/grub -d /usr/lib/grub/i38
Then follow instructions printed out by grub-mknetdir on configuring your DHCP
server.
+The grub.cfg file is placed in the same directory as the path output by
+grub-mknetdir hereafter referred to as FWPATH. GRUB will search for its
+configuration files in order using the following rules where the appended
+value corresponds to a value on the client machine.
+
+@example
+@group
+@samp{(FWPATH)}/grub.cfg-@samp{(UUID OF NIC)}
+@samp{(FWPATH)}/grub.cfg-@samp{(MAC ADDRESS OF NIC)}
+@samp{(FWPATH)}/grub.cfg-@samp{(IPv4 OR IPv6 ADDRESS)}
+@samp{(FWPATH)}/grub.cfg
+@end group
+@end example
+
+The client will only attempt to look up an IPv6 address config once, however,
+it will try the IPv4 multiple times. The concrete example below shows what
+would happen under the IPv4 case.
+
+@example
+@group
+UUID: 7726a678-7fc0-4853-a4f6-c85ac36a120a
+MAC: 52:54:00:ec:33:81
+IPV4: 10.0.0.130 (0A000082)
+@end group
+@end example
+
+@example
+@group
+@samp{(FWPATH)}/grub.cfg-7726a678-7fc0-4853-a4f6-c85ac36a120a
+@samp{(FWPATH)}/grub.cfg-52-54-00-ec-33-81
+@samp{(FWPATH)}/grub.cfg-0A000082
+@samp{(FWPATH)}/grub.cfg-0A00008
+@samp{(FWPATH)}/grub.cfg-0A0000
+@samp{(FWPATH)}/grub.cfg-0A000
+@samp{(FWPATH)}/grub.cfg-0A00
+@samp{(FWPATH)}/grub.cfg-0A0
+@samp{(FWPATH)}/grub.cfg-0A
+@samp{(FWPATH)}/grub.cfg-0
+@samp{(FWPATH)}/grub.cfg
+@end group
+@end example
+
After GRUB has started, files on the TFTP server will be accessible via the
@samp{(tftp)} device.

View File

@ -0,0 +1,447 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Robert Marshall <rmarshall@redhat.com>
Date: Mon, 16 Mar 2015 14:14:19 -0400
Subject: [PATCH] Use Distribution Package Sort for grub2-mkconfig (#1124074)
Users reported that newly installed kernels on their systems installed
with grub-mkconfig would not appear on the grub boot list in order
starting with the most recent. Added an option for rpm-based systems to
use the rpm-sort library to sort kernels instead.
Resolves rhbz#1124074
Signed-off-by: Robert Marshall <rmarshall@redhat.com>
[pjones: fix --enable-rpm-sort configure option]
Signed-off-by: Peter Jones <pjones@redhat.com>
---
configure.ac | 29 +++++
Makefile.util.def | 16 +++
util/grub-rpm-sort.c | 281 ++++++++++++++++++++++++++++++++++++++++++++++
util/grub-mkconfig_lib.in | 11 +-
util/grub-rpm-sort.8 | 12 ++
5 files changed, 348 insertions(+), 1 deletion(-)
create mode 100644 util/grub-rpm-sort.c
create mode 100644 util/grub-rpm-sort.8
diff --git a/configure.ac b/configure.ac
index 8df400e0a8b..6927615819b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -69,6 +69,7 @@ grub_TRANSFORM([grub-mkrelpath])
grub_TRANSFORM([grub-mkrescue])
grub_TRANSFORM([grub-probe])
grub_TRANSFORM([grub-reboot])
+grub_TRANSFORM([grub-rpm-sort])
grub_TRANSFORM([grub-script-check])
grub_TRANSFORM([grub-set-default])
grub_TRANSFORM([grub-sparc64-setup])
@@ -92,6 +93,7 @@ grub_TRANSFORM([grub-mkrescue.1])
grub_TRANSFORM([grub-mkstandalone.3])
grub_TRANSFORM([grub-ofpathname.3])
grub_TRANSFORM([grub-probe.3])
+grub_TRANSFORM([grub-rpm-sort.8])
grub_TRANSFORM([grub-reboot.3])
grub_TRANSFORM([grub-render-label.3])
grub_TRANSFORM([grub-script-check.3])
@@ -1802,6 +1804,33 @@ fi
AC_SUBST([LIBDEVMAPPER])
+AC_ARG_ENABLE([rpm-sort],
+ [AS_HELP_STRING([--enable-rpm-sort],
+ [enable native rpm sorting of kernels in grub (default=guessed)])])
+if test x"$enable_rpm_sort" = xno ; then
+ rpm_sort_excuse="explicitly disabled"
+fi
+
+if test x"$rpm_sort_excuse" = x ; then
+ # Check for rpmlib header.
+ AC_CHECK_HEADER([rpm/rpmlib.h], [],
+ [rpm_sort_excuse="need rpm/rpmlib header"])
+fi
+
+if test x"$rpm_sort_excuse" = x ; then
+ # Check for rpm library.
+ AC_CHECK_LIB([rpm], [rpmvercmp], [],
+ [rpm_sort_excuse="rpmlib missing rpmvercmp"])
+fi
+
+if test x"$rpm_sort_excuse" = x ; then
+ LIBRPM="-lrpm";
+ AC_DEFINE([HAVE_RPM], [1],
+ [Define to 1 if you have the rpm library.])
+fi
+
+AC_SUBST([LIBRPM])
+
LIBGEOM=
if test x$host_kernel = xkfreebsd; then
AC_CHECK_LIB([geom], [geom_gettree], [],
diff --git a/Makefile.util.def b/Makefile.util.def
index 1f298d05f3d..843ce092b94 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -696,6 +696,22 @@ program = {
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
};
+program = {
+ name = grub-rpm-sort;
+ mansection = 8;
+ installdir = sbin;
+
+ common = grub-core/kern/emu/misc.c;
+ common = grub-core/kern/emu/argp_common.c;
+ common = grub-core/osdep/init.c;
+ common = util/misc.c;
+ common = util/grub-rpm-sort.c;
+
+ ldadd = libgrubkern.a;
+ ldadd = grub-core/lib/gnulib/libgnu.a;
+ ldadd = '$(LIBDEVMAPPER) $(LIBRPM)';
+};
+
script = {
name = grub-mkconfig;
common = util/grub-mkconfig.in;
diff --git a/util/grub-rpm-sort.c b/util/grub-rpm-sort.c
new file mode 100644
index 00000000000..f33bd1ed568
--- /dev/null
+++ b/util/grub-rpm-sort.c
@@ -0,0 +1,281 @@
+#include <config.h>
+#include <grub/types.h>
+#include <grub/util/misc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+#include <argp.h>
+#include <rpm/rpmlib.h>
+
+static size_t
+read_file (const char *input, char **ret)
+{
+ FILE *in;
+ size_t s;
+ size_t sz = 2048;
+ size_t offset = 0;
+ char *text;
+
+ if (!strcmp(input, "-"))
+ in = stdin;
+ else
+ in = grub_util_fopen(input, "r");
+
+ text = xmalloc (sz);
+
+ if (!in)
+ grub_util_error (_("cannot open `%s': %s"), input, strerror (errno));
+
+ while ((s = fread (text + offset, 1, sz - offset, in)) != 0)
+ {
+ offset += s;
+ if (sz - offset == 0)
+ {
+ sz += 2048;
+ text = xrealloc (text, sz);
+ }
+ }
+
+ text[offset] = '\0';
+ *ret = text;
+
+ if (in != stdin)
+ fclose(in);
+
+ return offset + 1;
+}
+
+/* returns name/version/release */
+/* NULL string pointer returned if nothing found */
+static void
+split_package_string (char *package_string, char **name,
+ char **version, char **release)
+{
+ char *package_version, *package_release;
+
+ /* Release */
+ package_release = strrchr (package_string, '-');
+
+ if (package_release != NULL)
+ *package_release++ = '\0';
+
+ *release = package_release;
+
+ /* Version */
+ package_version = strrchr(package_string, '-');
+
+ if (package_version != NULL)
+ *package_version++ = '\0';
+
+ *version = package_version;
+ /* Name */
+ *name = package_string;
+
+ /* Bubble up non-null values from release to name */
+ if (*name == NULL)
+ {
+ *name = (*version == NULL ? *release : *version);
+ *version = *release;
+ *release = NULL;
+ }
+ if (*version == NULL)
+ {
+ *version = *release;
+ *release = NULL;
+ }
+}
+
+/*
+ * package name-version-release comparator for qsort
+ * expects p, q which are pointers to character strings (char *)
+ * which will not be altered in this function
+ */
+static int
+package_version_compare (const void *p, const void *q)
+{
+ char *local_p, *local_q;
+ char *lhs_name, *lhs_version, *lhs_release;
+ char *rhs_name, *rhs_version, *rhs_release;
+ int vercmpflag = 0;
+
+ local_p = alloca (strlen (*(char * const *)p) + 1);
+ local_q = alloca (strlen (*(char * const *)q) + 1);
+
+ /* make sure these allocated */
+ assert (local_p);
+ assert (local_q);
+
+ strcpy (local_p, *(char * const *)p);
+ strcpy (local_q, *(char * const *)q);
+
+ split_package_string (local_p, &lhs_name, &lhs_version, &lhs_release);
+ split_package_string (local_q, &rhs_name, &rhs_version, &rhs_release);
+
+ /* Check Name and return if unequal */
+ vercmpflag = rpmvercmp ((lhs_name == NULL ? "" : lhs_name),
+ (rhs_name == NULL ? "" : rhs_name));
+ if (vercmpflag != 0)
+ return vercmpflag;
+
+ /* Check version and return if unequal */
+ vercmpflag = rpmvercmp ((lhs_version == NULL ? "" : lhs_version),
+ (rhs_version == NULL ? "" : rhs_version));
+ if (vercmpflag != 0)
+ return vercmpflag;
+
+ /* Check release and return the version compare value */
+ vercmpflag = rpmvercmp ((lhs_release == NULL ? "" : lhs_release),
+ (rhs_release == NULL ? "" : rhs_release));
+
+ return vercmpflag;
+}
+
+static void
+add_input (const char *filename, char ***package_names, size_t *n_package_names)
+{
+ char *orig_input_buffer = NULL;
+ char *input_buffer;
+ char *position_of_newline;
+ char **names = *package_names;
+ char **new_names = NULL;
+ size_t n_names = *n_package_names;
+
+ if (!*package_names)
+ new_names = names = xmalloc (sizeof (char *) * 2);
+
+ if (read_file (filename, &orig_input_buffer) < 2)
+ {
+ if (new_names)
+ free (new_names);
+ if (orig_input_buffer)
+ free (orig_input_buffer);
+ return;
+ }
+
+ input_buffer = orig_input_buffer;
+ while (input_buffer && *input_buffer &&
+ (position_of_newline = strchrnul (input_buffer, '\n')))
+ {
+ size_t sz = position_of_newline - input_buffer;
+ char *new;
+
+ if (sz == 0)
+ {
+ input_buffer = position_of_newline + 1;
+ continue;
+ }
+
+ new = xmalloc (sz+1);
+ strncpy (new, input_buffer, sz);
+ new[sz] = '\0';
+
+ names = xrealloc (names, sizeof (char *) * (n_names + 1));
+ names[n_names] = new;
+ n_names++;
+
+ /* move buffer ahead to next line */
+ input_buffer = position_of_newline + 1;
+ if (*position_of_newline == '\0')
+ input_buffer = NULL;
+ }
+
+ free (orig_input_buffer);
+
+ *package_names = names;
+ *n_package_names = n_names;
+}
+
+static char *
+help_filter (int key, const char *text, void *input __attribute__ ((unused)))
+{
+ return (char *)text;
+}
+
+static struct argp_option options[] = {
+ { 0, }
+};
+
+struct arguments
+{
+ size_t ninputs;
+ size_t input_max;
+ char **inputs;
+};
+
+static error_t
+argp_parser (int key, char *arg, struct argp_state *state)
+{
+ struct arguments *arguments = state->input;
+ switch (key)
+ {
+ case ARGP_KEY_ARG:
+ assert (arguments->ninputs < arguments->input_max);
+ arguments->inputs[arguments->ninputs++] = xstrdup (arg);
+ break;
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+ return 0;
+}
+
+static struct argp argp = {
+ options, argp_parser, N_("[INPUT_FILES]"),
+ N_("Sort a list of strings in RPM version sort order."),
+ NULL, help_filter, NULL
+};
+
+int
+main (int argc, char *argv[])
+{
+ struct arguments arguments;
+ char **package_names = NULL;
+ size_t n_package_names = 0;
+ int i;
+
+ grub_util_host_init (&argc, &argv);
+
+ memset (&arguments, 0, sizeof (struct arguments));
+ arguments.input_max = argc+1;
+ arguments.inputs = xmalloc ((arguments.input_max + 1)
+ * sizeof (arguments.inputs[0]));
+ memset (arguments.inputs, 0, (arguments.input_max + 1)
+ * sizeof (arguments.inputs[0]));
+
+ /* Parse our arguments */
+ if (argp_parse (&argp, argc, argv, 0, 0, &arguments) != 0)
+ grub_util_error ("%s", _("Error in parsing command line arguments\n"));
+
+ /* If there's no inputs in argv, add one for stdin */
+ if (!arguments.ninputs)
+ {
+ arguments.ninputs = 1;
+ arguments.inputs[0] = xmalloc (2);
+ strcpy(arguments.inputs[0], "-");
+ }
+
+ for (i = 0; i < arguments.ninputs; i++)
+ add_input(arguments.inputs[i], &package_names, &n_package_names);
+
+ if (package_names == NULL || n_package_names < 1)
+ grub_util_error ("%s", _("Invalid input\n"));
+
+ qsort (package_names, n_package_names, sizeof (char *),
+ package_version_compare);
+
+ /* send sorted list to stdout */
+ for (i = 0; i < n_package_names; i++)
+ {
+ fprintf (stdout, "%s\n", package_names[i]);
+ free (package_names[i]);
+ }
+
+ free (package_names);
+ for (i = 0; i < arguments.ninputs; i++)
+ free (arguments.inputs[i]);
+
+ free (arguments.inputs);
+
+ return 0;
+}
diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in
index 1a4a57898f9..113a41f9409 100644
--- a/util/grub-mkconfig_lib.in
+++ b/util/grub-mkconfig_lib.in
@@ -33,6 +33,9 @@ fi
if test "x$grub_mkrelpath" = x; then
grub_mkrelpath="${bindir}/@grub_mkrelpath@"
fi
+if test "x$grub_rpm_sort" = x; then
+ grub_rpm_sort="${sbindir}/@grub_rpm_sort@"
+fi
if which gettext >/dev/null 2>/dev/null; then
:
@@ -214,6 +217,12 @@ version_sort ()
esac
}
+if [ "x$grub_rpm_sort" != x -a -x "$grub_rpm_sort" ]; then
+ kernel_sort="$grub_rpm_sort"
+else
+ kernel_sort=version_sort
+fi
+
version_test_numeric ()
{
version_test_numeric_a="$1"
@@ -230,7 +239,7 @@ version_test_numeric ()
version_test_numeric_a="$version_test_numeric_b"
version_test_numeric_b="$version_test_numeric_c"
fi
- if (echo "$version_test_numeric_a" ; echo "$version_test_numeric_b") | version_sort | head -n 1 | grep -qx "$version_test_numeric_b" ; then
+ if (echo "$version_test_numeric_a" ; echo "$version_test_numeric_b") | "$kernel_sort" | head -n 1 | grep -qx "$version_test_numeric_b" ; then
return 0
else
return 1
diff --git a/util/grub-rpm-sort.8 b/util/grub-rpm-sort.8
new file mode 100644
index 00000000000..8ce21488448
--- /dev/null
+++ b/util/grub-rpm-sort.8
@@ -0,0 +1,12 @@
+.TH GRUB-RPM-SORT 8 "Wed Feb 26 2014"
+.SH NAME
+\fBgrub-rpm-sort\fR \(em Sort input according to RPM version compare.
+
+.SH SYNOPSIS
+\fBgrub-rpm-sort\fR [OPTIONS].
+
+.SH DESCRIPTION
+You should not normally run this program directly. Use grub-mkconfig instead.
+
+.SH SEE ALSO
+.BR "info grub"

View File

@ -0,0 +1,36 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Tue, 30 Jun 2015 15:50:41 -0400
Subject: [PATCH] Handle rssd storage devices.
Resolves: rhbz#1087962
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/osdep/linux/getroot.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c
index 90d92d3ad5c..6d9f4e5faa2 100644
--- a/grub-core/osdep/linux/getroot.c
+++ b/grub-core/osdep/linux/getroot.c
@@ -921,6 +921,19 @@ grub_util_part_to_disk (const char *os_dev, struct stat *st,
return path;
}
+ /* If this is an rssd device. */
+ if ((strncmp ("rssd", p, 4) == 0) && p[4] >= 'a' && p[4] <= 'z')
+ {
+ char *pp = p + 4;
+ while (*pp >= 'a' && *pp <= 'z')
+ pp++;
+ if (*pp)
+ *is_part = 1;
+ /* /dev/rssd[a-z]+[0-9]* */
+ *pp = '\0';
+ return path;
+ }
+
/* If this is a loop device */
if ((strncmp ("loop", p, 4) == 0) && p[4] >= '0' && p[4] <= '9')
{

View File

@ -0,0 +1,69 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Tue, 28 Apr 2015 11:15:03 -0400
Subject: [PATCH] Make grub2-mkconfig construct titles that look like the ones
we want elsewhere.
Resolves: rhbz#1215839
Signed-off-by: Peter Jones <pjones@redhat.com>
---
util/grub.d/10_linux.in | 34 +++++++++++++++++++++++++++-------
1 file changed, 27 insertions(+), 7 deletions(-)
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index d12d2d784dc..12a20c9ad73 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -78,6 +78,32 @@ case x"$GRUB_FS" in
;;
esac
+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=
linux_entry ()
@@ -91,17 +117,11 @@ linux_entry ()
boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")"
fi
if [ x$type != xsimple ] ; then
- case $type in
- recovery)
- title="$(gettext_printf "%s, with Linux %s (recovery mode)" "${os}" "${version}")" ;;
- *)
- title="$(gettext_printf "%s, with Linux %s" "${os}" "${version}")" ;;
- esac
+ title=$(mktitle "$type" "$version")
if [ x"$title" = x"$GRUB_ACTUAL_DEFAULT" ] || [ x"Previous Linux versions>$title" = x"$GRUB_ACTUAL_DEFAULT" ]; then
replacement_title="$(echo "Advanced options for ${OS}" | sed 's,>,>>,g')>$(echo "$title" | sed 's,>,>>,g')"
quoted="$(echo "$GRUB_ACTUAL_DEFAULT" | grub_quote)"
title_correction_code="${title_correction_code}if [ \"x\$default\" = '$quoted' ]; then default='$(echo "$replacement_title" | grub_quote)'; fi;"
- grub_warn "$(gettext_printf "Please don't use old title \`%s' for GRUB_DEFAULT, use \`%s' (for versions before 2.00) or \`%s' (for 2.00 or later)" "$GRUB_ACTUAL_DEFAULT" "$replacement_title" "gnulinux-advanced-$boot_device_id>gnulinux-$version-$type-$boot_device_id")"
fi
echo "menuentry '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-$version-$type-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
else

View File

@ -0,0 +1,269 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Robert Marshall <rmarshall@redhat.com>
Date: Thu, 25 Jun 2015 11:13:11 -0400
Subject: [PATCH] Add friendly grub2 password config tool (#985962)
Provided a tool for users to reset the grub2 root user password
without having to alter the grub.cfg. The hashed password now
lives in a root-only-readable configuration file.
Resolves: rhbz#985962
Signed-off-by: Robert Marshall <rmarshall@redhat.com>
[pjones: fix the efidir in grub-setpassword and rename tool]
Signed-off-by: Peter Jones <pjones@redhat.com>
[luto: fix grub-setpassword -o's output path]
Andy Lutomirski <luto@kernel.org>
---
configure.ac | 1 +
Makefile.util.def | 13 +++++
util/grub-mkconfig.in | 2 +
util/grub-set-password.8 | 28 ++++++++++
util/grub-set-password.in | 128 ++++++++++++++++++++++++++++++++++++++++++++++
util/grub.d/01_users.in | 11 ++++
6 files changed, 183 insertions(+)
create mode 100644 util/grub-set-password.8
create mode 100644 util/grub-set-password.in
create mode 100644 util/grub.d/01_users.in
diff --git a/configure.ac b/configure.ac
index 6927615819b..68501662e8d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -69,6 +69,7 @@ grub_TRANSFORM([grub-mkrelpath])
grub_TRANSFORM([grub-mkrescue])
grub_TRANSFORM([grub-probe])
grub_TRANSFORM([grub-reboot])
+grub_TRANSFORM([grub-set-password])
grub_TRANSFORM([grub-rpm-sort])
grub_TRANSFORM([grub-script-check])
grub_TRANSFORM([grub-set-default])
diff --git a/Makefile.util.def b/Makefile.util.def
index 843ce092b94..e50436a4987 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -451,6 +451,12 @@ script = {
installdir = grubconf;
};
+script = {
+ name = '01_users';
+ common = util/grub.d/01_users.in;
+ installdir = grubconf;
+};
+
script = {
name = '10_windows';
common = util/grub.d/10_windows.in;
@@ -733,6 +739,13 @@ script = {
installdir = sbin;
};
+script = {
+ name = grub-set-password;
+ common = util/grub-set-password.in;
+ mansection = 8;
+ installdir = sbin;
+};
+
script = {
name = grub-mkconfig_lib;
common = util/grub-mkconfig_lib.in;
diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
index c645351dd2a..4e7a875309e 100644
--- a/util/grub-mkconfig.in
+++ b/util/grub-mkconfig.in
@@ -282,6 +282,8 @@ for i in "${grub_mkconfig_dir}"/* ; do
*~) ;;
# emacsen autosave files. FIXME: support other editors
*/\#*\#) ;;
+ # rpm config files of yore.
+ *.rpmsave|*.rpmnew|*.rpmorig) ;;
*)
if grub_file_is_not_garbage "$i" && test -x "$i" ; then
echo
diff --git a/util/grub-set-password.8 b/util/grub-set-password.8
new file mode 100644
index 00000000000..9646546e43d
--- /dev/null
+++ b/util/grub-set-password.8
@@ -0,0 +1,28 @@
+.TH GRUB-SET-PASSWORD 3 "Thu Jun 25 2015"
+.SH NAME
+\fBgrub-set-password\fR \(em Generate the user.cfg file containing the hashed grub bootloader password.
+
+.SH SYNOPSIS
+\fBgrub-set-password\fR [OPTION]
+
+.SH DESCRIPTION
+\fBgrub-set-password\fR outputs the user.cfg file which contains the hashed GRUB bootloader password. This utility only supports configurations where there is a single root user.
+
+The file has the format:
+GRUB2_PASSWORD=<\fIhashed password\fR>.
+
+.SH OPTIONS
+.TP
+-h, --help
+Display program usage and exit.
+.TP
+-v, --version
+Display the current version.
+.TP
+-o, --output=<\fIDIRECTORY\fR>
+Choose the file path to which user.cfg will be written.
+
+.SH SEE ALSO
+.BR "info grub"
+
+.BR "info grub2-mkpasswd-pbkdf2"
diff --git a/util/grub-set-password.in b/util/grub-set-password.in
new file mode 100644
index 00000000000..5ebf50576d6
--- /dev/null
+++ b/util/grub-set-password.in
@@ -0,0 +1,128 @@
+#!/bin/sh -e
+
+EFIDIR=$(grep ^ID= /etc/os-release | sed -e 's/^ID=//' -e 's/rhel/redhat/')
+if [ -d /sys/firmware/efi/efivars/ ]; then
+ grubdir=`echo "/@bootdirname@/efi/EFI/${EFIDIR}/" | sed 's,//*,/,g'`
+else
+ grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'`
+fi
+
+PACKAGE_VERSION="@PACKAGE_VERSION@"
+PACKAGE_NAME="@PACKAGE_NAME@"
+self=`basename $0`
+bindir="@bindir@"
+grub_mkpasswd="${bindir}/@grub_mkpasswd_pbkdf2@"
+
+# Usage: usage
+# Print the usage.
+usage () {
+ cat <<EOF
+Usage: $0 [OPTION]
+$0 prompts the user to set a password on the grub bootloader. The password
+is written to a file named user.cfg which lives in the GRUB directory
+located by default at ${grubdir}.
+
+ -h, --help print this message and exit
+ -v, --version print the version information and exit
+ -o, --output_path <DIRECTORY> put user.cfg in a user-selected directory
+
+Report bugs at https://bugzilla.redhat.com.
+EOF
+}
+
+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
+}
+
+# Ensure that it's the root user running this script
+if [ "${EUID}" -ne 0 ]; then
+ echo "The grub bootloader password may only be set by root."
+ usage
+ exit 2
+fi
+
+# 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 ;;
+ -o | --output)
+ OUTPUT_PATH=`argument $option "$@"`; shift ;;
+ --output=*)
+ OUTPUT_PATH=`echo "$option" | sed 's/--output=//'` ;;
+ -o=*)
+ OUTPUT_PATH=`echo "$option" | sed 's/-o=//'` ;;
+ esac
+done
+
+# set user input or default path for user.cfg file
+if [ -z "${OUTPUT_PATH}" ]; then
+ OUTPUT_PATH="${grubdir}"
+fi
+
+if [ ! -d "${OUTPUT_PATH}" ]; then
+ echo "${OUTPUT_PATH} does not exist."
+ usage
+ exit 2;
+fi
+
+ttyopt=$(stty -g)
+fixtty() {
+ stty ${ttyopt}
+}
+
+trap fixtty EXIT
+stty -echo
+
+# prompt & confirm new grub2 root user password
+echo -n "Enter password: "
+read PASSWORD
+echo
+echo -n "Confirm password: "
+read PASSWORD_CONFIRM
+echo
+stty ${ttyopt}
+
+getpass() {
+ local P0
+ local P1
+ P0="$1" && shift
+ P1="$1" && shift
+
+ ( echo ${P0} ; echo ${P1} ) | \
+ LC_ALL=C ${grub_mkpasswd} | \
+ grep -v '[eE]nter password:' | \
+ sed -e "s/PBKDF2 hash of your password is //"
+}
+
+MYPASS="$(getpass "${PASSWORD}" "${PASSWORD_CONFIRM}")"
+if [ -z "${MYPASS}" ]; then
+ echo "${self}: error: empty password" 1>&2
+ exit 1
+fi
+
+# on the ESP, these will fail to set the permissions, but it's okay because
+# the directory is protected.
+install -m 0600 /dev/null "${OUTPUT_PATH}/user.cfg" 2>/dev/null || :
+chmod 0600 "${OUTPUT_PATH}/user.cfg" 2>/dev/null || :
+echo "GRUB2_PASSWORD=${MYPASS}" > "${OUTPUT_PATH}/user.cfg"
+
+if ! grep -q "^### BEGIN /etc/grub.d/01_users ###$" "${OUTPUT_PATH}/grub.cfg"; then
+ echo "WARNING: The current configuration lacks password support!"
+ echo "Update your configuration with @grub_mkconfig@ to support this feature."
+fi
diff --git a/util/grub.d/01_users.in b/util/grub.d/01_users.in
new file mode 100644
index 00000000000..db2f44bfb78
--- /dev/null
+++ b/util/grub.d/01_users.in
@@ -0,0 +1,11 @@
+#!/bin/sh -e
+cat << EOF
+if [ -f \${prefix}/user.cfg ]; then
+ source \${prefix}/user.cfg
+ if [ -n "\${GRUB2_PASSWORD}" ]; then
+ set superusers="root"
+ export superusers
+ password_pbkdf2 root \${GRUB2_PASSWORD}
+ fi
+fi
+EOF

View File

@ -0,0 +1,87 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Josef Bacik <jbacik@fb.com>
Date: Wed, 12 Aug 2015 08:57:55 -0700
Subject: [PATCH] tcp: add window scaling support
Sometimes we have to provision boxes across regions, such as California to
Sweden. The http server has a 10 minute timeout, so if we can't get our 250mb
image transferred fast enough our provisioning fails, which is not ideal. So
add tcp window scaling on open connections and set the window size to 1mb. With
this change we're able to get higher sustained transfers between regions and can
transfer our image in well below 10 minutes. Without this patch we'd time out
every time halfway through the transfer. Thanks,
Signed-off-by: Josef Bacik <jbacik@fb.com>
---
grub-core/net/tcp.c | 42 +++++++++++++++++++++++++++++-------------
1 file changed, 29 insertions(+), 13 deletions(-)
diff --git a/grub-core/net/tcp.c b/grub-core/net/tcp.c
index e8ad34b84d4..7d4b822626d 100644
--- a/grub-core/net/tcp.c
+++ b/grub-core/net/tcp.c
@@ -106,6 +106,18 @@ struct tcphdr
grub_uint16_t urgent;
} GRUB_PACKED;
+struct tcp_scale_opt {
+ grub_uint8_t kind;
+ grub_uint8_t length;
+ grub_uint8_t scale;
+} GRUB_PACKED;
+
+struct tcp_synhdr {
+ struct tcphdr tcphdr;
+ struct tcp_scale_opt scale_opt;
+ grub_uint8_t padding;
+};
+
struct tcp_pseudohdr
{
grub_uint32_t src;
@@ -566,7 +578,7 @@ grub_net_tcp_open (char *server,
grub_net_tcp_socket_t socket;
static grub_uint16_t in_port = 21550;
struct grub_net_buff *nb;
- struct tcphdr *tcph;
+ struct tcp_synhdr *tcph;
int i;
grub_uint8_t *nbd;
grub_net_link_level_address_t ll_target_addr;
@@ -635,20 +647,24 @@ grub_net_tcp_open (char *server,
}
tcph = (void *) nb->data;
+ grub_memset(tcph, 0, sizeof (*tcph));
socket->my_start_seq = grub_get_time_ms ();
socket->my_cur_seq = socket->my_start_seq + 1;
- socket->my_window = 8192;
- tcph->seqnr = grub_cpu_to_be32 (socket->my_start_seq);
- tcph->ack = grub_cpu_to_be32_compile_time (0);
- tcph->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_SYN);
- tcph->window = grub_cpu_to_be16 (socket->my_window);
- tcph->urgent = 0;
- tcph->src = grub_cpu_to_be16 (socket->in_port);
- tcph->dst = grub_cpu_to_be16 (socket->out_port);
- tcph->checksum = 0;
- tcph->checksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_TCP,
- &socket->inf->address,
- &socket->out_nla);
+ socket->my_window = 32768;
+ tcph->tcphdr.seqnr = grub_cpu_to_be32 (socket->my_start_seq);
+ tcph->tcphdr.ack = grub_cpu_to_be32_compile_time (0);
+ tcph->tcphdr.flags = grub_cpu_to_be16_compile_time ((6 << 12) | TCP_SYN);
+ tcph->tcphdr.window = grub_cpu_to_be16 (socket->my_window);
+ tcph->tcphdr.urgent = 0;
+ tcph->tcphdr.src = grub_cpu_to_be16 (socket->in_port);
+ tcph->tcphdr.dst = grub_cpu_to_be16 (socket->out_port);
+ tcph->tcphdr.checksum = 0;
+ tcph->scale_opt.kind = 3;
+ tcph->scale_opt.length = 3;
+ tcph->scale_opt.scale = 5;
+ tcph->tcphdr.checksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_TCP,
+ &socket->inf->address,
+ &socket->out_nla);
tcp_socket_register (socket);

View File

@ -0,0 +1,44 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Hector Marco-Gisbert <hecmargi@upv.es>
Date: Fri, 13 Nov 2015 16:21:09 +0100
Subject: [PATCH] Fix security issue when reading username and password
This patch fixes two integer underflows at:
* grub-core/lib/crypto.c
* grub-core/normal/auth.c
Resolves: CVE-2015-8370
Signed-off-by: Hector Marco-Gisbert <hecmargi@upv.es>
Signed-off-by: Ismael Ripoll-Ripoll <iripoll@disca.upv.es>
---
grub-core/lib/crypto.c | 2 +-
grub-core/normal/auth.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/grub-core/lib/crypto.c b/grub-core/lib/crypto.c
index ca334d5a40e..e6c78d16d39 100644
--- a/grub-core/lib/crypto.c
+++ b/grub-core/lib/crypto.c
@@ -468,7 +468,7 @@ grub_password_get (char buf[], unsigned buf_size)
break;
}
- if (key == '\b')
+ if (key == '\b' && cur_len)
{
if (cur_len)
cur_len--;
diff --git a/grub-core/normal/auth.c b/grub-core/normal/auth.c
index 6be678c0de1..c35ce972473 100644
--- a/grub-core/normal/auth.c
+++ b/grub-core/normal/auth.c
@@ -172,7 +172,7 @@ grub_username_get (char buf[], unsigned buf_size)
break;
}
- if (key == GRUB_TERM_BACKSPACE)
+ if (key == GRUB_TERM_BACKSPACE && cur_len)
{
if (cur_len)
{

1021
0063-Add-a-url-parser.patch Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,661 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Tue, 9 Jul 2019 11:47:37 +0200
Subject: [PATCH] efinet and bootp: add support for dhcpv6
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/net/bootp.c | 174 +++++++++++++++++++++++++++++++++++++
grub-core/net/drivers/efi/efinet.c | 54 ++++++++++--
grub-core/net/net.c | 72 +++++++++++++++
grub-core/net/tftp.c | 4 +
include/grub/efi/api.h | 129 +++++++++++++++++++++++++--
include/grub/net.h | 60 +++++++++++++
6 files changed, 479 insertions(+), 14 deletions(-)
diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
index 0e6e41a1699..8c969595a7b 100644
--- a/grub-core/net/bootp.c
+++ b/grub-core/net/bootp.c
@@ -23,6 +23,7 @@
#include <grub/net/ip.h>
#include <grub/net/netbuff.h>
#include <grub/net/udp.h>
+#include <grub/net/url.h>
#include <grub/datetime.h>
struct grub_dhcp_discover_options
@@ -935,6 +936,179 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)),
static grub_command_t cmd_getdhcp, cmd_bootp, cmd_dhcp;
+struct grub_net_network_level_interface *
+grub_net_configure_by_dhcpv6_ack (const char *name,
+ struct grub_net_card *card,
+ grub_net_interface_flags_t flags
+ __attribute__((__unused__)),
+ const grub_net_link_level_address_t *hwaddr,
+ const struct grub_net_dhcpv6_packet *packet,
+ int is_def, char **device, char **path)
+{
+ struct grub_net_network_level_interface *inter = NULL;
+ struct grub_net_network_level_address addr;
+ int mask = -1;
+
+ if (!device || !path)
+ return NULL;
+
+ *device = 0;
+ *path = 0;
+
+ grub_dprintf ("net", "mac address is %02x:%02x:%02x:%02x:%02x:%02x\n",
+ hwaddr->mac[0], hwaddr->mac[1], hwaddr->mac[2],
+ hwaddr->mac[3], hwaddr->mac[4], hwaddr->mac[5]);
+
+ if (is_def)
+ grub_net_default_server = 0;
+
+ if (is_def && !grub_net_default_server && packet)
+ {
+ const grub_uint8_t *options = packet->dhcp_options;
+ unsigned int option_max = 1024 - OFFSET_OF (dhcp_options, packet);
+ unsigned int i;
+
+ for (i = 0; i < option_max - sizeof (grub_net_dhcpv6_option_t); )
+ {
+ grub_uint16_t num, len;
+ grub_net_dhcpv6_option_t *opt =
+ (grub_net_dhcpv6_option_t *)(options + i);
+
+ num = grub_be_to_cpu16(opt->option_num);
+ len = grub_be_to_cpu16(opt->option_len);
+
+ grub_dprintf ("net", "got dhcpv6 option %d len %d\n", num, len);
+
+ if (len == 0)
+ break;
+
+ if (len + i > 1024)
+ break;
+
+ if (num == GRUB_NET_DHCP6_BOOTFILE_URL)
+ {
+ char *scheme, *userinfo, *host, *file;
+ char *tmp;
+ int hostlen;
+ int port;
+ int rc = extract_url_info ((const char *)opt->option_data,
+ (grub_size_t)len,
+ &scheme, &userinfo, &host, &port,
+ &file);
+ if (rc < 0)
+ continue;
+
+ /* right now this only handles tftp. */
+ if (grub_strcmp("tftp", scheme))
+ {
+ grub_free (scheme);
+ grub_free (userinfo);
+ grub_free (host);
+ grub_free (file);
+ continue;
+ }
+ grub_free (userinfo);
+
+ hostlen = grub_strlen (host);
+ if (hostlen > 2 && host[0] == '[' && host[hostlen-1] == ']')
+ {
+ tmp = host+1;
+ host[hostlen-1] = '\0';
+ }
+ else
+ tmp = host;
+
+ *device = grub_xasprintf ("%s,%s", scheme, tmp);
+ grub_free (scheme);
+ grub_free (host);
+
+ if (file && *file)
+ {
+ tmp = grub_strrchr (file, '/');
+ if (tmp)
+ *(tmp+1) = '\0';
+ else
+ file[0] = '\0';
+ }
+ else if (!file)
+ file = grub_strdup ("");
+
+ if (file[0] == '/')
+ {
+ *path = grub_strdup (file+1);
+ grub_free (file);
+ }
+ else
+ *path = file;
+ }
+ else if (num == GRUB_NET_DHCP6_IA_NA)
+ {
+ const grub_net_dhcpv6_option_t *ia_na_opt;
+ const grub_net_dhcpv6_opt_ia_na_t *ia_na =
+ (const grub_net_dhcpv6_opt_ia_na_t *)opt;
+ unsigned int left = len - OFFSET_OF (options, ia_na);
+ unsigned int j;
+
+ if ((grub_uint8_t *)ia_na + left >
+ (grub_uint8_t *)options + option_max)
+ left -= ((grub_uint8_t *)ia_na + left)
+ - ((grub_uint8_t *)options + option_max);
+
+ if (len < OFFSET_OF (option_data, opt)
+ + sizeof (grub_net_dhcpv6_option_t))
+ {
+ grub_dprintf ("net",
+ "found dhcpv6 ia_na option with no address\n");
+ continue;
+ }
+
+ for (j = 0; left > sizeof (grub_net_dhcpv6_option_t); )
+ {
+ ia_na_opt = (const grub_net_dhcpv6_option_t *)
+ (ia_na->options + j);
+ grub_uint16_t ia_na_opt_num, ia_na_opt_len;
+
+ ia_na_opt_num = grub_be_to_cpu16 (ia_na_opt->option_num);
+ ia_na_opt_len = grub_be_to_cpu16 (ia_na_opt->option_len);
+ if (ia_na_opt_len == 0)
+ break;
+ if (j + ia_na_opt_len > left)
+ break;
+ if (ia_na_opt_num == GRUB_NET_DHCP6_IA_ADDRESS)
+ {
+ const grub_net_dhcpv6_opt_ia_address_t *ia_addr;
+
+ ia_addr = (const grub_net_dhcpv6_opt_ia_address_t *)
+ ia_na_opt;
+ addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
+ grub_memcpy(addr.ipv6, ia_addr->ipv6_address,
+ sizeof (ia_addr->ipv6_address));
+ inter = grub_net_add_addr (name, card, &addr, hwaddr, 0);
+ }
+
+ j += ia_na_opt_len;
+ left -= ia_na_opt_len;
+ }
+ }
+
+ i += len + 4;
+ }
+
+ grub_print_error ();
+ }
+
+ if (is_def)
+ {
+ grub_env_set ("net_default_interface", name);
+ grub_env_export ("net_default_interface");
+ }
+
+ if (inter)
+ grub_net_add_ipv6_local (inter, mask);
+ return inter;
+}
+
+
void
grub_bootp_init (void)
{
diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
index 5388f952ba9..a57189e8bb3 100644
--- a/grub-core/net/drivers/efi/efinet.c
+++ b/grub-core/net/drivers/efi/efinet.c
@@ -18,11 +18,15 @@
#include <grub/net/netbuff.h>
#include <grub/dl.h>
+#include <grub/env.h>
#include <grub/net.h>
+#include <grub/net/url.h>
#include <grub/time.h>
#include <grub/efi/api.h>
#include <grub/efi/efi.h>
#include <grub/i18n.h>
+#include <grub/lib/hexdump.h>
+#include <grub/types.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -329,7 +333,7 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
char **path)
{
struct grub_net_card *card;
- grub_efi_device_path_t *dp;
+ grub_efi_device_path_t *dp, *ldp = NULL;
dp = grub_efi_get_device_path (hnd);
if (! dp)
@@ -340,14 +344,19 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
grub_efi_device_path_t *cdp;
struct grub_efi_pxe *pxe;
struct grub_efi_pxe_mode *pxe_mode;
+
if (card->driver != &efidriver)
continue;
+
cdp = grub_efi_get_device_path (card->efi_handle);
if (! cdp)
continue;
+
+ ldp = grub_efi_find_last_device_path (dp);
+
if (grub_efi_compare_device_paths (dp, cdp) != 0)
{
- grub_efi_device_path_t *ldp, *dup_dp, *dup_ldp;
+ grub_efi_device_path_t *dup_dp, *dup_ldp;
int match;
/* EDK2 UEFI PXE driver creates pseudo devices with type IPv4/IPv6
@@ -356,7 +365,6 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
devices. We skip them when enumerating cards, so here we need to
find matching MAC device.
*/
- 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))
@@ -373,16 +381,46 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
if (!match)
continue;
}
+
pxe = grub_efi_open_protocol (hnd, &pxe_io_guid,
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (! pxe)
continue;
+
pxe_mode = pxe->mode;
- grub_net_configure_by_dhcp_ack (card->name, card, 0,
- (struct grub_net_bootp_packet *)
- &pxe_mode->dhcp_ack,
- sizeof (pxe_mode->dhcp_ack),
- 1, device, path);
+ if (pxe_mode->using_ipv6)
+ {
+ grub_net_link_level_address_t hwaddr;
+ struct grub_net_network_level_interface *intf;
+
+ grub_dprintf ("efinet", "using ipv6 and dhcpv6\n");
+ grub_dprintf ("efinet", "dhcp_ack_received: %s%s\n",
+ pxe_mode->dhcp_ack_received ? "yes" : "no",
+ pxe_mode->dhcp_ack_received ? "" : " cannot continue");
+ if (!pxe_mode->dhcp_ack_received)
+ continue;
+
+ hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
+ grub_memcpy (hwaddr.mac,
+ card->efi_net->mode->current_address,
+ sizeof (hwaddr.mac));
+
+ intf = grub_net_configure_by_dhcpv6_ack (card->name, card, 0, &hwaddr,
+ (const struct grub_net_dhcpv6_packet *)&pxe_mode->dhcp_ack.dhcpv6,
+ 1, device, path);
+ if (intf && device && path)
+ grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path);
+ }
+ else
+ {
+ grub_dprintf ("efinet", "using ipv4 and dhcp\n");
+ grub_net_configure_by_dhcp_ack (card->name, card, 0,
+ (struct grub_net_bootp_packet *)
+ &pxe_mode->dhcp_ack,
+ sizeof (pxe_mode->dhcp_ack),
+ 1, device, path);
+ grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path);
+ }
return;
}
}
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
index 4b7972b8e7e..f24f1fd63f6 100644
--- a/grub-core/net/net.c
+++ b/grub-core/net/net.c
@@ -955,6 +955,78 @@ grub_net_network_level_interface_register (struct grub_net_network_level_interfa
grub_net_network_level_interfaces = inter;
}
+int
+grub_ipv6_get_masksize (grub_uint16_t be_mask[8])
+{
+ grub_uint8_t *mask;
+ grub_uint16_t mask16[8];
+ int x, y;
+ int ret = 128;
+
+ grub_memcpy (mask16, be_mask, sizeof (mask16));
+ for (x = 0; x < 8; x++)
+ mask16[x] = grub_be_to_cpu16 (mask16[x]);
+
+ mask = (grub_uint8_t *)mask16;
+
+ for (x = 15; x >= 0; x--)
+ {
+ grub_uint8_t octet = mask[x];
+ if (!octet)
+ {
+ ret -= 8;
+ continue;
+ }
+ for (y = 0; y < 8; y++)
+ {
+ if (octet & (1 << y))
+ break;
+ else
+ ret--;
+ }
+ break;
+ }
+
+ return ret;
+}
+
+grub_err_t
+grub_net_add_ipv6_local (struct grub_net_network_level_interface *inter,
+ int mask)
+{
+ struct grub_net_route *route;
+
+ if (inter->address.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6)
+ return 0;
+
+ if (mask == -1)
+ mask = grub_ipv6_get_masksize ((grub_uint16_t *)inter->address.ipv6);
+
+ if (mask == -1)
+ return 0;
+
+ route = grub_zalloc (sizeof (*route));
+ if (!route)
+ return grub_errno;
+
+ route->name = grub_xasprintf ("%s:local", inter->name);
+ if (!route->name)
+ {
+ grub_free (route);
+ return grub_errno;
+ }
+
+ route->target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
+ grub_memcpy (route->target.ipv6.base, inter->address.ipv6,
+ sizeof (inter->address.ipv6));
+ route->target.ipv6.masksize = mask;
+ route->is_gateway = 0;
+ route->interface = inter;
+
+ grub_net_route_register (route);
+
+ return 0;
+}
grub_err_t
grub_net_add_ipv4_local (struct grub_net_network_level_interface *inter,
diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
index 7d90bf66e76..a5c5038130a 100644
--- a/grub-core/net/tftp.c
+++ b/grub-core/net/tftp.c
@@ -379,19 +379,23 @@ tftp_open (struct grub_file *file, const char *filename)
return grub_errno;
}
+ grub_dprintf ("tftp", "resolving address for %s\n", file->device->net->server);
err = grub_net_resolve_address (file->device->net->server, &addr);
if (err)
{
+ grub_dprintf("tftp", "Address resolution failed: %d\n", err);
destroy_pq (data);
grub_free (data);
return err;
}
+ grub_dprintf ("tftp", "opening connection\n");
data->sock = grub_net_udp_open (addr,
TFTP_SERVER_PORT, tftp_receive,
file);
if (!data->sock)
{
+ grub_dprintf ("tftp", "connection failed\n");
destroy_pq (data);
grub_free (data);
return grub_errno;
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
index addcbfa8fb7..d97cdf98c80 100644
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -572,10 +572,16 @@ typedef void *grub_efi_handle_t;
typedef void *grub_efi_event_t;
typedef grub_efi_uint64_t grub_efi_lba_t;
typedef grub_efi_uintn_t grub_efi_tpl_t;
-typedef grub_uint8_t grub_efi_mac_address_t[32];
-typedef grub_uint8_t grub_efi_ipv4_address_t[4];
-typedef grub_uint16_t grub_efi_ipv6_address_t[8];
-typedef grub_uint8_t grub_efi_ip_address_t[8] __attribute__ ((aligned(4)));
+typedef grub_efi_uint8_t grub_efi_mac_address_t[32];
+typedef grub_efi_uint8_t grub_efi_ipv4_address_t[4];
+typedef grub_efi_uint8_t grub_efi_ipv6_address_t[16];
+typedef union
+{
+ grub_efi_uint32_t addr[4];
+ grub_efi_ipv4_address_t v4;
+ grub_efi_ipv6_address_t v6;
+} grub_efi_ip_address_t __attribute__ ((aligned(4)));
+
typedef grub_efi_uint64_t grub_efi_physical_address_t;
typedef grub_efi_uint64_t grub_efi_virtual_address_t;
@@ -1450,16 +1456,127 @@ struct grub_efi_simple_text_output_interface
};
typedef struct grub_efi_simple_text_output_interface grub_efi_simple_text_output_interface_t;
-typedef grub_uint8_t grub_efi_pxe_packet_t[1472];
+typedef struct grub_efi_pxe_dhcpv4_packet
+{
+ grub_efi_uint8_t bootp_opcode;
+ grub_efi_uint8_t bootp_hwtype;
+ grub_efi_uint8_t bootp_hwaddr_len;
+ grub_efi_uint8_t bootp_gate_hops;
+ grub_efi_uint32_t bootp_ident;
+ grub_efi_uint16_t bootp_seconds;
+ grub_efi_uint16_t bootp_flags;
+ grub_efi_uint8_t bootp_ci_addr[4];
+ grub_efi_uint8_t bootp_yi_addr[4];
+ grub_efi_uint8_t bootp_si_addr[4];
+ grub_efi_uint8_t bootp_gi_addr[4];
+ grub_efi_uint8_t bootp_hw_addr[16];
+ grub_efi_uint8_t bootp_srv_name[64];
+ grub_efi_uint8_t bootp_boot_file[128];
+ grub_efi_uint32_t dhcp_magik;
+ grub_efi_uint8_t dhcp_options[56];
+} grub_efi_pxe_dhcpv4_packet_t;
+
+struct grub_efi_pxe_dhcpv6_packet
+{
+ grub_efi_uint32_t message_type:8;
+ grub_efi_uint32_t transaction_id:24;
+ grub_efi_uint8_t dhcp_options[1024];
+} GRUB_PACKED;
+typedef struct grub_efi_pxe_dhcpv6_packet grub_efi_pxe_dhcpv6_packet_t;
+
+typedef union
+{
+ grub_efi_uint8_t raw[1472];
+ grub_efi_pxe_dhcpv4_packet_t dhcpv4;
+ grub_efi_pxe_dhcpv6_packet_t dhcpv6;
+} grub_efi_pxe_packet_t;
+
+#define GRUB_EFI_PXE_MAX_IPCNT 8
+#define GRUB_EFI_PXE_MAX_ARP_ENTRIES 8
+#define GRUB_EFI_PXE_MAX_ROUTE_ENTRIES 8
+
+typedef struct grub_efi_pxe_ip_filter
+{
+ grub_efi_uint8_t filters;
+ grub_efi_uint8_t ip_count;
+ grub_efi_uint8_t reserved;
+ grub_efi_ip_address_t ip_list[GRUB_EFI_PXE_MAX_IPCNT];
+} grub_efi_pxe_ip_filter_t;
+
+typedef struct grub_efi_pxe_arp_entry
+{
+ grub_efi_ip_address_t ip_addr;
+ grub_efi_mac_address_t mac_addr;
+} grub_efi_pxe_arp_entry_t;
+
+typedef struct grub_efi_pxe_route_entry
+{
+ grub_efi_ip_address_t ip_addr;
+ grub_efi_ip_address_t subnet_mask;
+ grub_efi_ip_address_t gateway_addr;
+} grub_efi_pxe_route_entry_t;
+
+typedef struct grub_efi_pxe_icmp_error
+{
+ grub_efi_uint8_t type;
+ grub_efi_uint8_t code;
+ grub_efi_uint16_t checksum;
+ union
+ {
+ grub_efi_uint32_t reserved;
+ grub_efi_uint32_t mtu;
+ grub_efi_uint32_t pointer;
+ struct
+ {
+ grub_efi_uint16_t identifier;
+ grub_efi_uint16_t sequence;
+ } echo;
+ } u;
+ grub_efi_uint8_t data[494];
+} grub_efi_pxe_icmp_error_t;
+
+typedef struct grub_efi_pxe_tftp_error
+{
+ grub_efi_uint8_t error_code;
+ grub_efi_char8_t error_string[127];
+} grub_efi_pxe_tftp_error_t;
typedef struct grub_efi_pxe_mode
{
- grub_uint8_t unused[52];
+ grub_efi_boolean_t started;
+ grub_efi_boolean_t ipv6_available;
+ grub_efi_boolean_t ipv6_supported;
+ grub_efi_boolean_t using_ipv6;
+ grub_efi_boolean_t bis_supported;
+ grub_efi_boolean_t bis_detected;
+ grub_efi_boolean_t auto_arp;
+ grub_efi_boolean_t send_guid;
+ grub_efi_boolean_t dhcp_discover_valid;
+ grub_efi_boolean_t dhcp_ack_received;
+ grub_efi_boolean_t proxy_offer_received;
+ grub_efi_boolean_t pxe_discover_valid;
+ grub_efi_boolean_t pxe_reply_received;
+ grub_efi_boolean_t pxe_bis_reply_received;
+ grub_efi_boolean_t icmp_error_received;
+ grub_efi_boolean_t tftp_error_received;
+ grub_efi_boolean_t make_callbacks;
+ grub_efi_uint8_t ttl;
+ grub_efi_uint8_t tos;
+ grub_efi_ip_address_t station_ip;
+ grub_efi_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_efi_uint32_t arp_cache_entries;
+ grub_efi_pxe_arp_entry_t arp_cache[GRUB_EFI_PXE_MAX_ARP_ENTRIES];
+ grub_efi_uint32_t route_table_entries;
+ grub_efi_pxe_route_entry_t route_table[GRUB_EFI_PXE_MAX_ROUTE_ENTRIES];
+ grub_efi_pxe_icmp_error_t icmp_error;
+ grub_efi_pxe_tftp_error_t tftp_error;
} grub_efi_pxe_mode_t;
typedef struct grub_efi_pxe
diff --git a/include/grub/net.h b/include/grub/net.h
index ff6d347f7da..3647012374b 100644
--- a/include/grub/net.h
+++ b/include/grub/net.h
@@ -447,6 +447,51 @@ struct grub_net_bootp_packet
grub_uint8_t vendor[0];
} GRUB_PACKED;
+enum
+ {
+ GRUB_NET_DHCP6_IA_NA = 3,
+ GRUB_NET_DHCP6_IA_ADDRESS = 5,
+ GRUB_NET_DHCP6_BOOTFILE_URL = 59,
+ };
+
+struct grub_net_dhcpv6_option
+{
+ grub_uint16_t option_num;
+ grub_uint16_t option_len;
+ grub_uint8_t option_data[];
+} GRUB_PACKED;
+typedef struct grub_net_dhcpv6_option grub_net_dhcpv6_option_t;
+
+struct grub_net_dhcpv6_opt_ia_na
+{
+ grub_uint16_t option_num;
+ grub_uint16_t option_len;
+ grub_uint32_t iaid;
+ grub_uint32_t t1;
+ grub_uint32_t t2;
+ grub_uint8_t options[];
+} GRUB_PACKED;
+typedef struct grub_net_dhcpv6_opt_ia_na grub_net_dhcpv6_opt_ia_na_t;
+
+struct grub_net_dhcpv6_opt_ia_address
+{
+ grub_uint16_t option_num;
+ grub_uint16_t option_len;
+ grub_uint64_t ipv6_address[2];
+ grub_uint32_t preferred_lifetime;
+ grub_uint32_t valid_lifetime;
+ grub_uint8_t options[];
+} GRUB_PACKED;
+typedef struct grub_net_dhcpv6_opt_ia_address grub_net_dhcpv6_opt_ia_address_t;
+
+struct grub_net_dhcpv6_packet
+{
+ grub_uint32_t message_type:8;
+ grub_uint32_t transaction_id:24;
+ grub_uint8_t dhcp_options[1024];
+} GRUB_PACKED;
+typedef struct grub_net_dhcpv6_packet grub_net_dhcpv6_packet_t;
+
#define GRUB_NET_BOOTP_RFC1048_MAGIC_0 0x63
#define GRUB_NET_BOOTP_RFC1048_MAGIC_1 0x82
#define GRUB_NET_BOOTP_RFC1048_MAGIC_2 0x53
@@ -482,6 +527,21 @@ grub_net_configure_by_dhcp_ack (const char *name,
grub_size_t size,
int is_def, char **device, char **path);
+struct grub_net_network_level_interface *
+grub_net_configure_by_dhcpv6_ack (const char *name,
+ struct grub_net_card *card,
+ grub_net_interface_flags_t flags,
+ const grub_net_link_level_address_t *hwaddr,
+ const struct grub_net_dhcpv6_packet *packet,
+ int is_def, char **device, char **path);
+
+int
+grub_ipv6_get_masksize(grub_uint16_t *mask);
+
+grub_err_t
+grub_net_add_ipv6_local (struct grub_net_network_level_interface *inf,
+ int mask);
+
grub_err_t
grub_net_add_ipv4_local (struct grub_net_network_level_interface *inf,
int mask);

View File

@ -0,0 +1,296 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 23 Jun 2016 11:01:39 -0400
Subject: [PATCH] Add grub-get-kernel-settings and use it in 10_linux
This patch adds grub-get-kernel-settings, which reads the system kernel
installation configuration from /etc/sysconfig/kernel, and outputs
${GRUB_...} variables suitable for evaluation by grub-mkconfig. Those
variables are then used by 10_linux to choose whether or not to create
debug stanzas.
Resolves: rhbz#1226325
---
configure.ac | 2 +
Makefile.util.def | 7 ++
util/bash-completion.d/grub-completion.bash.in | 22 +++++++
util/grub-get-kernel-settings.3 | 20 ++++++
util/grub-get-kernel-settings.in | 88 ++++++++++++++++++++++++++
util/grub-mkconfig.in | 3 +
util/grub.d/10_linux.in | 23 +++++--
7 files changed, 160 insertions(+), 5 deletions(-)
create mode 100644 util/grub-get-kernel-settings.3
create mode 100644 util/grub-get-kernel-settings.in
diff --git a/configure.ac b/configure.ac
index 68501662e8d..fc3c2b44d60 100644
--- a/configure.ac
+++ b/configure.ac
@@ -62,6 +62,7 @@ grub_TRANSFORM([grub-install])
grub_TRANSFORM([grub-mkconfig])
grub_TRANSFORM([grub-mkfont])
grub_TRANSFORM([grub-mkimage])
+grub_TRANSFORM([grub-get-kernel-settings])
grub_TRANSFORM([grub-glue-efi])
grub_TRANSFORM([grub-mklayout])
grub_TRANSFORM([grub-mkpasswd-pbkdf2])
@@ -79,6 +80,7 @@ grub_TRANSFORM([grub-file])
grub_TRANSFORM([grub-bios-setup.3])
grub_TRANSFORM([grub-editenv.1])
grub_TRANSFORM([grub-fstest.3])
+grub_TRANSFORM([grub-get-kernel-settings.3])
grub_TRANSFORM([grub-glue-efi.3])
grub_TRANSFORM([grub-install.1])
grub_TRANSFORM([grub-kbdcomp.3])
diff --git a/Makefile.util.def b/Makefile.util.def
index e50436a4987..2215cc759c0 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -725,6 +725,13 @@ script = {
installdir = sbin;
};
+script = {
+ name = grub-get-kernel-settings;
+ common = util/grub-get-kernel-settings.in;
+ mansection = 3;
+ installdir = sbin;
+};
+
script = {
name = grub-set-default;
common = util/grub-set-default.in;
diff --git a/util/bash-completion.d/grub-completion.bash.in b/util/bash-completion.d/grub-completion.bash.in
index 44bf135b9f8..5c4acd496d4 100644
--- a/util/bash-completion.d/grub-completion.bash.in
+++ b/util/bash-completion.d/grub-completion.bash.in
@@ -264,6 +264,28 @@ have ${__grub_sparc64_setup_program} && \
unset __grub_sparc64_setup_program
+#
+# grub-get-kernel-settings
+#
+_grub_get_kernel_settings () {
+ local cur
+
+ COMPREPLY=()
+ cur=`_get_cword`
+
+ if [[ "$cur" == -* ]]; then
+ __grubcomp "$(__grub_get_options_from_help)"
+ else
+ # Default complete with a filename
+ _filedir
+ fi
+}
+__grub_get_kernel_settings_program="@grub_get_kernel_settings@"
+have ${__grub_get_kernel_settings_program} && \
+ complete -F _grub_get_kernel_settings -o filenames ${__grub_get_kernel_settings_program}
+unset __grub_get_kernel_settings_program
+
+
#
# grub-install
#
diff --git a/util/grub-get-kernel-settings.3 b/util/grub-get-kernel-settings.3
new file mode 100644
index 00000000000..ba33330e28d
--- /dev/null
+++ b/util/grub-get-kernel-settings.3
@@ -0,0 +1,20 @@
+.TH GRUB-GET-KERNEL-SETTINGS 3 "Thu Jun 25 2015"
+.SH NAME
+\fBgrub-get-kernel-settings\fR \(em Evaluate the system's kernel installation settings for use while making a grub configuration file.
+
+.SH SYNOPSIS
+\fBgrub-get-kernel-settings\fR [OPTION]
+
+.SH DESCRIPTION
+\fBgrub-get-kernel-settings\fR reads the kernel installation settings on the host system, and emits a set of grub settings suitable for use when creating a grub configuration file.
+
+.SH OPTIONS
+.TP
+-h, --help
+Display program usage and exit.
+.TP
+-v, --version
+Display the current version.
+
+.SH SEE ALSO
+.BR "info grub"
diff --git a/util/grub-get-kernel-settings.in b/util/grub-get-kernel-settings.in
new file mode 100644
index 00000000000..7e87dfccc0e
--- /dev/null
+++ b/util/grub-get-kernel-settings.in
@@ -0,0 +1,88 @@
+#!/bin/sh
+set -e
+
+# Evaluate new-kernel-pkg's configuration file.
+# Copyright (C) 2016 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/>.
+
+PACKAGE_NAME=@PACKAGE_NAME@
+PACKAGE_VERSION=@PACKAGE_VERSION@
+datadir="@datadir@"
+if [ "x$pkgdatadir" = x ]; then
+ pkgdatadir="${datadir}/@PACKAGE@"
+fi
+
+self=`basename $0`
+
+export TEXTDOMAIN=@PACKAGE@
+export TEXTDOMAINDIR="@localedir@"
+
+. "${pkgdatadir}/grub-mkconfig_lib"
+
+# Usage: usage
+# Print the usage.
+usage () {
+ gettext_printf "Usage: %s [OPTION]\n" "$self"
+ gettext "Evaluate new-kernel-pkg configuration"; 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
+}
+
+# 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 ;;
+ -*)
+ gettext_printf "Unrecognized option \`%s'\n" "$option" 1>&2
+ usage
+ exit 1
+ ;;
+ # Explicitly ignore non-option arguments, for compatibility.
+ esac
+done
+
+if test -f /etc/sysconfig/kernel ; then
+ . /etc/sysconfig/kernel
+fi
+
+if [ "$MAKEDEBUG" = "yes" ]; then
+ echo GRUB_LINUX_MAKE_DEBUG=true
+ echo export GRUB_LINUX_MAKE_DEBUG
+ echo GRUB_CMDLINE_LINUX_DEBUG=\"systemd.log_level=debug systemd.log_target=kmsg\"
+ echo export GRUB_CMDLINE_LINUX_DEBUG
+ echo GRUB_LINUX_DEBUG_TITLE_POSTFIX=\" with debugging\"
+ echo export GRUB_LINUX_DEBUG_TITLE_POSTFIX
+fi
+if [ "$DEFAULTDEBUG" = "yes" ]; then
+ echo GRUB_DEFAULT_TO_DEBUG=true
+else
+ echo GRUB_DEFAULT_TO_DEBUG=false
+fi
+echo export GRUB_DEFAULT_TO_DEBUG
+if [ "$UPDATEDEFAULT" = "yes" ]; then
+ echo GRUB_UPDATE_DEFAULT_KERNEL=true
+ echo export GRUB_UPDATE_DEFAULT_KERNEL
+fi
diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
index 4e7a875309e..6247a0ba850 100644
--- a/util/grub-mkconfig.in
+++ b/util/grub-mkconfig.in
@@ -45,6 +45,7 @@ grub_probe="${sbindir}/@grub_probe@"
grub_file="${bindir}/@grub_file@"
grub_editenv="${bindir}/@grub_editenv@"
grub_script_check="${bindir}/@grub_script_check@"
+grub_get_kernel_settings="${sbindir}/@grub_get_kernel_settings@"
export TEXTDOMAIN=@PACKAGE@
export TEXTDOMAINDIR="@localedir@"
@@ -158,6 +159,8 @@ if test -f ${sysconfdir}/default/grub ; then
. ${sysconfdir}/default/grub
fi
+eval "$("${grub_get_kernel_settings}")" || true
+
if [ "x$GRUB_DISABLE_UUID" != "xtrue" ]; then
if [ -z "$GRUB_DEVICE_UUID" ]; then
GRUB_DEVICE_UUID="$GRUB_DEVICE_UUID_GENERATED"
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index 12a20c9ad73..55f4aa783cf 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -111,7 +111,8 @@ linux_entry ()
os="$1"
version="$2"
type="$3"
- args="$4"
+ isdebug="$4"
+ args="$5"
if [ -z "$boot_device_id" ]; then
boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")"
@@ -123,6 +124,9 @@ linux_entry ()
quoted="$(echo "$GRUB_ACTUAL_DEFAULT" | grub_quote)"
title_correction_code="${title_correction_code}if [ \"x\$default\" = '$quoted' ]; then default='$(echo "$replacement_title" | grub_quote)'; fi;"
fi
+ if [ x$isdebug = xdebug ]; then
+ title="$title${GRUB_LINUX_DEBUG_TITLE_POSTFIX}"
+ fi
echo "menuentry '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-$version-$type-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
else
echo "menuentry '$(echo "$os" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
@@ -295,11 +299,15 @@ while [ "x$list" != "x" ] ; do
fi
if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xtrue ]; then
- linux_entry "${OS}" "${version}" simple \
+ linux_entry "${OS}" "${version}" simple standard \
"${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
+ if [ "x$GRUB_LINUX_MAKE_DEBUG" = "xtrue" ]; then
+ linux_entry "${OS}" "${version}" simple debug \
+ "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT} ${GRUB_CMDLINE_LINUX_DEBUG}"
+ fi
submenu_indentation="$grub_tab"
-
+
if [ -z "$boot_device_id" ]; then
boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")"
fi
@@ -308,10 +316,15 @@ while [ "x$list" != "x" ] ; do
is_top_level=false
fi
- linux_entry "${OS}" "${version}" advanced \
+ linux_entry "${OS}" "${version}" advanced standard \
"${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
+ if [ "x$GRUB_LINUX_MAKE_DEBUG" = "xtrue" ]; then
+ linux_entry "${OS}" "${version}" advanced debug \
+ "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT} ${GRUB_CMDLINE_LINUX_DEBUG}"
+ fi
+
if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then
- linux_entry "${OS}" "${version}" recovery \
+ linux_entry "${OS}" "${version}" recovery standard \
"single ${GRUB_CMDLINE_LINUX}"
fi

View File

@ -0,0 +1,61 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lenny Szubowicz <lszubowi@redhat.com>
Date: Mon, 29 Aug 2016 11:04:48 -0400
Subject: [PATCH] Normalize slashes in tftp paths.
Some tftp servers do not handle multiple consecutive slashes correctly;
this patch avoids sending tftp requests with non-normalized paths.
Signed-off-by: Lenny Szubowicz <lszubowi@redhat.com>
[msalter: fix malformed tftp packets]
Signed-off-by: Mark Salter <msalter@redhat.com>
---
grub-core/net/tftp.c | 28 +++++++++++++++++++++++++---
1 file changed, 25 insertions(+), 3 deletions(-)
diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
index a5c5038130a..e6d831f1bc9 100644
--- a/grub-core/net/tftp.c
+++ b/grub-core/net/tftp.c
@@ -300,6 +300,25 @@ destroy_pq (tftp_data_t data)
grub_priority_queue_destroy (data->pq);
}
+/* Create a normalized copy of the filename.
+ Compress any string of consecutive forward slashes to a single forward
+ slash. */
+static void
+grub_normalize_filename (char *normalized, const char *filename)
+{
+ char *dest = normalized;
+ char *src = filename;
+
+ while (*src != '\0')
+ {
+ if (src[0] == '/' && src[1] == '/')
+ src++;
+ else
+ *dest++ = *src++;
+ }
+ *dest = '\0';
+}
+
static grub_err_t
tftp_open (struct grub_file *file, const char *filename)
{
@@ -337,9 +356,12 @@ tftp_open (struct grub_file *file, const char *filename)
rrqlen = 0;
tftph->opcode = grub_cpu_to_be16_compile_time (TFTP_RRQ);
- grub_strcpy (rrq, filename);
- rrqlen += grub_strlen (filename) + 1;
- rrq += grub_strlen (filename) + 1;
+
+ /* Copy and normalize the filename to work-around issues on some tftp
+ servers when file names are being matched for remapping. */
+ grub_normalize_filename (rrq, filename);
+ rrqlen += grub_strlen (rrq) + 1;
+ rrq += grub_strlen (rrq) + 1;
grub_strcpy (rrq, "octet");
rrqlen += grub_strlen ("octet") + 1;

View File

@ -0,0 +1,45 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Masahiro Matsuya <mmatsuya@redhat.com>
Date: Sat, 29 Oct 2016 08:35:26 +0900
Subject: [PATCH] bz1374141 fix incorrect mask for ppc64
The netmask configured in firmware is not respected on ppc64 (big endian).
When 255.255.252.0 is set as netmask in firmware, the following is the value of bootpath string in grub_ieee1275_parse_bootpath().
/vdevice/l-lan@30000002:speed=auto,duplex=auto,192.168.88.10,,192.168.89.113,192.168.88.1,5,5,255.255.252.0,512
The netmask in this bootpath is no problem, since it's a value specified in firmware. But,
The value of 'subnet_mask.ipv4' was set with 0xfffffc00, and __builtin_ctz (~grub_le_to_cpu32 (subnet_mask.ipv4)) returned 16 (not 22).
As a result, 16 was used for netmask wrongly.
1111 1111 1111 1111 1111 1100 0000 0000 # subnet_mask.ipv4 (=0xfffffc00)
0000 0000 1111 1100 1111 1111 1111 1111 # grub_le_to_cpu32 (subnet_mask.ipv4)
1111 1111 0000 0011 0000 0000 0000 0000 # ~grub_le_to_cpu32 (subnet_mask.ipv4)
And, the count of zero with __builtin_ctz can be 16.
This patch changes it as below.
1111 1111 1111 1111 1111 1100 0000 0000 # subnet_mask.ipv4 (=0xfffffc00)
0000 0000 1111 1100 1111 1111 1111 1111 # grub_le_to_cpu32 (subnet_mask.ipv4)
1111 1111 1111 1111 1111 1100 0000 0000 # grub_swap_bytes32(grub_le_to_cpu32 (subnet_mask.ipv4))
0000 0000 0000 0000 0000 0011 1111 1111 # ~grub_swap_bytes32(grub_le_to_cpu32 (subnet_mask.ipv4))
The count of zero with __builtin_clz can be 22. (clz counts the number of one bits preceding the most significant zero bit)
---
grub-core/net/drivers/ieee1275/ofnet.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c
index ac4e62a95c9..3860b6f78d8 100644
--- a/grub-core/net/drivers/ieee1275/ofnet.c
+++ b/grub-core/net/drivers/ieee1275/ofnet.c
@@ -220,8 +220,7 @@ grub_ieee1275_parse_bootpath (const char *devpath, char *bootpath,
flags);
inter->vlantag = vlantag;
grub_net_add_ipv4_local (inter,
- __builtin_ctz (~grub_le_to_cpu32 (subnet_mask.ipv4)));
-
+ __builtin_clz (~grub_swap_bytes32(grub_le_to_cpu32 (subnet_mask.ipv4))));
}
if (gateway_addr.ipv4 != 0)

View File

@ -0,0 +1,172 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Wed, 27 Jan 2016 09:22:42 -0500
Subject: [PATCH] Make grub_fatal() also backtrace.
---
grub-core/Makefile.core.def | 3 ++
grub-core/kern/misc.c | 8 +++++-
grub-core/lib/arm64/backtrace.c | 62 +++++++++++++++++++++++++++++++++++++++++
grub-core/lib/backtrace.c | 2 ++
grub-core/lib/i386/backtrace.c | 14 +++++++++-
5 files changed, 87 insertions(+), 2 deletions(-)
create mode 100644 grub-core/lib/arm64/backtrace.c
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 99466b1e47e..ebc558019cd 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -186,6 +186,9 @@ kernel = {
softdiv = lib/division.c;
+ x86 = lib/i386/backtrace.c;
+ x86 = lib/backtrace.c;
+
i386 = kern/i386/dl.c;
i386_xen = kern/i386/dl.c;
i386_xen_pvh = kern/i386/dl.c;
diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
index 1c560ea570a..04371ac49f2 100644
--- a/grub-core/kern/misc.c
+++ b/grub-core/kern/misc.c
@@ -24,6 +24,7 @@
#include <grub/term.h>
#include <grub/env.h>
#include <grub/i18n.h>
+#include <grub/backtrace.h>
union printf_arg
{
@@ -1101,8 +1102,13 @@ grub_xasprintf (const char *fmt, ...)
static void __attribute__ ((noreturn))
grub_abort (void)
{
+#ifndef GRUB_UTIL
+#if defined(__i386__) || defined(__x86_64__)
+ grub_backtrace();
+#endif
+#endif
grub_printf ("\nAborted.");
-
+
#ifndef GRUB_UTIL
if (grub_term_inputs)
#endif
diff --git a/grub-core/lib/arm64/backtrace.c b/grub-core/lib/arm64/backtrace.c
new file mode 100644
index 00000000000..1079b5380e1
--- /dev/null
+++ b/grub-core/lib/arm64/backtrace.c
@@ -0,0 +1,62 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 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/>.
+ */
+
+#include <grub/misc.h>
+#include <grub/command.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/term.h>
+#include <grub/backtrace.h>
+
+#define MAX_STACK_FRAME 102400
+
+void
+grub_backtrace_pointer (int frame)
+{
+ while (1)
+ {
+ void *lp = __builtin_return_address (frame);
+ if (!lp)
+ break;
+
+ lp = __builtin_extract_return_addr (lp);
+
+ grub_printf ("%p: ", lp);
+ grub_backtrace_print_address (lp);
+ grub_printf (" (");
+ for (i = 0; i < 2; i++)
+ grub_printf ("%p,", ((void **)ptr) [i + 2]);
+ grub_printf ("%p)\n", ((void **)ptr) [i + 2]);
+ nptr = *(void **)ptr;
+ if (nptr < ptr || (void **) nptr - (void **) ptr > MAX_STACK_FRAME
+ || nptr == ptr)
+ {
+ grub_printf ("Invalid stack frame at %p (%p)\n", ptr, nptr);
+ break;
+ }
+ ptr = nptr;
+ }
+}
+
+void
+grub_backtrace (void)
+{
+ grub_backtrace_pointer (1);
+}
+
diff --git a/grub-core/lib/backtrace.c b/grub-core/lib/backtrace.c
index 825a8800e25..c0ad6ab8be1 100644
--- a/grub-core/lib/backtrace.c
+++ b/grub-core/lib/backtrace.c
@@ -29,6 +29,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
void
grub_backtrace_print_address (void *addr)
{
+#ifndef GRUB_UTIL
grub_dl_t mod;
FOR_DL_MODULES (mod)
@@ -44,6 +45,7 @@ grub_backtrace_print_address (void *addr)
}
}
+#endif
grub_printf ("%p", addr);
}
diff --git a/grub-core/lib/i386/backtrace.c b/grub-core/lib/i386/backtrace.c
index c3e03c7275c..c67273db3ae 100644
--- a/grub-core/lib/i386/backtrace.c
+++ b/grub-core/lib/i386/backtrace.c
@@ -15,11 +15,23 @@
* 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>
+#ifdef GRUB_UTIL
+#define REALLY_GRUB_UTIL GRUB_UTIL
+#undef GRUB_UTIL
+#endif
+
+#include <grub/symbol.h>
+#include <grub/dl.h>
+
+#ifdef REALLY_GRUB_UTIL
+#define GRUB_UTIL REALLY_GRUB_UTIL
+#undef REALLY_GRUB_UTIL
+#endif
#include <grub/misc.h>
#include <grub/command.h>
#include <grub/err.h>
-#include <grub/dl.h>
#include <grub/mm.h>
#include <grub/term.h>
#include <grub/backtrace.h>

View File

@ -0,0 +1,150 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Tue, 23 Sep 2014 09:58:49 -0400
Subject: [PATCH] Fix up some man pages rpmdiff noticed.
---
configure.ac | 2 ++
util/grub-macbless.8 | 26 +++++++++++++++++++
util/grub-mkimage.1 | 2 +-
util/grub-syslinux2cfg.1 | 65 ++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 94 insertions(+), 1 deletion(-)
create mode 100644 util/grub-macbless.8
create mode 100644 util/grub-syslinux2cfg.1
diff --git a/configure.ac b/configure.ac
index fc3c2b44d60..eb851b8d722 100644
--- a/configure.ac
+++ b/configure.ac
@@ -84,6 +84,7 @@ grub_TRANSFORM([grub-get-kernel-settings.3])
grub_TRANSFORM([grub-glue-efi.3])
grub_TRANSFORM([grub-install.1])
grub_TRANSFORM([grub-kbdcomp.3])
+grub_TRANSFORM([grub-macbless.8])
grub_TRANSFORM([grub-menulst2cfg.1])
grub_TRANSFORM([grub-mkconfig.1])
grub_TRANSFORM([grub-mkfont.3])
@@ -102,6 +103,7 @@ grub_TRANSFORM([grub-render-label.3])
grub_TRANSFORM([grub-script-check.3])
grub_TRANSFORM([grub-set-default.1])
grub_TRANSFORM([grub-sparc64-setup.3])
+grub_TRANSFORM([grub-syslinux2cfg.1])
# Optimization flag. Allow user to override.
if test "x$TARGET_CFLAGS" = x; then
diff --git a/util/grub-macbless.8 b/util/grub-macbless.8
new file mode 100644
index 00000000000..ae842f3a606
--- /dev/null
+++ b/util/grub-macbless.8
@@ -0,0 +1,26 @@
+.TH GRUB-MACBLESS 1 "Wed Feb 26 2014"
+.SH NAME
+\fBgrub-macbless\fR \(em Mac-style bless utility for HFS or HFS+
+
+.SH SYNOPSIS
+\fBgrub-macbless\fR [-p | --ppc] [-v | --verbose] [-x | --x86] \fIFILE\fR
+
+.SH DESCRIPTION
+\fBgrub-mkimage\fR blesses a file on an HFS or HFS+ file system, so that it
+can be used to boot a Mac.
+
+.SH OPTIONS
+.TP
+--ppc
+Bless the file for use on PPC-based Macs.
+
+.TP
+--verbose
+Print verbose messages.
+
+.TP
+--x86
+Bless the file for use on x86-based Macs.
+
+.SH SEE ALSO
+.BR "info grub"
diff --git a/util/grub-mkimage.1 b/util/grub-mkimage.1
index 4dea4f54597..0eaaafe505b 100644
--- a/util/grub-mkimage.1
+++ b/util/grub-mkimage.1
@@ -17,7 +17,7 @@
[-v | --verbose] \fIMODULES\fR
.SH DESCRIPTION
-\fBgrub-mkimage\fI builds a bootable image of GRUB.
+\fBgrub-mkimage\fR builds a bootable image of GRUB.
.SH OPTIONS
.TP
diff --git a/util/grub-syslinux2cfg.1 b/util/grub-syslinux2cfg.1
new file mode 100644
index 00000000000..85309482718
--- /dev/null
+++ b/util/grub-syslinux2cfg.1
@@ -0,0 +1,65 @@
+.TH GRUB-SYSLINUX2CFG 1 "Wed Feb 26 2014"
+.SH NAME
+\fBgrub-syslinux2cfg\fR \(em Transform a syslinux config file into a GRUB config.
+
+.SH SYNOPSIS
+\fBgrub-syslinux2cfg\fR [-c | --cwd=\fRDIR\fI] [-r | --root=\fIDIR\fR] [-v | --verbose]
+.RE
+.RS 25
+[-t | --target-root=\fIDIR\fR] [-T | --target-cwd=\fIDIR\fR]
+.RE
+.RS 25
+[-o | --output=\fIFILE\fR] [[-i | --isolinux] |
+.RE
+.RS 46
+ [-s | --syslinux] |
+.RE
+.RS 46
+ [-p | --pxelinux]] \fIFILE\fR
+
+.SH DESCRIPTION
+\fBgrub-syslinux2cfg\fR builds a GRUB configuration file out of an existing
+syslinux configuration file.
+
+.SH OPTIONS
+.TP
+--cwd=\fIDIR\fR
+Set \fIDIR\fR as syslinux's working directory. The default is to use the
+parent directory of the input file.
+
+.TP
+--root=\fIDIR\fR
+Set \fIDIR\fR as the root directory of the syslinux disk. The default value
+is "/".
+
+.TP
+--verbose
+Print verbose messages.
+
+.TP
+--target-root=\fIDIR\fR
+Root directory as it will be seen at runtime. The default value is "/".
+
+.TP
+--target-cwd=\fIDIR\fR
+Working directory of syslinux as it will be seen at runtime. The default
+value is the parent directory of the input file.
+
+.TP
+--output=\fIFILE\fR
+Write the new config file to \fIFILE\fR. The default value is standard output.
+
+.TP
+--isolinux
+Assume that the input file is an isolinux configuration file.
+
+.TP
+--pxelinux
+Assume that the input file is a pxelinux configuration file.
+
+.TP
+--syslinux
+Assume that the input file is a syslinux configuration file.
+
+.SH SEE ALSO
+.BR "info grub"

View File

@ -0,0 +1,42 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mark Salter <msalter@redhat.com>
Date: Mon, 17 Apr 2017 08:44:29 -0400
Subject: [PATCH] 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/linux.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
index 04994d5c67d..4c0a09c06de 100644
--- a/grub-core/loader/arm64/linux.c
+++ b/grub-core/loader/arm64/linux.c
@@ -81,7 +81,21 @@ finalize_params_linux (void)
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;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,41 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 1 May 2017 11:19:40 -0400
Subject: [PATCH] print more debug info in our module loader.
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/kern/efi/efi.c | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
index 370ce03c5d7..a1af9b46559 100644
--- a/grub-core/kern/efi/efi.c
+++ b/grub-core/kern/efi/efi.c
@@ -313,13 +313,23 @@ grub_efi_modules_addr (void)
}
if (i == coff_header->num_sections)
- return 0;
+ {
+ grub_dprintf("sections", "section %d is last section; invalid.\n", i);
+ return 0;
+ }
info = (struct grub_module_info *) ((char *) image->image_base
+ section->virtual_address);
- if (info->magic != GRUB_MODULE_MAGIC)
- return 0;
+ if (section->name[0] != '.' && info->magic != GRUB_MODULE_MAGIC)
+ {
+ grub_dprintf("sections",
+ "section %d has bad magic %08x, should be %08x\n",
+ i, info->magic, GRUB_MODULE_MAGIC);
+ return 0;
+ }
+ grub_dprintf("sections", "returning section info for section %d: \"%s\"\n",
+ i, section->name);
return (grub_addr_t) info;
}

View File

@ -0,0 +1,124 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Wed, 24 May 2017 12:42:32 -0400
Subject: [PATCH] macos: just build chainloader entries, don't try any xnu xnu.
Since our bugs tell us that the xnu boot entries really just don't work
most of the time, and they create piles of extra boot entries, because
they can't quite figure out 32-vs-64 and other stuff like that.
It's rediculous, and we should just boot their bootloader through the
chainloader instead.
So this patch does that.
Resolves: rhbz#893179
Signed-off-by: Peter Jones <pjones@redhat.com>
---
util/grub.d/30_os-prober.in | 78 +++++++++++----------------------------------
1 file changed, 18 insertions(+), 60 deletions(-)
diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
index 9b8f5968e2d..13a3a6bc752 100644
--- a/util/grub.d/30_os-prober.in
+++ b/util/grub.d/30_os-prober.in
@@ -42,68 +42,25 @@ if [ -z "${OSPROBED}" ] ; then
fi
osx_entry() {
- if [ x$2 = x32 ]; then
- # TRANSLATORS: it refers to kernel architecture (32-bit)
- bitstr="$(gettext "(32-bit)")"
- else
- # TRANSLATORS: it refers to kernel architecture (64-bit)
- bitstr="$(gettext "(64-bit)")"
- fi
# TRANSLATORS: it refers on the OS residing on device %s
onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
- cat << EOF
-menuentry '$(echo "${LONGNAME} $bitstr $onstr" | grub_quote)' --class osx --class darwin --class os \$menuentry_id_option 'osprober-xnu-$2-$(grub_get_device_id "${DEVICE}")' {
+ hints=""
+ for hint in `"${grub_probe}" --device ${device} --target=efi_hints 2> /dev/null` ; do
+ hints="${hints} --hint=${hint}"
+ done
+ cat << EOF
+menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' --class osx --class darwin --class os \$menuentry_id_option 'osprober-xnu-$2-$(grub_get_device_id "${DEVICE}")' {
EOF
save_default_entry | grub_add_tab
prepare_grub_to_access_device ${DEVICE} | grub_add_tab
cat << EOF
+ set gfxpayload=keep
load_video
- set do_resume=0
- if [ /var/vm/sleepimage -nt10 / ]; then
- if xnu_resume /var/vm/sleepimage; then
- set do_resume=1
- fi
- fi
- if [ \$do_resume = 0 ]; then
- xnu_uuid ${OSXUUID} uuid
- if [ -f /Extra/DSDT.aml ]; then
- acpi -e /Extra/DSDT.aml
- fi
- if [ /kernelcache -nt /System/Library/Extensions ]; then
- $1 /kernelcache boot-uuid=\${uuid} rd=*uuid
- elif [ -f /System/Library/Kernels/kernel ]; then
- $1 /System/Library/Kernels/kernel boot-uuid=\${uuid} rd=*uuid
- xnu_kextdir /System/Library/Extensions
- else
- $1 /mach_kernel boot-uuid=\${uuid} rd=*uuid
- if [ /System/Library/Extensions.mkext -nt /System/Library/Extensions ]; then
- xnu_mkext /System/Library/Extensions.mkext
- else
- xnu_kextdir /System/Library/Extensions
- fi
- fi
- if [ -f /Extra/Extensions.mkext ]; then
- xnu_mkext /Extra/Extensions.mkext
- fi
- if [ -d /Extra/Extensions ]; then
- xnu_kextdir /Extra/Extensions
- fi
- if [ -f /Extra/devprop.bin ]; then
- xnu_devprop_load /Extra/devprop.bin
- fi
- if [ -f /Extra/splash.jpg ]; then
- insmod jpeg
- xnu_splash /Extra/splash.jpg
- fi
- if [ -f /Extra/splash.png ]; then
- insmod png
- xnu_splash /Extra/splash.png
- fi
- if [ -f /Extra/splash.tga ]; then
- insmod tga
- xnu_splash /Extra/splash.tga
- fi
- fi
+ insmod part_gpt
+ insmod hfsplus
+ search --no-floppy --fs-uuid --set=root ${hints} $(grub_get_device_id "${DEVICE}")
+ chainloader (\$root)/System/Library/CoreServices/boot.efi
+ boot
}
EOF
}
@@ -284,11 +241,12 @@ EOF
echo "$title_correction_code"
;;
macosx)
- if [ "${UUID}" ]; then
- OSXUUID="${UUID}"
- osx_entry xnu_kernel 32
- osx_entry xnu_kernel64 64
- fi
+ for subdevice in ${DEVICE%[[:digit:]]*}* ; do
+ parttype="`"${grub_probe}" --device ${device} --target=gpt_parttype "${subdevice}" 2> /dev/null`"
+ if [[ "$parttype" = "426f6f74-0000-11aa-aa11-00306543ecac" ]]; then
+ DEVICE="${subdevice}" osx_entry
+ fi
+ done
;;
hurd)
onstr="$(gettext_printf "(on %s)" "${DEVICE}")"

View File

@ -0,0 +1,703 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jeff Mahoney <jeffm@suse.com>
Date: Tue, 9 Jul 2019 13:39:45 +0200
Subject: [PATCH] grub2/btrfs: Add ability to boot from subvolumes
This patch adds the ability to specify a different root on a btrfs
filesystem too boot from other than the default one.
btrfs-list-snapshots <dev> will list the subvolumes available on the
filesystem.
set btrfs_subvol=<path> and set btrfs_subvolid=<subvolid> will specify
which subvolume to use and any pathnames provided with either of those
variables set will start using that root. If the subvolume or subvolume id
doesn't exist, then an error case will result.
It is possible to boot into a separate GRUB instance by exporting the
variable and loading the config file from the subvolume.
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
---
grub-core/fs/btrfs.c | 552 +++++++++++++++++++++++++++++++++++++++++++++++++--
include/grub/btrfs.h | 1 +
2 files changed, 533 insertions(+), 20 deletions(-)
diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
index 48bd3d04a5e..6823d9765c4 100644
--- a/grub-core/fs/btrfs.c
+++ b/grub-core/fs/btrfs.c
@@ -38,6 +38,9 @@
#include <zstd.h>
#include <grub/i18n.h>
#include <grub/btrfs.h>
+#include <grub/command.h>
+#include <grub/env.h>
+#include <grub/extcmd.h>
#include <grub/crypto.h>
#include <grub/diskfilter.h>
@@ -78,9 +81,11 @@ struct grub_btrfs_superblock
grub_uint64_t generation;
grub_uint64_t root_tree;
grub_uint64_t chunk_tree;
- grub_uint8_t dummy2[0x20];
+ grub_uint8_t dummy2[0x18];
+ grub_uint64_t bytes_used;
grub_uint64_t root_dir_objectid;
- grub_uint8_t dummy3[0x41];
+ grub_uint64_t num_devices;
+ grub_uint8_t dummy3[0x39];
struct grub_btrfs_device this_device;
char label[0x100];
grub_uint8_t dummy4[0x100];
@@ -120,6 +125,7 @@ struct grub_btrfs_data
grub_uint64_t exttree;
grub_size_t extsize;
struct grub_btrfs_extent_data *extent;
+ grub_uint64_t fs_tree;
};
struct grub_btrfs_chunk_item
@@ -188,6 +194,14 @@ struct grub_btrfs_leaf_descriptor
} *data;
};
+struct grub_btrfs_root_ref
+{
+ grub_uint64_t dirid;
+ grub_uint64_t sequence;
+ grub_uint16_t name_len;
+ const char name[0];
+} __attribute__ ((packed));
+
struct grub_btrfs_time
{
grub_int64_t sec;
@@ -233,6 +247,14 @@ struct grub_btrfs_extent_data
#define GRUB_BTRFS_OBJECT_ID_CHUNK 0x100
+#define GRUB_BTRFS_ROOT_TREE_OBJECTID 1ULL
+#define GRUB_BTRFS_FS_TREE_OBJECTID 5ULL
+#define GRUB_BTRFS_ROOT_REF_KEY 156
+#define GRUB_BTRFS_ROOT_ITEM_KEY 132
+
+static grub_uint64_t btrfs_default_subvolid = 0;
+static char *btrfs_default_subvol = NULL;
+
static grub_disk_addr_t superblock_sectors[] = { 64 * 2, 64 * 1024 * 2,
256 * 1048576 * 2, 1048576ULL * 1048576ULL * 2
};
@@ -1153,6 +1175,62 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
return GRUB_ERR_NONE;
}
+static grub_err_t
+get_fs_root(struct grub_btrfs_data *data, grub_uint64_t tree,
+ grub_uint64_t objectid, grub_uint64_t offset,
+ grub_uint64_t *fs_root);
+
+static grub_err_t
+lookup_root_by_id(struct grub_btrfs_data *data, grub_uint64_t id)
+{
+ grub_err_t err;
+ grub_uint64_t tree;
+
+ err = get_fs_root(data, data->sblock.root_tree, id, -1, &tree);
+ if (!err)
+ data->fs_tree = tree;
+ return err;
+}
+
+static grub_err_t
+find_path (struct grub_btrfs_data *data,
+ const char *path, struct grub_btrfs_key *key,
+ grub_uint64_t *tree, grub_uint8_t *type);
+
+static grub_err_t
+lookup_root_by_name(struct grub_btrfs_data *data, const char *path)
+{
+ grub_err_t err;
+ grub_uint64_t tree = 0;
+ grub_uint8_t type;
+ struct grub_btrfs_key key;
+
+ err = find_path (data, path, &key, &tree, &type);
+ if (err)
+ return grub_error(GRUB_ERR_FILE_NOT_FOUND, "couldn't locate %s\n", path);
+
+ if (key.object_id != grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK) || tree == 0)
+ return grub_error(GRUB_ERR_BAD_FILE_TYPE, "%s: not a subvolume\n", path);
+
+ data->fs_tree = tree;
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+btrfs_handle_subvol(struct grub_btrfs_data *data __attribute__ ((unused)))
+{
+ if (btrfs_default_subvol)
+ return lookup_root_by_name(data, btrfs_default_subvol);
+
+ if (btrfs_default_subvolid)
+ return lookup_root_by_id(data, btrfs_default_subvolid);
+
+ data->fs_tree = 0;
+
+ return GRUB_ERR_NONE;
+}
+
+
static struct grub_btrfs_data *
grub_btrfs_mount (grub_device_t dev)
{
@@ -1188,6 +1266,13 @@ grub_btrfs_mount (grub_device_t dev)
data->devices_attached[0].dev = dev;
data->devices_attached[0].id = data->sblock.this_device.device_id;
+ err = btrfs_handle_subvol (data);
+ if (err)
+ {
+ grub_free (data);
+ return NULL;
+ }
+
return data;
}
@@ -1653,6 +1738,91 @@ get_root (struct grub_btrfs_data *data, struct grub_btrfs_key *key,
return GRUB_ERR_NONE;
}
+static grub_err_t
+find_pathname(struct grub_btrfs_data *data, grub_uint64_t objectid,
+ grub_uint64_t fs_root, const char *name, char **pathname)
+{
+ grub_err_t err;
+ struct grub_btrfs_key key = {
+ .object_id = objectid,
+ .type = GRUB_BTRFS_ITEM_TYPE_INODE_REF,
+ .offset = 0,
+ };
+ struct grub_btrfs_key key_out;
+ struct grub_btrfs_leaf_descriptor desc;
+ char *p = grub_strdup (name);
+ grub_disk_addr_t elemaddr;
+ grub_size_t elemsize;
+ grub_size_t alloc = grub_strlen(name) + 1;
+
+ err = lower_bound(data, &key, &key_out, fs_root,
+ &elemaddr, &elemsize, &desc, 0);
+ if (err)
+ return grub_error(err, "lower_bound caught %d\n", err);
+
+ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_INODE_REF)
+ next(data, &desc, &elemaddr, &elemsize, &key_out);
+
+ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_INODE_REF)
+ {
+ return grub_error(GRUB_ERR_FILE_NOT_FOUND,
+ "Can't find inode ref for {%"PRIuGRUB_UINT64_T
+ ", %u, %"PRIuGRUB_UINT64_T"} %"PRIuGRUB_UINT64_T
+ "/%"PRIuGRUB_SIZE"\n",
+ key_out.object_id, key_out.type,
+ key_out.offset, elemaddr, elemsize);
+ }
+
+
+ while (key_out.type == GRUB_BTRFS_ITEM_TYPE_INODE_REF &&
+ key_out.object_id != key_out.offset) {
+ struct grub_btrfs_inode_ref *inode_ref;
+ char *new;
+
+ inode_ref = grub_malloc(elemsize + 1);
+ if (!inode_ref)
+ return grub_error(GRUB_ERR_OUT_OF_MEMORY,
+ "couldn't allocate memory for inode_ref (%"PRIuGRUB_SIZE")\n", elemsize);
+
+ err = grub_btrfs_read_logical(data, elemaddr, inode_ref, elemsize, 0);
+ if (err)
+ return grub_error(err, "read_logical caught %d\n", err);
+
+ alloc += grub_le_to_cpu16 (inode_ref->n) + 2;
+ new = grub_malloc(alloc);
+ if (!new)
+ return grub_error(GRUB_ERR_OUT_OF_MEMORY,
+ "couldn't allocate memory for name (%"PRIuGRUB_SIZE")\n", alloc);
+
+ grub_memcpy(new, inode_ref->name, grub_le_to_cpu16 (inode_ref->n));
+ if (p)
+ {
+ new[grub_le_to_cpu16 (inode_ref->n)] = '/';
+ grub_strcpy (new + grub_le_to_cpu16 (inode_ref->n) + 1, p);
+ grub_free(p);
+ }
+ else
+ new[grub_le_to_cpu16 (inode_ref->n)] = 0;
+ grub_free(inode_ref);
+
+ p = new;
+
+ key.object_id = key_out.offset;
+
+ err = lower_bound(data, &key, &key_out, fs_root, &elemaddr,
+ &elemsize, &desc, 0);
+ if (err)
+ return grub_error(err, "lower_bound caught %d\n", err);
+
+ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_INODE_REF)
+ next(data, &desc, &elemaddr, &elemsize, &key_out);
+
+ }
+
+ *pathname = p;
+ return 0;
+}
+
static grub_err_t
find_path (struct grub_btrfs_data *data,
const char *path, struct grub_btrfs_key *key,
@@ -1671,14 +1841,26 @@ find_path (struct grub_btrfs_data *data,
char *origpath = NULL;
unsigned symlinks_max = 32;
- err = get_root (data, key, tree, type);
- if (err)
- return err;
-
origpath = grub_strdup (path);
if (!origpath)
return grub_errno;
+ if (data->fs_tree)
+ {
+ *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY;
+ *tree = data->fs_tree;
+ /* This is a tree root, so everything starts at objectid 256 */
+ key->object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK);
+ key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM;
+ key->offset = 0;
+ }
+ else
+ {
+ err = get_root (data, key, tree, type);
+ if (err)
+ return err;
+ }
+
while (1)
{
while (path[0] == '/')
@@ -1851,9 +2033,21 @@ find_path (struct grub_btrfs_data *data,
path = path_alloc = tmp;
if (path[0] == '/')
{
- err = get_root (data, key, tree, type);
- if (err)
- return err;
+ if (data->fs_tree)
+ {
+ *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY;
+ *tree = data->fs_tree;
+ /* This is a tree root, so everything starts at objectid 256 */
+ key->object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK);
+ key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM;
+ key->offset = 0;
+ }
+ else
+ {
+ err = get_root (data, key, tree, type);
+ if (err)
+ return err;
+ }
}
continue;
}
@@ -2094,18 +2288,10 @@ grub_btrfs_read (grub_file_t file, char *buf, grub_size_t len)
data->tree, file->offset, buf, len);
}
-static grub_err_t
-grub_btrfs_uuid (grub_device_t device, char **uuid)
+static char *
+btrfs_unparse_uuid(struct grub_btrfs_data *data)
{
- struct grub_btrfs_data *data;
-
- *uuid = NULL;
-
- data = grub_btrfs_mount (device);
- if (!data)
- return grub_errno;
-
- *uuid = grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
+ return grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
grub_be_to_cpu16 (data->sblock.uuid[0]),
grub_be_to_cpu16 (data->sblock.uuid[1]),
grub_be_to_cpu16 (data->sblock.uuid[2]),
@@ -2114,6 +2300,20 @@ grub_btrfs_uuid (grub_device_t device, char **uuid)
grub_be_to_cpu16 (data->sblock.uuid[5]),
grub_be_to_cpu16 (data->sblock.uuid[6]),
grub_be_to_cpu16 (data->sblock.uuid[7]));
+}
+
+static grub_err_t
+grub_btrfs_uuid (grub_device_t device, char **uuid)
+{
+ struct grub_btrfs_data *data;
+
+ *uuid = NULL;
+
+ data = grub_btrfs_mount (device);
+ if (!data)
+ return grub_errno;
+
+ *uuid = btrfs_unparse_uuid(data);
grub_btrfs_unmount (data);
@@ -2170,6 +2370,242 @@ grub_btrfs_embed (grub_device_t device __attribute__ ((unused)),
}
#endif
+static grub_err_t
+grub_cmd_btrfs_info (grub_command_t cmd __attribute__ ((unused)), int argc,
+ char **argv)
+{
+ grub_device_t dev;
+ char *devname;
+ struct grub_btrfs_data *data;
+ char *uuid;
+
+ 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;
+
+ dev = grub_device_open (devname);
+ grub_free (devname);
+ if (!dev)
+ return grub_errno;
+
+ data = grub_btrfs_mount (dev);
+ if (!data)
+ {
+ grub_device_close(dev);
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to open fs");
+ }
+
+ if (data->sblock.label)
+ grub_printf("Label: '%s' ", data->sblock.label);
+ else
+ grub_printf("Label: none ");
+
+ uuid = btrfs_unparse_uuid(data);
+
+ grub_printf(" uuid: %s\n\tTotal devices %" PRIuGRUB_UINT64_T
+ " FS bytes used %" PRIuGRUB_UINT64_T "\n",
+ uuid, grub_cpu_to_le64(data->sblock.num_devices),
+ grub_cpu_to_le64(data->sblock.bytes_used));
+
+ grub_btrfs_unmount (data);
+
+ return 0;
+}
+
+static grub_err_t
+get_fs_root(struct grub_btrfs_data *data, grub_uint64_t tree,
+ grub_uint64_t objectid, grub_uint64_t offset,
+ grub_uint64_t *fs_root)
+{
+ grub_err_t err;
+ struct grub_btrfs_key key_in = {
+ .object_id = objectid,
+ .type = GRUB_BTRFS_ROOT_ITEM_KEY,
+ .offset = offset,
+ }, key_out;
+ struct grub_btrfs_leaf_descriptor desc;
+ grub_disk_addr_t elemaddr;
+ grub_size_t elemsize;
+ struct grub_btrfs_root_item ri;
+
+ err = lower_bound(data, &key_in, &key_out, tree,
+ &elemaddr, &elemsize, &desc, 0);
+
+ if (err)
+ return err;
+
+ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_ROOT_ITEM || elemaddr == 0)
+ return grub_error(GRUB_ERR_FILE_NOT_FOUND,
+ N_("can't find fs root for subvol %"PRIuGRUB_UINT64_T"\n"),
+ key_in.object_id);
+
+ err = grub_btrfs_read_logical (data, elemaddr, &ri, sizeof (ri), 0);
+ if (err)
+ return err;
+
+ *fs_root = ri.tree;
+
+ return GRUB_ERR_NONE;
+}
+
+static const struct grub_arg_option options[] = {
+ {"output", 'o', 0, N_("Output to a variable instead of the console."),
+ N_("VARNAME"), ARG_TYPE_STRING},
+ {"path-only", 'p', 0, N_("Show only the path of the subvolume."), 0, 0},
+ {"id-only", 'i', 0, N_("Show only the id of the subvolume."), 0, 0},
+ {0, 0, 0, 0, 0, 0}
+};
+
+static grub_err_t
+grub_cmd_btrfs_list_subvols (struct grub_extcmd_context *ctxt,
+ int argc, char **argv)
+{
+ struct grub_btrfs_data *data;
+ grub_device_t dev;
+ char *devname;
+ grub_uint64_t tree;
+ struct grub_btrfs_key key_in = {
+ .object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_FS_TREE_OBJECTID),
+ .type = GRUB_BTRFS_ROOT_REF_KEY,
+ .offset = 0,
+ }, key_out;
+ struct grub_btrfs_leaf_descriptor desc;
+ grub_disk_addr_t elemaddr;
+ grub_uint64_t fs_root = 0;
+ grub_size_t elemsize;
+ grub_size_t allocated = 0;
+ int r = 0;
+ grub_err_t err;
+ char *buf = NULL;
+ int print = 1;
+ int path_only = ctxt->state[1].set;
+ int num_only = ctxt->state[2].set;
+ char *varname = NULL;
+ char *output = NULL;
+
+ if (ctxt->state[0].set) {
+ varname = ctxt->state[0].arg;
+ print = 0;
+ }
+
+ 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;
+
+ dev = grub_device_open (devname);
+ grub_free (devname);
+ if (!dev)
+ return grub_errno;
+
+ data = grub_btrfs_mount(dev);
+ if (!data)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "could not open device");
+
+ tree = data->sblock.root_tree;
+ err = get_fs_root(data, tree, grub_cpu_to_le64_compile_time (GRUB_BTRFS_FS_TREE_OBJECTID),
+ 0, &fs_root);
+ if (err)
+ goto out;
+
+ err = lower_bound(data, &key_in, &key_out, tree,
+ &elemaddr, &elemsize, &desc, 0);
+
+ if (err)
+ {
+ grub_btrfs_unmount(data);
+ return err;
+ }
+
+ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_ROOT_REF || elemaddr == 0)
+ {
+ r = next(data, &desc, &elemaddr, &elemsize, &key_out);
+ }
+
+ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_ROOT_REF) {
+ err = GRUB_ERR_FILE_NOT_FOUND;
+ grub_error(GRUB_ERR_FILE_NOT_FOUND, N_("can't find root refs"));
+ goto out;
+ }
+
+ do
+ {
+ struct grub_btrfs_root_ref *ref;
+ char *p = NULL;
+
+ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_ROOT_REF)
+ {
+ r = 0;
+ break;
+ }
+
+ if (elemsize > allocated)
+ {
+ grub_free(buf);
+ allocated = 2 * elemsize;
+ buf = grub_malloc(allocated + 1);
+ if (!buf)
+ {
+ r = -grub_errno;
+ break;
+ }
+ }
+ ref = (struct grub_btrfs_root_ref *)buf;
+
+ err = grub_btrfs_read_logical(data, elemaddr, buf, elemsize, 0);
+ if (err)
+ {
+ r = -err;
+ break;
+ }
+ buf[elemsize] = 0;
+
+ find_pathname(data, ref->dirid, fs_root, ref->name, &p);
+
+ if (print)
+ {
+ if (num_only)
+ grub_printf("ID %"PRIuGRUB_UINT64_T"\n", key_out.offset);
+ else if (path_only)
+ grub_printf("%s\n", p);
+ else
+ grub_printf("ID %"PRIuGRUB_UINT64_T" path %s\n", key_out.offset, p);
+ } else {
+ char *old = output;
+ if (num_only)
+ output = grub_xasprintf("%s%"PRIuGRUB_UINT64_T"\n",
+ old ?: "", key_out.offset);
+ else if (path_only)
+ output = grub_xasprintf("%s%s\n", old ?: "", p);
+ else
+ output = grub_xasprintf("%sID %"PRIuGRUB_UINT64_T" path %s\n",
+ old ?: "", key_out.offset, p);
+
+ if (old)
+ grub_free(old);
+ }
+
+ r = next(data, &desc, &elemaddr, &elemsize, &key_out);
+ } while(r > 0);
+
+ if (output)
+ grub_env_set(varname, output);
+
+out:
+ free_iterator(&desc);
+ grub_btrfs_unmount(data);
+
+ grub_device_close (dev);
+
+ return 0;
+}
+
static struct grub_fs grub_btrfs_fs = {
.name = "btrfs",
.fs_dir = grub_btrfs_dir,
@@ -2185,12 +2621,88 @@ static struct grub_fs grub_btrfs_fs = {
#endif
};
+static grub_command_t cmd_info;
+static grub_extcmd_t cmd_list_subvols;
+
+static char *
+subvolid_set_env (struct grub_env_var *var __attribute__ ((unused)),
+ const char *val)
+{
+ unsigned long long result = 0;
+
+ grub_errno = GRUB_ERR_NONE;
+ if (*val)
+ {
+ result = grub_strtoull(val, NULL, 10);
+ if (grub_errno)
+ return NULL;
+ }
+
+ grub_free (btrfs_default_subvol);
+ btrfs_default_subvol = NULL;
+ btrfs_default_subvolid = result;
+ return grub_strdup(val);
+}
+
+static const char *
+subvolid_get_env (struct grub_env_var *var __attribute__ ((unused)),
+ const char *val __attribute__ ((unused)))
+{
+ if (btrfs_default_subvol)
+ return grub_xasprintf("subvol:%s", btrfs_default_subvol);
+ else if (btrfs_default_subvolid)
+ return grub_xasprintf("%"PRIuGRUB_UINT64_T, btrfs_default_subvolid);
+ else
+ return "";
+}
+
+static char *
+subvol_set_env (struct grub_env_var *var __attribute__ ((unused)),
+ const char *val)
+{
+ grub_free (btrfs_default_subvol);
+ btrfs_default_subvol = grub_strdup (val);
+ btrfs_default_subvolid = 0;
+ return grub_strdup(val);
+}
+
+static const char *
+subvol_get_env (struct grub_env_var *var __attribute__ ((unused)),
+ const char *val __attribute__ ((unused)))
+{
+ if (btrfs_default_subvol)
+ return btrfs_default_subvol;
+ else if (btrfs_default_subvolid)
+ return grub_xasprintf("subvolid:%" PRIuGRUB_UINT64_T,
+ btrfs_default_subvolid);
+ else
+ return "";
+}
+
GRUB_MOD_INIT (btrfs)
{
grub_fs_register (&grub_btrfs_fs);
+ cmd_info = grub_register_command("btrfs-info", grub_cmd_btrfs_info,
+ "DEVICE",
+ "Print BtrFS info about DEVICE.");
+ cmd_list_subvols = grub_register_extcmd("btrfs-list-subvols",
+ grub_cmd_btrfs_list_subvols, 0,
+ "[-p|-n] [-o var] DEVICE",
+ "Print list of BtrFS subvolumes on "
+ "DEVICE.", options);
+ grub_register_variable_hook ("btrfs_subvol", subvol_get_env,
+ subvol_set_env);
+ grub_register_variable_hook ("btrfs_subvolid", subvolid_get_env,
+ subvolid_set_env);
}
GRUB_MOD_FINI (btrfs)
{
+ grub_register_variable_hook ("btrfs_subvol", NULL, NULL);
+ grub_register_variable_hook ("btrfs_subvolid", NULL, NULL);
+ grub_unregister_command (cmd_info);
+ grub_unregister_extcmd (cmd_list_subvols);
grub_fs_unregister (&grub_btrfs_fs);
}
+
+// vim: si et sw=2:
diff --git a/include/grub/btrfs.h b/include/grub/btrfs.h
index 9d93fb6c182..234ad976771 100644
--- a/include/grub/btrfs.h
+++ b/include/grub/btrfs.h
@@ -29,6 +29,7 @@ enum
GRUB_BTRFS_ITEM_TYPE_ROOT_ITEM = 0x84,
GRUB_BTRFS_ITEM_TYPE_ROOT_BACKREF = 0x90,
GRUB_BTRFS_ITEM_TYPE_DEVICE = 0xd8,
+ GRUB_BTRFS_ITEM_TYPE_ROOT_REF = 0x9c,
GRUB_BTRFS_ITEM_TYPE_CHUNK = 0xe4
};

View File

@ -0,0 +1,26 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Wed, 18 Dec 2013 09:57:04 +0000
Subject: [PATCH] export btrfs_subvol and btrfs_subvolid
We should export btrfs_subvol and btrfs_subvolid to have both visible
to subsidiary configuration files loaded using configfile.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/fs/btrfs.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
index 6823d9765c4..2d099b18ea1 100644
--- a/grub-core/fs/btrfs.c
+++ b/grub-core/fs/btrfs.c
@@ -2694,6 +2694,8 @@ GRUB_MOD_INIT (btrfs)
subvol_set_env);
grub_register_variable_hook ("btrfs_subvolid", subvolid_get_env,
subvolid_set_env);
+ grub_env_export ("btrfs_subvol");
+ grub_env_export ("btrfs_subvolid");
}
GRUB_MOD_FINI (btrfs)

View File

@ -0,0 +1,196 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 21 Aug 2014 03:39:11 +0000
Subject: [PATCH] grub2-btrfs-03-follow_default
---
grub-core/fs/btrfs.c | 107 ++++++++++++++++++++++++++++++++++++---------------
1 file changed, 76 insertions(+), 31 deletions(-)
diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
index 2d099b18ea1..2db89f71ea5 100644
--- a/grub-core/fs/btrfs.c
+++ b/grub-core/fs/btrfs.c
@@ -1236,6 +1236,7 @@ grub_btrfs_mount (grub_device_t dev)
{
struct grub_btrfs_data *data;
grub_err_t err;
+ const char *relpath = grub_env_get ("btrfs_relative_path");
if (!dev->disk)
{
@@ -1266,11 +1267,14 @@ grub_btrfs_mount (grub_device_t dev)
data->devices_attached[0].dev = dev;
data->devices_attached[0].id = data->sblock.this_device.device_id;
- err = btrfs_handle_subvol (data);
- if (err)
+ if (relpath && (relpath[0] == '1' || relpath[0] == 'y'))
{
- grub_free (data);
- return NULL;
+ err = btrfs_handle_subvol (data);
+ if (err)
+ {
+ grub_free (data);
+ return NULL;
+ }
}
return data;
@@ -1835,24 +1839,39 @@ find_path (struct grub_btrfs_data *data,
grub_size_t allocated = 0;
struct grub_btrfs_dir_item *direl = NULL;
struct grub_btrfs_key key_out;
+ int follow_default;
const char *ctoken;
grub_size_t ctokenlen;
char *path_alloc = NULL;
char *origpath = NULL;
unsigned symlinks_max = 32;
+ const char *relpath = grub_env_get ("btrfs_relative_path");
+ follow_default = 0;
origpath = grub_strdup (path);
if (!origpath)
return grub_errno;
- if (data->fs_tree)
+ if (relpath && (relpath[0] == '1' || relpath[0] == 'y'))
{
- *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY;
- *tree = data->fs_tree;
- /* This is a tree root, so everything starts at objectid 256 */
- key->object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK);
- key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM;
- key->offset = 0;
+ if (data->fs_tree)
+ {
+ *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY;
+ *tree = data->fs_tree;
+ /* This is a tree root, so everything starts at objectid 256 */
+ key->object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK);
+ key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM;
+ key->offset = 0;
+ }
+ else
+ {
+ *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY;
+ *tree = data->sblock.root_tree;
+ key->object_id = data->sblock.root_dir_objectid;
+ key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM;
+ key->offset = 0;
+ follow_default = 1;
+ }
}
else
{
@@ -1863,15 +1882,23 @@ find_path (struct grub_btrfs_data *data,
while (1)
{
- while (path[0] == '/')
- path++;
- if (!path[0])
- break;
- slash = grub_strchr (path, '/');
- if (!slash)
- slash = path + grub_strlen (path);
- ctoken = path;
- ctokenlen = slash - path;
+ if (!follow_default)
+ {
+ while (path[0] == '/')
+ path++;
+ if (!path[0])
+ break;
+ slash = grub_strchr (path, '/');
+ if (!slash)
+ slash = path + grub_strlen (path);
+ ctoken = path;
+ ctokenlen = slash - path;
+ }
+ else
+ {
+ ctoken = "default";
+ ctokenlen = sizeof ("default") - 1;
+ }
if (*type != GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY)
{
@@ -1882,7 +1909,9 @@ find_path (struct grub_btrfs_data *data,
if (ctokenlen == 1 && ctoken[0] == '.')
{
- path = slash;
+ if (!follow_default)
+ path = slash;
+ follow_default = 0;
continue;
}
if (ctokenlen == 2 && ctoken[0] == '.' && ctoken[1] == '.')
@@ -1913,8 +1942,9 @@ find_path (struct grub_btrfs_data *data,
*type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY;
key->object_id = key_out.offset;
- path = slash;
-
+ if (!follow_default)
+ path = slash;
+ follow_default = 0;
continue;
}
@@ -1983,7 +2013,9 @@ find_path (struct grub_btrfs_data *data,
return err;
}
- path = slash;
+ if (!follow_default)
+ path = slash;
+ follow_default = 0;
if (cdirel->type == GRUB_BTRFS_DIR_ITEM_TYPE_SYMLINK)
{
struct grub_btrfs_inode inode;
@@ -2033,14 +2065,26 @@ find_path (struct grub_btrfs_data *data,
path = path_alloc = tmp;
if (path[0] == '/')
{
- if (data->fs_tree)
+ if (relpath && (relpath[0] == '1' || relpath[0] == 'y'))
{
- *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY;
- *tree = data->fs_tree;
- /* This is a tree root, so everything starts at objectid 256 */
- key->object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK);
- key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM;
- key->offset = 0;
+ if (data->fs_tree)
+ {
+ *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY;
+ *tree = data->fs_tree;
+ /* This is a tree root, so everything starts at objectid 256 */
+ key->object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK);
+ key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM;
+ key->offset = 0;
+ }
+ else
+ {
+ *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY;
+ *tree = data->sblock.root_tree;
+ key->object_id = data->sblock.root_dir_objectid;
+ key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM;
+ key->offset = 0;
+ follow_default = 1;
+ }
}
else
{
@@ -2696,6 +2740,7 @@ GRUB_MOD_INIT (btrfs)
subvolid_set_env);
grub_env_export ("btrfs_subvol");
grub_env_export ("btrfs_subvolid");
+ grub_env_export ("btrfs_relative_path");
}
GRUB_MOD_FINI (btrfs)

View File

@ -0,0 +1,174 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 21 Aug 2014 03:39:11 +0000
Subject: [PATCH] grub2-btrfs-04-grub2-install
---
grub-core/osdep/linux/getroot.c | 7 +++++++
grub-core/osdep/unix/config.c | 17 +++++++++++++++--
util/config.c | 10 ++++++++++
util/grub-install.c | 15 +++++++++++++++
util/grub-mkrelpath.c | 6 ++++++
include/grub/emu/config.h | 1 +
6 files changed, 54 insertions(+), 2 deletions(-)
diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c
index 6d9f4e5faa2..5d50dd6f8dc 100644
--- a/grub-core/osdep/linux/getroot.c
+++ b/grub-core/osdep/linux/getroot.c
@@ -376,6 +376,7 @@ get_btrfs_fs_prefix (const char *mount_path)
return NULL;
}
+int use_relative_path_on_btrfs = 0;
char **
grub_find_root_devices_from_mountinfo (const char *dir, char **relroot)
@@ -519,6 +520,12 @@ again:
{
ret = grub_find_root_devices_from_btrfs (dir);
fs_prefix = get_btrfs_fs_prefix (entries[i].enc_path);
+ if (use_relative_path_on_btrfs)
+ {
+ if (fs_prefix)
+ free (fs_prefix);
+ fs_prefix = xstrdup ("/");
+ }
}
else if (!retry && grub_strcmp (entries[i].fstype, "autofs") == 0)
{
diff --git a/grub-core/osdep/unix/config.c b/grub-core/osdep/unix/config.c
index 65effa9f3a7..b637c58efb7 100644
--- a/grub-core/osdep/unix/config.c
+++ b/grub-core/osdep/unix/config.c
@@ -82,6 +82,19 @@ grub_util_load_config (struct grub_util_config *cfg)
if (v)
cfg->grub_distributor = xstrdup (v);
+ v = getenv ("SUSE_BTRFS_SNAPSHOT_BOOTING");
+ if (v)
+ {
+ if (grub_strncmp(v, "true", sizeof ("true") - 1) == 0)
+ {
+ cfg->is_suse_btrfs_snapshot_enabled = 1;
+ }
+ else
+ {
+ cfg->is_suse_btrfs_snapshot_enabled = 0;
+ }
+ }
+
cfgfile = grub_util_get_config_filename ();
if (!grub_util_is_regular (cfgfile))
return;
@@ -105,8 +118,8 @@ grub_util_load_config (struct grub_util_config *cfg)
*ptr++ = *iptr;
}
- strcpy (ptr, "'; printf \"GRUB_ENABLE_CRYPTODISK=%s\\nGRUB_DISTRIBUTOR=%s\\n\" "
- "\"$GRUB_ENABLE_CRYPTODISK\" \"$GRUB_DISTRIBUTOR\"");
+ strcpy (ptr, "'; printf \"GRUB_ENABLE_CRYPTODISK=%s\\nGRUB_DISTRIBUTOR=%s\\nSUSE_BTRFS_SNAPSHOT_BOOTING=%s\\n\" "
+ "\"$GRUB_ENABLE_CRYPTODISK\" \"$GRUB_DISTRIBUTOR\" \"$SUSE_BTRFS_SNAPSHOT_BOOTING\"");
argv[2] = script;
argv[3] = '\0';
diff --git a/util/config.c b/util/config.c
index ebcdd8f5e22..f044a880a76 100644
--- a/util/config.c
+++ b/util/config.c
@@ -42,6 +42,16 @@ grub_util_parse_config (FILE *f, struct grub_util_config *cfg, int simple)
cfg->is_cryptodisk_enabled = 1;
continue;
}
+ if (grub_strncmp (ptr, "SUSE_BTRFS_SNAPSHOT_BOOTING=",
+ sizeof ("SUSE_BTRFS_SNAPSHOT_BOOTING=") - 1) == 0)
+ {
+ ptr += sizeof ("SUSE_BTRFS_SNAPSHOT_BOOTING=") - 1;
+ if (*ptr == '"' || *ptr == '\'')
+ ptr++;
+ if (grub_strncmp(ptr, "true", sizeof ("true") - 1) == 0)
+ cfg->is_suse_btrfs_snapshot_enabled = 1;
+ continue;
+ }
if (grub_strncmp (ptr, "GRUB_DISTRIBUTOR=",
sizeof ("GRUB_DISTRIBUTOR=") - 1) == 0)
{
diff --git a/util/grub-install.c b/util/grub-install.c
index 8a55ad4b8dc..0e807b09c36 100644
--- a/util/grub-install.c
+++ b/util/grub-install.c
@@ -819,6 +819,8 @@ fill_core_services (const char *core_services)
free (sysv_plist);
}
+extern int use_relative_path_on_btrfs;
+
int
main (int argc, char *argv[])
{
@@ -852,6 +854,9 @@ main (int argc, char *argv[])
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;
@@ -1344,6 +1349,16 @@ main (int argc, char *argv[])
fprintf (load_cfg_f, "set debug='%s'\n",
debug_image);
}
+
+ if (config.is_suse_btrfs_snapshot_enabled
+ && grub_strncmp(grub_fs->name, "btrfs", sizeof ("btrfs") - 1) == 0)
+ {
+ if (!load_cfg_f)
+ load_cfg_f = grub_util_fopen (load_cfg, "wb");
+ have_load_cfg = 1;
+ fprintf (load_cfg_f, "set btrfs_relative_path='y'\n");
+ }
+
char *prefix_drive = NULL;
char *install_drive = NULL;
diff --git a/util/grub-mkrelpath.c b/util/grub-mkrelpath.c
index 47a241a391b..5db7a9a7d97 100644
--- a/util/grub-mkrelpath.c
+++ b/util/grub-mkrelpath.c
@@ -40,9 +40,12 @@ struct arguments
};
static struct argp_option options[] = {
+ {"relative", 'r', 0, 0, "use relative path on btrfs", 0},
{ 0, 0, 0, 0, 0, 0 }
};
+extern int use_relative_path_on_btrfs;
+
static error_t
argp_parser (int key, char *arg, struct argp_state *state)
{
@@ -52,6 +55,9 @@ argp_parser (int key, char *arg, struct argp_state *state)
switch (key)
{
+ case 'r':
+ use_relative_path_on_btrfs = 1;
+ break;
case ARGP_KEY_ARG:
if (state->arg_num == 0)
arguments->pathname = xstrdup (arg);
diff --git a/include/grub/emu/config.h b/include/grub/emu/config.h
index 875d5896ce1..c9a7e5f4ade 100644
--- a/include/grub/emu/config.h
+++ b/include/grub/emu/config.h
@@ -37,6 +37,7 @@ struct grub_util_config
{
int is_cryptodisk_enabled;
char *grub_distributor;
+ int is_suse_btrfs_snapshot_enabled;
};
void

View File

@ -0,0 +1,129 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 21 Aug 2014 03:39:11 +0000
Subject: [PATCH] grub2-btrfs-05-grub2-mkconfig
Signed-off-by: Michael Chang <mchang@suse.com>
---
util/grub-mkconfig.in | 3 ++-
util/grub-mkconfig_lib.in | 4 ++++
util/grub.d/00_header.in | 25 ++++++++++++++++++++++++-
util/grub.d/10_linux.in | 4 ++++
util/grub.d/20_linux_xen.in | 4 ++++
5 files changed, 38 insertions(+), 2 deletions(-)
diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
index 6247a0ba850..4649e92eb0f 100644
--- a/util/grub-mkconfig.in
+++ b/util/grub-mkconfig.in
@@ -258,7 +258,8 @@ export GRUB_DEFAULT \
GRUB_BADRAM \
GRUB_OS_PROBER_SKIP_LIST \
GRUB_DISABLE_SUBMENU \
- GRUB_DEFAULT_DTB
+ GRUB_DEFAULT_DTB \
+ SUSE_BTRFS_SNAPSHOT_BOOTING
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 113a41f9409..b3aae534ddc 100644
--- a/util/grub-mkconfig_lib.in
+++ b/util/grub-mkconfig_lib.in
@@ -52,7 +52,11 @@ grub_warn ()
make_system_path_relative_to_its_root ()
{
+ if [ "x${SUSE_BTRFS_SNAPSHOT_BOOTING}" = "xtrue" ] ; then
+ "${grub_mkrelpath}" -r "$1"
+ else
"${grub_mkrelpath}" "$1"
+ fi
}
is_path_readable_by_grub ()
diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in
index 858b526c925..de727e6ee6b 100644
--- a/util/grub.d/00_header.in
+++ b/util/grub.d/00_header.in
@@ -27,6 +27,14 @@ export TEXTDOMAINDIR="@localedir@"
. "$pkgdatadir/grub-mkconfig_lib"
+if [ "x${SUSE_BTRFS_SNAPSHOT_BOOTING}" = "xtrue" ] &&
+ [ "x${GRUB_FS}" = "xbtrfs" ] ; then
+ cat <<EOF
+set btrfs_relative_path="y"
+export btrfs_relative_path
+EOF
+fi
+
# Do this as early as possible, since other commands might depend on it.
# (e.g. the `loadfont' command might need lvm or raid modules)
for i in ${GRUB_PRELOAD_MODULES} ; do
@@ -45,7 +53,9 @@ if [ "x${GRUB_TIMEOUT_BUTTON}" = "x" ] ; then GRUB_TIMEOUT_BUTTON="$GRUB_TIMEOUT
cat << EOF
set pager=1
-if [ -s \$prefix/grubenv ]; then
+if [ -f \${config_directory}/grubenv ]; then
+ load_env -f \${config_directory}/grubenv
+elif [ -s \$prefix/grubenv ]; then
load_env
fi
EOF
@@ -356,3 +366,16 @@ fi
if [ "x${GRUB_BADRAM}" != "x" ] ; then
echo "badram ${GRUB_BADRAM}"
fi
+
+if [ "x${SUSE_BTRFS_SNAPSHOT_BOOTING}" = "xtrue" ] &&
+ [ "x${GRUB_ENABLE_BLSCFG}" = "xtrue" ] &&
+ [ "x${GRUB_FS}" = "xbtrfs" ] ; then
+ # Note: No $snapshot_num on *read-only* rollback! (bsc#901487)
+ cat <<EOF
+if [ -n "\$extra_cmdline" ]; then
+ submenu "Bootable snapshot #\$snapshot_num" {
+ menuentry "If OK, run 'snapper rollback' and reboot." { true; }
+ }
+fi
+EOF
+fi
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index 55f4aa783cf..5cab299dc08 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -66,10 +66,14 @@ fi
case x"$GRUB_FS" in
xbtrfs)
+ if [ "x${SUSE_BTRFS_SNAPSHOT_BOOTING}" = "xtrue" ]; then
+ GRUB_CMDLINE_LINUX="${GRUB_CMDLINE_LINUX} \${extra_cmdline}"
+ else
rootsubvol="`make_system_path_relative_to_its_root /`"
rootsubvol="${rootsubvol#/}"
if [ "x${rootsubvol}" != x ]; 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`
diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in
index 47e0d3f5cd6..1519ec692fe 100644
--- a/util/grub.d/20_linux_xen.in
+++ b/util/grub.d/20_linux_xen.in
@@ -73,10 +73,14 @@ fi
case x"$GRUB_FS" in
xbtrfs)
+ if [ "x${SUSE_BTRFS_SNAPSHOT_BOOTING}" = "xtrue" ]; then
+ GRUB_CMDLINE_LINUX="${GRUB_CMDLINE_LINUX} \${extra_cmdline}"
+ else
rootsubvol="`make_system_path_relative_to_its_root /`"
rootsubvol="${rootsubvol#/}"
if [ "x${rootsubvol}" != x ]; 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`

View File

@ -0,0 +1,537 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Tue, 9 Jul 2019 13:56:16 +0200
Subject: [PATCH] grub2-btrfs-06-subvol-mount
---
grub-core/fs/btrfs.c | 195 +++++++++++++++++++++++++++++++++++++++-
grub-core/osdep/linux/getroot.c | 148 +++++++++++++++++++++++++++++-
util/grub-install.c | 49 ++++++++++
include/grub/emu/getroot.h | 5 ++
4 files changed, 392 insertions(+), 5 deletions(-)
diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
index 2db89f71ea5..162723423ca 100644
--- a/grub-core/fs/btrfs.c
+++ b/grub-core/fs/btrfs.c
@@ -41,6 +41,7 @@
#include <grub/command.h>
#include <grub/env.h>
#include <grub/extcmd.h>
+#include <grub/list.h>
#include <grub/crypto.h>
#include <grub/diskfilter.h>
@@ -263,6 +264,12 @@ static grub_err_t
grub_btrfs_read_logical (struct grub_btrfs_data *data,
grub_disk_addr_t addr, void *buf, grub_size_t size,
int recursion_depth);
+static grub_err_t
+get_root (struct grub_btrfs_data *data, struct grub_btrfs_key *key,
+ grub_uint64_t *tree, grub_uint8_t *type);
+
+grub_uint64_t
+find_mtab_subvol_tree (const char *path, char **path_in_subvol);
static grub_err_t
read_sblock (grub_disk_t disk, struct grub_btrfs_superblock *sb)
@@ -1203,9 +1210,26 @@ lookup_root_by_name(struct grub_btrfs_data *data, const char *path)
grub_err_t err;
grub_uint64_t tree = 0;
grub_uint8_t type;
+ grub_uint64_t saved_tree;
struct grub_btrfs_key key;
+ if (path[0] == '\0')
+ {
+ data->fs_tree = 0;
+ return GRUB_ERR_NONE;
+ }
+
+ err = get_root (data, &key, &tree, &type);
+ if (err)
+ return err;
+
+ saved_tree = data->fs_tree;
+ data->fs_tree = tree;
+
err = find_path (data, path, &key, &tree, &type);
+
+ data->fs_tree = saved_tree;
+
if (err)
return grub_error(GRUB_ERR_FILE_NOT_FOUND, "couldn't locate %s\n", path);
@@ -2179,11 +2203,20 @@ grub_btrfs_dir (grub_device_t device, const char *path,
int r = 0;
grub_uint64_t tree;
grub_uint8_t type;
+ char *new_path = NULL;
if (!data)
return grub_errno;
- err = find_path (data, path, &key_in, &tree, &type);
+ tree = find_mtab_subvol_tree (path, &new_path);
+
+ if (tree)
+ data->fs_tree = tree;
+
+ err = find_path (data, new_path ? new_path : path, &key_in, &tree, &type);
+ if (new_path)
+ grub_free (new_path);
+
if (err)
{
grub_btrfs_unmount (data);
@@ -2285,11 +2318,21 @@ grub_btrfs_open (struct grub_file *file, const char *name)
struct grub_btrfs_inode inode;
grub_uint8_t type;
struct grub_btrfs_key key_in;
+ grub_uint64_t tree;
+ char *new_path = NULL;
if (!data)
return grub_errno;
- err = find_path (data, name, &key_in, &data->tree, &type);
+ tree = find_mtab_subvol_tree (name, &new_path);
+
+ if (tree)
+ data->fs_tree = tree;
+
+ err = find_path (data, new_path ? new_path : name, &key_in, &data->tree, &type);
+ if (new_path)
+ grub_free (new_path);
+
if (err)
{
grub_btrfs_unmount (data);
@@ -2460,6 +2503,150 @@ grub_cmd_btrfs_info (grub_command_t cmd __attribute__ ((unused)), int argc,
return 0;
}
+struct grub_btrfs_mtab
+{
+ struct grub_btrfs_mtab *next;
+ struct grub_btrfs_mtab **prev;
+ char *path;
+ char *subvol;
+ grub_uint64_t tree;
+};
+
+typedef struct grub_btrfs_mtab* grub_btrfs_mtab_t;
+
+static struct grub_btrfs_mtab *btrfs_mtab;
+
+#define FOR_GRUB_MTAB(var) FOR_LIST_ELEMENTS (var, btrfs_mtab)
+#define FOR_GRUB_MTAB_SAFE(var, next) FOR_LIST_ELEMENTS_SAFE((var), (next), btrfs_mtab)
+
+static void
+add_mountpoint (const char *path, const char *subvol, grub_uint64_t tree)
+{
+ grub_btrfs_mtab_t m = grub_malloc (sizeof (*m));
+
+ m->path = grub_strdup (path);
+ m->subvol = grub_strdup (subvol);
+ m->tree = tree;
+ grub_list_push (GRUB_AS_LIST_P (&btrfs_mtab), GRUB_AS_LIST (m));
+}
+
+static grub_err_t
+grub_cmd_btrfs_mount_subvol (grub_command_t cmd __attribute__ ((unused)), int argc,
+ char **argv)
+{
+ char *devname, *dirname, *subvol;
+ struct grub_btrfs_key key_in;
+ grub_uint8_t type;
+ grub_uint64_t tree;
+ grub_uint64_t saved_tree;
+ grub_err_t err;
+ struct grub_btrfs_data *data = NULL;
+ grub_device_t dev = NULL;
+
+ if (argc < 3)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "required <dev> <dir> and <subvol>");
+
+ devname = grub_file_get_device_name(argv[0]);
+ dev = grub_device_open (devname);
+ grub_free (devname);
+
+ if (!dev)
+ {
+ err = grub_errno;
+ goto err_out;
+ }
+
+ dirname = argv[1];
+ subvol = argv[2];
+
+ data = grub_btrfs_mount (dev);
+ if (!data)
+ {
+ err = grub_errno;
+ goto err_out;
+ }
+
+ err = find_path (data, dirname, &key_in, &tree, &type);
+ if (err)
+ goto err_out;
+
+ if (type != GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY)
+ {
+ err = grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
+ goto err_out;
+ }
+
+ err = get_root (data, &key_in, &tree, &type);
+
+ if (err)
+ goto err_out;
+
+ saved_tree = data->fs_tree;
+ data->fs_tree = tree;
+ err = find_path (data, subvol, &key_in, &tree, &type);
+ data->fs_tree = saved_tree;
+
+ if (err)
+ goto err_out;
+
+ if (key_in.object_id != grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK) || tree == 0)
+ {
+ err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "%s: not a subvolume\n", subvol);
+ goto err_out;
+ }
+
+ grub_btrfs_unmount (data);
+ grub_device_close (dev);
+ add_mountpoint (dirname, subvol, tree);
+
+ return GRUB_ERR_NONE;
+
+err_out:
+
+ if (data)
+ grub_btrfs_unmount (data);
+
+ if (dev)
+ grub_device_close (dev);
+
+ return err;
+}
+
+grub_uint64_t
+find_mtab_subvol_tree (const char *path, char **path_in_subvol)
+{
+ grub_btrfs_mtab_t m, cm;
+ grub_uint64_t tree;
+
+ if (!path || !path_in_subvol)
+ return 0;
+
+ *path_in_subvol = NULL;
+ tree = 0;
+ cm = NULL;
+
+ FOR_GRUB_MTAB (m)
+ {
+ if (grub_strncmp (path, m->path, grub_strlen (m->path)) == 0)
+ {
+ if (!cm)
+ cm = m;
+ else
+ if (grub_strcmp (m->path, cm->path) > 0)
+ cm = m;
+ }
+ }
+
+ if (cm)
+ {
+ const char *s = path + grub_strlen (cm->path);
+ *path_in_subvol = (s[0] == '\0') ? grub_strdup ("/") : grub_strdup (s);
+ tree = cm->tree;
+ }
+
+ return tree;
+}
+
static grub_err_t
get_fs_root(struct grub_btrfs_data *data, grub_uint64_t tree,
grub_uint64_t objectid, grub_uint64_t offset,
@@ -2666,6 +2853,7 @@ static struct grub_fs grub_btrfs_fs = {
};
static grub_command_t cmd_info;
+static grub_command_t cmd_mount_subvol;
static grub_extcmd_t cmd_list_subvols;
static char *
@@ -2729,6 +2917,9 @@ GRUB_MOD_INIT (btrfs)
cmd_info = grub_register_command("btrfs-info", grub_cmd_btrfs_info,
"DEVICE",
"Print BtrFS info about DEVICE.");
+ cmd_mount_subvol = grub_register_command("btrfs-mount-subvol", grub_cmd_btrfs_mount_subvol,
+ "DEVICE DIRECTORY SUBVOL",
+ "Set btrfs DEVICE the DIRECTORY a mountpoint of SUBVOL.");
cmd_list_subvols = grub_register_extcmd("btrfs-list-subvols",
grub_cmd_btrfs_list_subvols, 0,
"[-p|-n] [-o var] DEVICE",
diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c
index 5d50dd6f8dc..4c5a13022dc 100644
--- a/grub-core/osdep/linux/getroot.c
+++ b/grub-core/osdep/linux/getroot.c
@@ -107,6 +107,14 @@ struct btrfs_ioctl_search_key
grub_uint32_t unused[9];
};
+struct btrfs_ioctl_search_header {
+ grub_uint64_t transid;
+ grub_uint64_t objectid;
+ grub_uint64_t offset;
+ grub_uint32_t type;
+ grub_uint32_t len;
+};
+
struct btrfs_ioctl_search_args {
struct btrfs_ioctl_search_key key;
grub_uint64_t buf[(4096 - sizeof(struct btrfs_ioctl_search_key))
@@ -378,6 +386,109 @@ get_btrfs_fs_prefix (const char *mount_path)
int use_relative_path_on_btrfs = 0;
+static char *
+get_btrfs_subvol (const char *path)
+{
+ struct btrfs_ioctl_ino_lookup_args args;
+ grub_uint64_t tree_id;
+ int fd = -1;
+ char *ret = NULL;
+
+ fd = open (path, O_RDONLY);
+
+ if (fd < 0)
+ return NULL;
+
+ memset (&args, 0, sizeof(args));
+ args.objectid = GRUB_BTRFS_TREE_ROOT_OBJECTID;
+
+ if (ioctl (fd, BTRFS_IOC_INO_LOOKUP, &args) < 0)
+ goto error;
+
+ tree_id = args.treeid;
+
+ while (tree_id != GRUB_BTRFS_ROOT_VOL_OBJECTID)
+ {
+ struct btrfs_ioctl_search_args sargs;
+ struct grub_btrfs_root_backref *br;
+ struct btrfs_ioctl_search_header *search_header;
+ char *old;
+ grub_uint16_t len;
+ grub_uint64_t inode_id;
+
+ memset (&sargs, 0, sizeof(sargs));
+
+ sargs.key.tree_id = 1;
+ sargs.key.min_objectid = tree_id;
+ sargs.key.max_objectid = tree_id;
+
+ sargs.key.min_offset = 0;
+ sargs.key.max_offset = ~0ULL;
+ sargs.key.min_transid = 0;
+ sargs.key.max_transid = ~0ULL;
+ sargs.key.min_type = GRUB_BTRFS_ITEM_TYPE_ROOT_BACKREF;
+ sargs.key.max_type = GRUB_BTRFS_ITEM_TYPE_ROOT_BACKREF;
+
+ sargs.key.nr_items = 1;
+
+ if (ioctl (fd, BTRFS_IOC_TREE_SEARCH, &sargs) < 0)
+ goto error;
+
+ if (sargs.key.nr_items == 0)
+ goto error;
+
+ search_header = (struct btrfs_ioctl_search_header *)sargs.buf;
+ br = (struct grub_btrfs_root_backref *) (search_header + 1);
+
+ len = grub_le_to_cpu16 (br->n);
+ inode_id = grub_le_to_cpu64 (br->inode_id);
+ tree_id = search_header->offset;
+
+ old = ret;
+ ret = malloc (len + 1);
+ memcpy (ret, br->name, len);
+ ret[len] = '\0';
+
+ if (inode_id != GRUB_BTRFS_TREE_ROOT_OBJECTID)
+ {
+ char *s;
+
+ memset(&args, 0, sizeof(args));
+ args.treeid = search_header->offset;
+ args.objectid = inode_id;
+
+ if (ioctl (fd, BTRFS_IOC_INO_LOOKUP, &args) < 0)
+ goto error;
+
+ s = xasprintf ("%s%s", args.name, ret);
+ free (ret);
+ ret = s;
+ }
+
+ if (old)
+ {
+ char *s = xasprintf ("%s/%s", ret, old);
+ free (ret);
+ free (old);
+ ret = s;
+ }
+ }
+
+ close (fd);
+ return ret;
+
+error:
+
+ if (fd >= 0)
+ close (fd);
+ if (ret)
+ free (ret);
+
+ return NULL;
+}
+
+void (*grub_find_root_btrfs_mount_path_hook)(const char *mount_path);
+
char **
grub_find_root_devices_from_mountinfo (const char *dir, char **relroot)
{
@@ -519,12 +630,15 @@ again:
else if (grub_strcmp (entries[i].fstype, "btrfs") == 0)
{
ret = grub_find_root_devices_from_btrfs (dir);
- fs_prefix = get_btrfs_fs_prefix (entries[i].enc_path);
if (use_relative_path_on_btrfs)
{
- if (fs_prefix)
- free (fs_prefix);
fs_prefix = xstrdup ("/");
+ if (grub_find_root_btrfs_mount_path_hook)
+ grub_find_root_btrfs_mount_path_hook (entries[i].enc_path);
+ }
+ else
+ {
+ fs_prefix = get_btrfs_fs_prefix (entries[i].enc_path);
}
}
else if (!retry && grub_strcmp (entries[i].fstype, "autofs") == 0)
@@ -1150,6 +1264,34 @@ grub_util_get_grub_dev_os (const char *os_dev)
return grub_dev;
}
+
+char *
+grub_util_get_btrfs_subvol (const char *path, char **mount_path)
+{
+ char *mp = NULL;
+
+ if (mount_path)
+ *mount_path = NULL;
+
+ auto void
+ mount_path_hook (const char *m)
+ {
+ mp = strdup (m);
+ }
+
+ grub_find_root_btrfs_mount_path_hook = mount_path_hook;
+ grub_free (grub_find_root_devices_from_mountinfo (path, NULL));
+ grub_find_root_btrfs_mount_path_hook = NULL;
+
+ if (!mp)
+ return NULL;
+
+ if (mount_path)
+ *mount_path = mp;
+
+ return get_btrfs_subvol (mp);
+}
+
char *
grub_make_system_path_relative_to_its_root_os (const char *path)
{
diff --git a/util/grub-install.c b/util/grub-install.c
index 0e807b09c36..3e718b9e3fb 100644
--- a/util/grub-install.c
+++ b/util/grub-install.c
@@ -1561,6 +1561,55 @@ main (int argc, char *argv[])
prefix_drive = xasprintf ("(%s)", grub_drives[0]);
}
+#ifdef __linux__
+
+ if (config.is_suse_btrfs_snapshot_enabled
+ && grub_strncmp(grub_fs->name, "btrfs", sizeof ("btrfs") - 1) == 0)
+ {
+ char *subvol = NULL;
+ char *mount_path = NULL;
+ char **rootdir_devices = NULL;
+ char *rootdir_path = grub_util_path_concat (2, "/", rootdir);
+
+ if (grub_util_is_directory (rootdir_path))
+ rootdir_devices = grub_guess_root_devices (rootdir_path);
+
+ free (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 (subvol && mount_path)
+ {
+ char *def_subvol;
+
+ def_subvol = grub_util_get_btrfs_subvol ("/", NULL);
+
+ if (def_subvol)
+ {
+ if (!load_cfg_f)
+ load_cfg_f = grub_util_fopen (load_cfg, "wb");
+ have_load_cfg = 1;
+
+ if (grub_strcmp (subvol, def_subvol) != 0)
+ fprintf (load_cfg_f, "btrfs-mount-subvol ($root) %s %s\n", mount_path, subvol);
+ free (def_subvol);
+ }
+ }
+
+ for (curdev = rootdir_devices; *curdev; curdev++)
+ free (*curdev);
+ if (rootdir_devices)
+ free (rootdir_devices);
+ if (subvol)
+ free (subvol);
+ if (mount_path)
+ free (mount_path);
+ }
+
+#endif
+
char mkimage_target[200];
const char *core_name = NULL;
diff --git a/include/grub/emu/getroot.h b/include/grub/emu/getroot.h
index 73fa2d34abb..9c642ae3fe3 100644
--- a/include/grub/emu/getroot.h
+++ b/include/grub/emu/getroot.h
@@ -53,6 +53,11 @@ char **
grub_find_root_devices_from_mountinfo (const char *dir, char **relroot);
#endif
+#ifdef __linux__
+char *
+grub_util_get_btrfs_subvol (const char *path, char **mount_path);
+#endif
+
/* Devmapper functions provided by getroot_devmapper.c. */
void
grub_util_pull_devmapper (const char *os_dev);

View File

@ -0,0 +1,58 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Andrei Borzenkov <arvidjaar@gmail.com>
Date: Tue, 21 Jun 2016 16:44:17 +0000
Subject: [PATCH] Fallback to old subvol name scheme to support old snapshot
config
Ref: bsc#953538
---
grub-core/fs/btrfs.c | 32 +++++++++++++++++++++++++++++++-
1 file changed, 31 insertions(+), 1 deletion(-)
diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
index 162723423ca..69c30e62354 100644
--- a/grub-core/fs/btrfs.c
+++ b/grub-core/fs/btrfs.c
@@ -1240,11 +1240,41 @@ lookup_root_by_name(struct grub_btrfs_data *data, const char *path)
return GRUB_ERR_NONE;
}
+static grub_err_t
+lookup_root_by_name_fallback(struct grub_btrfs_data *data, const char *path)
+{
+ grub_err_t err;
+ grub_uint64_t tree = 0;
+ grub_uint8_t type;
+ struct grub_btrfs_key key;
+
+ err = find_path (data, path, &key, &tree, &type);
+ if (err)
+ return grub_error(GRUB_ERR_FILE_NOT_FOUND, "couldn't locate %s\n", path);
+
+ if (key.object_id != grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK) || tree == 0)
+ return grub_error(GRUB_ERR_BAD_FILE_TYPE, "%s: not a subvolume\n", path);
+
+ data->fs_tree = tree;
+ return GRUB_ERR_NONE;
+}
+
static grub_err_t
btrfs_handle_subvol(struct grub_btrfs_data *data __attribute__ ((unused)))
{
if (btrfs_default_subvol)
- return lookup_root_by_name(data, btrfs_default_subvol);
+ {
+ grub_err_t err;
+ err = lookup_root_by_name(data, btrfs_default_subvol);
+
+ /* Fallback to old schemes */
+ if (err == GRUB_ERR_FILE_NOT_FOUND)
+ {
+ err = GRUB_ERR_NONE;
+ return lookup_root_by_name_fallback(data, btrfs_default_subvol);
+ }
+ return err;
+ }
if (btrfs_default_subvolid)
return lookup_root_by_id(data, btrfs_default_subvolid);

View File

@ -0,0 +1,272 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 11 May 2017 08:56:57 +0000
Subject: [PATCH] Grub not working correctly with btrfs snapshots (bsc#1026511)
---
grub-core/fs/btrfs.c | 238 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 238 insertions(+)
diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
index 69c30e62354..ba99d04f8ed 100644
--- a/grub-core/fs/btrfs.c
+++ b/grub-core/fs/btrfs.c
@@ -2867,6 +2867,238 @@ out:
return 0;
}
+static grub_err_t
+grub_btrfs_get_parent_subvol_path (struct grub_btrfs_data *data,
+ grub_uint64_t child_id,
+ const char *child_path,
+ grub_uint64_t *parent_id,
+ char **path_out)
+{
+ grub_uint64_t fs_root = 0;
+ struct grub_btrfs_key key_in = {
+ .object_id = child_id,
+ .type = GRUB_BTRFS_ITEM_TYPE_ROOT_BACKREF,
+ .offset = 0,
+ }, key_out;
+ struct grub_btrfs_root_ref *ref;
+ char *buf;
+ struct grub_btrfs_leaf_descriptor desc;
+ grub_size_t elemsize;
+ grub_disk_addr_t elemaddr;
+ grub_err_t err;
+ char *parent_path;
+
+ *parent_id = 0;
+ *path_out = 0;
+
+ err = lower_bound(data, &key_in, &key_out, data->sblock.root_tree,
+ &elemaddr, &elemsize, &desc, 0);
+ if (err)
+ return err;
+
+ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_ROOT_BACKREF || elemaddr == 0)
+ next(data, &desc, &elemaddr, &elemsize, &key_out);
+
+ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_ROOT_BACKREF)
+ {
+ free_iterator(&desc);
+ return grub_error(GRUB_ERR_FILE_NOT_FOUND, N_("can't find root backrefs"));
+ }
+
+ buf = grub_malloc(elemsize + 1);
+ if (!buf)
+ {
+ free_iterator(&desc);
+ return grub_errno;
+ }
+
+ err = grub_btrfs_read_logical(data, elemaddr, buf, elemsize, 0);
+ if (err)
+ {
+ grub_free(buf);
+ free_iterator(&desc);
+ return err;
+ }
+
+ buf[elemsize] = 0;
+ ref = (struct grub_btrfs_root_ref *)buf;
+
+ err = get_fs_root(data, data->sblock.root_tree, grub_le_to_cpu64 (key_out.offset),
+ 0, &fs_root);
+ if (err)
+ {
+ grub_free(buf);
+ free_iterator(&desc);
+ return err;
+ }
+
+ find_pathname(data, grub_le_to_cpu64 (ref->dirid), fs_root, ref->name, &parent_path);
+
+ if (child_path)
+ {
+ *path_out = grub_xasprintf ("%s/%s", parent_path, child_path);
+ grub_free (parent_path);
+ }
+ else
+ *path_out = parent_path;
+
+ *parent_id = grub_le_to_cpu64 (key_out.offset);
+
+ grub_free(buf);
+ free_iterator(&desc);
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_btrfs_get_default_subvolume_id (struct grub_btrfs_data *data, grub_uint64_t *id)
+{
+ grub_err_t err;
+ grub_disk_addr_t elemaddr;
+ grub_size_t elemsize;
+ struct grub_btrfs_key key, key_out;
+ struct grub_btrfs_dir_item *direl = NULL;
+ const char *ctoken = "default";
+ grub_size_t ctokenlen = sizeof ("default") - 1;
+
+ *id = 0;
+ key.object_id = data->sblock.root_dir_objectid;
+ key.type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM;
+ key.offset = grub_cpu_to_le64 (~grub_getcrc32c (1, ctoken, ctokenlen));
+ err = lower_bound (data, &key, &key_out, data->sblock.root_tree, &elemaddr, &elemsize,
+ NULL, 0);
+ if (err)
+ return err;
+
+ if (key_cmp (&key, &key_out) != 0)
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file not found"));
+
+ struct grub_btrfs_dir_item *cdirel;
+ direl = grub_malloc (elemsize + 1);
+ err = grub_btrfs_read_logical (data, elemaddr, direl, elemsize, 0);
+ if (err)
+ {
+ grub_free (direl);
+ return err;
+ }
+ for (cdirel = direl;
+ (grub_uint8_t *) cdirel - (grub_uint8_t *) direl
+ < (grub_ssize_t) elemsize;
+ cdirel = (void *) ((grub_uint8_t *) (direl + 1)
+ + grub_le_to_cpu16 (cdirel->n)
+ + grub_le_to_cpu16 (cdirel->m)))
+ {
+ if (ctokenlen == grub_le_to_cpu16 (cdirel->n)
+ && grub_memcmp (cdirel->name, ctoken, ctokenlen) == 0)
+ break;
+ }
+ if ((grub_uint8_t *) cdirel - (grub_uint8_t *) direl
+ >= (grub_ssize_t) elemsize)
+ {
+ grub_free (direl);
+ err = grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file not found"));
+ return err;
+ }
+
+ if (cdirel->key.type != GRUB_BTRFS_ITEM_TYPE_ROOT_ITEM)
+ {
+ grub_free (direl);
+ err = grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file not found"));
+ return err;
+ }
+
+ *id = grub_le_to_cpu64 (cdirel->key.object_id);
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cmd_btrfs_get_default_subvol (struct grub_extcmd_context *ctxt,
+ int argc, char **argv)
+{
+ char *devname;
+ grub_device_t dev;
+ struct grub_btrfs_data *data;
+ grub_err_t err;
+ grub_uint64_t id;
+ char *subvol = NULL;
+ grub_uint64_t subvolid = 0;
+ char *varname = NULL;
+ char *output = NULL;
+ int path_only = ctxt->state[1].set;
+ int num_only = ctxt->state[2].set;
+
+ if (ctxt->state[0].set)
+ varname = ctxt->state[0].arg;
+
+ 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;
+
+ dev = grub_device_open (devname);
+ grub_free (devname);
+ if (!dev)
+ return grub_errno;
+
+ data = grub_btrfs_mount(dev);
+ if (!data)
+ {
+ grub_device_close (dev);
+ grub_dprintf ("btrfs", "failed to open fs\n");
+ grub_errno = GRUB_ERR_NONE;
+ return 0;
+ }
+
+ err = grub_btrfs_get_default_subvolume_id (data, &subvolid);
+ if (err)
+ {
+ grub_btrfs_unmount (data);
+ grub_device_close (dev);
+ return err;
+ }
+
+ id = subvolid;
+ while (id != GRUB_BTRFS_ROOT_VOL_OBJECTID)
+ {
+ grub_uint64_t parent_id;
+ char *path_out;
+
+ err = grub_btrfs_get_parent_subvol_path (data, grub_cpu_to_le64 (id), subvol, &parent_id, &path_out);
+ if (err)
+ {
+ grub_btrfs_unmount (data);
+ grub_device_close (dev);
+ return err;
+ }
+
+ if (subvol)
+ grub_free (subvol);
+ subvol = path_out;
+ id = parent_id;
+ }
+
+ if (num_only && path_only)
+ output = grub_xasprintf ("%"PRIuGRUB_UINT64_T" /%s", subvolid, subvol);
+ else if (num_only)
+ output = grub_xasprintf ("%"PRIuGRUB_UINT64_T, subvolid);
+ else
+ output = grub_xasprintf ("/%s", subvol);
+
+ if (varname)
+ grub_env_set(varname, output);
+ else
+ grub_printf ("%s\n", output);
+
+ grub_free (output);
+ grub_free (subvol);
+
+ grub_btrfs_unmount (data);
+ grub_device_close (dev);
+
+ return GRUB_ERR_NONE;
+}
+
static struct grub_fs grub_btrfs_fs = {
.name = "btrfs",
.fs_dir = grub_btrfs_dir,
@@ -2885,6 +3117,7 @@ static struct grub_fs grub_btrfs_fs = {
static grub_command_t cmd_info;
static grub_command_t cmd_mount_subvol;
static grub_extcmd_t cmd_list_subvols;
+static grub_extcmd_t cmd_get_default_subvol;
static char *
subvolid_set_env (struct grub_env_var *var __attribute__ ((unused)),
@@ -2955,6 +3188,11 @@ GRUB_MOD_INIT (btrfs)
"[-p|-n] [-o var] DEVICE",
"Print list of BtrFS subvolumes on "
"DEVICE.", options);
+ cmd_get_default_subvol = grub_register_extcmd("btrfs-get-default-subvol",
+ grub_cmd_btrfs_get_default_subvol, 0,
+ "[-p|-n] [-o var] DEVICE",
+ "Print default BtrFS subvolume on "
+ "DEVICE.", options);
grub_register_variable_hook ("btrfs_subvol", subvol_get_env,
subvol_set_env);
grub_register_variable_hook ("btrfs_subvolid", subvolid_get_env,

View File

@ -0,0 +1,72 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 1 Jun 2017 09:59:56 -0400
Subject: [PATCH] Add grub_efi_allocate_pool() and grub_efi_free_pool()
wrappers.
Signed-off-by: Peter Jones <pjones@redhat.com>
---
include/grub/efi/efi.h | 36 ++++++++++++++++++++++++++++++++----
1 file changed, 32 insertions(+), 4 deletions(-)
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
index 090c8621066..5e2b479daec 100644
--- a/include/grub/efi/efi.h
+++ b/include/grub/efi/efi.h
@@ -24,6 +24,10 @@
#include <grub/dl.h>
#include <grub/efi/api.h>
+/* Variables. */
+extern grub_efi_system_table_t *EXPORT_VAR(grub_efi_system_table);
+extern grub_efi_handle_t EXPORT_VAR(grub_efi_image_handle);
+
/* Functions. */
void *EXPORT_FUNC(grub_efi_locate_protocol) (grub_efi_guid_t *protocol,
void *registration);
@@ -60,6 +64,33 @@ EXPORT_FUNC(grub_efi_get_memory_map) (grub_efi_uintn_t *memory_map_size,
grub_efi_uintn_t *descriptor_size,
grub_efi_uint32_t *descriptor_version);
void grub_efi_memory_fini (void);
+
+static inline grub_efi_status_t
+__attribute__((__unused__))
+grub_efi_allocate_pool (grub_efi_memory_type_t pool_type,
+ grub_efi_uintn_t buffer_size,
+ void **buffer)
+{
+ grub_efi_boot_services_t *b;
+ grub_efi_status_t status;
+
+ b = grub_efi_system_table->boot_services;
+ status = efi_call_3 (b->allocate_pool, pool_type, buffer_size, buffer);
+ return status;
+}
+
+static inline grub_efi_status_t
+__attribute__((__unused__))
+grub_efi_free_pool (void *buffer)
+{
+ grub_efi_boot_services_t *b;
+ grub_efi_status_t status;
+
+ b = grub_efi_system_table->boot_services;
+ status = efi_call_1 (b->free_pool, buffer);
+ return status;
+}
+
grub_efi_loaded_image_t *EXPORT_FUNC(grub_efi_get_loaded_image) (grub_efi_handle_t image_handle);
void EXPORT_FUNC(grub_efi_print_device_path) (grub_efi_device_path_t *dp);
char *EXPORT_FUNC(grub_efi_get_filename) (grub_efi_device_path_t *dp);
@@ -109,10 +140,7 @@ void grub_efi_init (void);
void grub_efi_fini (void);
void grub_efi_set_prefix (void);
-/* Variables. */
-extern grub_efi_system_table_t *EXPORT_VAR(grub_efi_system_table);
-extern grub_efi_handle_t EXPORT_VAR(grub_efi_image_handle);
-
+/* More variables. */
extern int EXPORT_VAR(grub_efi_is_finished);
struct grub_net_card;

View File

@ -0,0 +1,106 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 1 Jun 2017 10:06:38 -0400
Subject: [PATCH] Use grub_efi_...() memory helpers where reasonable.
This uses grub_efi_allocate_pool(), grub_efi_free_pool(), and
grub_efi_free_pages() instead of open-coded efi_call_N() calls, so we
get more reasonable type checking.
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/loader/efi/chainloader.c | 24 +++++++++---------------
1 file changed, 9 insertions(+), 15 deletions(-)
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
index 5aa3a5dc7dd..3a724a9fcbf 100644
--- a/grub-core/loader/efi/chainloader.c
+++ b/grub-core/loader/efi/chainloader.c
@@ -65,7 +65,7 @@ grub_chainloader_unload (void)
b = grub_efi_system_table->boot_services;
efi_call_1 (b->unload_image, image_handle);
- efi_call_2 (b->free_pages, address, pages);
+ grub_efi_free_pages (address, pages);
grub_free (file_path);
grub_free (cmdline);
@@ -108,7 +108,7 @@ grub_chainloader_boot (void)
}
if (exit_data)
- efi_call_1 (b->free_pool, exit_data);
+ grub_efi_free_pool (exit_data);
grub_loader_unset ();
@@ -506,10 +506,9 @@ grub_efi_get_media_file_path (grub_efi_device_path_t *dp)
static grub_efi_boolean_t
handle_image (void *data, grub_efi_uint32_t datasize)
{
- grub_efi_boot_services_t *b;
grub_efi_loaded_image_t *li, li_bak;
grub_efi_status_t efi_status;
- char *buffer = NULL;
+ void *buffer = NULL;
char *buffer_aligned = NULL;
grub_efi_uint32_t i;
struct grub_pe32_section_table *section;
@@ -520,8 +519,6 @@ handle_image (void *data, grub_efi_uint32_t datasize)
int found_entry_point = 0;
int rc;
- b = grub_efi_system_table->boot_services;
-
rc = read_header (data, datasize, &context);
if (rc < 0)
{
@@ -561,8 +558,8 @@ handle_image (void *data, grub_efi_uint32_t datasize)
grub_dprintf ("chain", "image size is %08"PRIxGRUB_UINT64_T", datasize is %08x\n",
context.image_size, datasize);
- efi_status = efi_call_3 (b->allocate_pool, GRUB_EFI_LOADER_DATA,
- buffer_size, &buffer);
+ efi_status = grub_efi_allocate_pool (GRUB_EFI_LOADER_DATA, buffer_size,
+ &buffer);
if (efi_status != GRUB_EFI_SUCCESS)
{
@@ -794,14 +791,14 @@ handle_image (void *data, grub_efi_uint32_t datasize)
grub_dprintf ("chain", "entry_point returned %ld\n", efi_status);
grub_memcpy (li, &li_bak, sizeof (grub_efi_loaded_image_t));
- efi_status = efi_call_1 (b->free_pool, buffer);
+ efi_status = grub_efi_free_pool (buffer);
return 1;
error_exit:
grub_dprintf ("chain", "error_exit: grub_errno: %d\n", grub_errno);
if (buffer)
- efi_call_1 (b->free_pool, buffer);
+ grub_efi_free_pool (buffer);
return 0;
}
@@ -809,10 +806,7 @@ error_exit:
static grub_err_t
grub_secureboot_chainloader_unload (void)
{
- grub_efi_boot_services_t *b;
-
- b = grub_efi_system_table->boot_services;
- efi_call_2 (b->free_pages, address, pages);
+ grub_efi_free_pages (address, pages);
grub_free (file_path);
grub_free (cmdline);
cmdline = 0;
@@ -1079,7 +1073,7 @@ fail:
grub_free (file_path);
if (address)
- efi_call_2 (b->free_pages, address, pages);
+ grub_efi_free_pages (address, pages);
if (cmdline)
grub_free (cmdline);

View File

@ -0,0 +1,46 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 1 Jun 2017 10:07:50 -0400
Subject: [PATCH] Add PRIxGRUB_EFI_STATUS and use it.
This avoids syntax checkers getting confused about if it's llx or lx.
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/loader/efi/chainloader.c | 3 ++-
include/grub/efi/api.h | 8 ++++++++
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
index 3a724a9fcbf..f4ddbeda687 100644
--- a/grub-core/loader/efi/chainloader.c
+++ b/grub-core/loader/efi/chainloader.c
@@ -789,7 +789,8 @@ handle_image (void *data, grub_efi_uint32_t datasize)
efi_status = efi_call_2 (entry_point, grub_efi_image_handle,
grub_efi_system_table);
- grub_dprintf ("chain", "entry_point returned %ld\n", efi_status);
+ grub_dprintf ("chain", "entry_point returned 0x%"PRIxGRUB_EFI_STATUS"\n",
+ efi_status);
grub_memcpy (li, &li_bak, sizeof (grub_efi_loaded_image_t));
efi_status = grub_efi_free_pool (buffer);
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
index d97cdf98c80..955973ed484 100644
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -527,6 +527,14 @@ typedef grub_uint8_t grub_efi_char8_t;
typedef grub_uint16_t grub_efi_char16_t;
typedef grub_efi_intn_t grub_efi_status_t;
+/* Make grub_efi_status_t reasonably printable. */
+#if GRUB_CPU_SIZEOF_VOID_P == 8
+#define PRIxGRUB_EFI_STATUS "lx"
+#define PRIdGRUB_EFI_STATUS "ld"
+#else
+#define PRIxGRUB_EFI_STATUS "llx"
+#define PRIdGRUB_EFI_STATUS "lld"
+#endif
#define GRUB_EFI_ERROR_CODE(value) \
((((grub_efi_status_t) 1) << (sizeof (grub_efi_status_t) * 8 - 1)) | (value))

View File

@ -0,0 +1,43 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 26 Jun 2017 12:42:57 -0400
Subject: [PATCH] Don't use dynamic sized arrays since we don't build with
-std=c99
---
grub-core/net/net.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
index f24f1fd63f6..5366e443d2a 100644
--- a/grub-core/net/net.c
+++ b/grub-core/net/net.c
@@ -1853,14 +1853,25 @@ grub_net_search_configfile (char *config)
{
/* By the Client UUID. */
- char client_uuid_var[sizeof ("net_") + grub_strlen (inf->name) +
- sizeof ("_clientuuid") + 1];
- grub_snprintf (client_uuid_var, sizeof (client_uuid_var),
+ char *client_uuid_var;
+ grub_size_t client_uuid_var_size;
+
+ client_uuid_var_size = grub_snprintf (NULL, 0,
+ "net_%s_clientuuid", inf->name);
+ if (client_uuid_var_size <= 0)
+ continue;
+ client_uuid_var_size += 1;
+ client_uuid_var = grub_malloc(client_uuid_var_size);
+ if (!client_uuid_var)
+ continue;
+ grub_snprintf (client_uuid_var, client_uuid_var_size,
"net_%s_clientuuid", inf->name);
const char *client_uuid;
client_uuid = grub_env_get (client_uuid_var);
+ grub_free(client_uuid_var);
+
if (client_uuid)
{
grub_strcpy (suffix, client_uuid);

View File

@ -0,0 +1,22 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 26 Jun 2017 12:43:22 -0400
Subject: [PATCH] don't ignore const
---
grub-core/net/tftp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
index e6d831f1bc9..0c02a00255b 100644
--- a/grub-core/net/tftp.c
+++ b/grub-core/net/tftp.c
@@ -307,7 +307,7 @@ static void
grub_normalize_filename (char *normalized, const char *filename)
{
char *dest = normalized;
- char *src = filename;
+ const char *src = filename;
while (*src != '\0')
{

View File

@ -0,0 +1,22 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 26 Jun 2017 12:44:59 -0400
Subject: [PATCH] don't use int for efi status
---
grub-core/kern/efi/efi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
index a1af9b46559..2cf6a5ad526 100644
--- a/grub-core/kern/efi/efi.c
+++ b/grub-core/kern/efi/efi.c
@@ -166,7 +166,7 @@ grub_reboot (void)
void
grub_exit (int retval)
{
- int rc = GRUB_EFI_LOAD_ERROR;
+ grub_efi_status_t rc = GRUB_EFI_LOAD_ERROR;
if (retval == 0)
rc = GRUB_EFI_SUCCESS;

View File

@ -0,0 +1,29 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 26 Jun 2017 12:46:23 -0400
Subject: [PATCH] make GRUB_MOD_INIT() declare its function prototypes.
---
include/grub/dl.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/include/grub/dl.h b/include/grub/dl.h
index f03c03561a1..90dc9bb1017 100644
--- a/include/grub/dl.h
+++ b/include/grub/dl.h
@@ -54,6 +54,7 @@ grub_mod_fini (void)
#define GRUB_MOD_INIT(name) \
static void grub_mod_init (grub_dl_t mod __attribute__ ((unused))) __attribute__ ((used)); \
+extern void grub_##name##_init (void); \
void \
grub_##name##_init (void) { grub_mod_init (0); } \
static void \
@@ -61,6 +62,7 @@ grub_mod_init (grub_dl_t mod __attribute__ ((unused)))
#define GRUB_MOD_FINI(name) \
static void grub_mod_fini (void) __attribute__ ((used)); \
+extern void grub_##name##_fini (void); \
void \
grub_##name##_fini (void) { grub_mod_fini (); } \
static void \

View File

@ -0,0 +1,50 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jonathan Lebon <jlebon@redhat.com>
Date: Mon, 14 Aug 2017 14:37:20 -0400
Subject: [PATCH] editenv: handle relative symlinks
Handle symlinks with targets relative to the containing dir. This
ensures that the rename operation does not depend on the cwd.
Resolves: rhbz#1479960
Signed-off-by: Jonathan Lebon <jlebon@redhat.com>
---
util/editenv.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/util/editenv.c b/util/editenv.c
index e61dc1283a4..1f7f6f3ae18 100644
--- a/util/editenv.c
+++ b/util/editenv.c
@@ -28,6 +28,7 @@
#include <errno.h>
#include <string.h>
+#include <libgen.h>
#define DEFAULT_ENVBLK_SIZE 1024
@@ -88,9 +89,20 @@ grub_util_create_envblk_file (const char *name)
continue;
}
- free (rename_target);
linkbuf[retsize] = '\0';
- rename_target = linkbuf;
+ if (linkbuf[0] == '/')
+ {
+ free (rename_target);
+ rename_target = linkbuf;
+ }
+ else
+ {
+ char *dbuf = xstrdup (rename_target);
+ const char *dir = dirname (dbuf);
+ free (rename_target);
+ rename_target = xasprintf("%s/%s", dir, linkbuf);
+ free (dbuf);
+ }
}
int rc = grub_util_rename (namenew, rename_target);

View File

@ -0,0 +1,45 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Wed, 23 Aug 2017 10:37:27 -0400
Subject: [PATCH] Make libgrub.pp depend on config-util.h
If you build with "make -j48" a lot, sometimes you see:
gcc -E -DHAVE_CONFIG_H -I. -I.. -Wall -W -DGRUB_UTIL=1 -D_FILE_OFFSET_BITS=64 -I./include -DGRUB_FILE=\"grub_script.tab.h\" -I. -I.. -I. -I.. -I../include -I./include -I../grub-core/lib/libgcrypt-grub/src/ -I../grub-core/lib/minilzo -I../grub-core/lib/xzembed -DMINILZO_HAVE_CONFIG_H -Wall -W -DGRUB_UTIL=1 -D_FILE_OFFSET_BITS=64 -I./include -DGRUB_FILE=\"grub_script.tab.h\" -I. -I.. -I. -I.. -I../include -I./include -I../grub-core/lib/libgcrypt-grub/src/ -I./grub-core/gnulib -I../grub-core/gnulib -I/builddir/build/BUILD/grub-2.02/grub-aarch64-efi-2.02 -D_FILE_OFFSET_BITS=64 \
-D'GRUB_MOD_INIT(x)=@MARKER@x@' grub_script.tab.h grub_script.yy.h ../grub-core/commands/blocklist.c ../grub-core/commands/macbless.c ../grub-core/commands/xnu_uuid.c ../grub-core/commands/testload.c ../grub-core/commands/ls.c ../grub-core/disk/dmraid_nvidia.c ../grub-core/disk/loopback.c ../grub-core/disk/lvm.c ../grub-core/disk/mdraid_linux.c ../grub-core/disk/mdraid_linux_be.c ../grub-core/disk/mdraid1x_linux.c ../grub-core/disk/raid5_recover.c ../grub-core/disk/raid6_recover.c ../grub-core/font/font.c ../grub-core/gfxmenu/font.c ../grub-core/normal/charset.c ../grub-core/video/fb/fbblit.c ../grub-core/video/fb/fbutil.c ../grub-core/video/fb/fbfill.c ../grub-core/video/fb/video_fb.c ../grub-core/video/video.c ../grub-core/video/capture.c ../grub-core/video/colors.c ../grub-core/unidata.c ../grub-core/io/bufio.c ../grub-core/fs/affs.c ../grub-core/fs/afs.c ../grub-core/fs/bfs.c ../grub-core/fs/btrfs.c ../grub-core/fs/cbfs.c ../grub-core/fs/cpio.c ../grub-core/fs/cpio_be.c ../grub-core/fs/odc.c ../grub-core/fs/newc.c ../grub-core/fs/ext2.c ../grub-core/fs/fat.c ../grub-core/fs/exfat.c ../grub-core/fs/fshelp.c ../grub-core/fs/hfs.c ../grub-core/fs/hfsplus.c ../grub-core/fs/hfspluscomp.c ../grub-core/fs/iso9660.c ../grub-core/fs/jfs.c ../grub-core/fs/minix.c ../grub-core/fs/minix2.c ../grub-core/fs/minix3.c ../grub-core/fs/minix_be.c ../grub-core/fs/minix2_be.c ../grub-core/fs/minix3_be.c ../grub-core/fs/nilfs2.c ../grub-core/fs/ntfs.c ../grub-core/fs/ntfscomp.c ../grub-core/fs/reiserfs.c ../grub-core/fs/romfs.c ../grub-core/fs/sfs.c ../grub-core/fs/squash4.c ../grub-core/fs/tar.c ../grub-core/fs/udf.c ../grub-core/fs/ufs2.c ../grub-core/fs/ufs.c ../grub-core/fs/ufs_be.c ../grub-core/fs/xfs.c ../grub-core/fs/zfs/zfscrypt.c ../grub-core/fs/zfs/zfs.c ../grub-core/fs/zfs/zfsinfo.c ../grub-core/fs/zfs/zfs_lzjb.c ../grub-core/fs/zfs/zfs_lz4.c ../grub-core/fs/zfs/zfs_sha256.c ../grub-core/fs/zfs/zfs_fletcher.c ../grub-core/lib/envblk.c ../grub-core/lib/hexdump.c ../grub-core/lib/LzFind.c ../grub-core/lib/LzmaEnc.c ../grub-core/lib/crc.c ../grub-core/lib/adler32.c ../grub-core/lib/crc64.c ../grub-core/normal/datetime.c ../grub-core/normal/misc.c ../grub-core/partmap/acorn.c ../grub-core/partmap/amiga.c ../grub-core/partmap/apple.c ../grub-core/partmap/sun.c ../grub-core/partmap/plan.c ../grub-core/partmap/dvh.c ../grub-core/partmap/sunpc.c ../grub-core/partmap/bsdlabel.c ../grub-core/partmap/dfly.c ../grub-core/script/function.c ../grub-core/script/lexer.c ../grub-core/script/main.c ../grub-core/script/script.c ../grub-core/script/argv.c ../grub-core/io/gzio.c ../grub-core/io/xzio.c ../grub-core/io/lzopio.c ../grub-core/kern/ia64/dl_helper.c ../grub-core/kern/arm/dl_helper.c ../grub-core/kern/arm64/dl_helper.c ../grub-core/lib/minilzo/minilzo.c ../grub-core/lib/xzembed/xz_dec_bcj.c ../grub-core/lib/xzembed/xz_dec_lzma2.c ../grub-core/lib/xzembed/xz_dec_stream.c ../util/misc.c ../grub-core/kern/command.c ../grub-core/kern/device.c ../grub-core/kern/disk.c ../grub-core/lib/disk.c ../util/getroot.c ../grub-core/osdep/unix/getroot.c ../grub-core/osdep/getroot.c ../grub-core/osdep/devmapper/getroot.c ../grub-core/osdep/relpath.c ../grub-core/kern/emu/hostdisk.c ../grub-core/osdep/devmapper/hostdisk.c ../grub-core/osdep/hostdisk.c ../grub-core/osdep/unix/hostdisk.c ../grub-core/osdep/exec.c ../grub-core/osdep/sleep.c ../grub-core/osdep/password.c ../grub-core/kern/emu/misc.c ../grub-core/kern/emu/mm.c ../grub-core/kern/env.c ../grub-core/kern/err.c ../grub-core/kern/file.c ../grub-core/kern/fs.c ../grub-core/kern/list.c ../grub-core/kern/misc.c ../grub-core/kern/partition.c ../grub-core/lib/crypto.c ../grub-core/disk/luks.c ../grub-core/disk/geli.c ../grub-core/disk/cryptodisk.c ../grub-core/disk/AFSplitter.c ../grub-core/lib/pbkdf2.c ../grub-core/commands/extcmd.c ../grub-core/lib/arg.c ../grub-core/disk/ldm.c ../grub-core/disk/diskfilter.c ../grub-core/partmap/gpt.c ../grub-core/partmap/msdos.c ../grub-core/fs/proc.c ../grub-core/fs/archelp.c > libgrub.pp || (rm -f libgrub.pp; exit 1)
rm -f stamp-h1
touch ../config-util.h.in
cd . && /bin/sh ./config.status config-util.h
config.status: creating config-util.h
In file included from ../include/grub/mm.h:25:0,
from ../include/grub/disk.h:29,
from ../include/grub/file.h:26,
from ../grub-core/fs/btrfs.c:21:
./config.h:38:10: fatal error: ./config-util.h: No such file or directory
#include <config-util.h>
^~~~~~~~~~~~~~~
compilation terminated.
make: *** [Makefile:13098: libgrub.pp] Error 1
This is because libgrub.pp is built with -DGRUB_UTIL=1, which means
it'll try to include config-util.h, but a parallel make is actually
building that file. I think.
Signed-off-by: Peter Jones <pjones@redhat.com>
---
Makefile.am | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile.am b/Makefile.am
index 1f4bb9b8c5a..bf9c1ba64c9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -37,7 +37,7 @@ grub_script.yy.c: grub_script.yy.h
CLEANFILES += grub_script.yy.c grub_script.yy.h
# For libgrub.a
-libgrub.pp: grub_script.tab.h grub_script.yy.h $(libgrubmods_a_SOURCES) $(libgrubkern_a_SOURCES)
+libgrub.pp: config-util.h grub_script.tab.h grub_script.yy.h $(libgrubmods_a_SOURCES) $(libgrubkern_a_SOURCES)
$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgrubmods_a_CPPFLAGS) $(libgrubkern_a_CPPFLAGS) $(CPPFLAGS) \
-D'GRUB_MOD_INIT(x)=@MARKER@x@' $^ > $@ || (rm -f $@; exit 1)
CLEANFILES += libgrub.pp

View File

@ -0,0 +1,41 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 20 Apr 2017 13:29:06 -0400
Subject: [PATCH] Don't guess /boot/efi/ as HFS+ on ppc machines in
grub-install
This should never be trying this, and since we've consolidated the
grubenv to always be on /boot/efi/EFI/fedora/, this code causes it to
always make the wrong decision.
Resolves: rhbz#1484474
Signed-off-by: Peter Jones <pjones@redhat.com>
---
util/grub-install.c | 12 +-----------
1 file changed, 1 insertion(+), 11 deletions(-)
diff --git a/util/grub-install.c b/util/grub-install.c
index 3e718b9e3fb..37fcdac12cc 100644
--- a/util/grub-install.c
+++ b/util/grub-install.c
@@ -1182,18 +1182,8 @@ main (int argc, char *argv[])
char *d;
is_guess = 1;
- d = grub_util_path_concat (2, bootdir, "macppc");
- if (!grub_util_is_directory (d))
- {
- free (d);
- d = grub_util_path_concat (2, bootdir, "efi");
- }
/* Find the Mac HFS(+) System Partition. */
- if (!grub_util_is_directory (d))
- {
- free (d);
- d = grub_util_path_concat (2, bootdir, "EFI");
- }
+ d = grub_util_path_concat (2, bootdir, "macppc");
if (!grub_util_is_directory (d))
{
free (d);

View File

@ -0,0 +1,31 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Tue, 9 Jul 2019 14:31:19 +0200
Subject: [PATCH] 20_linux_xen: load xen or multiboot{,2} modules as needed.
Signed-off-by: Peter Jones <pjones@redhat.com>
---
util/grub.d/20_linux_xen.in | 3 +++
1 file changed, 3 insertions(+)
diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in
index 1519ec692fe..9aa23bc7d51 100644
--- a/util/grub.d/20_linux_xen.in
+++ b/util/grub.d/20_linux_xen.in
@@ -136,6 +136,8 @@ linux_entry ()
else
xen_rm_opts="no-real-mode edd=off"
fi
+ insmod ${module_loader}
+ insmod ${xen_loader}
${xen_loader} ${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} \${xen_rm_opts}
echo '$(echo "$lmessage" | grub_quote)'
${module_loader} ${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args}
@@ -149,6 +151,7 @@ EOF
done
sed "s/^/$submenu_indentation/" << EOF
echo '$(echo "$message" | grub_quote)'
+ insmod ${module_loader}
${module_loader} --nounzip $(echo $initrd_path)
EOF
fi

View File

@ -0,0 +1,211 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Tue, 7 Nov 2017 17:12:17 -0500
Subject: [PATCH] Make pmtimer tsc calibration not take 51 seconds to fail.
On my laptop running at 2.4GHz, if I run a VM where tsc calibration
using pmtimer will fail presuming a broken pmtimer, it takes ~51 seconds
to do so (as measured with the stopwatch on my phone), with a tsc delta
of 0x1cd1c85300, or around 125 billion cycles.
If instead of trying to wait for 5-200ms to show up on the pmtimer, we try
to wait for 5-200us, it decides it's broken in ~0x2626aa0 TSCs, aka ~2.4
million cycles, or more or less instantly.
Additionally, this reading the pmtimer was returning 0xffffffff anyway,
and that's obviously an invalid return. I've added a check for that and
0 so we don't bother waiting for the test if what we're seeing is dead
pins with no response at all.
If "debug" is includes "pmtimer", you will see one of the following
three outcomes. If pmtimer gives all 0 or all 1 bits, you will see:
kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 1
kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 2
kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 3
kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 4
kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 5
kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 6
kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 7
kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 8
kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 9
kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 10
kern/i386/tsc_pmtimer.c:78: timer is broken; giving up.
This outcome was tested using qemu+kvm with UEFI (OVMF) firmware and
these options: -machine pc-q35-2.10 -cpu Broadwell-noTSX
If pmtimer gives any other bit patterns but is not actually marching
forward fast enough to use for clock calibration, you will see:
kern/i386/tsc_pmtimer.c:121: pmtimer delta is 0x0 (1904 iterations)
kern/i386/tsc_pmtimer.c:124: tsc delta is implausible: 0x2626aa0
This outcome was tested using grub compiled with GRUB_PMTIMER_IGNORE_BAD_READS
defined (so as not to trip the bad read test) using qemu+kvm with UEFI
(OVMF) firmware, and these options: -machine pc-q35-2.10 -cpu Broadwell-noTSX
If pmtimer actually works, you'll see something like:
kern/i386/tsc_pmtimer.c:121: pmtimer delta is 0x0 (1904 iterations)
kern/i386/tsc_pmtimer.c:124: tsc delta is implausible: 0x2626aa0
This outcome was tested using qemu+kvm with UEFI (OVMF) firmware, and
these options: -machine pc-i440fx-2.4 -cpu Broadwell-noTSX
I've also tested this outcome on a real Intel Xeon E3-1275v3 on an Intel
Server Board S1200V3RPS using the SDV.RP.B8 "Release" build here:
https://firmware.intel.com/sites/default/files/UEFIDevKit_S1200RP_vB8.zip
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/kern/i386/tsc_pmtimer.c | 109 +++++++++++++++++++++++++++++++-------
1 file changed, 89 insertions(+), 20 deletions(-)
diff --git a/grub-core/kern/i386/tsc_pmtimer.c b/grub-core/kern/i386/tsc_pmtimer.c
index c9c36169978..ca15c3aacd7 100644
--- a/grub-core/kern/i386/tsc_pmtimer.c
+++ b/grub-core/kern/i386/tsc_pmtimer.c
@@ -28,40 +28,101 @@
#include <grub/acpi.h>
#include <grub/cpu/io.h>
+/*
+ * Define GRUB_PMTIMER_IGNORE_BAD_READS if you're trying to test a timer that's
+ * present but doesn't keep time well.
+ */
+// #define GRUB_PMTIMER_IGNORE_BAD_READS
+
grub_uint64_t
grub_pmtimer_wait_count_tsc (grub_port_t pmtimer,
grub_uint16_t num_pm_ticks)
{
grub_uint32_t start;
- grub_uint32_t last;
- grub_uint32_t cur, end;
+ grub_uint64_t cur, end;
grub_uint64_t start_tsc;
grub_uint64_t end_tsc;
- int num_iter = 0;
+ unsigned int num_iter = 0;
+#ifndef GRUB_PMTIMER_IGNORE_BAD_READS
+ int bad_reads = 0;
+#endif
- start = grub_inl (pmtimer) & 0xffffff;
- last = start;
+ /*
+ * Some timers are 24-bit and some are 32-bit, but it doesn't make much
+ * difference to us. Caring which one we have isn't really worth it since
+ * the low-order digits will give us enough data to calibrate TSC. So just
+ * mask the top-order byte off.
+ */
+ cur = start = grub_inl (pmtimer) & 0xffffffUL;
end = start + num_pm_ticks;
start_tsc = grub_get_tsc ();
while (1)
{
- cur = grub_inl (pmtimer) & 0xffffff;
- if (cur < last)
- cur |= 0x1000000;
- num_iter++;
+ cur &= 0xffffffffff000000ULL;
+ cur |= grub_inl (pmtimer) & 0xffffffUL;
+
+ end_tsc = grub_get_tsc();
+
+#ifndef GRUB_PMTIMER_IGNORE_BAD_READS
+ /*
+ * If we get 10 reads in a row that are obviously dead pins, there's no
+ * reason to do this thousands of times.
+ */
+ if (cur == 0xffffffUL || cur == 0)
+ {
+ bad_reads++;
+ grub_dprintf ("pmtimer",
+ "pmtimer: 0x%"PRIxGRUB_UINT64_T" bad_reads: %d\n",
+ cur, bad_reads);
+ grub_dprintf ("pmtimer", "timer is broken; giving up.\n");
+
+ if (bad_reads == 10)
+ return 0;
+ }
+#endif
+
+ if (cur < start)
+ cur += 0x1000000;
+
if (cur >= end)
{
- end_tsc = grub_get_tsc ();
+ grub_dprintf ("pmtimer", "pmtimer delta is 0x%"PRIxGRUB_UINT64_T"\n",
+ cur - start);
+ grub_dprintf ("pmtimer", "tsc delta is 0x%"PRIxGRUB_UINT64_T"\n",
+ end_tsc - start_tsc);
return end_tsc - start_tsc;
}
- /* Check for broken PM timer.
- 50000000 TSCs is between 5 ms (10GHz) and 200 ms (250 MHz)
- if after this time we still don't have 1 ms on pmtimer, then
- pmtimer is broken.
+
+ /*
+ * Check for broken PM timer. 1ms at 10GHz should be 1E+7 TSCs; at
+ * 250MHz it should be 2.5E6. So if after 4E+7 TSCs on a 10GHz machine,
+ * we should have seen pmtimer show 4ms of change (i.e. cur =~
+ * start+14320); on a 250MHz machine that should be 16ms (start+57280).
+ * If after this a time we still don't have 1ms on pmtimer, then pmtimer
+ * is broken.
+ *
+ * Likewise, if our code is perfectly efficient and introduces no delays
+ * whatsoever, on a 10GHz system we should see a TSC delta of 3580 in
+ * ~3580 iterations. On a 250MHz machine that should be ~900 iterations.
+ *
+ * With those factors in mind, there are two limits here. There's a hard
+ * limit here at 8x our desired pm timer delta, picked as an arbitrarily
+ * large value that's still not a lot of time to humans, because if we
+ * get that far this is either an implausibly fast machine or the pmtimer
+ * is not running. And there's another limit on 4x our 10GHz tsc delta
+ * without seeing cur converge on our target value.
*/
- if ((num_iter & 0xffffff) == 0 && grub_get_tsc () - start_tsc > 5000000) {
- return 0;
- }
+ if ((++num_iter > (grub_uint32_t)num_pm_ticks << 3UL) ||
+ end_tsc - start_tsc > 40000000)
+ {
+ grub_dprintf ("pmtimer",
+ "pmtimer delta is 0x%"PRIxGRUB_UINT64_T" (%u iterations)\n",
+ cur - start, num_iter);
+ grub_dprintf ("pmtimer",
+ "tsc delta is implausible: 0x%"PRIxGRUB_UINT64_T"\n",
+ end_tsc - start_tsc);
+ return 0;
+ }
}
}
@@ -74,12 +135,20 @@ grub_tsc_calibrate_from_pmtimer (void)
fadt = grub_acpi_find_fadt ();
if (!fadt)
- return 0;
+ {
+ grub_dprintf ("pmtimer", "No FADT found; not using pmtimer.\n");
+ return 0;
+ }
pmtimer = fadt->pmtimer;
if (!pmtimer)
- return 0;
+ {
+ grub_dprintf ("pmtimer", "FADT does not specify pmtimer; skipping.\n");
+ return 0;
+ }
- /* It's 3.579545 MHz clock. Wait 1 ms. */
+ /*
+ * It's 3.579545 MHz clock. Wait 1 ms.
+ */
tsc_diff = grub_pmtimer_wait_count_tsc (pmtimer, 3580);
if (tsc_diff == 0)
return 0;

View File

@ -0,0 +1,33 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Tue, 27 Feb 2018 13:55:35 -0500
Subject: [PATCH] align struct efi_variable better...
---
include/grub/efiemu/runtime.h | 2 +-
include/grub/types.h | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/include/grub/efiemu/runtime.h b/include/grub/efiemu/runtime.h
index 36d2dedf47e..9d93ba88bac 100644
--- a/include/grub/efiemu/runtime.h
+++ b/include/grub/efiemu/runtime.h
@@ -33,5 +33,5 @@ struct efi_variable
grub_uint32_t namelen;
grub_uint32_t size;
grub_efi_uint32_t attributes;
-} GRUB_PACKED;
+} GRUB_PACKED GRUB_ALIGNED(8);
#endif /* ! GRUB_EFI_EMU_RUNTIME_HEADER */
diff --git a/include/grub/types.h b/include/grub/types.h
index 035a4b528fc..2fc4be4039a 100644
--- a/include/grub/types.h
+++ b/include/grub/types.h
@@ -29,6 +29,7 @@
#else
#define GRUB_PACKED __attribute__ ((packed))
#endif
+#define GRUB_ALIGNED(x) __attribute__((aligned (x)))
#ifdef GRUB_BUILD
# define GRUB_CPU_SIZEOF_VOID_P BUILD_SIZEOF_VOID_P

View File

@ -0,0 +1,741 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Fri, 9 Dec 2016 15:40:29 -0500
Subject: [PATCH] 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>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
---
Makefile.util.def | 7 +
util/grub-mkconfig.8 | 4 +
util/grub-mkconfig.in | 9 +-
util/grub-mkconfig_lib.in | 20 +-
util/grub.d/10_linux.in | 67 ++++++-
util/grub.d/10_linux_bls.in | 478 ++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 580 insertions(+), 5 deletions(-)
create mode 100644 util/grub.d/10_linux_bls.in
diff --git a/Makefile.util.def b/Makefile.util.def
index 2215cc759c0..a61613656d1 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -499,6 +499,13 @@ script = {
condition = COND_HOST_LINUX;
};
+script = {
+ name = '10_linux_bls';
+ common = util/grub.d/10_linux_bls.in;
+ installdir = grubconf;
+ condition = COND_HOST_LINUX;
+};
+
script = {
name = '10_xnu';
common = util/grub.d/10_xnu.in;
diff --git a/util/grub-mkconfig.8 b/util/grub-mkconfig.8
index a2d1f577b9b..434fa4deda4 100644
--- a/util/grub-mkconfig.8
+++ b/util/grub-mkconfig.8
@@ -13,5 +13,9 @@
\fB--output\fR=\fIFILE\fR
Write generated output to \fIFILE\fR.
+.TP
+\fB--no-grubenv-update\fR
+Do not update variables in the grubenv file.
+
.SH SEE ALSO
.BR "info grub"
diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
index 4649e92eb0f..2601bdc0711 100644
--- a/util/grub-mkconfig.in
+++ b/util/grub-mkconfig.in
@@ -50,6 +50,8 @@ grub_get_kernel_settings="${sbindir}/@grub_get_kernel_settings@"
export TEXTDOMAIN=@PACKAGE@
export TEXTDOMAINDIR="@localedir@"
+export GRUB_GRUBENV_UPDATE="yes"
+
. "${pkgdatadir}/grub-mkconfig_lib"
# Usage: usage
@@ -59,6 +61,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
@@ -94,6 +97,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
@@ -259,7 +265,8 @@ export GRUB_DEFAULT \
GRUB_OS_PROBER_SKIP_LIST \
GRUB_DISABLE_SUBMENU \
GRUB_DEFAULT_DTB \
- SUSE_BTRFS_SNAPSHOT_BOOTING
+ SUSE_BTRFS_SNAPSHOT_BOOTING \
+ 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 b3aae534ddc..bc11df2bd84 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
@@ -125,8 +128,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='
'
@@ -161,14 +175,14 @@ 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=
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"
fi
IFS="$old_ifs"
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index 5cab299dc08..301594a0c9e 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -82,6 +82,67 @@ case x"$GRUB_FS" in
;;
esac
+populate_header_warn()
+{
+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 blscfg command 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://www.freedesktop.org/wiki/Specifications/BootLoaderSpec/.
+
+EOF
+}
+
+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
+
+ populate_header_warn
+
+ cat << EOF
+set default_kernelopts="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX}"
+
+insmod blscfg
+blscfg
+EOF
+
+ 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
+
+ ${grub_editenv} - set kernelopts="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX}"
+ if [ -n "${GRUB_EARLY_INITRD_LINUX_CUSTOM}" ]; then
+ ${grub_editenv} - set early_initrd="${GRUB_EARLY_INITRD_LINUX_CUSTOM}"
+ fi
+ fi
+
+ exit 0
+fi
+
mktitle ()
{
local title_type
@@ -121,6 +182,7 @@ linux_entry ()
if [ -z "$boot_device_id" ]; then
boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")"
fi
+
if [ x$type != xsimple ] ; then
title=$(mktitle "$type" "$version")
if [ x"$title" = x"$GRUB_ACTUAL_DEFAULT" ] || [ x"Previous Linux versions>$title" = x"$GRUB_ACTUAL_DEFAULT" ]; then
@@ -224,6 +286,7 @@ is_top_level=true
while [ "x$list" != "x" ] ; do
linux=`version_find_latest $list`
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`
@@ -262,7 +325,9 @@ while [ "x$list" != "x" ] ; 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
fdt=
diff --git a/util/grub.d/10_linux_bls.in b/util/grub.d/10_linux_bls.in
new file mode 100644
index 00000000000..1b7536435f1
--- /dev/null
+++ b/util/grub.d/10_linux_bls.in
@@ -0,0 +1,478 @@
+#! /bin/sh
+set -e
+
+# grub-mkconfig helper script.
+# Copyright (C) 2006,2007,2008,2009,2010 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/>.
+
+prefix="@prefix@"
+exec_prefix="@exec_prefix@"
+datarootdir="@datarootdir@"
+
+. "$pkgdatadir/grub-mkconfig_lib"
+
+export TEXTDOMAIN=@PACKAGE@
+export TEXTDOMAINDIR="@localedir@"
+
+CLASS="--class gnu-linux --class gnu --class os --unrestricted"
+
+if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
+ OS="$(eval $(grep PRETTY_NAME /etc/os-release) ; echo ${PRETTY_NAME})"
+ CLASS="--class $(eval $(grep '^ID_LIKE=\|^ID=' /etc/os-release) ; [ -n "${ID_LIKE}" ] && echo ${ID_LIKE} || echo ${ID}) ${CLASS}"
+else
+ OS="${GRUB_DISTRIBUTOR}"
+ CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1|LC_ALL=C sed 's,[^[:alnum:]_],_,g') ${CLASS}"
+fi
+
+# 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
+
+case x"$GRUB_FS" in
+ xbtrfs)
+ if [ "x${SUSE_BTRFS_SNAPSHOT_BOOTING}" = "xtrue" ]; then
+ GRUB_CMDLINE_LINUX="${GRUB_CMDLINE_LINUX} \${extra_cmdline}"
+ else
+ rootsubvol="`make_system_path_relative_to_its_root /`"
+ rootsubvol="${rootsubvol#/}"
+ if [ "x${rootsubvol}" != x ]; 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
+
+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=
+
+populate_header_warn()
+{
+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.
+
+EOF
+}
+
+read_config()
+{
+ config_file=${1}
+ title=""
+ initrd=""
+ options=""
+ linux=""
+ grub_users=""
+ grub_arg=""
+ grub_class=""
+
+ 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_users")
+ grub_users=${value}
+ ;;
+ "grub_arg")
+ grub_arg=${value}
+ ;;
+ "grub_class")
+ grub_class=${value}
+ ;;
+ esac
+ done < ${config_file}
+}
+
+populate_menu()
+{
+ blsdir="/boot/loader/entries"
+ local -a files
+ local IFS=$'\n'
+ gettext_printf "Generating boot entries from BLS files...\n" >&2
+
+ files=($(for bls in ${blsdir}/*.conf ; do
+ if ! [[ -e "${bls}" ]] ; then
+ continue
+ fi
+ bls="${bls%.conf}"
+ bls="${bls##*/}"
+ echo "${bls}"
+ done | ${kernel_sort} | tac)) || :
+
+ for bls in "${files[@]}" ; do
+ read_config "${blsdir}/${bls}.conf"
+
+ menu="${menu}menuentry '${title}' --class ${grub_class} ${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"
+}
+
+linux_entry ()
+{
+ os="$1"
+ version="$2"
+ type="$3"
+ isdebug="$4"
+ args="$5"
+
+ if [ -z "$boot_device_id" ]; then
+ boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")"
+ 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
+
+ populate_header_warn
+ populate_menu
+
+ 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
+
+ ${grub_editenv} - set kernelopts="root=${linux_root_device_thisversion} ro ${args}"
+ if [ -n "${GRUB_EARLY_INITRD_LINUX_CUSTOM}" ]; then
+ ${grub_editenv} - set early_initrd="${GRUB_EARLY_INITRD_LINUX_CUSTOM}"
+ fi
+ fi
+
+ exit 0
+ fi
+
+ if [ x$type != xsimple ] ; then
+ title=$(mktitle "$type" "$version")
+ if [ x"$title" = x"$GRUB_ACTUAL_DEFAULT" ] || [ x"Previous Linux versions>$title" = x"$GRUB_ACTUAL_DEFAULT" ]; then
+ replacement_title="$(echo "Advanced options for ${OS}" | sed 's,>,>>,g')>$(echo "$title" | sed 's,>,>>,g')"
+ quoted="$(echo "$GRUB_ACTUAL_DEFAULT" | grub_quote)"
+ title_correction_code="${title_correction_code}if [ \"x\$default\" = '$quoted' ]; then default='$(echo "$replacement_title" | grub_quote)'; fi;"
+ fi
+ if [ x$isdebug = xdebug ]; then
+ title="$title${GRUB_LINUX_DEBUG_TITLE_POSTFIX}"
+ fi
+ echo "menuentry '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-$version-$type-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
+ else
+ echo "menuentry '$(echo "$os" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
+ fi
+ if [ x$type != xrecovery ] ; then
+ save_default_entry | grub_add_tab
+ fi
+
+ # Use ELILO's generic "efifb" when it's known to be available.
+ # FIXME: We need an interface to select vesafb in case efifb can't be used.
+ if [ "x$GRUB_GFXPAYLOAD_LINUX" = x ]; then
+ echo " load_video" | sed "s/^/$submenu_indentation/"
+ if grep -qx "CONFIG_FB_EFI=y" "${config}" 2> /dev/null \
+ && grep -qx "CONFIG_VT_HW_CONSOLE_BINDING=y" "${config}" 2> /dev/null; then
+ echo " set gfxpayload=keep" | sed "s/^/$submenu_indentation/"
+ fi
+ else
+ if [ "x$GRUB_GFXPAYLOAD_LINUX" != xtext ]; then
+ echo " load_video" | sed "s/^/$submenu_indentation/"
+ fi
+ echo " set gfxpayload=$GRUB_GFXPAYLOAD_LINUX" | sed "s/^/$submenu_indentation/"
+ fi
+
+ echo " insmod gzio" | sed "s/^/$submenu_indentation/"
+
+ if [ x$dirname = x/ ]; then
+ if [ -z "${prepare_root_cache}" ]; then
+ prepare_root_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE} | grub_add_tab)"
+ fi
+ printf '%s\n' "${prepare_root_cache}" | sed "s/^/$submenu_indentation/"
+ else
+ if [ -z "${prepare_boot_cache}" ]; then
+ prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | grub_add_tab)"
+ fi
+ printf '%s\n' "${prepare_boot_cache}" | sed "s/^/$submenu_indentation/"
+ fi
+ sed "s/^/$submenu_indentation/" << EOF
+ linux ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args}
+EOF
+ if test -n "${initrd}" ; then
+ initrd_path=
+ for i in ${initrd}; do
+ initrd_path="${initrd_path} ${rel_dirname}/${i}"
+ done
+ sed "s/^/$submenu_indentation/" << EOF
+ initrd $(echo $initrd_path)
+EOF
+ fi
+ if test -n "${fdt}" ; then
+ sed "s/^/$submenu_indentation/" << EOF
+ devicetree ${rel_dirname}/${fdt}
+EOF
+ fi
+ sed "s/^/$submenu_indentation/" << EOF
+}
+EOF
+}
+
+machine=`uname -m`
+case "x$machine" in
+ xi?86 | xx86_64)
+ list=
+ for i in /boot/vmlinuz-* /vmlinuz-* /boot/kernel-* ; do
+ if grub_file_is_not_garbage "$i" ; then list="$list $i" ; fi
+ done ;;
+ *)
+ list=
+ for i in /boot/vmlinuz-* /boot/vmlinux-* /vmlinuz-* /vmlinux-* /boot/kernel-* ; do
+ if grub_file_is_not_garbage "$i" ; then list="$list $i" ; fi
+ done ;;
+esac
+
+if [ "x${GRUB_ENABLE_BLSCFG}" = "xtrue" ]; then
+ for i in /boot/ostree/*/vmlinuz-* ; do
+ if grub_file_is_not_garbage "$i" ; then list="$list $i" ; fi
+ done
+fi
+
+case "$machine" in
+ i?86) GENKERNEL_ARCH="x86" ;;
+ mips|mips64) GENKERNEL_ARCH="mips" ;;
+ mipsel|mips64el) GENKERNEL_ARCH="mipsel" ;;
+ arm*) GENKERNEL_ARCH="arm" ;;
+ *) GENKERNEL_ARCH="$machine" ;;
+esac
+
+prepare_boot_cache=
+prepare_root_cache=
+boot_device_id=
+title_correction_code=
+
+# Extra indentation to add to menu entries in a submenu. We're not in a submenu
+# yet, so it's empty. In a submenu it will be equal to '\t' (one tab).
+submenu_indentation=""
+
+is_top_level=true
+while [ "x$list" != "x" ] ; do
+ linux=`version_find_latest $list`
+ if [ "x${GRUB_ENABLE_BLSCFG}" != "xtrue" ]; then
+ gettext_printf "Found linux image: %s\n" "$linux" >&2
+ fi
+
+ basename=`basename $linux`
+ dirname=`dirname $linux`
+ rel_dirname=`make_system_path_relative_to_its_root $dirname`
+ version=`echo $basename | sed -e "s,^[^0-9]*-,,g"`
+ alt_version=`echo $version | sed -e "s,\.old$,,g"`
+ linux_root_device_thisversion="${LINUX_ROOT_DEVICE}"
+
+ initrd_early=
+ for i in ${GRUB_EARLY_INITRD_LINUX_STOCK} \
+ ${GRUB_EARLY_INITRD_LINUX_CUSTOM}; do
+ if test -e "${dirname}/${i}" ; then
+ initrd_early="${initrd_early} ${i}"
+ fi
+ done
+
+ initrd_real=
+ for i in "initrd.img-${version}" "initrd-${version}.img" "initrd-${version}.gz" \
+ "initrd-${version}" "initramfs-${version}.img" \
+ "initrd.img-${alt_version}" "initrd-${alt_version}.img" \
+ "initrd-${alt_version}" "initramfs-${alt_version}.img" \
+ "initramfs-genkernel-${version}" \
+ "initramfs-genkernel-${alt_version}" \
+ "initramfs-genkernel-${GENKERNEL_ARCH}-${version}" \
+ "initramfs-genkernel-${GENKERNEL_ARCH}-${alt_version}"; do
+ if test -e "${dirname}/${i}" ; then
+ initrd_real="${i}"
+ break
+ fi
+ done
+
+ initrd=
+ if test -n "${initrd_early}" || test -n "${initrd_real}"; then
+ initrd="${initrd_early} ${initrd_real}"
+
+ initrd_display=
+ for i in ${initrd}; do
+ initrd_display="${initrd_display} ${dirname}/${i}"
+ done
+ if [ "x${GRUB_ENABLE_BLSCFG}" != "xtrue" ]; then
+ gettext_printf "Found initrd image: %s\n" "$(echo $initrd_display)" >&2
+ fi
+ fi
+
+ fdt=
+ for i in "dtb-${version}" "dtb-${alt_version}"; do
+ if test -f "${dirname}/${i}/${GRUB_DEFAULT_DTB}" ; then
+ fdt="${i}/${GRUB_DEFAULT_DTB}"
+ break
+ fi
+ done
+
+ config=
+ for i in "${dirname}/config-${version}" "${dirname}/config-${alt_version}" "/etc/kernels/kernel-config-${version}" ; do
+ if test -e "${i}" ; then
+ config="${i}"
+ break
+ fi
+ done
+
+ initramfs=
+ if test -n "${config}" ; then
+ initramfs=`grep CONFIG_INITRAMFS_SOURCE= "${config}" | cut -f2 -d= | tr -d \"`
+ fi
+
+ if test -z "${initramfs}" && test -z "${initrd_real}" ; then
+ # "UUID=" and "ZFS=" magic is parsed by initrd or initramfs. Since there's
+ # no initrd or builtin initramfs, it can't work here.
+ if [ "x${GRUB_DEVICE_PARTUUID}" = "x" ] \
+ || [ "x${GRUB_DISABLE_LINUX_PARTUUID}" = "xtrue" ]; then
+
+ linux_root_device_thisversion=${GRUB_DEVICE}
+ else
+ linux_root_device_thisversion=PARTUUID=${GRUB_DEVICE_PARTUUID}
+ fi
+ fi
+
+ if [ "x${GRUB_DISABLE_SUBMENU}" = "xyes" ] || [ "x${GRUB_DISABLE_SUBMENU}" = "xy" ]; then
+ GRUB_DISABLE_SUBMENU="true"
+ fi
+
+ if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xtrue ]; then
+ linux_entry "${OS}" "${version}" simple standard \
+ "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
+ if [ "x$GRUB_LINUX_MAKE_DEBUG" = "xtrue" ]; then
+ linux_entry "${OS}" "${version}" simple debug \
+ "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT} ${GRUB_CMDLINE_LINUX_DEBUG}"
+ fi
+
+ submenu_indentation="$grub_tab"
+
+ if [ -z "$boot_device_id" ]; then
+ boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")"
+ fi
+ # TRANSLATORS: %s is replaced with an OS name
+ echo "submenu '$(gettext_printf "Advanced options for %s" "${OS}" | grub_quote)' \$menuentry_id_option 'gnulinux-advanced-$boot_device_id' {"
+ is_top_level=false
+ fi
+
+ linux_entry "${OS}" "${version}" advanced standard \
+ "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
+ if [ "x$GRUB_LINUX_MAKE_DEBUG" = "xtrue" ]; then
+ linux_entry "${OS}" "${version}" advanced debug \
+ "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT} ${GRUB_CMDLINE_LINUX_DEBUG}"
+ fi
+
+ if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then
+ linux_entry "${OS}" "${version}" recovery standard \
+ "single ${GRUB_CMDLINE_LINUX}"
+ fi
+
+ list=`echo $list | tr ' ' '\n' | fgrep -vx "$linux" | tr '\n' ' '`
+done
+
+# If at least one kernel was found, then we need to
+# add a closing '}' for the submenu command.
+if [ x"$is_top_level" != xtrue ]; then
+ echo '}'
+fi
+
+echo "$title_correction_code"

View File

@ -0,0 +1,26 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
Date: Tue, 6 Feb 2018 11:16:28 +0100
Subject: [PATCH] Don't attempt to backtrace on grub_abort() for grub-emu
The emu platform doesn't have a grub_backtrace() implementation, so this
causes a build error. Don't attempt to call this when building grub-emu.
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
---
grub-core/kern/misc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
index 04371ac49f2..636f97e1ba1 100644
--- a/grub-core/kern/misc.c
+++ b/grub-core/kern/misc.c
@@ -1103,7 +1103,7 @@ static void __attribute__ ((noreturn))
grub_abort (void)
{
#ifndef GRUB_UTIL
-#if defined(__i386__) || defined(__x86_64__)
+#if (defined(__i386__) || defined(__x86_64__)) && !defined(GRUB_MACHINE_EMU)
grub_backtrace();
#endif
#endif

View File

@ -0,0 +1,347 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Tue, 6 Feb 2018 09:09:00 +0100
Subject: [PATCH] Add linux and initrd commands for grub-emu
When using grub-emu, the linux and initrd commands are used as arguments
to the kexec command line tool, to allow booting the selected menu entry.
---
grub-core/Makefile.core.def | 1 -
grub-core/kern/emu/main.c | 4 +
grub-core/kern/emu/misc.c | 18 ++++-
grub-core/loader/emu/linux.c | 172 +++++++++++++++++++++++++++++++++++++++++++
include/grub/emu/exec.h | 4 +-
include/grub/emu/hostfile.h | 3 +-
include/grub/emu/misc.h | 3 +
grub-core/Makefile.am | 1 +
8 files changed, 202 insertions(+), 4 deletions(-)
create mode 100644 grub-core/loader/emu/linux.c
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index ebc558019cd..528f76a8c8e 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1802,7 +1802,6 @@ module = {
common = loader/linux.c;
common = lib/cmdline.c;
- enable = noemu;
efi = loader/efi/linux.c;
};
diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c
index 55ea5a11ccd..846fe9715ec 100644
--- a/grub-core/kern/emu/main.c
+++ b/grub-core/kern/emu/main.c
@@ -107,6 +107,7 @@ static struct argp_option options[] = {
N_("use GRUB files in the directory DIR [default=%s]"), 0},
{"verbose", 'v', 0, 0, N_("print verbose messages."), 0},
{"hold", 'H', N_("SECS"), OPTION_ARG_OPTIONAL, N_("wait until a debugger will attach"), 0},
+ {"kexec", 'X', 0, 0, N_("try the untryable."), 0},
{ 0, 0, 0, 0, 0, 0 }
};
@@ -164,6 +165,9 @@ argp_parser (int key, char *arg, struct argp_state *state)
case 'v':
verbosity++;
break;
+ case 'X':
+ grub_util_set_kexecute();
+ break;
case ARGP_KEY_ARG:
{
diff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c
index 19cd007d448..245b69cab51 100644
--- a/grub-core/kern/emu/misc.c
+++ b/grub-core/kern/emu/misc.c
@@ -39,6 +39,7 @@
#include <grub/emu/misc.h>
int verbosity;
+int kexecute;
void
grub_util_warn (const char *fmt, ...)
@@ -82,7 +83,7 @@ grub_util_error (const char *fmt, ...)
vfprintf (stderr, fmt, ap);
va_end (ap);
fprintf (stderr, ".\n");
- exit (1);
+ grub_exit (1);
}
void *
@@ -142,6 +143,9 @@ void
__attribute__ ((noreturn))
grub_exit (int rc)
{
+#if defined (GRUB_KERNEL)
+ grub_reboot();
+#endif
exit (rc < 0 ? 1 : rc);
}
#endif
@@ -203,3 +207,15 @@ grub_util_load_image (const char *path, char *buf)
fclose (fp);
}
+
+void
+grub_util_set_kexecute(void)
+{
+ kexecute++;
+}
+
+int
+grub_util_get_kexecute(void)
+{
+ return kexecute;
+}
diff --git a/grub-core/loader/emu/linux.c b/grub-core/loader/emu/linux.c
new file mode 100644
index 00000000000..fda9e00d24c
--- /dev/null
+++ b/grub-core/loader/emu/linux.c
@@ -0,0 +1,172 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2006,2007,2008,2009,2010 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/loader.h>
+#include <grub/dl.h>
+#include <grub/command.h>
+#include <grub/time.h>
+
+#include <grub/emu/exec.h>
+#include <grub/emu/hostfile.h>
+#include <grub/emu/misc.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static grub_dl_t my_mod;
+
+static char *kernel_path;
+static char *initrd_path;
+static char *boot_cmdline;
+
+static grub_err_t
+grub_linux_boot (void)
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+ char *initrd_param;
+ const char *kexec[] = { "kexec", "-l", kernel_path, boot_cmdline, NULL, NULL };
+ const char *systemctl[] = { "systemctl", "kexec", NULL };
+ int kexecute = grub_util_get_kexecute();
+
+ if (initrd_path) {
+ initrd_param = grub_xasprintf("--initrd=%s", initrd_path);
+ kexec[3] = initrd_param;
+ kexec[4] = boot_cmdline;
+ } else {
+ initrd_param = grub_xasprintf("%s", "");
+ }
+
+ grub_printf("%serforming 'kexec -l %s %s %s'\n",
+ (kexecute) ? "P" : "Not p",
+ kernel_path, initrd_param, boot_cmdline);
+
+ if (kexecute)
+ rc = grub_util_exec(kexec);
+
+ grub_free(initrd_param);
+
+ if (rc != GRUB_ERR_NONE) {
+ grub_error (rc, N_("Error trying to perform kexec load operation."));
+ grub_sleep (3);
+ return rc;
+ }
+ if (kexecute < 1)
+ grub_fatal (N_("Use '"PACKAGE"-emu --kexec' to force a system restart."));
+
+ grub_printf("Performing 'systemctl kexec' (%s) ",
+ (kexecute==1) ? "do-or-die" : "just-in-case");
+ rc = grub_util_exec (systemctl);
+
+ if (kexecute == 1)
+ grub_fatal (N_("Error trying to perform 'systemctl kexec'"));
+
+ /* need to check read-only root before resetting hard!? */
+ grub_printf("Performing 'kexec -e'");
+ kexec[1] = "-e";
+ kexec[2] = NULL;
+ rc = grub_util_exec(kexec);
+ if ( rc != GRUB_ERR_NONE )
+ grub_fatal (N_("Error trying to directly perform 'kexec -e'."));
+
+ return rc;
+}
+
+static grub_err_t
+grub_linux_unload (void)
+{
+ grub_dl_unref (my_mod);
+ if ( boot_cmdline != NULL )
+ grub_free (boot_cmdline);
+ boot_cmdline = NULL;
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[])
+{
+ int i;
+ char *tempstr;
+
+ grub_dl_ref (my_mod);
+
+ if (argc == 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+
+ if ( !grub_util_is_regular(argv[0]) )
+ return grub_error(GRUB_ERR_FILE_NOT_FOUND, N_("Cannot find kernel file %s"), argv[0]);
+
+ if ( kernel_path != NULL )
+ grub_free(kernel_path);
+
+ kernel_path = grub_xasprintf("%s", argv[0]);
+
+ if ( boot_cmdline != NULL ) {
+ grub_free(boot_cmdline);
+ boot_cmdline = NULL;
+ }
+
+ if ( argc > 1 )
+ {
+ boot_cmdline = grub_xasprintf("--command-line=%s", argv[1]);
+ for ( i = 2; i < argc; i++ ) {
+ tempstr = grub_xasprintf("%s %s", boot_cmdline, argv[i]);
+ grub_free(boot_cmdline);
+ boot_cmdline = tempstr;
+ }
+ }
+
+ grub_loader_set (grub_linux_boot, grub_linux_unload, 0);
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[])
+{
+ if (argc == 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+
+ if ( !grub_util_is_regular(argv[0]) )
+ return grub_error(GRUB_ERR_FILE_NOT_FOUND, N_("Cannot find initrd file %s"), argv[0]);
+
+ if ( initrd_path != NULL )
+ grub_free(initrd_path);
+
+ initrd_path = grub_xasprintf("%s", argv[0]);
+
+ grub_dl_unref (my_mod);
+
+ return GRUB_ERR_NONE;
+}
+
+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;
+ kernel_path = NULL;
+ initrd_path = NULL;
+ boot_cmdline = NULL;
+}
+
+GRUB_MOD_FINI(linux)
+{
+ grub_unregister_command (cmd_linux);
+ grub_unregister_command (cmd_initrd);
+}
diff --git a/include/grub/emu/exec.h b/include/grub/emu/exec.h
index d1073ef86af..1b61b4a2e5d 100644
--- a/include/grub/emu/exec.h
+++ b/include/grub/emu/exec.h
@@ -23,6 +23,8 @@
#include <stdarg.h>
#include <sys/types.h>
+#include <grub/symbol.h>
+
pid_t
grub_util_exec_pipe (const char *const *argv, int *fd);
pid_t
@@ -32,7 +34,7 @@ int
grub_util_exec_redirect_all (const char *const *argv, const char *stdin_file,
const char *stdout_file, const char *stderr_file);
int
-grub_util_exec (const char *const *argv);
+EXPORT_FUNC(grub_util_exec) (const char *const *argv);
int
grub_util_exec_redirect (const char *const *argv, const char *stdin_file,
const char *stdout_file);
diff --git a/include/grub/emu/hostfile.h b/include/grub/emu/hostfile.h
index cfb1e2b5661..a61568e36e9 100644
--- a/include/grub/emu/hostfile.h
+++ b/include/grub/emu/hostfile.h
@@ -22,6 +22,7 @@
#include <grub/disk.h>
#include <grub/partition.h>
#include <sys/types.h>
+#include <grub/symbol.h>
#include <grub/osdep/hostfile.h>
int
@@ -29,7 +30,7 @@ grub_util_is_directory (const char *path);
int
grub_util_is_special_file (const char *path);
int
-grub_util_is_regular (const char *path);
+EXPORT_FUNC(grub_util_is_regular) (const char *path);
char *
grub_util_path_concat (size_t n, ...);
diff --git a/include/grub/emu/misc.h b/include/grub/emu/misc.h
index ce464cfd007..5ef4f79e689 100644
--- a/include/grub/emu/misc.h
+++ b/include/grub/emu/misc.h
@@ -56,6 +56,9 @@ void EXPORT_FUNC(grub_util_warn) (const char *fmt, ...) __attribute__ ((format (
void EXPORT_FUNC(grub_util_info) (const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 1, 2)));
void EXPORT_FUNC(grub_util_error) (const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 1, 2), noreturn));
+void EXPORT_FUNC(grub_util_set_kexecute) (void);
+int EXPORT_FUNC(grub_util_get_kexecute) (void) WARN_UNUSED_RESULT;
+
grub_uint64_t EXPORT_FUNC (grub_util_get_cpu_time_ms) (void);
#ifdef HAVE_DEVICE_MAPPER
diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index c6ba5b2d763..5ff3afd62fa 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -304,6 +304,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/net.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/hostdisk.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/hostfile.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/exec.h
if COND_GRUB_EMU_SDL
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sdl.h
endif

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