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