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