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>
+ 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>.
#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
{
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);
};
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 */
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);
#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;
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)
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)
{
+ 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;
+}
grub_size_t len __attribute__ ((unused)))
{
}
-
-grub_addr_t
-grub_arch_modules_addr (void)
-{
- return 0;
-}
/* 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. */
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);