]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Pei/Image/Image.c
Enable Nt32 platform boot to DXE phase.
[mirror_edk2.git] / MdeModulePkg / Core / Pei / Image / Image.c
CommitLineData
192f6d4c 1/*++\r
2\r
3Copyright (c) 2006 - 2007, 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 Image.c\r
15\r
16Abstract:\r
17\r
18 Pei Core Load Image Support\r
19\r
20--*/\r
21\r
22//\r
23// Include common header file for this module.\r
24//\r
25#include "CommonHeader.h"\r
26\r
27#include <PeiMain.h>\r
28\r
29\r
30\r
31EFI_STATUS\r
32PeiLoadImage (\r
33 IN EFI_PEI_SERVICES **PeiServices,\r
34 IN EFI_FFS_FILE_HEADER *PeimFileHeader,\r
35 OUT VOID **EntryPoint\r
36 )\r
37/*++\r
38\r
39Routine Description:\r
40\r
41 Routine for loading file image.\r
42\r
43Arguments:\r
44\r
45 PeiServices - The PEI core services table.\r
46 PeimFileHeader - Pointer to the FFS file header of the image.\r
47 EntryPoint - Pointer to entry point of specified image file for output.\r
48\r
49Returns:\r
50\r
51 Status - EFI_SUCCESS - Image is successfully loaded.\r
52 EFI_NOT_FOUND - Fail to locate necessary PPI\r
53 Others - Fail to load file.\r
54\r
55--*/\r
56{\r
57 EFI_STATUS Status;\r
58 VOID *Pe32Data;\r
59 EFI_PEI_FV_FILE_LOADER_PPI *FvLoadFilePpi;\r
60 EFI_PHYSICAL_ADDRESS ImageAddress;\r
61 UINT64 ImageSize;\r
62 EFI_PHYSICAL_ADDRESS ImageEntryPoint;\r
63 EFI_TE_IMAGE_HEADER *TEImageHeader;\r
64 UINT16 Machine;\r
65\r
66 *EntryPoint = NULL;\r
67 TEImageHeader = NULL;\r
68\r
69 //\r
70 // Try to find a PE32 section.\r
71 //\r
72 Status = PeiServicesFfsFindSectionData (\r
73 EFI_SECTION_PE32,\r
74 PeimFileHeader,\r
75 &Pe32Data\r
76 );\r
77 //\r
78 // If we didn't find a PE32 section, try to find a TE section.\r
79 //\r
80 if (EFI_ERROR (Status)) {\r
81 Status = PeiServicesFfsFindSectionData (\r
82 EFI_SECTION_TE,\r
83 PeimFileHeader,\r
84 (VOID **) &TEImageHeader\r
85 );\r
86 if (EFI_ERROR (Status) || TEImageHeader == NULL) {\r
87 //\r
88 // There was not a PE32 or a TE section, so assume that it's a Compressed section\r
89 // and use the LoadFile\r
90 //\r
91 Status = PeiServicesLocatePpi (\r
92 &gEfiPeiFvFileLoaderPpiGuid,\r
93 0,\r
94 NULL,\r
95 (VOID **)&FvLoadFilePpi\r
96 );\r
97 if (EFI_ERROR (Status)) {\r
98 return EFI_NOT_FOUND;\r
99 }\r
100\r
101 Status = FvLoadFilePpi->FvLoadFile (\r
102 FvLoadFilePpi,\r
103 PeimFileHeader,\r
104 &ImageAddress,\r
105 &ImageSize,\r
106 &ImageEntryPoint\r
107 );\r
108\r
109 if (EFI_ERROR (Status)) {\r
110 return EFI_NOT_FOUND;\r
111 }\r
112\r
113 //\r
114 // Got the entry point from ImageEntryPoint and ImageStartAddress\r
115 //\r
116 Pe32Data = (VOID *) ((UINTN) ImageAddress);\r
117 *EntryPoint = (VOID *) ((UINTN) ImageEntryPoint);\r
118 } else {\r
119 //\r
120 // Retrieve the entry point from the TE image header\r
121 //\r
122 ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) TEImageHeader;\r
123 *EntryPoint = (VOID *)((UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) +\r
124 TEImageHeader->AddressOfEntryPoint - TEImageHeader->StrippedSize);\r
125 }\r
126 } else {\r
127 //\r
128 // Retrieve the entry point from the PE/COFF image header\r
129 //\r
130 ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) Pe32Data;\r
131 Status = PeCoffLoaderGetEntryPoint (Pe32Data, EntryPoint);\r
132 if (EFI_ERROR (Status)) {\r
133 return EFI_NOT_FOUND;\r
134 }\r
135 }\r
136\r
137 if (((EFI_TE_IMAGE_HEADER *) (UINTN) ImageAddress)->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
138 TEImageHeader = (EFI_TE_IMAGE_HEADER *) (UINTN) ImageAddress;\r
139 Machine = TEImageHeader->Machine;\r
140 } else {\r
141 Machine = PeCoffLoaderGetMachineType (Pe32Data);\r
142 } \r
143 \r
144 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Machine)) {\r
145 return EFI_UNSUPPORTED; \r
146 }\r
147\r
148 //\r
149 // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi\r
150 //\r
151 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%08x EntryPoint=0x%08x ", (UINTN) ImageAddress, *EntryPoint));\r
152 DEBUG_CODE_BEGIN ();\r
153 EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry;\r
154 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;\r
155 UINTN DirCount;\r
156 UINTN Index;\r
157 UINTN Index1;\r
158 BOOLEAN FileNameFound;\r
159 CHAR8 *AsciiString;\r
160 CHAR8 AsciiBuffer[512];\r
161 VOID *CodeViewEntryPointer;\r
162 INTN TEImageAdjust;\r
163 EFI_IMAGE_DOS_HEADER *DosHeader;\r
164 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
165 UINT32 NumberOfRvaAndSizes;\r
166\r
167 Hdr.Pe32 = NULL;\r
168 if (TEImageHeader == NULL) {\r
169 DosHeader = (EFI_IMAGE_DOS_HEADER *)Pe32Data;\r
170 if (DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
171 //\r
172 // DOS image header is present, so read the PE header after the DOS image header\r
173 //\r
174 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)Pe32Data + (UINTN)((DosHeader->e_lfanew) & 0x0ffff));\r
175 } else {\r
176 //\r
177 // DOS image header is not present, so PE header is at the image base\r
178 //\r
179 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;\r
180 }\r
181 }\r
182\r
183 //\r
184 // Find the codeview info in the image and display the file name\r
185 // being loaded.\r
186 //\r
187 // Per the PE/COFF spec, you can't assume that a given data directory\r
188 // is present in the image. You have to check the NumberOfRvaAndSizes in\r
189 // the optional header to verify a desired directory entry is there.\r
190 //\r
191 DebugEntry = NULL;\r
192 DirectoryEntry = NULL;\r
193 NumberOfRvaAndSizes = 0;\r
194 TEImageAdjust = 0;\r
195 \r
196 if (TEImageHeader == NULL) {\r
197 if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
198 // \r
199 // Use PE32 offset get Debug Directory Entry\r
200 //\r
201 NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
202 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);\r
203 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress);\r
204 } else if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
205 // \r
206 // Use PE32+ offset get Debug Directory Entry\r
207 //\r
208 NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;\r
209 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);\r
210 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress);\r
211 }\r
212\r
213 if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
214 DirectoryEntry = NULL;\r
215 DebugEntry = NULL;\r
216 }\r
217 } else {\r
218 if (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) {\r
219 DirectoryEntry = &TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG];\r
220 TEImageAdjust = sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize;\r
221 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN) TEImageHeader +\r
222 TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress +\r
223 TEImageAdjust);\r
224 }\r
225 }\r
226\r
227 if (DebugEntry != NULL && DirectoryEntry != NULL) {\r
228 for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount += sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY), DebugEntry++) {\r
229 if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {\r
230 if (DebugEntry->SizeOfData > 0) {\r
231 CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + (UINTN) ImageAddress + (UINTN)TEImageAdjust);\r
232 switch (* (UINT32 *) CodeViewEntryPointer) {\r
233 case CODEVIEW_SIGNATURE_NB10:\r
234 AsciiString = (CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);\r
235 break;\r
236\r
237 case CODEVIEW_SIGNATURE_RSDS:\r
238 AsciiString = (CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);\r
239 break;\r
240\r
241 default:\r
242 AsciiString = NULL;\r
243 break;\r
244 }\r
245 if (AsciiString != NULL) {\r
246 FileNameFound = FALSE;\r
247 for (Index = 0, Index1 = 0; AsciiString[Index] != '\0'; Index++) {\r
248 if (AsciiString[Index] == '\\') {\r
249 Index1 = Index;\r
250 FileNameFound = TRUE;\r
251 }\r
252 }\r
253\r
254 if (FileNameFound) {\r
255 for (Index = Index1 + 1; AsciiString[Index] != '.'; Index++) {\r
256 AsciiBuffer[Index - (Index1 + 1)] = AsciiString[Index];\r
257 }\r
258 AsciiBuffer[Index - (Index1 + 1)] = 0;\r
259 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a.efi", AsciiBuffer));\r
260 break;\r
261 }\r
262 }\r
263 }\r
264 }\r
265 }\r
266 }\r
267 DEBUG_CODE_END ();\r
268\r
269 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n"));\r
270\r
271 return EFI_SUCCESS;\r
272}\r