--- /dev/null
+/** @file\r
+ Var Check Hii generation from FV.\r
+\r
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "VarCheckHiiGen.h"\r
+\r
+// {d0bc7cb4-6a47-495f-aa11-710746da06a2}\r
+#define EFI_VFR_ATTRACT_GUID \\r
+{ 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } }\r
+\r
+EFI_GUID gVfrArrayAttractGuid = EFI_VFR_ATTRACT_GUID;\r
+\r
+#define ALL_FF_GUID \\r
+{ 0xFFFFFFFF, 0xFFFF, 0xFFFF, { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } }\r
+\r
+EFI_GUID mAllFfGuid = ALL_FF_GUID;\r
+\r
+#define VAR_CHECK_VFR_DRIVER_INFO_SIGNATURE SIGNATURE_32 ('V', 'D', 'R', 'I')\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+ EFI_GUID *DriverGuid;\r
+} VAR_CHECK_VFR_DRIVER_INFO;\r
+\r
+LIST_ENTRY mVfrDriverList = INITIALIZE_LIST_HEAD_VARIABLE (mVfrDriverList);\r
+\r
+#define VAR_CHECK_VFR_DRIVER_INFO_FROM_LINK(a) CR (a, VAR_CHECK_VFR_DRIVER_INFO, Link, VAR_CHECK_VFR_DRIVER_INFO_SIGNATURE)\r
+\r
+#define MAX_MATCH_GUID_NUM 100\r
+\r
+/**\r
+ Get the address by Guid.\r
+\r
+ Parse the FFS and find the GUID address.\r
+ There may be multiple Guids matching the searched Guid.\r
+\r
+ @param Ffs Pointer to the FFS.\r
+ @param Guid Guid to find.\r
+ @param Length The length of FFS.\r
+ @param Offset Pointer to pointer to the offset.\r
+ @param NumOfMatchingGuid The number of matching Guid.\r
+\r
+ @retval EFI_SUCCESS One or multiple Guids matching the searched Guid.\r
+ @retval EFI_NOT_FOUND No Guid matching the searched Guid.\r
+\r
+**/\r
+EFI_STATUS\r
+GetAddressByGuid (\r
+ IN VOID *Ffs,\r
+ IN EFI_GUID *Guid,\r
+ IN UINTN Length,\r
+ OUT UINTN **Offset,\r
+ OUT UINT8 *NumOfMatchingGuid\r
+ )\r
+{\r
+ UINTN LoopControl;\r
+ BOOLEAN Found;\r
+\r
+ if((Ffs == NULL) || (Guid == NULL) || (Length == 0)){\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ if (NumOfMatchingGuid != NULL) {\r
+ *NumOfMatchingGuid = 0;\r
+ }\r
+\r
+ Found = FALSE;\r
+ for (LoopControl = 0; LoopControl < Length; LoopControl++) {\r
+ if (CompareGuid (Guid, (EFI_GUID *) ((UINT8 *) Ffs + LoopControl))) {\r
+ Found = TRUE;\r
+ //\r
+ // If NumOfMatchGuid or Offset are NULL, means user only want\r
+ // to check whether current FFS includes this Guid or not.\r
+ //\r
+ if ((NumOfMatchingGuid != NULL) && (Offset != NULL)) {\r
+ if (*NumOfMatchingGuid == 0) {\r
+ *Offset = InternalVarCheckAllocateZeroPool (sizeof (UINTN) * MAX_MATCH_GUID_NUM);\r
+ ASSERT (*Offset != NULL);\r
+ }\r
+ *(*Offset + *NumOfMatchingGuid) = LoopControl + sizeof (EFI_GUID);\r
+ (*NumOfMatchingGuid)++;\r
+ } else {\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ return (Found ? EFI_SUCCESS : EFI_NOT_FOUND);\r
+}\r
+\r
+/**\r
+ Search the VfrBin Base address.\r
+\r
+ According to the known GUID gVfrArrayAttractGuid to get the base address from FFS.\r
+\r
+ @param Ffs Pointer to the FFS.\r
+ @param EfiAddr Pointer to the EFI in FFS\r
+ @param Length The length of FFS.\r
+ @param Offset Pointer to pointer to the Addr (Offset).\r
+ @param NumOfMatchingOffset The number of Addr (Offset).\r
+\r
+ @retval EFI_SUCCESS Get the address successfully.\r
+ @retval EFI_NOT_FOUND No VfrBin found.\r
+\r
+**/\r
+EFI_STATUS\r
+SearchVfrBinInFfs (\r
+ IN VOID *Ffs,\r
+ IN VOID *EfiAddr,\r
+ IN UINTN Length,\r
+ OUT UINTN **Offset,\r
+ OUT UINT8 *NumOfMatchingOffset\r
+ )\r
+{\r
+ UINTN Index;\r
+ EFI_STATUS Status;\r
+ UINTN VirOffValue;\r
+\r
+ if ((Ffs == NULL) || (Offset == NULL)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ Status = GetAddressByGuid (\r
+ Ffs,\r
+ &gVfrArrayAttractGuid,\r
+ Length,\r
+ Offset,\r
+ NumOfMatchingOffset\r
+ );\r
+ if (Status != EFI_SUCCESS) {\r
+ return Status;\r
+ }\r
+\r
+ for (Index = 0; Index < *NumOfMatchingOffset; Index++) {\r
+ //\r
+ // Got the virOffset after the GUID\r
+ //\r
+ VirOffValue = *(UINTN *) ((UINTN) Ffs + *(*Offset + Index));\r
+ //\r
+ // Transfer the offset to the VA address. One modules may own multiple VfrBin address.\r
+ //\r
+ *(*Offset + Index) = (UINTN) EfiAddr + VirOffValue;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Parse FFS.\r
+\r
+ @param[in] Fv2 Pointer to Fv2 protocol.\r
+ @param[in] DriverGuid Pointer to driver GUID.\r
+\r
+ @return Found the driver in the FV or not.\r
+\r
+**/\r
+BOOLEAN\r
+ParseFfs (\r
+ IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv2,\r
+ IN EFI_GUID *DriverGuid\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_FV_FILETYPE FoundType;\r
+ EFI_FV_FILE_ATTRIBUTES FileAttributes;\r
+ UINT32 AuthenticationStatus;\r
+ UINTN Size;\r
+ VOID *Buffer;\r
+ UINTN SectionSize;\r
+ VOID *SectionBuffer;\r
+ UINTN VfrBinIndex;\r
+ UINT8 NumberofMatchingVfrBin;\r
+ UINTN *VfrBinBaseAddress;\r
+\r
+ Status = Fv2->ReadFile (\r
+ Fv2,\r
+ DriverGuid,\r
+ NULL,\r
+ &Size,\r
+ &FoundType,\r
+ &FileAttributes,\r
+ &AuthenticationStatus\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ }\r
+\r
+ Buffer = NULL;\r
+ Status = Fv2->ReadSection (\r
+ Fv2,\r
+ DriverGuid,\r
+ EFI_SECTION_RAW,\r
+ 0, // Instance\r
+ &Buffer,\r
+ &Size,\r
+ &AuthenticationStatus\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = SearchVfrBinInFfs (Buffer, 0, Size, &VfrBinBaseAddress, &NumberofMatchingVfrBin);\r
+ if (!EFI_ERROR (Status)) {\r
+ SectionBuffer = NULL;\r
+ Status = Fv2->ReadSection (\r
+ Fv2,\r
+ DriverGuid,\r
+ EFI_SECTION_PE32,\r
+ 0, // Instance\r
+ &SectionBuffer,\r
+ &SectionSize,\r
+ &AuthenticationStatus\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_INFO, "FfsNameGuid - %g\n", DriverGuid));\r
+ DEBUG ((EFI_D_INFO, "NumberofMatchingVfrBin - 0x%02x\n", NumberofMatchingVfrBin));\r
+\r
+ for (VfrBinIndex = 0; VfrBinIndex < NumberofMatchingVfrBin; VfrBinIndex++) {\r
+#ifdef DUMP_HII_DATA\r
+ DEBUG_CODE (\r
+ DumpHiiPackage ((UINT8 *) (UINTN) SectionBuffer + VfrBinBaseAddress[VfrBinIndex] + sizeof (UINT32));\r
+ );\r
+#endif\r
+ VarCheckParseHiiPackage ((UINT8 *) (UINTN) SectionBuffer + VfrBinBaseAddress[VfrBinIndex] + sizeof (UINT32), TRUE);\r
+ }\r
+\r
+ FreePool (SectionBuffer);\r
+ }\r
+\r
+ InternalVarCheckFreePool (VfrBinBaseAddress);\r
+ }\r
+\r
+ FreePool (Buffer);\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ Parse FVs.\r
+\r
+ @param[in] ScanAll Scan all modules in all FVs or not.\r
+\r
+**/\r
+VOID\r
+ParseFv (\r
+ IN BOOLEAN ScanAll\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN HandleCount;\r
+ UINTN Index;\r
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv2;\r
+ VOID *Key;\r
+ EFI_FV_FILETYPE FileType;\r
+ EFI_GUID NameGuid;\r
+ EFI_FV_FILE_ATTRIBUTES FileAttributes;\r
+ UINTN Size;\r
+ UINTN FfsIndex;\r
+ VAR_CHECK_VFR_DRIVER_INFO *VfrDriverInfo;\r
+ LIST_ENTRY *VfrDriverLink;\r
+\r
+ HandleBuffer = NULL;\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiFirmwareVolume2ProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Search all FVs\r
+ //\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ DEBUG ((EFI_D_INFO, "FvIndex - %x\n", Index));\r
+ Status = gBS->HandleProtocol (\r
+ HandleBuffer[Index],\r
+ &gEfiFirmwareVolume2ProtocolGuid,\r
+ (VOID **) &Fv2\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ DEBUG_CODE (\r
+ EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *Fvb2;\r
+ EFI_PHYSICAL_ADDRESS FvAddress;\r
+ UINT64 FvSize;\r
+\r
+ Status = gBS->HandleProtocol (\r
+ HandleBuffer[Index],\r
+ &gEfiFirmwareVolumeBlock2ProtocolGuid,\r
+ (VOID **) &Fvb2\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ Status = Fvb2->GetPhysicalAddress (Fvb2, &FvAddress);\r
+ if (!EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_INFO, "FvAddress - 0x%08x\n", FvAddress));\r
+ FvSize = ((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) FvAddress)->FvLength;\r
+ DEBUG ((EFI_D_INFO, "FvSize - 0x%08x\n", FvSize));\r
+ }\r
+ );\r
+\r
+ if (ScanAll) {\r
+ //\r
+ // Need to parse all modules in all FVs.\r
+ //\r
+ Key = InternalVarCheckAllocateZeroPool (Fv2->KeySize);\r
+ ASSERT (Key != NULL);\r
+\r
+ for (FfsIndex = 0; ; FfsIndex++) {\r
+ FileType = EFI_FV_FILETYPE_ALL;\r
+ Status = Fv2->GetNextFile (\r
+ Fv2,\r
+ Key,\r
+ &FileType,\r
+ &NameGuid,\r
+ &FileAttributes,\r
+ &Size\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+\r
+ ParseFfs (Fv2, &NameGuid);\r
+ }\r
+\r
+ InternalVarCheckFreePool (Key);\r
+ } else {\r
+ //\r
+ // Only parse drivers in the VFR drivers list.\r
+ //\r
+ VfrDriverLink = mVfrDriverList.ForwardLink;\r
+ while (VfrDriverLink != &mVfrDriverList) {\r
+ VfrDriverInfo = VAR_CHECK_VFR_DRIVER_INFO_FROM_LINK (VfrDriverLink);\r
+ VfrDriverLink = VfrDriverLink->ForwardLink;\r
+ if (ParseFfs (Fv2, VfrDriverInfo->DriverGuid)) {\r
+ //\r
+ // Found the driver in the FV.\r
+ //\r
+ RemoveEntryList (&VfrDriverInfo->Link);\r
+ InternalVarCheckFreePool (VfrDriverInfo);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ FreePool (HandleBuffer);\r
+}\r
+\r
+/**\r
+ Create Vfr Driver List.\r
+\r
+ @param[in] DriverGuidArray Driver Guid Array\r
+\r
+**/\r
+VOID\r
+CreateVfrDriverList (\r
+ IN EFI_GUID *DriverGuidArray\r
+ )\r
+{\r
+ UINTN Index;\r
+ VAR_CHECK_VFR_DRIVER_INFO *VfrDriverInfo;\r
+\r
+ for (Index = 0; !CompareGuid (&DriverGuidArray[Index], &gZeroGuid); Index++) {\r
+ DEBUG ((EFI_D_INFO, "CreateVfrDriverList: %g\n", &DriverGuidArray[Index]));\r
+ VfrDriverInfo = InternalVarCheckAllocateZeroPool (sizeof (*VfrDriverInfo));\r
+ ASSERT (VfrDriverInfo != NULL);\r
+ VfrDriverInfo->Signature = VAR_CHECK_VFR_DRIVER_INFO_SIGNATURE;\r
+ VfrDriverInfo->DriverGuid = &DriverGuidArray[Index];\r
+ InsertTailList (&mVfrDriverList, &VfrDriverInfo->Link);\r
+ }\r
+}\r
+\r
+/**\r
+ Destroy Vfr Driver List.\r
+\r
+**/\r
+VOID\r
+DestroyVfrDriverList (\r
+ VOID\r
+ )\r
+{\r
+ VAR_CHECK_VFR_DRIVER_INFO *VfrDriverInfo;\r
+ LIST_ENTRY *VfrDriverLink;\r
+\r
+ while (mVfrDriverList.ForwardLink != &mVfrDriverList) {\r
+ VfrDriverLink = mVfrDriverList.ForwardLink;\r
+ VfrDriverInfo = VAR_CHECK_VFR_DRIVER_INFO_FROM_LINK (VfrDriverLink);\r
+ RemoveEntryList (&VfrDriverInfo->Link);\r
+ InternalVarCheckFreePool (VfrDriverInfo);\r
+ }\r
+}\r
+\r
+/**\r
+ Generate from FV.\r
+\r
+**/\r
+VOID\r
+VarCheckHiiGenFromFv (\r
+ VOID\r
+ )\r
+{\r
+ EFI_GUID *DriverGuidArray;\r
+ BOOLEAN ScanAll;\r
+\r
+ DEBUG ((EFI_D_INFO, "VarCheckHiiGenDxeFromFv\n"));\r
+\r
+ //\r
+ // Get vfr driver guid array from PCD.\r
+ //\r
+ DriverGuidArray = (EFI_GUID *) PcdGetPtr (PcdVarCheckVfrDriverGuidArray);\r
+\r
+ if (CompareGuid (&DriverGuidArray[0], &gZeroGuid)) {\r
+ //\r
+ // No VFR driver will be parsed from FVs.\r
+ //\r
+ return;\r
+ }\r
+\r
+ if (CompareGuid (&DriverGuidArray[0], &mAllFfGuid)) {\r
+ ScanAll = TRUE;\r
+ } else {\r
+ ScanAll = FALSE;\r
+ CreateVfrDriverList (DriverGuidArray);\r
+ }\r
+\r
+ ParseFv (ScanAll);\r
+\r
+ if (!ScanAll) {\r
+ DestroyVfrDriverList ();\r
+ }\r
+}\r