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