X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=MdeModulePkg%2FLibrary%2FVarCheckHiiLib%2FVarCheckHiiGenFromFv.c;fp=MdeModulePkg%2FLibrary%2FVarCheckHiiLib%2FVarCheckHiiGenFromFv.c;h=21fc80e89c1ad8242b463a2cf81db165584bc1e9;hb=1241af9510c6f7c0ff83cc3c418e9e1e24bf1ab1;hp=0000000000000000000000000000000000000000;hpb=b5817491a844e3a92be73f8a529551352aeda131;p=mirror_edk2.git diff --git a/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGenFromFv.c b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGenFromFv.c new file mode 100644 index 0000000000..21fc80e89c --- /dev/null +++ b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGenFromFv.c @@ -0,0 +1,443 @@ +/** @file + Var Check Hii generation from FV. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+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 (); + } +}