* grub-core/loader/multiboot_mbi2.c: Implement EFI memory map.
This commit is contained in:
parent
00bfa988fc
commit
329550c4a9
5 changed files with 96 additions and 6 deletions
|
@ -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>
|
||||
|
||||
* grub-core/loader/multiboot.c: Add support for multiboot kernels
|
||||
|
|
|
@ -36,6 +36,10 @@
|
|||
#include <grub/net.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. */
|
||||
#define UNSUPPORTED_FLAGS 0x0000fff8
|
||||
|
||||
|
@ -587,6 +591,12 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
|
|||
ptrdest += sizeof (struct grub_vbe_mode_info_block);
|
||||
#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;
|
||||
}
|
||||
|
||||
|
|
|
@ -131,12 +131,6 @@ grub_multiboot_boot (void)
|
|||
if (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__)
|
||||
grub_relocator32_boot (grub_multiboot_relocator, state, 0);
|
||||
#else
|
||||
|
|
|
@ -295,9 +295,55 @@ acpiv2_size (void)
|
|||
#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
|
||||
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)
|
||||
+ (sizeof (struct multiboot_tag_string)
|
||||
+ 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)
|
||||
+ sizeof (struct grub_acpi_rsdp_v10), MULTIBOOT_TAG_ALIGN)
|
||||
+ 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_apm) + MULTIBOOT_TAG_ALIGN - 1;
|
||||
}
|
||||
|
@ -760,6 +810,28 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
|
|||
}
|
||||
#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;
|
||||
tag->type = MULTIBOOT_TAG_TYPE_END;
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14
|
||||
#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15
|
||||
#define MULTIBOOT_TAG_TYPE_NETWORK 16
|
||||
#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17
|
||||
|
||||
#define MULTIBOOT_HEADER_TAG_END 0
|
||||
#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
|
||||
|
@ -361,6 +362,15 @@ struct multiboot_tag_network
|
|||
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 /* ! MULTIBOOT_HEADER */
|
||||
|
|
Loading…
Reference in a new issue