mirror of
https://github.com/ipxe/ipxe
synced 2026-02-07 07:23:41 +03:00
[multiboot] Place multiboot modules low in memory
Solaris assumes that there is enough space above the Multiboot modules to use as a decompression and scratch area. This assumption is invalid when using iPXE, which places the Multiboot modules near the top of (32-bit) memory. Fix by copying the modules to an area of memory immediately following the loaded kernel. Debugged-by: Michael Brown <mcb30@ipxe.org> Debugged-by: Scott McWhirter <scottm@joyent.com> Tested-by: Robin Smidsrød <robin@smidsrod.no> Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
@@ -47,11 +47,14 @@ typedef Elf32_Off Elf_Off;
|
||||
* @v phdr ELF program header
|
||||
* @v ehdr ELF executable header
|
||||
* @ret entry Entry point, if found
|
||||
* @ret max Maximum used address
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int elf_load_segment ( struct image *image, Elf_Phdr *phdr,
|
||||
Elf_Ehdr *ehdr, physaddr_t *entry ) {
|
||||
Elf_Ehdr *ehdr, physaddr_t *entry,
|
||||
physaddr_t *max ) {
|
||||
physaddr_t dest;
|
||||
physaddr_t end;
|
||||
userptr_t buffer;
|
||||
unsigned long e_offset;
|
||||
int rc;
|
||||
@@ -79,6 +82,7 @@ static int elf_load_segment ( struct image *image, Elf_Phdr *phdr,
|
||||
return -ENOEXEC;
|
||||
}
|
||||
buffer = phys_to_user ( dest );
|
||||
end = ( dest + phdr->p_memsz );
|
||||
|
||||
DBGC ( image, "ELF %p loading segment [%x,%x) to [%x,%x,%x)\n", image,
|
||||
phdr->p_offset, ( phdr->p_offset + phdr->p_filesz ),
|
||||
@@ -93,6 +97,10 @@ static int elf_load_segment ( struct image *image, Elf_Phdr *phdr,
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Update maximum used address, if applicable */
|
||||
if ( end > *max )
|
||||
*max = end;
|
||||
|
||||
/* Copy image to segment */
|
||||
memcpy_user ( buffer, 0, image->data, phdr->p_offset, phdr->p_filesz );
|
||||
|
||||
@@ -119,9 +127,10 @@ static int elf_load_segment ( struct image *image, Elf_Phdr *phdr,
|
||||
*
|
||||
* @v image ELF file
|
||||
* @ret entry Entry point
|
||||
* @ret max Maximum used address
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int elf_load ( struct image *image, physaddr_t *entry ) {
|
||||
int elf_load ( struct image *image, physaddr_t *entry, physaddr_t *max ) {
|
||||
static const uint8_t e_ident[] = {
|
||||
[EI_MAG0] = ELFMAG0,
|
||||
[EI_MAG1] = ELFMAG1,
|
||||
@@ -143,6 +152,9 @@ int elf_load ( struct image *image, physaddr_t *entry ) {
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
/* Initialise maximum used address */
|
||||
*max = 0;
|
||||
|
||||
/* Invalidate entry point */
|
||||
*entry = 0;
|
||||
|
||||
@@ -156,7 +168,7 @@ int elf_load ( struct image *image, physaddr_t *entry ) {
|
||||
}
|
||||
copy_from_user ( &phdr, image->data, phoff, sizeof ( phdr ) );
|
||||
if ( ( rc = elf_load_segment ( image, &phdr, &ehdr,
|
||||
entry ) ) != 0 ) {
|
||||
entry, max ) ) != 0 ) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user