]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/Common/PeCoffLoaderEx.c
BaseTools: BaseTools changes for RISC-V platform.
[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
130 UINT32 OrgValue;\r
131\r
132 OrgValue = *(UINT32 *) Fixup;\r
133 OrgValue = OrgValue;\r
134 switch ((*Reloc) >> 12) {\r
135 case EFI_IMAGE_REL_BASED_RISCV_HI20:\r
136 RiscVHi20Fixup = (UINT32 *) Fixup;\r
137 break;\r
138\r
139 case EFI_IMAGE_REL_BASED_RISCV_LOW12I:\r
140 if (RiscVHi20Fixup != NULL) {\r
141 Value = (UINT32)(RV_X(*RiscVHi20Fixup, 12, 20) << 12);\r
142 Value2 = (UINT32)(RV_X(*(UINT32 *)Fixup, 20, 12));\r
143 if (Value2 & (RISCV_IMM_REACH/2)) {\r
144 Value2 |= ~(RISCV_IMM_REACH-1);\r
145 }\r
146 Value += Value2;\r
147 Value += (UINT32)Adjust;\r
148 Value2 = RISCV_CONST_HIGH_PART (Value);\r
149 *(UINT32 *)RiscVHi20Fixup = (RV_X (Value2, 12, 20) << 12) | \\r
150 (RV_X (*(UINT32 *)RiscVHi20Fixup, 0, 12));\r
151 *(UINT32 *)Fixup = (RV_X (Value, 0, 12) << 20) | \\r
152 (RV_X (*(UINT32 *)Fixup, 0, 20));\r
153 }\r
154 RiscVHi20Fixup = NULL;\r
155 break;\r
156\r
157 case EFI_IMAGE_REL_BASED_RISCV_LOW12S:\r
158 if (RiscVHi20Fixup != NULL) {\r
159 Value = (UINT32)(RV_X(*RiscVHi20Fixup, 12, 20) << 12);\r
160 Value2 = (UINT32)(RV_X(*(UINT32 *)Fixup, 7, 5) | (RV_X(*(UINT32 *)Fixup, 25, 7) << 5));\r
161 if (Value2 & (RISCV_IMM_REACH/2)) {\r
162 Value2 |= ~(RISCV_IMM_REACH-1);\r
163 }\r
164 Value += Value2;\r
165 Value += (UINT32)Adjust;\r
166 Value2 = RISCV_CONST_HIGH_PART (Value);\r
167 *(UINT32 *)RiscVHi20Fixup = (RV_X (Value2, 12, 20) << 12) | \\r
168 (RV_X (*(UINT32 *)RiscVHi20Fixup, 0, 12));\r
169 Value2 = *(UINT32 *)Fixup & 0x01fff07f;\r
170 Value &= RISCV_IMM_REACH - 1;\r
171 *(UINT32 *)Fixup = Value2 | (UINT32)(((RV_X(Value, 0, 5) << 7) | (RV_X(Value, 5, 7) << 25)));\r
172 }\r
173 RiscVHi20Fixup = NULL;\r
174 break;\r
175\r
176 default:\r
177 return EFI_UNSUPPORTED;\r
178\r
179 }\r
180 return RETURN_SUCCESS;\r
181}\r
30fdf114 182\r
40d841f6 183/**\r
fb0b35e0 184 Pass in a pointer to an ARM MOVT or MOVW immediate instruction and\r
40d841f6
LG
185 return the immediate data encoded in the instruction\r
186\r
187 @param Instruction Pointer to ARM MOVT or MOVW immediate instruction\r
188\r
189 @return Immediate address encoded in the instruction\r
190\r
191**/\r
192UINT16\r
193ThumbMovtImmediateAddress (\r
194 IN UINT16 *Instruction\r
195 )\r
196{\r
197 UINT32 Movt;\r
198 UINT16 Address;\r
199\r
200 // Thumb2 is two 16-bit instructions working together. Not a single 32-bit instruction\r
201 // Example MOVT R0, #0 is 0x0000f2c0 or 0xf2c0 0x0000\r
f7496d71 202 Movt = (*Instruction << 16) | (*(Instruction + 1));\r
40d841f6
LG
203\r
204 // imm16 = imm4:i:imm3:imm8\r
205 // imm4 -> Bit19:Bit16\r
206 // i -> Bit26\r
207 // imm3 -> Bit14:Bit12\r
208 // imm8 -> Bit7:Bit0\r
209 Address = (UINT16)(Movt & 0x000000ff); // imm8\r
210 Address |= (UINT16)((Movt >> 4) & 0x0000f700); // imm4 imm3\r
211 Address |= (((Movt & BIT26) != 0) ? BIT11 : 0); // i\r
212 return Address;\r
213}\r
214\r
215\r
216/**\r
217 Update an ARM MOVT or MOVW immediate instruction immediate data.\r
218\r
219 @param Instruction Pointer to ARM MOVT or MOVW immediate instruction\r
fb0b35e0 220 @param Address New address to patch into the instruction\r
40d841f6
LG
221**/\r
222VOID\r
223ThumbMovtImmediatePatch (\r
224 IN OUT UINT16 *Instruction,\r
225 IN UINT16 Address\r
226 )\r
227{\r
228 UINT16 Patch;\r
229\r
fb0b35e0 230 // First 16-bit chunk of instruction\r
f7496d71 231 Patch = ((Address >> 12) & 0x000f); // imm4\r
40d841f6
LG
232 Patch |= (((Address & BIT11) != 0) ? BIT10 : 0); // i\r
233 *Instruction = (*Instruction & ~0x040f) | Patch;\r
234\r
235 // Second 16-bit chunk of instruction\r
236 Patch = Address & 0x000000ff; // imm8\r
237 Patch |= ((Address << 4) & 0x00007000); // imm3\r
238 Instruction++;\r
239 *Instruction = (*Instruction & ~0x70ff) | Patch;\r
240}\r
241\r
da92f276 242/**\r
fb0b35e0 243 Pass in a pointer to an ARM MOVW/MOVT instruction pair and\r
da92f276
LG
244 return the immediate data encoded in the two` instruction\r
245\r
fb0b35e0 246 @param Instructions Pointer to ARM MOVW/MOVT instruction pair\r
da92f276
LG
247\r
248 @return Immediate address encoded in the instructions\r
249\r
250**/\r
251UINT32\r
252EFIAPI\r
253ThumbMovwMovtImmediateAddress (\r
254 IN UINT16 *Instructions\r
255 )\r
256{\r
257 UINT16 *Word;\r
258 UINT16 *Top;\r
f7496d71 259\r
da92f276
LG
260 Word = Instructions; // MOVW\r
261 Top = Word + 2; // MOVT\r
f7496d71 262\r
da92f276
LG
263 return (ThumbMovtImmediateAddress (Top) << 16) + ThumbMovtImmediateAddress (Word);\r
264}\r
265\r
266\r
267/**\r
268 Update an ARM MOVW/MOVT immediate instruction instruction pair.\r
269\r
270 @param Instructions Pointer to ARM MOVW/MOVT instruction pair\r
fb0b35e0 271 @param Address New address to patch into the instructions\r
da92f276
LG
272**/\r
273VOID\r
274EFIAPI\r
275ThumbMovwMovtImmediatePatch (\r
276 IN OUT UINT16 *Instructions,\r
277 IN UINT32 Address\r
278 )\r
279{\r
280 UINT16 *Word;\r
281 UINT16 *Top;\r
f7496d71 282\r
da92f276
LG
283 Word = (UINT16 *)Instructions; // MOVW\r
284 Top = Word + 2; // MOVT\r
285\r
286 ThumbMovtImmediatePatch (Word, (UINT16)(Address & 0xffff));\r
287 ThumbMovtImmediatePatch (Top, (UINT16)(Address >> 16));\r
288}\r
289\r
290\r
40d841f6
LG
291/**\r
292 Performs an ARM-based specific relocation fixup and is a no-op on other\r
293 instruction sets.\r
294\r
295 @param Reloc Pointer to the relocation record.\r
296 @param Fixup Pointer to the address to fix up.\r
297 @param FixupData Pointer to a buffer to log the fixups.\r
298 @param Adjust The offset to adjust the fixup.\r
299\r
300 @return Status code.\r
301\r
302**/\r
303RETURN_STATUS\r
304PeCoffLoaderRelocateArmImage (\r
305 IN UINT16 **Reloc,\r
306 IN OUT CHAR8 *Fixup,\r
307 IN OUT CHAR8 **FixupData,\r
308 IN UINT64 Adjust\r
309 )\r
310{\r
311 UINT16 *Fixup16;\r
da92f276 312 UINT32 FixupVal;\r
40d841f6 313\r
da92f276 314 Fixup16 = (UINT16 *) Fixup;\r
40d841f6
LG
315\r
316 switch ((**Reloc) >> 12) {\r
f7496d71 317\r
da92f276
LG
318 case EFI_IMAGE_REL_BASED_ARM_MOV32T:\r
319 FixupVal = ThumbMovwMovtImmediateAddress (Fixup16) + (UINT32)Adjust;\r
320 ThumbMovwMovtImmediatePatch (Fixup16, FixupVal);\r
f7496d71
LG
321\r
322\r
40d841f6 323 if (*FixupData != NULL) {\r
da92f276 324 *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64));\r
da92f276 325 CopyMem (*FixupData, Fixup16, sizeof (UINT64));\r
94762dde 326 *FixupData = *FixupData + sizeof(UINT64);\r
40d841f6
LG
327 }\r
328 break;\r
f7496d71 329\r
da92f276
LG
330 case EFI_IMAGE_REL_BASED_ARM_MOV32A:\r
331 // break omitted - ARM instruction encoding not implemented\r
40d841f6
LG
332 default:\r
333 return RETURN_UNSUPPORTED;\r
334 }\r
335\r
336 return RETURN_SUCCESS;\r
337}\r