]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/Common/PeCoffLoaderEx.c
fa8c7e3d1737e778ac25e4b097d1574c47708cfa
[mirror_edk2.git] / BaseTools / Source / C / Common / PeCoffLoaderEx.c
1 /** @file
2 IA32 and X64 Specific relocation fixups
3
4 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
5 Portions Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>
6 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 <Common/UefiBaseTypes.h>
17 #include <IndustryStandard/PeImage.h>
18 #include "PeCoffLib.h"
19 #include "CommonLib.h"
20 #include "EfiUtilityMsgs.h"
21
22
23 #define EXT_IMM64(Value, Address, Size, InstPos, ValPos) \
24 Value |= (((UINT64)((*(Address) >> InstPos) & (((UINT64)1 << Size) - 1))) << ValPos)
25
26 #define INS_IMM64(Value, Address, Size, InstPos, ValPos) \
27 *(UINT32*)Address = (*(UINT32*)Address & ~(((1 << Size) - 1) << InstPos)) | \
28 ((UINT32)((((UINT64)Value >> ValPos) & (((UINT64)1 << Size) - 1))) << InstPos)
29
30 #define IMM64_IMM7B_INST_WORD_X 3
31 #define IMM64_IMM7B_SIZE_X 7
32 #define IMM64_IMM7B_INST_WORD_POS_X 4
33 #define IMM64_IMM7B_VAL_POS_X 0
34
35 #define IMM64_IMM9D_INST_WORD_X 3
36 #define IMM64_IMM9D_SIZE_X 9
37 #define IMM64_IMM9D_INST_WORD_POS_X 18
38 #define IMM64_IMM9D_VAL_POS_X 7
39
40 #define IMM64_IMM5C_INST_WORD_X 3
41 #define IMM64_IMM5C_SIZE_X 5
42 #define IMM64_IMM5C_INST_WORD_POS_X 13
43 #define IMM64_IMM5C_VAL_POS_X 16
44
45 #define IMM64_IC_INST_WORD_X 3
46 #define IMM64_IC_SIZE_X 1
47 #define IMM64_IC_INST_WORD_POS_X 12
48 #define IMM64_IC_VAL_POS_X 21
49
50 #define IMM64_IMM41a_INST_WORD_X 1
51 #define IMM64_IMM41a_SIZE_X 10
52 #define IMM64_IMM41a_INST_WORD_POS_X 14
53 #define IMM64_IMM41a_VAL_POS_X 22
54
55 #define IMM64_IMM41b_INST_WORD_X 1
56 #define IMM64_IMM41b_SIZE_X 8
57 #define IMM64_IMM41b_INST_WORD_POS_X 24
58 #define IMM64_IMM41b_VAL_POS_X 32
59
60 #define IMM64_IMM41c_INST_WORD_X 2
61 #define IMM64_IMM41c_SIZE_X 23
62 #define IMM64_IMM41c_INST_WORD_POS_X 0
63 #define IMM64_IMM41c_VAL_POS_X 40
64
65 #define IMM64_SIGN_INST_WORD_X 3
66 #define IMM64_SIGN_SIZE_X 1
67 #define IMM64_SIGN_INST_WORD_POS_X 27
68 #define IMM64_SIGN_VAL_POS_X 63
69
70 RETURN_STATUS
71 PeCoffLoaderRelocateIa32Image (
72 IN UINT16 *Reloc,
73 IN OUT CHAR8 *Fixup,
74 IN OUT CHAR8 **FixupData,
75 IN UINT64 Adjust
76 )
77 /*++
78
79 Routine Description:
80
81 Performs an IA-32 specific relocation fixup
82
83 Arguments:
84
85 Reloc - Pointer to the relocation record
86
87 Fixup - Pointer to the address to fix up
88
89 FixupData - Pointer to a buffer to log the fixups
90
91 Adjust - The offset to adjust the fixup
92
93 Returns:
94
95 EFI_UNSUPPORTED - Unsupported now
96
97 --*/
98 {
99 return RETURN_UNSUPPORTED;
100 }
101
102
103 /**
104 Pass in a pointer to an ARM MOVT or MOVW immediate instruciton and
105 return the immediate data encoded in the instruction
106
107 @param Instruction Pointer to ARM MOVT or MOVW immediate instruction
108
109 @return Immediate address encoded in the instruction
110
111 **/
112 UINT16
113 ThumbMovtImmediateAddress (
114 IN UINT16 *Instruction
115 )
116 {
117 UINT32 Movt;
118 UINT16 Address;
119
120 // Thumb2 is two 16-bit instructions working together. Not a single 32-bit instruction
121 // Example MOVT R0, #0 is 0x0000f2c0 or 0xf2c0 0x0000
122 Movt = (*Instruction << 16) | (*(Instruction + 1));
123
124 // imm16 = imm4:i:imm3:imm8
125 // imm4 -> Bit19:Bit16
126 // i -> Bit26
127 // imm3 -> Bit14:Bit12
128 // imm8 -> Bit7:Bit0
129 Address = (UINT16)(Movt & 0x000000ff); // imm8
130 Address |= (UINT16)((Movt >> 4) & 0x0000f700); // imm4 imm3
131 Address |= (((Movt & BIT26) != 0) ? BIT11 : 0); // i
132 return Address;
133 }
134
135
136 /**
137 Update an ARM MOVT or MOVW immediate instruction immediate data.
138
139 @param Instruction Pointer to ARM MOVT or MOVW immediate instruction
140 @param Address New addres to patch into the instruction
141 **/
142 VOID
143 ThumbMovtImmediatePatch (
144 IN OUT UINT16 *Instruction,
145 IN UINT16 Address
146 )
147 {
148 UINT16 Patch;
149
150 // First 16-bit chunk of instruciton
151 Patch = ((Address >> 12) & 0x000f); // imm4
152 Patch |= (((Address & BIT11) != 0) ? BIT10 : 0); // i
153 *Instruction = (*Instruction & ~0x040f) | Patch;
154
155 // Second 16-bit chunk of instruction
156 Patch = Address & 0x000000ff; // imm8
157 Patch |= ((Address << 4) & 0x00007000); // imm3
158 Instruction++;
159 *Instruction = (*Instruction & ~0x70ff) | Patch;
160 }
161
162 /**
163 Pass in a pointer to an ARM MOVW/MOVT instruciton pair and
164 return the immediate data encoded in the two` instruction
165
166 @param Instructions Pointer to ARM MOVW/MOVT insturction pair
167
168 @return Immediate address encoded in the instructions
169
170 **/
171 UINT32
172 EFIAPI
173 ThumbMovwMovtImmediateAddress (
174 IN UINT16 *Instructions
175 )
176 {
177 UINT16 *Word;
178 UINT16 *Top;
179
180 Word = Instructions; // MOVW
181 Top = Word + 2; // MOVT
182
183 return (ThumbMovtImmediateAddress (Top) << 16) + ThumbMovtImmediateAddress (Word);
184 }
185
186
187 /**
188 Update an ARM MOVW/MOVT immediate instruction instruction pair.
189
190 @param Instructions Pointer to ARM MOVW/MOVT instruction pair
191 @param Address New addres to patch into the instructions
192 **/
193 VOID
194 EFIAPI
195 ThumbMovwMovtImmediatePatch (
196 IN OUT UINT16 *Instructions,
197 IN UINT32 Address
198 )
199 {
200 UINT16 *Word;
201 UINT16 *Top;
202
203 Word = (UINT16 *)Instructions; // MOVW
204 Top = Word + 2; // MOVT
205
206 ThumbMovtImmediatePatch (Word, (UINT16)(Address & 0xffff));
207 ThumbMovtImmediatePatch (Top, (UINT16)(Address >> 16));
208 }
209
210
211 /**
212 Performs an ARM-based specific relocation fixup and is a no-op on other
213 instruction sets.
214
215 @param Reloc Pointer to the relocation record.
216 @param Fixup Pointer to the address to fix up.
217 @param FixupData Pointer to a buffer to log the fixups.
218 @param Adjust The offset to adjust the fixup.
219
220 @return Status code.
221
222 **/
223 RETURN_STATUS
224 PeCoffLoaderRelocateArmImage (
225 IN UINT16 **Reloc,
226 IN OUT CHAR8 *Fixup,
227 IN OUT CHAR8 **FixupData,
228 IN UINT64 Adjust
229 )
230 {
231 UINT16 *Fixup16;
232 UINT32 FixupVal;
233
234 Fixup16 = (UINT16 *) Fixup;
235
236 switch ((**Reloc) >> 12) {
237
238 case EFI_IMAGE_REL_BASED_ARM_MOV32T:
239 FixupVal = ThumbMovwMovtImmediateAddress (Fixup16) + (UINT32)Adjust;
240 ThumbMovwMovtImmediatePatch (Fixup16, FixupVal);
241
242
243 if (*FixupData != NULL) {
244 *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64));
245 CopyMem (*FixupData, Fixup16, sizeof (UINT64));
246 *FixupData = *FixupData + sizeof(UINT64);
247 }
248 break;
249
250 case EFI_IMAGE_REL_BASED_ARM_MOV32A:
251 // break omitted - ARM instruction encoding not implemented
252 default:
253 return RETURN_UNSUPPORTED;
254 }
255
256 return RETURN_SUCCESS;
257 }