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
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.
18 Pei Core Load Image Support
26 IN EFI_PEI_SERVICES
**PeiServices
,
27 IN EFI_FFS_FILE_HEADER
*PeimFileHeader
,
34 Routine for loading file image.
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.
44 Status - EFI_SUCCESS - Image is successfully loaded.
45 EFI_NOT_FOUND - Fail to locate necessary PPI
46 Others - Fail to load file.
52 EFI_PEI_FV_FILE_LOADER_PPI
*FvLoadFilePpi
;
53 EFI_PHYSICAL_ADDRESS ImageAddress
;
55 EFI_PHYSICAL_ADDRESS ImageEntryPoint
;
56 EFI_TE_IMAGE_HEADER
*TEImageHeader
;
62 // Try to find a PE32 section.
64 Status
= PeiServicesFfsFindSectionData (
70 // If we didn't find a PE32 section, try to find a TE section.
72 if (EFI_ERROR (Status
)) {
73 Status
= PeiServicesFfsFindSectionData (
76 (VOID
**) &TEImageHeader
78 if (EFI_ERROR (Status
) || TEImageHeader
== NULL
) {
80 // There was not a PE32 or a TE section, so assume that it's a Compressed section
81 // and use the LoadFile
83 Status
= PeiServicesLocatePpi (
84 &gEfiPeiFvFileLoaderPpiGuid
,
87 (VOID
**)&FvLoadFilePpi
89 if (EFI_ERROR (Status
)) {
93 Status
= FvLoadFilePpi
->FvLoadFile (
101 if (EFI_ERROR (Status
)) {
102 return EFI_NOT_FOUND
;
106 // Got the entry point from ImageEntryPoint
108 *EntryPoint
= (VOID
*) ((UINTN
) ImageEntryPoint
);
112 // Retrieve the entry point from the TE image header
114 ImageAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) TEImageHeader
;
115 *EntryPoint
= (VOID
*)((UINTN
) TEImageHeader
+ sizeof (EFI_TE_IMAGE_HEADER
) +
116 TEImageHeader
->AddressOfEntryPoint
- TEImageHeader
->StrippedSize
);
120 // Retrieve the entry point from the PE/COFF image header
122 ImageAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) Pe32Data
;
123 Status
= PeCoffLoaderGetEntryPoint (Pe32Data
, EntryPoint
);
124 if (EFI_ERROR (Status
)) {
125 return EFI_NOT_FOUND
;
130 // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi
132 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "Loading PEIM at 0x%08x EntryPoint=0x%08x ", Pe32Data
, *EntryPoint
));
134 EFI_IMAGE_DATA_DIRECTORY
* DirectoryEntry
;
135 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
* DebugEntry
;
139 BOOLEAN FileNameFound
;
141 CHAR8 AsciiBuffer
[512];
142 VOID
*CodeViewEntryPointer
;
144 EFI_IMAGE_DOS_HEADER
*DosHeader
;
145 EFI_IMAGE_NT_HEADERS
*PeHeader
;
148 // Pe32Data is NULL when load TE image
151 if (TEImageHeader
== NULL
) {
152 DosHeader
= (EFI_IMAGE_DOS_HEADER
*)Pe32Data
;
153 if (DosHeader
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
155 // DOS image header is present, so read the PE header after the DOS image header
157 PeHeader
= (EFI_IMAGE_NT_HEADERS
*) ((UINTN
) Pe32Data
+ (UINTN
) ((DosHeader
->e_lfanew
) & 0x0ffff));
160 // DOS image header is not present, so PE header is at the image base
162 PeHeader
= (EFI_IMAGE_NT_HEADERS
*) Pe32Data
;
167 // Find the codeview info in the image and display the file name
170 // Per the PE/COFF spec, you can't assume that a given data directory
171 // is present in the image. You have to check the NumberOfRvaAndSizes in
172 // the optional header to verify a desired directory entry is there.
175 DirectoryEntry
= NULL
;
177 if (TEImageHeader
== NULL
) {
178 if (PeHeader
->OptionalHeader
.NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
179 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*) &(PeHeader
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
]);
180 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*) ((UINTN
) ImageAddress
+ DirectoryEntry
->VirtualAddress
);
183 if (TEImageHeader
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
!= 0) {
184 DirectoryEntry
= &TEImageHeader
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
];
185 TEImageAdjust
= sizeof (EFI_TE_IMAGE_HEADER
) - TEImageHeader
->StrippedSize
;
186 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*)((UINTN
) TEImageHeader
+
187 TEImageHeader
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
+
192 if (DebugEntry
!= NULL
&& DirectoryEntry
!= NULL
) {
193 for (DirCount
= 0; DirCount
< DirectoryEntry
->Size
; DirCount
++, DebugEntry
++) {
194 if (DebugEntry
->Type
== EFI_IMAGE_DEBUG_TYPE_CODEVIEW
) {
195 if (DebugEntry
->SizeOfData
> 0) {
196 CodeViewEntryPointer
= (VOID
*) ((UINTN
) DebugEntry
->RVA
+ (UINTN
) ImageAddress
+ (UINTN
)TEImageAdjust
);
197 switch (* (UINT32
*) CodeViewEntryPointer
) {
198 case CODEVIEW_SIGNATURE_NB10
:
199 AsciiString
= (CHAR8
*) CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
);
202 case CODEVIEW_SIGNATURE_RSDS
:
203 AsciiString
= (CHAR8
*) CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY
);
210 if (AsciiString
!= NULL
) {
211 FileNameFound
= FALSE
;
212 for (Index
= 0, Index1
= 0; AsciiString
[Index
] != 0; Index
++) {
213 if (AsciiString
[Index
] == '\\') {
215 FileNameFound
= TRUE
;
220 for (Index
= Index1
+ 1; AsciiString
[Index
] != '.'; Index
++) {
221 AsciiBuffer
[Index
- (Index1
+ 1)] = AsciiString
[Index
];
223 AsciiBuffer
[Index
- (Index1
+ 1)] = 0;
224 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "%a.efi", AsciiBuffer
));
234 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "\n"));