summaryrefslogtreecommitdiffstats
path: root/src/image
diff options
context:
space:
mode:
authorMichael Brown2012-04-15 02:35:39 +0200
committerMichael Brown2012-04-19 14:13:32 +0200
commit62eb2294f002f16af0af9e4f623dd03c67e8cf4a (patch)
treed53ad830ef26e029d01cf452e00851fce6417d8a /src/image
parent[realtek] Replace driver for Realtek Gigabit NICs (diff)
downloadipxe-62eb2294f002f16af0af9e4f623dd03c67e8cf4a.tar.gz
ipxe-62eb2294f002f16af0af9e4f623dd03c67e8cf4a.tar.xz
ipxe-62eb2294f002f16af0af9e4f623dd03c67e8cf4a.zip
[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.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/src/image/elf.c b/src/image/elf.c
index f4ea4aab..26666ec5 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;
}
}