3 Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 IA32, X64 and IPF Specific relocation fixups
24 #include <Common/UefiBaseTypes.h>
25 #include <IndustryStandard/PeImage.h>
26 #include "PeCoffLib.h"
27 #include "CommonLib.h"
30 #define EXT_IMM64(Value, Address, Size, InstPos, ValPos) \
31 Value |= (((UINT64)((*(Address) >> InstPos) & (((UINT64)1 << Size) - 1))) << ValPos)
33 #define INS_IMM64(Value, Address, Size, InstPos, ValPos) \
34 *(UINT32*)Address = (*(UINT32*)Address & ~(((1 << Size) - 1) << InstPos)) | \
35 ((UINT32)((((UINT64)Value >> ValPos) & (((UINT64)1 << Size) - 1))) << InstPos)
37 #define IMM64_IMM7B_INST_WORD_X 3
38 #define IMM64_IMM7B_SIZE_X 7
39 #define IMM64_IMM7B_INST_WORD_POS_X 4
40 #define IMM64_IMM7B_VAL_POS_X 0
42 #define IMM64_IMM9D_INST_WORD_X 3
43 #define IMM64_IMM9D_SIZE_X 9
44 #define IMM64_IMM9D_INST_WORD_POS_X 18
45 #define IMM64_IMM9D_VAL_POS_X 7
47 #define IMM64_IMM5C_INST_WORD_X 3
48 #define IMM64_IMM5C_SIZE_X 5
49 #define IMM64_IMM5C_INST_WORD_POS_X 13
50 #define IMM64_IMM5C_VAL_POS_X 16
52 #define IMM64_IC_INST_WORD_X 3
53 #define IMM64_IC_SIZE_X 1
54 #define IMM64_IC_INST_WORD_POS_X 12
55 #define IMM64_IC_VAL_POS_X 21
57 #define IMM64_IMM41a_INST_WORD_X 1
58 #define IMM64_IMM41a_SIZE_X 10
59 #define IMM64_IMM41a_INST_WORD_POS_X 14
60 #define IMM64_IMM41a_VAL_POS_X 22
62 #define IMM64_IMM41b_INST_WORD_X 1
63 #define IMM64_IMM41b_SIZE_X 8
64 #define IMM64_IMM41b_INST_WORD_POS_X 24
65 #define IMM64_IMM41b_VAL_POS_X 32
67 #define IMM64_IMM41c_INST_WORD_X 2
68 #define IMM64_IMM41c_SIZE_X 23
69 #define IMM64_IMM41c_INST_WORD_POS_X 0
70 #define IMM64_IMM41c_VAL_POS_X 40
72 #define IMM64_SIGN_INST_WORD_X 3
73 #define IMM64_SIGN_SIZE_X 1
74 #define IMM64_SIGN_INST_WORD_POS_X 27
75 #define IMM64_SIGN_VAL_POS_X 63
78 PeCoffLoaderRelocateIa32Image (
81 IN OUT CHAR8
**FixupData
,
88 Performs an IA-32 specific relocation fixup
92 Reloc - Pointer to the relocation record
94 Fixup - Pointer to the address to fix up
96 FixupData - Pointer to a buffer to log the fixups
98 Adjust - The offset to adjust the fixup
102 EFI_UNSUPPORTED - Unsupported now
106 return RETURN_UNSUPPORTED
;
110 PeCoffLoaderRelocateIpfImage (
113 IN OUT CHAR8
**FixupData
,
120 Performs an Itanium-based specific relocation fixup
124 Reloc - Pointer to the relocation record
126 Fixup - Pointer to the address to fix up
128 FixupData - Pointer to a buffer to log the fixups
130 Adjust - The offset to adjust the fixup
141 switch ((*Reloc
) >> 12) {
143 case EFI_IMAGE_REL_BASED_DIR64
:
144 F64
= (UINT64
*) Fixup
;
145 *F64
= *F64
+ (UINT64
) Adjust
;
146 if (*FixupData
!= NULL
) {
147 *FixupData
= ALIGN_POINTER(*FixupData
, sizeof(UINT64
));
148 *(UINT64
*)(*FixupData
) = *F64
;
149 *FixupData
= *FixupData
+ sizeof(UINT64
);
153 case EFI_IMAGE_REL_BASED_IA64_IMM64
:
156 // Align it to bundle address before fixing up the
157 // 64-bit immediate value of the movl instruction.
160 Fixup
= (CHAR8
*)((UINTN
) Fixup
& (UINTN
) ~(15));
161 FixupVal
= (UINT64
)0;
164 // Extract the lower 32 bits of IMM64 from bundle
167 (UINT32
*)Fixup
+ IMM64_IMM7B_INST_WORD_X
,
169 IMM64_IMM7B_INST_WORD_POS_X
,
170 IMM64_IMM7B_VAL_POS_X
174 (UINT32
*)Fixup
+ IMM64_IMM9D_INST_WORD_X
,
176 IMM64_IMM9D_INST_WORD_POS_X
,
177 IMM64_IMM9D_VAL_POS_X
181 (UINT32
*)Fixup
+ IMM64_IMM5C_INST_WORD_X
,
183 IMM64_IMM5C_INST_WORD_POS_X
,
184 IMM64_IMM5C_VAL_POS_X
188 (UINT32
*)Fixup
+ IMM64_IC_INST_WORD_X
,
190 IMM64_IC_INST_WORD_POS_X
,
195 (UINT32
*)Fixup
+ IMM64_IMM41a_INST_WORD_X
,
197 IMM64_IMM41a_INST_WORD_POS_X
,
198 IMM64_IMM41a_VAL_POS_X
202 // Update 64-bit address
207 // Insert IMM64 into bundle
210 ((UINT32
*)Fixup
+ IMM64_IMM7B_INST_WORD_X
),
212 IMM64_IMM7B_INST_WORD_POS_X
,
213 IMM64_IMM7B_VAL_POS_X
217 ((UINT32
*)Fixup
+ IMM64_IMM9D_INST_WORD_X
),
219 IMM64_IMM9D_INST_WORD_POS_X
,
220 IMM64_IMM9D_VAL_POS_X
224 ((UINT32
*)Fixup
+ IMM64_IMM5C_INST_WORD_X
),
226 IMM64_IMM5C_INST_WORD_POS_X
,
227 IMM64_IMM5C_VAL_POS_X
231 ((UINT32
*)Fixup
+ IMM64_IC_INST_WORD_X
),
233 IMM64_IC_INST_WORD_POS_X
,
238 ((UINT32
*)Fixup
+ IMM64_IMM41a_INST_WORD_X
),
240 IMM64_IMM41a_INST_WORD_POS_X
,
241 IMM64_IMM41a_VAL_POS_X
245 ((UINT32
*)Fixup
+ IMM64_IMM41b_INST_WORD_X
),
247 IMM64_IMM41b_INST_WORD_POS_X
,
248 IMM64_IMM41b_VAL_POS_X
252 ((UINT32
*)Fixup
+ IMM64_IMM41c_INST_WORD_X
),
254 IMM64_IMM41c_INST_WORD_POS_X
,
255 IMM64_IMM41c_VAL_POS_X
259 ((UINT32
*)Fixup
+ IMM64_SIGN_INST_WORD_X
),
261 IMM64_SIGN_INST_WORD_POS_X
,
265 F64
= (UINT64
*) Fixup
;
266 if (*FixupData
!= NULL
) {
267 *FixupData
= ALIGN_POINTER(*FixupData
, sizeof(UINT64
));
268 *(UINT64
*)(*FixupData
) = *F64
;
269 *FixupData
= *FixupData
+ sizeof(UINT64
);
274 return RETURN_UNSUPPORTED
;
277 return RETURN_SUCCESS
;
281 PeCoffLoaderRelocateX64Image (
284 IN OUT CHAR8
**FixupData
,
288 Performs an x64 specific relocation fixup
290 @param Reloc Pointer to the relocation record
291 @param Fixup Pointer to the address to fix up
292 @param FixupData Pointer to a buffer to log the fixups
293 @param Adjust The offset to adjust the fixup
295 @retval RETURN_SUCCESS Success to perform relocation
296 @retval RETURN_UNSUPPORTED Unsupported.
301 switch ((*Reloc
) >> 12) {
303 case EFI_IMAGE_REL_BASED_DIR64
:
304 F64
= (UINT64
*) Fixup
;
305 *F64
= *F64
+ (UINT64
) Adjust
;
306 if (*FixupData
!= NULL
) {
307 *FixupData
= ALIGN_POINTER(*FixupData
, sizeof(UINT64
));
308 *(UINT64
*)(*FixupData
) = *F64
;
309 *FixupData
= *FixupData
+ sizeof(UINT64
);
314 return RETURN_UNSUPPORTED
;
317 return RETURN_SUCCESS
;
321 Pass in a pointer to an ARM MOVT or MOVW immediate instruciton and
322 return the immediate data encoded in the instruction
324 @param Instruction Pointer to ARM MOVT or MOVW immediate instruction
326 @return Immediate address encoded in the instruction
330 ThumbMovtImmediateAddress (
331 IN UINT16
*Instruction
337 // Thumb2 is two 16-bit instructions working together. Not a single 32-bit instruction
338 // Example MOVT R0, #0 is 0x0000f2c0 or 0xf2c0 0x0000
339 Movt
= (*Instruction
<< 16) | (*(Instruction
+ 1));
341 // imm16 = imm4:i:imm3:imm8
342 // imm4 -> Bit19:Bit16
344 // imm3 -> Bit14:Bit12
346 Address
= (UINT16
)(Movt
& 0x000000ff); // imm8
347 Address
|= (UINT16
)((Movt
>> 4) & 0x0000f700); // imm4 imm3
348 Address
|= (((Movt
& BIT26
) != 0) ? BIT11
: 0); // i
354 Update an ARM MOVT or MOVW immediate instruction immediate data.
356 @param Instruction Pointer to ARM MOVT or MOVW immediate instruction
357 @param Address New addres to patch into the instruction
360 ThumbMovtImmediatePatch (
361 IN OUT UINT16
*Instruction
,
367 // First 16-bit chunk of instruciton
368 Patch
= ((Address
>> 12) & 0x000f); // imm4
369 Patch
|= (((Address
& BIT11
) != 0) ? BIT10
: 0); // i
370 *Instruction
= (*Instruction
& ~0x040f) | Patch
;
372 // Second 16-bit chunk of instruction
373 Patch
= Address
& 0x000000ff; // imm8
374 Patch
|= ((Address
<< 4) & 0x00007000); // imm3
376 *Instruction
= (*Instruction
& ~0x70ff) | Patch
;
380 Pass in a pointer to an ARM MOVW/MOVT instruciton pair and
381 return the immediate data encoded in the two` instruction
383 @param Instructions Pointer to ARM MOVW/MOVT insturction pair
385 @return Immediate address encoded in the instructions
390 ThumbMovwMovtImmediateAddress (
391 IN UINT16
*Instructions
397 Word
= Instructions
; // MOVW
398 Top
= Word
+ 2; // MOVT
400 return (ThumbMovtImmediateAddress (Top
) << 16) + ThumbMovtImmediateAddress (Word
);
405 Update an ARM MOVW/MOVT immediate instruction instruction pair.
407 @param Instructions Pointer to ARM MOVW/MOVT instruction pair
408 @param Address New addres to patch into the instructions
412 ThumbMovwMovtImmediatePatch (
413 IN OUT UINT16
*Instructions
,
420 Word
= (UINT16
*)Instructions
; // MOVW
421 Top
= Word
+ 2; // MOVT
423 ThumbMovtImmediatePatch (Word
, (UINT16
)(Address
& 0xffff));
424 ThumbMovtImmediatePatch (Top
, (UINT16
)(Address
>> 16));
429 Performs an ARM-based specific relocation fixup and is a no-op on other
432 @param Reloc Pointer to the relocation record.
433 @param Fixup Pointer to the address to fix up.
434 @param FixupData Pointer to a buffer to log the fixups.
435 @param Adjust The offset to adjust the fixup.
441 PeCoffLoaderRelocateArmImage (
444 IN OUT CHAR8
**FixupData
,
451 Fixup16
= (UINT16
*) Fixup
;
453 switch ((**Reloc
) >> 12) {
455 case EFI_IMAGE_REL_BASED_ARM_MOV32T
:
456 FixupVal
= ThumbMovwMovtImmediateAddress (Fixup16
) + (UINT32
)Adjust
;
457 ThumbMovwMovtImmediatePatch (Fixup16
, FixupVal
);
460 if (*FixupData
!= NULL
) {
461 *FixupData
= ALIGN_POINTER(*FixupData
, sizeof(UINT64
));
462 *(UINT64
*)(*FixupData
) = *Fixup16
;
463 CopyMem (*FixupData
, Fixup16
, sizeof (UINT64
));
467 case EFI_IMAGE_REL_BASED_ARM_MOV32A
:
468 // break omitted - ARM instruction encoding not implemented
470 return RETURN_UNSUPPORTED
;
473 return RETURN_SUCCESS
;