@@ -133,7 +133,7 @@ typedef struct {
133
133
struct {
134
134
std_coff_t std ;
135
135
win_t win ;
136
- struct {
136
+ struct data_directory {
137
137
UINT32 address ;
138
138
UINT32 size ;
139
139
} data_directory [16 ];
@@ -153,6 +153,30 @@ typedef struct {
153
153
UINT32 characteristics ;
154
154
} section_header_t ;
155
155
156
+ typedef struct {
157
+ UINT32 virtual_address ;
158
+ UINT32 size_of_block ;
159
+ } relocation_t ;
160
+
161
+ typedef enum {
162
+ ABSOLUTE ,
163
+ HIGH ,
164
+ LOW ,
165
+ HIGHLOW ,
166
+ HIGHADJ ,
167
+ MACHINE_SPECIFIC_5 ,
168
+ RESERVED ,
169
+ MACHINE_SPECIFIC_7 ,
170
+ MACHINE_SPECIFIC_8 ,
171
+ MACHINE_SPECIFIC_9 ,
172
+ DIR64
173
+ } fixup_type_t ;
174
+
175
+ typedef struct {
176
+ UINT16 offset : 12 ;
177
+ UINT8 type : 4 ;
178
+ } fixup_t ;
179
+
156
180
#pragma pack()
157
181
158
182
typedef struct {
@@ -181,7 +205,7 @@ static void get_section_boundaries(section_header_t *section, UINT16 nb,
181
205
182
206
static EFI_STATUS load_sections (section_header_t * section , UINT16 nb ,
183
207
void * base , image_t * image ,
184
- size_t alignment )
208
+ size_t alignment , loaded_section_t * * data_p )
185
209
{
186
210
loaded_section_t * data ;
187
211
UINT16 i ;
@@ -229,15 +253,41 @@ static EFI_STATUS load_sections(section_header_t *section, UINT16 nb,
229
253
ewdbg (".text section loaded at %p" , dst );
230
254
}
231
255
256
+ * data_p = data ;
232
257
return EFI_SUCCESS ;
233
258
}
234
259
260
+ static void relocate (loaded_section_t * data , UINT32 base , relocation_t * table ,
261
+ UINT32 size )
262
+ {
263
+ relocation_t * table_end = (relocation_t * )((UINT8 * )table + size );
264
+ unsigned long diff = (unsigned long )data -> addr - base - data -> start ;
265
+
266
+ while (table < table_end ) {
267
+ fixup_t * fixup = (fixup_t * )& table [1 ];
268
+ fixup_t * fixup_end = (fixup_t * )((char * )table + table -> size_of_block );
269
+ unsigned char * mem = (unsigned char * )data -> addr +
270
+ table -> virtual_address - data -> start ;
271
+
272
+ for (; fixup < fixup_end ; fixup ++ ) {
273
+ if (* (UINT16 * )fixup == 0 )
274
+ break ;
275
+ if (fixup -> type != HIGHLOW )
276
+ continue ;
277
+ * (UINT32 * )& mem [fixup -> offset ] += diff ;
278
+ }
279
+ table = (relocation_t * )fixup_end ;
280
+ }
281
+ }
282
+
235
283
EFI_STATUS pe_load (void * data , UINTN size , image_t * image )
236
284
{
237
285
EFI_STATUS ret ;
238
286
dos_header_t * dos_hdr ;
239
287
pe_coff_t * pe ;
240
288
char * entry ;
289
+ loaded_section_t * section ;
290
+ struct data_directory * reloc_dir ;
241
291
242
292
if (!data || !size || !image )
243
293
return EFI_INVALID_PARAMETER ;
@@ -261,10 +311,16 @@ EFI_STATUS pe_load(void *data, UINTN size, image_t *image)
261
311
262
312
ret = load_sections ((section_header_t * )(pe + 1 ),
263
313
pe -> hdr .number_of_sections ,
264
- data , image , pe -> opt .win .section_alignment );
314
+ data , image , pe -> opt .win .section_alignment ,
315
+ & section );
265
316
if (EFI_ERROR (ret ))
266
317
return ret ;
267
318
319
+ reloc_dir = & pe -> opt .data_directory [BASERELOC_DIRECTORY_ENTRY ];
320
+ relocate ((loaded_section_t * )image -> data , pe -> opt .win .image_base ,
321
+ section -> addr + reloc_dir -> address - section -> start ,
322
+ reloc_dir -> size );
323
+
268
324
entry = (char * )((loaded_section_t * )image -> data )-> addr ;
269
325
entry += pe -> opt .std .address_of_entry_point ;
270
326
entry -= ((loaded_section_t * )image -> data )-> start ;
0 commit comments