From 0df77d793c0436be656f982d96d4edaea4993f96 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Fri, 13 Dec 2013 12:56:14 +0100 Subject: [PATCH] Implement multiboot2 EFI BS specification. --- ChangeLog | 4 ++++ grub-core/loader/multiboot.c | 2 +- grub-core/loader/multiboot_mbi2.c | 32 ++++++++++++++++++++++++++++--- include/multiboot2.h | 2 ++ 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9cec63f5c..9c5073c10 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2013-12-13 Vladimir Serbinenko + + Implement multiboot2 EFI BS specification. + 2013-12-11 Vladimir Serbinenko * grub-core/normal/charset.c: Fix premature line wrap and crash. diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c index 54e4d2408..4b71f3363 100644 --- a/grub-core/loader/multiboot.c +++ b/grub-core/loader/multiboot.c @@ -344,7 +344,7 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)), err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch, lowest_addr, (0xffffffff - size) + 1, size, MULTIBOOT_MOD_ALIGN, - GRUB_RELOCATOR_PREFERENCE_NONE, 0); + GRUB_RELOCATOR_PREFERENCE_NONE, 1); if (err) { grub_file_close (file); diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c index 951988fb9..2f5aa6294 100644 --- a/grub-core/loader/multiboot_mbi2.c +++ b/grub-core/loader/multiboot_mbi2.c @@ -67,6 +67,7 @@ static grub_uint32_t biosdev, slice, part; static grub_size_t elf_sec_num, elf_sec_entsize; static unsigned elf_sec_shstrndx; static void *elf_sections; +static int keep_bs = 0; void grub_multiboot_add_elfsyms (grub_size_t num, grub_size_t entsize, @@ -127,6 +128,8 @@ grub_multiboot_load (grub_file_t file, const char *filename) COMPILE_TIME_ASSERT (MULTIBOOT_TAG_ALIGN % 4 == 0); + keep_bs = 0; + for (tag = (struct multiboot_header_tag *) (header + 1); tag->type != MULTIBOOT_TAG_TYPE_END; tag = (struct multiboot_header_tag *) ((grub_uint32_t *) tag + ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) / 4)) @@ -160,6 +163,7 @@ grub_multiboot_load (grub_file_t file, const char *filename) case MULTIBOOT_TAG_TYPE_ACPI_NEW: case MULTIBOOT_TAG_TYPE_NETWORK: case MULTIBOOT_TAG_TYPE_EFI_MMAP: + case MULTIBOOT_TAG_TYPE_EFI_BS: break; default: @@ -198,6 +202,10 @@ grub_multiboot_load (grub_file_t file, const char *filename) case MULTIBOOT_HEADER_TAG_MODULE_ALIGN: break; + case MULTIBOOT_HEADER_TAG_EFI_BS: + keep_bs = 1; + break; + default: if (! (tag->flags & MULTIBOOT_HEADER_TAG_OPTIONAL)) { @@ -362,6 +370,7 @@ grub_multiboot_get_mbi_size (void) find_efi_mmap_size (); #endif return 2 * sizeof (grub_uint32_t) + sizeof (struct multiboot_tag) + + sizeof (struct multiboot_tag) + (sizeof (struct multiboot_tag_string) + ALIGN_UP (cmdline_size, MULTIBOOT_TAG_ALIGN)) + (sizeof (struct multiboot_tag_string) @@ -637,7 +646,7 @@ grub_multiboot_make_mbi (grub_uint32_t *target) err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch, 0, 0xffffffff - bufsize, bufsize, MULTIBOOT_TAG_ALIGN, - GRUB_RELOCATOR_PREFERENCE_NONE, 0); + GRUB_RELOCATOR_PREFERENCE_NONE, 1); if (err) return err; @@ -853,8 +862,16 @@ grub_multiboot_make_mbi (grub_uint32_t *target) tag->type = MULTIBOOT_TAG_TYPE_EFI_MMAP; tag->size = sizeof (*tag) + efi_mmap_size; - err = grub_efi_finish_boot_services (&efi_mmap_size, tag->efi_mmap, NULL, - &efi_desc_size, &efi_desc_version); + if (!keep_bs) + err = grub_efi_finish_boot_services (&efi_mmap_size, tag->efi_mmap, NULL, + &efi_desc_size, &efi_desc_version); + else + { + if (grub_efi_get_memory_map (&efi_mmap_size, (void *) tag->efi_mmap, + NULL, + &efi_desc_size, &efi_desc_version) <= 0) + err = grub_error (GRUB_ERR_IO, "couldn't retrieve memory map"); + } if (err) return err; tag->descr_size = efi_desc_size; @@ -864,6 +881,15 @@ grub_multiboot_make_mbi (grub_uint32_t *target) ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) / sizeof (grub_properly_aligned_t); } + + if (keep_bs) + { + struct multiboot_tag *tag = (struct multiboot_tag *) ptrorig; + tag->type = MULTIBOOT_TAG_TYPE_EFI_BS; + tag->size = sizeof (struct multiboot_tag); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); + } #endif { diff --git a/include/multiboot2.h b/include/multiboot2.h index 58f2f6845..2e33cbf8d 100644 --- a/include/multiboot2.h +++ b/include/multiboot2.h @@ -59,6 +59,7 @@ #define MULTIBOOT_TAG_TYPE_ACPI_NEW 15 #define MULTIBOOT_TAG_TYPE_NETWORK 16 #define MULTIBOOT_TAG_TYPE_EFI_MMAP 17 +#define MULTIBOOT_TAG_TYPE_EFI_BS 18 #define MULTIBOOT_HEADER_TAG_END 0 #define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1 @@ -67,6 +68,7 @@ #define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4 #define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5 #define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6 +#define MULTIBOOT_HEADER_TAG_EFI_BS 7 #define MULTIBOOT_ARCHITECTURE_I386 0 #define MULTIBOOT_ARCHITECTURE_MIPS32 4