]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/Common/PeCoffLoaderEx.c
BaseTools: Clean up source files
[mirror_edk2.git] / BaseTools / Source / C / Common / PeCoffLoaderEx.c
CommitLineData
30fdf114 1/** @file\r
97fa0ee9 2IA32, X64 and IPF Specific relocation fixups\r
30fdf114 3\r
f7496d71 4Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
4afd3d04 5Portions Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>\r
f7496d71
LG
6This program and the accompanying materials\r
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
30fdf114 13\r
30fdf114
LG
14--*/\r
15\r
16#include <Common/UefiBaseTypes.h>\r
17#include <IndustryStandard/PeImage.h>\r
18#include "PeCoffLib.h"\r
da92f276 19#include "CommonLib.h"\r
4afd3d04 20#include "EfiUtilityMsgs.h"\r
da92f276 21\r
30fdf114
LG
22\r
23#define EXT_IMM64(Value, Address, Size, InstPos, ValPos) \\r
24 Value |= (((UINT64)((*(Address) >> InstPos) & (((UINT64)1 << Size) - 1))) << ValPos)\r
25\r
26#define INS_IMM64(Value, Address, Size, InstPos, ValPos) \\r
27 *(UINT32*)Address = (*(UINT32*)Address & ~(((1 << Size) - 1) << InstPos)) | \\r
28 ((UINT32)((((UINT64)Value >> ValPos) & (((UINT64)1 << Size) - 1))) << InstPos)\r
29\r
f7496d71
LG
30#define IMM64_IMM7B_INST_WORD_X 3\r
31#define IMM64_IMM7B_SIZE_X 7\r
32#define IMM64_IMM7B_INST_WORD_POS_X 4\r
33#define IMM64_IMM7B_VAL_POS_X 0\r
34\r
35#define IMM64_IMM9D_INST_WORD_X 3\r
36#define IMM64_IMM9D_SIZE_X 9\r
37#define IMM64_IMM9D_INST_WORD_POS_X 18\r
38#define IMM64_IMM9D_VAL_POS_X 7\r
39\r
40#define IMM64_IMM5C_INST_WORD_X 3\r
41#define IMM64_IMM5C_SIZE_X 5\r
42#define IMM64_IMM5C_INST_WORD_POS_X 13\r
43#define IMM64_IMM5C_VAL_POS_X 16\r
44\r
45#define IMM64_IC_INST_WORD_X 3\r
46#define IMM64_IC_SIZE_X 1\r
47#define IMM64_IC_INST_WORD_POS_X 12\r
48#define IMM64_IC_VAL_POS_X 21\r
49\r
50#define IMM64_IMM41a_INST_WORD_X 1\r
51#define IMM64_IMM41a_SIZE_X 10\r
52#define IMM64_IMM41a_INST_WORD_POS_X 14\r
53#define IMM64_IMM41a_VAL_POS_X 22\r
54\r
55#define IMM64_IMM41b_INST_WORD_X 1\r
56#define IMM64_IMM41b_SIZE_X 8\r
57#define IMM64_IMM41b_INST_WORD_POS_X 24\r
58#define IMM64_IMM41b_VAL_POS_X 32\r
59\r
60#define IMM64_IMM41c_INST_WORD_X 2\r
61#define IMM64_IMM41c_SIZE_X 23\r
62#define IMM64_IMM41c_INST_WORD_POS_X 0\r
63#define IMM64_IMM41c_VAL_POS_X 40\r
64\r
65#define IMM64_SIGN_INST_WORD_X 3\r
66#define IMM64_SIGN_SIZE_X 1\r
67#define IMM64_SIGN_INST_WORD_POS_X 27\r
68#define IMM64_SIGN_VAL_POS_X 63\r
30fdf114
LG
69\r
70RETURN_STATUS\r
71PeCoffLoaderRelocateIa32Image (\r
72 IN UINT16 *Reloc,\r
73 IN OUT CHAR8 *Fixup,\r
74 IN OUT CHAR8 **FixupData,\r
75 IN UINT64 Adjust\r
76 )\r
77/*++\r
78\r
79Routine Description:\r
80\r
81 Performs an IA-32 specific relocation fixup\r
82\r
83Arguments:\r
84\r
85 Reloc - Pointer to the relocation record\r
86\r
87 Fixup - Pointer to the address to fix up\r
88\r
89 FixupData - Pointer to a buffer to log the fixups\r
90\r
91 Adjust - The offset to adjust the fixup\r
92\r
93Returns:\r
94\r
95 EFI_UNSUPPORTED - Unsupported now\r
96\r
97--*/\r
98{\r
99 return RETURN_UNSUPPORTED;\r
100}\r
101\r
102RETURN_STATUS\r
103PeCoffLoaderRelocateIpfImage (\r
104 IN UINT16 *Reloc,\r
f7496d71 105 IN OUT CHAR8 *Fixup,\r
30fdf114
LG
106 IN OUT CHAR8 **FixupData,\r
107 IN UINT64 Adjust\r
108 )\r
109/*++\r
110\r
111Routine Description:\r
112\r
113 Performs an Itanium-based specific relocation fixup\r
114\r
115Arguments:\r
116\r
117 Reloc - Pointer to the relocation record\r
118\r
119 Fixup - Pointer to the address to fix up\r
120\r
121 FixupData - Pointer to a buffer to log the fixups\r
122\r
123 Adjust - The offset to adjust the fixup\r
124\r
125Returns:\r
126\r
127 Status code\r
128\r
129--*/\r
130{\r
131 UINT64 *F64;\r
132 UINT64 FixupVal;\r
133\r
134 switch ((*Reloc) >> 12) {\r
135\r
30fdf114
LG
136 case EFI_IMAGE_REL_BASED_IA64_IMM64:\r
137\r
138 //\r
139 // Align it to bundle address before fixing up the\r
140 // 64-bit immediate value of the movl instruction.\r
141 //\r
142\r
143 Fixup = (CHAR8 *)((UINTN) Fixup & (UINTN) ~(15));\r
144 FixupVal = (UINT64)0;\r
f7496d71
LG
145\r
146 //\r
30fdf114
LG
147 // Extract the lower 32 bits of IMM64 from bundle\r
148 //\r
149 EXT_IMM64(FixupVal,\r
150 (UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X,\r
151 IMM64_IMM7B_SIZE_X,\r
152 IMM64_IMM7B_INST_WORD_POS_X,\r
153 IMM64_IMM7B_VAL_POS_X\r
154 );\r
155\r
156 EXT_IMM64(FixupVal,\r
157 (UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X,\r
158 IMM64_IMM9D_SIZE_X,\r
159 IMM64_IMM9D_INST_WORD_POS_X,\r
160 IMM64_IMM9D_VAL_POS_X\r
161 );\r
162\r
163 EXT_IMM64(FixupVal,\r
164 (UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X,\r
165 IMM64_IMM5C_SIZE_X,\r
166 IMM64_IMM5C_INST_WORD_POS_X,\r
167 IMM64_IMM5C_VAL_POS_X\r
168 );\r
169\r
170 EXT_IMM64(FixupVal,\r
171 (UINT32 *)Fixup + IMM64_IC_INST_WORD_X,\r
172 IMM64_IC_SIZE_X,\r
173 IMM64_IC_INST_WORD_POS_X,\r
174 IMM64_IC_VAL_POS_X\r
175 );\r
176\r
177 EXT_IMM64(FixupVal,\r
178 (UINT32 *)Fixup + IMM64_IMM41a_INST_WORD_X,\r
179 IMM64_IMM41a_SIZE_X,\r
180 IMM64_IMM41a_INST_WORD_POS_X,\r
181 IMM64_IMM41a_VAL_POS_X\r
182 );\r
f7496d71
LG
183\r
184 //\r
30fdf114
LG
185 // Update 64-bit address\r
186 //\r
187 FixupVal += Adjust;\r
188\r
f7496d71 189 //\r
30fdf114
LG
190 // Insert IMM64 into bundle\r
191 //\r
192 INS_IMM64(FixupVal,\r
193 ((UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X),\r
194 IMM64_IMM7B_SIZE_X,\r
195 IMM64_IMM7B_INST_WORD_POS_X,\r
196 IMM64_IMM7B_VAL_POS_X\r
197 );\r
198\r
199 INS_IMM64(FixupVal,\r
200 ((UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X),\r
201 IMM64_IMM9D_SIZE_X,\r
202 IMM64_IMM9D_INST_WORD_POS_X,\r
203 IMM64_IMM9D_VAL_POS_X\r
204 );\r
205\r
206 INS_IMM64(FixupVal,\r
207 ((UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X),\r
208 IMM64_IMM5C_SIZE_X,\r
209 IMM64_IMM5C_INST_WORD_POS_X,\r
210 IMM64_IMM5C_VAL_POS_X\r
211 );\r
212\r
213 INS_IMM64(FixupVal,\r
214 ((UINT32 *)Fixup + IMM64_IC_INST_WORD_X),\r
215 IMM64_IC_SIZE_X,\r
216 IMM64_IC_INST_WORD_POS_X,\r
217 IMM64_IC_VAL_POS_X\r
218 );\r
219\r
220 INS_IMM64(FixupVal,\r
221 ((UINT32 *)Fixup + IMM64_IMM41a_INST_WORD_X),\r
222 IMM64_IMM41a_SIZE_X,\r
223 IMM64_IMM41a_INST_WORD_POS_X,\r
224 IMM64_IMM41a_VAL_POS_X\r
225 );\r
226\r
227 INS_IMM64(FixupVal,\r
228 ((UINT32 *)Fixup + IMM64_IMM41b_INST_WORD_X),\r
229 IMM64_IMM41b_SIZE_X,\r
230 IMM64_IMM41b_INST_WORD_POS_X,\r
231 IMM64_IMM41b_VAL_POS_X\r
232 );\r
233\r
234 INS_IMM64(FixupVal,\r
235 ((UINT32 *)Fixup + IMM64_IMM41c_INST_WORD_X),\r
236 IMM64_IMM41c_SIZE_X,\r
237 IMM64_IMM41c_INST_WORD_POS_X,\r
238 IMM64_IMM41c_VAL_POS_X\r
239 );\r
240\r
241 INS_IMM64(FixupVal,\r
242 ((UINT32 *)Fixup + IMM64_SIGN_INST_WORD_X),\r
243 IMM64_SIGN_SIZE_X,\r
244 IMM64_SIGN_INST_WORD_POS_X,\r
245 IMM64_SIGN_VAL_POS_X\r
246 );\r
247\r
248 F64 = (UINT64 *) Fixup;\r
249 if (*FixupData != NULL) {\r
250 *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64));\r
251 *(UINT64 *)(*FixupData) = *F64;\r
252 *FixupData = *FixupData + sizeof(UINT64);\r
253 }\r
254 break;\r
255\r
256 default:\r
257 return RETURN_UNSUPPORTED;\r
258 }\r
259\r
260 return RETURN_SUCCESS;\r
261}\r
262\r
40d841f6 263/**\r
f7496d71 264 Pass in a pointer to an ARM MOVT or MOVW immediate instruciton and\r
40d841f6
LG
265 return the immediate data encoded in the instruction\r
266\r
267 @param Instruction Pointer to ARM MOVT or MOVW immediate instruction\r
268\r
269 @return Immediate address encoded in the instruction\r
270\r
271**/\r
272UINT16\r
273ThumbMovtImmediateAddress (\r
274 IN UINT16 *Instruction\r
275 )\r
276{\r
277 UINT32 Movt;\r
278 UINT16 Address;\r
279\r
280 // Thumb2 is two 16-bit instructions working together. Not a single 32-bit instruction\r
281 // Example MOVT R0, #0 is 0x0000f2c0 or 0xf2c0 0x0000\r
f7496d71 282 Movt = (*Instruction << 16) | (*(Instruction + 1));\r
40d841f6
LG
283\r
284 // imm16 = imm4:i:imm3:imm8\r
285 // imm4 -> Bit19:Bit16\r
286 // i -> Bit26\r
287 // imm3 -> Bit14:Bit12\r
288 // imm8 -> Bit7:Bit0\r
289 Address = (UINT16)(Movt & 0x000000ff); // imm8\r
290 Address |= (UINT16)((Movt >> 4) & 0x0000f700); // imm4 imm3\r
291 Address |= (((Movt & BIT26) != 0) ? BIT11 : 0); // i\r
292 return Address;\r
293}\r
294\r
295\r
296/**\r
297 Update an ARM MOVT or MOVW immediate instruction immediate data.\r
298\r
299 @param Instruction Pointer to ARM MOVT or MOVW immediate instruction\r
300 @param Address New addres to patch into the instruction\r
301**/\r
302VOID\r
303ThumbMovtImmediatePatch (\r
304 IN OUT UINT16 *Instruction,\r
305 IN UINT16 Address\r
306 )\r
307{\r
308 UINT16 Patch;\r
309\r
310 // First 16-bit chunk of instruciton\r
f7496d71 311 Patch = ((Address >> 12) & 0x000f); // imm4\r
40d841f6
LG
312 Patch |= (((Address & BIT11) != 0) ? BIT10 : 0); // i\r
313 *Instruction = (*Instruction & ~0x040f) | Patch;\r
314\r
315 // Second 16-bit chunk of instruction\r
316 Patch = Address & 0x000000ff; // imm8\r
317 Patch |= ((Address << 4) & 0x00007000); // imm3\r
318 Instruction++;\r
319 *Instruction = (*Instruction & ~0x70ff) | Patch;\r
320}\r
321\r
da92f276 322/**\r
f7496d71 323 Pass in a pointer to an ARM MOVW/MOVT instruciton pair and\r
da92f276
LG
324 return the immediate data encoded in the two` instruction\r
325\r
326 @param Instructions Pointer to ARM MOVW/MOVT insturction pair\r
327\r
328 @return Immediate address encoded in the instructions\r
329\r
330**/\r
331UINT32\r
332EFIAPI\r
333ThumbMovwMovtImmediateAddress (\r
334 IN UINT16 *Instructions\r
335 )\r
336{\r
337 UINT16 *Word;\r
338 UINT16 *Top;\r
f7496d71 339\r
da92f276
LG
340 Word = Instructions; // MOVW\r
341 Top = Word + 2; // MOVT\r
f7496d71 342\r
da92f276
LG
343 return (ThumbMovtImmediateAddress (Top) << 16) + ThumbMovtImmediateAddress (Word);\r
344}\r
345\r
346\r
347/**\r
348 Update an ARM MOVW/MOVT immediate instruction instruction pair.\r
349\r
350 @param Instructions Pointer to ARM MOVW/MOVT instruction pair\r
351 @param Address New addres to patch into the instructions\r
352**/\r
353VOID\r
354EFIAPI\r
355ThumbMovwMovtImmediatePatch (\r
356 IN OUT UINT16 *Instructions,\r
357 IN UINT32 Address\r
358 )\r
359{\r
360 UINT16 *Word;\r
361 UINT16 *Top;\r
f7496d71 362\r
da92f276
LG
363 Word = (UINT16 *)Instructions; // MOVW\r
364 Top = Word + 2; // MOVT\r
365\r
366 ThumbMovtImmediatePatch (Word, (UINT16)(Address & 0xffff));\r
367 ThumbMovtImmediatePatch (Top, (UINT16)(Address >> 16));\r
368}\r
369\r
370\r
40d841f6
LG
371/**\r
372 Performs an ARM-based specific relocation fixup and is a no-op on other\r
373 instruction sets.\r
374\r
375 @param Reloc Pointer to the relocation record.\r
376 @param Fixup Pointer to the address to fix up.\r
377 @param FixupData Pointer to a buffer to log the fixups.\r
378 @param Adjust The offset to adjust the fixup.\r
379\r
380 @return Status code.\r
381\r
382**/\r
383RETURN_STATUS\r
384PeCoffLoaderRelocateArmImage (\r
385 IN UINT16 **Reloc,\r
386 IN OUT CHAR8 *Fixup,\r
387 IN OUT CHAR8 **FixupData,\r
388 IN UINT64 Adjust\r
389 )\r
390{\r
391 UINT16 *Fixup16;\r
da92f276 392 UINT32 FixupVal;\r
40d841f6 393\r
da92f276 394 Fixup16 = (UINT16 *) Fixup;\r
40d841f6
LG
395\r
396 switch ((**Reloc) >> 12) {\r
f7496d71 397\r
da92f276
LG
398 case EFI_IMAGE_REL_BASED_ARM_MOV32T:\r
399 FixupVal = ThumbMovwMovtImmediateAddress (Fixup16) + (UINT32)Adjust;\r
400 ThumbMovwMovtImmediatePatch (Fixup16, FixupVal);\r
f7496d71
LG
401\r
402\r
40d841f6 403 if (*FixupData != NULL) {\r
da92f276 404 *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64));\r
da92f276 405 CopyMem (*FixupData, Fixup16, sizeof (UINT64));\r
94762dde 406 *FixupData = *FixupData + sizeof(UINT64);\r
40d841f6
LG
407 }\r
408 break;\r
f7496d71 409\r
da92f276
LG
410 case EFI_IMAGE_REL_BASED_ARM_MOV32A:\r
411 // break omitted - ARM instruction encoding not implemented\r
40d841f6
LG
412 default:\r
413 return RETURN_UNSUPPORTED;\r
414 }\r
415\r
416 return RETURN_SUCCESS;\r
417}\r