Olivier Martin 5d9e9d1a1c ArmPlatformPkg/Bds: Added support for booting legacy kernel from BDS
When PcdBdsLinuxSupport is enabled, users can create boot
entries for the legacy EFI Linux loader.

The ARM BDS detects if the image is a EFI image if not
then it assumes it is a legacy Linux kernel (a kernel
without EFI Stub).
If the Boot Manager did not manage to load the binary
(it could happen when the binary is on the network or
not present on the media yet).

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Olivier Martin <Olivier.Martin@arm.com>
Reviewed-by: Ronald Cron <Ronald.Cron@arm.com>



git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17974 6f19259b-4bc3-4df7-8a09-765794883524
2015-07-14 14:41:46 +00:00

125 lines
3.8 KiB
C

/** @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;
}