#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))
+ 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;
}
}
#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;
#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
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 */