@@ -40,27 +40,54 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
40
40
#include <ipxe/image.h>
41
41
#include <ipxe/elf.h>
42
42
43
- typedef Elf32_Ehdr Elf_Ehdr ;
44
- typedef Elf32_Phdr Elf_Phdr ;
45
- typedef Elf32_Off Elf_Off ;
46
- #define ELFCLASS ELFCLASS32
47
-
48
43
/**
49
44
* Load ELF segment into memory
50
45
*
51
46
* @v image ELF file
52
47
* @v phdr ELF program header
48
+ * @v dest Destination address
49
+ * @ret rc Return status code
50
+ */
51
+ static int elf_load_segment ( struct image * image , Elf_Phdr * phdr ,
52
+ physaddr_t dest ) {
53
+ userptr_t buffer = phys_to_user ( dest );
54
+ int rc ;
55
+
56
+ DBGC ( image , "ELF %p loading segment [%x,%x) to [%lx,%lx,%lx)\n" ,
57
+ image , phdr -> p_offset , ( phdr -> p_offset + phdr -> p_filesz ),
58
+ dest , ( dest + phdr -> p_filesz ), ( dest + phdr -> p_memsz ) );
59
+
60
+ /* Verify and prepare segment */
61
+ if ( ( rc = prep_segment ( buffer , phdr -> p_filesz ,
62
+ phdr -> p_memsz ) ) != 0 ) {
63
+ DBGC ( image , "ELF %p could not prepare segment: %s\n" ,
64
+ image , strerror ( rc ) );
65
+ return rc ;
66
+ }
67
+
68
+ /* Copy image to segment */
69
+ memcpy_user ( buffer , 0 , image -> data , phdr -> p_offset , phdr -> p_filesz );
70
+
71
+ return 0 ;
72
+ }
73
+
74
+ /**
75
+ * Process ELF segment
76
+ *
77
+ * @v image ELF file
53
78
* @v ehdr ELF executable header
79
+ * @v phdr ELF program header
80
+ * @v process Segment processor
54
81
* @ret entry Entry point, if found
55
82
* @ret max Maximum used address
56
83
* @ret rc Return status code
57
84
*/
58
- static int elf_load_segment ( struct image * image , Elf_Phdr * phdr ,
59
- Elf_Ehdr * ehdr , physaddr_t * entry ,
60
- physaddr_t * max ) {
85
+ static int elf_segment ( struct image * image , Elf_Ehdr * ehdr , Elf_Phdr * phdr ,
86
+ int ( * process ) ( struct image * image ,
87
+ Elf_Phdr * phdr , physaddr_t dest ),
88
+ physaddr_t * entry , physaddr_t * max ) {
61
89
physaddr_t dest ;
62
90
physaddr_t end ;
63
- userptr_t buffer ;
64
91
unsigned long e_offset ;
65
92
int rc ;
66
93
@@ -86,28 +113,15 @@ static int elf_load_segment ( struct image *image, Elf_Phdr *phdr,
86
113
image );
87
114
return - ENOEXEC ;
88
115
}
89
- buffer = phys_to_user ( dest );
90
116
end = ( dest + phdr -> p_memsz );
91
117
92
- DBGC ( image , "ELF %p loading segment [%x,%x) to [%x,%x,%x)\n" , image ,
93
- phdr -> p_offset , ( phdr -> p_offset + phdr -> p_filesz ),
94
- phdr -> p_paddr , ( phdr -> p_paddr + phdr -> p_filesz ),
95
- ( phdr -> p_paddr + phdr -> p_memsz ) );
96
-
97
- /* Verify and prepare segment */
98
- if ( ( rc = prep_segment ( buffer , phdr -> p_filesz ,
99
- phdr -> p_memsz ) ) != 0 ) {
100
- DBGC ( image , "ELF %p could not prepare segment: %s\n" ,
101
- image , strerror ( rc ) );
102
- return rc ;
103
- }
104
-
105
118
/* Update maximum used address, if applicable */
106
119
if ( end > * max )
107
120
* max = end ;
108
121
109
- /* Copy image to segment */
110
- memcpy_user ( buffer , 0 , image -> data , phdr -> p_offset , phdr -> p_filesz );
122
+ /* Process segment */
123
+ if ( ( rc = process ( image , phdr , dest ) ) != 0 )
124
+ return rc ;
111
125
112
126
/* Set execution address, if it lies within this segment */
113
127
if ( ( e_offset = ( ehdr -> e_entry - dest ) ) < phdr -> p_filesz ) {
@@ -128,62 +142,85 @@ static int elf_load_segment ( struct image *image, Elf_Phdr *phdr,
128
142
}
129
143
130
144
/**
131
- * Load ELF image into memory
145
+ * Process ELF segments
132
146
*
133
147
* @v image ELF file
134
- * @ret entry Entry point
148
+ * @v ehdr ELF executable header
149
+ * @v process Segment processor
150
+ * @ret entry Entry point, if found
135
151
* @ret max Maximum used address
136
152
* @ret rc Return status code
137
153
*/
138
- int elf_load ( struct image * image , physaddr_t * entry , physaddr_t * max ) {
139
- static const uint8_t e_ident [] = {
140
- [EI_MAG0 ] = ELFMAG0 ,
141
- [EI_MAG1 ] = ELFMAG1 ,
142
- [EI_MAG2 ] = ELFMAG2 ,
143
- [EI_MAG3 ] = ELFMAG3 ,
144
- [EI_CLASS ] = ELFCLASS ,
145
- };
146
- Elf_Ehdr ehdr ;
154
+ int elf_segments ( struct image * image , Elf_Ehdr * ehdr ,
155
+ int ( * process ) ( struct image * image , Elf_Phdr * phdr ,
156
+ physaddr_t dest ),
157
+ physaddr_t * entry , physaddr_t * max ) {
147
158
Elf_Phdr phdr ;
148
159
Elf_Off phoff ;
149
160
unsigned int phnum ;
150
161
int rc ;
151
162
152
- /* Read ELF header */
153
- copy_from_user ( & ehdr , image -> data , 0 , sizeof ( ehdr ) );
154
- if ( memcmp ( & ehdr .e_ident [EI_MAG0 ], e_ident ,
155
- sizeof ( e_ident ) ) != 0 ) {
156
- DBGC ( image , "ELF %p has invalid signature\n" , image );
157
- return - ENOEXEC ;
158
- }
159
-
160
163
/* Initialise maximum used address */
161
164
* max = 0 ;
162
165
163
166
/* Invalidate entry point */
164
167
* entry = 0 ;
165
168
166
- /* Read ELF program headers */
167
- for ( phoff = ehdr . e_phoff , phnum = ehdr . e_phnum ; phnum ;
168
- phoff += ehdr . e_phentsize , phnum -- ) {
169
+ /* Read and process ELF program headers */
170
+ for ( phoff = ehdr -> e_phoff , phnum = ehdr -> e_phnum ; phnum ;
171
+ phoff += ehdr -> e_phentsize , phnum -- ) {
169
172
if ( phoff > image -> len ) {
170
173
DBGC ( image , "ELF %p program header %d outside "
171
174
"image\n" , image , phnum );
172
175
return - ENOEXEC ;
173
176
}
174
177
copy_from_user ( & phdr , image -> data , phoff , sizeof ( phdr ) );
175
- if ( ( rc = elf_load_segment ( image , & phdr , & ehdr ,
176
- entry , max ) ) != 0 ) {
178
+ if ( ( rc = elf_segment ( image , ehdr , & phdr , process ,
179
+ entry , max ) ) != 0 )
177
180
return rc ;
178
- }
179
181
}
180
182
181
183
/* Check for a valid execution address */
182
184
if ( ! * entry ) {
183
185
DBGC ( image , "ELF %p entry point %lx outside image\n" ,
184
- image , ( ( unsigned long ) ehdr .e_entry ) );
186
+ image , ( ( unsigned long ) ehdr -> e_entry ) );
187
+ return - ENOEXEC ;
188
+ }
189
+
190
+ return 0 ;
191
+ }
192
+
193
+ /**
194
+ * Load ELF image into memory
195
+ *
196
+ * @v image ELF file
197
+ * @ret entry Entry point
198
+ * @ret max Maximum used address
199
+ * @ret rc Return status code
200
+ */
201
+ int elf_load ( struct image * image , physaddr_t * entry , physaddr_t * max ) {
202
+ static const uint8_t e_ident [] = {
203
+ [EI_MAG0 ] = ELFMAG0 ,
204
+ [EI_MAG1 ] = ELFMAG1 ,
205
+ [EI_MAG2 ] = ELFMAG2 ,
206
+ [EI_MAG3 ] = ELFMAG3 ,
207
+ [EI_CLASS ] = ELFCLASS ,
208
+ };
209
+ Elf_Ehdr ehdr ;
210
+ int rc ;
211
+
212
+ /* Read ELF header */
213
+ copy_from_user ( & ehdr , image -> data , 0 , sizeof ( ehdr ) );
214
+ if ( memcmp ( & ehdr .e_ident [EI_MAG0 ], e_ident ,
215
+ sizeof ( e_ident ) ) != 0 ) {
216
+ DBGC ( image , "ELF %p has invalid signature\n" , image );
185
217
return - ENOEXEC ;
186
218
}
187
219
220
+ /* Load ELF segments into memory */
221
+ if ( ( rc = elf_segments ( image , & ehdr , elf_load_segment ,
222
+ entry , max ) ) != 0 )
223
+ return rc ;
224
+
188
225
return 0 ;
189
226
}
0 commit comments