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