Third version of the patch (sent to grub-devel in 2008-01-30)

This commit is contained in:
Robert Millan 2010-01-18 14:28:03 +00:00
parent c8298743f3
commit 45220d832e
4 changed files with 69 additions and 68 deletions

View file

@ -23,7 +23,7 @@
reuse rescue mode commands. */ reuse rescue mode commands. */
void grub_rescue_cmd_linux (int argc, char *argv[]); void grub_rescue_cmd_linux (int argc, char *argv[]);
void grub_rescue_cmd_initrd (int argc, char *argv[]); void grub_rescue_cmd_initrd (int argc, char *argv[]);
void grub_rescue_cmd_module (int argc, char *argv[]); void grub_rescue_cmd_payload (int argc, char *argv[]);
void grub_rescue_cmd_relocate (int argc, char *argv[]); void grub_rescue_cmd_relocate (int argc, char *argv[]);
void grub_rescue_cmd_fpswa (int argc, char *argv[]); void grub_rescue_cmd_fpswa (int argc, char *argv[]);

View file

@ -27,7 +27,7 @@
#include <grub/dl.h> #include <grub/dl.h>
#include <grub/mm.h> #include <grub/mm.h>
#include <grub/cache.h> #include <grub/cache.h>
/* #include <grub/cpu/linux.h> */ #include <grub/kernel.h>
#include <grub/efi/api.h> #include <grub/efi/api.h>
#include <grub/efi/efi.h> #include <grub/efi/efi.h>
#include <grub/elf.h> #include <grub/elf.h>
@ -59,16 +59,16 @@ struct ia64_boot_param
grub_uint64_t initrd_size; grub_uint64_t initrd_size;
grub_uint64_t domain_start; /* boot domain address. */ grub_uint64_t domain_start; /* boot domain address. */
grub_uint64_t domain_size; /* how big is the boot domain */ grub_uint64_t domain_size; /* how big is the boot domain */
grub_uint64_t modules_chain; grub_uint64_t payloads_chain;
grub_uint64_t modules_nbr; grub_uint64_t payloads_nbr;
}; };
struct ia64_boot_module struct ia64_boot_payload
{ {
grub_uint64_t mod_start; grub_uint64_t start;
grub_uint64_t mod_end; grub_uint64_t length;
/* Module command line */ /* Payload command line */
grub_uint64_t cmdline; grub_uint64_t cmdline;
grub_uint64_t next; grub_uint64_t next;
@ -101,7 +101,7 @@ static grub_efi_uintn_t initrd_size;
static struct ia64_boot_param *boot_param; static struct ia64_boot_param *boot_param;
static grub_efi_uintn_t boot_param_pages; static grub_efi_uintn_t boot_param_pages;
static struct ia64_boot_module *last_module = NULL; static struct ia64_boot_payload *last_payload = NULL;
/* Can linux kernel be relocated ? */ /* Can linux kernel be relocated ? */
#define RELOCATE_OFF 0 /* No. */ #define RELOCATE_OFF 0 /* No. */
@ -133,14 +133,15 @@ query_fpswa (void)
bs = grub_efi_system_table->boot_services; bs = grub_efi_system_table->boot_services;
status = bs->locate_handle (GRUB_EFI_BY_PROTOCOL, status = bs->locate_handle (GRUB_EFI_BY_PROTOCOL,
&fpswa_protocol, (void *)&fpswa_protocol,
NULL, &size, &fpswa_image); NULL, &size, &fpswa_image);
if (status != GRUB_EFI_SUCCESS) if (status != GRUB_EFI_SUCCESS)
{ {
grub_printf("Could not locate FPSWA driver\n"); grub_printf("Could not locate FPSWA driver\n");
return; return;
} }
status = bs->handle_protocol (fpswa_image, &fpswa_protocol, &fpswa); status = bs->handle_protocol (fpswa_image,
(void *)&fpswa_protocol, (void *)&fpswa);
if (status != GRUB_EFI_SUCCESS) if (status != GRUB_EFI_SUCCESS)
{ {
grub_printf ("Fpswa protocol not able find the interface\n"); grub_printf ("Fpswa protocol not able find the interface\n");
@ -204,20 +205,20 @@ free_pages (void)
if (boot_param) if (boot_param)
{ {
struct ia64_boot_module *mod; struct ia64_boot_payload *payload;
struct ia64_boot_module *next_mod; struct ia64_boot_payload *next_payload;
/* Free modules. */ /* Free payloads. */
mod = (struct ia64_boot_module *)boot_param->modules_chain; payload = (struct ia64_boot_payload *)boot_param->payloads_chain;
while (mod != 0) while (payload != 0)
{ {
next_mod = (struct ia64_boot_module *)mod->next; next_payload = (struct ia64_boot_payload *)payload->next;
grub_efi_free_boot_pages grub_efi_free_boot_pages
(mod->mod_start, page_align (mod->mod_end - mod->mod_start) >> 12); (payload->start, page_align (payload->length) >> 12);
grub_efi_free_boot_pages ((grub_efi_physical_address_t)mod, 1); grub_efi_free_boot_pages ((grub_efi_physical_address_t)payload, 1);
mod = next_mod; payload = next_payload;
} }
/* Free bootparam. */ /* Free bootparam. */
@ -446,8 +447,8 @@ grub_load_elf64 (grub_file_t file, void *buffer)
kernel_mem = allocate_pages (align, kernel_pages, low_addr); kernel_mem = allocate_pages (align, kernel_pages, low_addr);
if (kernel_mem) if (kernel_mem)
{ {
reloc_offset = kernel_mem - low_addr; reloc_offset = (grub_uint64_t)kernel_mem - low_addr;
grub_printf (" Relocated at %p (offset=%016llx)\n", grub_printf (" Relocated at %p (offset=%016lx)\n",
kernel_mem, reloc_offset); kernel_mem, reloc_offset);
entry += reloc_offset; entry += reloc_offset;
} }
@ -463,12 +464,12 @@ grub_load_elf64 (grub_file_t file, void *buffer)
+ i * ehdr->e_phentsize); + i * ehdr->e_phentsize);
if (phdr->p_type == PT_LOAD) if (phdr->p_type == PT_LOAD)
{ {
grub_printf (" [paddr=%llx load=%llx memsz=%08llx " grub_printf (" [paddr=%lx load=%lx memsz=%08lx "
"off=%lx flags=%x]\n", "off=%lx flags=%x]\n",
phdr->p_paddr, phdr->p_paddr + reloc_offset, phdr->p_paddr, phdr->p_paddr + reloc_offset,
phdr->p_memsz, phdr->p_offset, phdr->p_flags); phdr->p_memsz, phdr->p_offset, phdr->p_flags);
if (grub_file_seek (file, phdr->p_offset) == -1) if (grub_file_seek (file, phdr->p_offset) == (grub_off_t)-1)
return grub_error (GRUB_ERR_BAD_OS, return grub_error (GRUB_ERR_BAD_OS,
"invalid offset in program header"); "invalid offset in program header");
@ -582,7 +583,7 @@ grub_rescue_cmd_initrd (int argc, char *argv[])
if (argc == 0) if (argc == 0)
{ {
grub_error (GRUB_ERR_BAD_ARGUMENT, "No module specified"); grub_error (GRUB_ERR_BAD_ARGUMENT, "No filename specified");
goto fail; goto fail;
} }
@ -619,12 +620,12 @@ grub_rescue_cmd_initrd (int argc, char *argv[])
} }
void void
grub_rescue_cmd_module (int argc, char *argv[]) grub_rescue_cmd_payload (int argc, char *argv[])
{ {
grub_file_t file = 0; grub_file_t file = 0;
grub_ssize_t size, len = 0; grub_ssize_t size, len = 0;
char *module = 0, *cmdline = 0, *p; char *base = 0, *cmdline = 0, *p;
struct ia64_boot_module *mod = NULL; struct ia64_boot_payload *payload = NULL;
int i; int i;
if (argc == 0) if (argc == 0)
@ -636,7 +637,7 @@ grub_rescue_cmd_module (int argc, char *argv[])
if (!boot_param) if (!boot_param)
{ {
grub_error (GRUB_ERR_BAD_ARGUMENT, grub_error (GRUB_ERR_BAD_ARGUMENT,
"You need to load the multiboot kernel first"); "You need to load the kernel first");
goto fail; goto fail;
} }
@ -645,47 +646,47 @@ grub_rescue_cmd_module (int argc, char *argv[])
goto fail; goto fail;
size = grub_file_size (file); size = grub_file_size (file);
module = grub_efi_allocate_boot_pages (0, page_align (size) >> 12); base = grub_efi_allocate_boot_pages (0, page_align (size) >> 12);
if (! module) if (! base)
goto fail; goto fail;
grub_printf ("Module %s [addr=%llx + %lx]\n", grub_printf ("Payload %s [addr=%lx + %lx]\n",
argv[0], (grub_uint64_t)module, size); argv[0], (grub_uint64_t)base, size);
if (grub_file_read (file, module, size) != size) if (grub_file_read (file, base, size) != size)
{ {
grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file"); grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file");
goto fail; goto fail;
} }
len = sizeof (struct ia64_boot_module); len = sizeof (struct ia64_boot_payload);
for (i = 0; i < argc; i++) for (i = 0; i < argc; i++)
len += grub_strlen (argv[i]) + 1; len += grub_strlen (argv[i]) + 1;
if (len > 4096) if (len > 4096)
{ {
grub_error (GRUB_ERR_OUT_OF_RANGE, "module command line too long"); grub_error (GRUB_ERR_OUT_OF_RANGE, "payload command line too long");
goto fail; goto fail;
} }
mod = grub_efi_allocate_boot_pages (0, 1); payload = grub_efi_allocate_boot_pages (0, 1);
if (! mod) if (! payload)
goto fail; goto fail;
p = (char *)(mod + 1); p = (char *)(payload + 1);
mod->mod_start = (grub_uint64_t)module; payload->start = (grub_uint64_t)base;
mod->mod_end = (grub_uint64_t)module + size; payload->length = size;
mod->cmdline = (grub_uint64_t)p; payload->cmdline = (grub_uint64_t)p;
mod->next = 0; payload->next = 0;
if (last_module) if (last_payload)
last_module->next = (grub_uint64_t)mod; last_payload->next = (grub_uint64_t)payload;
else else
{ {
last_module = mod; last_payload = payload;
boot_param->modules_chain = (grub_uint64_t)mod; boot_param->payloads_chain = (grub_uint64_t)payload;
} }
boot_param->modules_nbr++; boot_param->payloads_nbr++;
/* Copy command line. */ /* Copy command line. */
for (i = 0; i < argc; i++) for (i = 0; i < argc; i++)
@ -704,7 +705,7 @@ grub_rescue_cmd_module (int argc, char *argv[])
if (grub_errno != GRUB_ERR_NONE) if (grub_errno != GRUB_ERR_NONE)
{ {
grub_free (module); grub_free (base);
grub_free (cmdline); grub_free (cmdline);
} }
} }
@ -761,8 +762,8 @@ GRUB_MOD_INIT(linux)
grub_rescue_register_command ("initrd", grub_rescue_register_command ("initrd",
grub_rescue_cmd_initrd, grub_rescue_cmd_initrd,
"load initrd"); "load initrd");
grub_rescue_register_command ("module", grub_rescue_cmd_module, grub_rescue_register_command ("payload", grub_rescue_cmd_payload,
"load a multiboot module"); "load an additional file");
grub_rescue_register_command ("relocate", grub_rescue_cmd_relocate, grub_rescue_register_command ("relocate", grub_rescue_cmd_relocate,
"set relocate feature"); "set relocate feature");
grub_rescue_register_command ("fpswa", grub_rescue_cmd_fpswa, grub_rescue_register_command ("fpswa", grub_rescue_cmd_fpswa,
@ -774,7 +775,7 @@ GRUB_MOD_FINI(linux)
{ {
grub_rescue_unregister_command ("linux"); grub_rescue_unregister_command ("linux");
grub_rescue_unregister_command ("initrd"); grub_rescue_unregister_command ("initrd");
grub_rescue_unregister_command ("module"); grub_rescue_unregister_command ("payload");
grub_rescue_unregister_command ("relocate"); grub_rescue_unregister_command ("relocate");
grub_rescue_unregister_command ("fpswa"); grub_rescue_unregister_command ("fpswa");
} }

View file

@ -40,10 +40,10 @@ grub_normal_initrd_command (struct grub_arg_list *state __attribute__ ((unused))
} }
static grub_err_t static grub_err_t
grub_normal_cmd_module (struct grub_arg_list *state __attribute__ ((unused)), grub_normal_cmd_payload (struct grub_arg_list *state __attribute__ ((unused)),
int argc, char **args) int argc, char **args)
{ {
grub_rescue_cmd_module (argc, args); grub_rescue_cmd_payload (argc, args);
return grub_errno; return grub_errno;
} }
@ -79,10 +79,10 @@ GRUB_MOD_INIT(linux_normal)
"Load an initrd.", 0); "Load an initrd.", 0);
grub_register_command grub_register_command
("module", grub_normal_cmd_module, ("payload", grub_normal_cmd_payload,
GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_NO_ARG_PARSE, GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_NO_ARG_PARSE,
"module FILE [ARGS...]", "payload FILE [ARGS...]",
"Load a Multiboot module.", 0); "Load an additional file.", 0);
grub_register_command grub_register_command
("relocate", grub_normal_cmd_relocate, ("relocate", grub_normal_cmd_relocate,
@ -101,7 +101,7 @@ GRUB_MOD_FINI(linux_normal)
{ {
grub_unregister_command ("linux"); grub_unregister_command ("linux");
grub_unregister_command ("initrd"); grub_unregister_command ("initrd");
grub_unregister_command ("module"); grub_unregister_command ("payload");
grub_unregister_command ("relocate"); grub_unregister_command ("relocate");
grub_unregister_command ("fpswa"); grub_unregister_command ("fpswa");
} }

View file

@ -70,7 +70,7 @@ typedef Elf64_Sym Elf_Sym;
#define ELF_R_SYM(r) ELF64_R_SYM(r) #define ELF_R_SYM(r) ELF64_R_SYM(r)
#endif #endif
#ifdef __ia64__ #ifdef ELF2PE_IA64
#define ELF_ETYPE ET_DYN #define ELF_ETYPE ET_DYN
#else #else
#define ELF_ETYPE ET_EXEC #define ELF_ETYPE ET_EXEC
@ -99,7 +99,7 @@ uint32_t text_offset;
uint32_t data_offset; uint32_t data_offset;
uint32_t reloc_offset; uint32_t reloc_offset;
#ifdef __ia64__ #ifdef ELF2PE_IA64
uint32_t coff_entry_descr_offset; uint32_t coff_entry_descr_offset;
uint32_t coff_entry_descr_func; uint32_t coff_entry_descr_func;
uint64_t plt_base; uint64_t plt_base;
@ -160,7 +160,7 @@ is_text_shdr (Elf_Shdr *shdr)
if (shdr->sh_type != SHT_PROGBITS) { if (shdr->sh_type != SHT_PROGBITS) {
return 0; return 0;
} }
#ifdef __ia64__ #ifdef ELF2PE_IA64
return (shdr->sh_flags & (SHF_EXECINSTR | SHF_ALLOC)) return (shdr->sh_flags & (SHF_EXECINSTR | SHF_ALLOC))
== (SHF_ALLOC | SHF_EXECINSTR); == (SHF_ALLOC | SHF_EXECINSTR);
#else #else
@ -229,7 +229,7 @@ scan_sections (void)
} }
coff_sections_offset[i] = coff_offset; coff_sections_offset[i] = coff_offset;
coff_offset += shdr->sh_size; coff_offset += shdr->sh_size;
#ifdef __ia64__ #ifdef ELF2PE_IA64
if (coff_sections_offset[i] != shdr->sh_addr) { if (coff_sections_offset[i] != shdr->sh_addr) {
fprintf (stderr, fprintf (stderr,
"Section %s: Coff offset (%x) != Elf offset (%lx)", "Section %s: Coff offset (%x) != Elf offset (%lx)",
@ -244,7 +244,7 @@ scan_sections (void)
shdr_dynamic = shdr; shdr_dynamic = shdr;
} }
} }
#ifdef __ia64__ #ifdef ELF2PE_IA64
/* 16 bytes are reserved (by the ld script) for the entry point descriptor. /* 16 bytes are reserved (by the ld script) for the entry point descriptor.
*/ */
coff_entry_descr_offset = coff_offset - 16; coff_entry_descr_offset = coff_offset - 16;
@ -259,7 +259,7 @@ scan_sections (void)
if (is_data_shdr (shdr)) { if (is_data_shdr (shdr)) {
coff_sections_offset[i] = coff_offset; coff_sections_offset[i] = coff_offset;
coff_offset += shdr->sh_size; coff_offset += shdr->sh_size;
#ifdef __ia64__ #ifdef ELF2PE_IA64
if (coff_sections_offset[i] != shdr->sh_addr) { if (coff_sections_offset[i] != shdr->sh_addr) {
fprintf (stderr, fprintf (stderr,
"Section %s: Coff offset (%x) != Elf offset (%lx)", "Section %s: Coff offset (%x) != Elf offset (%lx)",
@ -307,7 +307,7 @@ scan_sections (void)
nt_hdr->optional_header.code_size = data_offset - text_offset; nt_hdr->optional_header.code_size = data_offset - text_offset;
nt_hdr->optional_header.data_size = reloc_offset - data_offset; nt_hdr->optional_header.data_size = reloc_offset - data_offset;
nt_hdr->optional_header.bss_size = 0; nt_hdr->optional_header.bss_size = 0;
#ifdef __ia64__ #ifdef ELF2PE_IA64
nt_hdr->optional_header.entry_addr = coff_entry_descr_offset; nt_hdr->optional_header.entry_addr = coff_entry_descr_offset;
coff_entry_descr_func = coff_entry; coff_entry_descr_func = coff_entry;
#else #else
@ -335,7 +335,7 @@ scan_sections (void)
PE32_SCN_CNT_INITIALIZED_DATA PE32_SCN_CNT_INITIALIZED_DATA
| PE32_SCN_MEM_WRITE | PE32_SCN_MEM_WRITE
| PE32_SCN_MEM_READ); | PE32_SCN_MEM_READ);
#ifdef __ia64__ #ifdef ELF2PE_IA64
if (shdr_dynamic != NULL) if (shdr_dynamic != NULL)
{ {
Elf64_Dyn *dyn = (Elf64_Dyn*)((uint8_t*)ehdr + shdr_dynamic->sh_offset); Elf64_Dyn *dyn = (Elf64_Dyn*)((uint8_t*)ehdr + shdr_dynamic->sh_offset);
@ -639,7 +639,7 @@ write_relocations(void)
} }
} }
#ifdef __ia64__ #ifdef ELF2PE_IA64
coff_add_fixup (coff_entry_descr_offset, PE32_REL_BASED_DIR64); coff_add_fixup (coff_entry_descr_offset, PE32_REL_BASED_DIR64);
coff_add_fixup (coff_entry_descr_offset + 8, PE32_REL_BASED_DIR64); coff_add_fixup (coff_entry_descr_offset + 8, PE32_REL_BASED_DIR64);
#endif #endif
@ -719,7 +719,7 @@ convert_elf (uint8_t **file_buffer, unsigned int *file_length)
if (write_sections (is_text_shdr) != 0) if (write_sections (is_text_shdr) != 0)
return -3; return -3;
#ifdef __ia64__ #ifdef ELF2PE_IA64
*(uint64_t*)(coff_file + coff_entry_descr_offset) = coff_entry_descr_func; *(uint64_t*)(coff_file + coff_entry_descr_offset) = coff_entry_descr_func;
*(uint64_t*)(coff_file + coff_entry_descr_offset + 8) = plt_base; *(uint64_t*)(coff_file + coff_entry_descr_offset + 8) = plt_base;
#endif #endif