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. */
void grub_rescue_cmd_linux (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_fpswa (int argc, char *argv[]);

View File

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

View File

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