Make elfload not use hooks. Opt for flags and iterators instead.
This commit is contained in:
parent
7f8c105f61
commit
73bf57e2c8
9 changed files with 298 additions and 629 deletions
|
@ -1311,89 +1311,6 @@ grub_bsd_load_aout (grub_file_t file, const char *filename)
|
|||
bss_size);
|
||||
}
|
||||
|
||||
static int
|
||||
grub_bsd_elf32_size_hook (grub_elf_t elf __attribute__ ((unused)),
|
||||
Elf32_Phdr *phdr, void *arg __attribute__ ((unused)))
|
||||
{
|
||||
Elf32_Addr paddr;
|
||||
|
||||
if (phdr->p_type != PT_LOAD
|
||||
&& phdr->p_type != PT_DYNAMIC)
|
||||
return 0;
|
||||
|
||||
paddr = phdr->p_paddr & 0xFFFFFFF;
|
||||
|
||||
if (paddr < kern_start)
|
||||
kern_start = paddr;
|
||||
|
||||
if (paddr + phdr->p_memsz > kern_end)
|
||||
kern_end = paddr + phdr->p_memsz;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_bsd_elf32_hook (Elf32_Phdr * phdr, grub_addr_t * addr, int *do_load)
|
||||
{
|
||||
Elf32_Addr paddr;
|
||||
|
||||
if (phdr->p_type != PT_LOAD
|
||||
&& phdr->p_type != PT_DYNAMIC)
|
||||
{
|
||||
*do_load = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*do_load = 1;
|
||||
phdr->p_paddr &= 0xFFFFFFF;
|
||||
paddr = phdr->p_paddr;
|
||||
|
||||
*addr = (grub_addr_t) (paddr - kern_start + (grub_uint8_t *) kern_chunk_src);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static int
|
||||
grub_bsd_elf64_size_hook (grub_elf_t elf __attribute__ ((unused)),
|
||||
Elf64_Phdr *phdr, void *arg __attribute__ ((unused)))
|
||||
{
|
||||
Elf64_Addr paddr;
|
||||
|
||||
if (phdr->p_type != PT_LOAD
|
||||
&& phdr->p_type != PT_DYNAMIC)
|
||||
return 0;
|
||||
|
||||
paddr = phdr->p_paddr & 0xfffffff;
|
||||
|
||||
if (paddr < kern_start)
|
||||
kern_start = paddr;
|
||||
|
||||
if (paddr + phdr->p_memsz > kern_end)
|
||||
kern_end = paddr + phdr->p_memsz;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_bsd_elf64_hook (Elf64_Phdr * phdr, grub_addr_t * addr, int *do_load)
|
||||
{
|
||||
Elf64_Addr paddr;
|
||||
|
||||
if (phdr->p_type != PT_LOAD
|
||||
&& phdr->p_type != PT_DYNAMIC)
|
||||
{
|
||||
*do_load = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*do_load = 1;
|
||||
paddr = phdr->p_paddr & 0xfffffff;
|
||||
|
||||
*addr = (grub_addr_t) (paddr - kern_start + (grub_uint8_t *) kern_chunk_src);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_bsd_load_elf (grub_elf_t elf, const char *filename)
|
||||
{
|
||||
|
@ -1405,12 +1322,29 @@ grub_bsd_load_elf (grub_elf_t elf, const char *filename)
|
|||
if (grub_elf_is_elf32 (elf))
|
||||
{
|
||||
grub_relocator_chunk_t ch;
|
||||
Elf32_Phdr *phdr;
|
||||
|
||||
entry = elf->ehdr.ehdr32.e_entry & 0xFFFFFFF;
|
||||
err = grub_elf32_phdr_iterate (elf, filename,
|
||||
grub_bsd_elf32_size_hook, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
FOR_ELF32_PHDRS (elf, phdr)
|
||||
{
|
||||
Elf32_Addr paddr;
|
||||
|
||||
if (phdr->p_type != PT_LOAD
|
||||
&& phdr->p_type != PT_DYNAMIC)
|
||||
continue;
|
||||
|
||||
paddr = phdr->p_paddr & 0xFFFFFFF;
|
||||
|
||||
if (paddr < kern_start)
|
||||
kern_start = paddr;
|
||||
|
||||
if (paddr + phdr->p_memsz > kern_end)
|
||||
kern_end = paddr + phdr->p_memsz;
|
||||
}
|
||||
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
err = grub_relocator_alloc_chunk_addr (relocator, &ch,
|
||||
kern_start, kern_end - kern_start);
|
||||
if (err)
|
||||
|
@ -1418,7 +1352,7 @@ grub_bsd_load_elf (grub_elf_t elf, const char *filename)
|
|||
|
||||
kern_chunk_src = get_virtual_current_address (ch);
|
||||
|
||||
err = grub_elf32_load (elf, filename, grub_bsd_elf32_hook, 0, 0);
|
||||
err = grub_elf32_load (elf, filename, (grub_uint8_t *) kern_chunk_src - kern_start, GRUB_ELF_LOAD_FLAGS_LOAD_PT_DYNAMIC | GRUB_ELF_LOAD_FLAGS_28BITS, 0, 0);
|
||||
if (err)
|
||||
return err;
|
||||
if (kernel_type != KERNEL_TYPE_OPENBSD)
|
||||
|
@ -1428,6 +1362,8 @@ grub_bsd_load_elf (grub_elf_t elf, const char *filename)
|
|||
}
|
||||
else if (grub_elf_is_elf64 (elf))
|
||||
{
|
||||
Elf64_Phdr *phdr;
|
||||
|
||||
is_64bit = 1;
|
||||
|
||||
if (! grub_cpuid_has_longmode)
|
||||
|
@ -1445,10 +1381,25 @@ grub_bsd_load_elf (grub_elf_t elf, const char *filename)
|
|||
entry_hi = 0;
|
||||
}
|
||||
|
||||
err = grub_elf64_phdr_iterate (elf, filename,
|
||||
grub_bsd_elf64_size_hook, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
FOR_ELF64_PHDRS (elf, phdr)
|
||||
{
|
||||
Elf64_Addr paddr;
|
||||
|
||||
if (phdr->p_type != PT_LOAD
|
||||
&& phdr->p_type != PT_DYNAMIC)
|
||||
continue;
|
||||
|
||||
paddr = phdr->p_paddr & 0xFFFFFFF;
|
||||
|
||||
if (paddr < kern_start)
|
||||
kern_start = paddr;
|
||||
|
||||
if (paddr + phdr->p_memsz > kern_end)
|
||||
kern_end = paddr + phdr->p_memsz;
|
||||
}
|
||||
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
|
||||
grub_dprintf ("bsd", "kern_start = %lx, kern_end = %lx\n",
|
||||
(unsigned long) kern_start, (unsigned long) kern_end);
|
||||
|
@ -1463,7 +1414,7 @@ grub_bsd_load_elf (grub_elf_t elf, const char *filename)
|
|||
}
|
||||
|
||||
err = grub_elf64_load (elf, filename,
|
||||
grub_bsd_elf64_hook, 0, 0);
|
||||
(grub_uint8_t *) kern_chunk_src - kern_start, GRUB_ELF_LOAD_FLAGS_LOAD_PT_DYNAMIC | GRUB_ELF_LOAD_FLAGS_28BITS, 0, 0);
|
||||
if (err)
|
||||
return err;
|
||||
if (kernel_type != KERNEL_TYPE_OPENBSD)
|
||||
|
|
|
@ -55,30 +55,6 @@ grub_chain_unload (void)
|
|||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_chain_elf32_hook (Elf32_Phdr * phdr, grub_addr_t * addr, int *do_load)
|
||||
{
|
||||
grub_err_t err;
|
||||
grub_relocator_chunk_t ch;
|
||||
|
||||
if (phdr->p_type != PT_LOAD)
|
||||
{
|
||||
*do_load = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*do_load = 1;
|
||||
err = grub_relocator_alloc_chunk_addr (relocator, &ch,
|
||||
phdr->p_paddr, phdr->p_memsz);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
*addr = (grub_addr_t) get_virtual_current_address (ch);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_chain (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
|
@ -86,6 +62,7 @@ grub_cmd_chain (grub_command_t cmd __attribute__ ((unused)),
|
|||
grub_err_t err;
|
||||
grub_file_t file;
|
||||
grub_elf_t elf;
|
||||
Elf32_Phdr *phdr;
|
||||
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||
|
@ -118,13 +95,47 @@ grub_cmd_chain (grub_command_t cmd __attribute__ ((unused)),
|
|||
grub_elf_close (elf);
|
||||
}
|
||||
|
||||
entry = elf->ehdr.ehdr32.e_entry & 0xFFFFFF;
|
||||
|
||||
err = grub_elf32_load (elf, argv[0], grub_chain_elf32_hook, 0, 0);
|
||||
entry = elf->ehdr.ehdr32.e_entry;
|
||||
|
||||
FOR_ELF32_PHDRS(elf, phdr)
|
||||
{
|
||||
grub_uint8_t *load_addr;
|
||||
grub_relocator_chunk_t ch;
|
||||
|
||||
if (phdr->p_type != PT_LOAD)
|
||||
continue;
|
||||
|
||||
err = grub_relocator_alloc_chunk_addr (relocator, &ch,
|
||||
phdr->p_paddr, phdr->p_memsz);
|
||||
if (err)
|
||||
break;
|
||||
|
||||
load_addr = get_virtual_current_address (ch);
|
||||
|
||||
if (grub_file_seek (elf->file, phdr->p_offset) == (grub_off_t) -1)
|
||||
return grub_errno;
|
||||
|
||||
if (phdr->p_filesz)
|
||||
{
|
||||
grub_ssize_t read;
|
||||
read = grub_file_read (elf->file, load_addr, phdr->p_filesz);
|
||||
if (read != (grub_ssize_t) phdr->p_filesz)
|
||||
{
|
||||
if (!grub_errno)
|
||||
grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
|
||||
argv[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (phdr->p_filesz < phdr->p_memsz)
|
||||
grub_memset ((load_addr + phdr->p_filesz),
|
||||
0, phdr->p_memsz - phdr->p_filesz);
|
||||
}
|
||||
|
||||
grub_elf_close (elf);
|
||||
if (err)
|
||||
return err;
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
|
||||
grub_loader_set (grub_chain_boot, grub_chain_unload, 0);
|
||||
return GRUB_ERR_NONE;
|
||||
|
|
|
@ -144,7 +144,7 @@ grub_linux_load32 (grub_elf_t elf, const char *filename,
|
|||
/* Linux's entry point incorrectly contains a virtual address. */
|
||||
entry_addr = elf->ehdr.ehdr32.e_entry;
|
||||
|
||||
linux_size = grub_elf32_size (elf, filename, &base, 0);
|
||||
linux_size = grub_elf32_size (elf, &base, 0);
|
||||
if (linux_size == 0)
|
||||
return grub_errno;
|
||||
target_addr = base;
|
||||
|
@ -171,22 +171,7 @@ grub_linux_load32 (grub_elf_t elf, const char *filename,
|
|||
*extra_mem = playground + extraoff;
|
||||
|
||||
/* Now load the segments into the area we claimed. */
|
||||
auto grub_err_t offset_phdr (Elf32_Phdr *phdr, grub_addr_t *addr, int *do_load);
|
||||
grub_err_t offset_phdr (Elf32_Phdr *phdr, grub_addr_t *addr, int *do_load)
|
||||
{
|
||||
if (phdr->p_type != PT_LOAD)
|
||||
{
|
||||
*do_load = 0;
|
||||
return 0;
|
||||
}
|
||||
*do_load = 1;
|
||||
|
||||
/* Linux's program headers incorrectly contain virtual addresses.
|
||||
* Translate those to physical, and offset to the area we claimed. */
|
||||
*addr = (grub_addr_t) (phdr->p_paddr - base + playground);
|
||||
return 0;
|
||||
}
|
||||
return grub_elf32_load (elf, filename, offset_phdr, 0, 0);
|
||||
return grub_elf32_load (elf, filename, playground - base, GRUB_ELF_LOAD_FLAGS_NONE, 0, 0);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
|
@ -200,7 +185,7 @@ grub_linux_load64 (grub_elf_t elf, const char *filename,
|
|||
/* Linux's entry point incorrectly contains a virtual address. */
|
||||
entry_addr = elf->ehdr.ehdr64.e_entry;
|
||||
|
||||
linux_size = grub_elf64_size (elf, filename, &base, 0);
|
||||
linux_size = grub_elf64_size (elf, &base, 0);
|
||||
if (linux_size == 0)
|
||||
return grub_errno;
|
||||
target_addr = base;
|
||||
|
@ -227,21 +212,7 @@ grub_linux_load64 (grub_elf_t elf, const char *filename,
|
|||
*extra_mem = playground + extraoff;
|
||||
|
||||
/* Now load the segments into the area we claimed. */
|
||||
auto grub_err_t offset_phdr (Elf64_Phdr *phdr, grub_addr_t *addr, int *do_load);
|
||||
grub_err_t offset_phdr (Elf64_Phdr *phdr, grub_addr_t *addr, int *do_load)
|
||||
{
|
||||
if (phdr->p_type != PT_LOAD)
|
||||
{
|
||||
*do_load = 0;
|
||||
return 0;
|
||||
}
|
||||
*do_load = 1;
|
||||
/* Linux's program headers incorrectly contain virtual addresses.
|
||||
* Translate those to physical, and offset to the area we claimed. */
|
||||
*addr = (grub_addr_t) (phdr->p_paddr - base + playground);
|
||||
return 0;
|
||||
}
|
||||
return grub_elf64_load (elf, filename, offset_phdr, 0, 0);
|
||||
return grub_elf64_load (elf, filename, playground - base, GRUB_ELF_LOAD_FLAGS_NONE, 0, 0);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
|
|
|
@ -179,7 +179,7 @@ grub_linux_load32 (grub_elf_t elf, const char *filename)
|
|||
grub_uint32_t offset;
|
||||
Elf32_Addr entry;
|
||||
|
||||
linux_size = grub_elf32_size (elf, filename, &base_addr, &align);
|
||||
linux_size = grub_elf32_size (elf, &base_addr, &align);
|
||||
if (linux_size == 0)
|
||||
return grub_errno;
|
||||
/* Pad it; the kernel scribbles over memory beyond its load address. */
|
||||
|
@ -203,20 +203,7 @@ grub_linux_load32 (grub_elf_t elf, const char *filename)
|
|||
linux_addr = seg_addr;
|
||||
|
||||
/* Now load the segments into the area we claimed. */
|
||||
auto grub_err_t offset_phdr (Elf32_Phdr *phdr, grub_addr_t *addr, int *do_load);
|
||||
grub_err_t offset_phdr (Elf32_Phdr *phdr, grub_addr_t *addr, int *do_load)
|
||||
{
|
||||
if (phdr->p_type != PT_LOAD)
|
||||
{
|
||||
*do_load = 0;
|
||||
return 0;
|
||||
}
|
||||
*do_load = 1;
|
||||
|
||||
*addr = (phdr->p_paddr - base_addr) + seg_addr;
|
||||
return 0;
|
||||
}
|
||||
return grub_elf32_load (elf, filename, offset_phdr, 0, 0);
|
||||
return grub_elf32_load (elf, filename, (void *) (seg_addr - base_addr), GRUB_ELF_LOAD_FLAGS_NONE, 0, 0);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
|
@ -228,7 +215,7 @@ grub_linux_load64 (grub_elf_t elf, const char *filename)
|
|||
grub_uint64_t offset;
|
||||
Elf64_Addr entry;
|
||||
|
||||
linux_size = grub_elf64_size (elf, filename, &base_addr, &align);
|
||||
linux_size = grub_elf64_size (elf, &base_addr, &align);
|
||||
if (linux_size == 0)
|
||||
return grub_errno;
|
||||
/* Pad it; the kernel scribbles over memory beyond its load address. */
|
||||
|
@ -250,20 +237,7 @@ grub_linux_load64 (grub_elf_t elf, const char *filename)
|
|||
linux_addr = seg_addr;
|
||||
|
||||
/* Now load the segments into the area we claimed. */
|
||||
auto grub_err_t offset_phdr (Elf64_Phdr *phdr, grub_addr_t *addr, int *do_load);
|
||||
grub_err_t offset_phdr (Elf64_Phdr *phdr, grub_addr_t *addr, int *do_load)
|
||||
{
|
||||
if (phdr->p_type != PT_LOAD)
|
||||
{
|
||||
*do_load = 0;
|
||||
return 0;
|
||||
}
|
||||
*do_load = 1;
|
||||
|
||||
*addr = (phdr->p_paddr - base_addr) + seg_addr;
|
||||
return 0;
|
||||
}
|
||||
return grub_elf64_load (elf, filename, offset_phdr, 0, 0);
|
||||
return grub_elf64_load (elf, filename, (void *) (grub_addr_t) (seg_addr - base_addr), GRUB_ELF_LOAD_FLAGS_NONE, 0, 0);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
|
|
|
@ -261,7 +261,7 @@ grub_linux_load64 (grub_elf_t elf, const char *filename)
|
|||
linux_entry = elf->ehdr.ehdr64.e_entry;
|
||||
linux_addr = 0x40004000;
|
||||
off = 0x4000;
|
||||
linux_size = grub_elf64_size (elf, filename, 0, 0);
|
||||
linux_size = grub_elf64_size (elf, 0, 0);
|
||||
if (linux_size == 0)
|
||||
return grub_errno;
|
||||
|
||||
|
@ -286,21 +286,7 @@ grub_linux_load64 (grub_elf_t elf, const char *filename)
|
|||
base = linux_entry - off;
|
||||
|
||||
/* Now load the segments into the area we claimed. */
|
||||
auto grub_err_t offset_phdr (Elf64_Phdr *phdr, grub_addr_t *addr, int *do_load);
|
||||
grub_err_t offset_phdr (Elf64_Phdr *phdr, grub_addr_t *addr, int *do_load)
|
||||
{
|
||||
if (phdr->p_type != PT_LOAD)
|
||||
{
|
||||
*do_load = 0;
|
||||
return 0;
|
||||
}
|
||||
*do_load = 1;
|
||||
|
||||
/* Adjust the program load address to linux_addr. */
|
||||
*addr = (phdr->p_paddr - base) + (linux_addr - off);
|
||||
return 0;
|
||||
}
|
||||
return grub_elf64_load (elf, filename, offset_phdr, 0, 0);
|
||||
return grub_elf64_load (elf, filename, (void *) (linux_addr - off - base), GRUB_ELF_LOAD_FLAGS_NONE, 0, 0);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue