summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGenFromFv.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGenFromFv.c')
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGenFromFv.c437
1 files changed, 437 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGenFromFv.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGenFromFv.c
new file mode 100644
index 00000000..0cf02094
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGenFromFv.c
@@ -0,0 +1,437 @@
+/** @file
+ Var Check Hii generation from FV.
+
+Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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 ((DEBUG_INFO , "FfsNameGuid - %g\n", DriverGuid));
+ DEBUG ((DEBUG_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 ((DEBUG_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 ((DEBUG_INFO , "FvAddress - 0x%08x\n", FvAddress));
+ FvSize = ((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) FvAddress)->FvLength;
+ DEBUG ((DEBUG_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 ((DEBUG_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 ((DEBUG_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 ();
+ }
+}