]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BasePeCoffLib/Ipf/PeCoffLoaderEx.c
Add in the 1st version of ECP.
[mirror_edk2.git] / EdkCompatibilityPkg / Foundation / Library / EdkIIGlueLib / Library / BasePeCoffLib / Ipf / PeCoffLoaderEx.c
1 /*++
2
3 Copyright (c) 2004 - 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12
13 Module Name:
14
15 PeCoffLoaderEx.c
16
17 Abstract:
18
19 IA-32 Specific relocation fixups.
20
21 --*/
22
23 #include "BasePeCoffLibInternals.h"
24
25 #define EFI_IMAGE_MACHINE_IPF EFI_IMAGE_MACHINE_IA64
26
27 #define EXT_IMM64(Value, Address, Size, InstPos, ValPos) \
28 Value |= (((UINT64)((*(Address) >> InstPos) & (((UINT64)1 << Size) - 1))) << ValPos)
29
30 #define INS_IMM64(Value, Address, Size, InstPos, ValPos) \
31 *(UINT32*)Address = (*(UINT32*)Address & ~(((1 << Size) - 1) << InstPos)) | \
32 ((UINT32)((((UINT64)Value >> ValPos) & (((UINT64)1 << Size) - 1))) << InstPos)
33
34 #define IMM64_IMM7B_INST_WORD_X 3
35 #define IMM64_IMM7B_SIZE_X 7
36 #define IMM64_IMM7B_INST_WORD_POS_X 4
37 #define IMM64_IMM7B_VAL_POS_X 0
38
39 #define IMM64_IMM9D_INST_WORD_X 3
40 #define IMM64_IMM9D_SIZE_X 9
41 #define IMM64_IMM9D_INST_WORD_POS_X 18
42 #define IMM64_IMM9D_VAL_POS_X 7
43
44 #define IMM64_IMM5C_INST_WORD_X 3
45 #define IMM64_IMM5C_SIZE_X 5
46 #define IMM64_IMM5C_INST_WORD_POS_X 13
47 #define IMM64_IMM5C_VAL_POS_X 16
48
49 #define IMM64_IC_INST_WORD_X 3
50 #define IMM64_IC_SIZE_X 1
51 #define IMM64_IC_INST_WORD_POS_X 12
52 #define IMM64_IC_VAL_POS_X 21
53
54 #define IMM64_IMM41a_INST_WORD_X 1
55 #define IMM64_IMM41a_SIZE_X 10
56 #define IMM64_IMM41a_INST_WORD_POS_X 14
57 #define IMM64_IMM41a_VAL_POS_X 22
58
59 #define IMM64_IMM41b_INST_WORD_X 1
60 #define IMM64_IMM41b_SIZE_X 8
61 #define IMM64_IMM41b_INST_WORD_POS_X 24
62 #define IMM64_IMM41b_VAL_POS_X 32
63
64 #define IMM64_IMM41c_INST_WORD_X 2
65 #define IMM64_IMM41c_SIZE_X 23
66 #define IMM64_IMM41c_INST_WORD_POS_X 0
67 #define IMM64_IMM41c_VAL_POS_X 40
68
69 #define IMM64_SIGN_INST_WORD_X 3
70 #define IMM64_SIGN_SIZE_X 1
71 #define IMM64_SIGN_INST_WORD_POS_X 27
72 #define IMM64_SIGN_VAL_POS_X 63
73
74 /**
75 Performs an Itanium-based specific relocation fixup.
76
77 @param Reloc Pointer to the relocation record.
78 @param Fixup Pointer to the address to fix up.
79 @param FixupData Pointer to a buffer to log the fixups.
80 @param Adjust The offset to adjust the fixup.
81
82 @return Status code.
83
84 **/
85 RETURN_STATUS
86 GluePeCoffLoaderRelocateImageEx (
87 IN UINT16 *Reloc,
88 IN OUT CHAR8 *Fixup,
89 IN OUT CHAR8 **FixupData,
90 IN UINT64 Adjust
91 )
92 {
93 UINT64 *F64;
94 UINT64 FixupVal;
95
96 switch ((*Reloc) >> 12) {
97 case EFI_IMAGE_REL_BASED_IA64_IMM64:
98
99 //
100 // Align it to bundle address before fixing up the
101 // 64-bit immediate value of the movl instruction.
102 //
103
104 Fixup = (CHAR8 *)((UINTN) Fixup & (UINTN) ~(15));
105 FixupVal = (UINT64)0;
106
107 //
108 // Extract the lower 32 bits of IMM64 from bundle
109 //
110 EXT_IMM64(FixupVal,
111 (UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X,
112 IMM64_IMM7B_SIZE_X,
113 IMM64_IMM7B_INST_WORD_POS_X,
114 IMM64_IMM7B_VAL_POS_X
115 );
116
117 EXT_IMM64(FixupVal,
118 (UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X,
119 IMM64_IMM9D_SIZE_X,
120 IMM64_IMM9D_INST_WORD_POS_X,
121 IMM64_IMM9D_VAL_POS_X
122 );
123
124 EXT_IMM64(FixupVal,
125 (UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X,
126 IMM64_IMM5C_SIZE_X,
127 IMM64_IMM5C_INST_WORD_POS_X,
128 IMM64_IMM5C_VAL_POS_X
129 );
130
131 EXT_IMM64(FixupVal,
132 (UINT32 *)Fixup + IMM64_IC_INST_WORD_X,
133 IMM64_IC_SIZE_X,
134 IMM64_IC_INST_WORD_POS_X,
135 IMM64_IC_VAL_POS_X
136 );
137
138 EXT_IMM64(FixupVal,
139 (UINT32 *)Fixup + IMM64_IMM41a_INST_WORD_X,
140 IMM64_IMM41a_SIZE_X,
141 IMM64_IMM41a_INST_WORD_POS_X,
142 IMM64_IMM41a_VAL_POS_X
143 );
144
145 //
146 // Update 64-bit address
147 //
148 FixupVal += Adjust;
149
150 //
151 // Insert IMM64 into bundle
152 //
153 INS_IMM64(FixupVal,
154 ((UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X),
155 IMM64_IMM7B_SIZE_X,
156 IMM64_IMM7B_INST_WORD_POS_X,
157 IMM64_IMM7B_VAL_POS_X
158 );
159
160 INS_IMM64(FixupVal,
161 ((UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X),
162 IMM64_IMM9D_SIZE_X,
163 IMM64_IMM9D_INST_WORD_POS_X,
164 IMM64_IMM9D_VAL_POS_X
165 );
166
167 INS_IMM64(FixupVal,
168 ((UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X),
169 IMM64_IMM5C_SIZE_X,
170 IMM64_IMM5C_INST_WORD_POS_X,
171 IMM64_IMM5C_VAL_POS_X
172 );
173
174 INS_IMM64(FixupVal,
175 ((UINT32 *)Fixup + IMM64_IC_INST_WORD_X),
176 IMM64_IC_SIZE_X,
177 IMM64_IC_INST_WORD_POS_X,
178 IMM64_IC_VAL_POS_X
179 );
180
181 INS_IMM64(FixupVal,
182 ((UINT32 *)Fixup + IMM64_IMM41a_INST_WORD_X),
183 IMM64_IMM41a_SIZE_X,
184 IMM64_IMM41a_INST_WORD_POS_X,
185 IMM64_IMM41a_VAL_POS_X
186 );
187
188 INS_IMM64(FixupVal,
189 ((UINT32 *)Fixup + IMM64_IMM41b_INST_WORD_X),
190 IMM64_IMM41b_SIZE_X,
191 IMM64_IMM41b_INST_WORD_POS_X,
192 IMM64_IMM41b_VAL_POS_X
193 );
194
195 INS_IMM64(FixupVal,
196 ((UINT32 *)Fixup + IMM64_IMM41c_INST_WORD_X),
197 IMM64_IMM41c_SIZE_X,
198 IMM64_IMM41c_INST_WORD_POS_X,
199 IMM64_IMM41c_VAL_POS_X
200 );
201
202 INS_IMM64(FixupVal,
203 ((UINT32 *)Fixup + IMM64_SIGN_INST_WORD_X),
204 IMM64_SIGN_SIZE_X,
205 IMM64_SIGN_INST_WORD_POS_X,
206 IMM64_SIGN_VAL_POS_X
207 );
208
209 F64 = (UINT64 *) Fixup;
210 if (*FixupData != NULL) {
211 *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64));
212 *(UINT64 *)(*FixupData) = *F64;
213 *FixupData = *FixupData + sizeof(UINT64);
214 }
215 break;
216
217 default:
218 return RETURN_UNSUPPORTED;
219 }
220
221 return RETURN_SUCCESS;
222 }
223
224 /**
225 Returns TRUE if the machine type of PE/COFF image is supported. Supported
226 does not mean the image can be executed it means the PE/COFF loader supports
227 loading and relocating of the image type. It's up to the caller to support
228 the entry point.
229
230 This function implies the basic PE/COFF loader/relocator supports IA32, EBC,
231 & X64 images. Calling the entry point in a correct mannor is up to the
232 consumer of this library. This version also supports the special relocations
233 for Itanium.
234
235 @param Machine Machine type from the PE Header.
236
237 @return TRUE if this PE/COFF loader can load the image
238
239 **/
240 BOOLEAN
241 PeCoffLoaderImageFormatSupported (
242 IN UINT16 Machine
243 )
244 {
245 if ((Machine == EFI_IMAGE_MACHINE_IPF) || (Machine == EFI_IMAGE_MACHINE_IA32) ||
246 (Machine == EFI_IMAGE_MACHINE_EBC) || (Machine == EFI_IMAGE_MACHINE_X64)) {
247 return TRUE;
248 }
249
250 return FALSE;
251 }
252
253
254 /**
255 ImageRead function that operates on a memory buffer whos base is passed into
256 FileHandle.
257
258 @param Reloc Ponter to baes of the input stream
259 @param Fixup Offset to the start of the buffer
260 @param FixupData Number of bytes to copy into the buffer
261 @param Adjust Location to place results of read
262
263 @retval RETURN_SUCCESS Data is read from FileOffset from the Handle into
264 the buffer.
265 **/
266 RETURN_STATUS
267 GluePeHotRelocateImageEx (
268 IN UINT16 *Reloc,
269 IN OUT CHAR8 *Fixup,
270 IN OUT CHAR8 **FixupData,
271 IN UINT64 Adjust
272 )
273 {
274 UINT64 *F64;
275 UINT64 FixupVal;
276
277 switch ((*Reloc) >> 12) {
278 case EFI_IMAGE_REL_BASED_DIR64:
279 F64 = (UINT64 *) Fixup;
280 *FixupData = ALIGN_POINTER (*FixupData, sizeof (UINT64));
281 if (*(UINT64 *) (*FixupData) == *F64) {
282 *F64 = *F64 + (UINT64) Adjust;
283 }
284
285 *FixupData = *FixupData + sizeof (UINT64);
286 break;
287
288 case EFI_IMAGE_REL_BASED_IA64_IMM64:
289 F64 = (UINT64 *) Fixup;
290 *FixupData = ALIGN_POINTER (*FixupData, sizeof (UINT64));
291 if (*(UINT64 *) (*FixupData) == *F64) {
292 //
293 // Align it to bundle address before fixing up the
294 // 64-bit immediate value of the movl instruction.
295 //
296 //
297 Fixup = (CHAR8 *) ((UINT64) Fixup & (UINT64)~(15));
298 FixupVal = (UINT64) 0;
299
300 //
301 // Extract the lower 32 bits of IMM64 from bundle
302 //
303 EXT_IMM64 (
304 FixupVal,
305 (UINT32 *) Fixup + IMM64_IMM7B_INST_WORD_X,
306 IMM64_IMM7B_SIZE_X,
307 IMM64_IMM7B_INST_WORD_POS_X,
308 IMM64_IMM7B_VAL_POS_X
309 );
310
311 EXT_IMM64 (
312 FixupVal,
313 (UINT32 *) Fixup + IMM64_IMM9D_INST_WORD_X,
314 IMM64_IMM9D_SIZE_X,
315 IMM64_IMM9D_INST_WORD_POS_X,
316 IMM64_IMM9D_VAL_POS_X
317 );
318
319 EXT_IMM64 (
320 FixupVal,
321 (UINT32 *) Fixup + IMM64_IMM5C_INST_WORD_X,
322 IMM64_IMM5C_SIZE_X,
323 IMM64_IMM5C_INST_WORD_POS_X,
324 IMM64_IMM5C_VAL_POS_X
325 );
326
327 EXT_IMM64 (
328 FixupVal,
329 (UINT32 *) Fixup + IMM64_IC_INST_WORD_X,
330 IMM64_IC_SIZE_X,
331 IMM64_IC_INST_WORD_POS_X,
332 IMM64_IC_VAL_POS_X
333 );
334
335 EXT_IMM64 (
336 FixupVal,
337 (UINT32 *) Fixup + IMM64_IMM41a_INST_WORD_X,
338 IMM64_IMM41a_SIZE_X,
339 IMM64_IMM41a_INST_WORD_POS_X,
340 IMM64_IMM41a_VAL_POS_X
341 );
342
343 //
344 // Update 64-bit address
345 //
346 FixupVal += Adjust;
347
348 //
349 // Insert IMM64 into bundle
350 //
351 INS_IMM64 (
352 FixupVal,
353 ((UINT32 *) Fixup + IMM64_IMM7B_INST_WORD_X),
354 IMM64_IMM7B_SIZE_X,
355 IMM64_IMM7B_INST_WORD_POS_X,
356 IMM64_IMM7B_VAL_POS_X
357 );
358
359 INS_IMM64 (
360 FixupVal,
361 ((UINT32 *) Fixup + IMM64_IMM9D_INST_WORD_X),
362 IMM64_IMM9D_SIZE_X,
363 IMM64_IMM9D_INST_WORD_POS_X,
364 IMM64_IMM9D_VAL_POS_X
365 );
366
367 INS_IMM64 (
368 FixupVal,
369 ((UINT32 *) Fixup + IMM64_IMM5C_INST_WORD_X),
370 IMM64_IMM5C_SIZE_X,
371 IMM64_IMM5C_INST_WORD_POS_X,
372 IMM64_IMM5C_VAL_POS_X
373 );
374
375 INS_IMM64 (
376 FixupVal,
377 ((UINT32 *) Fixup + IMM64_IC_INST_WORD_X),
378 IMM64_IC_SIZE_X,
379 IMM64_IC_INST_WORD_POS_X,
380 IMM64_IC_VAL_POS_X
381 );
382
383 INS_IMM64 (
384 FixupVal,
385 ((UINT32 *) Fixup + IMM64_IMM41a_INST_WORD_X),
386 IMM64_IMM41a_SIZE_X,
387 IMM64_IMM41a_INST_WORD_POS_X,
388 IMM64_IMM41a_VAL_POS_X
389 );
390
391 INS_IMM64 (
392 FixupVal,
393 ((UINT32 *) Fixup + IMM64_IMM41b_INST_WORD_X),
394 IMM64_IMM41b_SIZE_X,
395 IMM64_IMM41b_INST_WORD_POS_X,
396 IMM64_IMM41b_VAL_POS_X
397 );
398
399 INS_IMM64 (
400 FixupVal,
401 ((UINT32 *) Fixup + IMM64_IMM41c_INST_WORD_X),
402 IMM64_IMM41c_SIZE_X,
403 IMM64_IMM41c_INST_WORD_POS_X,
404 IMM64_IMM41c_VAL_POS_X
405 );
406
407 INS_IMM64 (
408 FixupVal,
409 ((UINT32 *) Fixup + IMM64_SIGN_INST_WORD_X),
410 IMM64_SIGN_SIZE_X,
411 IMM64_SIGN_INST_WORD_POS_X,
412 IMM64_SIGN_VAL_POS_X
413 );
414
415 *(UINT64 *) (*FixupData) = *F64;
416 }
417
418 *FixupData = *FixupData + sizeof (UINT64);
419 break;
420
421 default:
422 DEBUG ((EFI_D_ERROR, "PeHotRelocateEx:unknown fixed type\n"));
423 return RETURN_UNSUPPORTED;
424 }
425
426 return RETURN_SUCCESS;
427 }
428
429
430