From 716e24f03037f7654f289e6bc10c1a6935fd0f22e566e54b6c273530983fb657 Mon Sep 17 00:00:00 2001 From: Stephan Kulow Date: Thu, 31 Jan 2013 13:48:08 +0000 Subject: [PATCH] Accepting request 150545 from Base:System a couple of secureboot changes and some improvement. OBS-URL: https://build.opensuse.org/request/show/150545 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/grub2?expand=0&rev=56 --- grub.default | 4 + grub2-cdpath.patch | 50 +++ grub2-once | 5 +- grub2-secureboot-chainloader.patch | 646 +++++++++++++++++++++++++++++ grub2.changes | 25 ++ grub2.spec | 38 +- 6 files changed, 747 insertions(+), 21 deletions(-) create mode 100644 grub2-cdpath.patch create mode 100644 grub2-secureboot-chainloader.patch diff --git a/grub.default b/grub.default index 285681f..835eb80 100644 --- a/grub.default +++ b/grub.default @@ -9,6 +9,10 @@ GRUB_TIMEOUT=10 GRUB_CMDLINE_LINUX_DEFAULT="quiet splash=silent" GRUB_CMDLINE_LINUX="" +# Uncomment to automatically save last booted menu entry in GRUB2 environment +# variable `saved_entry' +#GRUB_SAVEDEFAULT="true" + # Uncomment to enable BadRAM filtering, modify to suit your needs # This works with Linux (no patch required) and with any kernel that obtains # the memory map information from GRUB (GNU Mach, kernel of FreeBSD ...) diff --git a/grub2-cdpath.patch b/grub2-cdpath.patch new file mode 100644 index 0000000..a8a7865 --- /dev/null +++ b/grub2-cdpath.patch @@ -0,0 +1,50 @@ +From: Matthew Garrett +Date: 2012-07-10 11:58:52 EDT +Subject: [PATCH] Add support for crappy cd craparino + +References: fate#314485 +Patch-Mainline: no + +Signed-off-by: Michael Chang + +Follow other code in this function and duplicate device path +before overwriting it. + +Signed-off-by: Andrey Borzenkov + +Index: grub-2.00/grub-core/disk/efi/efidisk.c +=================================================================== +--- grub-2.00.orig/grub-core/disk/efi/efidisk.c ++++ grub-2.00/grub-core/disk/efi/efidisk.c +@@ -820,6 +820,31 @@ grub_efidisk_get_device_name (grub_efi_h + + return dev_name; + } ++ else if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE && ++ (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE)) ++ { ++ grub_efi_device_path_t *dup_dp, *dup_ldp; ++ ++ /* It is necessary to duplicate the device path so that GRUB ++ can overwrite it. */ ++ dup_dp = duplicate_device_path (dp); ++ if (! dup_dp) ++ return 0; ++ ++ dup_ldp = find_last_device_path (dup_dp); ++ dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; ++ dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; ++ dup_ldp->length[0] = 4; ++ dup_ldp->length[1] = 0; ++ ++ if (!get_diskname_from_path (dup_dp, device_name)) ++ { ++ grub_free (dup_dp); ++ return 0; ++ } ++ grub_free (dup_dp); ++ return grub_strdup (device_name); ++ } + else + { + /* This should be an entire disk. */ diff --git a/grub2-once b/grub2-once index f9fcf3a..2ed9488 100644 --- a/grub2-once +++ b/grub2-once @@ -45,12 +45,9 @@ $grub2_dir = ""; while () { if (/LOADER_TYPE="(.*)"/) { my $bl = $1; - if ($bl eq "grub2") { + if ($bl eq "grub2" || $bl eq "grub2-efi") { $grub2_dir = "/boot/grub2"; $grub2_reboot = "/usr/sbin/grub2-reboot"; - } elsif ($bl eq "grub2-efi") { - $grub2_dir = "/boot/grub2-efi"; - $grub2_reboot = "/usr/sbin/grub2-efi-reboot"; } last; } diff --git a/grub2-secureboot-chainloader.patch b/grub2-secureboot-chainloader.patch new file mode 100644 index 0000000..7121229 --- /dev/null +++ b/grub2-secureboot-chainloader.patch @@ -0,0 +1,646 @@ +From 06ff1079788fedac5e3f1f12ed7bbe69228a7ae0 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Tue, 18 Dec 2012 16:54:03 +0800 +Subject: [PATCH] Add secureboot support on efi chainloader + +References: fate#314485 +Patch-Mainline: no + +Expand the chainloader to be able to verify the image by means of shim +lock protocol. The PE/COFF image is loaded and relocated by the +chainloader instead of calling LoadImage and StartImage UEFI boot +Service as they require positive verification result from keys enrolled +in KEK or DB. The shim will use MOK in addition to firmware enrolled +keys to verify the image. + +The chainloader module could be used to load other UEFI bootloaders, +such as xen.efi, and could be signed by any of MOK, KEK or DB. + +Signed-off-by: Michael Chang +--- + grub-core/loader/efi/chainloader.c | 538 +++++++++++++++++++++++++++++++++-- + 1 files changed, 507 insertions(+), 31 deletions(-) + +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index 3f3e6e3..12e1aff 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -36,15 +36,30 @@ + #include + #include + ++#ifdef __x86_64__ ++#define SUPPORT_SECURE_BOOT ++#endif ++ ++#ifdef SUPPORT_SECURE_BOOT ++#include ++#endif ++ + GRUB_MOD_LICENSE ("GPLv3+"); + + static grub_dl_t my_mod; + + static grub_efi_physical_address_t address; + static grub_efi_uintn_t pages; ++static grub_ssize_t fsize; + static grub_efi_device_path_t *file_path; + static grub_efi_handle_t image_handle; + static grub_efi_char16_t *cmdline; ++static grub_ssize_t cmdline_len; ++ ++#ifdef SUPPORT_SECURE_BOOT ++static grub_efi_boolean_t debug_secureboot = 0; ++static grub_efi_status_t (*entry_point) (grub_efi_handle_t image_handle, grub_efi_system_table_t *system_table); ++#endif + + static grub_err_t + grub_chainloader_unload (void) +@@ -186,12 +201,458 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename) + return file_path; + } + ++#ifdef SUPPORT_SECURE_BOOT ++#define SHIM_LOCK_GUID \ ++ { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} } ++ ++struct grub_pe32_header_no_msdos_stub ++{ ++ char signature[GRUB_PE32_SIGNATURE_SIZE]; ++ struct grub_pe32_coff_header coff_header; ++ struct grub_pe64_optional_header optional_header; ++}; ++ ++struct pe_coff_loader_image_context ++{ ++ grub_efi_uint64_t image_address; ++ grub_efi_uint64_t image_size; ++ grub_efi_uint64_t entry_point; ++ grub_efi_uintn_t size_of_headers; ++ grub_efi_uint16_t image_type; ++ grub_efi_uint16_t number_of_sections; ++ struct grub_pe32_section_table *first_section; ++ struct grub_pe32_data_directory *reloc_dir; ++ struct grub_pe32_data_directory *sec_dir; ++ grub_efi_uint64_t number_of_rva_and_sizes; ++ struct grub_pe32_header_no_msdos_stub *pe_hdr; ++}; ++ ++typedef struct pe_coff_loader_image_context pe_coff_loader_image_context_t; ++ ++struct grub_efi_shim_lock ++{ ++ grub_efi_status_t (*verify)(void *buffer, ++ grub_efi_uint32_t size); ++ grub_efi_status_t (*hash)(void *data, ++ grub_efi_int32_t datasize, ++ pe_coff_loader_image_context_t *context, ++ grub_efi_uint8_t *sha256hash, ++ grub_efi_uint8_t *sha1hash); ++ grub_efi_status_t (*context)(void *data, ++ grub_efi_uint32_t size, ++ pe_coff_loader_image_context_t *context); ++}; ++ ++typedef struct grub_efi_shim_lock grub_efi_shim_lock_t; ++ ++static grub_efi_boolean_t ++grub_secure_validate (void *data, grub_efi_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) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "no shim lock protocol"); ++ return 0; ++ } ++ ++ if (shim_lock->verify (data, size) == GRUB_EFI_SUCCESS) ++ { ++ grub_dprintf ("chain", "verify success\n"); ++ return 1; ++ } ++ ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "verify failed"); ++ return 0; ++} ++ ++static grub_efi_boolean_t ++grub_secure_mode (void) ++{ ++ grub_efi_guid_t efi_var_guid = GRUB_EFI_GLOBAL_VARIABLE_GUID; ++ grub_uint8_t *data; ++ grub_size_t datasize; ++ ++ data = grub_efi_get_variable ("SecureBoot", &efi_var_guid, &datasize); ++ ++ if (data) ++ { ++ grub_dprintf ("chain", "SecureBoot: %d, datasize %d\n", (int)*data, (int)datasize); ++ } ++ ++ if (data && (datasize == 1)) ++ { ++ if (*data != 1) ++ { ++ grub_dprintf ("chain", "secure boot not enabled\n"); ++ return 0; ++ } ++ } ++ else ++ { ++ grub_dprintf ("chain", "unknown secure boot status\n"); ++ return 0; ++ } ++ ++ grub_free (data); ++ ++ data = grub_efi_get_variable ("SetupMode", &efi_var_guid, &datasize); ++ ++ if (data) ++ { ++ grub_dprintf ("chain", "SetupMode: %d, datasize %d\n", (int)*data, (int)datasize); ++ } ++ ++ if (data && (datasize == 1)) ++ { ++ if (*data == 1) ++ { ++ grub_dprintf ("chain", "platform in setup mode\n"); ++ return 0; ++ } ++ } ++ ++ grub_free (data); ++ ++ return 1; ++} ++ ++static grub_efi_boolean_t ++read_header (void *data, grub_efi_uint32_t size, pe_coff_loader_image_context_t *context) ++{ ++ grub_efi_guid_t guid = SHIM_LOCK_GUID; ++ grub_efi_shim_lock_t *shim_lock; ++ grub_efi_status_t status; ++ ++ shim_lock = grub_efi_locate_protocol (&guid, NULL); ++ ++ if (!shim_lock) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "no shim lock protocol"); ++ return 0; ++ } ++ ++ status = shim_lock->context (data, size, context); ++ ++ if (status == GRUB_EFI_SUCCESS) ++ { ++ grub_dprintf ("chain", "context success\n"); ++ return 1; ++ } ++ ++ switch (status) ++ { ++ case GRUB_EFI_UNSUPPORTED: ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "context error unsupported"); ++ break; ++ case GRUB_EFI_INVALID_PARAMETER: ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "context error invalid parameter"); ++ break; ++ default: ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "context error code"); ++ break; ++ } ++ ++ return 0; ++} ++ ++static void* ++image_address (void *image, grub_efi_uint64_t sz, grub_efi_uint64_t adr) ++{ ++ if (adr > sz) ++ return NULL; ++ ++ return ((grub_uint8_t*)image + adr); ++} ++ ++static grub_efi_status_t ++relocate_coff (pe_coff_loader_image_context_t *context, void *data) ++{ ++ struct grub_pe32_data_directory *reloc_base, *reloc_base_end; ++ grub_efi_uint64_t adjust; ++ grub_efi_uint16_t *reloc, *reloc_end; ++ char *fixup, *fixup_base, *fixup_data = NULL; ++ grub_efi_uint16_t *fixup_16; ++ grub_efi_uint32_t *fixup_32; ++ grub_efi_uint64_t *fixup_64; ++ ++ grub_efi_uint64_t size = context->image_size; ++ void *image_end = (char *)data + size; ++ ++ context->pe_hdr->optional_header.image_base = (grub_uint64_t)data; ++ ++ if (context->number_of_rva_and_sizes <= 5 || context->reloc_dir->size == 0) ++ { ++ grub_dprintf ("chain", "no need to reloc, we are done\n"); ++ return GRUB_EFI_SUCCESS; ++ } ++ ++ reloc_base = image_address (data, size, context->reloc_dir->rva); ++ reloc_base_end = image_address (data, size, context->reloc_dir->rva + context->reloc_dir->size -1); ++ ++ grub_dprintf ("chain", "reloc_base %p reloc_base_end %p\n", reloc_base, reloc_base_end); ++ ++ if (!reloc_base || !reloc_base_end) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "Reloc table overflows binary"); ++ return GRUB_EFI_UNSUPPORTED; ++ } ++ ++ adjust = (grub_uint64_t)data - context->image_address; ++ ++ while (reloc_base < reloc_base_end) ++ { ++ reloc = (grub_uint16_t *)((char*)reloc_base + sizeof (struct grub_pe32_data_directory)); ++ reloc_end = (grub_uint16_t *)((char*)reloc_base + reloc_base->size); ++ ++ if ((void *)reloc_end < data || (void *)reloc_end > image_end) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "Reloc table overflows binary"); ++ return GRUB_EFI_UNSUPPORTED; ++ } ++ ++ fixup_base = image_address(data, size, reloc_base->rva); ++ ++ if (!fixup_base) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid fixupbase"); ++ return GRUB_EFI_UNSUPPORTED; ++ } ++ ++ while (reloc < reloc_end) ++ { ++ fixup = fixup_base + (*reloc & 0xFFF); ++ switch ((*reloc) >> 12) ++ { ++ case GRUB_PE32_REL_BASED_ABSOLUTE: ++ break; ++ case GRUB_PE32_REL_BASED_HIGH: ++ fixup_16 = (grub_uint16_t *)fixup; ++ *fixup_16 = (grub_uint16_t) (*fixup_16 + ((grub_uint16_t)((grub_uint32_t)adjust >> 16))); ++ if (fixup_data != NULL) ++ { ++ *(grub_uint16_t *) fixup_data = *fixup_16; ++ fixup_data = fixup_data + sizeof (grub_uint16_t); ++ } ++ break; ++ case GRUB_PE32_REL_BASED_LOW: ++ fixup_16 = (grub_uint16_t *)fixup; ++ *fixup_16 = (grub_uint16_t) (*fixup_16 + (grub_uint16_t)adjust ); ++ if (fixup_data != NULL) ++ { ++ *(grub_uint16_t *) fixup_data = *fixup_16; ++ fixup_data = fixup_data + sizeof (grub_uint16_t); ++ } ++ break; ++ case GRUB_PE32_REL_BASED_HIGHLOW: ++ fixup_32 = (grub_uint32_t *)fixup; ++ *fixup_32 = *fixup_32 + (grub_uint32_t)adjust; ++ if (fixup_data != NULL) ++ { ++ fixup_data = (char *)ALIGN_UP ((grub_addr_t)fixup_data, sizeof (grub_uint32_t)); ++ *(grub_uint32_t *) fixup_data = *fixup_32; ++ fixup_data += sizeof (grub_uint32_t); ++ } ++ break; ++ case GRUB_PE32_REL_BASED_DIR64: ++ fixup_64 = (grub_uint64_t *)fixup; ++ *fixup_64 = *fixup_64 + (grub_uint64_t)adjust; ++ if (fixup_data != NULL) ++ { ++ fixup_data = (char *)ALIGN_UP ((grub_addr_t)fixup_data, sizeof (grub_uint64_t)); ++ *(grub_uint64_t *) fixup_data = *fixup_64; ++ fixup_data += sizeof (grub_uint64_t); ++ } ++ break; ++ default: ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown relocation"); ++ return GRUB_EFI_UNSUPPORTED; ++ } ++ reloc += 1; ++ } ++ reloc_base = (struct grub_pe32_data_directory *)reloc_end; ++ } ++ ++ return GRUB_EFI_SUCCESS; ++} ++ ++static grub_efi_device_path_t * ++grub_efi_get_media_file_path (grub_efi_device_path_t *dp) ++{ ++ while (1) ++ { ++ grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp); ++ grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp); ++ ++ if (type == GRUB_EFI_END_DEVICE_PATH_TYPE) ++ break; ++ else if (type == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE ++ && subtype == GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE) ++ return dp; ++ ++ dp = GRUB_EFI_NEXT_DEVICE_PATH (dp); ++ } ++ ++ return NULL; ++} ++ ++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; ++ char *buffer_aligned = NULL; ++ grub_efi_uint32_t i, size; ++ struct grub_pe32_section_table *section; ++ char *base, *end; ++ pe_coff_loader_image_context_t context; ++ grub_uint32_t section_alignment; ++ grub_uint32_t buffer_size; ++ ++ b = grub_efi_system_table->boot_services; ++ ++ if (read_header (data, datasize, &context)) ++ { ++ grub_dprintf ("chain", "Succeed to read header\n"); ++ } ++ else ++ { ++ grub_dprintf ("chain", "Failed to read header\n"); ++ goto error_exit; ++ } ++ ++ section_alignment = context.pe_hdr->optional_header.section_alignment; ++ buffer_size = context.image_size + section_alignment; ++ ++ efi_status = efi_call_3 (b->allocate_pool, GRUB_EFI_LOADER_DATA, ++ buffer_size, &buffer); ++ ++ if (efi_status != GRUB_EFI_SUCCESS) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); ++ goto error_exit; ++ } ++ ++ buffer_aligned = (char *)ALIGN_DOWN ((grub_addr_t)buffer, section_alignment); ++ ++ grub_memcpy (buffer_aligned, data, context.size_of_headers); ++ ++ section = context.first_section; ++ for (i = 0; i < context.number_of_sections; i++) ++ { ++ size = section->virtual_size; ++ if (size > section->raw_data_size) ++ size = section->raw_data_size; ++ ++ base = image_address (buffer_aligned, context.image_size, section->virtual_address); ++ end = image_address (buffer_aligned, context.image_size, section->virtual_address + size - 1); ++ ++ if (!base || !end) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid section size"); ++ goto error_exit; ++ } ++ ++ if (section->raw_data_size > 0) ++ grub_memcpy (base, (grub_efi_uint8_t*)data + section->raw_data_offset, size); ++ ++ if (size < section->virtual_size) ++ grub_memset (base + size, 0, section->virtual_size - size); ++ ++ grub_dprintf ("chain", "copied section %s\n", section->name); ++ section += 1; ++ } ++ ++ efi_status = relocate_coff (&context, buffer_aligned); ++ ++ if (efi_status != GRUB_EFI_SUCCESS) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "relocation failed"); ++ goto error_exit; ++ } ++ ++ entry_point = image_address (buffer_aligned, context.image_size, context.entry_point); ++ ++ if (!entry_point) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid entry point"); ++ goto error_exit; ++ } ++ ++ li = grub_efi_get_loaded_image (grub_efi_image_handle); ++ if (!li) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "no loaded image available"); ++ goto error_exit; ++ } ++ ++ grub_memcpy (&li_bak, li, sizeof (grub_efi_loaded_image_t)); ++ li->image_base = buffer_aligned; ++ li->image_size = context.image_size; ++ li->load_options = cmdline; ++ li->load_options_size = cmdline_len; ++ li->file_path = grub_efi_get_media_file_path (file_path); ++ if (li->file_path) ++ { ++ grub_printf ("file path: "); ++ grub_efi_print_device_path (li->file_path); ++ } ++ else ++ { ++ grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching file path found"); ++ goto error_exit; ++ } ++ ++ efi_status = efi_call_2 (entry_point, grub_efi_image_handle, grub_efi_system_table); ++ ++ grub_memcpy (li, &li_bak, sizeof (grub_efi_loaded_image_t)); ++ efi_status = efi_call_1 (b->free_pool, buffer); ++ ++ return 1; ++ ++error_exit: ++ if (buffer) ++ efi_call_1 (b->free_pool, buffer); ++ ++ return 0; ++ ++} ++ ++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_free (file_path); ++ grub_free (cmdline); ++ cmdline = 0; ++ file_path = 0; ++ ++ grub_dl_unref (my_mod); ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_secureboot_chainloader_boot (void) ++{ ++ handle_image ((void *)address, fsize); ++ grub_loader_unset (); ++ return grub_errno; ++} ++#endif ++ + static grub_err_t + grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) + { + grub_file_t file = 0; +- grub_ssize_t size; + grub_efi_status_t status; + grub_efi_boot_services_t *b; + grub_device_t dev = 0; +@@ -213,6 +674,32 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + + b = grub_efi_system_table->boot_services; + ++ if (argc > 1) ++ { ++ int i; ++ grub_efi_char16_t *p16; ++ ++ for (i = 1, cmdline_len = 0; i < argc; i++) ++ cmdline_len += grub_strlen (argv[i]) + 1; ++ ++ cmdline_len *= sizeof (grub_efi_char16_t); ++ cmdline = p16 = grub_malloc (cmdline_len); ++ if (! cmdline) ++ goto fail; ++ ++ for (i = 1; i < argc; i++) ++ { ++ char *p8; ++ ++ p8 = argv[i]; ++ while (*p8) ++ *(p16++) = *(p8++); ++ ++ *(p16++) = ' '; ++ } ++ *(--p16) = 0; ++ } ++ + file = grub_file_open (filename); + if (! file) + goto fail; +@@ -258,14 +745,14 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + grub_printf ("file path: "); + grub_efi_print_device_path (file_path); + +- size = grub_file_size (file); +- if (!size) ++ fsize = grub_file_size (file); ++ if (!fsize) + { + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); + goto fail; + } +- pages = (((grub_efi_uintn_t) size + ((1 << 12) - 1)) >> 12); ++ pages = (((grub_efi_uintn_t) fsize + ((1 << 12) - 1)) >> 12); + + status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ANY_PAGES, + GRUB_EFI_LOADER_CODE, +@@ -278,7 +765,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + +- if (grub_file_read (file, (void *) ((grub_addr_t) address), size) != size) ++ if (grub_file_read (file, (void *) ((grub_addr_t) address), fsize) != fsize) + { + if (grub_errno == GRUB_ERR_NONE) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), +@@ -287,8 +774,17 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + ++#ifdef SUPPORT_SECURE_BOOT ++ if (debug_secureboot || (grub_secure_mode() && grub_secure_validate ((void *)address, fsize))) ++ { ++ grub_file_close (file); ++ grub_loader_set (grub_secureboot_chainloader_boot, grub_secureboot_chainloader_unload, 0); ++ return 0; ++ } ++#endif ++ + status = efi_call_6 (b->load_image, 0, grub_efi_image_handle, file_path, +- (void *) ((grub_addr_t) address), size, ++ (void *) ((grub_addr_t) address), fsize, + &image_handle); + if (status != GRUB_EFI_SUCCESS) + { +@@ -313,33 +809,10 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + + grub_file_close (file); + +- if (argc > 1) ++ if (cmdline) + { +- int i, len; +- grub_efi_char16_t *p16; +- +- for (i = 1, len = 0; i < argc; i++) +- len += grub_strlen (argv[i]) + 1; +- +- len *= sizeof (grub_efi_char16_t); +- cmdline = p16 = grub_malloc (len); +- if (! cmdline) +- goto fail; +- +- for (i = 1; i < argc; i++) +- { +- char *p8; +- +- p8 = argv[i]; +- while (*p8) +- *(p16++) = *(p8++); +- +- *(p16++) = ' '; +- } +- *(--p16) = 0; +- + loaded_image->load_options = cmdline; +- loaded_image->load_options_size = len; ++ loaded_image->load_options_size = cmdline_len; + } + + grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0); +@@ -358,6 +831,9 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + if (address) + efi_call_2 (b->free_pages, address, pages); + ++ if (cmdline) ++ grub_free (cmdline); ++ + grub_dl_unref (my_mod); + + return grub_errno; +-- +1.7.3.4 + diff --git a/grub2.changes b/grub2.changes index 8155558..fc7f04e 100644 --- a/grub2.changes +++ b/grub2.changes @@ -1,3 +1,28 @@ +------------------------------------------------------------------- +Wed Jan 30 07:29:29 UTC 2013 - mchang@suse.com + +- sync from SLE-11 SP3 to date +- set empty prefix to grub.efi for looking up in current directory +- grub2-cdpath.patch: fix the grub.cfg not found when booting from + optical disk +- put grub.efi in grub2's source module directory +- create links in system's efi directory to grub.efi +- arvidjaar: do not overwrite device path in grub2-cdpath.patch + +------------------------------------------------------------------- +Wed Jan 30 04:36:45 UTC 2013 - arvidjaar@gmail.com + +- remove obsolete reference to /boot/grub2-efi and /usr/sbin/grub2-efi + from grub2-once +- add GRUB_SAVEDFAULT description to /etc/default/grub + +------------------------------------------------------------------- +Fri Jan 18 07:39:18 UTC 2013 - mchang@suse.com + +- ship a Secure Boot UEFI compatible bootloader (fate#314485) +- add grub2-secureboot-chainloader.patch, which expands the efi + chainloader to be able to verify images via shim lock protocol. + ------------------------------------------------------------------- Tue Jan 8 08:09:01 UTC 2013 - mchang@suse.com diff --git a/grub2.spec b/grub2.spec index 30900ec..9bd98db 100644 --- a/grub2.spec +++ b/grub2.spec @@ -81,14 +81,6 @@ BuildRequires: guile %define only_x86_64 %{nil} %endif -%if 0%{?sles_version} -%global efidir SuSE -%else -%if 0%{?suse_version} -%global efidir opensuse -%endif -%endif - Version: 2.00 Release: 0 Summary: Bootloader with support for Linux, Multiboot and more @@ -135,6 +127,8 @@ Patch25: 30_os-prober_UEFI_support.patch Patch26: grub2-fix-enumeration-of-extended-partition.patch Patch27: grub2-add-device-to-os_prober-linux-menuentry.patch Patch28: grub2-fix-unquoted-string-in-class.patch +Patch29: grub2-secureboot-chainloader.patch +Patch30: grub2-cdpath.patch PreReq: perl-Bootloader Requires: gettext-runtime %if 0%{?suse_version} >= 1140 @@ -250,6 +244,8 @@ mv docs/grub.texi docs/grub2.texi %patch26 -p1 %patch27 -p1 %patch28 -p1 +%patch29 -p1 +%patch30 -p1 cd .. # README.openSUSE @@ -278,9 +274,9 @@ make %{?_smp_mflags} #TODO: add efifwsetup module -FS_MODULES="ext2 fat btrfs ext2 xfs jfs reiserfs" +FS_MODULES="ext2 btrfs ext2 xfs jfs reiserfs" CD_MODULES=" all_video boot cat chain configfile echo \ - efinet ext2 font gfxmenu gfxterm gzio halt iso9660 \ + efinet fat font gfxmenu gfxterm gzio halt iso9660 \ jpeg minicmd normal part_apple part_msdos part_gpt \ password_pbkdf2 png reboot search search_fs_uuid \ search_fs_file search_label sleep test video" @@ -292,7 +288,7 @@ CD_MODULES="${CD_MODULES} linux" %endif GRUB_MODULES="${CD_MODULES} ${FS_MODULES} mdraid09 mdraid1x" -./grub-mkimage -O %{grubefiarch} -o grub.efi -p /EFI/%{efidir} \ +./grub-mkimage -O %{grubefiarch} -o grub.efi --prefix= \ -d grub-core ${GRUB_MODULES} #./grub-mkimage -O %{grubefiarch} -o grub.efi -d grub-core part_gpt hfsplus fat \ # ext2 btrfs normal chain boot configfile linux appleldr minicmd \ @@ -336,8 +332,17 @@ make %{?_smp_mflags} cd grub-efi-%{version} make DESTDIR=$RPM_BUILD_ROOT install -install -m 755 -d $RPM_BUILD_ROOT/boot/efi/EFI/%{efidir}/ -install -m 755 grub.efi $RPM_BUILD_ROOT/boot/efi/EFI/%{efidir}/grub.efi +install -m 644 grub.efi $RPM_BUILD_ROOT%{_libdir}/%{name}/%{grubefiarch}/grub.efi + +# Create grub.efi link to system efi directory +# This is for tools like kiwi not fiddling with the path +%if "%{grubefiarch}" == "x86_64-efi" +%define sysefidir %{_exec_prefix}/lib64/efi +%else +%define sysefidir %{_libdir}/efi +%endif +install -d $RPM_BUILD_ROOT%{sysefidir} +ln -sf ../../../%{_libdir}/%{name}/%{grubefiarch}/grub.efi $RPM_BUILD_ROOT%{sysefidir}/grub.efi cd .. %endif @@ -608,11 +613,8 @@ fi %files %{grubefiarch} %defattr(-,root,root,-) -%dir /boot/efi -%dir /boot/efi/EFI -%dir /boot/efi/EFI/%{efidir} -%attr(0755,root,root)/boot/efi/EFI/%{efidir}/grub.efi %dir %{_libdir}/%{name}/%{grubefiarch} +%{_libdir}/%{name}/%{grubefiarch}/grub.efi %{_libdir}/%{name}/%{grubefiarch}/*.img %{_libdir}/%{name}/%{grubefiarch}/*.lst %{_libdir}/%{name}/%{grubefiarch}/*.mod @@ -621,6 +623,8 @@ fi %{_libdir}/%{name}/%{grubefiarch}/gmodule.pl %{_libdir}/%{name}/%{grubefiarch}/kernel.exec %{_libdir}/%{name}/%{grubefiarch}/modinfo.sh +%dir %{sysefidir} +%{sysefidir}/grub.efi %endif %changelog