3 Copyright (c) 2006, 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
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.
25 RuntimePeImageAddress (
26 IN RUNTIME_IMAGE_RELOCATION_DATA
*Image
,
33 Converts an image address to the loaded address
37 Image - The relocation data of the image being loaded
39 Address - The address to be converted to the loaded address
43 NULL if the address can not be converted, otherwise, the converted address
47 if (Address
>= (Image
->ImageSize
) << EFI_PAGE_SHIFT
) {
51 return (CHAR8
*) ((UINTN
) Image
->ImageBase
+ Address
);
55 RelocatePeImageForRuntime (
56 RUNTIME_IMAGE_RELOCATION_DATA
*Image
61 EFI_IMAGE_DOS_HEADER
*DosHdr
;
62 EFI_IMAGE_NT_HEADERS
*PeHdr
;
63 UINT32 NumberOfRvaAndSizes
;
64 EFI_IMAGE_DATA_DIRECTORY
*DataDirectory
;
65 EFI_IMAGE_DATA_DIRECTORY
*RelocDir
;
66 EFI_IMAGE_BASE_RELOCATION
*RelocBase
;
67 EFI_IMAGE_BASE_RELOCATION
*RelocBaseEnd
;
78 OldBase
= (CHAR8
*) ((UINTN
) Image
->ImageBase
);
79 NewBase
= (CHAR8
*) ((UINTN
) Image
->ImageBase
);
81 Status
= RuntimeDriverConvertPointer (0, (VOID
**) &NewBase
);
82 ASSERT_EFI_ERROR (Status
);
84 Adjust
= (UINTN
) NewBase
- (UINTN
) OldBase
;
87 // Find the image's relocate dir info
89 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) OldBase
;
90 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
92 // Valid DOS header so get address of PE header
94 PeHdr
= (EFI_IMAGE_NT_HEADERS
*) (((CHAR8
*) DosHdr
) + DosHdr
->e_lfanew
);
97 // No Dos header so assume image starts with PE header.
99 PeHdr
= (EFI_IMAGE_NT_HEADERS
*) OldBase
;
102 if (PeHdr
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
104 // Not a valid PE image so Exit
109 // Get some data from the PE type dependent data
111 NumberOfRvaAndSizes
= PeHdr
->OptionalHeader
.NumberOfRvaAndSizes
;
112 DataDirectory
= &PeHdr
->OptionalHeader
.DataDirectory
[0];
115 // Find the relocation block
117 // Per the PE/COFF spec, you can't assume that a given data directory
118 // is present in the image. You have to check the NumberOfRvaAndSizes in
119 // the optional header to verify a desired directory entry is there.
121 if (NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
122 RelocDir
= DataDirectory
+ EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
;
123 RelocBase
= RuntimePeImageAddress (Image
, RelocDir
->VirtualAddress
);
124 RelocBaseEnd
= RuntimePeImageAddress (Image
, RelocDir
->VirtualAddress
+ RelocDir
->Size
);
127 // Cannot find relocations, cannot continue
133 ASSERT (RelocBase
!= NULL
&& RelocBaseEnd
!= NULL
);
136 // Run the whole relocation block. And re-fixup data that has not been
137 // modified. The FixupData is used to see if the image has been modified
138 // since it was relocated. This is so data sections that have been updated
139 // by code will not be fixed up, since that would set them back to
142 FixupData
= Image
->RelocationData
;
143 while (RelocBase
< RelocBaseEnd
) {
145 Reloc
= (UINT16
*) ((UINT8
*) RelocBase
+ sizeof (EFI_IMAGE_BASE_RELOCATION
));
146 RelocEnd
= (UINT16
*) ((UINT8
*) RelocBase
+ RelocBase
->SizeOfBlock
);
147 FixupBase
= (CHAR8
*) ((UINTN
) Image
->ImageBase
) + RelocBase
->VirtualAddress
;
150 // Run this relocation record
152 while (Reloc
< RelocEnd
) {
154 Fixup
= FixupBase
+ (*Reloc
& 0xFFF);
155 switch ((*Reloc
) >> 12) {
157 case EFI_IMAGE_REL_BASED_ABSOLUTE
:
160 case EFI_IMAGE_REL_BASED_HIGH
:
161 F16
= (UINT16
*) Fixup
;
162 if (*(UINT16
*) FixupData
== *F16
) {
163 *F16
= (UINT16
) ((*F16
<< 16) + ((UINT16
) Adjust
& 0xffff));
166 FixupData
= FixupData
+ sizeof (UINT16
);
169 case EFI_IMAGE_REL_BASED_LOW
:
170 F16
= (UINT16
*) Fixup
;
171 if (*(UINT16
*) FixupData
== *F16
) {
172 *F16
= (UINT16
) (*F16
+ ((UINT16
) Adjust
& 0xffff));
175 FixupData
= FixupData
+ sizeof (UINT16
);
178 case EFI_IMAGE_REL_BASED_HIGHLOW
:
179 F32
= (UINT32
*) Fixup
;
180 FixupData
= ALIGN_POINTER (FixupData
, sizeof (UINT32
));
181 if (*(UINT32
*) FixupData
== *F32
) {
182 *F32
= *F32
+ (UINT32
) Adjust
;
185 FixupData
= FixupData
+ sizeof (UINT32
);
188 case EFI_IMAGE_REL_BASED_HIGHADJ
:
190 // Not implemented, but not used in EFI 1.0
197 // Only Itanium requires ConvertPeImage_Ex
199 Status
= PeHotRelocateImageEx (Reloc
, Fixup
, &FixupData
, Adjust
);
200 if (EFI_ERROR (Status
)) {
205 // Next relocation record
212 RelocBase
= (EFI_IMAGE_BASE_RELOCATION
*) RelocEnd
;
215 FlushCpuCache (Image
->ImageBase
, (UINT64
) Image
->ImageSize
);