From 55a9f75d149ea53d1c8b3da197ec344c2aedb848 Mon Sep 17 00:00:00 2001 From: Olivier Martin Date: Fri, 11 Apr 2014 10:57:47 +0000 Subject: [PATCH] ArmPlatformPkg/Bds: Added support to detect if the binary is a EFI image Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Olivier Martin git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15453 6f19259b-4bc3-4df7-8a09-765794883524 --- ArmPlatformPkg/Bds/BdsInternal.h | 11 +- ArmPlatformPkg/Bds/BootMenu.c | 34 ++++- ArmPlatformPkg/Bds/BootOptionSupport.c | 174 +++++++++++++------------ 3 files changed, 130 insertions(+), 89 deletions(-) diff --git a/ArmPlatformPkg/Bds/BdsInternal.h b/ArmPlatformPkg/Bds/BdsInternal.h index 085a5a49ef..da7b8ca704 100644 --- a/ArmPlatformPkg/Bds/BdsInternal.h +++ b/ArmPlatformPkg/Bds/BdsInternal.h @@ -102,8 +102,8 @@ typedef struct _BDS_LOAD_OPTION_SUPPORT { BDS_SUPPORTED_DEVICE_TYPE Type; EFI_STATUS (*ListDevices)(IN OUT LIST_ENTRY* BdsLoadOptionList); BOOLEAN (*IsSupported)(IN EFI_DEVICE_PATH *DevicePath); - EFI_STATUS (*CreateDevicePathNode)(IN CHAR16* FileName, OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes, OUT ARM_BDS_LOADER_TYPE *BootType, OUT UINT32 *Attributes); - EFI_STATUS (*UpdateDevicePathNode)(IN EFI_DEVICE_PATH *OldDevicePath, IN CHAR16* FileName, OUT EFI_DEVICE_PATH_PROTOCOL** NewDevicePath, OUT ARM_BDS_LOADER_TYPE *BootType, OUT UINT32 *Attributes); + EFI_STATUS (*CreateDevicePathNode)(IN CHAR16* FileName, OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes, OUT BOOLEAN *RequestBootType); + EFI_STATUS (*UpdateDevicePathNode)(IN EFI_DEVICE_PATH *OldDevicePath, IN CHAR16* FileName, OUT EFI_DEVICE_PATH_PROTOCOL** NewDevicePath, OUT BOOLEAN *RequestBootType); } BDS_LOAD_OPTION_SUPPORT; #define LOAD_OPTION_ENTRY_FROM_LINK(a) BASE_CR(a, BDS_LOAD_OPTION_ENTRY, Link) @@ -240,6 +240,13 @@ BootOptionDelete ( IN BDS_LOAD_OPTION *BootOption ); +EFI_STATUS +BootDeviceGetType ( + IN EFI_DEVICE_PATH* DevicePath, + OUT ARM_BDS_LOADER_TYPE *BootType, + OUT UINT32 *Attributes + ); + EFI_STATUS BootMenuMain ( VOID diff --git a/ArmPlatformPkg/Bds/BootMenu.c b/ArmPlatformPkg/Bds/BootMenu.c index 9ca703842f..e00d06e394 100644 --- a/ArmPlatformPkg/Bds/BootMenu.c +++ b/ArmPlatformPkg/Bds/BootMenu.c @@ -134,6 +134,7 @@ BootMenuAddBootOption ( UINTN InitrdSize; UINT8* OptionalData; UINTN OptionalDataSize; + BOOLEAN RequestBootType; Attributes = 0; SupportedBootDevice = NULL; @@ -146,7 +147,8 @@ BootMenuAddBootOption ( } // Create the specific device path node - Status = SupportedBootDevice->Support->CreateDevicePathNode (L"EFI Application or the kernel", &DevicePathNodes, &BootType, &Attributes); + RequestBootType = TRUE; + Status = SupportedBootDevice->Support->CreateDevicePathNode (L"EFI Application or the kernel", &DevicePathNodes, &RequestBootType); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; goto EXIT; @@ -158,6 +160,16 @@ BootMenuAddBootOption ( goto EXIT; } + if (RequestBootType) { + Status = BootDeviceGetType (DevicePath, &BootType, &Attributes); + if (EFI_ERROR(Status)) { + Status = EFI_ABORTED; + goto EXIT; + } + } else { + BootType = BDS_LOADER_EFI_APPLICATION; + } + if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) { Print(L"Add an initrd: "); Status = GetHIInputBoolean (&InitrdSupport); @@ -168,7 +180,7 @@ BootMenuAddBootOption ( if (InitrdSupport) { // Create the specific device path node - Status = SupportedBootDevice->Support->CreateDevicePathNode (L"initrd", &InitrdPathNodes, NULL, NULL); + Status = SupportedBootDevice->Support->CreateDevicePathNode (L"initrd", &InitrdPathNodes, NULL); if (EFI_ERROR(Status) && Status != EFI_NOT_FOUND) { // EFI_NOT_FOUND is returned on empty input string, but we can boot without an initrd Status = EFI_ABORTED; goto EXIT; @@ -390,6 +402,7 @@ BootMenuUpdateBootOption ( BOOLEAN InitrdSupport; UINT8* OptionalData; UINTN OptionalDataSize; + BOOLEAN RequestBootType; Status = BootMenuSelectBootOption (BootOptionsList, UPDATE_BOOT_ENTRY, TRUE, &BootOptionEntry); if (EFI_ERROR(Status)) { @@ -404,12 +417,21 @@ BootMenuUpdateBootOption ( return EFI_UNSUPPORTED; } - Status = DeviceSupport->UpdateDevicePathNode (BootOption->FilePathList, L"EFI Application or the kernel", &DevicePath, NULL, NULL); + RequestBootType = TRUE; + Status = DeviceSupport->UpdateDevicePathNode (BootOption->FilePathList, L"EFI Application or the kernel", &DevicePath, &RequestBootType); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; goto EXIT; } + if (RequestBootType) { + Status = BootDeviceGetType (DevicePath, &BootType, &BootOption->Attributes); + if (EFI_ERROR(Status)) { + Status = EFI_ABORTED; + goto EXIT; + } + } + LoaderOptionalData = BootOption->OptionalData; BootType = (ARM_BDS_LOADER_TYPE)ReadUnaligned32 ((UINT32 *)(&LoaderOptionalData->Header.LoaderType)); @@ -433,7 +455,7 @@ BootMenuUpdateBootOption ( if (InitrdSupport) { if (InitrdSize > 0) { // Case we update the initrd device path - Status = DeviceSupport->UpdateDevicePathNode ((EFI_DEVICE_PATH*)((UINTN)(LinuxArguments + 1) + CmdLineSize), L"initrd", &InitrdPath, NULL, NULL); + Status = DeviceSupport->UpdateDevicePathNode ((EFI_DEVICE_PATH*)((UINTN)(LinuxArguments + 1) + CmdLineSize), L"initrd", &InitrdPath, NULL); if (EFI_ERROR(Status) && Status != EFI_NOT_FOUND) {// EFI_NOT_FOUND is returned on empty input string, but we can boot without an initrd Status = EFI_ABORTED; goto EXIT; @@ -442,7 +464,7 @@ BootMenuUpdateBootOption ( } else { // Case we create the initrd device path - Status = DeviceSupport->CreateDevicePathNode (L"initrd", &InitrdPathNodes, NULL, NULL); + Status = DeviceSupport->CreateDevicePathNode (L"initrd", &InitrdPathNodes, NULL); if (EFI_ERROR(Status) && Status != EFI_NOT_FOUND) { // EFI_NOT_FOUND is returned on empty input string, but we can boot without an initrd Status = EFI_ABORTED; goto EXIT; @@ -535,7 +557,7 @@ UpdateFdtPath ( } // Create the specific device path node - Status = SupportedBootDevice->Support->CreateDevicePathNode (L"FDT blob", &FdtDevicePathNodes, NULL, NULL); + Status = SupportedBootDevice->Support->CreateDevicePathNode (L"FDT blob", &FdtDevicePathNodes, NULL); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; goto EXIT; diff --git a/ArmPlatformPkg/Bds/BootOptionSupport.c b/ArmPlatformPkg/Bds/BootOptionSupport.c index 190169a304..dc70dc4a1e 100644 --- a/ArmPlatformPkg/Bds/BootOptionSupport.c +++ b/ArmPlatformPkg/Bds/BootOptionSupport.c @@ -1,6 +1,6 @@ /** @file * -* Copyright (c) 2011, ARM Limited. All rights reserved. +* Copyright (c) 2011-2014, 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 @@ -35,8 +35,7 @@ EFI_STATUS BdsLoadOptionFileSystemCreateDevicePath ( IN CHAR16* FileName, OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + OUT BOOLEAN *RequestBootType ); EFI_STATUS @@ -44,8 +43,7 @@ BdsLoadOptionFileSystemUpdateDevicePath ( IN EFI_DEVICE_PATH *OldDevicePath, IN CHAR16* FileName, OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + OUT BOOLEAN *RequestBootType ); BOOLEAN @@ -62,8 +60,7 @@ EFI_STATUS BdsLoadOptionMemMapCreateDevicePath ( IN CHAR16* FileName, OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + OUT BOOLEAN *RequestBootType ); EFI_STATUS @@ -71,8 +68,7 @@ BdsLoadOptionMemMapUpdateDevicePath ( IN EFI_DEVICE_PATH *OldDevicePath, IN CHAR16* FileName, OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + OUT BOOLEAN *RequestBootType ); BOOLEAN @@ -89,8 +85,7 @@ EFI_STATUS BdsLoadOptionPxeCreateDevicePath ( IN CHAR16* FileName, OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + OUT BOOLEAN *RequestBootType ); EFI_STATUS @@ -98,8 +93,7 @@ BdsLoadOptionPxeUpdateDevicePath ( IN EFI_DEVICE_PATH *OldDevicePath, IN CHAR16* FileName, OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + OUT BOOLEAN *RequestBootType ); BOOLEAN @@ -116,8 +110,7 @@ EFI_STATUS BdsLoadOptionTftpCreateDevicePath ( IN CHAR16* FileName, OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + OUT BOOLEAN *RequestBootType ); EFI_STATUS @@ -125,8 +118,7 @@ BdsLoadOptionTftpUpdateDevicePath ( IN EFI_DEVICE_PATH *OldDevicePath, IN CHAR16* FileName, OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + OUT BOOLEAN *RequestBootType ); BOOLEAN @@ -222,18 +214,44 @@ BootDeviceGetDeviceSupport ( return EFI_UNSUPPORTED; } -STATIC EFI_STATUS BootDeviceGetType ( - IN CHAR16* FileName, + IN EFI_DEVICE_PATH* DevicePath, OUT ARM_BDS_LOADER_TYPE *BootType, OUT UINT32 *Attributes ) { - EFI_STATUS Status; - BOOLEAN IsEfiApp; - BOOLEAN IsBootLoader; - BOOLEAN HasFDTSupport; + EFI_STATUS Status; + BOOLEAN IsEfiApp; + BOOLEAN IsBootLoader; + BOOLEAN HasFDTSupport; + 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; + + // + // 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? "); @@ -244,7 +262,41 @@ BootDeviceGetType ( } else if (HasFilePathEfiExtension(FileName)) { IsEfiApp = TRUE; } else { - IsEfiApp = FALSE; + // 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) { + IsEfiApp = FALSE; + } else { + IsEfiApp = 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 (&IsEfiApp); + if (EFI_ERROR(Status)) { + return EFI_ABORTED; + } + } } if (IsEfiApp) { @@ -333,8 +385,7 @@ EFI_STATUS BdsLoadOptionFileSystemCreateDevicePath ( IN CHAR16* FileName, OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + OUT BOOLEAN *RequestBootType ) { EFI_STATUS Status; @@ -361,16 +412,7 @@ BdsLoadOptionFileSystemCreateDevicePath ( SetDevicePathNodeLength (FilePathDevicePath, SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize); CopyMem (FilePathDevicePath->PathName, BootFilePath, BootFilePathSize); SetDevicePathEndNode ((VOID*)((UINTN)FilePathDevicePath + SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize)); - - if (BootType != NULL || Attributes != NULL) { - Status = BootDeviceGetType (FilePathDevicePath->PathName, BootType, Attributes); - } - - if (EFI_ERROR(Status)) { - FreePool (FilePathDevicePath); - } else { - *DevicePathNodes = (EFI_DEVICE_PATH_PROTOCOL*)FilePathDevicePath; - } + *DevicePathNodes = (EFI_DEVICE_PATH_PROTOCOL*)FilePathDevicePath; return Status; } @@ -380,8 +422,7 @@ BdsLoadOptionFileSystemUpdateDevicePath ( IN EFI_DEVICE_PATH *OldDevicePath, IN CHAR16* FileName, OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + OUT BOOLEAN *RequestBootType ) { EFI_STATUS Status; @@ -420,10 +461,6 @@ BdsLoadOptionFileSystemUpdateDevicePath ( *NewDevicePath = AppendDevicePathNode (DevicePath, (CONST EFI_DEVICE_PATH_PROTOCOL *)FilePathDevicePath); FreePool(DevicePath); - if (BootType != NULL || Attributes != NULL) { - return BootDeviceGetType (FilePathDevicePath->PathName, BootType, Attributes); - } - return EFI_SUCCESS; } @@ -535,8 +572,7 @@ EFI_STATUS BdsLoadOptionMemMapCreateDevicePath ( IN CHAR16* FileName, OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + OUT BOOLEAN *RequestBootType ) { EFI_STATUS Status; @@ -567,16 +603,7 @@ BdsLoadOptionMemMapCreateDevicePath ( // Set a Device Path End Node after the Memory Map Device Path Node SetDevicePathEndNode (MemMapDevicePath + 1); - - if (BootType != NULL || Attributes != NULL) { - Status = BootDeviceGetType (NULL, BootType, Attributes); - } - - if (EFI_ERROR(Status)) { - FreePool (MemMapDevicePath); - } else { - *DevicePathNodes = (EFI_DEVICE_PATH_PROTOCOL*)MemMapDevicePath; - } + *DevicePathNodes = (EFI_DEVICE_PATH_PROTOCOL*)MemMapDevicePath; return Status; } @@ -586,8 +613,7 @@ BdsLoadOptionMemMapUpdateDevicePath ( IN EFI_DEVICE_PATH *OldDevicePath, IN CHAR16* FileName, OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + OUT BOOLEAN *RequestBootType ) { EFI_STATUS Status; @@ -616,10 +642,6 @@ BdsLoadOptionMemMapUpdateDevicePath ( EndingDevicePath->StartingAddress = StrHexToUint64 (StrStartingAddress); EndingDevicePath->EndingAddress = StrHexToUint64 (StrEndingAddress); - if (BootType != NULL || Attributes != NULL) { - Status = BootDeviceGetType (NULL, BootType, Attributes); - } - if (EFI_ERROR(Status)) { FreePool(DevicePath); } else { @@ -693,13 +715,15 @@ EFI_STATUS BdsLoadOptionPxeCreateDevicePath ( IN CHAR16* FileName, OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + OUT BOOLEAN *RequestBootType ) { *DevicePathNodes = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH); SetDevicePathEndNode (*DevicePathNodes); - *BootType = BDS_LOADER_EFI_APPLICATION; + + if (RequestBootType) { + *RequestBootType = FALSE; + } return EFI_SUCCESS; } @@ -708,12 +732,11 @@ BdsLoadOptionPxeUpdateDevicePath ( IN EFI_DEVICE_PATH *OldDevicePath, IN CHAR16* FileName, OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + OUT BOOLEAN *RequestBootType ) { ASSERT (0); - return EFI_SUCCESS; + return EFI_UNSUPPORTED; } BOOLEAN @@ -795,8 +818,7 @@ EFI_STATUS BdsLoadOptionTftpCreateDevicePath ( IN CHAR16* FileName, OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + OUT BOOLEAN *RequestBootType ) { EFI_STATUS Status; @@ -862,16 +884,7 @@ BdsLoadOptionTftpCreateDevicePath ( // Set the End Device Path Node SetDevicePathEndNode ((VOID*)((UINTN)FilePathDevicePath + SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize)); - - if (BootType != NULL || Attributes != NULL) { - Status = BootDeviceGetType (NULL, BootType, Attributes); - } - - if (EFI_ERROR(Status)) { - FreePool (IPv4DevicePathNode); - } else { - *DevicePathNodes = (EFI_DEVICE_PATH_PROTOCOL*)IPv4DevicePathNode; - } + *DevicePathNodes = (EFI_DEVICE_PATH_PROTOCOL*)IPv4DevicePathNode; return Status; } @@ -881,12 +894,11 @@ BdsLoadOptionTftpUpdateDevicePath ( IN EFI_DEVICE_PATH *OldDevicePath, IN CHAR16* FileName, OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath, - OUT ARM_BDS_LOADER_TYPE *BootType, - OUT UINT32 *Attributes + OUT BOOLEAN *RequestBootType ) { ASSERT (0); - return EFI_SUCCESS; + return EFI_UNSUPPORTED; } BOOLEAN -- 2.39.2