import grub2-2.02-156.el8

i8c-beta changed/i8c-beta/grub2-2.02-156.el8
MSVSphere Packaging Team 8 months ago
commit 82ddce2bdf

9
.gitignore vendored

@ -0,0 +1,9 @@
SOURCES/grub-2.02.tar.xz
SOURCES/redhatsecureboot301.cer
SOURCES/redhatsecureboot502.cer
SOURCES/redhatsecureboot601.cer
SOURCES/redhatsecureboot701.cer
SOURCES/redhatsecurebootca3.cer
SOURCES/redhatsecurebootca5.cer
SOURCES/theme.tar.bz2
SOURCES/unifont-5.1.20080820.pcf.gz

@ -0,0 +1,9 @@
3d7eb6eaab28b88cb969ba9ab24af959f4d1b178 SOURCES/grub-2.02.tar.xz
4a07b56e28741884b86da6ac91f8f9929541a1e4 SOURCES/redhatsecureboot301.cer
3f94c47f1d08bacc7cb29bdd912e286b8d2f6fcf SOURCES/redhatsecureboot502.cer
039357ef97aab3e484d1119edd4528156f5859e6 SOURCES/redhatsecureboot601.cer
e89890ca0ded2f9058651cc5fa838b78db2e6cc2 SOURCES/redhatsecureboot701.cer
cf9230e69000076727e5b784ec871d22716dc5da SOURCES/redhatsecurebootca3.cer
e6f506462069aa17d2e8610503635c20f3a995c3 SOURCES/redhatsecurebootca5.cer
cf0b7763c528902da7e8b05cfa248f20c8825ce5 SOURCES/theme.tar.bz2
87f8600ba24e521b5d20bdf6c4b71af8ae861e3a SOURCES/unifont-5.1.20080820.pcf.gz

