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.
This commit is contained in:
parent
c352d8dd0b
commit
2eab1c0dad
6 changed files with 180 additions and 14 deletions
21
ChangeLog
21
ChangeLog
|
@ -1,3 +1,24 @@
|
||||||
|
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>
|
2006-04-20 Yoshinori K. Okuji <okuji@enbug.org>
|
||||||
|
|
||||||
* loader/i386/pc/linux.c (grub_rescue_cmd_linux): Compare the file
|
* loader/i386/pc/linux.c (grub_rescue_cmd_linux): Compare the file
|
||||||
|
|
|
@ -69,6 +69,9 @@
|
||||||
|
|
||||||
#define GRUB_EFI_OPTIONAL_PTR 0x00000001
|
#define GRUB_EFI_OPTIONAL_PTR 0x00000001
|
||||||
|
|
||||||
|
#define GRUB_EFI_LOADED_IMAGE_GUID \
|
||||||
|
{ 0x5b1b31a1, 0x9562, 0x11d2, 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b }
|
||||||
|
|
||||||
/* Enumerations. */
|
/* Enumerations. */
|
||||||
enum grub_efi_timer_delay
|
enum grub_efi_timer_delay
|
||||||
{
|
{
|
||||||
|
@ -343,7 +346,6 @@ struct grub_efi_boot_services
|
||||||
grub_efi_event_t *event);
|
grub_efi_event_t *event);
|
||||||
|
|
||||||
grub_efi_status_t
|
grub_efi_status_t
|
||||||
|
|
||||||
(*set_timer) (grub_efi_event_t event,
|
(*set_timer) (grub_efi_event_t event,
|
||||||
grub_efi_timer_delay_t type,
|
grub_efi_timer_delay_t type,
|
||||||
grub_efi_uint64_t trigger_time);
|
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;
|
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 */
|
#endif /* ! GRUB_EFI_API_HEADER */
|
||||||
|
|
|
@ -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 *map_key,
|
||||||
grub_efi_uintn_t *descriptor_size,
|
grub_efi_uintn_t *descriptor_size,
|
||||||
grub_efi_uint32_t *descriptor_version);
|
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_init (void);
|
||||||
void grub_efi_mm_fini (void);
|
void grub_efi_mm_fini (void);
|
||||||
|
|
|
@ -22,8 +22,10 @@
|
||||||
#include <grub/efi/api.h>
|
#include <grub/efi/api.h>
|
||||||
#include <grub/efi/efi.h>
|
#include <grub/efi/efi.h>
|
||||||
#include <grub/efi/console_control.h>
|
#include <grub/efi/console_control.h>
|
||||||
|
#include <grub/efi/pe32.h>
|
||||||
#include <grub/machine/time.h>
|
#include <grub/machine/time.h>
|
||||||
#include <grub/term.h>
|
#include <grub/term.h>
|
||||||
|
#include <grub/kernel.h>
|
||||||
|
|
||||||
/* The handle of GRUB itself. Filled in by the startup code. */
|
/* The handle of GRUB itself. Filled in by the startup code. */
|
||||||
grub_efi_handle_t grub_efi_image_handle;
|
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;
|
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_console_control_guid = GRUB_EFI_CONSOLE_CONTROL_GUID;
|
||||||
|
static grub_efi_guid_t grub_efi_loaded_image_guid = GRUB_EFI_LOADED_IMAGE_GUID;
|
||||||
|
|
||||||
void *
|
void *
|
||||||
grub_efi_locate_protocol (grub_efi_guid_t *protocol, void *registration)
|
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_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
|
void
|
||||||
grub_stop (void)
|
grub_stop (void)
|
||||||
{
|
{
|
||||||
|
@ -108,3 +131,46 @@ grub_get_rtc (void)
|
||||||
+ time.nanosecond / 1000000)
|
+ time.nanosecond / 1000000)
|
||||||
* GRUB_TICKS_PER_SECOND / 1000);
|
* 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;
|
||||||
|
}
|
||||||
|
|
|
@ -45,9 +45,3 @@ grub_arch_sync_caches (void *address __attribute__ ((unused)),
|
||||||
grub_size_t len __attribute__ ((unused)))
|
grub_size_t len __attribute__ ((unused)))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_addr_t
|
|
||||||
grub_arch_modules_addr (void)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
|
@ -591,14 +591,74 @@ write_data_sections (FILE *out, Elf32_Addr current_address,
|
||||||
|
|
||||||
/* Write modules. */
|
/* Write modules. */
|
||||||
static Elf32_Addr
|
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. */
|
struct grub_util_path_list *path_list;
|
||||||
(void) mods;
|
grub_size_t total_module_size;
|
||||||
write_padding (out, GRUB_PE32_SECTION_ALIGNMENT);
|
struct grub_util_path_list *p;
|
||||||
current_address += GRUB_PE32_SECTION_ALIGNMENT;
|
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. */
|
/* 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,
|
mods_address = write_data_sections (out, data_address, e, sections,
|
||||||
section_entsize, num_sections,
|
section_entsize, num_sections,
|
||||||
strtab);
|
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,
|
end_address = make_reloc_section (out, reloc_address, e, section_addresses,
|
||||||
sections, section_entsize, num_sections,
|
sections, section_entsize, num_sections,
|
||||||
strtab);
|
strtab);
|
||||||
|
|
Loading…
Reference in a new issue