alder_lake_bios/Oem/L05/FeatureCommon/InsydeL05ModulePkg/ServiceBody/L05LoadEfiDriverFromFv/L05LoadEfiDriverFromFv.c

192 lines
5.3 KiB
C

/** @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;
}