@ -0,0 +1,997 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Matthew Garrett <mjg@redhat.com>
Date: Tue, 10 Jul 2012 11:58:52 -0400
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 ++++
include/grub/i386/linux.h | 1 +
14 files changed, 620 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 9590e87d9..0b4b0c212 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1626,13 +1626,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;
@@ -1685,7 +1678,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;
xen = loader/i386/xen.c;
i386_pc = lib/i386/pc/vesa_modes_table.c;
mips = loader/mips/linux.c;
@@ -1696,9 +1691,14 @@ module = {
arm_efi = loader/arm64/linux.c;
arm_uboot = loader/arm/linux.c;
arm64 = loader/arm64/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 e394cd96f..04e804d16 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);
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
index 708581fcb..c8a9d8307 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 42ad7c570..5cdf6c943 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 1f86229f8..6c00af98d 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>
@@ -40,6 +41,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;
@@ -66,7 +68,8 @@ grub_armxx_efi_linux_check_image (struct linux_armxx_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;
@@ -101,79 +104,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_armxx_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_armxx_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_armxx_efi_linux_boot_image((grub_addr_t)kernel_addr,
- kernel_size, linux_args));
+ return grub_armxx_efi_linux_boot_image((grub_addr_t)kernel_addr, linux_args);
}
static grub_err_t
@@ -287,6 +281,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
{
grub_file_t file = 0;
struct linux_armxx_kernel_header lh;
+ struct grub_armxx_linux_pe_header *pe;
grub_dl_ref (my_mod);
@@ -331,6 +326,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 1003a0b99..f35b16caa 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_armxx_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 000000000..c24202a5d
--- /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 000000000..3db82e782
--- /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++)
+ {
+ grub_file_filter_disable_compression ();
+ files[i] = grub_file_open (argv[i]);
+ 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_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]);
+ 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));
+
+ 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 b69cb7a3a..a3c87cf2f 100644
--- a/grub-core/loader/i386/pc/linux.c
+++ b/grub-core/loader/i386/pc/linux.c
@@ -468,14 +468,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;
@@ -484,5 +490,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 712ba17b9..5900fc8a4 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_armxx_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 8655067e0..7b533b571 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_armxx_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 2c6648d46..1061aee97 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_armxx_efi_linux_check_image(struct linux_armxx_kernel_header *lh);
-grub_err_t grub_armxx_efi_linux_boot_image(grub_addr_t addr, grub_size_t size,
- char *args);
+grub_err_t grub_armxx_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 000000000..d9ede3677
--- /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 */
diff --git a/include/grub/i386/linux.h b/include/grub/i386/linux.h
index 60c7c3b5e..bb19dbd5a 100644
--- a/include/grub/i386/linux.h
+++ b/include/grub/i386/linux.h
@@ -142,6 +142,7 @@ struct linux_i386_kernel_header
grub_uint64_t setup_data;
grub_uint64_t pref_address;
grub_uint32_t init_size;
+ grub_uint32_t handover_offset;
} GRUB_PACKED;
/* Boot parameters for Linux based on 2.6.12. This is used by the setup

@ -0,0 +1,115 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Matthew Garrett <mjg59@coreos.com>
Date: Sun, 9 Aug 2015 16:12:39 -0700
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 | 37 ++++++++++++++++++++++++-------------
1 file changed, 24 insertions(+), 13 deletions(-)
diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
index 9b53d3168..f7186be40 100644
--- a/grub-core/loader/i386/linux.c
+++ b/grub-core/loader/i386/linux.c
@@ -685,13 +685,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);
@@ -705,7 +707,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"),
@@ -713,6 +723,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");
@@ -804,6 +817,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);
@@ -812,13 +826,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
linux_params.ps_mouse = linux_params.padding10 = 0;
len = sizeof (linux_params) - 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;
@@ -877,7 +888,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);
@@ -1025,9 +1036,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
- (sizeof (LINUX_IMAGE) - 1));
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)
{
@@ -1038,6 +1047,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
fail:
+ grub_free (kernel);
+
if (file)
grub_file_close (file);

@ -0,0 +1,98 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Matthew Garrett <mjg59@coreos.com>
Date: Sun, 9 Aug 2015 16:20:58 -0700
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 | 34 +++++++++++++++++++++-------------
1 file changed, 21 insertions(+), 13 deletions(-)
diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c
index a3c87cf2f..caa76bee8 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)
@@ -355,10 +363,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
}
len = grub_linux16_prot_size;
- if (grub_file_read (file, grub_linux_prot_chunk, grub_linux16_prot_size)
- != (grub_ssize_t) grub_linux16_prot_size && !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)
{
@@ -368,6 +374,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

@ -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 0b4b0c212..e92a7ef32 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -195,6 +195,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 a0c164e54..41a7f3f04 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 98769eadb..088cbe9e2 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 04e804d16..621070918 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 91129e335..708581fcb 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 000000000..d74778b0c
--- /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 74888c463..69c2a10d3 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 af2189619..5cd9b6e08 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 7f96515da..87709aa23 100644
--- a/grub-core/loader/i386/bsd.c
+++ b/grub-core/loader/i386/bsd.c
@@ -38,6 +38,7 @@
#ifdef GRUB_MACHINE_PCBIOS
#include <grub/machine/int.h>
#endif
+#include <grub/efi/sb.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -2124,6 +2125,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");
@@ -2163,6 +2167,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 f7186be40..c84747ea8 100644
--- a/grub-core/loader/i386/linux.c
+++ b/grub-core/loader/i386/linux.c
@@ -35,6 +35,7 @@
#include <grub/i18n.h>
#include <grub/lib/cmdline.h>
#include <grub/linux.h>
+#include <grub/efi/sb.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -1156,6 +1157,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,
@@ -1165,6 +1169,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 caa76bee8..783a3cd93 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+");
@@ -480,6 +481,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."));
@@ -497,6 +501,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 40c67e824..26df46a41 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+");
@@ -446,6 +447,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,
@@ -466,6 +470,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 c9885b1bc..df8dfdb4b 100644
--- a/grub-core/loader/xnu.c
+++ b/grub-core/loader/xnu.c
@@ -33,6 +33,7 @@
#include <grub/extcmd.h>
#include <grub/env.h>
#include <grub/i18n.h>
+#include <grub/efi/sb.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -1469,6 +1470,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,
@@ -1509,6 +1513,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 1061aee97..39480b386 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 000000000..9629fbb0f
--- /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 000000000..e69de29bb
diff --git a/include/grub/mips/linux.h b/include/grub/mips/linux.h
new file mode 100644
index 000000000..e69de29bb
diff --git a/include/grub/powerpc/linux.h b/include/grub/powerpc/linux.h
new file mode 100644
index 000000000..e69de29bb
diff --git a/include/grub/sparc64/linux.h b/include/grub/sparc64/linux.h
new file mode 100644
index 000000000..e69de29bb
diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index f4ff62b76..9c69aa886 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

@ -0,0 +1,263 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Tue, 14 Feb 2017 16:18:54 -0500
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 c8ecce6df..0622dfa48 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 8db228c5b..800c3e540 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);
}
@@ -154,14 +150,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_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);
@@ -201,48 +203,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"));
@@ -255,21 +288,23 @@ 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));
- 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 bb19dbd5a..8474a857e 100644
--- a/include/grub/i386/linux.h
+++ b/include/grub/i386/linux.h
@@ -133,7 +133,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;

@ -0,0 +1,502 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Tue, 8 Aug 2017 12:48:04 -0400
Subject: [PATCH] re-write .gitignore
---
.gitignore | 357 +++++++++++++-------------------------
build-aux/.gitignore | 9 +
docs/.gitignore | 4 +
grub-core/.gitignore | 15 ++
grub-core/gnulib/.gitignore | 22 +++
grub-core/lib/.gitignore | 1 +
include/grub/gcrypt/.gitignore | 2 +
po/.gitignore | 4 +
util/bash-completion.d/.gitignore | 1 +
9 files changed, 175 insertions(+), 240 deletions(-)
create mode 100644 build-aux/.gitignore
create mode 100644 docs/.gitignore
create mode 100644 grub-core/.gitignore
create mode 100644 grub-core/gnulib/.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 eca17bec9..43f04d472 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,249 +1,126 @@
-00_header
-10_*
-20_linux_xen
-30_os-prober
-40_custom
-41_custom
-*.1
-*.8
-aclocal.m4
-ahci_test
-ascii.bitmaps
-ascii.h
-autom4te.cache
-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
+# things ./autogen.sh will create
+/Makefile.utilgcry.def
+/aclocal.m4
+/autom4te.cache
+/configure
+Makefile
+# we want to enable building in a subdirectory, but we don't want to exclude
+# /build-aux so explicitly don't ignore it.
+/build*/
+!/build-aux/
+
+# things very common editors create that we never want
+*~
+.*.sw?
+*.patch
+
+# built objects across the whole tree
+Makefile.in
+*.a
+*.am
*.exec
-*.exec.exe
-fddboot_test
-genkernsyms.sh
-gensymlist.sh
-gentrigtables
-gentrigtables.exe
-gettext_strings_test
-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-sh
-lib/libgcrypt-grub
-libgrub_a_init.c
-*.log
+*.img
+*.info
*.lst
-lzocompress_test
*.marker
-Makefile
*.mod
-mod-*.c
-missing
-netboot_test
+*.module
*.o
-*.a
-ohci_test
-partmap_test
-pata_test
*.pf2
-*.pp
-po/*.mo
-po/grub.pot
-po/POTFILES
-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/gnulib/alloca.h
-grub-core/gnulib/arg-nonnull.h
-grub-core/gnulib/c++defs.h
-grub-core/gnulib/charset.alias
-grub-core/gnulib/configmake.h
-grub-core/gnulib/float.h
-grub-core/gnulib/getopt.h
-grub-core/gnulib/langinfo.h
-grub-core/gnulib/ref-add.sed
-grub-core/gnulib/ref-del.sed
-grub-core/gnulib/stdio.h
-grub-core/gnulib/stdlib.h
-grub-core/gnulib/string.h
-grub-core/gnulib/strings.h
-grub-core/gnulib/sys
-grub-core/gnulib/unistd.h
-grub-core/gnulib/warn-on-use.h
-grub-core/gnulib/wchar.h
-grub-core/gnulib/wctype.h
-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
-grub-core/gnulib/locale.h
-grub-core/gnulib/unitypes.h
-grub-core/gnulib/uniwidth.h
-build-aux/test-driver
+
+# 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
+/po/POTFILES
+/stamp-h
+/stamp-h1
+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*-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*-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*-script-check
+/grub*-script-check.1
+/grub*-set-default
+/grub*-set-default.8
+/grub*-shell
+/grub*-shell-tester
+/grub*-sparc64-setup
+/grub*-sparc64-setup.8
+/grub*-syslinux2cfg
+/grub*-syslinux2cfg.1
+/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/build-aux/.gitignore b/build-aux/.gitignore
new file mode 100644
index 000000000..f2f17aab9
--- /dev/null
+++ b/build-aux/.gitignore
@@ -0,0 +1,9 @@
+/compile
+/config.guess
+/config.sub
+/depcomp
+/install-sh
+/mdate-sh
+/missing
+/test-driver
+/texinfo.tex
diff --git a/docs/.gitignore b/docs/.gitignore
new file mode 100644
index 000000000..91aee84d3
--- /dev/null
+++ b/docs/.gitignore
@@ -0,0 +1,4 @@
+/*.in
+/stamp-1
+/stamp-vti
+/version*.texi
diff --git a/grub-core/.gitignore b/grub-core/.gitignore
new file mode 100644
index 000000000..c738ac6c6
--- /dev/null
+++ b/grub-core/.gitignore
@@ -0,0 +1,15 @@
+/*.lst
+/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/gnulib/.gitignore b/grub-core/gnulib/.gitignore
new file mode 100644
index 000000000..29e199c2d
--- /dev/null
+++ b/grub-core/gnulib/.gitignore
@@ -0,0 +1,22 @@
+/alloca.h
+/arg-nonnull.h
+/c++defs.h
+/charset.alias
+/configmake.h
+/getopt.h
+/langinfo.h
+/libgnu.a
+/locale.h
+/ref-add.sed
+/ref-del.sed
+/stdio.h
+/stdlib.h
+/string.h
+/strings.h
+/sys/
+/unistd.h
+/unitypes.h
+/uniwidth.h
+/warn-on-use.h
+/wchar.h
+/wctype.h
diff --git a/grub-core/lib/.gitignore b/grub-core/lib/.gitignore
new file mode 100644
index 000000000..681545914
--- /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 000000000..8fbf56462
--- /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 000000000..97b679c31
--- /dev/null
+++ b/po/.gitignore
@@ -0,0 +1,4 @@
+/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 000000000..b7e1eb124
--- /dev/null
+++ b/util/bash-completion.d/.gitignore
@@ -0,0 +1 @@
+grub

@ -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 62929d983..2d53c0e86 100644
--- a/grub-core/kern/ieee1275/openfw.c
+++ b/grub-core/kern/ieee1275/openfw.c
@@ -588,3 +588,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 78a70a8bf..249e19bc7 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 a8502d907..ab78ca87f 100644
--- a/grub-core/script/execute.c
+++ b/grub-core/script/execute.c
@@ -27,6 +27,9 @@
#include <grub/normal.h>
#include <grub/extcmd.h>
#include <grub/i18n.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. */
@@ -877,6 +880,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 8868f3a75..2310f33db 100644
--- a/include/grub/ieee1275/ieee1275.h
+++ b/include/grub/ieee1275/ieee1275.h
@@ -252,6 +252,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);

@ -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 d317efa36..29df35e6d 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)

@ -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 3e12e6b24..3e14f5393 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 17a3dbbb5..b8e4b3feb 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 2310f33db..ca08bd966 100644
--- a/include/grub/ieee1275/ieee1275.h
+++ b/include/grub/ieee1275/ieee1275.h
@@ -146,6 +146,8 @@ enum grub_ieee1275_flag
GRUB_IEEE1275_FLAG_BROKEN_REPEAT,
GRUB_IEEE1275_FLAG_CURSORONOFF_ANSI_BROKEN,
+
+ GRUB_IEEE1275_FLAG_DISABLE_VIDEO_SUPPORT
};
extern int EXPORT_FUNC(grub_ieee1275_test_flag) (enum grub_ieee1275_flag flag);

@ -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 33332360e..bc5a3f175 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

@ -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 c7888e40f..783118ccd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -289,6 +289,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.
#
@@ -498,6 +506,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 136287cf1..61108f054 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

