* grub-core/loader/multiboot_mbi2.c: Implement EFI memory map.

This commit is contained in:
Vladimir Serbinenko 2013-10-28 15:37:00 +01:00
parent 00bfa988fc
commit 329550c4a9
5 changed files with 96 additions and 6 deletions

View file

@ -1,3 +1,7 @@
2013-10-28 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/loader/multiboot_mbi2.c: Implement EFI memory map.
2013-10-28 Vladimir Serbinenko <phcoder@gmail.com> 2013-10-28 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/loader/multiboot.c: Add support for multiboot kernels * grub-core/loader/multiboot.c: Add support for multiboot kernels

View file

@ -36,6 +36,10 @@
#include <grub/net.h> #include <grub/net.h>
#include <grub/i18n.h> #include <grub/i18n.h>
#ifdef GRUB_MACHINE_EFI
#include <grub/efi/efi.h>
#endif
/* The bits in the required part of flags field we don't support. */ /* The bits in the required part of flags field we don't support. */
#define UNSUPPORTED_FLAGS 0x0000fff8 #define UNSUPPORTED_FLAGS 0x0000fff8
@ -587,6 +591,12 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
ptrdest += sizeof (struct grub_vbe_mode_info_block); ptrdest += sizeof (struct grub_vbe_mode_info_block);
#endif #endif
#ifdef GRUB_MACHINE_EFI
err = grub_efi_finish_boot_services (NULL, NULL, NULL, NULL, NULL);
if (err)
return err;
#endif
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }

View file

@ -131,12 +131,6 @@ grub_multiboot_boot (void)
if (err) if (err)
return err; return err;
#ifdef GRUB_MACHINE_EFI
err = grub_efi_finish_boot_services (NULL, NULL, NULL, NULL, NULL);
if (err)
return err;
#endif
#if defined (__i386__) || defined (__x86_64__) #if defined (__i386__) || defined (__x86_64__)
grub_relocator32_boot (grub_multiboot_relocator, state, 0); grub_relocator32_boot (grub_multiboot_relocator, state, 0);
#else #else

View file

@ -295,9 +295,55 @@ acpiv2_size (void)
#endif #endif
} }
#ifdef GRUB_MACHINE_EFI
static grub_efi_uintn_t efi_mmap_size = 0;
/* Find the optimal number of pages for the memory map. Is it better to
move this code to efi/mm.c? */
static void
find_efi_mmap_size (void)
{
efi_mmap_size = (1 << 12);
while (1)
{
int ret;
grub_efi_memory_descriptor_t *mmap;
grub_efi_uintn_t desc_size;
grub_efi_uintn_t cur_mmap_size = efi_mmap_size;
mmap = grub_malloc (cur_mmap_size);
if (! mmap)
return;
ret = grub_efi_get_memory_map (&cur_mmap_size, mmap, 0, &desc_size, 0);
grub_free (mmap);
if (ret < 0)
return;
else if (ret > 0)
break;
if (efi_mmap_size < cur_mmap_size)
efi_mmap_size = cur_mmap_size;
efi_mmap_size += (1 << 12);
}
/* Increase the size a bit for safety, because GRUB allocates more on
later, and EFI itself may allocate more. */
efi_mmap_size += (3 << 12);
efi_mmap_size = ALIGN_UP (efi_mmap_size, 4096);
}
#endif
static grub_size_t static grub_size_t
grub_multiboot_get_mbi_size (void) grub_multiboot_get_mbi_size (void)
{ {
#ifdef GRUB_MACHINE_EFI
if (!efi_mmap_size)
find_efi_mmap_size ();
#endif
return 2 * sizeof (grub_uint32_t) + sizeof (struct multiboot_tag) return 2 * sizeof (grub_uint32_t) + sizeof (struct multiboot_tag)
+ (sizeof (struct multiboot_tag_string) + (sizeof (struct multiboot_tag_string)
+ ALIGN_UP (cmdline_size, MULTIBOOT_TAG_ALIGN)) + ALIGN_UP (cmdline_size, MULTIBOOT_TAG_ALIGN))
@ -318,6 +364,10 @@ grub_multiboot_get_mbi_size (void)
+ ALIGN_UP (sizeof (struct multiboot_tag_old_acpi) + ALIGN_UP (sizeof (struct multiboot_tag_old_acpi)
+ sizeof (struct grub_acpi_rsdp_v10), MULTIBOOT_TAG_ALIGN) + sizeof (struct grub_acpi_rsdp_v10), MULTIBOOT_TAG_ALIGN)
+ acpiv2_size () + acpiv2_size ()
#ifdef GRUB_MACHINE_EFI
+ ALIGN_UP (sizeof (struct multiboot_tag_efi_mmap)
+ efi_mmap_size, MULTIBOOT_TAG_ALIGN)
#endif
+ sizeof (struct multiboot_tag_vbe) + MULTIBOOT_TAG_ALIGN - 1 + sizeof (struct multiboot_tag_vbe) + MULTIBOOT_TAG_ALIGN - 1
+ sizeof (struct multiboot_tag_apm) + MULTIBOOT_TAG_ALIGN - 1; + sizeof (struct multiboot_tag_apm) + MULTIBOOT_TAG_ALIGN - 1;
} }
@ -760,6 +810,28 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
} }
#endif #endif
#ifdef GRUB_MACHINE_EFI
{
struct multiboot_tag_efi_mmap *tag = (struct multiboot_tag_efi_mmap *) ptrorig;
grub_efi_uintn_t efi_desc_size;
grub_efi_uint32_t efi_desc_version;
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 (err)
return err;
tag->descr_size = efi_desc_size;
tag->descr_vers = efi_desc_version;
tag->size = sizeof (*tag) + efi_mmap_size;
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
/ sizeof (grub_properly_aligned_t);
}
#endif
{ {
struct multiboot_tag *tag = (struct multiboot_tag *) ptrorig; struct multiboot_tag *tag = (struct multiboot_tag *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_END; tag->type = MULTIBOOT_TAG_TYPE_END;

View file

@ -58,6 +58,7 @@
#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14 #define MULTIBOOT_TAG_TYPE_ACPI_OLD 14
#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15 #define MULTIBOOT_TAG_TYPE_ACPI_NEW 15
#define MULTIBOOT_TAG_TYPE_NETWORK 16 #define MULTIBOOT_TAG_TYPE_NETWORK 16
#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17
#define MULTIBOOT_HEADER_TAG_END 0 #define MULTIBOOT_HEADER_TAG_END 0
#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1 #define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
@ -361,6 +362,15 @@ struct multiboot_tag_network
multiboot_uint8_t dhcpack[0]; multiboot_uint8_t dhcpack[0];
}; };
struct multiboot_tag_efi_mmap
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t descr_size;
multiboot_uint32_t descr_vers;
multiboot_uint8_t efi_mmap[0];
};
#endif /* ! ASM_FILE */ #endif /* ! ASM_FILE */
#endif /* ! MULTIBOOT_HEADER */ #endif /* ! MULTIBOOT_HEADER */