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