@ -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 e7a83c2d6..d2f64b05e 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)

@ -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 2adfa97be..2fd32608c 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 bc5a3f175..b0a8626dd 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 0f801cab3..1001a1223 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'

@ -0,0 +1,256 @@
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 | 2 +-
grub-core/kern/uboot/init.c | 6 +++---
grub-core/kern/xen/init.c | 2 +-
include/grub/misc.h | 2 +-
14 files changed, 39 insertions(+), 21 deletions(-)
diff --git a/grub-core/commands/minicmd.c b/grub-core/commands/minicmd.c
index a3a118241..b25ca4b9f 100644
--- a/grub-core/commands/minicmd.c
+++ b/grub-core/commands/minicmd.c
@@ -176,12 +176,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 708581fcb..e339f264b 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 425bb9603..55ea5a11c 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 76661337f..82012a72f 100644
--- a/grub-core/kern/emu/misc.c
+++ b/grub-core/kern/emu/misc.c
@@ -137,9 +137,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 3314f027f..36f9134b7 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 271b6fbfa..9fafe98f0 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 0d8ebf58b..f5423ce27 100644
--- a/grub-core/kern/ieee1275/init.c
+++ b/grub-core/kern/ieee1275/init.c
@@ -68,7 +68,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 3834a1490..86b3a25ec 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 7b96531b9..dff598ca7 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 be88b77d2..8b6c55ffc 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 3b633d51f..952411d5d 100644
--- a/grub-core/kern/misc.c
+++ b/grub-core/kern/misc.c
@@ -1095,7 +1095,7 @@ grub_abort (void)
grub_getkey ();
}
- grub_exit ();
+ grub_exit (1);
}
void
diff --git a/grub-core/kern/uboot/init.c b/grub-core/kern/uboot/init.c
index 3e338645c..be2a5be1d 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 0559c033c..fce526d41 100644
--- a/grub-core/kern/xen/init.c
+++ b/grub-core/kern/xen/init.c
@@ -549,7 +549,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 372f009e8..83fd69f4a 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);

@ -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 000000000..33ffaa404
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+po/exclude.pot binary

@ -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 e92a7ef32..f80653882 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -191,6 +191,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 3dfdf2d22..71d2279a0 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);

@ -0,0 +1,142 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
Date: Tue, 27 Nov 2012 17:18:53 -0200
Subject: [PATCH] DHCP client ID and UUID options added.
---
grub-core/net/bootp.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++-----
include/grub/net.h | 2 ++
2 files changed, 81 insertions(+), 8 deletions(-)
diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
index 9e2fdb795..f03eeab2f 100644
--- a/grub-core/net/bootp.c
+++ b/grub-core/net/bootp.c
@@ -25,6 +25,49 @@
#include <grub/net/udp.h>
#include <grub/datetime.h>
+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 void
parse_dhcp_vendor (const char *name, const void *vend, int limit, int *mask)
{
@@ -55,6 +98,9 @@ parse_dhcp_vendor (const char *name, const void *vend, int limit, int *mask)
taglength = *ptr++;
+ grub_dprintf("net", "DHCP option %u (0x%02x) found with length %u.\n",
+ tagtype, tagtype, taglength);
+
switch (tagtype)
{
case GRUB_NET_BOOTP_NETMASK:
@@ -120,6 +166,39 @@ parse_dhcp_vendor (const char *name, const void *vend, int limit, int *mask)
taglength);
break;
+ case GRUB_NET_BOOTP_CLIENT_ID:
+ set_env_limn_ro (name, "clientid", (char *) ptr, taglength);
+ break;
+
+ case GRUB_NET_BOOTP_CLIENT_UUID:
+ {
+ if (taglength != 17)
+ break;
+
+ /* The format is 9cfe245e-d0c8-bd45-a79f-54ea5fbd3d97 */
+
+ ptr += 1;
+ taglength -= 1;
+
+ char *val = grub_malloc (2 * taglength + 4 + 1);
+ int i = 0;
+ int j = 0;
+ for (i = 0; i < taglength; i++)
+ {
+ val[2 * i + j] = hexdigit (ptr[i] >> 4);
+ val[2 * i + 1 + j] = hexdigit (ptr[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 * taglength + 4);
+ }
+ break;
+
/* If you need any other options please contact GRUB
development team. */
}
@@ -302,14 +381,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 1096b2432..e266bae23 100644
--- a/include/grub/net.h
+++ b/include/grub/net.h
@@ -457,6 +457,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_BOOTP_END = 0xff
};

@ -0,0 +1,28 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
Date: Wed, 5 Feb 2014 09:42:42 -0200
Subject: [PATCH] trim arp packets with abnormal size
GRUB uses arp request to create the arp response. If the incoming packet
is foobared, GRUB needs to trim the arp response packet before sending it.
---
grub-core/net/arp.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c
index 54306e3b1..d1c69ed2b 100644
--- a/grub-core/net/arp.c
+++ b/grub-core/net/arp.c
@@ -150,6 +150,12 @@ grub_net_arp_receive (struct grub_net_buff *nb, struct grub_net_card *card,
if (grub_net_addr_cmp (&inf->address, &target_addr) == 0
&& arp_packet->op == grub_cpu_to_be16_compile_time (ARP_REQUEST))
{
+ if ((nb->tail - nb->data) > 50)
+ {
+ grub_dprintf ("net", "arp packet with abnormal size (%ld bytes).\n",
+ nb->tail - nb->data);
+ nb->tail = nb->data + 50;
+ }
grub_net_link_level_address_t target;
struct grub_net_buff nb_reply;
struct arppkt *arp_reply;

@ -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 61ebd7dc7..87a7da349 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}"

@ -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 515a68c7a..9b8f5968e 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

@ -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 3180ac880..c7b775bce 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -487,6 +487,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 000000000..10d665868
--- /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

@ -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 9cad0c448..8ab7794c4 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 249e19bc7..759c475c4 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);
+ 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)

@ -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 9b4e72766..02c46f9fd 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 d5e10ee87..0a5b2afb9 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;
@@ -85,7 +97,25 @@ int 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 ab78ca87f..cf6cd6601 100644
--- a/grub-core/script/execute.c
+++ b/grub-core/script/execute.c
@@ -55,6 +55,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)
{
@@ -71,7 +77,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;
}
@@ -95,7 +109,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;
@@ -397,10 +418,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)

@ -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 952411d5d..8344526be 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':
{

@ -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 10773fc34..0769bf850 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);
+
+ 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 759c475c4..b2654ef62 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 e266bae23..50d62ab0c 100644
--- a/include/grub/net.h
+++ b/include/grub/net.h
@@ -566,4 +566,7 @@ extern char *grub_net_default_server;
#define VLANTAG_IDENTIFIER 0x8100
+grub_err_t
+grub_net_search_configfile (char *config);
+
#endif /* ! GRUB_NET_HEADER */

