/** @file | |
* | |
* Copyright (c) 2011 - 2015, ARM Limited. All rights reserved. | |
* | |
* This program and the accompanying materials | |
* are licensed and made available under the terms and conditions of the BSD License | |
* which accompanies this distribution. The full text of the license may be found at | |
* http://opensource.org/licenses/bsd-license.php | |
* | |
* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
* | |
**/ | |
#include "BdsInternal.h" | |
// This GUID is defined in the INGF file of ArmPkg/Application/LinuxLoader | |
CONST EFI_GUID mLinuxLoaderAppGuid = { 0x701f54f2, 0x0d70, 0x4b89, { 0xbc, 0x0a, 0xd9, 0xca, 0x25, 0x37, 0x90, 0x59 }}; | |
// Device path of the EFI Linux Loader in the Firmware Volume | |
EFI_DEVICE_PATH* mLinuxLoaderDevicePath = NULL; | |
STATIC | |
BOOLEAN | |
HasFilePathEfiExtension ( | |
IN CHAR16* FilePath | |
) | |
{ | |
return (StrCmp (FilePath + (StrSize (FilePath) / sizeof (CHAR16)) - 5, L".EFI") == 0) || | |
(StrCmp (FilePath + (StrSize (FilePath) / sizeof (CHAR16)) - 5, L".efi") == 0); | |
} | |
/** | |
* This function check if the DevicePath defines an EFI binary | |
* | |
* This function is used when the BDS support Linux loader to | |
* detect if the binary is an EFI application or potentially a | |
* Linux kernel. | |
*/ | |
EFI_STATUS | |
IsEfiBinary ( | |
IN EFI_DEVICE_PATH* DevicePath, | |
OUT BOOLEAN *EfiBinary | |
) | |
{ | |
EFI_STATUS Status; | |
CHAR16* FileName; | |
EFI_DEVICE_PATH* PrevDevicePathNode; | |
EFI_DEVICE_PATH* DevicePathNode; | |
EFI_PHYSICAL_ADDRESS Image; | |
UINTN FileSize; | |
EFI_IMAGE_DOS_HEADER* DosHeader; | |
UINTN PeCoffHeaderOffset; | |
EFI_IMAGE_NT_HEADERS32* NtHeader; | |
ASSERT (EfiBinary != NULL); | |
// | |
// Check if the last node of the device path is a FilePath node | |
// | |
PrevDevicePathNode = NULL; | |
DevicePathNode = DevicePath; | |
while ((DevicePathNode != NULL) && !IsDevicePathEnd (DevicePathNode)) { | |
PrevDevicePathNode = DevicePathNode; | |
DevicePathNode = NextDevicePathNode (DevicePathNode); | |
} | |
if ((PrevDevicePathNode != NULL) && | |
(PrevDevicePathNode->Type == MEDIA_DEVICE_PATH) && | |
(PrevDevicePathNode->SubType == MEDIA_FILEPATH_DP)) | |
{ | |
FileName = ((FILEPATH_DEVICE_PATH*)PrevDevicePathNode)->PathName; | |
} else { | |
FileName = NULL; | |
} | |
if (FileName == NULL) { | |
Print (L"Is an EFI Application? "); | |
Status = GetHIInputBoolean (EfiBinary); | |
if (EFI_ERROR (Status)) { | |
return EFI_ABORTED; | |
} | |
} else if (HasFilePathEfiExtension (FileName)) { | |
*EfiBinary = TRUE; | |
} else { | |
// Check if the file exist | |
Status = BdsLoadImage (DevicePath, AllocateAnyPages, &Image, &FileSize); | |
if (!EFI_ERROR (Status)) { | |
DosHeader = (EFI_IMAGE_DOS_HEADER *)(UINTN) Image; | |
if (DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE) { | |
// | |
// DOS image header is present, | |
// so read the PE header after the DOS image header. | |
// | |
PeCoffHeaderOffset = DosHeader->e_lfanew; | |
} else { | |
PeCoffHeaderOffset = 0; | |
} | |
// | |
// Check PE/COFF image. | |
// | |
NtHeader = (EFI_IMAGE_NT_HEADERS32 *)(UINTN) (Image + PeCoffHeaderOffset); | |
if (NtHeader->Signature != EFI_IMAGE_NT_SIGNATURE) { | |
*EfiBinary = FALSE; | |
} else { | |
*EfiBinary = TRUE; | |
} | |
// Free memory | |
gBS->FreePages (Image, EFI_SIZE_TO_PAGES (FileSize)); | |
} else { | |
// If we did not manage to open it then ask for the type | |
Print (L"Is an EFI Application? "); | |
Status = GetHIInputBoolean (EfiBinary); | |
if (EFI_ERROR (Status)) { | |
return EFI_ABORTED; | |
} | |
} | |
} | |
return EFI_SUCCESS; | |
} |