alder_lake_bios/Insyde/InsydeModulePkg/Library/Irsi/IrsiLib/FvRegionAccessLib/FvRegionAccessLib.c

374 lines
11 KiB
C

/** @file
Library Instance implementation for FV Region Read/Write
;******************************************************************************
;* Copyright (c) 2012 - 2019, Insyde Software Corp. 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 <PiDxe.h>
#include <Library/BaseLib.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/IrsiLib.h>
#include <Library/IrsiRegistrationLib.h>
#include <Library/DebugLib.h>
#include <Protocol/FirmwareManagement.h>
#include <Protocol/LoadedImage.h>
#define GET_IMAGE_PROGRESS_NAME L"GetImageProgress"
STATIC EFI_GUID mFirmwareManagementRuntimeDxeFileGuid = { 0xb795675e, 0x7583, 0x4f98, { 0xac, 0x6a, 0xf9, 0xdd, 0xbb, 0xcc, 0x32, 0xe8 } };
STATIC EFI_FIRMWARE_MANAGEMENT_PROTOCOL *mFirmwareManagement = NULL;
STATIC UINT8 *mProgress;
STATIC EFI_RUNTIME_SERVICES *mRT;
/**
Get the ImageIndex for the specified ImageTypeGuid
@param[in] ImageTypeGuid Pointer to the image type GUID
@return The ImageIndex for the specified ImageTypeGuid
A value of 0xFF means the Image cannot be found
*/
UINT8
EFIAPI
GetImageIndex (
EFI_GUID *ImageTypeGuid
)
{
UINTN ImageInfoSize;
EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageInfo;
UINT32 DescriptorVersion;
UINT8 DescriptorCount;
UINTN DescriptorSize;
UINT8 *IrsiBuf;
UINTN IrsiBufSize;
UINTN Index;
EFI_STATUS Status;
if (mFirmwareManagement == NULL) {
ASSERT (mFirmwareManagement != NULL);
return 0xFF;
}
ImageInfoSize = 0;
DescriptorCount = 0;
ImageInfo = NULL;
Status = mFirmwareManagement->GetImageInfo (
mFirmwareManagement,
&ImageInfoSize,
ImageInfo,
&DescriptorVersion,
&DescriptorCount,
&DescriptorSize,
NULL,
NULL
);
if (Status != EFI_BUFFER_TOO_SMALL) {
ASSERT(Status == EFI_BUFFER_TOO_SMALL);
return 0xFF;
}
IrsiGetRuntimeBuffer((VOID **)&IrsiBuf, &IrsiBufSize);
ASSERT (IrsiBuf != NULL);
if (IrsiBuf == NULL) {
return 0xFF;
}
ImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)IrsiBuf;
Status = mFirmwareManagement->GetImageInfo (
mFirmwareManagement,
&ImageInfoSize,
ImageInfo,
&DescriptorVersion,
&DescriptorCount,
&DescriptorSize,
NULL,
NULL
);
if (EFI_ERROR(Status)) {
return 0xFF;
}
for (Index = 0; Index < (UINTN)DescriptorCount; Index++) {
if (CompareGuid(ImageTypeGuid, &ImageInfo[Index].ImageTypeId)) {
return ImageInfo[Index].ImageIndex;
}
}
return 0xFF;
}
/**
Update percentage of progress for FirmwareManagementProtocol.SetImage()
@param[in] Completion Percentage (1 to 100) of completion
A zero value means the completion status is not supported
@retval EFI_SUCCESS function returns successfully
*/
EFI_STATUS
EFIAPI
UpdateProgress (
IN UINTN Completion
)
{
if (mProgress != NULL) {
*mProgress = (UINT8)Completion;
}
return EFI_SUCCESS;
}
/**
ReadFvRegion function
This routine reads image from platform with specific image GUID defined in
RegionBuf
@param[in] ImageTypeGuid Pointer to the image type GUID
@param[in, out] ImageSize Pointer to the read image size
@param[in] RegionBuf The region buffer
@param[out] Progress The current progress update (0 to 100)
@retval EFI_SUCCESS The FV region was successfully retrieved
@retval EFI_INVALID_PARAMETER Invalid parameter list
@retval EFI_BUFFER_TOO_SMALL The given ImageSize is too small
@retval EFI_UNSUPPORTED Unsupported for the specified image type
@return others FV Region read failed
**/
EFI_STATUS
EFIAPI
ReadFvRegion (
IN EFI_GUID *ImageTypeGuid,
IN OUT UINTN *ImageSize,
OUT VOID *RegionBuf,
OUT UINT8 *Progress
)
{
EFI_STATUS Status;
UINT8 ImageIndex;
EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS ProgressFun;
ImageIndex = GetImageIndex (ImageTypeGuid);
if (ImageIndex == 0xFF) {
return EFI_UNSUPPORTED;
}
mProgress = Progress;
if (Progress != NULL) {
*Progress = 0;
ProgressFun = UpdateProgress;
Status = mRT->SetVariable (
GET_IMAGE_PROGRESS_NAME,
&gEfiFirmwareManagementProtocolGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
sizeof (EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS),
&ProgressFun
);
}
Status = mFirmwareManagement->GetImage (
mFirmwareManagement,
ImageIndex,
RegionBuf,
ImageSize
);
return Status;
}
/**
WriteFvRegion function
This routine write image to platform with specific capsule GUID defined in
RegionBuf
@param[in] ImageTypeGuid Pointer to the image type GUID
@param[in, out] ImageSize Pointer to the read image size
@param[in] RegionBuf The region buffer
@param[out] Progress The current progress update (0 to 100)
@retval EFI_SUCCESS The FV region was successfully written
@retval EFI_INVALID_PARAMETER Invalid parameter list
@retval EFI_BUFFER_TOO_SMALL The given ImageSize is too small
@retval EFI_UNSUPPORTED Unsupported for the specified image type
@return others FV Region write failed
**/
EFI_STATUS
EFIAPI
WriteFvRegion (
IN EFI_GUID *ImageTypeGuid,
IN UINTN ImageSize,
IN CONST VOID *RegionBuf,
OUT UINT8 *Progress
)
{
CHAR16 *AbortReason;
EFI_STATUS Status;
UINT8 ImageIndex;
UINT8 Sum8;
AbortReason = NULL;
mProgress = Progress;
ImageIndex = GetImageIndex (ImageTypeGuid);
if (ImageIndex == 0xFF) {
return EFI_UNSUPPORTED;
}
Sum8 = CalculateSum8(RegionBuf, ImageSize);
AbortReason = NULL;
Status = mFirmwareManagement->SetImage (
mFirmwareManagement,
ImageIndex,
RegionBuf,
ImageSize,
&Sum8,
UpdateProgress,
&AbortReason
);
if (AbortReason != NULL) {
FreePool (AbortReason);
}
return Status;
}
/**
Find Firmware Management Protocol instance
@retval Firmware Management Protocol instance
**/
EFI_FIRMWARE_MANAGEMENT_PROTOCOL*
EFIAPI
FindFirmwareManagementInstance (
VOID
)
{
EFI_STATUS Status;
EFI_GUID FileName;
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
EFI_FIRMWARE_MANAGEMENT_PROTOCOL *FirmwareManagement;
EFI_HANDLE *HandleBuffer;
UINTN HandleCount;
UINTN Index;
BOOLEAN Found;
HandleCount = 0;
HandleBuffer = NULL;
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiFirmwareManagementProtocolGuid,
NULL,
&HandleCount,
&HandleBuffer
);
if (EFI_ERROR (Status)) {
return NULL;
}
Found = FALSE;
FirmwareManagement = NULL;
for (Index = 0; Index < HandleCount && !Found; Index++) {
Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiFirmwareManagementProtocolGuid, (VOID **) &FirmwareManagement);
if (EFI_ERROR (Status)) {
continue;
}
Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiLoadedImageProtocolGuid, (VOID **) &LoadedImage);
if (EFI_ERROR (Status)) {
continue;
}
FileName = ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) (LoadedImage->FilePath))->FvFileName;
//
// Find the instance of FMP that distributes by FirmwareManagementRuntimeDxe
//
if (CompareGuid(&FileName, &mFirmwareManagementRuntimeDxeFileGuid)) {
Found = TRUE;
}
}
if (!Found) {
FirmwareManagement = NULL;
}
if (HandleCount != 0) {
FreePool(HandleBuffer);
}
return FirmwareManagement;
}
/**
Notification event handler to save Firmware Management Protocol instance
@param[in] Event The Event whose notification function is being invoked.
@param[in] Context Pointer to the notification function's context.
@retval None
**/
VOID
EFIAPI
FirmwareManagementNotify (
IN EFI_EVENT Event,
IN VOID *Context
)
{
mFirmwareManagement = FindFirmwareManagementInstance ();
if (mFirmwareManagement != NULL) {
IrsiAddVirtualPointer((VOID **)&mFirmwareManagement);
gBS->CloseEvent(Event);
}
}
/**
FvRegionAccessLib Initialization
This routine is a LibraryClass constructor for FvRegionAccessLib
@param ImageHandle A handle for the image that is initializing this driver
@param SystemTable A pointer to the EFI system table
@retval EFI_SUCCESS Module initialized successfully
**/
EFI_STATUS
EFIAPI
FvRegionAccessLibInit (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
VOID *Registration;
EFI_EVENT Event;
mFirmwareManagement = FindFirmwareManagementInstance ();
if (mFirmwareManagement == NULL) {
Registration = NULL;
Event = EfiCreateProtocolNotifyEvent (
&gEfiFirmwareManagementProtocolGuid,
TPL_CALLBACK,
FirmwareManagementNotify,
NULL,
&Registration
);
ASSERT (Event != NULL);
} else {
IrsiAddVirtualPointer ((VOID **)&mFirmwareManagement);
}
mRT = gRT;
IrsiAddVirtualPointer ((VOID **) &mRT);
return EFI_SUCCESS;
}