]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Core/Pei/Image/Image.c
Fixed EDKT145
[mirror_edk2.git] / EdkModulePkg / Core / Pei / Image / Image.c
CommitLineData
a0b7c09f 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 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
59\r
60 *EntryPoint = NULL;\r
61 TEImageHeader = NULL;\r
62\r
63 //\r
64 // Try to find a PE32 section.\r
65 //\r
84a99d48 66 Status = PeiServicesFfsFindSectionData (\r
a0b7c09f 67 EFI_SECTION_PE32,\r
68 PeimFileHeader,\r
69 &Pe32Data\r
70 );\r
71 //\r
72 // If we didn't find a PE32 section, try to find a TE section.\r
73 //\r
74 if (EFI_ERROR (Status)) {\r
84a99d48 75 Status = PeiServicesFfsFindSectionData (\r
a0b7c09f 76 EFI_SECTION_TE,\r
77 PeimFileHeader,\r
78 (VOID **) &TEImageHeader\r
79 );\r
80 if (EFI_ERROR (Status) || TEImageHeader == NULL) {\r
81 //\r
82 // There was not a PE32 or a TE section, so assume that it's a Compressed section\r
83 // and use the LoadFile\r
84 //\r
84a99d48 85 Status = PeiServicesLocatePpi (\r
a0b7c09f 86 &gEfiPeiFvFileLoaderPpiGuid,\r
87 0,\r
88 NULL,\r
89 (VOID **)&FvLoadFilePpi\r
90 );\r
91 if (EFI_ERROR (Status)) {\r
92 return EFI_NOT_FOUND;\r
93 }\r
94\r
95 Status = FvLoadFilePpi->FvLoadFile (\r
96 FvLoadFilePpi,\r
97 PeimFileHeader,\r
98 &ImageAddress,\r
99 &ImageSize,\r
100 &ImageEntryPoint\r
101 );\r
102\r
103 if (EFI_ERROR (Status)) {\r
104 return EFI_NOT_FOUND;\r
105 }\r
106\r
107 //\r
2d10530b 108 // Got the entry point from ImageEntryPoint\r
a0b7c09f 109 //\r
2d10530b
LG
110 *EntryPoint = (VOID *) ((UINTN) ImageEntryPoint);\r
111 return EFI_SUCCESS;\r
a0b7c09f 112 } else {\r
113 //\r
114 // Retrieve the entry point from the TE image header\r
115 //\r
116 ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) TEImageHeader;\r
117 *EntryPoint = (VOID *)((UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) +\r
118 TEImageHeader->AddressOfEntryPoint - TEImageHeader->StrippedSize);\r
119 }\r
120 } else {\r
121 //\r
122 // Retrieve the entry point from the PE/COFF image header\r
123 //\r
124 ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) Pe32Data;\r
125 Status = PeCoffLoaderGetEntryPoint (Pe32Data, EntryPoint);\r
126 if (EFI_ERROR (Status)) {\r
127 return EFI_NOT_FOUND;\r
128 }\r
129 }\r
130\r
131 //\r
132 // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi\r
133 //\r
134 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%08x EntryPoint=0x%08x ", Pe32Data, *EntryPoint));\r
2ce31132 135 DEBUG_CODE_BEGIN ();\r
ec412251 136 EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry;\r
137 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;\r
138 UINTN DirCount;\r
139 UINTN Index;\r
140 UINTN Index1;\r
141 BOOLEAN FileNameFound;\r
142 CHAR8 *AsciiString;\r
143 CHAR8 AsciiBuffer[512];\r
144 VOID *CodeViewEntryPointer;\r
145 INTN TEImageAdjust;\r
146 EFI_IMAGE_DOS_HEADER *DosHeader;\r
147 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
148 UINT32 NumberOfRvaAndSizes;\r
149\r
150 DosHeader = (EFI_IMAGE_DOS_HEADER *)Pe32Data;\r
151 if (DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
2ce31132 152 //\r
ec412251 153 // DOS image header is present, so read the PE header after the DOS image header\r
2ce31132 154 //\r
ec412251 155 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)Pe32Data + (UINTN)((DosHeader->e_lfanew) & 0x0ffff));\r
156 } else {\r
157 //\r
158 // DOS image header is not present, so PE header is at the image base\r
159 //\r
160 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;\r
161 }\r
162\r
163 //\r
164 // Find the codeview info in the image and display the file name\r
165 // being loaded.\r
166 //\r
167 // Per the PE/COFF spec, you can't assume that a given data directory\r
168 // is present in the image. You have to check the NumberOfRvaAndSizes in\r
169 // the optional header to verify a desired directory entry is there.\r
170 //\r
171 DebugEntry = NULL;\r
172 DirectoryEntry = NULL;\r
173 TEImageAdjust = 0;\r
174 if (TEImageHeader == NULL) {\r
175 if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
176 // \r
177 // Use PE32 offset\r
178 //\r
179 NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
180 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);\r
181 } else {\r
182 // \r
183 // Use PE32+ offset\r
184 //\r
185 NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;\r
186 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);\r
187 } \r
188\r
189 if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
190 DirectoryEntry = NULL;\r
191 DebugEntry = NULL;\r
192 }\r
193 } else {\r
194 if (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) {\r
195 DirectoryEntry = &TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG];\r
196 TEImageAdjust = sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize;\r
197 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN) TEImageHeader +\r
198 TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress +\r
199 TEImageAdjust);\r
a0b7c09f 200 }\r
201 }\r
2ce31132 202\r
ec412251 203 if (DebugEntry != NULL && DirectoryEntry != NULL) {\r
204 for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount++, DebugEntry++) {\r
205 if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {\r
206 if (DebugEntry->SizeOfData > 0) {\r
207 CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + (UINTN) ImageAddress + (UINTN)TEImageAdjust);\r
208 switch (* (UINT32 *) CodeViewEntryPointer) {\r
209 case CODEVIEW_SIGNATURE_NB10:\r
210 AsciiString = (CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);\r
211 break;\r
212\r
213 case CODEVIEW_SIGNATURE_RSDS:\r
214 AsciiString = (CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);\r
215 break;\r
216\r
217 default:\r
218 AsciiString = NULL;\r
219 break;\r
220 }\r
221 if (AsciiString != NULL) {\r
222 FileNameFound = FALSE;\r
223 for (Index = 0, Index1 = 0; (AsciiString[Index] != 0) && (Index < sizeof (AsciiString)); Index++) {\r
224 if (AsciiString[Index] == '\\') {\r
225 Index1 = Index;\r
226 FileNameFound = TRUE;\r
227 }\r
228 }\r
229\r
230 if (FileNameFound) {\r
231 for (Index = Index1 + 1; AsciiString[Index] != '.'; Index++) {\r
232 AsciiBuffer[Index - (Index1 + 1)] = AsciiString[Index];\r
233 }\r
234 AsciiBuffer[Index - (Index1 + 1)] = 0;\r
235 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a.efi", AsciiBuffer));\r
236 break;\r
237 }\r
238 }\r
239 }\r
240 }\r
241 }\r
242 }\r
2ce31132 243 DEBUG_CODE_END ();\r
a0b7c09f 244\r
245 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n"));\r
246\r
247 return EFI_SUCCESS;\r
248}\r