@ -0,0 +1,248 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Fedora Ninjas <grub2-owner@fedoraproject.org>
Date: Tue, 22 Jan 2013 06:31:38 +0100
Subject: [PATCH] blscfg: add blscfg module to parse Boot Loader Specification
snippets
http://www.freedesktop.org/wiki/Specifications/BootLoaderSpec
Works like this:
insmod blscfg
bls_import
Done! You should now have menu items for your snippets in place.
Signed-off-by: Peter Jones <grub2-owner@fedoraproject.org>
---
grub-core/Makefile.core.def | 8 ++
grub-core/commands/blscfg.c | 201 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 209 insertions(+)
create mode 100644 grub-core/commands/blscfg.c
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index f80653882..cd0902b46 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -768,6 +768,14 @@ module = {
common = commands/blocklist.c;
};
+module = {
+ name = blscfg;
+ common = commands/blscfg.c;
+ enable = i386_efi;
+ enable = x86_64_efi;
+ enable = i386_pc;
+};
+
module = {
name = boot;
common = commands/boot.c;
diff --git a/grub-core/commands/blscfg.c b/grub-core/commands/blscfg.c
new file mode 100644
index 000000000..4274aca5a
--- /dev/null
+++ b/grub-core/commands/blscfg.c
@@ -0,0 +1,201 @@
+/*-*- Mode: C; c-basic-offset: 2; indent-tabs-mode: t -*-*/
+
+/* bls.c - implementation of the boot loader spec */
+
+/*
+ * GRUB -- GRand Unified Bootloader
+ *
+ * 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/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/extcmd.h>
+#include <grub/i18n.h>
+#include <grub/fs.h>
+#include <grub/env.h>
+#include <grub/file.h>
+#include <grub/normal.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+#ifdef GRUB_MACHINE_EFI
+#define GRUB_LINUX_CMD "linuxefi"
+#define GRUB_INITRD_CMD "initrdefi"
+#define GRUB_BLS_CONFIG_PATH "/EFI/fedora/loader/entries/"
+#define GRUB_BOOT_DEVICE "($boot)"
+#else
+#define GRUB_LINUX_CMD "linux"
+#define GRUB_INITRD_CMD "initrd"
+#define GRUB_BLS_CONFIG_PATH "/loader/entries/"
+#define GRUB_BOOT_DEVICE "($root)"
+#endif
+
+static int parse_entry (
+ const char *filename,
+ const struct grub_dirhook_info *info __attribute__ ((unused)),
+ void *data __attribute__ ((unused)))
+{
+ grub_size_t n;
+ char *p;
+ grub_file_t f = NULL;
+ grub_off_t sz;
+ char *title = NULL, *options = NULL, *clinux = NULL, *initrd = NULL, *src = NULL;
+ const char *args[2] = { NULL, NULL };
+
+ if (filename[0] == '.')
+ return 0;
+
+ n = grub_strlen (filename);
+ if (n <= 5)
+ return 0;
+
+ if (grub_strcmp (filename + n - 5, ".conf") != 0)
+ return 0;
+
+ p = grub_xasprintf (GRUB_BLS_CONFIG_PATH "%s", filename);
+
+ f = grub_file_open (p);
+ if (!f)
+ goto finish;
+
+ sz = grub_file_size (f);
+ if (sz == GRUB_FILE_SIZE_UNKNOWN || sz > 1024*1024)
+ goto finish;
+
+ for (;;)
+ {
+ char *buf;
+
+ buf = grub_file_getline (f);
+ if (!buf)
+ break;
+
+ if (grub_strncmp (buf, "title ", 6) == 0)
+ {
+ grub_free (title);
+ title = grub_strdup (buf + 6);
+ if (!title)
+ goto finish;
+ }
+ else if (grub_strncmp (buf, "options ", 8) == 0)
+ {
+ grub_free (options);
+ options = grub_strdup (buf + 8);
+ if (!options)
+ goto finish;
+ }
+ else if (grub_strncmp (buf, "linux ", 6) == 0)
+ {
+ grub_free (clinux);
+ clinux = grub_strdup (buf + 6);
+ if (!clinux)
+ goto finish;
+ }
+ else if (grub_strncmp (buf, "initrd ", 7) == 0)
+ {
+ grub_free (initrd);
+ initrd = grub_strdup (buf + 7);
+ if (!initrd)
+ goto finish;
+ }
+
+ grub_free(buf);
+ }
+
+ if (!linux)
+ {
+ grub_printf ("Skipping file %s with no 'linux' key.", p);
+ goto finish;
+ }
+
+ args[0] = title ? title : filename;
+
+ src = grub_xasprintf ("load_video\n"
+ "set gfx_payload=keep\n"
+ "insmod gzio\n"
+ GRUB_LINUX_CMD " %s%s%s%s\n"
+ "%s%s%s%s",
+ GRUB_BOOT_DEVICE, clinux, options ? " " : "", options ? options : "",
+ initrd ? GRUB_INITRD_CMD " " : "", initrd ? GRUB_BOOT_DEVICE : "", initrd ? initrd : "", initrd ? "\n" : "");
+
+ grub_normal_add_menu_entry (1, args, NULL, NULL, "bls", NULL, NULL, src, 0);
+
+finish:
+ grub_free (p);
+ grub_free (title);
+ grub_free (options);
+ grub_free (clinux);
+ grub_free (initrd);
+ grub_free (src);
+
+ if (f)
+ grub_file_close (f);
+
+ return 0;
+}
+
+static grub_err_t
+grub_cmd_bls_import (grub_extcmd_context_t ctxt __attribute__ ((unused)),
+ int argc __attribute__ ((unused)),
+ char **args __attribute__ ((unused)))
+{
+ grub_fs_t fs;
+ grub_device_t dev;
+ static grub_err_t r;
+ const char *devid;
+
+ devid = grub_env_get ("root");
+ if (!devid)
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "root");
+
+ dev = grub_device_open (devid);
+ if (!dev)
+ return grub_errno;
+
+ fs = grub_fs_probe (dev);
+ if (!fs)
+ {
+ r = grub_errno;
+ goto finish;
+ }
+
+ r = fs->dir (dev, GRUB_BLS_CONFIG_PATH, parse_entry, NULL);
+
+finish:
+ if (dev)
+ grub_device_close (dev);
+
+ return r;
+}
+
+static grub_extcmd_t cmd;
+
+GRUB_MOD_INIT(bls)
+{
+ cmd = grub_register_extcmd ("bls_import",
+ grub_cmd_bls_import,
+ 0,
+ NULL,
+ N_("Import Boot Loader Specification snippets."),
+ NULL);
+}
+
+GRUB_MOD_FINI(bls)
+{
+ grub_unregister_extcmd (cmd);
+}

@ -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 b0a8626dd..f68d4925e 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 87a7da349..233754ff2 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

@ -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 4880cefe3..b22e1bcc9 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 8ab7794c4..da47b18b5 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 2bd0b2d28..ea167fe12 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 c1addc0df..68d31de0c 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 233754ff2..3a5aa0f8d 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

@ -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 b2654ef62..f57b7508a 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -202,15 +202,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)
@@ -235,6 +236,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

@ -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 e22bb91f6..a3d1f23f6 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,

@ -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 a3d1f23f6..64a83862f 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 ();

@ -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 64a83862f..1062d64ee 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;

@ -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 f57b7508a..0ce59fdc3 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -426,8 +426,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);

@ -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 1062d64ee..ecc60f99f 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,

@ -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 ecc60f99f..0e43f2c10 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 */;

@ -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 0e43f2c10..537d4bf86 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*/

@ -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 93a90233e..858b526c9 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

@ -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 537d4bf86..452d55bf9 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);

@ -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 3a5aa0f8d..6299836b5 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 e8143b079..972a4b5a0 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

@ -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 452d55bf9..1ed2bd92c 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

@ -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 1ed2bd92c..7681f7d28 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;
}
}

@ -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 311da61c6..044ab3abe 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

@ -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 0a5b2afb9..970ea868c 100644
--- a/grub-core/lib/cmdline.c
+++ b/grub-core/lib/cmdline.c
@@ -97,16 +97,7 @@ int 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++;

@ -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 6299836b5..b744438e0 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)"

@ -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 d2f64b05e..5e2f5283d 100644
--- a/grub-core/normal/menu.c
+++ b/grub-core/normal/menu.c
@@ -838,12 +838,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 cdf3590a3..5785f67ee 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;

@ -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 0ce59fdc3..a3713efcd 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -343,7 +343,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);
@@ -366,7 +366,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;

@ -0,0 +1,111 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 6 Mar 2014 11:51:33 -0500
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 | 80 ++++++++++++++++++++++++++-----------------------
1 file changed, 43 insertions(+), 37 deletions(-)
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
index a3713efcd..7d9c4f09b 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -341,53 +341,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);
- 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 (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;
+ if (! config)
+ goto quit;
- grub_snprintf (config, config_len, "%s/grub.cfg", prefix);
+ 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_net_search_configfile (config);
- grub_enter_normal_mode (config);
- grub_free (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);
+ 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]);

@ -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 847406fba..fa3460d6c 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);

