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