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