@ -0,0 +1,43 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Fedora Ninjas <grub2-owner@fedoraproject.org>
Date: Sat, 15 Feb 2014 15:10:22 -0500
Subject: [PATCH] reopen SNP protocol for exclusive use by grub
---
grub-core/net/drivers/efi/efinet.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
index 5388f952b..ea0e0ca36 100644
--- a/grub-core/net/drivers/efi/efinet.c
+++ b/grub-core/net/drivers/efi/efinet.c
@@ -330,6 +330,7 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
{
struct grub_net_card *card;
grub_efi_device_path_t *dp;
+ grub_efi_simple_network_t *net;
dp = grub_efi_get_device_path (hnd);
if (! dp)
@@ -383,6 +384,21 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
&pxe_mode->dhcp_ack,
sizeof (pxe_mode->dhcp_ack),
1, device, path);
+ net = grub_efi_open_protocol (card->efi_handle, &net_io_guid,
+ GRUB_EFI_OPEN_PROTOCOL_BY_EXCLUSIVE);
+ if (net) {
+ if (net->mode->state == GRUB_EFI_NETWORK_STOPPED
+ && efi_call_1 (net->start, net) != GRUB_EFI_SUCCESS)
+ continue;
+
+ if (net->mode->state == GRUB_EFI_NETWORK_STOPPED)
+ continue;
+
+ if (net->mode->state == GRUB_EFI_NETWORK_STARTED
+ && efi_call_3 (net->initialize, net, 0, 0) != GRUB_EFI_SUCCESS)
+ continue;
+ card->efi_net = net;
+ }
return;
}
}

@ -0,0 +1,51 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Fri, 4 Mar 2016 15:13:59 -0500
Subject: [PATCH] Revert "reopen SNP protocol for exclusive use by grub"
This reverts commit a3f2c756ce34c9666bddef35e3b3b85ccecdcffc , which is
obsoleted by these:
49426e9 efinet: open Simple Network Protocol exclusively
f348aee efinet: enable hardware filters when opening interface
c52ae40 efinet: skip virtual IPv4 and IPv6 devices when enumerating cards
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/net/drivers/efi/efinet.c | 16 ----------------
1 file changed, 16 deletions(-)
diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
index ea0e0ca36..5388f952b 100644
--- a/grub-core/net/drivers/efi/efinet.c
+++ b/grub-core/net/drivers/efi/efinet.c
@@ -330,7 +330,6 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
{
struct grub_net_card *card;
grub_efi_device_path_t *dp;
- grub_efi_simple_network_t *net;
dp = grub_efi_get_device_path (hnd);
if (! dp)
@@ -384,21 +383,6 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
&pxe_mode->dhcp_ack,
sizeof (pxe_mode->dhcp_ack),
1, device, path);
- net = grub_efi_open_protocol (card->efi_handle, &net_io_guid,
- GRUB_EFI_OPEN_PROTOCOL_BY_EXCLUSIVE);
- if (net) {
- if (net->mode->state == GRUB_EFI_NETWORK_STOPPED
- && efi_call_1 (net->start, net) != GRUB_EFI_SUCCESS)
- continue;
-
- if (net->mode->state == GRUB_EFI_NETWORK_STOPPED)
- continue;
-
- if (net->mode->state == GRUB_EFI_NETWORK_STARTED
- && efi_call_3 (net->initialize, net, 0, 0) != GRUB_EFI_SUCCESS)
- continue;
- card->efi_net = net;
- }
return;
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,102 @@
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 | 9 +++++++++
util/editenv.c | 46 ++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 53 insertions(+), 2 deletions(-)
diff --git a/Makefile.util.def b/Makefile.util.def
index c7b775bce..d08713b55 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -231,8 +231,17 @@ 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 = 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 c6f8d2298..d8d1dad6a 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);
@@ -59,7 +60,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);
}

@ -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 b744438e0..43d98476b 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}"

@ -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 1001a1223..1a4a57898 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 "$?"

@ -0,0 +1,208 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Fri, 3 Oct 2014 11:08:03 -0400
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 f5423ce27..e01bc6eab 100644
--- a/grub-core/kern/ieee1275/init.c
+++ b/grub-core/kern/ieee1275/init.c
@@ -124,23 +124,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 0769bf850..16d2ce06d 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 7d9c4f09b..b69f9e738 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -331,74 +331,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);
+ 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);
- 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;
}

@ -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 2fd32608c..a7155c22f 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.

