• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Fixes Intel Itanium(TM) specific relocation types.
3 
4   Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
5   This program and the accompanying materials
6   are licensed and made available under the terms and conditions of the BSD License
7   which accompanies this distribution.  The full text of the license may be found at
8   http://opensource.org/licenses/bsd-license.php.
9 
10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include "BasePeCoffLibInternals.h"
16 
17 
18 
19 #define EXT_IMM64(Value, Address, Size, InstPos, ValPos)  \
20     Value |= (((UINT64)((*(Address) >> InstPos) & (((UINT64)1 << Size) - 1))) << ValPos)
21 
22 #define INS_IMM64(Value, Address, Size, InstPos, ValPos)  \
23     *(UINT32*)Address = (*(UINT32*)Address & ~(((1 << Size) - 1) << InstPos)) | \
24           ((UINT32)((((UINT64)Value >> ValPos) & (((UINT64)1 << Size) - 1))) << InstPos)
25 
26 #define IMM64_IMM7B_INST_WORD_X         3
27 #define IMM64_IMM7B_SIZE_X              7
28 #define IMM64_IMM7B_INST_WORD_POS_X     4
29 #define IMM64_IMM7B_VAL_POS_X           0
30 
31 #define IMM64_IMM9D_INST_WORD_X         3
32 #define IMM64_IMM9D_SIZE_X              9
33 #define IMM64_IMM9D_INST_WORD_POS_X     18
34 #define IMM64_IMM9D_VAL_POS_X           7
35 
36 #define IMM64_IMM5C_INST_WORD_X         3
37 #define IMM64_IMM5C_SIZE_X              5
38 #define IMM64_IMM5C_INST_WORD_POS_X     13
39 #define IMM64_IMM5C_VAL_POS_X           16
40 
41 #define IMM64_IC_INST_WORD_X            3
42 #define IMM64_IC_SIZE_X                 1
43 #define IMM64_IC_INST_WORD_POS_X        12
44 #define IMM64_IC_VAL_POS_X              21
45 
46 #define IMM64_IMM41A_INST_WORD_X        1
47 #define IMM64_IMM41A_SIZE_X             10
48 #define IMM64_IMM41A_INST_WORD_POS_X    14
49 #define IMM64_IMM41A_VAL_POS_X          22
50 
51 #define IMM64_IMM41B_INST_WORD_X        1
52 #define IMM64_IMM41B_SIZE_X             8
53 #define IMM64_IMM41B_INST_WORD_POS_X    24
54 #define IMM64_IMM41B_VAL_POS_X          32
55 
56 #define IMM64_IMM41C_INST_WORD_X        2
57 #define IMM64_IMM41C_SIZE_X             23
58 #define IMM64_IMM41C_INST_WORD_POS_X    0
59 #define IMM64_IMM41C_VAL_POS_X          40
60 
61 #define IMM64_SIGN_INST_WORD_X          3
62 #define IMM64_SIGN_SIZE_X               1
63 #define IMM64_SIGN_INST_WORD_POS_X      27
64 #define IMM64_SIGN_VAL_POS_X            63
65 
66 /**
67   Performs an Itanium-based specific relocation fixup.
68 
69   @param  Reloc       The pointer to the relocation record.
70   @param  Fixup       The pointer to the address to fix up.
71   @param  FixupData   The pointer to a buffer to log the fixups.
72   @param  Adjust      The offset to adjust the fixup.
73 
74   @retval RETURN_SUCCESS Succeed to fix the relocation entry.
75   @retval RETURN_UNSUPPOTED Unrecoganized relocation entry.
76 
77 **/
78 RETURN_STATUS
PeCoffLoaderRelocateImageEx(IN UINT16 * Reloc,IN OUT CHAR8 * Fixup,IN OUT CHAR8 ** FixupData,IN UINT64 Adjust)79 PeCoffLoaderRelocateImageEx (
80   IN UINT16      *Reloc,
81   IN OUT CHAR8   *Fixup,
82   IN OUT CHAR8   **FixupData,
83   IN UINT64      Adjust
84   )
85 {
86   UINT64      *Fixup64;
87   UINT64      FixupVal;
88 
89   switch ((*Reloc) >> 12) {
90     case EFI_IMAGE_REL_BASED_IA64_IMM64:
91 
92       //
93       // Align it to bundle address before fixing up the
94       // 64-bit immediate value of the movl instruction.
95       //
96 
97       Fixup = (CHAR8 *)((UINTN) Fixup & (UINTN) ~(15));
98       FixupVal = (UINT64)0;
99 
100       //
101       // Extract the lower 32 bits of IMM64 from bundle
102       //
103       EXT_IMM64(FixupVal,
104                 (UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X,
105                 IMM64_IMM7B_SIZE_X,
106                 IMM64_IMM7B_INST_WORD_POS_X,
107                 IMM64_IMM7B_VAL_POS_X
108                 );
109 
110       EXT_IMM64(FixupVal,
111                 (UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X,
112                 IMM64_IMM9D_SIZE_X,
113                 IMM64_IMM9D_INST_WORD_POS_X,
114                 IMM64_IMM9D_VAL_POS_X
115                 );
116 
117       EXT_IMM64(FixupVal,
118                 (UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X,
119                 IMM64_IMM5C_SIZE_X,
120                 IMM64_IMM5C_INST_WORD_POS_X,
121                 IMM64_IMM5C_VAL_POS_X
122                 );
123 
124       EXT_IMM64(FixupVal,
125                 (UINT32 *)Fixup + IMM64_IC_INST_WORD_X,
126                 IMM64_IC_SIZE_X,
127                 IMM64_IC_INST_WORD_POS_X,
128                 IMM64_IC_VAL_POS_X
129                 );
130 
131       EXT_IMM64(FixupVal,
132                 (UINT32 *)Fixup + IMM64_IMM41A_INST_WORD_X,
133                 IMM64_IMM41A_SIZE_X,
134                 IMM64_IMM41A_INST_WORD_POS_X,
135                 IMM64_IMM41A_VAL_POS_X
136                 );
137 
138       //
139       // Update 64-bit address
140       //
141       FixupVal += Adjust;
142 
143       //
144       // Insert IMM64 into bundle
145       //
146       INS_IMM64(FixupVal,
147                 ((UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X),
148                 IMM64_IMM7B_SIZE_X,
149                 IMM64_IMM7B_INST_WORD_POS_X,
150                 IMM64_IMM7B_VAL_POS_X
151                 );
152 
153       INS_IMM64(FixupVal,
154                 ((UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X),
155                 IMM64_IMM9D_SIZE_X,
156                 IMM64_IMM9D_INST_WORD_POS_X,
157                 IMM64_IMM9D_VAL_POS_X
158                 );
159 
160       INS_IMM64(FixupVal,
161                 ((UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X),
162                 IMM64_IMM5C_SIZE_X,
163                 IMM64_IMM5C_INST_WORD_POS_X,
164                 IMM64_IMM5C_VAL_POS_X
165                 );
166 
167       INS_IMM64(FixupVal,
168                 ((UINT32 *)Fixup + IMM64_IC_INST_WORD_X),
169                 IMM64_IC_SIZE_X,
170                 IMM64_IC_INST_WORD_POS_X,
171                 IMM64_IC_VAL_POS_X
172                 );
173 
174       INS_IMM64(FixupVal,
175                 ((UINT32 *)Fixup + IMM64_IMM41A_INST_WORD_X),
176                 IMM64_IMM41A_SIZE_X,
177                 IMM64_IMM41A_INST_WORD_POS_X,
178                 IMM64_IMM41A_VAL_POS_X
179                 );
180 
181       INS_IMM64(FixupVal,
182                 ((UINT32 *)Fixup + IMM64_IMM41B_INST_WORD_X),
183                 IMM64_IMM41B_SIZE_X,
184                 IMM64_IMM41B_INST_WORD_POS_X,
185                 IMM64_IMM41B_VAL_POS_X
186                 );
187 
188       INS_IMM64(FixupVal,
189                 ((UINT32 *)Fixup + IMM64_IMM41C_INST_WORD_X),
190                 IMM64_IMM41C_SIZE_X,
191                 IMM64_IMM41C_INST_WORD_POS_X,
192                 IMM64_IMM41C_VAL_POS_X
193                 );
194 
195       INS_IMM64(FixupVal,
196                 ((UINT32 *)Fixup + IMM64_SIGN_INST_WORD_X),
197                 IMM64_SIGN_SIZE_X,
198                 IMM64_SIGN_INST_WORD_POS_X,
199                 IMM64_SIGN_VAL_POS_X
200                 );
201 
202       Fixup64 = (UINT64 *) Fixup;
203       if (*FixupData != NULL) {
204         *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64));
205         *(UINT64 *)(*FixupData) = *Fixup64;
206         *FixupData = *FixupData + sizeof(UINT64);
207       }
208       break;
209 
210     default:
211       return RETURN_UNSUPPORTED;
212   }
213 
214   return RETURN_SUCCESS;
215 }
216 
217 /**
218   Returns TRUE if the machine type of PE/COFF image is supported. Supported
219   does not mean the image can be executed it means the PE/COFF loader supports
220   loading and relocating of the image type. It's up to the caller to support
221   the entry point.
222 
223   The itanium version PE/COFF loader/relocater supports itanium and EBC image.
224 
225   @param  Machine   Machine type from the PE Header.
226 
227   @return TRUE if this PE/COFF loader can load the image
228   @return FALSE unrecoganized machine type of image.
229 
230 **/
231 BOOLEAN
PeCoffLoaderImageFormatSupported(IN UINT16 Machine)232 PeCoffLoaderImageFormatSupported (
233   IN  UINT16  Machine
234   )
235 {
236   if ((Machine == IMAGE_FILE_MACHINE_IA64) || (Machine == IMAGE_FILE_MACHINE_EBC)) {
237     return TRUE;
238   }
239 
240   return FALSE;
241 }
242 
243 
244 /**
245   ImageRead function that operates on a memory buffer whos base is passed into
246   FileHandle.
247 
248   @param  Reloc             Ponter to baes of the input stream
249   @param  Fixup             Offset to the start of the buffer
250   @param  FixupData         The number of bytes to copy into the buffer
251   @param  Adjust            Location to place results of read
252 
253   @retval RETURN_SUCCESS    Data is read from FileOffset from the Handle into
254                             the buffer.
255   @retval RETURN_UNSUPPORTED Un-recoganized relocation entry
256                              type.
257 **/
258 RETURN_STATUS
PeHotRelocateImageEx(IN UINT16 * Reloc,IN OUT CHAR8 * Fixup,IN OUT CHAR8 ** FixupData,IN UINT64 Adjust)259 PeHotRelocateImageEx (
260   IN UINT16      *Reloc,
261   IN OUT CHAR8   *Fixup,
262   IN OUT CHAR8   **FixupData,
263   IN UINT64      Adjust
264   )
265 {
266   UINT64  *Fixup64;
267   UINT64  FixupVal;
268 
269   switch ((*Reloc) >> 12) {
270   case EFI_IMAGE_REL_BASED_DIR64:
271     Fixup64     = (UINT64 *) Fixup;
272     *FixupData  = ALIGN_POINTER (*FixupData, sizeof (UINT64));
273     if (*(UINT64 *) (*FixupData) == *Fixup64) {
274       *Fixup64 = *Fixup64 + (UINT64) Adjust;
275     }
276 
277     *FixupData = *FixupData + sizeof (UINT64);
278     break;
279 
280   case EFI_IMAGE_REL_BASED_IA64_IMM64:
281     Fixup64     = (UINT64 *) Fixup;
282     *FixupData  = ALIGN_POINTER (*FixupData, sizeof (UINT64));
283     if (*(UINT64 *) (*FixupData) == *Fixup64) {
284       //
285       // Align it to bundle address before fixing up the
286       // 64-bit immediate value of the movl instruction.
287       //
288       //
289       Fixup     = (CHAR8 *) ((UINT64) Fixup & (UINT64)~(15));
290       FixupVal  = (UINT64) 0;
291 
292       //
293       // Extract the lower 32 bits of IMM64 from bundle
294       //
295       EXT_IMM64 (
296         FixupVal,
297         (UINT32 *) Fixup + IMM64_IMM7B_INST_WORD_X,
298         IMM64_IMM7B_SIZE_X,
299         IMM64_IMM7B_INST_WORD_POS_X,
300         IMM64_IMM7B_VAL_POS_X
301         );
302 
303       EXT_IMM64 (
304         FixupVal,
305         (UINT32 *) Fixup + IMM64_IMM9D_INST_WORD_X,
306         IMM64_IMM9D_SIZE_X,
307         IMM64_IMM9D_INST_WORD_POS_X,
308         IMM64_IMM9D_VAL_POS_X
309         );
310 
311       EXT_IMM64 (
312         FixupVal,
313         (UINT32 *) Fixup + IMM64_IMM5C_INST_WORD_X,
314         IMM64_IMM5C_SIZE_X,
315         IMM64_IMM5C_INST_WORD_POS_X,
316         IMM64_IMM5C_VAL_POS_X
317         );
318 
319       EXT_IMM64 (
320         FixupVal,
321         (UINT32 *) Fixup + IMM64_IC_INST_WORD_X,
322         IMM64_IC_SIZE_X,
323         IMM64_IC_INST_WORD_POS_X,
324         IMM64_IC_VAL_POS_X
325         );
326 
327       EXT_IMM64 (
328         FixupVal,
329         (UINT32 *) Fixup + IMM64_IMM41A_INST_WORD_X,
330         IMM64_IMM41A_SIZE_X,
331         IMM64_IMM41A_INST_WORD_POS_X,
332         IMM64_IMM41A_VAL_POS_X
333         );
334 
335       //
336       // Update 64-bit address
337       //
338       FixupVal += Adjust;
339 
340       //
341       // Insert IMM64 into bundle
342       //
343       INS_IMM64 (
344         FixupVal,
345         ((UINT32 *) Fixup + IMM64_IMM7B_INST_WORD_X),
346         IMM64_IMM7B_SIZE_X,
347         IMM64_IMM7B_INST_WORD_POS_X,
348         IMM64_IMM7B_VAL_POS_X
349         );
350 
351       INS_IMM64 (
352         FixupVal,
353         ((UINT32 *) Fixup + IMM64_IMM9D_INST_WORD_X),
354         IMM64_IMM9D_SIZE_X,
355         IMM64_IMM9D_INST_WORD_POS_X,
356         IMM64_IMM9D_VAL_POS_X
357         );
358 
359       INS_IMM64 (
360         FixupVal,
361         ((UINT32 *) Fixup + IMM64_IMM5C_INST_WORD_X),
362         IMM64_IMM5C_SIZE_X,
363         IMM64_IMM5C_INST_WORD_POS_X,
364         IMM64_IMM5C_VAL_POS_X
365         );
366 
367       INS_IMM64 (
368         FixupVal,
369         ((UINT32 *) Fixup + IMM64_IC_INST_WORD_X),
370         IMM64_IC_SIZE_X,
371         IMM64_IC_INST_WORD_POS_X,
372         IMM64_IC_VAL_POS_X
373         );
374 
375       INS_IMM64 (
376         FixupVal,
377         ((UINT32 *) Fixup + IMM64_IMM41A_INST_WORD_X),
378         IMM64_IMM41A_SIZE_X,
379         IMM64_IMM41A_INST_WORD_POS_X,
380         IMM64_IMM41A_VAL_POS_X
381         );
382 
383       INS_IMM64 (
384         FixupVal,
385         ((UINT32 *) Fixup + IMM64_IMM41B_INST_WORD_X),
386         IMM64_IMM41B_SIZE_X,
387         IMM64_IMM41B_INST_WORD_POS_X,
388         IMM64_IMM41B_VAL_POS_X
389         );
390 
391       INS_IMM64 (
392         FixupVal,
393         ((UINT32 *) Fixup + IMM64_IMM41C_INST_WORD_X),
394         IMM64_IMM41C_SIZE_X,
395         IMM64_IMM41C_INST_WORD_POS_X,
396         IMM64_IMM41C_VAL_POS_X
397         );
398 
399       INS_IMM64 (
400         FixupVal,
401         ((UINT32 *) Fixup + IMM64_SIGN_INST_WORD_X),
402         IMM64_SIGN_SIZE_X,
403         IMM64_SIGN_INST_WORD_POS_X,
404         IMM64_SIGN_VAL_POS_X
405         );
406 
407       *(UINT64 *) (*FixupData) = *Fixup64;
408     }
409 
410     *FixupData = *FixupData + sizeof (UINT64);
411     break;
412 
413   default:
414     DEBUG ((EFI_D_ERROR, "PeHotRelocateEx:unknown fixed type\n"));
415     return RETURN_UNSUPPORTED;
416   }
417 
418   return RETURN_SUCCESS;
419 }
420 
421 
422 
423