]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
2006-04-20 Yoshinori K. Okuji <okuji@enbug.org>
authorokuji <okuji@localhost>
Thu, 20 Apr 2006 04:29:17 +0000 (04:29 +0000)
committerokuji <okuji@localhost>
Thu, 20 Apr 2006 04:29:17 +0000 (04:29 +0000)
        Add support for pre-loaded modules into the EFI port.

        * util/i386/efi/grub-mkimage.c (make_mods_section): Rewritten
        completely. Accept one more argument DIR. The caller has changed.

        * kern/i386/efi/init.c (grub_arch_modules_addr): Removed.

        * kern/efi/efi.c: Include grub/efi/pe32.h and grub/kernel.h.
        (grub_efi_loaded_image_guid): New variable.
        (grub_efi_get_loaded_image): New function.
        (grub_arch_modules_addr): Likewise.

        * include/grub/efi/efi.h (grub_efi_get_loaded_image): New
        prototype.

        * include/grub/efi/api.h (GRUB_EFI_LOADED_IMAGE_GUID): New macro.
        (struct grub_efi_loaded_image): New structure.
        (grub_efi_loaded_image_t): New type.

ChangeLog
include/grub/efi/api.h
include/grub/efi/efi.h
kern/efi/efi.c
kern/i386/efi/init.c
util/i386/efi/grub-mkimage.c

index 8fed46ab78ea32ed9c3db5be4dd1d9a4da477457..ffd3cdf6352fcb7aa10c0c6769ceb23fff9b9c58 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,26 @@
 2006-04-20  Yoshinori K. Okuji  <okuji@enbug.org>
 
+       Add support for pre-loaded modules into the EFI port.
+       
+       * util/i386/efi/grub-mkimage.c (make_mods_section): Rewritten
+       completely. Accept one more argument DIR. The caller has changed.
+
+       * kern/i386/efi/init.c (grub_arch_modules_addr): Removed.
+
+       * kern/efi/efi.c: Include grub/efi/pe32.h and grub/kernel.h.
+       (grub_efi_loaded_image_guid): New variable.
+       (grub_efi_get_loaded_image): New function.
+       (grub_arch_modules_addr): Likewise.
+
+       * include/grub/efi/efi.h (grub_efi_get_loaded_image): New
+       prototype.
+
+       * include/grub/efi/api.h (GRUB_EFI_LOADED_IMAGE_GUID): New macro.
+       (struct grub_efi_loaded_image): New structure.
+       (grub_efi_loaded_image_t): New type.
+
+2006-04-20  Yoshinori K. Okuji  <okuji@enbug.org>
+       
        * loader/i386/pc/linux.c (grub_rescue_cmd_linux): Compare the file
        size with GRUB_OS_AREA_SIZE as grub_size_t instead of
        grub_ssize_t. Reported by Jeff Chua <jeff84@silk.corp.fedex.com>.
index 6de22329ee3568878b06f067d94f3fa8f235aaaf..d8ca9a1fe9f6119d250fdd5c5da81a4d0442acfe 100644 (file)
@@ -69,6 +69,9 @@
 
 #define GRUB_EFI_OPTIONAL_PTR  0x00000001
 
+#define GRUB_EFI_LOADED_IMAGE_GUID     \
+  { 0x5b1b31a1, 0x9562, 0x11d2, 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b }
+
 /* Enumerations.  */
 enum grub_efi_timer_delay
   {
@@ -343,7 +346,6 @@ struct grub_efi_boot_services
                   grub_efi_event_t *event);
 
   grub_efi_status_t
-
   (*set_timer) (grub_efi_event_t event,
                grub_efi_timer_delay_t type,
                grub_efi_uint64_t trigger_time);
@@ -682,4 +684,26 @@ struct grub_efi_system_table
 };
 typedef struct grub_efi_system_table  grub_efi_system_table_t;
 
