Change-Id: I51baf6b1ef8df582358b92e0b6277e2de3733cc4
Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/2859
Tested-by: gerrit-photon <photon-checkins@vmware.com>
Reviewed-by: Alexey Makhalov <amakhalov@vmware.com>
| 1 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,663 +0,0 @@ |
| 1 |
-From e5d5e5a259a9827e4d6e41e49085f730c773c178 Mon Sep 17 00:00:00 2001 |
|
| 2 |
-From: Alexey Makhalov <amakhalov@vmware.com> |
|
| 3 |
-Date: Tue, 10 Jul 2012 11:58:52 -0400 |
|
| 4 |
-Subject: [PATCH] Secure Boot support |
|
| 5 |
- |
|
| 6 |
-New commands: linuxefi, initrdefi |
|
| 7 |
-If running under secure boot use linuxefi loader only and linux |
|
| 8 |
-command is fallback to linuxefi. |
|
| 9 |
-Forbid dl file loading (insmod and similar) when secure boot is enabled. |
|
| 10 |
- grub-core/Makefile.core.def | 8 + |
|
| 11 |
- grub-core/kern/dl.c | 21 +++ |
|
| 12 |
- grub-core/kern/efi/efi.c | 30 +++ |
|
| 13 |
- grub-core/kern/efi/mm.c | 32 ++++ |
|
| 14 |
- grub-core/loader/i386/efi/linux.c | 387 ++++++++++++++++++++++++++++++++++++++ |
|
| 15 |
- grub-core/loader/i386/linux.c | 45 +++++ |
|
| 16 |
- include/grub/efi/efi.h | 4 + |
|
| 17 |
- include/grub/i386/linux.h | 1 + |
|
| 18 |
- 8 files changed, 528 insertions(+) |
|
| 19 |
- create mode 100644 grub-core/loader/i386/efi/linux.c |
|
| 20 |
- |
|
| 21 |
-diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def |
|
| 22 |
-index 2dfa22a..68e47a7 100644 |
|
| 23 |
-+++ b/grub-core/Makefile.core.def |
|
| 24 |
-@@ -1734,6 +1734,14 @@ module = {
|
|
| 25 |
- }; |
|
| 26 |
- |
|
| 27 |
- module = {
|
|
| 28 |
-+ name = linuxefi; |
|
| 29 |
-+ efi = loader/i386/efi/linux.c; |
|
| 30 |
-+ efi = lib/cmdline.c; |
|
| 31 |
-+ enable = i386_efi; |
|
| 32 |
-+ enable = x86_64_efi; |
|
| 33 |
-+}; |
|
| 34 |
-+ |
|
| 35 |
-+module = {
|
|
| 36 |
- name = chain; |
|
| 37 |
- efi = loader/efi/chainloader.c; |
|
| 38 |
- i386_pc = loader/i386/pc/chainloader.c; |
|
| 39 |
-diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c |
|
| 40 |
-index e394cd9..04e804d 100644 |
|
| 41 |
-+++ b/grub-core/kern/dl.c |
|
| 42 |
-@@ -38,6 +38,14 @@ |
|
| 43 |
- #define GRUB_MODULES_MACHINE_READONLY |
|
| 44 |
- #endif |
|
| 45 |
- |
|
| 46 |
-+#ifdef GRUB_MACHINE_EMU |
|
| 47 |
-+#include <sys/mman.h> |
|
| 48 |
-+#endif |
|
| 49 |
-+ |
|
| 50 |
-+#ifdef GRUB_MACHINE_EFI |
|
| 51 |
-+#include <grub/efi/efi.h> |
|
| 52 |
-+#endif |
|
| 53 |
-+ |
|
| 54 |
- |
|
| 55 |
- |
|
| 56 |
- #pragma GCC diagnostic ignored "-Wcast-align" |
|
| 57 |
-@@ -686,6 +694,19 @@ grub_dl_load_file (const char *filename) |
|
| 58 |
- void *core = 0; |
|
| 59 |
- grub_dl_t mod = 0; |
|
| 60 |
- |
|
| 61 |
-+#ifdef GRUB_MACHINE_EFI |
|
| 62 |
-+ if (grub_efi_secure_boot ()) |
|
| 63 |
-+ {
|
|
| 64 |
-+#if 0 |
|
| 65 |
-+ /* This is an error, but grub2-mkconfig still generates a pile of |
|
| 66 |
-+ * insmod commands, so emitting it would be mostly just obnoxious. */ |
|
| 67 |
-+ grub_error (GRUB_ERR_ACCESS_DENIED, |
|
| 68 |
-+ "Secure Boot forbids loading module from %s", filename); |
|
| 69 |
-+#endif |
|
| 70 |
-+ return 0; |
|
| 71 |
-+ } |
|
| 72 |
-+#endif |
|
| 73 |
-+ |
|
| 74 |
- grub_boot_time ("Loading module %s", filename);
|
|
| 75 |
- |
|
| 76 |
- file = grub_file_open (filename); |
|
| 77 |
-diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c |
|
| 78 |
-index d467785..270eba8 100644 |
|
| 79 |
-+++ b/grub-core/kern/efi/efi.c |
|
| 80 |
-@@ -264,6 +264,36 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid, |
|
| 81 |
- return NULL; |
|
| 82 |
- } |
|
| 83 |
- |
|
| 84 |
-+grub_efi_boolean_t |
|
| 85 |
-+grub_efi_secure_boot (void) |
|
| 86 |
-+{
|
|
| 87 |
-+ grub_efi_guid_t efi_var_guid = GRUB_EFI_GLOBAL_VARIABLE_GUID; |
|
| 88 |
-+ grub_size_t datasize; |
|
| 89 |
-+ char *secure_boot = NULL; |
|
| 90 |
-+ char *setup_mode = NULL; |
|
| 91 |
-+ grub_efi_boolean_t ret = 0; |
|
| 92 |
-+ |
|
| 93 |
-+ secure_boot = grub_efi_get_variable("SecureBoot", &efi_var_guid, &datasize);
|
|
| 94 |
-+ |
|
| 95 |
-+ if (datasize != 1 || !secure_boot) |
|
| 96 |
-+ goto out; |
|
| 97 |
-+ |
|
| 98 |
-+ setup_mode = grub_efi_get_variable("SetupMode", &efi_var_guid, &datasize);
|
|
| 99 |
-+ |
|
| 100 |
-+ if (datasize != 1 || !setup_mode) |
|
| 101 |
-+ goto out; |
|
| 102 |
-+ |
|
| 103 |
-+ if (*secure_boot && !*setup_mode) |
|
| 104 |
-+ ret = 1; |
|
| 105 |
-+ |
|
| 106 |
-+ grub_dprintf ("secureboot", "secure_boot = %d, setup_mode = %d\n",
|
|
| 107 |
-+ *secure_boot, *setup_mode); |
|
| 108 |
-+ out: |
|
| 109 |
-+ grub_free (secure_boot); |
|
| 110 |
-+ grub_free (setup_mode); |
|
| 111 |
-+ return ret; |
|
| 112 |
-+} |
|
| 113 |
-+ |
|
| 114 |
- #pragma GCC diagnostic ignored "-Wcast-align" |
|
| 115 |
- |
|
| 116 |
- /* Search the mods section from the PE32/PE32+ image. This code uses |
|
| 117 |
-diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c |
|
| 118 |
-index 20a47aa..efb15cc 100644 |
|
| 119 |
-+++ b/grub-core/kern/efi/mm.c |
|
| 120 |
-@@ -49,6 +49,38 @@ static grub_efi_uintn_t finish_desc_size; |
|
| 121 |
- static grub_efi_uint32_t finish_desc_version; |
|
| 122 |
- int grub_efi_is_finished = 0; |
|
| 123 |
- |
|
| 124 |
-+/* Allocate pages below a specified address */ |
|
| 125 |
-+void * |
|
| 126 |
-+grub_efi_allocate_pages_max (grub_efi_physical_address_t max, |
|
| 127 |
-+ grub_efi_uintn_t pages) |
|
| 128 |
-+{
|
|
| 129 |
-+ grub_efi_status_t status; |
|
| 130 |
-+ grub_efi_boot_services_t *b; |
|
| 131 |
-+ grub_efi_physical_address_t address = max; |
|
| 132 |
-+ |
|
| 133 |
-+ if (max > 0xffffffff) |
|
| 134 |
-+ return 0; |
|
| 135 |
-+ |
|
| 136 |
-+ b = grub_efi_system_table->boot_services; |
|
| 137 |
-+ status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, GRUB_EFI_LOADER_DATA, pages, &address); |
|
| 138 |
-+ |
|
| 139 |
-+ if (status != GRUB_EFI_SUCCESS) |
|
| 140 |
-+ return 0; |
|
| 141 |
-+ |
|
| 142 |
-+ if (address == 0) |
|
| 143 |
-+ {
|
|
| 144 |
-+ /* Uggh, the address 0 was allocated... This is too annoying, |
|
| 145 |
-+ so reallocate another one. */ |
|
| 146 |
-+ address = max; |
|
| 147 |
-+ status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, GRUB_EFI_LOADER_DATA, pages, &address); |
|
| 148 |
-+ grub_efi_free_pages (0, pages); |
|
| 149 |
-+ if (status != GRUB_EFI_SUCCESS) |
|
| 150 |
-+ return 0; |
|
| 151 |
-+ } |
|
| 152 |
-+ |
|
| 153 |
-+ return (void *) ((grub_addr_t) address); |
|
| 154 |
-+} |
|
| 155 |
-+ |
|
| 156 |
- /* Allocate pages. Return the pointer to the first of allocated pages. */ |
|
| 157 |
- void * |
|
| 158 |
- grub_efi_allocate_pages (grub_efi_physical_address_t address, |
|
| 159 |
-diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c |
|
| 160 |
-new file mode 100644 |
|
| 161 |
-index 0000000..78bc216 |
|
| 162 |
-+++ b/grub-core/loader/i386/efi/linux.c |
|
| 163 |
-@@ -0,0 +1,387 @@ |
|
| 164 |
-+/* |
|
| 165 |
-+ * GRUB -- GRand Unified Bootloader |
|
| 166 |
-+ * Copyright (C) 2012 Free Software Foundation, Inc. |
|
| 167 |
-+ * |
|
| 168 |
-+ * GRUB is free software: you can redistribute it and/or modify |
|
| 169 |
-+ * it under the terms of the GNU General Public License as published by |
|
| 170 |
-+ * the Free Software Foundation, either version 3 of the License, or |
|
| 171 |
-+ * (at your option) any later version. |
|
| 172 |
-+ * |
|
| 173 |
-+ * GRUB is distributed in the hope that it will be useful, |
|
| 174 |
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 175 |
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 176 |
-+ * GNU General Public License for more details. |
|
| 177 |
-+ * |
|
| 178 |
-+ * You should have received a copy of the GNU General Public License |
|
| 179 |
-+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>. |
|
| 180 |
-+ */ |
|
| 181 |
-+ |
|
| 182 |
-+#include <grub/loader.h> |
|
| 183 |
-+#include <grub/file.h> |
|
| 184 |
-+#include <grub/err.h> |
|
| 185 |
-+#include <grub/misc.h> |
|
| 186 |
-+#include <grub/types.h> |
|
| 187 |
-+#include <grub/mm.h> |
|
| 188 |
-+#include <grub/cpu/linux.h> |
|
| 189 |
-+#include <grub/command.h> |
|
| 190 |
-+#include <grub/i18n.h> |
|
| 191 |
-+#include <grub/lib/cmdline.h> |
|
| 192 |
-+#include <grub/efi/efi.h> |
|
| 193 |
-+ |
|
| 194 |
-+GRUB_MOD_LICENSE ("GPLv3+");
|
|
| 195 |
-+ |
|
| 196 |
-+static grub_dl_t my_mod; |
|
| 197 |
-+static int loaded; |
|
| 198 |
-+static void *kernel_mem; |
|
| 199 |
-+static grub_uint64_t kernel_size; |
|
| 200 |
-+static grub_uint8_t *initrd_mem; |
|
| 201 |
-+static grub_uint32_t handover_offset; |
|
| 202 |
-+struct linux_kernel_params *params; |
|
| 203 |
-+static char *linux_cmdline; |
|
| 204 |
-+ |
|
| 205 |
-+#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12) |
|
| 206 |
-+ |
|
| 207 |
-+#define SHIM_LOCK_GUID \ |
|
| 208 |
-+ { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }
|
|
| 209 |
-+ |
|
| 210 |
-+struct grub_efi_shim_lock |
|
| 211 |
-+{
|
|
| 212 |
-+ grub_efi_status_t (*verify) (void *buffer, grub_uint32_t size); |
|
| 213 |
-+}; |
|
| 214 |
-+typedef struct grub_efi_shim_lock grub_efi_shim_lock_t; |
|
| 215 |
-+ |
|
| 216 |
-+static grub_efi_boolean_t |
|
| 217 |
-+grub_linuxefi_secure_validate (void *data, grub_uint32_t size) |
|
| 218 |
-+{
|
|
| 219 |
-+ grub_efi_guid_t guid = SHIM_LOCK_GUID; |
|
| 220 |
-+ grub_efi_shim_lock_t *shim_lock; |
|
| 221 |
-+ grub_efi_status_t status; |
|
| 222 |
-+ |
|
| 223 |
-+ grub_dprintf ("linuxefi", "Locating shim protocol\n");
|
|
| 224 |
-+ shim_lock = grub_efi_locate_protocol(&guid, NULL); |
|
| 225 |
-+ |
|
| 226 |
-+ if (!shim_lock) |
|
| 227 |
-+ {
|
|
| 228 |
-+ grub_dprintf ("linuxefi", "shim not available\n");
|
|
| 229 |
-+ return 0; |
|
| 230 |
-+ } |
|
| 231 |
-+ |
|
| 232 |
-+ grub_dprintf ("linuxefi", "Asking shim to verify kernel signature\n");
|
|
| 233 |
-+ status = shim_lock->verify(data, size); |
|
| 234 |
-+ if (status == GRUB_EFI_SUCCESS) |
|
| 235 |
-+ {
|
|
| 236 |
-+ grub_dprintf ("linuxefi", "Kernel signature verification passed\n");
|
|
| 237 |
-+ return 1; |
|
| 238 |
-+ } |
|
| 239 |
-+ |
|
| 240 |
-+ grub_dprintf ("linuxefi", "Kernel signature verification failed (0x%lx)\n",
|
|
| 241 |
-+ (unsigned long) status); |
|
| 242 |
-+ |
|
| 243 |
-+ return 0; |
|
| 244 |
-+} |
|
| 245 |
-+ |
|
| 246 |
-+typedef void(*handover_func)(void *, grub_efi_system_table_t *, struct linux_kernel_params *); |
|
| 247 |
-+ |
|
| 248 |
-+static grub_err_t |
|
| 249 |
-+grub_linuxefi_boot (void) |
|
| 250 |
-+{
|
|
| 251 |
-+ handover_func hf; |
|
| 252 |
-+ int offset = 0; |
|
| 253 |
-+ |
|
| 254 |
-+#ifdef __x86_64__ |
|
| 255 |
-+ offset = 512; |
|
| 256 |
-+#endif |
|
| 257 |
-+ |
|
| 258 |
-+ hf = (handover_func)((char *)kernel_mem + handover_offset + offset); |
|
| 259 |
-+ |
|
| 260 |
-+ asm volatile ("cli");
|
|
| 261 |
-+ |
|
| 262 |
-+ hf (grub_efi_image_handle, grub_efi_system_table, params); |
|
| 263 |
-+ |
|
| 264 |
-+ /* Not reached */ |
|
| 265 |
-+ return GRUB_ERR_NONE; |
|
| 266 |
-+} |
|
| 267 |
-+ |
|
| 268 |
-+static grub_err_t |
|
| 269 |
-+grub_linuxefi_unload (void) |
|
| 270 |
-+{
|
|
| 271 |
-+ grub_dl_unref (my_mod); |
|
| 272 |
-+ loaded = 0; |
|
| 273 |
-+ if (initrd_mem) |
|
| 274 |
-+ grub_efi_free_pages((grub_efi_physical_address_t)initrd_mem, BYTES_TO_PAGES(params->ramdisk_size)); |
|
| 275 |
-+ if (linux_cmdline) |
|
| 276 |
-+ grub_efi_free_pages((grub_efi_physical_address_t)linux_cmdline, BYTES_TO_PAGES(params->cmdline_size + 1)); |
|
| 277 |
-+ if (kernel_mem) |
|
| 278 |
-+ grub_efi_free_pages((grub_efi_physical_address_t)kernel_mem, BYTES_TO_PAGES(kernel_size)); |
|
| 279 |
-+ if (params) |
|
| 280 |
-+ grub_efi_free_pages((grub_efi_physical_address_t)params, BYTES_TO_PAGES(16384)); |
|
| 281 |
-+ return GRUB_ERR_NONE; |
|
| 282 |
-+} |
|
| 283 |
-+ |
|
| 284 |
-+static grub_err_t |
|
| 285 |
-+grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), |
|
| 286 |
-+ int argc, char *argv[]) |
|
| 287 |
-+{
|
|
| 288 |
-+ grub_file_t *files = 0; |
|
| 289 |
-+ int i, nfiles = 0; |
|
| 290 |
-+ grub_size_t size = 0; |
|
| 291 |
-+ grub_uint8_t *ptr; |
|
| 292 |
-+ |
|
| 293 |
-+ if (argc == 0) |
|
| 294 |
-+ {
|
|
| 295 |
-+ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
|
| 296 |
-+ goto fail; |
|
| 297 |
-+ } |
|
| 298 |
-+ |
|
| 299 |
-+ if (!loaded) |
|
| 300 |
-+ {
|
|
| 301 |
-+ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first"));
|
|
| 302 |
-+ goto fail; |
|
| 303 |
-+ } |
|
| 304 |
-+ |
|
| 305 |
-+ files = grub_zalloc (argc * sizeof (files[0])); |
|
| 306 |
-+ if (!files) |
|
| 307 |
-+ goto fail; |
|
| 308 |
-+ |
|
| 309 |
-+ for (i = 0; i < argc; i++) |
|
| 310 |
-+ {
|
|
| 311 |
-+ grub_file_filter_disable_compression (); |
|
| 312 |
-+ files[i] = grub_file_open (argv[i]); |
|
| 313 |
-+ if (! files[i]) |
|
| 314 |
-+ goto fail; |
|
| 315 |
-+ nfiles++; |
|
| 316 |
-+ size += ALIGN_UP (grub_file_size (files[i]), 4); |
|
| 317 |
-+ } |
|
| 318 |
-+ |
|
| 319 |
-+ initrd_mem = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(size)); |
|
| 320 |
-+ |
|
| 321 |
-+ if (!initrd_mem) |
|
| 322 |
-+ {
|
|
| 323 |
-+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate initrd"));
|
|
| 324 |
-+ goto fail; |
|
| 325 |
-+ } |
|
| 326 |
-+ |
|
| 327 |
-+ params->ramdisk_size = size; |
|
| 328 |
-+ params->ramdisk_image = (grub_uint32_t)(grub_uint64_t) initrd_mem; |
|
| 329 |
-+ |
|
| 330 |
-+ ptr = initrd_mem; |
|
| 331 |
-+ |
|
| 332 |
-+ for (i = 0; i < nfiles; i++) |
|
| 333 |
-+ {
|
|
| 334 |
-+ grub_ssize_t cursize = grub_file_size (files[i]); |
|
| 335 |
-+ if (grub_file_read (files[i], ptr, cursize) != cursize) |
|
| 336 |
-+ {
|
|
| 337 |
-+ if (!grub_errno) |
|
| 338 |
-+ grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
|
|
| 339 |
-+ argv[i]); |
|
| 340 |
-+ goto fail; |
|
| 341 |
-+ } |
|
| 342 |
-+ ptr += cursize; |
|
| 343 |
-+ grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4)); |
|
| 344 |
-+ ptr += ALIGN_UP_OVERHEAD (cursize, 4); |
|
| 345 |
-+ } |
|
| 346 |
-+ |
|
| 347 |
-+ params->ramdisk_size = size; |
|
| 348 |
-+ |
|
| 349 |
-+ fail: |
|
| 350 |
-+ for (i = 0; i < nfiles; i++) |
|
| 351 |
-+ grub_file_close (files[i]); |
|
| 352 |
-+ grub_free (files); |
|
| 353 |
-+ |
|
| 354 |
-+ if (initrd_mem && grub_errno) |
|
| 355 |
-+ grub_efi_free_pages((grub_efi_physical_address_t)initrd_mem, BYTES_TO_PAGES(size)); |
|
| 356 |
-+ |
|
| 357 |
-+ return grub_errno; |
|
| 358 |
-+} |
|
| 359 |
-+ |
|
| 360 |
-+static grub_err_t |
|
| 361 |
-+grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), |
|
| 362 |
-+ int argc, char *argv[]) |
|
| 363 |
-+{
|
|
| 364 |
-+ grub_file_t file = 0; |
|
| 365 |
-+ struct linux_kernel_header lh; |
|
| 366 |
-+ grub_ssize_t len, start, filelen; |
|
| 367 |
-+ void *kernel; |
|
| 368 |
-+ grub_err_t fail_errno; |
|
| 369 |
-+ |
|
| 370 |
-+ grub_dl_ref (my_mod); |
|
| 371 |
-+ |
|
| 372 |
-+ if (argc == 0) |
|
| 373 |
-+ {
|
|
| 374 |
-+ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
|
| 375 |
-+ goto fail; |
|
| 376 |
-+ } |
|
| 377 |
-+ |
|
| 378 |
-+ file = grub_file_open (argv[0]); |
|
| 379 |
-+ if (! file) |
|
| 380 |
-+ goto fail; |
|
| 381 |
-+ |
|
| 382 |
-+ filelen = grub_file_size (file); |
|
| 383 |
-+ |
|
| 384 |
-+ kernel = grub_malloc(filelen); |
|
| 385 |
-+ |
|
| 386 |
-+ if (!kernel) |
|
| 387 |
-+ {
|
|
| 388 |
-+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer"));
|
|
| 389 |
-+ goto fail; |
|
| 390 |
-+ } |
|
| 391 |
-+ |
|
| 392 |
-+ if (grub_file_read (file, kernel, filelen) != filelen) |
|
| 393 |
-+ {
|
|
| 394 |
-+ grub_error (GRUB_ERR_FILE_READ_ERROR, N_("Can't read kernel %s"), argv[0]);
|
|
| 395 |
-+ grub_free (kernel); |
|
| 396 |
-+ goto fail; |
|
| 397 |
-+ } |
|
| 398 |
-+ |
|
| 399 |
-+ if (! grub_linuxefi_secure_validate (kernel, filelen)) |
|
| 400 |
-+ {
|
|
| 401 |
-+ grub_error (GRUB_ERR_ACCESS_DENIED, N_("%s has invalid signature"), argv[0]);
|
|
| 402 |
-+ grub_free (kernel); |
|
| 403 |
-+ goto fail; |
|
| 404 |
-+ } |
|
| 405 |
-+ |
|
| 406 |
-+ grub_file_seek (file, 0); |
|
| 407 |
-+ |
|
| 408 |
-+ grub_free(kernel); |
|
| 409 |
-+ |
|
| 410 |
-+ params = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(16384)); |
|
| 411 |
-+ |
|
| 412 |
-+ if (! params) |
|
| 413 |
-+ {
|
|
| 414 |
-+ grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters"); |
|
| 415 |
-+ goto fail; |
|
| 416 |
-+ } |
|
| 417 |
-+ |
|
| 418 |
-+ memset (params, 0, 16384); |
|
| 419 |
-+ |
|
| 420 |
-+ if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh)) |
|
| 421 |
-+ {
|
|
| 422 |
-+ if (!grub_errno) |
|
| 423 |
-+ grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
|
|
| 424 |
-+ argv[0]); |
|
| 425 |
-+ goto fail; |
|
| 426 |
-+ } |
|
| 427 |
-+ |
|
| 428 |
-+ if (lh.boot_flag != grub_cpu_to_le16 (0xaa55)) |
|
| 429 |
-+ {
|
|
| 430 |
-+ grub_error (GRUB_ERR_BAD_OS, N_("invalid magic number"));
|
|
| 431 |
-+ goto fail; |
|
| 432 |
-+ } |
|
| 433 |
-+ |
|
| 434 |
-+ if (lh.setup_sects > GRUB_LINUX_MAX_SETUP_SECTS) |
|
| 435 |
-+ {
|
|
| 436 |
-+ grub_error (GRUB_ERR_BAD_OS, N_("too many setup sectors"));
|
|
| 437 |
-+ goto fail; |
|
| 438 |
-+ } |
|
| 439 |
-+ |
|
| 440 |
-+ if (lh.version < grub_cpu_to_le16 (0x020b)) |
|
| 441 |
-+ {
|
|
| 442 |
-+ grub_error (GRUB_ERR_BAD_OS, N_("kernel too old"));
|
|
| 443 |
-+ goto fail; |
|
| 444 |
-+ } |
|
| 445 |
-+ |
|
| 446 |
-+ if (!lh.handover_offset) |
|
| 447 |
-+ {
|
|
| 448 |
-+ grub_error (GRUB_ERR_BAD_OS, N_("kernel doesn't support EFI handover"));
|
|
| 449 |
-+ goto fail; |
|
| 450 |
-+ } |
|
| 451 |
-+ |
|
| 452 |
-+ linux_cmdline = grub_efi_allocate_pages_max(0x3fffffff, |
|
| 453 |
-+ BYTES_TO_PAGES(lh.cmdline_size + 1)); |
|
| 454 |
-+ |
|
| 455 |
-+ if (!linux_cmdline) |
|
| 456 |
-+ {
|
|
| 457 |
-+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate cmdline"));
|
|
| 458 |
-+ goto fail; |
|
| 459 |
-+ } |
|
| 460 |
-+ |
|
| 461 |
-+ grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE)); |
|
| 462 |
-+ grub_create_loader_cmdline (argc, argv, |
|
| 463 |
-+ linux_cmdline + sizeof (LINUX_IMAGE) - 1, |
|
| 464 |
-+ lh.cmdline_size - (sizeof (LINUX_IMAGE) - 1)); |
|
| 465 |
-+ |
|
| 466 |
-+ lh.cmd_line_ptr = (grub_uint32_t)(grub_uint64_t)linux_cmdline; |
|
| 467 |
-+ |
|
| 468 |
-+ handover_offset = lh.handover_offset; |
|
| 469 |
-+ |
|
| 470 |
-+ start = (lh.setup_sects + 1) * 512; |
|
| 471 |
-+ len = grub_file_size(file) - start; |
|
| 472 |
-+ |
|
| 473 |
-+ kernel_mem = grub_efi_allocate_pages(lh.pref_address, |
|
| 474 |
-+ BYTES_TO_PAGES(lh.init_size)); |
|
| 475 |
-+ |
|
| 476 |
-+ if (!kernel_mem) |
|
| 477 |
-+ kernel_mem = grub_efi_allocate_pages_max(0x3fffffff, |
|
| 478 |
-+ BYTES_TO_PAGES(lh.init_size)); |
|
| 479 |
-+ |
|
| 480 |
-+ if (!kernel_mem) |
|
| 481 |
-+ {
|
|
| 482 |
-+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate kernel"));
|
|
| 483 |
-+ goto fail; |
|
| 484 |
-+ } |
|
| 485 |
-+ |
|
| 486 |
-+ if (grub_file_seek (file, start) == (grub_off_t) -1) |
|
| 487 |
-+ {
|
|
| 488 |
-+ grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
|
|
| 489 |
-+ argv[0]); |
|
| 490 |
-+ goto fail; |
|
| 491 |
-+ } |
|
| 492 |
-+ |
|
| 493 |
-+ if (grub_file_read (file, kernel_mem, len) != len && !grub_errno) |
|
| 494 |
-+ {
|
|
| 495 |
-+ grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
|
|
| 496 |
-+ argv[0]); |
|
| 497 |
-+ } |
|
| 498 |
-+ |
|
| 499 |
-+ if (grub_errno == GRUB_ERR_NONE) |
|
| 500 |
-+ {
|
|
| 501 |
-+ grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0); |
|
| 502 |
-+ loaded = 1; |
|
| 503 |
-+ lh.code32_start = (grub_uint32_t)(grub_uint64_t) kernel_mem; |
|
| 504 |
-+ } |
|
| 505 |
-+ |
|
| 506 |
-+ memcpy(params, &lh, 2 * 512); |
|
| 507 |
-+ |
|
| 508 |
-+ params->type_of_loader = 0x21; |
|
| 509 |
-+ |
|
| 510 |
-+ fail: |
|
| 511 |
-+ fail_errno = grub_errno; |
|
| 512 |
-+ if (file) |
|
| 513 |
-+ grub_file_close (file); |
|
| 514 |
-+ |
|
| 515 |
-+ if (fail_errno != GRUB_ERR_NONE) |
|
| 516 |
-+ {
|
|
| 517 |
-+ grub_dl_unref (my_mod); |
|
| 518 |
-+ loaded = 0; |
|
| 519 |
-+ } |
|
| 520 |
-+ |
|
| 521 |
-+ if (linux_cmdline && !loaded) |
|
| 522 |
-+ grub_efi_free_pages((grub_efi_physical_address_t)linux_cmdline, BYTES_TO_PAGES(lh.cmdline_size + 1)); |
|
| 523 |
-+ |
|
| 524 |
-+ if (kernel_mem && !loaded) |
|
| 525 |
-+ grub_efi_free_pages((grub_efi_physical_address_t)kernel_mem, BYTES_TO_PAGES(kernel_size)); |
|
| 526 |
-+ |
|
| 527 |
-+ if (params && !loaded) |
|
| 528 |
-+ grub_efi_free_pages((grub_efi_physical_address_t)params, BYTES_TO_PAGES(16384)); |
|
| 529 |
-+ |
|
| 530 |
-+ return fail_errno; |
|
| 531 |
-+} |
|
| 532 |
-+ |
|
| 533 |
-+static grub_command_t cmd_linux, cmd_initrd; |
|
| 534 |
-+ |
|
| 535 |
-+GRUB_MOD_INIT(linuxefi) |
|
| 536 |
-+{
|
|
| 537 |
-+ cmd_linux = |
|
| 538 |
-+ grub_register_command ("linuxefi", grub_cmd_linux,
|
|
| 539 |
-+ 0, N_("Load Linux."));
|
|
| 540 |
-+ cmd_initrd = |
|
| 541 |
-+ grub_register_command ("initrdefi", grub_cmd_initrd,
|
|
| 542 |
-+ 0, N_("Load initrd."));
|
|
| 543 |
-+ my_mod = mod; |
|
| 544 |
-+} |
|
| 545 |
-+ |
|
| 546 |
-+GRUB_MOD_FINI(linuxefi) |
|
| 547 |
-+{
|
|
| 548 |
-+ grub_unregister_command (cmd_linux); |
|
| 549 |
-+ grub_unregister_command (cmd_initrd); |
|
| 550 |
-+} |
|
| 551 |
-diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c |
|
| 552 |
-index b15b8cc..fce1b45 100644 |
|
| 553 |
-+++ b/grub-core/loader/i386/linux.c |
|
| 554 |
-@@ -75,6 +75,8 @@ static grub_size_t maximal_cmdline_size; |
|
| 555 |
- static struct linux_kernel_params linux_params; |
|
| 556 |
- static char *linux_cmdline; |
|
| 557 |
- #ifdef GRUB_MACHINE_EFI |
|
| 558 |
-+static int using_linuxefi; |
|
| 559 |
-+static grub_command_t initrdefi_cmd; |
|
| 560 |
- static grub_efi_uintn_t efi_mmap_size; |
|
| 561 |
- #else |
|
| 562 |
- static const grub_size_t efi_mmap_size = 0; |
|
| 563 |
-@@ -689,6 +691,43 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), |
|
| 564 |
- |
|
| 565 |
- grub_dl_ref (my_mod); |
|
| 566 |
- |
|
| 567 |
-+#ifdef GRUB_MACHINE_EFI |
|
| 568 |
-+ using_linuxefi = 0; |
|
| 569 |
-+ if (grub_efi_secure_boot ()) |
|
| 570 |
-+ {
|
|
| 571 |
-+ /* Use linuxefi if SB is enabled, which will require a successful |
|
| 572 |
-+ signature check and then hand over to the kernel without calling |
|
| 573 |
-+ ExitBootServices. |
|
| 574 |
-+ If that fails, however, DO NOT fall back to original 'linux' |
|
| 575 |
-+ command which boots an unsigned kernel. */ |
|
| 576 |
-+ grub_dl_t mod; |
|
| 577 |
-+ grub_command_t linuxefi_cmd; |
|
| 578 |
-+ |
|
| 579 |
-+ grub_dprintf ("linux", "Secure Boot enabled: trying linuxefi\n");
|
|
| 580 |
-+ |
|
| 581 |
-+ mod = grub_dl_load ("linuxefi");
|
|
| 582 |
-+ if (mod) |
|
| 583 |
-+ {
|
|
| 584 |
-+ grub_dl_ref (mod); |
|
| 585 |
-+ linuxefi_cmd = grub_command_find ("linuxefi");
|
|
| 586 |
-+ initrdefi_cmd = grub_command_find ("initrdefi");
|
|
| 587 |
-+ if (linuxefi_cmd && initrdefi_cmd) |
|
| 588 |
-+ {
|
|
| 589 |
-+ (linuxefi_cmd->func) (linuxefi_cmd, argc, argv); |
|
| 590 |
-+ if (grub_errno == GRUB_ERR_NONE) |
|
| 591 |
-+ {
|
|
| 592 |
-+ grub_dprintf ("linux", "Handing off to linuxefi\n");
|
|
| 593 |
-+ using_linuxefi = 1; |
|
| 594 |
-+ return GRUB_ERR_NONE; |
|
| 595 |
-+ } |
|
| 596 |
-+ grub_dprintf ("linux", "linuxefi failed (%d)\n", grub_errno);
|
|
| 597 |
-+ grub_errno = GRUB_ERR_ACCESS_DENIED; |
|
| 598 |
-+ } |
|
| 599 |
-+ } |
|
| 600 |
-+ goto fail; |
|
| 601 |
-+ } |
|
| 602 |
-+#endif |
|
| 603 |
-+ |
|
| 604 |
- if (argc == 0) |
|
| 605 |
- {
|
|
| 606 |
- grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
|
| 607 |
-@@ -1051,6 +1090,12 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), |
|
| 608 |
- grub_err_t err; |
|
| 609 |
- struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 };
|
|
| 610 |
- |
|
| 611 |
-+#ifdef GRUB_MACHINE_EFI |
|
| 612 |
-+ /* If we're using linuxefi, just forward to initrdefi. */ |
|
| 613 |
-+ if (using_linuxefi && initrdefi_cmd) |
|
| 614 |
-+ return (initrdefi_cmd->func) (initrdefi_cmd, argc, argv); |
|
| 615 |
-+#endif |
|
| 616 |
-+ |
|
| 617 |
- if (argc == 0) |
|
| 618 |
- {
|
|
| 619 |
- grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
|
| 620 |
-diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h |
|
| 621 |
-index e9c601f..62a3d97 100644 |
|
| 622 |
-+++ b/include/grub/efi/efi.h |
|
| 623 |
-@@ -40,6 +40,9 @@ void EXPORT_FUNC(grub_efi_stall) (grub_efi_uintn_t microseconds); |
|
| 624 |
- void * |
|
| 625 |
- EXPORT_FUNC(grub_efi_allocate_pages) (grub_efi_physical_address_t address, |
|
| 626 |
- grub_efi_uintn_t pages); |
|
| 627 |
-+void * |
|
| 628 |
-+EXPORT_FUNC(grub_efi_allocate_pages_max) (grub_efi_physical_address_t max, |
|
| 629 |
-+ grub_efi_uintn_t pages); |
|
| 630 |
- void EXPORT_FUNC(grub_efi_free_pages) (grub_efi_physical_address_t address, |
|
| 631 |
- grub_efi_uintn_t pages); |
|
| 632 |
- int |
|
| 633 |
-@@ -73,6 +76,7 @@ EXPORT_FUNC (grub_efi_set_variable) (const char *var, |
|
| 634 |
- const grub_efi_guid_t *guid, |
|
| 635 |
- void *data, |
|
| 636 |
- grub_size_t datasize); |
|
| 637 |
-+grub_efi_boolean_t EXPORT_FUNC (grub_efi_secure_boot) (void); |
|
| 638 |
- int |
|
| 639 |
- EXPORT_FUNC (grub_efi_compare_device_paths) (const grub_efi_device_path_t *dp1, |
|
| 640 |
- const grub_efi_device_path_t *dp2); |
|
| 641 |
-diff --git a/include/grub/i386/linux.h b/include/grub/i386/linux.h |
|
| 642 |
-index da0ca3b..fc36bda 100644 |
|
| 643 |
-+++ b/include/grub/i386/linux.h |
|
| 644 |
-@@ -139,6 +139,7 @@ struct linux_kernel_header |
|
| 645 |
- grub_uint64_t setup_data; |
|
| 646 |
- grub_uint64_t pref_address; |
|
| 647 |
- grub_uint32_t init_size; |
|
| 648 |
-+ grub_uint32_t handover_offset; |
|
| 649 |
- } GRUB_PACKED; |
|
| 650 |
- |
|
| 651 |
- /* Boot parameters for Linux based on 2.6.12. This is used by the setup |
|
| 652 |
-2.8.1 |
|
| 653 |
- |
| 654 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,104 +0,0 @@ |
| 1 |
-%define debug_package %{nil}
|
|
| 2 |
-%define __os_install_post %{nil}
|
|
| 3 |
-Summary: GRand Unified Bootloader |
|
| 4 |
-Name: grub2-efi |
|
| 5 |
-Version: 2.02 |
|
| 6 |
-Release: 8%{?dist}
|
|
| 7 |
-License: GPLv3+ |
|
| 8 |
-URL: http://www.gnu.org/software/grub |
|
| 9 |
-Group: Applications/System |
|
| 10 |
-Vendor: VMware, Inc. |
|
| 11 |
-Distribution: Photon |
|
| 12 |
-Source0: http://alpha.gnu.org/gnu/grub/grub-2.02~rc2.tar.xz |
|
| 13 |
-%define sha1 grub=4f6f3719fd7dbb0449a58547c1b08c9801337663 |
|
| 14 |
-Patch0: 0001-Secure-Boot-support.patch |
|
| 15 |
-BuildRequires: device-mapper-devel |
|
| 16 |
-BuildRequires: xz-devel |
|
| 17 |
-BuildRequires: systemd-devel |
|
| 18 |
-Requires: xz |
|
| 19 |
-Requires: device-mapper |
|
| 20 |
-%description |
|
| 21 |
-The GRUB package contains the GRand Unified Bootloader. |
|
| 22 |
- |
|
| 23 |
-%package lang |
|
| 24 |
-Summary: Additional language files for grub |
|
| 25 |
-Group: System Environment/Programming |
|
| 26 |
-Requires: grub2 >= 2.00 |
|
| 27 |
-%description lang |
|
| 28 |
-These are the additional language files of grub. |
|
| 29 |
- |
|
| 30 |
- |
|
| 31 |
-%prep |
|
| 32 |
-%setup -qn grub-2.02~rc2 |
|
| 33 |
-%patch0 -p1 |
|
| 34 |
-%build |
|
| 35 |
-./autogen.sh |
|
| 36 |
-./configure \ |
|
| 37 |
- --prefix=%{_prefix} \
|
|
| 38 |
- --sbindir=/sbin \ |
|
| 39 |
- --sysconfdir=%{_sysconfdir} \
|
|
| 40 |
- --disable-grub-emu-usb \ |
|
| 41 |
- --disable-werror \ |
|
| 42 |
- --disable-efiemu \ |
|
| 43 |
- --program-transform-name=s,grub,%{name}, \
|
|
| 44 |
- --with-grubdir=grub2 \ |
|
| 45 |
- --with-platform=efi \ |
|
| 46 |
- --target=x86_64 \ |
|
| 47 |
- --with-program-prefix="" \ |
|
| 48 |
- --with-bootdir="/boot" |
|
| 49 |
- |
|
| 50 |
-make %{?_smp_mflags}
|
|
| 51 |
- |
|
| 52 |
-%install |
|
| 53 |
-make DESTDIR=%{buildroot} install
|
|
| 54 |
-mkdir %{buildroot}%{_sysconfdir}/default
|
|
| 55 |
-touch %{buildroot}%{_sysconfdir}/default/grub
|
|
| 56 |
-mkdir %{buildroot}%{_sysconfdir}/sysconfig
|
|
| 57 |
-ln -sf %{_sysconfdir}/default/grub %{buildroot}%{_sysconfdir}/sysconfig/grub
|
|
| 58 |
-mkdir -p %{buildroot}/boot/%{name}
|
|
| 59 |
-touch %{buildroot}/boot/%{name}/grub.cfg
|
|
| 60 |
-rm -rf %{buildroot}%{_infodir}
|
|
| 61 |
-%post -p /sbin/ldconfig |
|
| 62 |
-%postun -p /sbin/ldconfig |
|
| 63 |
-%files |
|
| 64 |
-%defattr(-,root,root) |
|
| 65 |
-%dir %{_sysconfdir}/grub.d
|
|
| 66 |
-%config() %{_sysconfdir}/bash_completion.d/grub
|
|
| 67 |
-%config() %{_sysconfdir}/grub.d/00_header
|
|
| 68 |
-%config() %{_sysconfdir}/grub.d/10_linux
|
|
| 69 |
-%config() %{_sysconfdir}/grub.d/20_linux_xen
|
|
| 70 |
-%config() %{_sysconfdir}/grub.d/30_os-prober
|
|
| 71 |
-%config() %{_sysconfdir}/grub.d/40_custom
|
|
| 72 |
-%config() %{_sysconfdir}/grub.d/41_custom
|
|
| 73 |
-%config() %{_sysconfdir}/grub.d/README
|
|
| 74 |
-/sbin/* |
|
| 75 |
-%{_bindir}/*
|
|
| 76 |
-%{_libdir}/grub/*
|
|
| 77 |
-%{_datarootdir}/grub/*
|
|
| 78 |
-%{_sysconfdir}/sysconfig/grub
|
|
| 79 |
-%{_sysconfdir}/default/grub
|
|
| 80 |
-%ghost %config(noreplace) /boot/%{name}/grub.cfg
|
|
| 81 |
- |
|
| 82 |
-%files lang |
|
| 83 |
-%defattr(-,root,root) |
|
| 84 |
-/usr/share/locale/* |
|
| 85 |
- |
|
| 86 |
-%changelog |
|
| 87 |
-* Thu May 4 2017 Alexey Makhalov <amakhalov@vmware.com> 2.02-8 |
|
| 88 |
-- linuxefi: free allocated memory on error. |
|
| 89 |
-* Fri Apr 14 2017 Alexey Makhalov <amakhalov@vmware.com> 2.02-7 |
|
| 90 |
-- Version update to 2.02~rc2 |
|
| 91 |
-- SecureBoot hardening: forbid unsigned vmlinuz image |
|
| 92 |
-* Wed Mar 22 2017 Alexey Makhalov <amakhalov@vmware.com> 2.02-6 |
|
| 93 |
-- Version update to 2.02~beta3 |
|
| 94 |
-- SecureBoot support |
|
| 95 |
-* Fri Nov 18 2016 Anish Swaminathan <anishs@vmware.com> 2.02-5 |
|
| 96 |
-- Add fix for CVE-2015-8370 |
|
| 97 |
-* Fri Nov 18 2016 Anish Swaminathan <anishs@vmware.com> 2.02-4 |
|
| 98 |
-- Change systemd dependency |
|
| 99 |
-* Thu Oct 06 2016 ChangLee <changlee@vmware.com> 2.02-3 |
|
| 100 |
-- Modified %check |
|
| 101 |
-* Tue May 24 2016 Priyesh Padmavilasom <ppadmavilasom@vmware.com> 2.02-2 |
|
| 102 |
-- GA - Bump release of all rpms |
|
| 103 |
-* Fri Jul 31 2015 Sharath George <sharathg@vmware.com> 2.02-1 |
|
| 104 |
-- Adding EFI support. |
| 105 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,663 @@ |
| 0 |
+From e5d5e5a259a9827e4d6e41e49085f730c773c178 Mon Sep 17 00:00:00 2001 |
|
| 1 |
+From: Alexey Makhalov <amakhalov@vmware.com> |
|
| 2 |
+Date: Tue, 10 Jul 2012 11:58:52 -0400 |
|
| 3 |
+Subject: [PATCH] Secure Boot support |
|
| 4 |
+ |
|
| 5 |
+New commands: linuxefi, initrdefi |
|
| 6 |
+If running under secure boot use linuxefi loader only and linux |
|
| 7 |
+command is fallback to linuxefi. |
|
| 8 |
+Forbid dl file loading (insmod and similar) when secure boot is enabled. |
|
| 9 |
+--- |
|
| 10 |
+ grub-core/Makefile.core.def | 8 + |
|
| 11 |
+ grub-core/kern/dl.c | 21 +++ |
|
| 12 |
+ grub-core/kern/efi/efi.c | 30 +++ |
|
| 13 |
+ grub-core/kern/efi/mm.c | 32 ++++ |
|
| 14 |
+ grub-core/loader/i386/efi/linux.c | 387 ++++++++++++++++++++++++++++++++++++++ |
|
| 15 |
+ grub-core/loader/i386/linux.c | 45 +++++ |
|
| 16 |
+ include/grub/efi/efi.h | 4 + |
|
| 17 |
+ include/grub/i386/linux.h | 1 + |
|
| 18 |
+ 8 files changed, 528 insertions(+) |
|
| 19 |
+ create mode 100644 grub-core/loader/i386/efi/linux.c |
|
| 20 |
+ |
|
| 21 |
+diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def |
|
| 22 |
+index 2dfa22a..68e47a7 100644 |
|
| 23 |
+--- a/grub-core/Makefile.core.def |
|
| 24 |
+@@ -1734,6 +1734,14 @@ module = {
|
|
| 25 |
+ }; |
|
| 26 |
+ |
|
| 27 |
+ module = {
|
|
| 28 |
++ name = linuxefi; |
|
| 29 |
++ efi = loader/i386/efi/linux.c; |
|
| 30 |
++ efi = lib/cmdline.c; |
|
| 31 |
++ enable = i386_efi; |
|
| 32 |
++ enable = x86_64_efi; |
|
| 33 |
++}; |
|
| 34 |
++ |
|
| 35 |
++module = {
|
|
| 36 |
+ name = chain; |
|
| 37 |
+ efi = loader/efi/chainloader.c; |
|
| 38 |
+ i386_pc = loader/i386/pc/chainloader.c; |
|
| 39 |
+diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c |
|
| 40 |
+index e394cd9..04e804d 100644 |
|
| 41 |
+--- a/grub-core/kern/dl.c |
|
| 42 |
+@@ -38,6 +38,14 @@ |
|
| 43 |
+ #define GRUB_MODULES_MACHINE_READONLY |
|
| 44 |
+ #endif |
|
| 45 |
+ |
|
| 46 |
++#ifdef GRUB_MACHINE_EMU |
|
| 47 |
++#include <sys/mman.h> |
|
| 48 |
++#endif |
|
| 49 |
++ |
|
| 50 |
++#ifdef GRUB_MACHINE_EFI |
|
| 51 |
++#include <grub/efi/efi.h> |
|
| 52 |
++#endif |
|
| 53 |
++ |
|
| 54 |
+ |
|
| 55 |
+ |
|
| 56 |
+ #pragma GCC diagnostic ignored "-Wcast-align" |
|
| 57 |
+@@ -686,6 +694,19 @@ grub_dl_load_file (const char *filename) |
|
| 58 |
+ void *core = 0; |
|
| 59 |
+ grub_dl_t mod = 0; |
|
| 60 |
+ |
|
| 61 |
++#ifdef GRUB_MACHINE_EFI |
|
| 62 |
++ if (grub_efi_secure_boot ()) |
|
| 63 |
++ {
|
|
| 64 |
++#if 0 |
|
| 65 |
++ /* This is an error, but grub2-mkconfig still generates a pile of |
|
| 66 |
++ * insmod commands, so emitting it would be mostly just obnoxious. */ |
|
| 67 |
++ grub_error (GRUB_ERR_ACCESS_DENIED, |
|
| 68 |
++ "Secure Boot forbids loading module from %s", filename); |
|
| 69 |
++#endif |
|
| 70 |
++ return 0; |
|
| 71 |
++ } |
|
| 72 |
++#endif |
|
| 73 |
++ |
|
| 74 |
+ grub_boot_time ("Loading module %s", filename);
|
|
| 75 |
+ |
|
| 76 |
+ file = grub_file_open (filename); |
|
| 77 |
+diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c |
|
| 78 |
+index d467785..270eba8 100644 |
|
| 79 |
+--- a/grub-core/kern/efi/efi.c |
|
| 80 |
+@@ -264,6 +264,36 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid, |
|
| 81 |
+ return NULL; |
|
| 82 |
+ } |
|
| 83 |
+ |
|
| 84 |
++grub_efi_boolean_t |
|
| 85 |
++grub_efi_secure_boot (void) |
|
| 86 |
++{
|
|
| 87 |
++ grub_efi_guid_t efi_var_guid = GRUB_EFI_GLOBAL_VARIABLE_GUID; |
|
| 88 |
++ grub_size_t datasize; |
|
| 89 |
++ char *secure_boot = NULL; |
|
| 90 |
++ char *setup_mode = NULL; |
|
| 91 |
++ grub_efi_boolean_t ret = 0; |
|
| 92 |
++ |
|
| 93 |
++ secure_boot = grub_efi_get_variable("SecureBoot", &efi_var_guid, &datasize);
|
|
| 94 |
++ |
|
| 95 |
++ if (datasize != 1 || !secure_boot) |
|
| 96 |
++ goto out; |
|
| 97 |
++ |
|
| 98 |
++ setup_mode = grub_efi_get_variable("SetupMode", &efi_var_guid, &datasize);
|
|
| 99 |
++ |
|
| 100 |
++ if (datasize != 1 || !setup_mode) |
|
| 101 |
++ goto out; |
|
| 102 |
++ |
|
| 103 |
++ if (*secure_boot && !*setup_mode) |
|
| 104 |
++ ret = 1; |
|
| 105 |
++ |
|
| 106 |
++ grub_dprintf ("secureboot", "secure_boot = %d, setup_mode = %d\n",
|
|
| 107 |
++ *secure_boot, *setup_mode); |
|
| 108 |
++ out: |
|
| 109 |
++ grub_free (secure_boot); |
|
| 110 |
++ grub_free (setup_mode); |
|
| 111 |
++ return ret; |
|
| 112 |
++} |
|
| 113 |
++ |
|
| 114 |
+ #pragma GCC diagnostic ignored "-Wcast-align" |
|
| 115 |
+ |
|
| 116 |
+ /* Search the mods section from the PE32/PE32+ image. This code uses |
|
| 117 |
+diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c |
|
| 118 |
+index 20a47aa..efb15cc 100644 |
|
| 119 |
+--- a/grub-core/kern/efi/mm.c |
|
| 120 |
+@@ -49,6 +49,38 @@ static grub_efi_uintn_t finish_desc_size; |
|
| 121 |
+ static grub_efi_uint32_t finish_desc_version; |
|
| 122 |
+ int grub_efi_is_finished = 0; |
|
| 123 |
+ |
|
| 124 |
++/* Allocate pages below a specified address */ |
|
| 125 |
++void * |
|
| 126 |
++grub_efi_allocate_pages_max (grub_efi_physical_address_t max, |
|
| 127 |
++ grub_efi_uintn_t pages) |
|
| 128 |
++{
|
|
| 129 |
++ grub_efi_status_t status; |
|
| 130 |
++ grub_efi_boot_services_t *b; |
|
| 131 |
++ grub_efi_physical_address_t address = max; |
|
| 132 |
++ |
|
| 133 |
++ if (max > 0xffffffff) |
|
| 134 |
++ return 0; |
|
| 135 |
++ |
|
| 136 |
++ b = grub_efi_system_table->boot_services; |
|
| 137 |
++ status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, GRUB_EFI_LOADER_DATA, pages, &address); |
|
| 138 |
++ |
|
| 139 |
++ if (status != GRUB_EFI_SUCCESS) |
|
| 140 |
++ return 0; |
|
| 141 |
++ |
|
| 142 |
++ if (address == 0) |
|
| 143 |
++ {
|
|
| 144 |
++ /* Uggh, the address 0 was allocated... This is too annoying, |
|
| 145 |
++ so reallocate another one. */ |
|
| 146 |
++ address = max; |
|
| 147 |
++ status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, GRUB_EFI_LOADER_DATA, pages, &address); |
|
| 148 |
++ grub_efi_free_pages (0, pages); |
|
| 149 |
++ if (status != GRUB_EFI_SUCCESS) |
|
| 150 |
++ return 0; |
|
| 151 |
++ } |
|
| 152 |
++ |
|
| 153 |
++ return (void *) ((grub_addr_t) address); |
|
| 154 |
++} |
|
| 155 |
++ |
|
| 156 |
+ /* Allocate pages. Return the pointer to the first of allocated pages. */ |
|
| 157 |
+ void * |
|
| 158 |
+ grub_efi_allocate_pages (grub_efi_physical_address_t address, |
|
| 159 |
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c |
|
| 160 |
+new file mode 100644 |
|
| 161 |
+index 0000000..78bc216 |
|
| 162 |
+--- /dev/null |
|
| 163 |
+@@ -0,0 +1,387 @@ |
|
| 164 |
++/* |
|
| 165 |
++ * GRUB -- GRand Unified Bootloader |
|
| 166 |
++ * Copyright (C) 2012 Free Software Foundation, Inc. |
|
| 167 |
++ * |
|
| 168 |
++ * GRUB is free software: you can redistribute it and/or modify |
|
| 169 |
++ * it under the terms of the GNU General Public License as published by |
|
| 170 |
++ * the Free Software Foundation, either version 3 of the License, or |
|
| 171 |
++ * (at your option) any later version. |
|
| 172 |
++ * |
|
| 173 |
++ * GRUB is distributed in the hope that it will be useful, |
|
| 174 |
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 175 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 176 |
++ * GNU General Public License for more details. |
|
| 177 |
++ * |
|
| 178 |
++ * You should have received a copy of the GNU General Public License |
|
| 179 |
++ * along with GRUB. If not, see <http://www.gnu.org/licenses/>. |
|
| 180 |
++ */ |
|
| 181 |
++ |
|
| 182 |
++#include <grub/loader.h> |
|
| 183 |
++#include <grub/file.h> |
|
| 184 |
++#include <grub/err.h> |
|
| 185 |
++#include <grub/misc.h> |
|
| 186 |
++#include <grub/types.h> |
|
| 187 |
++#include <grub/mm.h> |
|
| 188 |
++#include <grub/cpu/linux.h> |
|
| 189 |
++#include <grub/command.h> |
|
| 190 |
++#include <grub/i18n.h> |
|
| 191 |
++#include <grub/lib/cmdline.h> |
|
| 192 |
++#include <grub/efi/efi.h> |
|
| 193 |
++ |
|
| 194 |
++GRUB_MOD_LICENSE ("GPLv3+");
|
|
| 195 |
++ |
|
| 196 |
++static grub_dl_t my_mod; |
|
| 197 |
++static int loaded; |
|
| 198 |
++static void *kernel_mem; |
|
| 199 |
++static grub_uint64_t kernel_size; |
|
| 200 |
++static grub_uint8_t *initrd_mem; |
|
| 201 |
++static grub_uint32_t handover_offset; |
|
| 202 |
++struct linux_kernel_params *params; |
|
| 203 |
++static char *linux_cmdline; |
|
| 204 |
++ |
|
| 205 |
++#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12) |
|
| 206 |
++ |
|
| 207 |
++#define SHIM_LOCK_GUID \ |
|
| 208 |
++ { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }
|
|
| 209 |
++ |
|
| 210 |
++struct grub_efi_shim_lock |
|
| 211 |
++{
|
|
| 212 |
++ grub_efi_status_t (*verify) (void *buffer, grub_uint32_t size); |
|
| 213 |
++}; |
|
| 214 |
++typedef struct grub_efi_shim_lock grub_efi_shim_lock_t; |
|
| 215 |
++ |
|
| 216 |
++static grub_efi_boolean_t |
|
| 217 |
++grub_linuxefi_secure_validate (void *data, grub_uint32_t size) |
|
| 218 |
++{
|
|
| 219 |
++ grub_efi_guid_t guid = SHIM_LOCK_GUID; |
|
| 220 |
++ grub_efi_shim_lock_t *shim_lock; |
|
| 221 |
++ grub_efi_status_t status; |
|
| 222 |
++ |
|
| 223 |
++ grub_dprintf ("linuxefi", "Locating shim protocol\n");
|
|
| 224 |
++ shim_lock = grub_efi_locate_protocol(&guid, NULL); |
|
| 225 |
++ |
|
| 226 |
++ if (!shim_lock) |
|
| 227 |
++ {
|
|
| 228 |
++ grub_dprintf ("linuxefi", "shim not available\n");
|
|
| 229 |
++ return 0; |
|
| 230 |
++ } |
|
| 231 |
++ |
|
| 232 |
++ grub_dprintf ("linuxefi", "Asking shim to verify kernel signature\n");
|
|
| 233 |
++ status = shim_lock->verify(data, size); |
|
| 234 |
++ if (status == GRUB_EFI_SUCCESS) |
|
| 235 |
++ {
|
|
| 236 |
++ grub_dprintf ("linuxefi", "Kernel signature verification passed\n");
|
|
| 237 |
++ return 1; |
|
| 238 |
++ } |
|
| 239 |
++ |
|
| 240 |
++ grub_dprintf ("linuxefi", "Kernel signature verification failed (0x%lx)\n",
|
|
| 241 |
++ (unsigned long) status); |
|
| 242 |
++ |
|
| 243 |
++ return 0; |
|
| 244 |
++} |
|
| 245 |
++ |
|
| 246 |
++typedef void(*handover_func)(void *, grub_efi_system_table_t *, struct linux_kernel_params *); |
|
| 247 |
++ |
|
| 248 |
++static grub_err_t |
|
| 249 |
++grub_linuxefi_boot (void) |
|
| 250 |
++{
|
|
| 251 |
++ handover_func hf; |
|
| 252 |
++ int offset = 0; |
|
| 253 |
++ |
|
| 254 |
++#ifdef __x86_64__ |
|
| 255 |
++ offset = 512; |
|
| 256 |
++#endif |
|
| 257 |
++ |
|
| 258 |
++ hf = (handover_func)((char *)kernel_mem + handover_offset + offset); |
|
| 259 |
++ |
|
| 260 |
++ asm volatile ("cli");
|
|
| 261 |
++ |
|
| 262 |
++ hf (grub_efi_image_handle, grub_efi_system_table, params); |
|
| 263 |
++ |
|
| 264 |
++ /* Not reached */ |
|
| 265 |
++ return GRUB_ERR_NONE; |
|
| 266 |
++} |
|
| 267 |
++ |
|
| 268 |
++static grub_err_t |
|
| 269 |
++grub_linuxefi_unload (void) |
|
| 270 |
++{
|
|
| 271 |
++ grub_dl_unref (my_mod); |
|
| 272 |
++ loaded = 0; |
|
| 273 |
++ if (initrd_mem) |
|
| 274 |
++ grub_efi_free_pages((grub_efi_physical_address_t)initrd_mem, BYTES_TO_PAGES(params->ramdisk_size)); |
|
| 275 |
++ if (linux_cmdline) |
|
| 276 |
++ grub_efi_free_pages((grub_efi_physical_address_t)linux_cmdline, BYTES_TO_PAGES(params->cmdline_size + 1)); |
|
| 277 |
++ if (kernel_mem) |
|
| 278 |
++ grub_efi_free_pages((grub_efi_physical_address_t)kernel_mem, BYTES_TO_PAGES(kernel_size)); |
|
| 279 |
++ if (params) |
|
| 280 |
++ grub_efi_free_pages((grub_efi_physical_address_t)params, BYTES_TO_PAGES(16384)); |
|
| 281 |
++ return GRUB_ERR_NONE; |
|
| 282 |
++} |
|
| 283 |
++ |
|
| 284 |
++static grub_err_t |
|
| 285 |
++grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), |
|
| 286 |
++ int argc, char *argv[]) |
|
| 287 |
++{
|
|
| 288 |
++ grub_file_t *files = 0; |
|
| 289 |
++ int i, nfiles = 0; |
|
| 290 |
++ grub_size_t size = 0; |
|
| 291 |
++ grub_uint8_t *ptr; |
|
| 292 |
++ |
|
| 293 |
++ if (argc == 0) |
|
| 294 |
++ {
|
|
| 295 |
++ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
|
| 296 |
++ goto fail; |
|
| 297 |
++ } |
|
| 298 |
++ |
|
| 299 |
++ if (!loaded) |
|
| 300 |
++ {
|
|
| 301 |
++ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first"));
|
|
| 302 |
++ goto fail; |
|
| 303 |
++ } |
|
| 304 |
++ |
|
| 305 |
++ files = grub_zalloc (argc * sizeof (files[0])); |
|
| 306 |
++ if (!files) |
|
| 307 |
++ goto fail; |
|
| 308 |
++ |
|
| 309 |
++ for (i = 0; i < argc; i++) |
|
| 310 |
++ {
|
|
| 311 |
++ grub_file_filter_disable_compression (); |
|
| 312 |
++ files[i] = grub_file_open (argv[i]); |
|
| 313 |
++ if (! files[i]) |
|
| 314 |
++ goto fail; |
|
| 315 |
++ nfiles++; |
|
| 316 |
++ size += ALIGN_UP (grub_file_size (files[i]), 4); |
|
| 317 |
++ } |
|
| 318 |
++ |
|
| 319 |
++ initrd_mem = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(size)); |
|
| 320 |
++ |
|
| 321 |
++ if (!initrd_mem) |
|
| 322 |
++ {
|
|
| 323 |
++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate initrd"));
|
|
| 324 |
++ goto fail; |
|
| 325 |
++ } |
|
| 326 |
++ |
|
| 327 |
++ params->ramdisk_size = size; |
|
| 328 |
++ params->ramdisk_image = (grub_uint32_t)(grub_uint64_t) initrd_mem; |
|
| 329 |
++ |
|
| 330 |
++ ptr = initrd_mem; |
|
| 331 |
++ |
|
| 332 |
++ for (i = 0; i < nfiles; i++) |
|
| 333 |
++ {
|
|
| 334 |
++ grub_ssize_t cursize = grub_file_size (files[i]); |
|
| 335 |
++ if (grub_file_read (files[i], ptr, cursize) != cursize) |
|
| 336 |
++ {
|
|
| 337 |
++ if (!grub_errno) |
|
| 338 |
++ grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
|
|
| 339 |
++ argv[i]); |
|
| 340 |
++ goto fail; |
|
| 341 |
++ } |
|
| 342 |
++ ptr += cursize; |
|
| 343 |
++ grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4)); |
|
| 344 |
++ ptr += ALIGN_UP_OVERHEAD (cursize, 4); |
|
| 345 |
++ } |
|
| 346 |
++ |
|
| 347 |
++ params->ramdisk_size = size; |
|
| 348 |
++ |
|
| 349 |
++ fail: |
|
| 350 |
++ for (i = 0; i < nfiles; i++) |
|
| 351 |
++ grub_file_close (files[i]); |
|
| 352 |
++ grub_free (files); |
|
| 353 |
++ |
|
| 354 |
++ if (initrd_mem && grub_errno) |
|
| 355 |
++ grub_efi_free_pages((grub_efi_physical_address_t)initrd_mem, BYTES_TO_PAGES(size)); |
|
| 356 |
++ |
|
| 357 |
++ return grub_errno; |
|
| 358 |
++} |
|
| 359 |
++ |
|
| 360 |
++static grub_err_t |
|
| 361 |
++grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), |
|
| 362 |
++ int argc, char *argv[]) |
|
| 363 |
++{
|
|
| 364 |
++ grub_file_t file = 0; |
|
| 365 |
++ struct linux_kernel_header lh; |
|
| 366 |
++ grub_ssize_t len, start, filelen; |
|
| 367 |
++ void *kernel; |
|
| 368 |
++ grub_err_t fail_errno; |
|
| 369 |
++ |
|
| 370 |
++ grub_dl_ref (my_mod); |
|
| 371 |
++ |
|
| 372 |
++ if (argc == 0) |
|
| 373 |
++ {
|
|
| 374 |
++ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
|
| 375 |
++ goto fail; |
|
| 376 |
++ } |
|
| 377 |
++ |
|
| 378 |
++ file = grub_file_open (argv[0]); |
|
| 379 |
++ if (! file) |
|
| 380 |
++ goto fail; |
|
| 381 |
++ |
|
| 382 |
++ filelen = grub_file_size (file); |
|
| 383 |
++ |
|
| 384 |
++ kernel = grub_malloc(filelen); |
|
| 385 |
++ |
|
| 386 |
++ if (!kernel) |
|
| 387 |
++ {
|
|
| 388 |
++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer"));
|
|
| 389 |
++ goto fail; |
|
| 390 |
++ } |
|
| 391 |
++ |
|
| 392 |
++ if (grub_file_read (file, kernel, filelen) != filelen) |
|
| 393 |
++ {
|
|
| 394 |
++ grub_error (GRUB_ERR_FILE_READ_ERROR, N_("Can't read kernel %s"), argv[0]);
|
|
| 395 |
++ grub_free (kernel); |
|
| 396 |
++ goto fail; |
|
| 397 |
++ } |
|
| 398 |
++ |
|
| 399 |
++ if (! grub_linuxefi_secure_validate (kernel, filelen)) |
|
| 400 |
++ {
|
|
| 401 |
++ grub_error (GRUB_ERR_ACCESS_DENIED, N_("%s has invalid signature"), argv[0]);
|
|
| 402 |
++ grub_free (kernel); |
|
| 403 |
++ goto fail; |
|
| 404 |
++ } |
|
| 405 |
++ |
|
| 406 |
++ grub_file_seek (file, 0); |
|
| 407 |
++ |
|
| 408 |
++ grub_free(kernel); |
|
| 409 |
++ |
|
| 410 |
++ params = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(16384)); |
|
| 411 |
++ |
|
| 412 |
++ if (! params) |
|
| 413 |
++ {
|
|
| 414 |
++ grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters"); |
|
| 415 |
++ goto fail; |
|
| 416 |
++ } |
|
| 417 |
++ |
|
| 418 |
++ memset (params, 0, 16384); |
|
| 419 |
++ |
|
| 420 |
++ if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh)) |
|
| 421 |
++ {
|
|
| 422 |
++ if (!grub_errno) |
|
| 423 |
++ grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
|
|
| 424 |
++ argv[0]); |
|
| 425 |
++ goto fail; |
|
| 426 |
++ } |
|
| 427 |
++ |
|
| 428 |
++ if (lh.boot_flag != grub_cpu_to_le16 (0xaa55)) |
|
| 429 |
++ {
|
|
| 430 |
++ grub_error (GRUB_ERR_BAD_OS, N_("invalid magic number"));
|
|
| 431 |
++ goto fail; |
|
| 432 |
++ } |
|
| 433 |
++ |
|
| 434 |
++ if (lh.setup_sects > GRUB_LINUX_MAX_SETUP_SECTS) |
|
| 435 |
++ {
|
|
| 436 |
++ grub_error (GRUB_ERR_BAD_OS, N_("too many setup sectors"));
|
|
| 437 |
++ goto fail; |
|
| 438 |
++ } |
|
| 439 |
++ |
|
| 440 |
++ if (lh.version < grub_cpu_to_le16 (0x020b)) |
|
| 441 |
++ {
|
|
| 442 |
++ grub_error (GRUB_ERR_BAD_OS, N_("kernel too old"));
|
|
| 443 |
++ goto fail; |
|
| 444 |
++ } |
|
| 445 |
++ |
|
| 446 |
++ if (!lh.handover_offset) |
|
| 447 |
++ {
|
|
| 448 |
++ grub_error (GRUB_ERR_BAD_OS, N_("kernel doesn't support EFI handover"));
|
|
| 449 |
++ goto fail; |
|
| 450 |
++ } |
|
| 451 |
++ |
|
| 452 |
++ linux_cmdline = grub_efi_allocate_pages_max(0x3fffffff, |
|
| 453 |
++ BYTES_TO_PAGES(lh.cmdline_size + 1)); |
|
| 454 |
++ |
|
| 455 |
++ if (!linux_cmdline) |
|
| 456 |
++ {
|
|
| 457 |
++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate cmdline"));
|
|
| 458 |
++ goto fail; |
|
| 459 |
++ } |
|
| 460 |
++ |
|
| 461 |
++ grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE)); |
|
| 462 |
++ grub_create_loader_cmdline (argc, argv, |
|
| 463 |
++ linux_cmdline + sizeof (LINUX_IMAGE) - 1, |
|
| 464 |
++ lh.cmdline_size - (sizeof (LINUX_IMAGE) - 1)); |
|
| 465 |
++ |
|
| 466 |
++ lh.cmd_line_ptr = (grub_uint32_t)(grub_uint64_t)linux_cmdline; |
|
| 467 |
++ |
|
| 468 |
++ handover_offset = lh.handover_offset; |
|
| 469 |
++ |
|
| 470 |
++ start = (lh.setup_sects + 1) * 512; |
|
| 471 |
++ len = grub_file_size(file) - start; |
|
| 472 |
++ |
|
| 473 |
++ kernel_mem = grub_efi_allocate_pages(lh.pref_address, |
|
| 474 |
++ BYTES_TO_PAGES(lh.init_size)); |
|
| 475 |
++ |
|
| 476 |
++ if (!kernel_mem) |
|
| 477 |
++ kernel_mem = grub_efi_allocate_pages_max(0x3fffffff, |
|
| 478 |
++ BYTES_TO_PAGES(lh.init_size)); |
|
| 479 |
++ |
|
| 480 |
++ if (!kernel_mem) |
|
| 481 |
++ {
|
|
| 482 |
++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate kernel"));
|
|
| 483 |
++ goto fail; |
|
| 484 |
++ } |
|
| 485 |
++ |
|
| 486 |
++ if (grub_file_seek (file, start) == (grub_off_t) -1) |
|
| 487 |
++ {
|
|
| 488 |
++ grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
|
|
| 489 |
++ argv[0]); |
|
| 490 |
++ goto fail; |
|
| 491 |
++ } |
|
| 492 |
++ |
|
| 493 |
++ if (grub_file_read (file, kernel_mem, len) != len && !grub_errno) |
|
| 494 |
++ {
|
|
| 495 |
++ grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
|
|
| 496 |
++ argv[0]); |
|
| 497 |
++ } |
|
| 498 |
++ |
|
| 499 |
++ if (grub_errno == GRUB_ERR_NONE) |
|
| 500 |
++ {
|
|
| 501 |
++ grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0); |
|
| 502 |
++ loaded = 1; |
|
| 503 |
++ lh.code32_start = (grub_uint32_t)(grub_uint64_t) kernel_mem; |
|
| 504 |
++ } |
|
| 505 |
++ |
|
| 506 |
++ memcpy(params, &lh, 2 * 512); |
|
| 507 |
++ |
|
| 508 |
++ params->type_of_loader = 0x21; |
|
| 509 |
++ |
|
| 510 |
++ fail: |
|
| 511 |
++ fail_errno = grub_errno; |
|
| 512 |
++ if (file) |
|
| 513 |
++ grub_file_close (file); |
|
| 514 |
++ |
|
| 515 |
++ if (fail_errno != GRUB_ERR_NONE) |
|
| 516 |
++ {
|
|
| 517 |
++ grub_dl_unref (my_mod); |
|
| 518 |
++ loaded = 0; |
|
| 519 |
++ } |
|
| 520 |
++ |
|
| 521 |
++ if (linux_cmdline && !loaded) |
|
| 522 |
++ grub_efi_free_pages((grub_efi_physical_address_t)linux_cmdline, BYTES_TO_PAGES(lh.cmdline_size + 1)); |
|
| 523 |
++ |
|
| 524 |
++ if (kernel_mem && !loaded) |
|
| 525 |
++ grub_efi_free_pages((grub_efi_physical_address_t)kernel_mem, BYTES_TO_PAGES(kernel_size)); |
|
| 526 |
++ |
|
| 527 |
++ if (params && !loaded) |
|
| 528 |
++ grub_efi_free_pages((grub_efi_physical_address_t)params, BYTES_TO_PAGES(16384)); |
|
| 529 |
++ |
|
| 530 |
++ return fail_errno; |
|
| 531 |
++} |
|
| 532 |
++ |
|
| 533 |
++static grub_command_t cmd_linux, cmd_initrd; |
|
| 534 |
++ |
|
| 535 |
++GRUB_MOD_INIT(linuxefi) |
|
| 536 |
++{
|
|
| 537 |
++ cmd_linux = |
|
| 538 |
++ grub_register_command ("linuxefi", grub_cmd_linux,
|
|
| 539 |
++ 0, N_("Load Linux."));
|
|
| 540 |
++ cmd_initrd = |
|
| 541 |
++ grub_register_command ("initrdefi", grub_cmd_initrd,
|
|
| 542 |
++ 0, N_("Load initrd."));
|
|
| 543 |
++ my_mod = mod; |
|
| 544 |
++} |
|
| 545 |
++ |
|
| 546 |
++GRUB_MOD_FINI(linuxefi) |
|
| 547 |
++{
|
|
| 548 |
++ grub_unregister_command (cmd_linux); |
|
| 549 |
++ grub_unregister_command (cmd_initrd); |
|
| 550 |
++} |
|
| 551 |
+diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c |
|
| 552 |
+index b15b8cc..fce1b45 100644 |
|
| 553 |
+--- a/grub-core/loader/i386/linux.c |
|
| 554 |
+@@ -75,6 +75,8 @@ static grub_size_t maximal_cmdline_size; |
|
| 555 |
+ static struct linux_kernel_params linux_params; |
|
| 556 |
+ static char *linux_cmdline; |
|
| 557 |
+ #ifdef GRUB_MACHINE_EFI |
|
| 558 |
++static int using_linuxefi; |
|
| 559 |
++static grub_command_t initrdefi_cmd; |
|
| 560 |
+ static grub_efi_uintn_t efi_mmap_size; |
|
| 561 |
+ #else |
|
| 562 |
+ static const grub_size_t efi_mmap_size = 0; |
|
| 563 |
+@@ -689,6 +691,43 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), |
|
| 564 |
+ |
|
| 565 |
+ grub_dl_ref (my_mod); |
|
| 566 |
+ |
|
| 567 |
++#ifdef GRUB_MACHINE_EFI |
|
| 568 |
++ using_linuxefi = 0; |
|
| 569 |
++ if (grub_efi_secure_boot ()) |
|
| 570 |
++ {
|
|
| 571 |
++ /* Use linuxefi if SB is enabled, which will require a successful |
|
| 572 |
++ signature check and then hand over to the kernel without calling |
|
| 573 |
++ ExitBootServices. |
|
| 574 |
++ If that fails, however, DO NOT fall back to original 'linux' |
|
| 575 |
++ command which boots an unsigned kernel. */ |
|
| 576 |
++ grub_dl_t mod; |
|
| 577 |
++ grub_command_t linuxefi_cmd; |
|
| 578 |
++ |
|
| 579 |
++ grub_dprintf ("linux", "Secure Boot enabled: trying linuxefi\n");
|
|
| 580 |
++ |
|
| 581 |
++ mod = grub_dl_load ("linuxefi");
|
|
| 582 |
++ if (mod) |
|
| 583 |
++ {
|
|
| 584 |
++ grub_dl_ref (mod); |
|
| 585 |
++ linuxefi_cmd = grub_command_find ("linuxefi");
|
|
| 586 |
++ initrdefi_cmd = grub_command_find ("initrdefi");
|
|
| 587 |
++ if (linuxefi_cmd && initrdefi_cmd) |
|
| 588 |
++ {
|
|
| 589 |
++ (linuxefi_cmd->func) (linuxefi_cmd, argc, argv); |
|
| 590 |
++ if (grub_errno == GRUB_ERR_NONE) |
|
| 591 |
++ {
|
|
| 592 |
++ grub_dprintf ("linux", "Handing off to linuxefi\n");
|
|
| 593 |
++ using_linuxefi = 1; |
|
| 594 |
++ return GRUB_ERR_NONE; |
|
| 595 |
++ } |
|
| 596 |
++ grub_dprintf ("linux", "linuxefi failed (%d)\n", grub_errno);
|
|
| 597 |
++ grub_errno = GRUB_ERR_ACCESS_DENIED; |
|
| 598 |
++ } |
|
| 599 |
++ } |
|
| 600 |
++ goto fail; |
|
| 601 |
++ } |
|
| 602 |
++#endif |
|
| 603 |
++ |
|
| 604 |
+ if (argc == 0) |
|
| 605 |
+ {
|
|
| 606 |
+ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
|
| 607 |
+@@ -1051,6 +1090,12 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), |
|
| 608 |
+ grub_err_t err; |
|
| 609 |
+ struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 };
|
|
| 610 |
+ |
|
| 611 |
++#ifdef GRUB_MACHINE_EFI |
|
| 612 |
++ /* If we're using linuxefi, just forward to initrdefi. */ |
|
| 613 |
++ if (using_linuxefi && initrdefi_cmd) |
|
| 614 |
++ return (initrdefi_cmd->func) (initrdefi_cmd, argc, argv); |
|
| 615 |
++#endif |
|
| 616 |
++ |
|
| 617 |
+ if (argc == 0) |
|
| 618 |
+ {
|
|
| 619 |
+ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
|
| 620 |
+diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h |
|
| 621 |
+index e9c601f..62a3d97 100644 |
|
| 622 |
+--- a/include/grub/efi/efi.h |
|
| 623 |
+@@ -40,6 +40,9 @@ void EXPORT_FUNC(grub_efi_stall) (grub_efi_uintn_t microseconds); |
|
| 624 |
+ void * |
|
| 625 |
+ EXPORT_FUNC(grub_efi_allocate_pages) (grub_efi_physical_address_t address, |
|
| 626 |
+ grub_efi_uintn_t pages); |
|
| 627 |
++void * |
|
| 628 |
++EXPORT_FUNC(grub_efi_allocate_pages_max) (grub_efi_physical_address_t max, |
|
| 629 |
++ grub_efi_uintn_t pages); |
|
| 630 |
+ void EXPORT_FUNC(grub_efi_free_pages) (grub_efi_physical_address_t address, |
|
| 631 |
+ grub_efi_uintn_t pages); |
|
| 632 |
+ int |
|
| 633 |
+@@ -73,6 +76,7 @@ EXPORT_FUNC (grub_efi_set_variable) (const char *var, |
|
| 634 |
+ const grub_efi_guid_t *guid, |
|
| 635 |
+ void *data, |
|
| 636 |
+ grub_size_t datasize); |
|
| 637 |
++grub_efi_boolean_t EXPORT_FUNC (grub_efi_secure_boot) (void); |
|
| 638 |
+ int |
|
| 639 |
+ EXPORT_FUNC (grub_efi_compare_device_paths) (const grub_efi_device_path_t *dp1, |
|
| 640 |
+ const grub_efi_device_path_t *dp2); |
|
| 641 |
+diff --git a/include/grub/i386/linux.h b/include/grub/i386/linux.h |
|
| 642 |
+index da0ca3b..fc36bda 100644 |
|
| 643 |
+--- a/include/grub/i386/linux.h |
|
| 644 |
+@@ -139,6 +139,7 @@ struct linux_kernel_header |
|
| 645 |
+ grub_uint64_t setup_data; |
|
| 646 |
+ grub_uint64_t pref_address; |
|
| 647 |
+ grub_uint32_t init_size; |
|
| 648 |
++ grub_uint32_t handover_offset; |
|
| 649 |
+ } GRUB_PACKED; |
|
| 650 |
+ |
|
| 651 |
+ /* Boot parameters for Linux based on 2.6.12. This is used by the setup |
|
| 652 |
+-- |
|
| 653 |
+2.8.1 |
|
| 654 |
+ |
| ... | ... |
@@ -3,7 +3,7 @@ |
| 3 | 3 |
Summary: GRand Unified Bootloader |
| 4 | 4 |
Name: grub2 |
| 5 | 5 |
Version: 2.02 |
| 6 |
-Release: 8%{?dist}
|
|
| 6 |
+Release: 9%{?dist}
|
|
| 7 | 7 |
License: GPLv3+ |
| 8 | 8 |
URL: http://www.gnu.org/software/grub |
| 9 | 9 |
Group: Applications/System |
| ... | ... |
@@ -12,6 +12,7 @@ Distribution: Photon |
| 12 | 12 |
Source0: http://alpha.gnu.org/gnu/grub/grub-2.02~rc2.tar.xz |
| 13 | 13 |
%define sha1 grub=4f6f3719fd7dbb0449a58547c1b08c9801337663 |
| 14 | 14 |
Patch0: Fix_to_boot_entries_with_out_password.patch |
| 15 |
+Patch1: 0001-Secure-Boot-support.patch |
|
| 15 | 16 |
BuildRequires: device-mapper-devel |
| 16 | 17 |
BuildRequires: xz-devel |
| 17 | 18 |
BuildRequires: systemd-devel |
| ... | ... |
@@ -23,28 +24,73 @@ The GRUB package contains the GRand Unified Bootloader. |
| 23 | 23 |
%package lang |
| 24 | 24 |
Summary: Additional language files for grub |
| 25 | 25 |
Group: System Environment/Programming |
| 26 |
-Requires: grub2 >= 2.00 |
|
| 26 |
+Requires: %{name} = %{version}
|
|
| 27 | 27 |
%description lang |
| 28 | 28 |
These are the additional language files of grub. |
| 29 | 29 |
|
| 30 |
+%package pc |
|
| 31 |
+Summary: GRUB Library for BIOS |
|
| 32 |
+Group: System Environment/Programming |
|
| 33 |
+Requires: %{name} = %{version}
|
|
| 34 |
+%description pc |
|
| 35 |
+Additional library files for grub |
|
| 36 |
+ |
|
| 37 |
+%package efi |
|
| 38 |
+Summary: GRUB Library for UEFI |
|
| 39 |
+Group: System Environment/Programming |
|
| 40 |
+Requires: %{name} = %{version}
|
|
| 41 |
+%description efi |
|
| 42 |
+Additional library files for grub |
|
| 30 | 43 |
|
| 31 | 44 |
%prep |
| 32 | 45 |
%setup -qn grub-2.02~rc2 |
| 33 | 46 |
%patch0 -p1 |
| 47 |
+%patch1 -p1 |
|
| 34 | 48 |
%build |
| 35 |
-./configure \ |
|
| 49 |
+./autogen.sh |
|
| 50 |
+mkdir build-for-pc build-for-efi |
|
| 51 |
+cd build-for-pc |
|
| 52 |
+../configure \ |
|
| 36 | 53 |
--prefix=%{_prefix} \
|
| 37 | 54 |
--sbindir=/sbin \ |
| 38 | 55 |
--sysconfdir=%{_sysconfdir} \
|
| 39 | 56 |
--disable-grub-emu-usb \ |
| 57 |
+ --disable-werror \ |
|
| 40 | 58 |
--disable-efiemu \ |
| 59 |
+ --with-grubdir=grub2 \ |
|
| 60 |
+ --with-platform=pc \ |
|
| 61 |
+ --target=i386 \ |
|
| 62 |
+ --program-transform-name=s,grub,%{name}, \
|
|
| 63 |
+ --with-bootdir="/boot" |
|
| 64 |
+make %{?_smp_mflags}
|
|
| 65 |
+make DESTDIR=$PWD/../install-for-pc install |
|
| 66 |
+cd ../build-for-efi |
|
| 67 |
+../configure \ |
|
| 68 |
+ --prefix=%{_prefix} \
|
|
| 69 |
+ --sbindir=/sbin \ |
|
| 70 |
+ --sysconfdir=%{_sysconfdir} \
|
|
| 71 |
+ --disable-grub-emu-usb \ |
|
| 41 | 72 |
--disable-werror \ |
| 73 |
+ --disable-efiemu \ |
|
| 74 |
+ --with-grubdir=grub2 \ |
|
| 75 |
+ --with-platform=efi \ |
|
| 76 |
+ --target=x86_64 \ |
|
| 42 | 77 |
--program-transform-name=s,grub,%{name}, \
|
| 43 |
- --with-grubdir=%{name}
|
|
| 78 |
+ --with-bootdir="/boot" |
|
| 44 | 79 |
make %{?_smp_mflags}
|
| 80 |
+make DESTDIR=$PWD/../install-for-efi install |
|
| 81 |
+ |
|
| 82 |
+#make sure all the files are same between two configure except the /usr/lib/grub |
|
| 83 |
+%check |
|
| 84 |
+diff -sr install-for-efi/sbin install-for-pc/sbin && \ |
|
| 85 |
+diff -sr install-for-efi%{_bindir} install-for-pc%{_bindir} && \
|
|
| 86 |
+diff -sr install-for-efi%{_sysconfdir} install-for-pc%{_sysconfdir} && \
|
|
| 87 |
+diff -sr install-for-efi%{_datarootdir} install-for-pc%{_datarootdir}
|
|
| 45 | 88 |
|
| 46 | 89 |
%install |
| 47 |
-make DESTDIR=%{buildroot} install
|
|
| 90 |
+mkdir -p %{buildroot}
|
|
| 91 |
+cp -a install-for-efi/. %{buildroot}/.
|
|
| 92 |
+cp -a install-for-pc/. %{buildroot}/.
|
|
| 48 | 93 |
mkdir %{buildroot}%{_sysconfdir}/default
|
| 49 | 94 |
touch %{buildroot}%{_sysconfdir}/default/grub
|
| 50 | 95 |
mkdir %{buildroot}%{_sysconfdir}/sysconfig
|
| ... | ... |
@@ -52,8 +98,10 @@ ln -sf %{_sysconfdir}/default/grub %{buildroot}%{_sysconfdir}/sysconfig/grub
|
| 52 | 52 |
mkdir -p %{buildroot}/boot/%{name}
|
| 53 | 53 |
touch %{buildroot}/boot/%{name}/grub.cfg
|
| 54 | 54 |
rm -rf %{buildroot}%{_infodir}
|
| 55 |
+ |
|
| 55 | 56 |
%post -p /sbin/ldconfig |
| 56 | 57 |
%postun -p /sbin/ldconfig |
| 58 |
+ |
|
| 57 | 59 |
%files |
| 58 | 60 |
%defattr(-,root,root) |
| 59 | 61 |
%dir %{_sysconfdir}/grub.d
|
| ... | ... |
@@ -62,22 +110,29 @@ rm -rf %{buildroot}%{_infodir}
|
| 62 | 62 |
%config() %{_sysconfdir}/grub.d/10_linux
|
| 63 | 63 |
%config() %{_sysconfdir}/grub.d/20_linux_xen
|
| 64 | 64 |
%config() %{_sysconfdir}/grub.d/30_os-prober
|
| 65 |
-%config() %{_sysconfdir}/grub.d/40_custom
|
|
| 66 |
-%config() %{_sysconfdir}/grub.d/41_custom
|
|
| 67 |
-%config() %{_sysconfdir}/grub.d/README
|
|
| 65 |
+%config(noreplace) %{_sysconfdir}/grub.d/40_custom
|
|
| 66 |
+%config(noreplace) %{_sysconfdir}/grub.d/41_custom
|
|
| 67 |
+%{_sysconfdir}/grub.d/README
|
|
| 68 | 68 |
/sbin/* |
| 69 | 69 |
%{_bindir}/*
|
| 70 |
-%{_libdir}/grub/*
|
|
| 71 | 70 |
%{_datarootdir}/grub/*
|
| 72 | 71 |
%{_sysconfdir}/sysconfig/grub
|
| 73 | 72 |
%{_sysconfdir}/default/grub
|
| 74 | 73 |
%ghost %config(noreplace) /boot/%{name}/grub.cfg
|
| 75 | 74 |
|
| 75 |
+%files pc |
|
| 76 |
+%{_libdir}/grub/i386-pc
|
|
| 77 |
+ |
|
| 78 |
+%files efi |
|
| 79 |
+%{_libdir}/grub/x86_64-efi
|
|
| 80 |
+ |
|
| 76 | 81 |
%files lang |
| 77 | 82 |
%defattr(-,root,root) |
| 78 |
-/usr/share/locale/* |
|
| 83 |
+%{_datarootdir}/locale/*
|
|
| 79 | 84 |
|
| 80 | 85 |
%changelog |
| 86 |
+* Fri Jun 2 2017 Bo Gan <ganb@vmware.com> 2.02-9 |
|
| 87 |
+- Split grub2 to grub2 and grub2-pc, remove grub2-efi spec |
|
| 81 | 88 |
* Fri Apr 14 2017 Alexey Makhalov <amakhalov@vmware.com> 2.02-8 |
| 82 | 89 |
- Version update to 2.02~rc2 |
| 83 | 90 |
* Fri Nov 18 2016 Anish Swaminathan <anishs@vmware.com> 2.02-7 |
| ... | ... |
@@ -5,5 +5,5 @@ |
| 5 | 5 |
"libffi","expat","linux","cpio","Linux-PAM","attr","libcap", "systemd","dbus", |
| 6 | 6 |
"gzip", "sqlite","nspr","nss","popt","lua","rpm","gptfdisk","tar", "librepo", |
| 7 | 7 |
"hawkey", "python2","python2-libs","pcre","glib", "tdnf", "python-requests", |
| 8 |
- "grub2", "dracut", "curl", "ostree", "dosfstools"] |
|
| 8 |
+ "grub2-pc", "grub2-efi", "dracut", "curl", "ostree", "dosfstools"] |
|
| 9 | 9 |
} |