]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/Common/PeCoffLoaderEx.c
BaseTools/PeCoffLoaderEx: Remove the unused local variable
[mirror_edk2.git] / BaseTools / Source / C / Common / PeCoffLoaderEx.c
CommitLineData
30fdf114 1/** @file\r
8daa4278 2IA32 and X64 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
ad1db975 6Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>\r
2e351cbe 7SPDX-License-Identifier: BSD-2-Clause-Patent\r
30fdf114 8\r
30fdf114
LG
9--*/\r
10\r
11#include <Common/UefiBaseTypes.h>\r
12#include <IndustryStandard/PeImage.h>\r
13#include "PeCoffLib.h"\r
da92f276 14#include "CommonLib.h"\r
4afd3d04 15#include "EfiUtilityMsgs.h"\r
da92f276 16\r
30fdf114
LG
17\r
18#define EXT_IMM64(Value, Address, Size, InstPos, ValPos) \\r
19 Value |= (((UINT64)((*(Address) >> InstPos) & (((UINT64)1 << Size) - 1))) << ValPos)\r
20\r
21#define INS_IMM64(Value, Address, Size, InstPos, ValPos) \\r
22 *(UINT32*)Address = (*(UINT32*)Address & ~(((1 << Size) - 1) << InstPos)) | \\r
23 ((UINT32)((((UINT64)Value >> ValPos) & (((UINT64)1 << Size) - 1))) << InstPos)\r
24\r
f7496d71
LG
25#define IMM64_IMM7B_INST_WORD_X 3\r
26#define IMM64_IMM7B_SIZE_X 7\r
27#define IMM64_IMM7B_INST_WORD_POS_X 4\r
28#define IMM64_IMM7B_VAL_POS_X 0\r
29\r
30#define IMM64_IMM9D_INST_WORD_X 3\r
31#define IMM64_IMM9D_SIZE_X 9\r
32#define IMM64_IMM9D_INST_WORD_POS_X 18\r
33#define IMM64_IMM9D_VAL_POS_X 7\r
34\r
35#define IMM64_IMM5C_INST_WORD_X 3\r
36#define IMM64_IMM5C_SIZE_X 5\r
37#define IMM64_IMM5C_INST_WORD_POS_X 13\r
38#define IMM64_IMM5C_VAL_POS_X 16\r
39\r
40#define IMM64_IC_INST_WORD_X 3\r
41#define IMM64_IC_SIZE_X 1\r
42#define IMM64_IC_INST_WORD_POS_X 12\r
43#define IMM64_IC_VAL_POS_X 21\r
44\r
45#define IMM64_IMM41a_INST_WORD_X 1\r
46#define IMM64_IMM41a_SIZE_X 10\r
47#define IMM64_IMM41a_INST_WORD_POS_X 14\r
48#define IMM64_IMM41a_VAL_POS_X 22\r
49\r
50#define IMM64_IMM41b_INST_WORD_X 1\r
51#define IMM64_IMM41b_SIZE_X 8\r
52#define IMM64_IMM41b_INST_WORD_POS_X 24\r
53#define IMM64_IMM41b_VAL_POS_X 32\r
54\r
55#define IMM64_IMM41c_INST_WORD_X 2\r
56#define IMM64_IMM41c_SIZE_X 23\r
57#define IMM64_IMM41c_INST_WORD_POS_X 0\r
58#define IMM64_IMM41c_VAL_POS_X 40\r
59\r
60#define IMM64_SIGN_INST_WORD_X 3\r
61#define IMM64_SIGN_SIZE_X 1\r
62#define IMM64_SIGN_INST_WORD_POS_X 27\r
63#define IMM64_SIGN_VAL_POS_X 63\r
30fdf114 64\r
ad1db975
AC
65UINT32 *RiscVHi20Fixup = NULL;\r
66\r
30fdf114
LG
67RETURN_STATUS\r
68PeCoffLoaderRelocateIa32Image (\r
69 IN UINT16 *Reloc,\r
70 IN OUT CHAR8 *Fixup,\r
71 IN OUT CHAR8 **FixupData,\r
72 IN UINT64 Adjust\r
73 )\r
74/*++\r
75\r
76Routine Description:\r
77\r
78 Performs an IA-32 specific relocation fixup\r
79\r
80Arguments:\r
81\r
82 Reloc - Pointer to the relocation record\r
83\r
84 Fixup - Pointer to the address to fix up\r
85\r
86 FixupData - Pointer to a buffer to log the fixups\r
87\r
88 Adjust - The offset to adjust the fixup\r
89\r
90Returns:\r
91\r
92 EFI_UNSUPPORTED - Unsupported now\r
93\r
94--*/\r
95{\r
96 return RETURN_UNSUPPORTED;\r
97}\r
98\r
ad1db975
AC
99/*++\r
100\r
101Routine Description:\r
102\r
103 Performs an RISC-V specific relocation fixup\r
104\r
105Arguments:\r
106\r
107 Reloc - Pointer to the relocation record\r
108\r
109 Fixup - Pointer to the address to fix up\r
110\r
111 FixupData - Pointer to a buffer to log the fixups\r
112\r
113 Adjust - The offset to adjust the fixup\r
114\r
115Returns:\r
116\r
117 Status code\r
118\r
119--*/\r
120RETURN_STATUS\r
121PeCoffLoaderRelocateRiscVImage (\r
122 IN UINT16 *Reloc,\r
123 IN OUT CHAR8 *Fixup,\r
124 IN OUT CHAR8 **FixupData,\r
125 IN UINT64 Adjust\r
126 )\r
127{\r
128 UINT32 Value;\r
129 UINT32 Value2;\r
ad1db975 130\r
ad1db975
AC
131 switch ((*Reloc) >> 12) {\r
132 case EFI_IMAGE_REL_BASED_RISCV_HI20:\r
133 RiscVHi20Fixup = (UINT32 *) Fixup;\r
134 break;\r
135\r
136 case EFI_IMAGE_REL_BASED_RISCV_LOW12I:\r
137 if (RiscVHi20Fixup != NULL) {\r
138 Value = (UINT32)(RV_X(*RiscVHi20Fixup, 12, 20) << 12);\r
139 Value2 = (UINT32)(RV_X(*(UINT32 *)Fixup, 20, 12));\r
140 if (Value2 & (RISCV_IMM_REACH/2)) {\r
141 Value2 |= ~(RISCV_IMM_REACH-1);\r
142 }\r
143 Value += Value2;\r
144 Value += (UINT32)Adjust;\r
145 Value2 = RISCV_CONST_HIGH_PART (Value);\r
146 *(UINT32 *)RiscVHi20Fixup = (RV_X (Value2, 12, 20) << 12) | \\r
147 (RV_X (*(UINT32 *)RiscVHi20Fixup, 0, 12));\r
148 *(UINT32 *)Fixup = (RV_X (Value, 0, 12) << 20) | \\r
149 (RV_X (*(UINT32 *)Fixup, 0, 20));\r
150 }\r
151 RiscVHi20Fixup = NULL;\r
152 break;\r
153\r
154 case EFI_IMAGE_REL_BASED_RISCV_LOW12S:\r
155 if (RiscVHi20Fixup != NULL) {\r
156 Value = (UINT32)(RV_X(*RiscVHi20Fixup, 12, 20) << 12);\r
157 Value2 = (UINT32)(RV_X(*(UINT32 *)Fixup, 7, 5) | (RV_X(*(UINT32 *)Fixup, 25, 7) << 5));\r
158 if (Value2 & (RISCV_IMM_REACH/2)) {\r
159 Value2 |= ~(RISCV_IMM_REACH-1);\r
160 }\r
161 Value += Value2;\r
162 Value += (UINT32)Adjust;\r
163 Value2 = RISCV_CONST_HIGH_PART (Value);\r
164 *(UINT32 *)RiscVHi20Fixup = (RV_X (Value2, 12, 20) << 12) | \\r
165 (RV_X (*(UINT32 *)RiscVHi20Fixup, 0, 12));\r
166 Value2 = *(UINT32 *)Fixup & 0x01fff07f;\r
167 Value &= RISCV_IMM_REACH - 1;\r
168 *(UINT32 *)Fixup = Value2 | (UINT32)(((RV_X(Value, 0, 5) << 7) | (RV_X(Value, 5, 7) << 25)));\r
169 }\r
170 RiscVHi20Fixup = NULL;\r
171 break;\r
172\r
173 default:\r
174 return EFI_UNSUPPORTED;\r
175\r
176 }\r
177 return RETURN_SUCCESS;\r
178}\r
30fdf114 179\r
40d841f6 180/**\r
fb0b35e0 181 Pass in a pointer to an ARM MOVT or MOVW immediate instruction and\r
40d841f6
LG
182 return the immediate data encoded in the instruction\r
183\r
184 @param Instruction Pointer to ARM MOVT or MOVW immediate instruction\r
185\r
186 @return Immediate address encoded in the instruction\r
187\r
188**/\r
189UINT16\r
190ThumbMovtImmediateAddress (\r
191 IN UINT16 *Instruction\r
192 )\r
193{\r
194 UINT32 Movt;\r
195 UINT16 Address;\r
196\r
197 // Thumb2 is two 16-bit instructions working together. Not a single 32-bit instruction\r
198 // Example MOVT R0, #0 is 0x0000f2c0 or 0xf2c0 0x0000\r
f7496d71 199 Movt = (*Instruction << 16) | (*(Instruction + 1));\r
40d841f6
LG
200\r
201 // imm16 = imm4:i:imm3:imm8\r
202 // imm4 -> Bit19:Bit16\r
203 // i -> Bit26\r
204 // imm3 -> Bit14:Bit12\r
205 // imm8 -> Bit7:Bit0\r
206 Address = (UINT16)(Movt & 0x000000ff); // imm8\r
207 Address |= (UINT16)((Movt >> 4) & 0x0000f700); // imm4 imm3\r
208 Address |= (((Movt & BIT26) != 0) ? BIT11 : 0); // i\r
209 return Address;\r
210}\r
211\r
212\r
213/**\r
214 Update an ARM MOVT or MOVW immediate instruction immediate data.\r
215\r
216 @param Instruction Pointer to ARM MOVT or MOVW immediate instruction\r
fb0b35e0 217 @param Address New address to patch into the instruction\r
40d841f6
LG
218**/\r
219VOID\r
220ThumbMovtImmediatePatch (\r
221 IN OUT UINT16 *Instruction,\r
222 IN UINT16 Address\r
223 )\r
224{\r
225 UINT16 Patch;\r
226\r
fb0b35e0 227 // First 16-bit chunk of instruction\r
f7496d71 228 Patch = ((Address >> 12) & 0x000f); // imm4\r
40d841f6
LG
229 Patch |= (((Address & BIT11) != 0) ? BIT10 : 0); // i\r
230 *Instruction = (*Instruction & ~0x040f) | Patch;\r
231\r
232 // Second 16-bit chunk of instruction\r
233 Patch = Address & 0x000000ff; // imm8\r
234 Patch |= ((Address << 4) & 0x00007000); // imm3\r
235 Instruction++;\r
236 *Instruction = (*Instruction & ~0x70ff) | Patch;\r
237}\r
238\r
da92f276 239/**\r
fb0b35e0 240 Pass in a pointer to an ARM MOVW/MOVT instruction pair and\r
da92f276
LG
241 return the immediate data encoded in the two` instruction\r
242\r
fb0b35e0 243 @param Instructions Pointer to ARM MOVW/MOVT instruction pair\r
da92f276
LG
244\r
245 @return Immediate address encoded in the instructions\r
246\r
247**/\r
248UINT32\r
249EFIAPI\r
250ThumbMovwMovtImmediateAddress (\r
251 IN UINT16 *Instructions\r
252 )\r
253{\r
254 UINT16 *Word;\r
255 UINT16 *Top;\r
f7496d71 256\r
da92f276
LG
257 Word = Instructions; // MOVW\r
258 Top = Word + 2; // MOVT\r
f7496d71 259\r
da92f276
LG
260 return (ThumbMovtImmediateAddress (Top) << 16) + ThumbMovtImmediateAddress (Word);\r
261}\r
262\r
263\r
264/**\r
265 Update an ARM MOVW/MOVT immediate instruction instruction pair.\r
266\r
267 @param Instructions Pointer to ARM MOVW/MOVT instruction pair\r
fb0b35e0 268 @param Address New address to patch into the instructions\r
da92f276
LG
269**/\r
270VOID\r
271EFIAPI\r
272ThumbMovwMovtImmediatePatch (\r
273 IN OUT UINT16 *Instructions,\r
274 IN UINT32 Address\r
275 )\r
276{\r
277 UINT16 *Word;\r
278 UINT16 *Top;\r
f7496d71 279\r
da92f276
LG
280 Word = (UINT16 *)Instructions; // MOVW\r
281 Top = Word + 2; // MOVT\r
282\r
283 ThumbMovtImmediatePatch (Word, (UINT16)(Address & 0xffff));\r
284 ThumbMovtImmediatePatch (Top, (UINT16)(Address >> 16));\r
285}\r
286\r
287\r
40d841f6
LG
288/**\r
289 Performs an ARM-based specific relocation fixup and is a no-op on other\r
290 instruction sets.\r
291\r
292 @param Reloc Pointer to the relocation record.\r
293 @param Fixup Pointer to the address to fix up.\r
294 @param FixupData Pointer to a buffer to log the fixups.\r
295 @param Adjust The offset to adjust the fixup.\r
296\r
297 @return Status code.\r
298\r
299**/\r
300RETURN_STATUS\r
301PeCoffLoaderRelocateArmImage (\r
302 IN UINT16 **Reloc,\r
303 IN OUT CHAR8 *Fixup,\r
304 IN OUT CHAR8 **FixupData,\r
305 IN UINT64 Adjust\r
306 )\r
307{\r
308 UINT16 *Fixup16;\r
da92f276 309 UINT32 FixupVal;\r
40d841f6 310\r
da92f276 311 Fixup16 = (UINT16 *) Fixup;\r
40d841f6
LG
312\r
313 switch ((**Reloc) >> 12) {\r
f7496d71 314\r
da92f276
LG
315 case EFI_IMAGE_REL_BASED_ARM_MOV32T:\r
316 FixupVal = ThumbMovwMovtImmediateAddress (Fixup16) + (UINT32)Adjust;\r
317 ThumbMovwMovtImmediatePatch (Fixup16, FixupVal);\r
f7496d71
LG
318\r
319\r
40d841f6 320 if (*FixupData != NULL) {\r
da92f276 321 *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64));\r
da92f276 322 CopyMem (*FixupData, Fixup16, sizeof (UINT64));\r
94762dde 323 *FixupData = *FixupData + sizeof(UINT64);\r
40d841f6
LG
324 }\r
325 break;\r
f7496d71 326\r
da92f276
LG
327 case EFI_IMAGE_REL_BASED_ARM_MOV32A:\r
328 // break omitted - ARM instruction encoding not implemented\r
40d841f6
LG
329 default:\r
330 return RETURN_UNSUPPORTED;\r
331 }\r
332\r
333 return RETURN_SUCCESS;\r
334}\r