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 <olivier.mar...@arm.com> Reviewed-by: Ronald Cron <ronald.c...@arm.com> --- 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 c6416db..3d9e195 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 2b88bf1..1f208f8 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 <Library/DxeServicesLib.h> +/** + 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 f4c0f1c..76a45e0 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 d2dccbc..a304cc4 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.1.1 ------------------------------------------------------------------------------ Don't Limit Your Business. Reach for the Cloud. GigeNET's Cloud Solutions provide you with the tools and support that you need to offload your IT needs and focus on growing your business. Configured For All Businesses. Start Your Cloud Today. https://www.gigenetcloud.com/ _______________________________________________ edk2-devel mailing list edk2-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/edk2-devel