]>
Commit | Line | Data |
---|---|---|
e20ee534 LG |
1 | /*++ |
2 | ||
3 | Copyright (c) 2006, Intel Corporation | |
4 | All rights reserved. This program and the accompanying materials | |
5 | are licensed and made available under the terms and conditions of the BSD License | |
6 | which accompanies this distribution. The full text of the license may be found at | |
7 | http://opensource.org/licenses/bsd-license.php | |
8 | ||
9 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
10 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
11 | ||
12 | Module Name: | |
13 | ||
14 | Image.c | |
15 | ||
16 | Abstract: | |
17 | ||
18 | Pei Core Load Image Support | |
19 | ||
20 | --*/ | |
21 | ||
22 | #include <PeiMain.h> | |
23 | ||
24 | EFI_STATUS | |
25 | PeiLoadImage ( | |
26 | IN EFI_PEI_SERVICES **PeiServices, | |
27 | IN EFI_FFS_FILE_HEADER *PeimFileHeader, | |
28 | OUT VOID **EntryPoint | |
29 | ) | |
30 | /*++ | |
31 | ||
32 | Routine Description: | |
33 | ||
34 | Routine for loading file image. | |
35 | ||
36 | Arguments: | |
37 | ||
38 | PeiServices - The PEI core services table. | |
39 | PeimFileHeader - Pointer to the FFS file header of the image. | |
40 | EntryPoint - Pointer to entry point of specified image file for output. | |
41 | ||
42 | Returns: | |
43 | ||
44 | Status - EFI_SUCCESS - Image is successfully loaded. | |
45 | EFI_NOT_FOUND - Fail to locate necessary PPI | |
46 | Others - Fail to load file. | |
47 | ||
48 | --*/ | |
49 | { | |
50 | EFI_STATUS Status; | |
51 | VOID *Pe32Data; | |
52 | EFI_PEI_FV_FILE_LOADER_PPI *FvLoadFilePpi; | |
53 | //#ifdef EFI_NT_EMULATOR | |
54 | // EFI_PEI_PPI_DESCRIPTOR *PpiDescriptor; | |
55 | // NT_PEI_LOAD_FILE_PPI *PeiNtService; | |
56 | //#endif | |
57 | EFI_PHYSICAL_ADDRESS ImageAddress; | |
58 | UINT64 ImageSize; | |
59 | EFI_PHYSICAL_ADDRESS ImageEntryPoint; | |
60 | EFI_TE_IMAGE_HEADER *TEImageHeader; | |
61 | ||
62 | *EntryPoint = NULL; | |
63 | TEImageHeader = NULL; | |
64 | ||
65 | // | |
66 | // Try to find a PE32 section. | |
67 | // | |
68 | Status = PeiCoreFfsFindSectionData ( | |
69 | EFI_SECTION_PE32, | |
70 | PeimFileHeader, | |
71 | &Pe32Data | |
72 | ); | |
73 | // | |
74 | // If we didn't find a PE32 section, try to find a TE section. | |
75 | // | |
76 | if (EFI_ERROR (Status)) { | |
77 | Status = PeiCoreFfsFindSectionData ( | |
78 | EFI_SECTION_TE, | |
79 | PeimFileHeader, | |
80 | (VOID **) &TEImageHeader | |
81 | ); | |
82 | if (EFI_ERROR (Status) || TEImageHeader == NULL) { | |
83 | // | |
84 | // There was not a PE32 or a TE section, so assume that it's a Compressed section | |
85 | // and use the LoadFile | |
86 | // | |
87 | Status = PeiCoreLocatePpi ( | |
88 | &gEfiPeiFvFileLoaderPpiGuid, | |
89 | 0, | |
90 | NULL, | |
91 | (VOID **)&FvLoadFilePpi | |
92 | ); | |
93 | if (EFI_ERROR (Status)) { | |
94 | return EFI_NOT_FOUND; | |
95 | } | |
96 | ||
97 | Status = FvLoadFilePpi->FvLoadFile ( | |
98 | FvLoadFilePpi, | |
99 | PeimFileHeader, | |
100 | &ImageAddress, | |
101 | &ImageSize, | |
102 | &ImageEntryPoint | |
103 | ); | |
104 | ||
105 | if (EFI_ERROR (Status)) { | |
106 | return EFI_NOT_FOUND; | |
107 | } | |
108 | ||
109 | // | |
110 | // Retrieve the entry point from the PE/COFF image header | |
111 | // | |
112 | Status = PeCoffLoaderGetEntryPoint ((VOID *)(UINTN)ImageAddress, EntryPoint); | |
113 | if (EFI_ERROR (Status)) { | |
114 | return EFI_NOT_FOUND; | |
115 | } | |
116 | } else { | |
117 | // | |
118 | // Retrieve the entry point from the TE image header | |
119 | // | |
120 | ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) TEImageHeader; | |
121 | *EntryPoint = (VOID *)((UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) + | |
122 | TEImageHeader->AddressOfEntryPoint - TEImageHeader->StrippedSize); | |
123 | } | |
124 | } else { | |
125 | // | |
126 | // Retrieve the entry point from the PE/COFF image header | |
127 | // | |
128 | ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) Pe32Data; | |
129 | Status = PeCoffLoaderGetEntryPoint (Pe32Data, EntryPoint); | |
130 | if (EFI_ERROR (Status)) { | |
131 | return EFI_NOT_FOUND; | |
132 | } | |
133 | } | |
134 | ||
135 | // | |
136 | // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi | |
137 | // | |
138 | DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%08x EntryPoint=0x%08x ", Pe32Data, *EntryPoint)); | |
139 | DEBUG_CODE ( | |
140 | EFI_IMAGE_DATA_DIRECTORY * DirectoryEntry; | |
141 | EFI_IMAGE_DEBUG_DIRECTORY_ENTRY * DebugEntry; | |
142 | UINTN DirCount; | |
143 | UINTN Index; | |
144 | UINTN Index1; | |
145 | BOOLEAN FileNameFound; | |
146 | CHAR8 *AsciiString; | |
147 | CHAR8 AsciiBuffer[512]; | |
148 | VOID *CodeViewEntryPointer; | |
149 | INTN TEImageAdjust; | |
150 | EFI_IMAGE_DOS_HEADER *DosHeader; | |
151 | EFI_IMAGE_NT_HEADERS *PeHeader; | |
152 | ||
153 | // | |
154 | // Pe32Data is NULL when load TE image | |
155 | // | |
156 | PeHeader = NULL; | |
157 | if (TEImageHeader == NULL) { | |
158 | DosHeader = (EFI_IMAGE_DOS_HEADER *)Pe32Data; | |
159 | if (DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE) { | |
160 | // | |
161 | // DOS image header is present, so read the PE header after the DOS image header | |
162 | // | |
163 | PeHeader = (EFI_IMAGE_NT_HEADERS *) ((UINTN) Pe32Data + (UINTN) ((DosHeader->e_lfanew) & 0x0ffff)); | |
164 | } else { | |
165 | // | |
166 | // DOS image header is not present, so PE header is at the image base | |
167 | // | |
168 | PeHeader = (EFI_IMAGE_NT_HEADERS *) Pe32Data; | |
169 | } | |
170 | } | |
171 | ||
172 | // | |
173 | // Find the codeview info in the image and display the file name | |
174 | // being loaded. | |
175 | // | |
176 | // Per the PE/COFF spec, you can't assume that a given data directory | |
177 | // is present in the image. You have to check the NumberOfRvaAndSizes in | |
178 | // the optional header to verify a desired directory entry is there. | |
179 | // | |
180 | DebugEntry = NULL; | |
181 | DirectoryEntry = NULL; | |
182 | TEImageAdjust = 0; | |
183 | if (TEImageHeader == NULL) { | |
184 | if (PeHeader->OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { | |
185 | DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(PeHeader->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); | |
186 | DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) ImageAddress + DirectoryEntry->VirtualAddress); | |
187 | } | |
188 | } else { | |
189 | if (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) { | |
190 | DirectoryEntry = &TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG]; | |
191 | TEImageAdjust = sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize; | |
192 | DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN) TEImageHeader + | |
193 | TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress + | |
194 | TEImageAdjust); | |
195 | } | |
196 | } | |
197 | ||
198 | if (DebugEntry != NULL && DirectoryEntry != NULL) { | |
199 | for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount++, DebugEntry++) { | |
200 | if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { | |
201 | if (DebugEntry->SizeOfData > 0) { | |
202 | CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + (UINTN) ImageAddress + (UINTN)TEImageAdjust); | |
203 | switch (* (UINT32 *) CodeViewEntryPointer) { | |
204 | case CODEVIEW_SIGNATURE_NB10: | |
205 | AsciiString = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY); | |
206 | break; | |
207 | ||
208 | case CODEVIEW_SIGNATURE_RSDS: | |
209 | AsciiString = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY); | |
210 | break; | |
211 | ||
212 | default: | |
213 | AsciiString = NULL; | |
214 | break; | |
215 | } | |
216 | if (AsciiString != NULL) { | |
217 | FileNameFound = FALSE; | |
218 | for (Index = 0, Index1 = 0; AsciiString[Index] != 0; Index++) { | |
219 | if (AsciiString[Index] == '\\') { | |
220 | Index1 = Index; | |
221 | FileNameFound = TRUE; | |
222 | } | |
223 | } | |
224 | ||
225 | if (FileNameFound) { | |
226 | for (Index = Index1 + 1; AsciiString[Index] != '.'; Index++) { | |
227 | AsciiBuffer[Index - (Index1 + 1)] = AsciiString[Index]; | |
228 | } | |
229 | AsciiBuffer[Index - (Index1 + 1)] = 0; | |
230 | DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a.efi", AsciiBuffer)); | |
231 | break; | |
232 | } | |
233 | } | |
234 | } | |
235 | } | |
236 | } | |
237 | } | |
238 | ); | |
239 | ||
240 | DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n")); | |
241 | ||
242 | return EFI_SUCCESS; | |
243 | } |