+struct grub_efi_loaded_image
+{
+  grub_efi_uint32_t revision;
+  grub_efi_handle_t parent_handle;
+  grub_efi_system_table_t *system_table;
+
+  grub_efi_handle_t device_handle;
+  grub_efi_device_path_t *file_path;
+  void *reserved;
+
+  grub_efi_uint32_t load_options_size;
+  void *load_options;
+
+  void *image_base;
+  grub_efi_uint64_t image_size;
+  grub_efi_memory_type_t image_code_type;
+  grub_efi_memory_type_t image_data_type;
+
+  grub_efi_status_t (*unload) (grub_efi_handle_t image_handle);
+};
+typedef struct grub_efi_loaded_image grub_efi_loaded_image_t;
+
 #endif /* ! GRUB_EFI_API_HEADER */
index 1d28f1fd446d5da48e9762b397266e462dbf7f2d..046bfda9341c4a38219cce8020cec8df7cd349e6 100644 (file)
@@ -40,6 +40,7 @@ int EXPORT_FUNC(grub_efi_get_memory_map) (grub_efi_uintn_t *memory_map_size,
                                          grub_efi_uintn_t *map_key,
                                          grub_efi_uintn_t *descriptor_size,
                                          grub_efi_uint32_t *descriptor_version);
+grub_efi_loaded_image_t *EXPORT_FUNC(grub_efi_get_loaded_image) (void);
 
 void grub_efi_mm_init (void);
 void grub_efi_mm_fini (void);
index 299de11c6bea0960f38ec7cecb3aa7873b98bad1..842067d9a7ef47ed647068304a1e7b4b418467f8 100644 (file)
 #include <grub/efi/api.h>
 #include <grub/efi/efi.h>
 #include <grub/efi/console_control.h>
+#include <grub/efi/pe32.h>
 #include <grub/machine/time.h>
 #include <grub/term.h>
+#include <grub/kernel.h>
 
 /* The handle of GRUB itself. Filled in by the startup code.  */
 grub_efi_handle_t grub_efi_image_handle;
@@ -32,6 +34,7 @@ grub_efi_handle_t grub_efi_image_handle;
 grub_efi_system_table_t *grub_efi_system_table;
 
 static grub_efi_guid_t grub_efi_console_control_guid = GRUB_EFI_CONSOLE_CONTROL_GUID;
+static grub_efi_guid_t grub_efi_loaded_image_guid = GRUB_EFI_LOADED_IMAGE_GUID;
 
 void *
 grub_efi_locate_protocol (grub_efi_guid_t *protocol, void *registration)
@@ -83,6 +86,26 @@ grub_efi_stall (grub_efi_uintn_t microseconds)
   grub_efi_system_table->boot_services->stall (microseconds);
 }
 
+grub_efi_loaded_image_t *
+grub_efi_get_loaded_image (void)
+{
+  grub_efi_boot_services_t *b;
+  void *interface;
+  grub_efi_status_t status;
+  
+  b = grub_efi_system_table->boot_services;
+  status = b->open_protocol (grub_efi_image_handle,
+                            &grub_efi_loaded_image_guid,
+                            &interface,
+                            grub_efi_image_handle,
+                            0,
+                            GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+  if (status != GRUB_EFI_SUCCESS)
+    return 0;
+
+  return interface;
+}
+
 void
 grub_stop (void)
 {
@@ -108,3 +131,46 @@ grub_get_rtc (void)
           + time.nanosecond / 1000000)
          * GRUB_TICKS_PER_SECOND / 1000);
 }
+
+/* Search the mods section from the PE32/PE32+ image. This code uses
+   a PE32 header, but should work with PE32+ as well.  */
+grub_addr_t
+grub_arch_modules_addr (void)
+{
+  grub_efi_loaded_image_t *image;
+  struct grub_pe32_header *header;
+  struct grub_pe32_coff_header *coff_header;
+  struct grub_pe32_section_table *sections;
+  struct grub_pe32_section_table *section;
+  struct grub_module_info *info;
+  grub_uint16_t i;
+  
+  image = grub_efi_get_loaded_image ();
+  if (! image)
+    return 0;
+
+  header = image->image_base;
+  coff_header = &(header->coff_header);
+  sections
+    = (struct grub_pe32_section_table *) ((char *) coff_header
+                                         + sizeof (*coff_header)
+                                         + coff_header->optional_header_size);
+
+  for (i = 0, section = sections;
+       i < coff_header->num_sections;
+       i++, section++)
+    {
+      if (grub_strcmp (section->name, "mods") == 0)
+       break;
+    }
+
+  if (i == coff_header->num_sections)
+    return 0;
+
+  info = (struct grub_module_info *) ((char *) image->image_base
+                                     + section->virtual_address);
+  if (info->magic != GRUB_MODULE_MAGIC)
+    return 0;
+
+  return (grub_addr_t) info;
+}
index 364f78bbd680906dd32e5378ec7b90edb30d17de..dab9dddfddf1da32a2e8a7d55d330730265f30cc 100644 (file)
@@ -45,9 +45,3 @@ grub_arch_sync_caches (void *address __attribute__ ((unused)),
                        grub_size_t len __attribute__ ((unused)))
 {
 }
