/** @file * * 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 * 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" /** 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 ) { 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; EFI_HANDLE *HandleBuffer; UINTN NumberOfHandles; UINTN Index; EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance; 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; } *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; } // 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); } } } 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; 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; } } FREE_HANDLE_BUFFER: // // Free any allocated buffers // FreePool (HandleBuffer); if (*DevicePath == NULL) { return EFI_NOT_FOUND; } else { return EFI_SUCCESS; } }