These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / ipxe / src / arch / i386 / image / elfboot.c
1 /*
2  * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26 #include <errno.h>
27 #include <elf.h>
28 #include <ipxe/image.h>
29 #include <ipxe/elf.h>
30 #include <ipxe/features.h>
31 #include <ipxe/init.h>
32
33 /**
34  * @file
35  *
36  * ELF bootable image
37  *
38  */
39
40 FEATURE ( FEATURE_IMAGE, "ELF", DHCP_EB_FEATURE_ELF, 1 );
41
42 /**
43  * Execute ELF image
44  *
45  * @v image             ELF image
46  * @ret rc              Return status code
47  */
48 static int elfboot_exec ( struct image *image ) {
49         physaddr_t entry;
50         physaddr_t max;
51         int rc;
52
53         /* Load the image using core ELF support */
54         if ( ( rc = elf_load ( image, &entry, &max ) ) != 0 ) {
55                 DBGC ( image, "ELF %p could not load: %s\n",
56                        image, strerror ( rc ) );
57                 return rc;
58         }
59
60         /* An ELF image has no callback interface, so we need to shut
61          * down before invoking it.
62          */
63         shutdown_boot();
64
65         /* Jump to OS with flat physical addressing */
66         DBGC ( image, "ELF %p starting execution at %lx\n", image, entry );
67         __asm__ __volatile__ ( PHYS_CODE ( "pushl %%ebp\n\t" /* gcc bug */
68                                            "call *%%edi\n\t"
69                                            "popl %%ebp\n\t" /* gcc bug */ )
70                                : : "D" ( entry )
71                                : "eax", "ebx", "ecx", "edx", "esi", "memory" );
72
73         DBGC ( image, "ELF %p returned\n", image );
74
75         /* It isn't safe to continue after calling shutdown() */
76         while ( 1 ) {}
77
78         return -ECANCELED;  /* -EIMPOSSIBLE, anyone? */
79 }
80
81 /**
82  * Check that ELF segment uses flat physical addressing
83  *
84  * @v image             ELF file
85  * @v phdr              ELF program header
86  * @v dest              Destination address
87  * @ret rc              Return status code
88  */
89 static int elfboot_check_segment ( struct image *image, Elf_Phdr *phdr,
90                                    physaddr_t dest ) {
91
92         /* Check that ELF segment uses flat physical addressing */
93         if ( phdr->p_vaddr != dest ) {
94                 DBGC ( image, "ELF %p uses virtual addressing (phys %x, "
95                        "virt %x)\n", image, phdr->p_paddr, phdr->p_vaddr );
96                 return -ENOEXEC;
97         }
98
99         return 0;
100 }
101
102 /**
103  * Probe ELF image
104  *
105  * @v image             ELF file
106  * @ret rc              Return status code
107  */
108 static int elfboot_probe ( struct image *image ) {
109         Elf32_Ehdr ehdr;
110         static const uint8_t e_ident[] = {
111                 [EI_MAG0]       = ELFMAG0,
112                 [EI_MAG1]       = ELFMAG1,
113                 [EI_MAG2]       = ELFMAG2,
114                 [EI_MAG3]       = ELFMAG3,
115                 [EI_CLASS]      = ELFCLASS32,
116                 [EI_DATA]       = ELFDATA2LSB,
117                 [EI_VERSION]    = EV_CURRENT,
118         };
119         physaddr_t entry;
120         physaddr_t max;
121         int rc;
122
123         /* Read ELF header */
124         copy_from_user ( &ehdr, image->data, 0, sizeof ( ehdr ) );
125         if ( memcmp ( ehdr.e_ident, e_ident, sizeof ( e_ident ) ) != 0 ) {
126                 DBGC ( image, "Invalid ELF identifier\n" );
127                 return -ENOEXEC;
128         }
129
130         /* Check that this image uses flat physical addressing */
131         if ( ( rc = elf_segments ( image, &ehdr, elfboot_check_segment,
132                                    &entry, &max ) ) != 0 ) {
133                 DBGC ( image, "Unloadable ELF image\n" );
134                 return rc;
135         }
136
137         return 0;
138 }
139
140 /** ELF image type */
141 struct image_type elfboot_image_type __image_type ( PROBE_NORMAL ) = {
142         .name = "ELF",
143         .probe = elfboot_probe,
144         .exec = elfboot_exec,
145 };