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 <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@17966 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Olivier Martin 2015-07-14 14:30:08 +00:00 committed by oliviermartin
parent 4fc18df913
commit 0c72676d37
4 changed files with 257 additions and 119 deletions

View File

@ -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

View File

@ -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
STATIC
@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
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)) {
ASSERT (DevicePath != NULL);
// Length of FilePath
UiStringLen = StrLen (EfiAppName);
// Locate all the Firmware Volume protocols.
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiFirmwareVolume2ProtocolGuid,
NULL,
&NumberOfHandles,
&HandleBuffer
);
if (EFI_ERROR (Status)) {
return Status;
}
// Length of FilePath
UiStringLen = StrLen (FilePath);
*DevicePath = NULL;
// Allocate Key
Key = AllocatePool (FvProtocol->KeySize);
ASSERT (Key != NULL);
ZeroMem (Key, FvProtocol->KeySize);
// 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;
}
do {
// Search in all files
FileType = FileTypeFilter;
// Allocate Key
Key = AllocatePool (FvInstance->KeySize);
ASSERT (Key != NULL);
ZeroMem (Key, FvInstance->KeySize);
Status = FvProtocol->GetNextFile (FvProtocol, Key, &FileType, &NameGuid, &Attributes, &Size);
if (!EFI_ERROR (Status)) {
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);
}
}
} while (!EFI_ERROR (Status));
FreePool (Key);
}
FREE_HANDLE_BUFFER:
FreePool (HandleBuffer);
return EFI_NOT_FOUND;
}
/**
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
)
{
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;
}
*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 = 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;
FileStatus = FvProtocol->ReadSection (
FvProtocol,
&NameGuid,
Status = FvInstance->ReadSection (
FvInstance,
EfiAppGuid,
EFI_SECTION_USER_INTERFACE,
0,
(VOID **)&UiSection,
&Size,
&Authentication
&AuthenticationStatus
);
if (!EFI_ERROR (FileStatus)) {
if (StrnCmp (FilePath, UiSection, UiStringLen) == 0) {
//
// We found a UiString match.
//
Status = gBS->HandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath);
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);
// Generate the Device Path for the file
//DevicePath = DuplicateDevicePath(FvDevicePath);
EfiInitializeFwVolDevicepathNode (&FileDevicePath, &NameGuid);
*EfiAppDevicePath = AppendDevicePathNode (FvDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&FileDevicePath);
//
// Create the EFI Device Path for the application using the EFI GUID of the application
//
EfiInitializeFwVolDevicepathNode (&FvFileDevicePath, EfiAppGuid);
FreePool (Key);
FreePool (UiSection);
return FileStatus;
}
FreePool (UiSection);
*DevicePath = AppendDevicePathNode (FvDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&FvFileDevicePath);
ASSERT (*DevicePath != NULL);
}
}
} while (!EFI_ERROR (Status));
FreePool(Key);
return Status;
}
/**
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 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"));
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;
}
// 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;
break;
}
}
return Status;
FREE_HANDLE_BUFFER:
//
// Free any allocated buffers
//
FreePool (HandleBuffer);
if (*DevicePath == NULL) {
return EFI_NOT_FOUND;
} else {
return EFI_SUCCESS;
}
}

View File

@ -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

View File

@ -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 {