MdeModulePkg: Add VarCheckHiiLib NULL class library
The check will be based on VarCheckHiiBin that generated from FV and Hii Database. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Star Zeng <star.zeng@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18293 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
443
MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGenFromFv.c
Normal file
443
MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGenFromFv.c
Normal file
@@ -0,0 +1,443 @@
|
||||
/** @file
|
||||
Var Check Hii generation from FV.
|
||||
|
||||
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
|
||||
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 "VarCheckHiiGen.h"
|
||||
|
||||
// {d0bc7cb4-6a47-495f-aa11-710746da06a2}
|
||||
#define EFI_VFR_ATTRACT_GUID \
|
||||
{ 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } }
|
||||
|
||||
EFI_GUID gVfrArrayAttractGuid = EFI_VFR_ATTRACT_GUID;
|
||||
|
||||
#define ALL_FF_GUID \
|
||||
{ 0xFFFFFFFF, 0xFFFF, 0xFFFF, { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } }
|
||||
|
||||
EFI_GUID mAllFfGuid = ALL_FF_GUID;
|
||||
|
||||
#define VAR_CHECK_VFR_DRIVER_INFO_SIGNATURE SIGNATURE_32 ('V', 'D', 'R', 'I')
|
||||
|
||||
typedef struct {
|
||||
UINTN Signature;
|
||||
LIST_ENTRY Link;
|
||||
EFI_GUID *DriverGuid;
|
||||
} VAR_CHECK_VFR_DRIVER_INFO;
|
||||
|
||||
LIST_ENTRY mVfrDriverList = INITIALIZE_LIST_HEAD_VARIABLE (mVfrDriverList);
|
||||
|
||||
#define VAR_CHECK_VFR_DRIVER_INFO_FROM_LINK(a) CR (a, VAR_CHECK_VFR_DRIVER_INFO, Link, VAR_CHECK_VFR_DRIVER_INFO_SIGNATURE)
|
||||
|
||||
#define MAX_MATCH_GUID_NUM 100
|
||||
|
||||
/**
|
||||
Get the address by Guid.
|
||||
|
||||
Parse the FFS and find the GUID address.
|
||||
There may be multiple Guids matching the searched Guid.
|
||||
|
||||
@param Ffs Pointer to the FFS.
|
||||
@param Guid Guid to find.
|
||||
@param Length The length of FFS.
|
||||
@param Offset Pointer to pointer to the offset.
|
||||
@param NumOfMatchingGuid The number of matching Guid.
|
||||
|
||||
@retval EFI_SUCCESS One or multiple Guids matching the searched Guid.
|
||||
@retval EFI_NOT_FOUND No Guid matching the searched Guid.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
GetAddressByGuid (
|
||||
IN VOID *Ffs,
|
||||
IN EFI_GUID *Guid,
|
||||
IN UINTN Length,
|
||||
OUT UINTN **Offset,
|
||||
OUT UINT8 *NumOfMatchingGuid
|
||||
)
|
||||
{
|
||||
UINTN LoopControl;
|
||||
BOOLEAN Found;
|
||||
|
||||
if((Ffs == NULL) || (Guid == NULL) || (Length == 0)){
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (NumOfMatchingGuid != NULL) {
|
||||
*NumOfMatchingGuid = 0;
|
||||
}
|
||||
|
||||
Found = FALSE;
|
||||
for (LoopControl = 0; LoopControl < Length; LoopControl++) {
|
||||
if (CompareGuid (Guid, (EFI_GUID *) ((UINT8 *) Ffs + LoopControl))) {
|
||||
Found = TRUE;
|
||||
//
|
||||
// If NumOfMatchGuid or Offset are NULL, means user only want
|
||||
// to check whether current FFS includes this Guid or not.
|
||||
//
|
||||
if ((NumOfMatchingGuid != NULL) && (Offset != NULL)) {
|
||||
if (*NumOfMatchingGuid == 0) {
|
||||
*Offset = InternalVarCheckAllocateZeroPool (sizeof (UINTN) * MAX_MATCH_GUID_NUM);
|
||||
ASSERT (*Offset != NULL);
|
||||
}
|
||||
*(*Offset + *NumOfMatchingGuid) = LoopControl + sizeof (EFI_GUID);
|
||||
(*NumOfMatchingGuid)++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (Found ? EFI_SUCCESS : EFI_NOT_FOUND);
|
||||
}
|
||||
|
||||
/**
|
||||
Search the VfrBin Base address.
|
||||
|
||||
According to the known GUID gVfrArrayAttractGuid to get the base address from FFS.
|
||||
|
||||
@param Ffs Pointer to the FFS.
|
||||
@param EfiAddr Pointer to the EFI in FFS
|
||||
@param Length The length of FFS.
|
||||
@param Offset Pointer to pointer to the Addr (Offset).
|
||||
@param NumOfMatchingOffset The number of Addr (Offset).
|
||||
|
||||
@retval EFI_SUCCESS Get the address successfully.
|
||||
@retval EFI_NOT_FOUND No VfrBin found.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SearchVfrBinInFfs (
|
||||
IN VOID *Ffs,
|
||||
IN VOID *EfiAddr,
|
||||
IN UINTN Length,
|
||||
OUT UINTN **Offset,
|
||||
OUT UINT8 *NumOfMatchingOffset
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
EFI_STATUS Status;
|
||||
UINTN VirOffValue;
|
||||
|
||||
if ((Ffs == NULL) || (Offset == NULL)) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
Status = GetAddressByGuid (
|
||||
Ffs,
|
||||
&gVfrArrayAttractGuid,
|
||||
Length,
|
||||
Offset,
|
||||
NumOfMatchingOffset
|
||||
);
|
||||
if (Status != EFI_SUCCESS) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < *NumOfMatchingOffset; Index++) {
|
||||
//
|
||||
// Got the virOffset after the GUID
|
||||
//
|
||||
VirOffValue = *(UINTN *) ((UINTN) Ffs + *(*Offset + Index));
|
||||
//
|
||||
// Transfer the offset to the VA address. One modules may own multiple VfrBin address.
|
||||
//
|
||||
*(*Offset + Index) = (UINTN) EfiAddr + VirOffValue;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Parse FFS.
|
||||
|
||||
@param[in] Fv2 Pointer to Fv2 protocol.
|
||||
@param[in] DriverGuid Pointer to driver GUID.
|
||||
|
||||
@return Found the driver in the FV or not.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
ParseFfs (
|
||||
IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv2,
|
||||
IN EFI_GUID *DriverGuid
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_FV_FILETYPE FoundType;
|
||||
EFI_FV_FILE_ATTRIBUTES FileAttributes;
|
||||
UINT32 AuthenticationStatus;
|
||||
UINTN Size;
|
||||
VOID *Buffer;
|
||||
UINTN SectionSize;
|
||||
VOID *SectionBuffer;
|
||||
UINTN VfrBinIndex;
|
||||
UINT8 NumberofMatchingVfrBin;
|
||||
UINTN *VfrBinBaseAddress;
|
||||
|
||||
Status = Fv2->ReadFile (
|
||||
Fv2,
|
||||
DriverGuid,
|
||||
NULL,
|
||||
&Size,
|
||||
&FoundType,
|
||||
&FileAttributes,
|
||||
&AuthenticationStatus
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Buffer = NULL;
|
||||
Status = Fv2->ReadSection (
|
||||
Fv2,
|
||||
DriverGuid,
|
||||
EFI_SECTION_RAW,
|
||||
0, // Instance
|
||||
&Buffer,
|
||||
&Size,
|
||||
&AuthenticationStatus
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
Status = SearchVfrBinInFfs (Buffer, 0, Size, &VfrBinBaseAddress, &NumberofMatchingVfrBin);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
SectionBuffer = NULL;
|
||||
Status = Fv2->ReadSection (
|
||||
Fv2,
|
||||
DriverGuid,
|
||||
EFI_SECTION_PE32,
|
||||
0, // Instance
|
||||
&SectionBuffer,
|
||||
&SectionSize,
|
||||
&AuthenticationStatus
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_INFO, "FfsNameGuid - %g\n", DriverGuid));
|
||||
DEBUG ((EFI_D_INFO, "NumberofMatchingVfrBin - 0x%02x\n", NumberofMatchingVfrBin));
|
||||
|
||||
for (VfrBinIndex = 0; VfrBinIndex < NumberofMatchingVfrBin; VfrBinIndex++) {
|
||||
#ifdef DUMP_HII_DATA
|
||||
DEBUG_CODE (
|
||||
DumpHiiPackage ((UINT8 *) (UINTN) SectionBuffer + VfrBinBaseAddress[VfrBinIndex] + sizeof (UINT32));
|
||||
);
|
||||
#endif
|
||||
VarCheckParseHiiPackage ((UINT8 *) (UINTN) SectionBuffer + VfrBinBaseAddress[VfrBinIndex] + sizeof (UINT32), TRUE);
|
||||
}
|
||||
|
||||
FreePool (SectionBuffer);
|
||||
}
|
||||
|
||||
InternalVarCheckFreePool (VfrBinBaseAddress);
|
||||
}
|
||||
|
||||
FreePool (Buffer);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
Parse FVs.
|
||||
|
||||
@param[in] ScanAll Scan all modules in all FVs or not.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ParseFv (
|
||||
IN BOOLEAN ScanAll
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_HANDLE *HandleBuffer;
|
||||
UINTN HandleCount;
|
||||
UINTN Index;
|
||||
EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv2;
|
||||
VOID *Key;
|
||||
EFI_FV_FILETYPE FileType;
|
||||
EFI_GUID NameGuid;
|
||||
EFI_FV_FILE_ATTRIBUTES FileAttributes;
|
||||
UINTN Size;
|
||||
UINTN FfsIndex;
|
||||
VAR_CHECK_VFR_DRIVER_INFO *VfrDriverInfo;
|
||||
LIST_ENTRY *VfrDriverLink;
|
||||
|
||||
HandleBuffer = NULL;
|
||||
Status = gBS->LocateHandleBuffer (
|
||||
ByProtocol,
|
||||
&gEfiFirmwareVolume2ProtocolGuid,
|
||||
NULL,
|
||||
&HandleCount,
|
||||
&HandleBuffer
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Search all FVs
|
||||
//
|
||||
for (Index = 0; Index < HandleCount; Index++) {
|
||||
DEBUG ((EFI_D_INFO, "FvIndex - %x\n", Index));
|
||||
Status = gBS->HandleProtocol (
|
||||
HandleBuffer[Index],
|
||||
&gEfiFirmwareVolume2ProtocolGuid,
|
||||
(VOID **) &Fv2
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
DEBUG_CODE (
|
||||
EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *Fvb2;
|
||||
EFI_PHYSICAL_ADDRESS FvAddress;
|
||||
UINT64 FvSize;
|
||||
|
||||
Status = gBS->HandleProtocol (
|
||||
HandleBuffer[Index],
|
||||
&gEfiFirmwareVolumeBlock2ProtocolGuid,
|
||||
(VOID **) &Fvb2
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
Status = Fvb2->GetPhysicalAddress (Fvb2, &FvAddress);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_INFO, "FvAddress - 0x%08x\n", FvAddress));
|
||||
FvSize = ((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) FvAddress)->FvLength;
|
||||
DEBUG ((EFI_D_INFO, "FvSize - 0x%08x\n", FvSize));
|
||||
}
|
||||
);
|
||||
|
||||
if (ScanAll) {
|
||||
//
|
||||
// Need to parse all modules in all FVs.
|
||||
//
|
||||
Key = InternalVarCheckAllocateZeroPool (Fv2->KeySize);
|
||||
ASSERT (Key != NULL);
|
||||
|
||||
for (FfsIndex = 0; ; FfsIndex++) {
|
||||
FileType = EFI_FV_FILETYPE_ALL;
|
||||
Status = Fv2->GetNextFile (
|
||||
Fv2,
|
||||
Key,
|
||||
&FileType,
|
||||
&NameGuid,
|
||||
&FileAttributes,
|
||||
&Size
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
break;
|
||||
}
|
||||
|
||||
ParseFfs (Fv2, &NameGuid);
|
||||
}
|
||||
|
||||
InternalVarCheckFreePool (Key);
|
||||
} else {
|
||||
//
|
||||
// Only parse drivers in the VFR drivers list.
|
||||
//
|
||||
VfrDriverLink = mVfrDriverList.ForwardLink;
|
||||
while (VfrDriverLink != &mVfrDriverList) {
|
||||
VfrDriverInfo = VAR_CHECK_VFR_DRIVER_INFO_FROM_LINK (VfrDriverLink);
|
||||
VfrDriverLink = VfrDriverLink->ForwardLink;
|
||||
if (ParseFfs (Fv2, VfrDriverInfo->DriverGuid)) {
|
||||
//
|
||||
// Found the driver in the FV.
|
||||
//
|
||||
RemoveEntryList (&VfrDriverInfo->Link);
|
||||
InternalVarCheckFreePool (VfrDriverInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FreePool (HandleBuffer);
|
||||
}
|
||||
|
||||
/**
|
||||
Create Vfr Driver List.
|
||||
|
||||
@param[in] DriverGuidArray Driver Guid Array
|
||||
|
||||
**/
|
||||
VOID
|
||||
CreateVfrDriverList (
|
||||
IN EFI_GUID *DriverGuidArray
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
VAR_CHECK_VFR_DRIVER_INFO *VfrDriverInfo;
|
||||
|
||||
for (Index = 0; !CompareGuid (&DriverGuidArray[Index], &gZeroGuid); Index++) {
|
||||
DEBUG ((EFI_D_INFO, "CreateVfrDriverList: %g\n", &DriverGuidArray[Index]));
|
||||
VfrDriverInfo = InternalVarCheckAllocateZeroPool (sizeof (*VfrDriverInfo));
|
||||
ASSERT (VfrDriverInfo != NULL);
|
||||
VfrDriverInfo->Signature = VAR_CHECK_VFR_DRIVER_INFO_SIGNATURE;
|
||||
VfrDriverInfo->DriverGuid = &DriverGuidArray[Index];
|
||||
InsertTailList (&mVfrDriverList, &VfrDriverInfo->Link);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Destroy Vfr Driver List.
|
||||
|
||||
**/
|
||||
VOID
|
||||
DestroyVfrDriverList (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
VAR_CHECK_VFR_DRIVER_INFO *VfrDriverInfo;
|
||||
LIST_ENTRY *VfrDriverLink;
|
||||
|
||||
while (mVfrDriverList.ForwardLink != &mVfrDriverList) {
|
||||
VfrDriverLink = mVfrDriverList.ForwardLink;
|
||||
VfrDriverInfo = VAR_CHECK_VFR_DRIVER_INFO_FROM_LINK (VfrDriverLink);
|
||||
RemoveEntryList (&VfrDriverInfo->Link);
|
||||
InternalVarCheckFreePool (VfrDriverInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Generate from FV.
|
||||
|
||||
**/
|
||||
VOID
|
||||
VarCheckHiiGenFromFv (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EFI_GUID *DriverGuidArray;
|
||||
BOOLEAN ScanAll;
|
||||
|
||||
DEBUG ((EFI_D_INFO, "VarCheckHiiGenDxeFromFv\n"));
|
||||
|
||||
//
|
||||
// Get vfr driver guid array from PCD.
|
||||
//
|
||||
DriverGuidArray = (EFI_GUID *) PcdGetPtr (PcdVarCheckVfrDriverGuidArray);
|
||||
|
||||
if (CompareGuid (&DriverGuidArray[0], &gZeroGuid)) {
|
||||
//
|
||||
// No VFR driver will be parsed from FVs.
|
||||
//
|
||||
return;
|
||||
}
|
||||
|
||||
if (CompareGuid (&DriverGuidArray[0], &mAllFfGuid)) {
|
||||
ScanAll = TRUE;
|
||||
} else {
|
||||
ScanAll = FALSE;
|
||||
CreateVfrDriverList (DriverGuidArray);
|
||||
}
|
||||
|
||||
ParseFv (ScanAll);
|
||||
|
||||
if (!ScanAll) {
|
||||
DestroyVfrDriverList ();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user