]> git.proxmox.com Git - mirror_edk2.git/blob - Tools/Source/TianoTools/GenFvImage/Ipf/PeCoffLoaderEx.c
2a58a62f6d2aa8ddf2a3aec7888bbaeae53e4271
[mirror_edk2.git] / Tools / Source / TianoTools / GenFvImage / Ipf / PeCoffLoaderEx.c
1 /*++
2
3 Copyright (c) 2004, Intel Corporation
4 All rights reserved. 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
8
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.
11
12 Module Name:
13
14 PeCoffLoaderEx.c
15
16 Abstract:
17
18 Fixes Intel Itanium(TM) specific relocation types
19
20
21 Revision History
22
23 --*/
24
25 #define EFI_SPECIFICATION_VERSION 0x00000000
26 #define EDK_RELEASE_VERSION 0x00020000
27 #include <Base.h>
28 #include <Library/PeCoffLib.h>
29 #include <Library/BaseMemoryLib.h>
30
31
32
33
34
35 #define EXT_IMM64(Value, Address, Size, InstPos, ValPos) \
36 Value |= (((UINT64)((*(Address) >> InstPos) & (((UINT64)1 << Size) - 1))) << ValPos)
37
38 #define INS_IMM64(Value, Address, Size, InstPos, ValPos) \
39 *(UINT32*)Address = (*(UINT32*)Address & ~(((1 << Size) - 1) << InstPos)) | \
40 ((UINT32)((((UINT64)Value >> ValPos) & (((UINT64)1 << Size) - 1))) << InstPos)
41
42 #define IMM64_IMM7B_INST_WORD_X 3
43 #define IMM64_IMM7B_SIZE_X 7
44 #define IMM64_IMM7B_INST_WORD_POS_X 4
45 #define IMM64_IMM7B_VAL_POS_X 0
46
47 #define IMM64_IMM9D_INST_WORD_X 3
48 #define IMM64_IMM9D_SIZE_X 9
49 #define IMM64_IMM9D_INST_WORD_POS_X 18
50 #define IMM64_IMM9D_VAL_POS_X 7
51
52 #define IMM64_IMM5C_INST_WORD_X 3
53 #define IMM64_IMM5C_SIZE_X 5
54 #define IMM64_IMM5C_INST_WORD_POS_X 13
55 #define IMM64_IMM5C_VAL_POS_X 16
56
57 #define IMM64_IC_INST_WORD_X 3
58 #define IMM64_IC_SIZE_X 1
59 #define IMM64_IC_INST_WORD_POS_X 12
60 #define IMM64_IC_VAL_POS_X 21
61
62 #define IMM64_IMM41a_INST_WORD_X 1
63 #define IMM64_IMM41a_SIZE_X 10
64 #define IMM64_IMM41a_INST_WORD_POS_X 14
65 #define IMM64_IMM41a_VAL_POS_X 22
66
67 #define IMM64_IMM41b_INST_WORD_X 1
68 #define IMM64_IMM41b_SIZE_X 8
69 #define IMM64_IMM41b_INST_WORD_POS_X 24
70 #define IMM64_IMM41b_VAL_POS_X 32
71
72 #define IMM64_IMM41c_INST_WORD_X 2
73 #define IMM64_IMM41c_SIZE_X 23
74 #define IMM64_IMM41c_INST_WORD_POS_X 0
75 #define IMM64_IMM41c_VAL_POS_X 40
76
77 #define IMM64_SIGN_INST_WORD_X 3
78 #define IMM64_SIGN_SIZE_X 1
79 #define IMM64_SIGN_INST_WORD_POS_X 27
80 #define IMM64_SIGN_VAL_POS_X 63
81
82 RETURN_STATUS
83 PeCoffLoaderRelocateImageEx (
84 IN UINT16 *Reloc,
85 IN OUT CHAR8 *Fixup,
86 IN OUT CHAR8 **FixupData,
87 IN UINT64 Adjust
88 )
89 /*++
90
91 Routine Description:
92
93 Performs an Itanium-based specific relocation fixup
94
95 Arguments:
96
97 Reloc - Pointer to the relocation record
98
99 Fixup - Pointer to the address to fix up
100
101 FixupData - Pointer to a buffer to log the fixups
102
103 Adjust - The offset to adjust the fixup
104
105 Returns:
106
107 Status code
108
109 --*/
110 {
111 UINT64 *F64;
112 UINT64 FixupVal;
113
114 switch ((*Reloc) >> 12) {
115
116 case EFI_IMAGE_REL_BASED_DIR64:
117 F64 = (UINT64 *) Fixup;
118 *F64 = *F64 + (UINT64) Adjust;
119 if (*FixupData != NULL) {
120 *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64));
121 *(UINT64 *)(*FixupData) = *F64;
122 *FixupData = *FixupData + sizeof(UINT64);
123 }
124 break;
125
126 case EFI_IMAGE_REL_BASED_IA64_IMM64:
127
128 //
129 // Align it to bundle address before fixing up the
130 // 64-bit immediate value of the movl instruction.
131 //
132
133 Fixup = (CHAR8 *)((UINTN) Fixup & (UINTN) ~(15));
134 FixupVal = (UINT64)0;
135
136 //
137 // Extract the lower 32 bits of IMM64 from bundle
138 //
139 EXT_IMM64(FixupVal,
140 (UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X,
141 IMM64_IMM7B_SIZE_X,
142 IMM64_IMM7B_INST_WORD_POS_X,
143 IMM64_IMM7B_VAL_POS_X
144 );
145
146 EXT_IMM64(FixupVal,
147 (UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X,
148 IMM64_IMM9D_SIZE_X,
149 IMM64_IMM9D_INST_WORD_POS_X,
150 IMM64_IMM9D_VAL_POS_X
151 );
152
153 EXT_IMM64(FixupVal,
154 (UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X,
155 IMM64_IMM5C_SIZE_X,
156 IMM64_IMM5C_INST_WORD_POS_X,
157 IMM64_IMM5C_VAL_POS_X
158 );
159
160 EXT_IMM64(FixupVal,
161 (UINT32 *)Fixup + IMM64_IC_INST_WORD_X,
162 IMM64_IC_SIZE_X,
163 IMM64_IC_INST_WORD_POS_X,
164 IMM64_IC_VAL_POS_X
165 );
166
167 EXT_IMM64(FixupVal,
168 (UINT32 *)Fixup + IMM64_IMM41a_INST_WORD_X,
169 IMM64_IMM41a_SIZE_X,
170 IMM64_IMM41a_INST_WORD_POS_X,
171 IMM64_IMM41a_VAL_POS_X
172 );
173
174 //
175 // Update 64-bit address
176 //
177 FixupVal += Adjust;
178
179 //
180 // Insert IMM64 into bundle
181 //
182 INS_IMM64(FixupVal,
183 ((UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X),
184 IMM64_IMM7B_SIZE_X,
185 IMM64_IMM7B_INST_WORD_POS_X,
186 IMM64_IMM7B_VAL_POS_X
187 );
188
189 INS_IMM64(FixupVal,
190 ((UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X),
191 IMM64_IMM9D_SIZE_X,
192 IMM64_IMM9D_INST_WORD_POS_X,
193 IMM64_IMM9D_VAL_POS_X
194 );
195
196 INS_IMM64(FixupVal,
197 ((UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X),
198 IMM64_IMM5C_SIZE_X,
199 IMM64_IMM5C_INST_WORD_POS_X,
200 IMM64_IMM5C_VAL_POS_X
201 );
202
203 INS_IMM64(FixupVal,
204 ((UINT32 *)Fixup + IMM64_IC_INST_WORD_X),
205 IMM64_IC_SIZE_X,
206 IMM64_IC_INST_WORD_POS_X,
207 IMM64_IC_VAL_POS_X
208 );
209
210 INS_IMM64(FixupVal,
211 ((UINT32 *)Fixup + IMM64_IMM41a_INST_WORD_X),
212 IMM64_IMM41a_SIZE_X,
213 IMM64_IMM41a_INST_WORD_POS_X,
214 IMM64_IMM41a_VAL_POS_X
215 );
216
217 INS_IMM64(FixupVal,
218 ((UINT32 *)Fixup + IMM64_IMM41b_INST_WORD_X),
219 IMM64_IMM41b_SIZE_X,
220 IMM64_IMM41b_INST_WORD_POS_X,
221 IMM64_IMM41b_VAL_POS_X
222 );
223
224 INS_IMM64(FixupVal,
225 ((UINT32 *)Fixup + IMM64_IMM41c_INST_WORD_X),
226 IMM64_IMM41c_SIZE_X,
227 IMM64_IMM41c_INST_WORD_POS_X,
228 IMM64_IMM41c_VAL_POS_X
229 );
230
231 INS_IMM64(FixupVal,
232 ((UINT32 *)Fixup + IMM64_SIGN_INST_WORD_X),
233 IMM64_SIGN_SIZE_X,
234 IMM64_SIGN_INST_WORD_POS_X,
235 IMM64_SIGN_VAL_POS_X
236 );
237
238 F64 = (UINT64 *) Fixup;
239 if (*FixupData != NULL) {
240 *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64));
241 *(UINT64 *)(*FixupData) = *F64;
242 *FixupData = *FixupData + sizeof(UINT64);
243 }
244 break;
245
246 default:
247 return RETURN_UNSUPPORTED;
248 }
249
250 return RETURN_SUCCESS;
251 }