]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Core/Pei/Image/Image.c
1. PEI core needs to check image machine type
[mirror_edk2.git] / EdkModulePkg / Core / Pei / Image / Image.c
CommitLineData
a0b7c09f 1/*++\r
2\r
a8b194b9 3Copyright (c) 2006 - 2007, Intel Corporation \r
a0b7c09f 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#include <PeiMain.h>\r
23\r
2ce31132 24\r
25\r
a0b7c09f 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
a0b7c09f 55 EFI_PHYSICAL_ADDRESS ImageAddress;\r
56 UINT64 ImageSize;\r
57 EFI_PHYSICAL_ADDRESS ImageEntryPoint;\r
58 EFI_TE_IMAGE_HEADER *TEImageHeader;\r
a8b194b9 59 UINT16 Machine;\r
a0b7c09f 60\r
61 *EntryPoint = NULL;\r
62 TEImageHeader = NULL;\r
63\r
64 //\r
65 // Try to find a PE32 section.\r
66 //\r
84a99d48 67 Status = PeiServicesFfsFindSectionData (\r
a0b7c09f 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
84a99d48 76 Status = PeiServicesFfsFindSectionData (\r
a0b7c09f 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
84a99d48 86 Status = PeiServicesLocatePpi (\r
a0b7c09f 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
7c9e5810 109 // Got the entry point from ImageEntryPoint and ImageStartAddress\r
a0b7c09f 110 //\r
7c9e5810 111 Pe32Data = (VOID *) ((UINTN) ImageAddress);\r
2d10530b 112 *EntryPoint = (VOID *) ((UINTN) ImageEntryPoint);\r
a0b7c09f 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
a8b194b9 118 *EntryPoint = (VOID *)((UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) +\r
a0b7c09f 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
a8b194b9 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
a0b7c09f 143 //\r
144 // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi\r
145 //\r
a61513d6 146 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%08x EntryPoint=0x%08x ", (UINTN) ImageAddress, *EntryPoint));\r
2ce31132 147 DEBUG_CODE_BEGIN ();\r
ec412251 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
5b18234d 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
ec412251 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
7c9e5810
LG
186 DebugEntry = NULL;\r
187 DirectoryEntry = NULL;\r
188 NumberOfRvaAndSizes = 0;\r
189 TEImageAdjust = 0;\r
190 \r
ec412251 191 if (TEImageHeader == NULL) {\r
192 if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
193 // \r
7c9e5810 194 // Use PE32 offset get Debug Directory Entry\r
ec412251 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
7c9e5810
LG
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
ec412251 200 // \r
7c9e5810 201 // Use PE32+ offset get Debug Directory Entry\r
ec412251 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
7c9e5810
LG
205 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress);\r
206 }\r
ec412251 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
a0b7c09f 219 }\r
220 }\r
2ce31132 221\r
ec412251 222 if (DebugEntry != NULL && DirectoryEntry != NULL) {\r
5b664244 223 for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount += sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY), DebugEntry++) {\r
ec412251 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
b5ace64c 242 for (Index = 0, Index1 = 0; AsciiString[Index] != '\0'; Index++) {\r
ec412251 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
2ce31132 262 DEBUG_CODE_END ();\r
a0b7c09f 263\r
264 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n"));\r
265\r
266 return EFI_SUCCESS;\r
267}\r