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