When an async operation dies, orphan its children.
[people/xl0/gpxe.git] / src / image / elf.c
index d69a3e3..75c976e 100644 (file)
@@ -30,6 +30,8 @@
 #include <gpxe/image.h>
 #include <gpxe/elf.h>
 
+struct image_type elf_image_type __image_type ( PROBE_NORMAL );
+
 typedef Elf32_Ehdr     Elf_Ehdr;
 typedef Elf32_Phdr     Elf_Phdr;
 typedef Elf32_Off      Elf_Off;
@@ -40,7 +42,7 @@ typedef Elf32_Off     Elf_Off;
  * @v image            ELF file
  * @ret rc             Return status code
  */
-static int elf_execute ( struct image *image __unused ) {
+static int elf_exec ( struct image *image __unused ) {
        return -ENOTSUP;
 }
 
@@ -63,7 +65,7 @@ static int elf_load_segment ( struct image *image, Elf_Phdr *phdr ) {
        /* Check segment lies within image */
        if ( ( phdr->p_offset + phdr->p_filesz ) > image->len ) {
                DBG ( "ELF segment outside ELF file\n" );
-               return -ERANGE;
+               return -ENOEXEC;
        }
 
        /* Find start address: use physical address for preference,
@@ -75,7 +77,7 @@ static int elf_load_segment ( struct image *image, Elf_Phdr *phdr ) {
                dest = phdr->p_vaddr;
        if ( ! dest ) {
                DBG ( "ELF segment loads to physical address 0\n" );
-               return -ERANGE;
+               return -ENOEXEC;
        }
        buffer = phys_to_user ( dest );
 
@@ -92,7 +94,7 @@ static int elf_load_segment ( struct image *image, Elf_Phdr *phdr ) {
        }
 
        /* Copy image to segment */
-       copy_user ( buffer, 0, image->data, phdr->p_offset, phdr->p_filesz );
+       memcpy_user ( buffer, 0, image->data, phdr->p_offset, phdr->p_filesz );
 
        return 0;
 }
@@ -117,28 +119,32 @@ int elf_load ( struct image *image ) {
                return -ENOEXEC;
        }
 
+       /* This is an ELF image, valid or otherwise */
+       if ( ! image->type )
+               image->type = &elf_image_type;
+
        /* Read ELF program headers */
        for ( phoff = ehdr.e_phoff , phnum = ehdr.e_phnum ; phnum ;
              phoff += ehdr.e_phentsize, phnum-- ) {
                if ( phoff > image->len ) {
                        DBG ( "ELF program header %d outside ELF image\n",
                              phnum );
-                       return -ERANGE;
+                       return -ENOEXEC;
                }
                copy_from_user ( &phdr, image->data, phoff, sizeof ( phdr ) );
                if ( ( rc = elf_load_segment ( image, &phdr ) ) != 0 )
                        return rc;
        }
 
-       /* Fill in entry point address */
-       image->entry = ehdr.e_entry;
-       image->execute = elf_execute;
+       /* Record execution entry point in image private data field */
+       image->priv.phys = ehdr.e_entry;
 
        return 0;
 }
 
 /** ELF image type */
-struct image_type elf_image_type __image_type = {
+struct image_type elf_image_type __image_type ( PROBE_NORMAL ) = {
        .name = "ELF",
        .load = elf_load,
+       .exec = elf_exec,
 };