-
-grub_addr_t
-grub_arch_modules_addr (void)
-{
-  return 0;
-}
index 72abda64ecf768fdd8e7ce322da1ce322c86b3ce..aae418db2f63346c0f7a751c526b1dda2a93653c 100644 (file)
@@ -591,14 +591,74 @@ write_data_sections (FILE *out, Elf32_Addr current_address,
 
 /* Write modules.  */
 static Elf32_Addr
-make_mods_section (FILE *out, Elf32_Addr current_address, char *mods[])
+make_mods_section (FILE *out, Elf32_Addr current_address,
+                  const char *dir, char *mods[])
 {
-  /* FIXME: not implemented yet.  */
-  (void) mods;
-  write_padding (out, GRUB_PE32_SECTION_ALIGNMENT);
-  current_address += GRUB_PE32_SECTION_ALIGNMENT;
+  struct grub_util_path_list *path_list;
+  grub_size_t total_module_size;
+  struct grub_util_path_list *p;
+  struct grub_module_info modinfo;
+  Elf32_Addr addr;
 
-  return current_address;
+  path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods);
+  
+  total_module_size = sizeof (struct grub_module_info);
+  for (p = path_list; p; p = p->next)
+    {
+      total_module_size += (grub_util_get_image_size (p->name)
+                           + sizeof (struct grub_module_header));
+    }
+
+  grub_util_info ("the total module size is 0x%x", total_module_size);
+
+  modinfo.magic = grub_cpu_to_le32 (GRUB_MODULE_MAGIC);
+  modinfo.offset = grub_cpu_to_le32 (sizeof (modinfo));
+  modinfo.size = grub_cpu_to_le32 (total_module_size);
+
+  if (fwrite (&modinfo, sizeof (modinfo), 1, out) != 1)
+    grub_util_error ("write failed");
+
+  for (p = path_list; p; p = p->next)
+    {
+      struct grub_module_header header;
+      size_t mod_size;
+      char *mod_image;
+      
+      grub_util_info ("adding module %s", p->name);
+      
+      mod_size = grub_util_get_image_size (p->name);
+      header.offset = grub_cpu_to_le32 (sizeof (header));
+      header.size = grub_cpu_to_le32 (mod_size + sizeof (header));
+      
+      mod_image = grub_util_read_image (p->name);
+
+      if (fwrite (&header, sizeof (header), 1, out) != 1
+         || fwrite (mod_image, mod_size, 1, out) != 1)
+       grub_util_error ("write failed");
+
+      free (mod_image);
+    }
+  
+  for (p = path_list; p; )
+    {
+      struct grub_util_path_list *q;
+
+      q = p->next;
+      free (p);
+      p = q;
+    }
+      
+  current_address += total_module_size;
+  
+  addr = align_pe32_section (current_address);
+  if (addr != current_address)
+    {
+      grub_util_info ("padding %d bytes for the PE32 section alignment",
+                     addr - current_address);
+      write_padding (out, addr - current_address);
+    }
+
+  return addr;
 }
 
 /* Make a .reloc section.  */
@@ -837,7 +897,7 @@ convert_elf (const char *dir, FILE *out, char *mods[])
   mods_address = write_data_sections (out, data_address, e, sections,
                                      section_entsize, num_sections,
                                      strtab);
-  reloc_address = make_mods_section (out, mods_address, mods);
+  reloc_address = make_mods_section (out, mods_address, dir, mods);
   end_address = make_reloc_section (out, reloc_address, e, section_addresses,
                                    sections, section_entsize, num_sections,
                                    strtab);