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