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