/** @file | |
* | |
* Copyright (c) 2011-2012, 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" | |
//#include <Library/DxeServicesLib.h> | |
STATIC | |
EFI_STATUS | |
BdsLoadFileFromFirmwareVolume ( | |
IN EFI_HANDLE FvHandle, | |
IN CHAR16 *FilePath, | |
IN EFI_FV_FILETYPE FileTypeFilter, | |
OUT EFI_DEVICE_PATH **EfiAppDevicePath | |
) | |
{ | |
EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol; | |
VOID *Key; | |
EFI_STATUS Status, FileStatus; | |
EFI_GUID NameGuid; | |
EFI_FV_FILETYPE FileType; | |
EFI_FV_FILE_ATTRIBUTES Attributes; | |
UINTN Size; | |
UINTN UiStringLen; | |
CHAR16 *UiSection; | |
UINT32 Authentication; | |
EFI_DEVICE_PATH *FvDevicePath; | |
MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileDevicePath; | |
Status = gBS->HandleProtocol (FvHandle,&gEfiFirmwareVolume2ProtocolGuid, (VOID **)&FvProtocol); | |
if (EFI_ERROR(Status)) { | |
return Status; | |
} | |
// Length of FilePath | |
UiStringLen = StrLen (FilePath); | |
// Allocate Key | |
Key = AllocatePool (FvProtocol->KeySize); | |
ASSERT (Key != NULL); | |
ZeroMem (Key, FvProtocol->KeySize); | |
do { | |
// Search in all files | |
FileType = FileTypeFilter; | |
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); | |
FreePool (UiSection); | |
return FileStatus; | |
} | |
FreePool (UiSection); | |
} | |
} | |
} 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; | |
} | |
} | |
return Status; | |
} |