@ -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
---
configure.ac | 29 +++++
Makefile.util.def | 16 +++
util/grub-rpm-sort.c | 281 ++++++++++++++++++++++++++++++++++++++++++++++
.gitignore | 2 +
util/grub-mkconfig_lib.in | 8 +-
util/grub-rpm-sort.8 | 12 ++
6 files changed, 347 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 d5db2803e..056df1cba 100644
--- a/configure.ac
+++ b/configure.ac
@@ -65,6 +65,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])
@@ -88,6 +89,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])
@@ -1790,6 +1792,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 d08713b55..406d96861 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -685,6 +685,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 = grub-core/gnulib/libgnu.a;
+ ldadd = libgrubkern.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 000000000..f33bd1ed5
--- /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/.gitignore b/.gitignore
index 43f04d472..fa2e5b609 100644
--- a/.gitignore
+++ b/.gitignore
@@ -105,6 +105,8 @@ grub-*.tar.*
/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-default
diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in
index 1a4a57898..7fe359843 100644
--- a/util/grub-mkconfig_lib.in
+++ b/util/grub-mkconfig_lib.in
@@ -214,6 +214,12 @@ version_sort ()
esac
}
+if [ "x$RPMLIB" = x ]; then
+ kernel_sort=version_sort
+else
+ kernel_sort="${sbindir}/grub-rpm-sort"
+fi
+
version_test_numeric ()
{
version_test_numeric_a="$1"
@@ -230,7 +236,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 000000000..8ce214884
--- /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"

@ -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 90d92d3ad..6d9f4e5fa 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')
{

@ -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 43d98476b..a8a8e2cf3 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

@ -0,0 +1,272 @@
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
---
configure.ac | 1 +
Makefile.util.def | 13 +++++
.gitignore | 2 +
util/grub-mkconfig.in | 2 +
util/grub-setpassword.8 | 28 +++++++++++
util/grub-setpassword.in | 123 +++++++++++++++++++++++++++++++++++++++++++++++
util/grub.d/01_users.in | 11 +++++
7 files changed, 180 insertions(+)
create mode 100644 util/grub-setpassword.8
create mode 100644 util/grub-setpassword.in
create mode 100644 util/grub.d/01_users.in
diff --git a/configure.ac b/configure.ac
index 056df1cba..679f634ce 100644
--- a/configure.ac
+++ b/configure.ac
@@ -65,6 +65,7 @@ grub_TRANSFORM([grub-mkrelpath])
grub_TRANSFORM([grub-mkrescue])
grub_TRANSFORM([grub-probe])
grub_TRANSFORM([grub-reboot])
+grub_TRANSFORM([grub-setpassword])
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 406d96861..fd91045bd 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -440,6 +440,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;
@@ -722,6 +728,13 @@ script = {
installdir = sbin;
};
+script = {
+ name = grub-setpassword;
+ common = util/grub-setpassword.in;
+ mansection = 8;
+ installdir = sbin;
+};
+
script = {
name = grub-mkconfig_lib;
common = util/grub-mkconfig_lib.in;
diff --git a/.gitignore b/.gitignore
index fa2e5b609..5066689bc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -111,6 +111,8 @@ grub-*.tar.*
/grub*-script-check.1
/grub*-set-default
/grub*-set-default.8
+/grub*-setsetpassword
+/grub*-setsetpassword.8
/grub*-shell
/grub*-shell-tester
/grub*-sparc64-setup
diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
index f68d4925e..bdb9982ae 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-setpassword.8 b/util/grub-setpassword.8
new file mode 100644
index 000000000..49200a848
--- /dev/null
+++ b/util/grub-setpassword.8
@@ -0,0 +1,28 @@
+.TH GRUB-SETPASSWORD 3 "Thu Jun 25 2015"
+.SH NAME
+\fBgrub-setpassword\fR \(em Generate the user.cfg file containing the hashed grub bootloader password.
+
+.SH SYNOPSIS
+\fBgrub-setpassword\fR [OPTION]
+
+.SH DESCRIPTION
+\fBgrub-setpassword\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 PATH\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-setpassword.in b/util/grub-setpassword.in
new file mode 100644
index 000000000..dd76f00fc
--- /dev/null
+++ b/util/grub-setpassword.in
@@ -0,0 +1,123 @@
+#!/bin/sh -e
+
+if [ -d /sys/firmware/efi/efivars/ ]; then
+ grubdir=`echo "/@bootdirname@/efi/EFI/redhat/" | 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] [SOURCE]
+Run GRUB script in a Qemu instance.
+
+ -h, --help print this message and exit
+ -v, --version print the version information and exit
+ -o, --output_path choose a custom output path for user.cfg
+
+$0 prompts the user to set a password on the grub bootloader. The password
+is written to a file named user.cfg.
+
+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} ) | \
+ ${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 "${grubdir}/user.cfg" 2>/dev/null || :
+chmod 0600 "${grubdir}/user.cfg" 2>/dev/null || :
+echo "GRUB2_PASSWORD=${MYPASS}" > "${grubdir}/user.cfg"
diff --git a/util/grub.d/01_users.in b/util/grub.d/01_users.in
new file mode 100644
index 000000000..db2f44bfb
--- /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

@ -0,0 +1,57 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 3 Aug 2015 11:46:42 -0400
Subject: [PATCH] Try to make sure configure.ac and grub-rpm-sort play nice.
Apparently the test for whether to use grub-rpm-sort and also the
renaming of it to grub2-rpm-sort on the runtime side weren't right.
Related: rhbz#1124074
Signed-off-by: Peter Jones <pjones@redhat.com>
---
configure.ac | 2 +-
util/grub-mkconfig_lib.in | 9 ++++++---
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/configure.ac b/configure.ac
index 679f634ce..71d105696 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1796,7 +1796,7 @@ 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
+if test x"$enable_rpm_sort" = xno ; then
rpm_sort_excuse="explicitly disabled"
fi
diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in
index 7fe359843..113a41f94 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,10 +217,10 @@ version_sort ()
esac
}
-if [ "x$RPMLIB" = x ]; then
+if [ "x$grub_rpm_sort" != x -a -x "$grub_rpm_sort" ]; then
+ kernel_sort="$grub_rpm_sort"
+else
kernel_sort=version_sort
-else
- kernel_sort="${sbindir}/grub-rpm-sort"
fi
version_test_numeric ()

@ -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 e8ad34b84..7d4b82262 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);

@ -0,0 +1,59 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: RHEL Ninjas <example@example.com>
Date: Fri, 25 Sep 2015 16:24:23 +0900
Subject: [PATCH] efinet: add filter for the first exclusive reopen of SNP
---
grub-core/net/drivers/efi/efinet.c | 39 ++++++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
index 5388f952b..d15a799f2 100644
--- a/grub-core/net/drivers/efi/efinet.c
+++ b/grub-core/net/drivers/efi/efinet.c
@@ -383,6 +383,45 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
&pxe_mode->dhcp_ack,
sizeof (pxe_mode->dhcp_ack),
1, device, path);
+ net = grub_efi_open_protocol (card->efi_handle, &net_io_guid,
+ GRUB_EFI_OPEN_PROTOCOL_BY_EXCLUSIVE);
+ if (net) {
+ if (net->mode->state == GRUB_EFI_NETWORK_STOPPED
+ && efi_call_1 (net->start, net) != GRUB_EFI_SUCCESS)
+ continue;
+
+ if (net->mode->state == GRUB_EFI_NETWORK_STOPPED)
+ continue;
+
+ if (net->mode->state == GRUB_EFI_NETWORK_STARTED
+ && efi_call_3 (net->initialize, net, 0, 0) != GRUB_EFI_SUCCESS)
+ continue;
+
+ /* Enable hardware receive filters if driver declares support for it.
+ We need unicast and broadcast and additionaly all nodes and
+ solicited multicast for IPv6. Solicited multicast is per-IPv6
+ address and we currently do not have API to do it so simply
+ try to enable receive of all multicast packets or evertyhing in
+ the worst case (i386 PXE driver always enables promiscuous too).
+
+ This does trust firmware to do what it claims to do.
+ */
+ if (net->mode->receive_filter_mask)
+ {
+ grub_uint32_t filters = GRUB_EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
+ GRUB_EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST |
+ GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
+
+ filters &= net->mode->receive_filter_mask;
+ if (!(filters & GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST))
+ filters |= (net->mode->receive_filter_mask &
+ GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS);
+
+ efi_call_6 (net->receive_filters, net, filters, 0, 0, 0, NULL);
+ }
+
+ card->efi_net = net;
+ }
return;
}
}

@ -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 ca334d5a4..e6c78d16d 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 6be678c0d..c35ce9724 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)
{

@ -0,0 +1,28 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Robert Marshall <rmarshall@redhat.com>
Date: Mon, 22 Feb 2016 15:30:05 -0500
Subject: [PATCH] Warn if grub password will not be read (#1290803)
It is possible for a system to have never run grub-mkconfig and add the
section that reads the user.cfg file which contains a user set GRUB
password. Users in that scenario will now be warned that grub-mkconfig
must be run prior to their newly set password taking effect.
Resolves: rhbz#1290803
---
util/grub-setpassword.in | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/util/grub-setpassword.in b/util/grub-setpassword.in
index dd76f00fc..fb9d3a3b6 100644
--- a/util/grub-setpassword.in
+++ b/util/grub-setpassword.in
@@ -121,3 +121,8 @@ fi
install -m 0600 /dev/null "${grubdir}/user.cfg" 2>/dev/null || :
chmod 0600 "${grubdir}/user.cfg" 2>/dev/null || :
echo "GRUB2_PASSWORD=${MYPASS}" > "${grubdir}/user.cfg"
+
+if ! grep -q "^### BEGIN /etc/grub.d/01_users ###$" "${grubdir}/grub.cfg"; then
+ echo "WARNING: The current configuration lacks password support!"
+ echo "Update your configuration with @grub_mkconfig@ to support this feature."
+fi

@ -0,0 +1,55 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Robert Marshall <rmarshall@redhat.com>
Date: Tue, 26 Jan 2016 10:28:35 -0500
Subject: [PATCH] Clean up grub-setpassword documentation (#1290799)
The output for --help had some errors. Corrected those and polished the
text to be a little easier to follow. Carried verbage over to man page
to maintain internal consistency.
Resolves: rhbz#1290799
---
util/grub-setpassword.8 | 2 +-
util/grub-setpassword.in | 15 +++++++--------
2 files changed, 8 insertions(+), 9 deletions(-)
diff --git a/util/grub-setpassword.8 b/util/grub-setpassword.8
index 49200a848..dc91dd669 100644
--- a/util/grub-setpassword.8
+++ b/util/grub-setpassword.8
@@ -19,7 +19,7 @@ Display program usage and exit.
-v, --version
Display the current version.
.TP
--o, --output[=\fIDIRECTORY PATH\fR]
+-o, --output=<\fIDIRECTORY\fR>
Choose the file path to which user.cfg will be written.
.SH SEE ALSO
diff --git a/util/grub-setpassword.in b/util/grub-setpassword.in
index fb9d3a3b6..c8c0fa419 100644
--- a/util/grub-setpassword.in
+++ b/util/grub-setpassword.in
@@ -16,15 +16,14 @@ grub_mkpasswd="${bindir}/@grub_mkpasswd_pbkdf2@"
# Print the usage.
usage () {
cat <<EOF
-Usage: $0 [OPTION] [SOURCE]
-Run GRUB script in a Qemu instance.
-
- -h, --help print this message and exit
- -v, --version print the version information and exit
- -o, --output_path choose a custom output path for user.cfg
-
+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.
+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

@ -0,0 +1,27 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Robert Marshall <rmarshall@redhat.com>
Date: Fri, 29 Jan 2016 16:56:11 -0500
Subject: [PATCH] Fix locale issue in grub-setpassword (#1294243)
A shell substitution was expecting non-translated output to grab the
hashed password and put it in the user.cfg file. Modified code to force
the generic C locale when this particular piece of code is run.
Resolves: rhbz#1294243
---
util/grub-setpassword.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/util/grub-setpassword.in b/util/grub-setpassword.in
index c8c0fa419..d7924af51 100644
--- a/util/grub-setpassword.in
+++ b/util/grub-setpassword.in
@@ -104,7 +104,7 @@ getpass() {
P1="$1" && shift
( echo ${P0} ; echo ${P1} ) | \
- ${grub_mkpasswd} | \
+ LC_ALL=C ${grub_mkpasswd} | \
grep -v '[eE]nter password:' | \
sed -e "s/PBKDF2 hash of your password is //"
}

@ -0,0 +1,28 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Robert Elliott <elliott@hpe.com>
Date: Fri, 22 Jan 2016 13:32:30 +0100
Subject: [PATCH] efiemu: Handle persistent RAM and unknown possible future
additions.
(cherry picked from commit ae3b83a4d4df75a01198a2fed7542391e7c449e0)
Resolves: rhbz#1288608
---
grub-core/efiemu/mm.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/grub-core/efiemu/mm.c b/grub-core/efiemu/mm.c
index 52a032f7b..92e7df7e5 100644
--- a/grub-core/efiemu/mm.c
+++ b/grub-core/efiemu/mm.c
@@ -410,8 +410,8 @@ fill_hook (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type,
return grub_efiemu_add_to_mmap (addr, size,
GRUB_EFI_ACPI_MEMORY_NVS);
- case GRUB_MEMORY_PERSISTENT:
- case GRUB_MEMORY_PERSISTENT_LEGACY:
+ case GRUB_MEMORY_PRAM:
+ case GRUB_MEMORY_PMEM:
return grub_efiemu_add_to_mmap (addr, size,
GRUB_EFI_PERSISTENT_MEMORY);
default:

@ -0,0 +1,27 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Vladimir Serbinenko <phcoder@gmail.com>
Date: Fri, 22 Jan 2016 14:10:30 +0100
Subject: [PATCH] efiemu: Fix compilation failure
(cherry picked from commit b6a03dfd327489d53ee07c6d7d593b99c7b7cb62)
Resolves: rhbz#1288608
---
grub-core/efiemu/mm.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/grub-core/efiemu/mm.c b/grub-core/efiemu/mm.c
index 92e7df7e5..52a032f7b 100644
--- a/grub-core/efiemu/mm.c
+++ b/grub-core/efiemu/mm.c
@@ -410,8 +410,8 @@ fill_hook (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type,
return grub_efiemu_add_to_mmap (addr, size,
GRUB_EFI_ACPI_MEMORY_NVS);
- case GRUB_MEMORY_PRAM:
- case GRUB_MEMORY_PMEM:
+ case GRUB_MEMORY_PERSISTENT:
+ case GRUB_MEMORY_PERSISTENT_LEGACY:
return grub_efiemu_add_to_mmap (addr, size,
GRUB_EFI_PERSISTENT_MEMORY);
default:

@ -0,0 +1,65 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 7 Apr 2016 10:58:06 -0400
Subject: [PATCH] Revert "reopen SNP protocol for exclusive use by grub"
I *think* this should have been replaced by upstream's
49426e9fd2e562c73a4f1206f32eff9e424a1a73, so I'm reverting for now.
May resolve rhbz#1273974.
This reverts commit 147daeab22db793978f952b6f0d832919a1b0081.
---
grub-core/net/drivers/efi/efinet.c | 39 --------------------------------------
1 file changed, 39 deletions(-)
diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
index d15a799f2..5388f952b 100644
--- a/grub-core/net/drivers/efi/efinet.c
+++ b/grub-core/net/drivers/efi/efinet.c
@@ -383,45 +383,6 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
&pxe_mode->dhcp_ack,
sizeof (pxe_mode->dhcp_ack),
1, device, path);
- net = grub_efi_open_protocol (card->efi_handle, &net_io_guid,
- GRUB_EFI_OPEN_PROTOCOL_BY_EXCLUSIVE);
- if (net) {
- if (net->mode->state == GRUB_EFI_NETWORK_STOPPED
- && efi_call_1 (net->start, net) != GRUB_EFI_SUCCESS)
- continue;
-
- if (net->mode->state == GRUB_EFI_NETWORK_STOPPED)
- continue;
-
- if (net->mode->state == GRUB_EFI_NETWORK_STARTED
- && efi_call_3 (net->initialize, net, 0, 0) != GRUB_EFI_SUCCESS)
- continue;
-
- /* Enable hardware receive filters if driver declares support for it.
- We need unicast and broadcast and additionaly all nodes and
- solicited multicast for IPv6. Solicited multicast is per-IPv6
- address and we currently do not have API to do it so simply
- try to enable receive of all multicast packets or evertyhing in
- the worst case (i386 PXE driver always enables promiscuous too).
-
- This does trust firmware to do what it claims to do.
- */
- if (net->mode->receive_filter_mask)
- {
- grub_uint32_t filters = GRUB_EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
- GRUB_EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST |
- GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
-
- filters &= net->mode->receive_filter_mask;
- if (!(filters & GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST))
- filters |= (net->mode->receive_filter_mask &
- GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS);
-
- efi_call_6 (net->receive_filters, net, filters, 0, 0, 0, NULL);
- }
-
- card->efi_net = net;
- }
return;
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,660 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Wed, 8 Jun 2016 21:03:37 -0400
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 | 53 +++++++++--
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, 478 insertions(+), 14 deletions(-)
diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
index f03eeab2f..da3e45446 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>
static char *
@@ -349,6 +350,179 @@ grub_net_configure_by_dhcp_ack (const char *name,
return inter;
}
+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_net_process_dhcp (struct grub_net_buff *nb,
struct grub_net_card *card)
diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
index 5388f952b..a4daaa460 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,18 @@ 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 +364,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 +380,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 16d2ce06d..4be228d95 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 7d90bf66e..1157524fc 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 c7c9f0e1d..28b6adf76 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 50d62ab0c..f8f3ec13a 100644
--- a/include/grub/net.h
+++ b/include/grub/net.h
@@ -442,6 +442,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
@@ -470,6 +515,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);

@ -0,0 +1,300 @@
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 +++
.gitignore | 2 +
util/bash-completion.d/grub-completion.bash.in | 22 ++++++++
util/grub-get-kernel-settings.3 | 20 +++++++
util/grub-get-kernel-settings.in | 78 ++++++++++++++++++++++++++
util/grub-mkconfig.in | 3 +
util/grub.d/10_linux.in | 23 ++++++--
8 files changed, 152 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 71d105696..aa06ed59c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -58,6 +58,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])
@@ -75,6 +76,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 fd91045bd..2d032643d 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -714,6 +714,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/.gitignore b/.gitignore
index 5066689bc..54795fa60 100644
--- a/.gitignore
+++ b/.gitignore
@@ -68,6 +68,8 @@ grub-*.tar.*
/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
diff --git a/util/bash-completion.d/grub-completion.bash.in b/util/bash-completion.d/grub-completion.bash.in
index 44bf135b9..5c4acd496 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 000000000..ba33330e2
--- /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 000000000..120462198
--- /dev/null
+++ b/util/grub-get-kernel-settings.in
@@ -0,0 +1,78 @@
+#!/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
diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
index bdb9982ae..8218f3d47 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 a8a8e2cf3..4e49ccdf7 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

@ -0,0 +1,55 @@
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: Peter Jones <pjones@redhat.com>
---
grub-core/net/tftp.c | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
index 1157524fc..5ca0a96a6 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,7 +356,10 @@ 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);
+
+ /* 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 (filename) + 1;
rrq += grub_strlen (filename) + 1;

@ -0,0 +1,32 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mark Salter <msalter@redhat.com>
Date: Tue, 7 Mar 2017 18:26:17 -0500
Subject: [PATCH] Fix malformed tftp packets
0088-Normalize-slashes-in-tftp-paths.patch collapses multiple contiguous
slashes in a filename into one slash in the tftp packet filename field.
However, the packet buffer pointer is advanced using the original name.
This leaves unitialized data between the name field and the type field
leading to tftp errors. Use the length of the normalized name to avoid
this.
Signed-off-by: Mark Salter <msalter@redhat.com>
---
grub-core/net/tftp.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
index 5ca0a96a6..dcd824943 100644
--- a/grub-core/net/tftp.c
+++ b/grub-core/net/tftp.c
@@ -360,8 +360,8 @@ tftp_open (struct grub_file *file, const char *filename)
/* 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 (filename) + 1;
- rrq += grub_strlen (filename) + 1;
+ rrqlen += grub_strlen (rrq) + 1;
+ rrq += grub_strlen (rrq) + 1;
grub_strcpy (rrq, "octet");
rrqlen += grub_strlen ("octet") + 1;

@ -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 002446be1..3df75357a 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)

@ -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 991891a6e..27563743b 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -175,6 +175,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;
diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
index f1fab7000..5ce89a40c 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 000000000..1079b5380
--- /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 825a8800e..c0ad6ab8b 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 c3e03c727..c67273db3 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>

@ -0,0 +1,27 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Fri, 4 Mar 2016 16:29:13 -0500
Subject: [PATCH] Make grub-editenv build again.
36212460d3565b18439a3a8130b28e6c97702c6a split how some of the mkimage
utility functions are defined, and they wind up being linked into
grub-editenv. Most utilities got fixed, but this one was missed.
Signed-off-by: Peter Jones <pjones@redhat.com>
---
Makefile.util.def | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Makefile.util.def b/Makefile.util.def
index 2d032643d..879e8eb98 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -237,6 +237,8 @@ program = {
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;

@ -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 aa06ed59c..f69f89867 100644
--- a/configure.ac
+++ b/configure.ac
@@ -80,6 +80,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])
@@ -98,6 +99,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 000000000..ae842f3a6
--- /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 4dea4f545..0eaaafe50 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 000000000..853094827
--- /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"

@ -0,0 +1,53 @@
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/kern/emu/main.c | 6 ++++++
grub-core/kern/misc.c | 9 +++++++++
2 files changed, 15 insertions(+)
diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c
index 55ea5a11c..7e47ec812 100644
--- a/grub-core/kern/emu/main.c
+++ b/grub-core/kern/emu/main.c
@@ -72,6 +72,12 @@ grub_exit (int retval __attribute__((unused)))
grub_reboot ();
}
+void
+grub_exit (int retval __attribute__((unused)))
+{
+ grub_reboot ();
+}
+
void
grub_machine_init (void)
{
diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
index 5ce89a40c..04371ac49 100644
--- a/grub-core/kern/misc.c
+++ b/grub-core/kern/misc.c
@@ -1120,6 +1120,15 @@ grub_abort (void)
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, ...)
{

@ -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 a1ac7a388..93b5cd306 100644
--- a/grub-core/loader/arm64/linux.c
+++ b/grub-core/loader/arm64/linux.c
@@ -80,7 +80,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;

@ -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 e339f264b..562d6887e 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;
}

@ -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 9b8f5968e..13a3a6bc7 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}")"

@ -0,0 +1,703 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jeff Mahoney <jeffm@suse.com>
Date: Wed, 18 Dec 2013 09:57:04 +0000
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 be195448d..51ed63d42 100644
--- a/grub-core/fs/btrfs.c
+++ b/grub-core/fs/btrfs.c
@@ -29,6 +29,9 @@
#include <minilzo.h>
#include <grub/i18n.h>
#include <grub/btrfs.h>
+#include <grub/command.h>
+#include <grub/env.h>
+#include <grub/extcmd.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -64,9 +67,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];
@@ -105,6 +110,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
@@ -171,6 +177,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;
@@ -215,6 +229,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
};
@@ -837,6 +859,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)
{
@@ -872,6 +950,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;
}
@@ -1232,6 +1317,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,
@@ -1250,14 +1420,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] == '/')
@@ -1430,9 +1612,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;
}
@@ -1673,18 +1867,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]),
@@ -1693,6 +1879,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);
@@ -1749,6 +1949,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",
.dir = grub_btrfs_dir,
@@ -1764,12 +2200,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 9d93fb6c1..234ad9767 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
};

@ -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 51ed63d42..88d727d16 100644
--- a/grub-core/fs/btrfs.c
+++ b/grub-core/fs/btrfs.c
@@ -2273,6 +2273,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)

@ -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 88d727d16..a47d29756 100644
--- a/grub-core/fs/btrfs.c
+++ b/grub-core/fs/btrfs.c
@@ -920,6 +920,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)
{
@@ -950,11 +951,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;
@@ -1414,24 +1418,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
{
@@ -1442,15 +1461,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)
{
@@ -1461,7 +1488,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] == '.')
@@ -1492,8 +1521,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;
}
@@ -1562,7 +1592,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;
@@ -1612,14 +1644,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
{
@@ -2275,6 +2319,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)

@ -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 6d9f4e5fa..5d50dd6f8 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 65effa9f3..b637c58ef 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 ebcdd8f5e..f044a880a 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 78d0138cb..4375c1619 100644
--- a/util/grub-install.c
+++ b/util/grub-install.c
@@ -816,6 +816,8 @@ fill_core_services (const char *core_services)
free (sysv_plist);
}
+extern int use_relative_path_on_btrfs;
+
int
main (int argc, char *argv[])
{
@@ -849,6 +851,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;
@@ -1321,6 +1326,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 47a241a39..5db7a9a7d 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 875d5896c..c9a7e5f4a 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

@ -0,0 +1,127 @@
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
---
util/grub-mkconfig.in | 3 ++-
util/grub-mkconfig_lib.in | 4 ++++
util/grub.d/00_header.in | 24 +++++++++++++++++++++++-
util/grub.d/10_linux.in | 4 ++++
util/grub.d/20_linux_xen.in | 4 ++++
5 files changed, 37 insertions(+), 2 deletions(-)
diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
index 8218f3d47..4248b9341 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 113a41f94..b3aae534d 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 858b526c9..e2a533001 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,15 @@ fi
if [ "x${GRUB_BADRAM}" != "x" ] ; then
echo "badram ${GRUB_BADRAM}"
fi
+
+if [ "x${SUSE_BTRFS_SNAPSHOT_BOOTING}" = "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 4e49ccdf7..d9a05937e 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 972a4b5a0..bcdc3ceac 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`

@ -0,0 +1,537 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 22 May 2015 11:45:25 +0000
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 a47d29756..2e36ac47e 100644
--- a/grub-core/fs/btrfs.c
+++ b/grub-core/fs/btrfs.c
@@ -32,6 +32,7 @@
#include <grub/command.h>
#include <grub/env.h>
#include <grub/extcmd.h>
+#include <grub/list.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -245,6 +246,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)
@@ -887,9 +894,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);
@@ -1758,11 +1782,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);
@@ -1864,11 +1897,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);
@@ -2039,6 +2082,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,
@@ -2245,6 +2432,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 *
@@ -2308,6 +2496,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 5d50dd6f8..4c5a13022 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 4375c1619..a0ad99729 100644
--- a/util/grub-install.c
+++ b/util/grub-install.c
@@ -1535,6 +1535,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 73fa2d34a..9c642ae3f 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);

