diff options
author | Michael Brown <mcb30@ipxe.org> | 2011-03-07 00:37:50 +0000 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2011-03-07 00:37:50 +0000 |
commit | 34b6ecb2f1d7940a0065cbabd6f9dcd439b4c841 (patch) | |
tree | ea583bf6fde26b2ed12ee3c6b117055e555555d9 /src/image/elf.c | |
parent | 530a01eff0351d177d95e021249ec65ec631108c (diff) | |
download | ipxe-34b6ecb2f1d7940a0065cbabd6f9dcd439b4c841.zip ipxe-34b6ecb2f1d7940a0065cbabd6f9dcd439b4c841.tar.gz ipxe-34b6ecb2f1d7940a0065cbabd6f9dcd439b4c841.tar.bz2 |
[image] Simplify image management
Refactor the {load,exec} image operations as {probe,exec}. This makes
the probe mechanism cleaner, eliminates some forward declarations,
avoids holding magic state in image->priv, eliminates the possibility
of screwing up between the "load" and "exec" stages, and makes the
documentation simpler since the concept of "loading" (as distinct from
"executing") no longer needs to be explained.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/image/elf.c')
-rw-r--r-- | src/image/elf.c | 29 |
1 files changed, 15 insertions, 14 deletions
diff --git a/src/image/elf.c b/src/image/elf.c index 740fd3a..406a8d4 100644 --- a/src/image/elf.c +++ b/src/image/elf.c @@ -45,10 +45,11 @@ typedef Elf32_Off Elf_Off; * @v image ELF file * @v phdr ELF program header * @v ehdr ELF executable header + * @ret entry Entry point, if found * @ret rc Return status code */ static int elf_load_segment ( struct image *image, Elf_Phdr *phdr, - Elf_Ehdr *ehdr ) { + Elf_Ehdr *ehdr, physaddr_t *entry ) { physaddr_t dest; userptr_t buffer; unsigned long e_offset; @@ -96,15 +97,15 @@ static int elf_load_segment ( struct image *image, Elf_Phdr *phdr, /* Set execution address, if it lies within this segment */ if ( ( e_offset = ( ehdr->e_entry - dest ) ) < phdr->p_filesz ) { - image->priv.phys = ehdr->e_entry; + *entry = ehdr->e_entry; DBGC ( image, "ELF %p found physical entry point at %lx\n", - image, image->priv.phys ); + image, *entry ); } else if ( ( e_offset = ( ehdr->e_entry - phdr->p_vaddr ) ) < phdr->p_filesz ) { - if ( ! image->priv.phys ) { - image->priv.phys = ( dest + e_offset ); + if ( ! *entry ) { + *entry = ( dest + e_offset ); DBGC ( image, "ELF %p found virtual entry point at %lx" - " (virt %lx)\n", image, image->priv.phys, + " (virt %lx)\n", image, *entry, ( ( unsigned long ) ehdr->e_entry ) ); } } @@ -116,18 +117,16 @@ static int elf_load_segment ( struct image *image, Elf_Phdr *phdr, * Load ELF image into memory * * @v image ELF file + * @ret entry Entry point * @ret rc Return status code */ -int elf_load ( struct image *image ) { +int elf_load ( struct image *image, physaddr_t *entry ) { Elf_Ehdr ehdr; Elf_Phdr phdr; Elf_Off phoff; unsigned int phnum; int rc; - /* Image type must already have been set by caller */ - assert ( image->type != NULL ); - /* Read ELF header */ copy_from_user ( &ehdr, image->data, 0, sizeof ( ehdr ) ); if ( memcmp ( &ehdr.e_ident[EI_MAG0], ELFMAG, SELFMAG ) != 0 ) { @@ -135,8 +134,8 @@ int elf_load ( struct image *image ) { return -ENOEXEC; } - /* Invalidate execution address */ - image->priv.phys = 0; + /* Invalidate entry point */ + *entry = 0; /* Read ELF program headers */ for ( phoff = ehdr.e_phoff , phnum = ehdr.e_phnum ; phnum ; @@ -147,12 +146,14 @@ int elf_load ( struct image *image ) { return -ENOEXEC; } copy_from_user ( &phdr, image->data, phoff, sizeof ( phdr ) ); - if ( ( rc = elf_load_segment ( image, &phdr, &ehdr ) ) != 0 ) + if ( ( rc = elf_load_segment ( image, &phdr, &ehdr, + entry ) ) != 0 ) { return rc; + } } /* Check for a valid execution address */ - if ( ! image->priv.phys ) { + if ( ! *entry ) { DBGC ( image, "ELF %p entry point %lx outside image\n", image, ( ( unsigned long ) ehdr.e_entry ) ); return -ENOEXEC; |