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