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