mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-11-04 05:25:45 +01:00 
			
		
		
		
	Instead of comparing a GUID with gZeroGuid via the CompareGuid API, the commit uses the IsZeroGuid API to check if the given GUID is a zero GUID. Cc: Feng Tian <feng.tian@intel.com> Cc: Star Zeng <star.zeng@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Hao Wu <hao.a.wu@intel.com> Reviewed-by: Feng Tian <feng.tian@Intel.com>
		
			
				
	
	
		
			444 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			444 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Var Check Hii generation from FV.
 | 
						|
 | 
						|
Copyright (c) 2015 - 2016, 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; !IsZeroGuid (&DriverGuidArray[Index]); 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 (IsZeroGuid (&DriverGuidArray[0])) {
 | 
						|
    //
 | 
						|
    // 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 ();
 | 
						|
  }
 | 
						|
}
 |