diff options
author | Michael Brown <mcb30@ipxe.org> | 2012-04-15 01:35:39 +0100 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2012-04-19 13:13:32 +0100 |
commit | 62eb2294f002f16af0af9e4f623dd03c67e8cf4a (patch) | |
tree | d53ad830ef26e029d01cf452e00851fce6417d8a /src/image | |
parent | 2a0154db5b9a7d60aa363d48d441bf1bfe4ca7ad (diff) | |
download | ipxe-62eb2294f002f16af0af9e4f623dd03c67e8cf4a.zip ipxe-62eb2294f002f16af0af9e4f623dd03c67e8cf4a.tar.gz ipxe-62eb2294f002f16af0af9e4f623dd03c67e8cf4a.tar.bz2 |
[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>
Diffstat (limited to 'src/image')
-rw-r--r-- | src/image/elf.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/src/image/elf.c b/src/image/elf.c index f4ea4aa..26666ec 100644 --- a/src/image/elf.c +++ b/src/image/elf.c @@ -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; } } |