From 0c72676d371f8a2988f1fae958da696444e70672 Mon Sep 17 00:00:00 2001 From: Olivier Martin Date: Tue, 14 Jul 2015 14:30:08 +0000 Subject: [PATCH] ArmPkg/BdsLib: Replaced BdsLoadApplication() by LocateEfiApplicationInFv() Replaced the function BdsLoadApplication() by two explicit functions that load the EFI application either by its GUID or its Name. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Olivier Martin Reviewed-by: Ronald Cron git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17966 6f19259b-4bc3-4df7-8a09-765794883524 --- ArmPkg/Include/Library/BdsLib.h | 52 +++-- ArmPkg/Library/BdsLib/BdsAppLoader.c | 283 +++++++++++++++++++-------- ArmPlatformPkg/Bds/Bds.inf | 3 + ArmPlatformPkg/Bds/BootMenu.c | 24 ++- 4 files changed, 250 insertions(+), 112 deletions(-) diff --git a/ArmPkg/Include/Library/BdsLib.h b/ArmPkg/Include/Library/BdsLib.h index c6416db8ae..3d9e1954f3 100644 --- a/ArmPkg/Include/Library/BdsLib.h +++ b/ArmPkg/Include/Library/BdsLib.h @@ -193,24 +193,6 @@ BdsStartEfiApplication ( IN VOID* LoadOptions ); -/** - Start an EFI Application from any Firmware Volume - - @param EfiApp EFI Application Name - - @retval EFI_SUCCESS All drivers have been connected - @retval EFI_NOT_FOUND The Linux kernel Device Path has not been found - @retval EFI_OUT_OF_RESOURCES There is not enough resource memory to store the matching results. - -**/ -EFI_STATUS -BdsLoadApplication ( - IN EFI_HANDLE ParentImageHandle, - IN CHAR16* EfiApp, - IN UINTN LoadOptionsSize, - IN VOID* LoadOptions - ); - EFI_STATUS BdsLoadImage ( IN EFI_DEVICE_PATH *DevicePath, @@ -227,4 +209,38 @@ ShutdownUefiBootServices ( VOID ); +/** + Locate an EFI application in a the Firmware Volumes by its name + + @param EfiAppGuid Guid of the EFI Application into the Firmware Volume + @param DevicePath EFI Device Path of the EFI application + + @return EFI_SUCCESS The function completed successfully. + @return EFI_NOT_FOUND The protocol could not be located. + @return EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol. + +**/ +EFI_STATUS +LocateEfiApplicationInFvByName ( + IN CONST CHAR16* EfiAppName, + OUT EFI_DEVICE_PATH **DevicePath + ); + +/** + Locate an EFI application in a the Firmware Volumes by its GUID + + @param EfiAppGuid Guid of the EFI Application into the Firmware Volume + @param DevicePath EFI Device Path of the EFI application + + @return EFI_SUCCESS The function completed successfully. + @return EFI_NOT_FOUND The protocol could not be located. + @return EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol. + +**/ +EFI_STATUS +LocateEfiApplicationInFvByGuid ( + IN CONST EFI_GUID *EfiAppGuid, + OUT EFI_DEVICE_PATH **DevicePath + ); + #endif diff --git a/ArmPkg/Library/BdsLib/BdsAppLoader.c b/ArmPkg/Library/BdsLib/BdsAppLoader.c index 2b88bf1e05..1f208f8dd7 100644 --- a/ArmPkg/Library/BdsLib/BdsAppLoader.c +++ b/ArmPkg/Library/BdsLib/BdsAppLoader.c @@ -1,6 +1,6 @@ /** @file * -* Copyright (c) 2011-2012, ARM Limited. All rights reserved. +* 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 @@ -14,18 +14,23 @@ #include "BdsInternal.h" -//#include +/** + Locate an EFI application in a the Firmware Volumes by its Name + + @param EfiAppGuid Guid of the EFI Application into the Firmware Volume + @param DevicePath EFI Device Path of the EFI application + + @return EFI_SUCCESS The function completed successfully. + @return EFI_NOT_FOUND The protocol could not be located. + @return EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol. -STATIC +**/ EFI_STATUS -BdsLoadFileFromFirmwareVolume ( - IN EFI_HANDLE FvHandle, - IN CHAR16 *FilePath, - IN EFI_FV_FILETYPE FileTypeFilter, - OUT EFI_DEVICE_PATH **EfiAppDevicePath +LocateEfiApplicationInFvByName ( + IN CONST CHAR16* EfiAppName, + OUT EFI_DEVICE_PATH **DevicePath ) { - EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol; VOID *Key; EFI_STATUS Status, FileStatus; EFI_GUID NameGuid; @@ -37,108 +42,212 @@ BdsLoadFileFromFirmwareVolume ( UINT32 Authentication; EFI_DEVICE_PATH *FvDevicePath; MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileDevicePath; + EFI_HANDLE *HandleBuffer; + UINTN NumberOfHandles; + UINTN Index; + EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance; - Status = gBS->HandleProtocol (FvHandle,&gEfiFirmwareVolume2ProtocolGuid, (VOID **)&FvProtocol); - if (EFI_ERROR(Status)) { - return Status; - } + ASSERT (DevicePath != NULL); // Length of FilePath - UiStringLen = StrLen (FilePath); - - // Allocate Key - Key = AllocatePool (FvProtocol->KeySize); - ASSERT (Key != NULL); - ZeroMem (Key, FvProtocol->KeySize); + UiStringLen = StrLen (EfiAppName); + + // Locate all the Firmware Volume protocols. + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolume2ProtocolGuid, + NULL, + &NumberOfHandles, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } - do { - // Search in all files - FileType = FileTypeFilter; + *DevicePath = NULL; + + // Looking for FV with ACPI storage file + for (Index = 0; Index < NumberOfHandles; Index++) { + // + // Get the protocol on this handle + // This should not fail because of LocateHandleBuffer + // + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiFirmwareVolume2ProtocolGuid, + (VOID**) &FvInstance + ); + if (EFI_ERROR (Status)) { + goto FREE_HANDLE_BUFFER; + } - Status = FvProtocol->GetNextFile (FvProtocol, Key, &FileType, &NameGuid, &Attributes, &Size); - if (!EFI_ERROR (Status)) { - UiSection = NULL; - FileStatus = FvProtocol->ReadSection ( - FvProtocol, - &NameGuid, - EFI_SECTION_USER_INTERFACE, - 0, - (VOID **)&UiSection, - &Size, - &Authentication - ); - if (!EFI_ERROR (FileStatus)) { - if (StrnCmp (FilePath, UiSection, UiStringLen) == 0) { - // - // We found a UiString match. - // - Status = gBS->HandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath); - - // Generate the Device Path for the file - //DevicePath = DuplicateDevicePath(FvDevicePath); - EfiInitializeFwVolDevicepathNode (&FileDevicePath, &NameGuid); - *EfiAppDevicePath = AppendDevicePathNode (FvDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&FileDevicePath); - - FreePool (Key); + // Allocate Key + Key = AllocatePool (FvInstance->KeySize); + ASSERT (Key != NULL); + ZeroMem (Key, FvInstance->KeySize); + + do { + // Search in all files + FileType = EFI_FV_FILETYPE_ALL; + + Status = FvInstance->GetNextFile (FvInstance, Key, &FileType, &NameGuid, &Attributes, &Size); + if (!EFI_ERROR (Status)) { + UiSection = NULL; + FileStatus = FvInstance->ReadSection ( + FvInstance, + &NameGuid, + EFI_SECTION_USER_INTERFACE, + 0, + (VOID **)&UiSection, + &Size, + &Authentication + ); + if (!EFI_ERROR (FileStatus)) { + if (StrnCmp (EfiAppName, UiSection, UiStringLen) == 0) { + // + // We found a UiString match. + // + Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath); + + // Generate the Device Path for the file + EfiInitializeFwVolDevicepathNode (&FileDevicePath, &NameGuid); + *DevicePath = AppendDevicePathNode (FvDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&FileDevicePath); + ASSERT (*DevicePath != NULL); + + FreePool (Key); + FreePool (UiSection); + FreePool (HandleBuffer); + return FileStatus; + } FreePool (UiSection); - return FileStatus; } - FreePool (UiSection); } - } - } while (!EFI_ERROR (Status)); + } while (!EFI_ERROR (Status)); - FreePool(Key); - return Status; + FreePool (Key); + } + +FREE_HANDLE_BUFFER: + FreePool (HandleBuffer); + return EFI_NOT_FOUND; } /** - Start an EFI Application from any Firmware Volume + Locate an EFI application in a the Firmware Volumes by its GUID - @param EfiApp EFI Application Name + @param EfiAppGuid Guid of the EFI Application into the Firmware Volume + @param DevicePath EFI Device Path of the EFI application - @retval EFI_SUCCESS All drivers have been connected - @retval EFI_NOT_FOUND The Linux kernel Device Path has not been found - @retval EFI_OUT_OF_RESOURCES There is not enough resource memory to store the matching results. + @return EFI_SUCCESS The function completed successfully. + @return EFI_NOT_FOUND The protocol could not be located. + @return EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol. **/ EFI_STATUS -BdsLoadApplication ( - IN EFI_HANDLE ParentImageHandle, - IN CHAR16* EfiApp, - IN UINTN LoadOptionsSize, - IN VOID* LoadOptions +LocateEfiApplicationInFvByGuid ( + IN CONST EFI_GUID *EfiAppGuid, + OUT EFI_DEVICE_PATH **DevicePath ) { - EFI_STATUS Status; - UINTN NoHandles, HandleIndex; - EFI_HANDLE *Handles; - EFI_DEVICE_PATH *EfiAppDevicePath; - - // Need to connect every drivers to ensure no dependencies are missing for the application - Status = BdsConnectAllDrivers(); - if (EFI_ERROR(Status)) { - DEBUG ((EFI_D_ERROR, "FAIL to connect all drivers\n")); + EFI_STATUS Status; + EFI_DEVICE_PATH *FvDevicePath; + EFI_HANDLE *HandleBuffer; + UINTN NumberOfHandles; + UINTN Index; + EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance; + EFI_FV_FILE_ATTRIBUTES Attributes; + UINT32 AuthenticationStatus; + EFI_FV_FILETYPE Type; + UINTN Size; + CHAR16 *UiSection; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FvFileDevicePath; + + ASSERT (DevicePath != NULL); + + // Locate all the Firmware Volume protocols. + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolume2ProtocolGuid, + NULL, + &NumberOfHandles, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { return Status; } - // Search the application in any Firmware Volume - Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiFirmwareVolume2ProtocolGuid, NULL, &NoHandles, &Handles); - if (EFI_ERROR (Status) || (NoHandles == 0)) { - DEBUG ((EFI_D_ERROR, "FAIL to find Firmware Volume\n")); - return Status; - } + *DevicePath = NULL; + + // Looking for FV with ACPI storage file + for (Index = 0; Index < NumberOfHandles; Index++) { + // + // Get the protocol on this handle + // This should not fail because of LocateHandleBuffer + // + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiFirmwareVolume2ProtocolGuid, + (VOID**) &FvInstance + ); + if (EFI_ERROR (Status)) { + goto FREE_HANDLE_BUFFER; + } - // Search in all Firmware Volume for the EFI Application - for (HandleIndex = 0; HandleIndex < NoHandles; HandleIndex++) { - EfiAppDevicePath = NULL; - Status = BdsLoadFileFromFirmwareVolume (Handles[HandleIndex], EfiApp, EFI_FV_FILETYPE_APPLICATION, &EfiAppDevicePath); - if (!EFI_ERROR (Status)) { - // Start the application - Status = BdsStartEfiApplication (ParentImageHandle, EfiAppDevicePath, LoadOptionsSize, LoadOptions); - return Status; + Status = FvInstance->ReadFile ( + FvInstance, + EfiAppGuid, + NULL, + &Size, + &Type, + &Attributes, + &AuthenticationStatus + ); + if (EFI_ERROR (Status)) { + // + // Skip if no EFI application file in the FV + // + continue; + } else { + UiSection = NULL; + Status = FvInstance->ReadSection ( + FvInstance, + EfiAppGuid, + EFI_SECTION_USER_INTERFACE, + 0, + (VOID **)&UiSection, + &Size, + &AuthenticationStatus + ); + if (!EFI_ERROR (Status)) { + // + // Create the EFI Device Path for the application using the Filename of the application + // + *DevicePath = FileDevicePath (HandleBuffer[Index], UiSection); + } else { + Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID**)&FvDevicePath); + ASSERT_EFI_ERROR (Status); + + // + // Create the EFI Device Path for the application using the EFI GUID of the application + // + EfiInitializeFwVolDevicepathNode (&FvFileDevicePath, EfiAppGuid); + + *DevicePath = AppendDevicePathNode (FvDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&FvFileDevicePath); + ASSERT (*DevicePath != NULL); + } + break; } } - return Status; +FREE_HANDLE_BUFFER: + // + // Free any allocated buffers + // + FreePool (HandleBuffer); + + if (*DevicePath == NULL) { + return EFI_NOT_FOUND; + } else { + return EFI_SUCCESS; + } } diff --git a/ArmPlatformPkg/Bds/Bds.inf b/ArmPlatformPkg/Bds/Bds.inf index f4c0f1c55d..76a45e03e5 100644 --- a/ArmPlatformPkg/Bds/Bds.inf +++ b/ArmPlatformPkg/Bds/Bds.inf @@ -37,6 +37,7 @@ ArmPkg/ArmPkg.dec ArmPlatformPkg/ArmPlatformPkg.dec EmbeddedPkg/EmbeddedPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec [LibraryClasses] BdsLib @@ -79,5 +80,7 @@ gArmPlatformTokenSpaceGuid.PcdDefaultConInPaths gArmPlatformTokenSpaceGuid.PcdDefaultConOutPaths + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile + [Depex] TRUE diff --git a/ArmPlatformPkg/Bds/BootMenu.c b/ArmPlatformPkg/Bds/BootMenu.c index d2dccbc9f2..a304cc4ce9 100644 --- a/ArmPlatformPkg/Bds/BootMenu.c +++ b/ArmPlatformPkg/Bds/BootMenu.c @@ -1069,17 +1069,27 @@ BootShell ( IN LIST_ENTRY *BootOptionsList ) { - EFI_STATUS Status; + EFI_STATUS Status; + EFI_DEVICE_PATH* EfiShellDevicePath; - // Start EFI Shell - Status = BdsLoadApplication (gImageHandle, L"Shell", 0, NULL); + // Find the EFI Shell + Status = LocateEfiApplicationInFvByName (L"Shell", &EfiShellDevicePath); if (Status == EFI_NOT_FOUND) { Print (L"Error: EFI Application not found.\n"); - } else if (EFI_ERROR(Status)) { - Print (L"Error: Status Code: 0x%X\n",(UINT32)Status); - } + return Status; + } else if (EFI_ERROR (Status)) { + Print (L"Error: Status Code: 0x%X\n", (UINT32)Status); + return Status; + } else { + // Need to connect every drivers to ensure no dependencies are missing for the application + Status = BdsConnectAllDrivers (); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "FAIL to connect all drivers\n")); + return Status; + } - return Status; + return BdsStartEfiApplication (gImageHandle, EfiShellDevicePath, 0, NULL); + } } struct BOOT_MAIN_ENTRY { -- 2.39.2