3 * Copyright (c) 2011, ARM Limited. All rights reserved.
5 * This program and the accompanying materials
6 * are licensed and made available under the terms and conditions of the BSD License
7 * which accompanies this distribution. The full text of the license may be found at
8 * http://opensource.org/licenses/bsd-license.php
10 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "BdsInternal.h"
17 //#include <Library/PeCoffLib.h>
18 #include <Library/DxeServicesLib.h>
21 #include <Protocol/DevicePathToText.h>
24 Retrieves the magic value from the PE/COFF header.
26 @param Hdr The buffer in which to return the PE32, PE32+, or TE header.
28 @return EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC - Image is PE32
29 @return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC - Image is PE32+
33 PeCoffLoaderGetPeHeaderMagicValue (
34 IN EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
38 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
39 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
40 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
41 // then override the returned value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
43 if (Hdr
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& Hdr
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
44 return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
47 // Return the magic value from the PC/COFF Optional Header
49 return Hdr
.Pe32
->OptionalHeader
.Magic
;
59 EFI_IMAGE_DOS_HEADER
*DosHeader
;
60 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Header
;
66 DosHeader
= (EFI_IMAGE_DOS_HEADER
*)Image
;
67 if (DosHeader
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
68 Header
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINT8
*)Image
+ DosHeader
->e_lfanew
);
70 Header
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)(Image
);
73 if (Header
.Te
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
76 } else if (Header
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
) {
77 Magic
= PeCoffLoaderGetPeHeaderMagicValue (Header
);
78 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
81 } else if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
82 // It is a PE32+ Image
85 DEBUG ((EFI_D_ERROR
,"BdsLoadBinaryFromPath(): Fail unrecognized PE Image\n"));
88 DEBUG ((EFI_D_ERROR
,"BdsLoadBinaryFromPath(): Fail unrecognize image\n"));
96 BdsLoadFileFromFirmwareVolume (
97 IN EFI_HANDLE FvHandle
,
99 IN EFI_FV_FILETYPE FileTypeFilter
,
100 OUT EFI_DEVICE_PATH
**EfiAppDevicePath
103 EFI_FIRMWARE_VOLUME2_PROTOCOL
*FvProtocol
;
105 EFI_STATUS Status
, FileStatus
;
107 EFI_FV_FILETYPE FileType
;
108 EFI_FV_FILE_ATTRIBUTES Attributes
;
112 UINT32 Authentication
;
113 EFI_DEVICE_PATH
*FvDevicePath
;
114 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileDevicePath
;
116 Status
= gBS
->HandleProtocol (FvHandle
,&gEfiFirmwareVolume2ProtocolGuid
, (VOID
**)&FvProtocol
);
117 if (EFI_ERROR(Status
)) {
121 // Length of FilePath
122 UiStringLen
= StrLen (FilePath
);
125 Key
= AllocatePool (FvProtocol
->KeySize
);
126 ASSERT (Key
!= NULL
);
127 ZeroMem (Key
, FvProtocol
->KeySize
);
130 // Search in all files
131 FileType
= FileTypeFilter
;
133 Status
= FvProtocol
->GetNextFile (FvProtocol
, Key
, &FileType
, &NameGuid
, &Attributes
, &Size
);
134 if (!EFI_ERROR (Status
)) {
136 FileStatus
= FvProtocol
->ReadSection (
139 EFI_SECTION_USER_INTERFACE
,
145 if (!EFI_ERROR (FileStatus
)) {
146 if (StrnCmp (FilePath
, UiSection
, UiStringLen
) == 0) {
148 // We found a UiString match.
150 Status
= gBS
->HandleProtocol (FvHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&FvDevicePath
);
152 // Generate the Device Path for the file
153 //DevicePath = DuplicateDevicePath(FvDevicePath);
154 EfiInitializeFwVolDevicepathNode (&FileDevicePath
, &NameGuid
);
155 *EfiAppDevicePath
= AppendDevicePathNode (FvDevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&FileDevicePath
);
158 FreePool (UiSection
);
161 FreePool (UiSection
);
164 } while (!EFI_ERROR (Status
));
171 Start an EFI Application from any Firmware Volume
173 @param EfiApp EFI Application Name
175 @retval EFI_SUCCESS All drivers have been connected
176 @retval EFI_NOT_FOUND The Linux kernel Device Path has not been found
177 @retval EFI_OUT_OF_RESOURCES There is not enough resource memory to store the matching results.
182 IN EFI_HANDLE ParentImageHandle
,
187 UINTN NoHandles
, HandleIndex
;
189 EFI_DEVICE_PATH
*FvDevicePath
;
190 EFI_DEVICE_PATH
*EfiAppDevicePath
;
192 // Need to connect every drivers to ensure no dependencies are missing for the application
193 Status
= BdsConnectAllDrivers();
194 if (EFI_ERROR(Status
)) {
195 DEBUG ((EFI_D_ERROR
, "FAIL to connect all drivers\n"));
199 // Search the application in any Firmware Volume
200 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiFirmwareVolume2ProtocolGuid
, NULL
, &NoHandles
, &Handles
);
201 if (EFI_ERROR (Status
) || (NoHandles
== 0)) {
202 DEBUG ((EFI_D_ERROR
, "FAIL to find Firmware Volume\n"));
206 // Search in all Firmware Volume for the EFI Application
207 for (HandleIndex
= 0; HandleIndex
< NoHandles
; HandleIndex
++) {
208 Status
= BdsLoadFileFromFirmwareVolume (Handles
[HandleIndex
], EfiApp
, EFI_FV_FILETYPE_APPLICATION
, &EfiAppDevicePath
);
209 if (!EFI_ERROR (Status
)) {
210 // Start the application
211 Status
= BdsStartEfiApplication (ParentImageHandle
, EfiAppDevicePath
);