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
28 IN EFI_PEI_SERVICES
**PeiServices
,
29 IN EFI_FFS_FILE_HEADER
*PeimFileHeader
,
36 Routine for loading file image.
40 PeiServices - The PEI core services table.
41 PeimFileHeader - Pointer to the FFS file header of the image.
42 EntryPoint - Pointer to entry point of specified image file for output.
46 Status - EFI_SUCCESS - Image is successfully loaded.
47 EFI_NOT_FOUND - Fail to locate necessary PPI
48 Others - Fail to load file.
54 EFI_PEI_FV_FILE_LOADER_PPI
*FvLoadFilePpi
;
55 EFI_PHYSICAL_ADDRESS ImageAddress
;
57 EFI_PHYSICAL_ADDRESS ImageEntryPoint
;
58 EFI_TE_IMAGE_HEADER
*TEImageHeader
;
64 // Try to find a PE32 section.
66 Status
= PeiServicesFfsFindSectionData (
72 // If we didn't find a PE32 section, try to find a TE section.
74 if (EFI_ERROR (Status
)) {
75 Status
= PeiServicesFfsFindSectionData (
78 (VOID
**) &TEImageHeader
80 if (EFI_ERROR (Status
) || TEImageHeader
== NULL
) {
82 // There was not a PE32 or a TE section, so assume that it's a Compressed section
83 // and use the LoadFile
85 Status
= PeiServicesLocatePpi (
86 &gEfiPeiFvFileLoaderPpiGuid
,
89 (VOID
**)&FvLoadFilePpi
91 if (EFI_ERROR (Status
)) {
95 Status
= FvLoadFilePpi
->FvLoadFile (
103 if (EFI_ERROR (Status
)) {
104 return EFI_NOT_FOUND
;
108 // Got the entry point from ImageEntryPoint and ImageStartAddress
110 Pe32Data
= (VOID
*) ((UINTN
) ImageAddress
);
111 *EntryPoint
= (VOID
*) ((UINTN
) ImageEntryPoint
);
114 // Retrieve the entry point from the TE image header
116 ImageAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) TEImageHeader
;
117 *EntryPoint
= (VOID
*)((UINTN
) TEImageHeader
+ sizeof (EFI_TE_IMAGE_HEADER
) +
118 TEImageHeader
->AddressOfEntryPoint
- TEImageHeader
->StrippedSize
);
122 // Retrieve the entry point from the PE/COFF image header
124 ImageAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) Pe32Data
;
125 Status
= PeCoffLoaderGetEntryPoint (Pe32Data
, EntryPoint
);
126 if (EFI_ERROR (Status
)) {
127 return EFI_NOT_FOUND
;
132 // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi
134 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "Loading PEIM at 0x%08x EntryPoint=0x%08x ", (UINTN
) ImageAddress
, *EntryPoint
));
136 EFI_IMAGE_DATA_DIRECTORY
*DirectoryEntry
;
137 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*DebugEntry
;
141 BOOLEAN FileNameFound
;
143 CHAR8 AsciiBuffer
[512];
144 VOID
*CodeViewEntryPointer
;
146 EFI_IMAGE_DOS_HEADER
*DosHeader
;
147 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
148 UINT32 NumberOfRvaAndSizes
;
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 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINTN
)Pe32Data
+ (UINTN
)((DosHeader
->e_lfanew
) & 0x0ffff));
160 // DOS image header is not present, so PE header is at the image base
162 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)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
;
176 NumberOfRvaAndSizes
= 0;
179 if (TEImageHeader
== NULL
) {
180 if (Hdr
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
182 // Use PE32 offset get Debug Directory Entry
184 NumberOfRvaAndSizes
= Hdr
.Pe32
->OptionalHeader
.NumberOfRvaAndSizes
;
185 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)&(Hdr
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
]);
186 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*) ((UINTN
) Pe32Data
+ DirectoryEntry
->VirtualAddress
);
187 } else if (Hdr
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
189 // Use PE32+ offset get Debug Directory Entry
191 NumberOfRvaAndSizes
= Hdr
.Pe32Plus
->OptionalHeader
.NumberOfRvaAndSizes
;
192 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)&(Hdr
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
]);
193 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*) ((UINTN
) Pe32Data
+ DirectoryEntry
->VirtualAddress
);
196 if (NumberOfRvaAndSizes
<= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
197 DirectoryEntry
= NULL
;
201 if (TEImageHeader
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
!= 0) {
202 DirectoryEntry
= &TEImageHeader
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
];
203 TEImageAdjust
= sizeof (EFI_TE_IMAGE_HEADER
) - TEImageHeader
->StrippedSize
;
204 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*)((UINTN
) TEImageHeader
+
205 TEImageHeader
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
+
210 if (DebugEntry
!= NULL
&& DirectoryEntry
!= NULL
) {
211 for (DirCount
= 0; DirCount
< DirectoryEntry
->Size
; DirCount
++, DebugEntry
++) {
212 if (DebugEntry
->Type
== EFI_IMAGE_DEBUG_TYPE_CODEVIEW
) {
213 if (DebugEntry
->SizeOfData
> 0) {
214 CodeViewEntryPointer
= (VOID
*) ((UINTN
) DebugEntry
->RVA
+ (UINTN
) ImageAddress
+ (UINTN
)TEImageAdjust
);
215 switch (* (UINT32
*) CodeViewEntryPointer
) {
216 case CODEVIEW_SIGNATURE_NB10
:
217 AsciiString
= (CHAR8
*)CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
);
220 case CODEVIEW_SIGNATURE_RSDS
:
221 AsciiString
= (CHAR8
*)CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY
);
228 if (AsciiString
!= NULL
) {
229 FileNameFound
= FALSE
;
230 for (Index
= 0, Index1
= 0; (AsciiString
[Index
] != 0) && (Index
< sizeof (AsciiString
)); Index
++) {
231 if (AsciiString
[Index
] == '\\') {
233 FileNameFound
= TRUE
;
238 for (Index
= Index1
+ 1; AsciiString
[Index
] != '.'; Index
++) {
239 AsciiBuffer
[Index
- (Index1
+ 1)] = AsciiString
[Index
];
241 AsciiBuffer
[Index
- (Index1
+ 1)] = 0;
242 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "%a.efi", AsciiBuffer
));
252 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "\n"));