@ -0,0 +1,31 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dusty Mabe <dusty@dustymabe.com>
Date: Sat, 18 Jul 2015 15:38:08 +0000
Subject: [PATCH] No more "Bootable Snapshot" submenu in grub.cfg.
This breaks grubby (run on kernel upgrades) because grubby just
does a search for "menuentry".
---
util/grub.d/00_header.in | 12 ------------
1 file changed, 12 deletions(-)
diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in
index e2a533001..8a16fea34 100644
--- a/util/grub.d/00_header.in
+++ b/util/grub.d/00_header.in
@@ -366,15 +366,3 @@ fi
if [ "x${GRUB_BADRAM}" != "x" ] ; then
echo "badram ${GRUB_BADRAM}"
fi
-
-if [ "x${SUSE_BTRFS_SNAPSHOT_BOOTING}" = "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

@ -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 2e36ac47e..4a31d39ee 100644
--- a/grub-core/fs/btrfs.c
+++ b/grub-core/fs/btrfs.c
@@ -924,11 +924,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);

@ -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 4a31d39ee..7002ad81b 100644
--- a/grub-core/fs/btrfs.c
+++ b/grub-core/fs/btrfs.c
@@ -2446,6 +2446,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",
.dir = grub_btrfs_dir,
@@ -2464,6 +2696,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)),
@@ -2534,6 +2767,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,

@ -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 39480b386..09a18e563 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;

@ -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 5cd9b6e08..106eb10a3 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 ();
@@ -500,10 +500,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;
@@ -514,8 +513,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)
{
@@ -555,8 +552,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)
{
@@ -788,14 +785,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;
}
@@ -803,10 +800,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;
@@ -1073,7 +1067,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);

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

Loading…
Cancel
Save