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