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