mbi: Use per segment a separate relocator chunk
Instead of setting up a all comprising relocator chunk for all segments, use per segment a separate relocator chunk. Currently, if the ELF is non-relocatable, a single relocator chunk will comprise memory (between the segments) which gets overridden by the relst() invocation of the movers code in grub_relocator16/32/64_boot(). The overridden memory may contain reserved ranges like VGA memory or ACPI tables, which may lead to crashes or at least to strange boot behaviour. Signed-off-by: Alexander Boettcher <alexander.boettcher@genode-labs.com> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
This commit is contained in:
parent
ba474d531a
commit
14ec665c3f
1 changed files with 40 additions and 23 deletions
|
@ -57,9 +57,9 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
|
||||||
char *phdr_base;
|
char *phdr_base;
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
grub_relocator_chunk_t ch;
|
grub_relocator_chunk_t ch;
|
||||||
grub_uint32_t load_offset, load_size;
|
grub_uint32_t load_offset = 0, load_size;
|
||||||
int i;
|
int i;
|
||||||
void *source;
|
void *source = NULL;
|
||||||
|
|
||||||
if (ehdr->e_ident[EI_MAG0] != ELFMAG0
|
if (ehdr->e_ident[EI_MAG0] != ELFMAG0
|
||||||
|| ehdr->e_ident[EI_MAG1] != ELFMAG1
|
|| ehdr->e_ident[EI_MAG1] != ELFMAG1
|
||||||
|
@ -97,10 +97,15 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
|
||||||
return grub_error (GRUB_ERR_BAD_OS, "segment crosses 4 GiB border");
|
return grub_error (GRUB_ERR_BAD_OS, "segment crosses 4 GiB border");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
load_size = highest_load - mld->link_base_addr;
|
|
||||||
|
|
||||||
if (mld->relocatable)
|
if (mld->relocatable)
|
||||||
{
|
{
|
||||||
|
load_size = highest_load - mld->link_base_addr;
|
||||||
|
|
||||||
|
grub_dprintf ("multiboot_loader", "align=0x%lx, preference=0x%x, "
|
||||||
|
"load_size=0x%x, avoid_efi_boot_services=%d\n",
|
||||||
|
(long) mld->align, mld->preference, load_size,
|
||||||
|
mld->avoid_efi_boot_services);
|
||||||
|
|
||||||
if (load_size > mld->max_addr || mld->min_addr > mld->max_addr - load_size)
|
if (load_size > mld->max_addr || mld->min_addr > mld->max_addr - load_size)
|
||||||
return grub_error (GRUB_ERR_BAD_OS, "invalid min/max address and/or load size");
|
return grub_error (GRUB_ERR_BAD_OS, "invalid min/max address and/or load size");
|
||||||
|
|
||||||
|
@ -108,27 +113,22 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
|
||||||
mld->min_addr, mld->max_addr - load_size,
|
mld->min_addr, mld->max_addr - load_size,
|
||||||
load_size, mld->align ? mld->align : 1,
|
load_size, mld->align ? mld->align : 1,
|
||||||
mld->preference, mld->avoid_efi_boot_services);
|
mld->preference, mld->avoid_efi_boot_services);
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
grub_dprintf ("multiboot_loader", "Cannot allocate memory for OS image\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
mld->load_base_addr = get_physical_target_address (ch);
|
||||||
|
source = get_virtual_current_address (ch);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
err = grub_relocator_alloc_chunk_addr (GRUB_MULTIBOOT (relocator), &ch,
|
mld->load_base_addr = mld->link_base_addr;
|
||||||
mld->link_base_addr, load_size);
|
|
||||||
|
|
||||||
if (err)
|
grub_dprintf ("multiboot_loader", "relocatable=%d, link_base_addr=0x%x, "
|
||||||
{
|
"load_base_addr=0x%x\n", relocatable,
|
||||||
grub_dprintf ("multiboot_loader", "Cannot allocate memory for OS image\n");
|
mld->link_base_addr, mld->load_base_addr);
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
mld->load_base_addr = get_physical_target_address (ch);
|
|
||||||
source = get_virtual_current_address (ch);
|
|
||||||
|
|
||||||
grub_dprintf ("multiboot_loader", "link_base_addr=0x%x, load_base_addr=0x%x, "
|
|
||||||
"load_size=0x%x, relocatable=%d\n", mld->link_base_addr,
|
|
||||||
mld->load_base_addr, load_size, mld->relocatable);
|
|
||||||
|
|
||||||
if (mld->relocatable)
|
|
||||||
grub_dprintf ("multiboot_loader", "align=0x%lx, preference=0x%x, avoid_efi_boot_services=%d\n",
|
|
||||||
(long) mld->align, mld->preference, mld->avoid_efi_boot_services);
|
|
||||||
|
|
||||||
/* Load every loadable segment in memory. */
|
/* Load every loadable segment in memory. */
|
||||||
for (i = 0; i < ehdr->e_phnum; i++)
|
for (i = 0; i < ehdr->e_phnum; i++)
|
||||||
|
@ -139,7 +139,24 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
|
||||||
grub_dprintf ("multiboot_loader", "segment %d: paddr=0x%lx, memsz=0x%lx, vaddr=0x%lx\n",
|
grub_dprintf ("multiboot_loader", "segment %d: paddr=0x%lx, memsz=0x%lx, vaddr=0x%lx\n",
|
||||||
i, (long) phdr(i)->p_paddr, (long) phdr(i)->p_memsz, (long) phdr(i)->p_vaddr);
|
i, (long) phdr(i)->p_paddr, (long) phdr(i)->p_memsz, (long) phdr(i)->p_vaddr);
|
||||||
|
|
||||||
load_offset = phdr(i)->p_paddr - mld->link_base_addr;
|
if (mld->relocatable)
|
||||||
|
{
|
||||||
|
load_offset = phdr(i)->p_paddr - mld->link_base_addr;
|
||||||
|
grub_dprintf ("multiboot_loader", "segment %d: load_offset=0x%x\n", i, load_offset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
err = grub_relocator_alloc_chunk_addr (GRUB_MULTIBOOT (relocator), &ch,
|
||||||
|
phdr(i)->p_paddr, phdr(i)->p_memsz);
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
grub_dprintf ("multiboot_loader", "Cannot allocate memory for OS image\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
source = get_virtual_current_address (ch);
|
||||||
|
}
|
||||||
|
|
||||||
if (phdr(i)->p_filesz != 0)
|
if (phdr(i)->p_filesz != 0)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue