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