]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
* grub-core/loader/multiboot_mbi2.c: Implement EFI memory map.
authorVladimir Serbinenko <phcoder@gmail.com>
Mon, 28 Oct 2013 14:37:00 +0000 (15:37 +0100)
committerVladimir Serbinenko <phcoder@gmail.com>
Mon, 28 Oct 2013 14:37:00 +0000 (15:37 +0100)
ChangeLog
grub-core/loader/i386/multiboot_mbi.c
grub-core/loader/multiboot.c
grub-core/loader/multiboot_mbi2.c
include/multiboot2.h

index 62d5e7bea2c66967f22d85a71c8c89cf5f728cf0..4c7a1a08f12435b703c70be27316f283a69c2aa9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
index e78b482a7ef9cbbd5aa652f4ed378c8a0d3d3c56..bff03896bae0d834ab26275c9bbb45765492fb28 100644 (file)
 #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;
 }
 
index 093717cde1141cb3e3c3fd38d852e18df8808ff0..54e4d240858d27bdb270e8df94026c777c6b63da 100644 (file)
@@ -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
index 561c7915732065f869935c4a2e2af7fd7571c85b..dfd7b92924e2cfdde33a454053bd2af8d999c7fe 100644 (file)
@@ -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;
index 0e26a8ec27a5bbdd76990ec682d77d8c6e83f840..58f2f684554d108056b6e34229d23d6a4a908cbd 100644 (file)
@@ -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 */