/** @file Load EFI driver from Firmware Volume. ;****************************************************************************** ;* Copyright (c) 2020, Insyde Software Corporation. All Rights Reserved. ;* ;* You may not reproduce, distribute, publish, display, perform, modify, adapt, ;* transmit, broadcast, present, recite, release, license or otherwise exploit ;* any part of this publication in any form, by any means, without the prior ;* written permission of Insyde Software Corporation. ;* ;****************************************************************************** */ #include "L05DxeServiceBody.h" /** Load EFI driver from Firmware Volume by GUID. @param NameGuid GUID File Name @retval None **/ EFI_STATUS L05LoadEfiDriverFromFv ( IN EFI_GUID *NameGuid ) { EFI_STATUS Status; UINTN HandleCount; EFI_HANDLE *HandleBuffer; EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; EFI_FV_FILETYPE Type; UINTN Size; EFI_FV_FILE_ATTRIBUTES Attributes; UINT32 AuthenticationStatus; UINTN Index; EFI_HANDLE ImageHandle; EFI_DEVICE_PATH_PROTOCOL *FileDevicePath; MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FwVolFilePathNode; H2O_BDS_SERVICES_PROTOCOL *BdsServices; H2O_BDS_LOAD_OPTION *BdsLoadOption; CHAR16 *OsRecoveryOptionalData; UINTN ExitDataSize; CHAR16 *ExitData; Status = EFI_SUCCESS; HandleCount = 0; HandleBuffer = NULL; Type = 0; Size = 0; Attributes = 0; AuthenticationStatus = 0; Index = 0; FileDevicePath = NULL; BdsServices = NULL; BdsLoadOption = NULL; OsRecoveryOptionalData = NULL; ExitDataSize = 0; ExitData = NULL; Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiFirmwareVolume2ProtocolGuid, NULL, &HandleCount, &HandleBuffer ); if (EFI_ERROR (Status) || HandleCount == 0) { return Status; } Status = gBS->LocateProtocol ( &gH2OBdsServicesProtocolGuid, NULL, (VOID **) &BdsServices ); if (EFI_ERROR (Status)) { FreePool (HandleBuffer); return Status; } // // Loop through all the Firmware Volumes looking for the GUID Filename // for (Index = 0; Index < HandleCount; Index++) { Status = gBS->HandleProtocol ( HandleBuffer[Index], &gEfiFirmwareVolume2ProtocolGuid, (VOID **) &Fv ); if (EFI_ERROR (Status)) { continue; } Size = 0; Status = Fv->ReadFile ( Fv, NameGuid, NULL, &Size, &Type, &Attributes, &AuthenticationStatus ); if (EFI_ERROR (Status)) { // // Skip if no specifie file in the fv // continue; } // // Get fv device path // FileDevicePath = DevicePathFromHandle (HandleBuffer[Index]); // // Get the device path of the efi with file guid // EfiInitializeFwVolDevicepathNode (&FwVolFilePathNode, NameGuid); // // Append efi device path to fv device path // FileDevicePath = AppendDevicePathNode ( FileDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &FwVolFilePathNode ); break; } FreePool (HandleBuffer); if (FileDevicePath == NULL) { // // Cannot to find efi driver from fv // return EFI_NOT_FOUND; } Status = gBS->LoadImage ( FALSE, gImageHandle, FileDevicePath, NULL, 0, &ImageHandle ); if (EFI_ERROR (Status)) { FreePool (FileDevicePath); return Status; } Status = BdsServices->CreateLoadOption ( BdsServices, BOOT_OPTION, NULL, // OptionName NULL, // OptionGuid LOAD_OPTION_ACTIVE, FileDevicePath, NULL, // Description (UINT8 *) OsRecoveryOptionalData, (UINT32) 0, &BdsLoadOption ); if (EFI_ERROR (Status)) { FreePool (FileDevicePath); return Status; } Status = BdsServices->LaunchLoadOption ( BdsServices, BdsLoadOption, &ExitDataSize, &ExitData ); FreePool (FileDevicePath); FreePool (BdsLoadOption); return Status; }