]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/BasePeCoffLib/Ipf/PeCoffLoaderEx.c
Initial import.
[mirror_edk2.git] / MdePkg / Library / BasePeCoffLib / Ipf / PeCoffLoaderEx.c
CommitLineData
878ddf1f 1/** @file\r
2 Fixes Intel Itanium(TM) specific relocation types.\r
3\r
4 Copyright (c) 2006, Intel Corporation\r
5 All rights reserved. This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13 Module Name: PeCoffLoaderEx.c\r
14\r
15**/\r
16\r
17\r
18\r
19\r
20\r
21#define EXT_IMM64(Value, Address, Size, InstPos, ValPos) \\r
22 Value |= (((UINT64)((*(Address) >> InstPos) & (((UINT64)1 << Size) - 1))) << ValPos)\r
23\r
24#define INS_IMM64(Value, Address, Size, InstPos, ValPos) \\r
25 *(UINT32*)Address = (*(UINT32*)Address & ~(((1 << Size) - 1) << InstPos)) | \\r
26 ((UINT32)((((UINT64)Value >> ValPos) & (((UINT64)1 << Size) - 1))) << InstPos)\r
27\r
28#define IMM64_IMM7B_INST_WORD_X 3 \r
29#define IMM64_IMM7B_SIZE_X 7 \r
30#define IMM64_IMM7B_INST_WORD_POS_X 4 \r
31#define IMM64_IMM7B_VAL_POS_X 0 \r
32\r
33#define IMM64_IMM9D_INST_WORD_X 3 \r
34#define IMM64_IMM9D_SIZE_X 9 \r
35#define IMM64_IMM9D_INST_WORD_POS_X 18 \r
36#define IMM64_IMM9D_VAL_POS_X 7 \r
37\r
38#define IMM64_IMM5C_INST_WORD_X 3 \r
39#define IMM64_IMM5C_SIZE_X 5 \r
40#define IMM64_IMM5C_INST_WORD_POS_X 13 \r
41#define IMM64_IMM5C_VAL_POS_X 16 \r
42\r
43#define IMM64_IC_INST_WORD_X 3 \r
44#define IMM64_IC_SIZE_X 1 \r
45#define IMM64_IC_INST_WORD_POS_X 12 \r
46#define IMM64_IC_VAL_POS_X 21 \r
47\r
48#define IMM64_IMM41a_INST_WORD_X 1 \r
49#define IMM64_IMM41a_SIZE_X 10 \r
50#define IMM64_IMM41a_INST_WORD_POS_X 14 \r
51#define IMM64_IMM41a_VAL_POS_X 22 \r
52\r
53#define IMM64_IMM41b_INST_WORD_X 1 \r
54#define IMM64_IMM41b_SIZE_X 8 \r
55#define IMM64_IMM41b_INST_WORD_POS_X 24 \r
56#define IMM64_IMM41b_VAL_POS_X 32 \r
57\r
58#define IMM64_IMM41c_INST_WORD_X 2 \r
59#define IMM64_IMM41c_SIZE_X 23 \r
60#define IMM64_IMM41c_INST_WORD_POS_X 0 \r
61#define IMM64_IMM41c_VAL_POS_X 40 \r
62\r
63#define IMM64_SIGN_INST_WORD_X 3 \r
64#define IMM64_SIGN_SIZE_X 1 \r
65#define IMM64_SIGN_INST_WORD_POS_X 27 \r
66#define IMM64_SIGN_VAL_POS_X 63 \r
67\r
68/**\r
69 Performs an Itanium-based specific relocation fixup.\r
70\r
71 @param Reloc Pointer to the relocation record.\r
72 \r
73 @param Fixup Pointer to the address to fix up.\r
74 \r
75 @param FixupData Pointer to a buffer to log the fixups.\r
76 \r
77 @param Adjust The offset to adjust the fixup.\r
78\r
79 @return Status code.\r
80\r
81**/\r
82RETURN_STATUS\r
83PeCoffLoaderRelocateImageEx (\r
84 IN UINT16 *Reloc,\r
85 IN OUT CHAR8 *Fixup, \r
86 IN OUT CHAR8 **FixupData,\r
87 IN UINT64 Adjust\r
88 )\r
89{\r
90 UINT64 *F64;\r
91 UINT64 FixupVal;\r
92\r
93 switch ((*Reloc) >> 12) {\r
94\r
95 case EFI_IMAGE_REL_BASED_DIR64:\r
96 F64 = (UINT64 *) Fixup;\r
97 *F64 = *F64 + (UINT64) Adjust;\r
98 if (*FixupData != NULL) {\r
99 *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64));\r
100 *(UINT64 *)(*FixupData) = *F64;\r
101 *FixupData = *FixupData + sizeof(UINT64);\r
102 }\r
103 break;\r
104\r
105 case EFI_IMAGE_REL_BASED_IA64_IMM64:\r
106\r
107 //\r
108 // Align it to bundle address before fixing up the\r
109 // 64-bit immediate value of the movl instruction.\r
110 //\r
111\r
112 Fixup = (CHAR8 *)((UINTN) Fixup & (UINTN) ~(15));\r
113 FixupVal = (UINT64)0;\r
114 \r
115 // \r
116 // Extract the lower 32 bits of IMM64 from bundle\r
117 //\r
118 EXT_IMM64(FixupVal,\r
119 (UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X,\r
120 IMM64_IMM7B_SIZE_X,\r
121 IMM64_IMM7B_INST_WORD_POS_X,\r
122 IMM64_IMM7B_VAL_POS_X\r
123 );\r
124\r
125 EXT_IMM64(FixupVal,\r
126 (UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X,\r
127 IMM64_IMM9D_SIZE_X,\r
128 IMM64_IMM9D_INST_WORD_POS_X,\r
129 IMM64_IMM9D_VAL_POS_X\r
130 );\r
131\r
132 EXT_IMM64(FixupVal,\r
133 (UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X,\r
134 IMM64_IMM5C_SIZE_X,\r
135 IMM64_IMM5C_INST_WORD_POS_X,\r
136 IMM64_IMM5C_VAL_POS_X\r
137 );\r
138\r
139 EXT_IMM64(FixupVal,\r
140 (UINT32 *)Fixup + IMM64_IC_INST_WORD_X,\r
141 IMM64_IC_SIZE_X,\r
142 IMM64_IC_INST_WORD_POS_X,\r
143 IMM64_IC_VAL_POS_X\r
144 );\r
145\r
146 EXT_IMM64(FixupVal,\r
147 (UINT32 *)Fixup + IMM64_IMM41a_INST_WORD_X,\r
148 IMM64_IMM41a_SIZE_X,\r
149 IMM64_IMM41a_INST_WORD_POS_X,\r
150 IMM64_IMM41a_VAL_POS_X\r
151 );\r
152 \r
153 // \r
154 // Update 64-bit address\r
155 //\r
156 FixupVal += Adjust;\r
157\r
158 // \r
159 // Insert IMM64 into bundle\r
160 //\r
161 INS_IMM64(FixupVal,\r
162 ((UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X),\r
163 IMM64_IMM7B_SIZE_X,\r
164 IMM64_IMM7B_INST_WORD_POS_X,\r
165 IMM64_IMM7B_VAL_POS_X\r
166 );\r
167\r
168 INS_IMM64(FixupVal,\r
169 ((UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X),\r
170 IMM64_IMM9D_SIZE_X,\r
171 IMM64_IMM9D_INST_WORD_POS_X,\r
172 IMM64_IMM9D_VAL_POS_X\r
173 );\r
174\r
175 INS_IMM64(FixupVal,\r
176 ((UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X),\r
177 IMM64_IMM5C_SIZE_X,\r
178 IMM64_IMM5C_INST_WORD_POS_X,\r
179 IMM64_IMM5C_VAL_POS_X\r
180 );\r
181\r
182 INS_IMM64(FixupVal,\r
183 ((UINT32 *)Fixup + IMM64_IC_INST_WORD_X),\r
184 IMM64_IC_SIZE_X,\r
185 IMM64_IC_INST_WORD_POS_X,\r
186 IMM64_IC_VAL_POS_X\r
187 );\r
188\r
189 INS_IMM64(FixupVal,\r
190 ((UINT32 *)Fixup + IMM64_IMM41a_INST_WORD_X),\r
191 IMM64_IMM41a_SIZE_X,\r
192 IMM64_IMM41a_INST_WORD_POS_X,\r
193 IMM64_IMM41a_VAL_POS_X\r
194 );\r
195\r
196 INS_IMM64(FixupVal,\r
197 ((UINT32 *)Fixup + IMM64_IMM41b_INST_WORD_X),\r
198 IMM64_IMM41b_SIZE_X,\r
199 IMM64_IMM41b_INST_WORD_POS_X,\r
200 IMM64_IMM41b_VAL_POS_X\r
201 );\r
202\r
203 INS_IMM64(FixupVal,\r
204 ((UINT32 *)Fixup + IMM64_IMM41c_INST_WORD_X),\r
205 IMM64_IMM41c_SIZE_X,\r
206 IMM64_IMM41c_INST_WORD_POS_X,\r
207 IMM64_IMM41c_VAL_POS_X\r
208 );\r
209\r
210 INS_IMM64(FixupVal,\r
211 ((UINT32 *)Fixup + IMM64_SIGN_INST_WORD_X),\r
212 IMM64_SIGN_SIZE_X,\r
213 IMM64_SIGN_INST_WORD_POS_X,\r
214 IMM64_SIGN_VAL_POS_X\r
215 );\r
216\r
217 F64 = (UINT64 *) Fixup;\r
218 if (*FixupData != NULL) {\r
219 *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64));\r
220 *(UINT64 *)(*FixupData) = *F64;\r
221 *FixupData = *FixupData + sizeof(UINT64);\r
222 }\r
223 break;\r
224\r
225 default:\r
226 return RETURN_UNSUPPORTED;\r
227 }\r
228\r
229 return RETURN_SUCCESS;\r
230}\r