]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdePkg/Library/BasePeCoffLib/Arm/PeCoffLoaderEx.c
MdePkg: Apply uncrustify changes
[mirror_edk2.git] / MdePkg / Library / BasePeCoffLib / Arm / PeCoffLoaderEx.c
... / ...
CommitLineData
1/** @file\r
2 Specific relocation fixups for ARM architecture.\r
3\r
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
5 Portions copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>\r
6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
7\r
8**/\r
9\r
10#include "BasePeCoffLibInternals.h"\r
11#include <Library/BaseLib.h>\r
12\r
13/**\r
14 Pass in a pointer to an ARM MOVT or MOVW immediate instruciton and\r
15 return the immediate data encoded in the instruction.\r
16\r
17 @param Instruction Pointer to ARM MOVT or MOVW immediate instruction\r
18\r
19 @return Immediate address encoded in the instruction\r
20\r
21**/\r
22UINT16\r
23ThumbMovtImmediateAddress (\r
24 IN UINT16 *Instruction\r
25 )\r
26{\r
27 UINT32 Movt;\r
28 UINT16 Address;\r
29\r
30 // Thumb2 is two 16-bit instructions working together. Not a single 32-bit instruction\r
31 // Example MOVT R0, #0 is 0x0000f2c0 or 0xf2c0 0x0000\r
32 Movt = (*Instruction << 16) | (*(Instruction + 1));\r
33\r
34 // imm16 = imm4:i:imm3:imm8\r
35 // imm4 -> Bit19:Bit16\r
36 // i -> Bit26\r
37 // imm3 -> Bit14:Bit12\r
38 // imm8 -> Bit7:Bit0\r
39 Address = (UINT16)(Movt & 0x000000ff); // imm8\r
40 Address |= (UINT16)((Movt >> 4) & 0x0000f700); // imm4 imm3\r
41 Address |= (((Movt & BIT26) != 0) ? BIT11 : 0); // i\r
42 return Address;\r
43}\r
44\r
45/**\r
46 Update an ARM MOVT or MOVW immediate instruction immediate data.\r
47\r
48 @param Instruction Pointer to ARM MOVT or MOVW immediate instruction\r
49 @param Address New addres to patch into the instruction\r
50**/\r
51VOID\r
52ThumbMovtImmediatePatch (\r
53 IN OUT UINT16 *Instruction,\r
54 IN UINT16 Address\r
55 )\r
56{\r
57 UINT16 Patch;\r
58\r
59 // First 16-bit chunk of instruciton\r
60 Patch = ((Address >> 12) & 0x000f); // imm4\r
61 Patch |= (((Address & BIT11) != 0) ? BIT10 : 0); // i\r
62 // Mask out instruction bits and or in address\r
63 *(Instruction) = (*Instruction & ~0x040f) | Patch;\r
64\r
65 // Second 16-bit chunk of instruction\r
66 Patch = Address & 0x000000ff; // imm8\r
67 Patch |= ((Address << 4) & 0x00007000); // imm3\r
68 // Mask out instruction bits and or in address\r
69 Instruction++;\r
70 *Instruction = (*Instruction & ~0x70ff) | Patch;\r
71}\r
72\r
73/**\r
74 Pass in a pointer to an ARM MOVW/MOVT instruciton pair and\r
75 return the immediate data encoded in the two` instruction.\r
76\r
77 @param Instructions Pointer to ARM MOVW/MOVT insturction pair\r
78\r
79 @return Immediate address encoded in the instructions\r
80\r
81**/\r
82UINT32\r
83ThumbMovwMovtImmediateAddress (\r
84 IN UINT16 *Instructions\r
85 )\r
86{\r
87 UINT16 *Word;\r
88 UINT16 *Top;\r
89\r
90 Word = Instructions; // MOVW\r
91 Top = Word + 2; // MOVT\r
92\r
93 return (ThumbMovtImmediateAddress (Top) << 16) + ThumbMovtImmediateAddress (Word);\r
94}\r
95\r
96/**\r
97 Update an ARM MOVW/MOVT immediate instruction instruction pair.\r
98\r
99 @param Instructions Pointer to ARM MOVW/MOVT instruction pair\r
100 @param Address New addres to patch into the instructions\r
101**/\r
102VOID\r
103ThumbMovwMovtImmediatePatch (\r
104 IN OUT UINT16 *Instructions,\r
105 IN UINT32 Address\r
106 )\r
107{\r
108 UINT16 *Word;\r
109 UINT16 *Top;\r
110\r
111 Word = Instructions; // MOVW\r
112 Top = Word + 2; // MOVT\r
113\r
114 ThumbMovtImmediatePatch (Word, (UINT16)(Address & 0xffff));\r
115 ThumbMovtImmediatePatch (Top, (UINT16)(Address >> 16));\r
116}\r
117\r
118/**\r
119 Performs an ARM-based specific relocation fixup and is a no-op on other\r
120 instruction sets.\r
121\r
122 @param Reloc The pointer to the relocation record.\r
123 @param Fixup The pointer to the address to fix up.\r
124 @param FixupData The pointer to a buffer to log the fixups.\r
125 @param Adjust The offset to adjust the fixup.\r
126\r
127 @return Status code.\r
128\r
129**/\r
130RETURN_STATUS\r
131PeCoffLoaderRelocateImageEx (\r
132 IN UINT16 *Reloc,\r
133 IN OUT CHAR8 *Fixup,\r
134 IN OUT CHAR8 **FixupData,\r
135 IN UINT64 Adjust\r
136 )\r
137{\r
138 UINT16 *Fixup16;\r
139 UINT32 FixupVal;\r
140\r
141 Fixup16 = (UINT16 *)Fixup;\r
142\r
143 switch ((*Reloc) >> 12) {\r
144 case EFI_IMAGE_REL_BASED_ARM_MOV32T:\r
145 FixupVal = ThumbMovwMovtImmediateAddress (Fixup16) + (UINT32)Adjust;\r
146 ThumbMovwMovtImmediatePatch (Fixup16, FixupVal);\r
147\r
148 if (*FixupData != NULL) {\r
149 *FixupData = ALIGN_POINTER (*FixupData, sizeof (UINT64));\r
150 // Fixup16 is not aligned so we must copy it. Thumb instructions are streams of 16 bytes.\r
151 CopyMem (*FixupData, Fixup16, sizeof (UINT64));\r
152 *FixupData = *FixupData + sizeof (UINT64);\r
153 }\r
154\r
155 break;\r
156\r
157 case EFI_IMAGE_REL_BASED_ARM_MOV32A:\r
158 ASSERT (FALSE);\r
159 // break omitted - ARM instruction encoding not implemented\r
160 default:\r
161 return RETURN_UNSUPPORTED;\r
162 }\r
163\r
164 return RETURN_SUCCESS;\r
165}\r
166\r
167/**\r
168 Returns TRUE if the machine type of PE/COFF image is supported. Supported\r
169 does not mean the image can be executed it means the PE/COFF loader supports\r
170 loading and relocating of the image type. It's up to the caller to support\r
171 the entry point.\r
172\r
173 @param Machine Machine type from the PE Header.\r
174\r
175 @return TRUE if this PE/COFF loader can load the image\r
176\r
177**/\r
178BOOLEAN\r
179PeCoffLoaderImageFormatSupported (\r
180 IN UINT16 Machine\r
181 )\r
182{\r
183 if ((Machine == IMAGE_FILE_MACHINE_ARMTHUMB_MIXED) || (Machine == IMAGE_FILE_MACHINE_EBC)) {\r
184 return TRUE;\r
185 }\r
186\r
187 return FALSE;\r
188}\r
189\r
190/**\r
191 Performs an ARM-based specific re-relocation fixup and is a no-op on other\r
192 instruction sets. This is used to re-relocated the image into the EFI virtual\r
193 space for runtime calls.\r
194\r
195 @param Reloc The pointer to the relocation record.\r
196 @param Fixup The pointer to the address to fix up.\r
197 @param FixupData The pointer to a buffer to log the fixups.\r
198 @param Adjust The offset to adjust the fixup.\r
199\r
200 @return Status code.\r
201\r
202**/\r
203RETURN_STATUS\r
204PeHotRelocateImageEx (\r
205 IN UINT16 *Reloc,\r
206 IN OUT CHAR8 *Fixup,\r
207 IN OUT CHAR8 **FixupData,\r
208 IN UINT64 Adjust\r
209 )\r
210{\r
211 UINT16 *Fixup16;\r
212 UINT32 FixupVal;\r
213\r
214 Fixup16 = (UINT16 *)Fixup;\r
215\r
216 switch ((*Reloc) >> 12) {\r
217 case EFI_IMAGE_REL_BASED_ARM_MOV32T:\r
218 *FixupData = ALIGN_POINTER (*FixupData, sizeof (UINT64));\r
219 if (*(UINT64 *)(*FixupData) == ReadUnaligned64 ((UINT64 *)Fixup16)) {\r
220 FixupVal = ThumbMovwMovtImmediateAddress (Fixup16) + (UINT32)Adjust;\r
221 ThumbMovwMovtImmediatePatch (Fixup16, FixupVal);\r
222 }\r
223\r
224 *FixupData = *FixupData + sizeof (UINT64);\r
225 break;\r
226\r
227 case EFI_IMAGE_REL_BASED_ARM_MOV32A:\r
228 ASSERT (FALSE);\r
229 // break omitted - ARM instruction encoding not implemented\r
230 default:\r
231 DEBUG ((DEBUG_ERROR, "PeHotRelocateEx:unknown fixed type\n"));\r
232 return RETURN_UNSUPPORTED;\r
233 }\r
234\r
235 return RETURN_SUCCESS;\r
236}\r