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