]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Universal/Runtime/RuntimeDxe/PeHotRelocate.c
Fix capitalization
[mirror_edk2.git] / EdkModulePkg / Universal / Runtime / RuntimeDxe / PeHotRelocate.c
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 PeHotRelocate.c\r
15\r
16Abstract:\r
17\r
18\r
19--*/\r
20\r
21#include "Runtime.h"\r
22\r
23STATIC\r
24VOID *\r
25RuntimePeImageAddress (\r
26 IN RUNTIME_IMAGE_RELOCATION_DATA *Image,\r
27 IN UINTN Address\r
28 )\r
29/*++\r
30\r
31Routine Description:\r
32\r
33 Converts an image address to the loaded address\r
34\r
35Arguments:\r
36\r
37 Image - The relocation data of the image being loaded\r
38\r
39 Address - The address to be converted to the loaded address\r
40\r
41Returns:\r
42\r
43 NULL if the address can not be converted, otherwise, the converted address\r
44\r
45--*/\r
46{\r
47 if (Address >= (Image->ImageSize) << EFI_PAGE_SHIFT) {\r
48 return NULL;\r
49 }\r
50\r
51 return (CHAR8 *) ((UINTN) Image->ImageBase + Address);\r
52}\r
53\r
54VOID\r
55RelocatePeImageForRuntime (\r
56 RUNTIME_IMAGE_RELOCATION_DATA *Image\r
57 )\r
58{\r
59 CHAR8 *OldBase;\r
60 CHAR8 *NewBase;\r
61 EFI_IMAGE_DOS_HEADER *DosHdr;\r
62 EFI_IMAGE_NT_HEADERS *PeHdr;\r
63 UINT32 NumberOfRvaAndSizes;\r
64 EFI_IMAGE_DATA_DIRECTORY *DataDirectory;\r
65 EFI_IMAGE_DATA_DIRECTORY *RelocDir;\r
66 EFI_IMAGE_BASE_RELOCATION *RelocBase;\r
67 EFI_IMAGE_BASE_RELOCATION *RelocBaseEnd;\r
68 UINT16 *Reloc;\r
69 UINT16 *RelocEnd;\r
70 CHAR8 *Fixup;\r
71 CHAR8 *FixupBase;\r
72 UINT16 *F16;\r
73 UINT32 *F32;\r
74 CHAR8 *FixupData;\r
75 UINTN Adjust;\r
76 EFI_STATUS Status;\r
77\r
78 OldBase = (CHAR8 *) ((UINTN) Image->ImageBase);\r
79 NewBase = (CHAR8 *) ((UINTN) Image->ImageBase);\r
80\r
81 Status = RuntimeDriverConvertPointer (0, (VOID **) &NewBase);\r
82 ASSERT_EFI_ERROR (Status);\r
83\r
84 Adjust = (UINTN) NewBase - (UINTN) OldBase;\r
85\r
86 //\r
87 // Find the image's relocate dir info\r
88 //\r
89 DosHdr = (EFI_IMAGE_DOS_HEADER *) OldBase;\r
90 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
91 //\r
92 // Valid DOS header so get address of PE header\r
93 //\r
94 PeHdr = (EFI_IMAGE_NT_HEADERS *) (((CHAR8 *) DosHdr) + DosHdr->e_lfanew);\r
95 } else {\r
96 //\r
97 // No Dos header so assume image starts with PE header.\r
98 //\r
99 PeHdr = (EFI_IMAGE_NT_HEADERS *) OldBase;\r
100 }\r
101\r
102 if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
103 //\r
104 // Not a valid PE image so Exit\r
105 //\r
106 return ;\r
107 }\r
108 //\r
109 // Get some data from the PE type dependent data\r
110 //\r
111 NumberOfRvaAndSizes = PeHdr->OptionalHeader.NumberOfRvaAndSizes;\r
112 DataDirectory = &PeHdr->OptionalHeader.DataDirectory[0];\r
113\r
114 //\r
115 // Find the relocation block\r
116 //\r
117 // Per the PE/COFF spec, you can't assume that a given data directory\r
118 // is present in the image. You have to check the NumberOfRvaAndSizes in\r
119 // the optional header to verify a desired directory entry is there.\r
120 //\r
121 if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
122 RelocDir = DataDirectory + EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC;\r
123 RelocBase = RuntimePeImageAddress (Image, RelocDir->VirtualAddress);\r
124 RelocBaseEnd = RuntimePeImageAddress (Image, RelocDir->VirtualAddress + RelocDir->Size);\r
125 } else {\r
126 //\r
127 // Cannot find relocations, cannot continue\r
128 //\r
129 ASSERT (FALSE);\r
130 return ;\r
131 }\r
132\r
133 ASSERT (RelocBase != NULL && RelocBaseEnd != NULL);\r
134\r
135 //\r
136 // Run the whole relocation block. And re-fixup data that has not been\r
137 // modified. The FixupData is used to see if the image has been modified\r
138 // since it was relocated. This is so data sections that have been updated\r
139 // by code will not be fixed up, since that would set them back to\r
140 // defaults.\r
141 //\r
142 FixupData = Image->RelocationData;\r
143 while (RelocBase < RelocBaseEnd) {\r
144\r
145 Reloc = (UINT16 *) ((UINT8 *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION));\r
146 RelocEnd = (UINT16 *) ((UINT8 *) RelocBase + RelocBase->SizeOfBlock);\r
147 FixupBase = (CHAR8 *) ((UINTN) Image->ImageBase) + RelocBase->VirtualAddress;\r
148\r
149 //\r
150 // Run this relocation record\r
151 //\r
152 while (Reloc < RelocEnd) {\r
153\r
154 Fixup = FixupBase + (*Reloc & 0xFFF);\r
155 switch ((*Reloc) >> 12) {\r
156\r
157 case EFI_IMAGE_REL_BASED_ABSOLUTE:\r
158 break;\r
159\r
160 case EFI_IMAGE_REL_BASED_HIGH:\r
161 F16 = (UINT16 *) Fixup;\r
162 if (*(UINT16 *) FixupData == *F16) {\r
163 *F16 = (UINT16) ((*F16 << 16) + ((UINT16) Adjust & 0xffff));\r
164 }\r
165\r
166 FixupData = FixupData + sizeof (UINT16);\r
167 break;\r
168\r
169 case EFI_IMAGE_REL_BASED_LOW:\r
170 F16 = (UINT16 *) Fixup;\r
171 if (*(UINT16 *) FixupData == *F16) {\r
172 *F16 = (UINT16) (*F16 + ((UINT16) Adjust & 0xffff));\r
173 }\r
174\r
175 FixupData = FixupData + sizeof (UINT16);\r
176 break;\r
177\r
178 case EFI_IMAGE_REL_BASED_HIGHLOW:\r
179 F32 = (UINT32 *) Fixup;\r
180 FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32));\r
181 if (*(UINT32 *) FixupData == *F32) {\r
182 *F32 = *F32 + (UINT32) Adjust;\r
183 }\r
184\r
185 FixupData = FixupData + sizeof (UINT32);\r
186 break;\r
187\r
188 case EFI_IMAGE_REL_BASED_HIGHADJ:\r
189 //\r
190 // Not implemented, but not used in EFI 1.0\r
191 //\r
192 ASSERT (FALSE);\r
193 break;\r
194\r
195 default:\r
196 //\r
197 // Only Itanium requires ConvertPeImage_Ex\r
198 //\r
199 Status = PeHotRelocateImageEx (Reloc, Fixup, &FixupData, Adjust);\r
200 if (EFI_ERROR (Status)) {\r
201 return ;\r
202 }\r
203 }\r
204 //\r
205 // Next relocation record\r
206 //\r
207 Reloc += 1;\r
208 }\r
209 //\r
210 // next reloc block\r
211 //\r
212 RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd;\r
213 }\r
214\r
215 FlushCpuCache (Image->ImageBase, (UINT64) Image->ImageSize);\r
216}\r