\r
/**\r
Remember that Fv protocol on FvHandle has had it's drivers placed on the\r
- mDiscoveredList. This fucntion adds entries on the mFvHandleList. Items are\r
- never removed/freed from the mFvHandleList.\r
+ mDiscoveredList. This fucntion adds entries on the mFvHandleList if new \r
+ entry is different from one in mFvHandleList by checking FvImage Guid.\r
+ Items are never removed/freed from the mFvHandleList.\r
\r
@param FvHandle The handle of a FV that has been processed\r
\r
+ @return A point to new added FvHandle entry. If FvHandle with the same FvImage guid\r
+ has been added, NULL will return. \r
+\r
**/\r
-VOID\r
+KNOWN_HANDLE * \r
FvIsBeingProcesssed (\r
IN EFI_HANDLE FvHandle\r
)\r
{\r
- KNOWN_HANDLE *KnownHandle;\r
+ EFI_STATUS Status;\r
+ EFI_GUID FvNameGuid;\r
+ BOOLEAN FvNameGuidIsFound;\r
+ UINT32 ExtHeaderOffset;\r
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;\r
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
+ EFI_FV_BLOCK_MAP_ENTRY *BlockMap;\r
+ UINTN LbaOffset;\r
+ UINTN Index;\r
+ EFI_LBA LbaIndex;\r
+ LIST_ENTRY *Link;\r
+ KNOWN_HANDLE *KnownHandle;\r
\r
- KnownHandle = AllocatePool (sizeof (KNOWN_HANDLE));\r
+ //\r
+ // Get the FirmwareVolumeBlock protocol on that handle\r
+ //\r
+ FvNameGuidIsFound = FALSE;\r
+ Status = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **)&Fvb);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Get the full FV header based on FVB protocol.\r
+ //\r
+ Status = GetFwVolHeader (Fvb, &FwVolHeader);\r
+ if (EFI_ERROR (Status)) {\r
+ FwVolHeader = NULL;\r
+ } else if (VerifyFvHeaderChecksum (FwVolHeader) && FwVolHeader->ExtHeaderOffset != 0) {\r
+ ExtHeaderOffset = (UINT32) FwVolHeader->ExtHeaderOffset;\r
+ BlockMap = FwVolHeader->BlockMap;\r
+ LbaIndex = 0;\r
+ LbaOffset = 0;\r
+ //\r
+ // Find LbaIndex and LbaOffset for FV extension header based on BlockMap.\r
+ //\r
+ while ((BlockMap->NumBlocks != 0) || (BlockMap->Length != 0)) {\r
+ for (Index = 0; Index < BlockMap->NumBlocks && ExtHeaderOffset >= BlockMap->Length; Index ++) {\r
+ ExtHeaderOffset -= BlockMap->Length;\r
+ LbaIndex ++;\r
+ }\r
+ //\r
+ // Check whether FvExtHeader is crossing the multi block range.\r
+ //\r
+ if (Index < BlockMap->NumBlocks) {\r
+ LbaOffset = ExtHeaderOffset;\r
+ break;\r
+ }\r
+ BlockMap++;\r
+ }\r
+ //\r
+ // Read FvNameGuid from FV extension header.\r
+ //\r
+ Status = ReadFvbData (Fvb, &LbaIndex, &LbaOffset, sizeof (FvNameGuid), (UINT8 *) &FvNameGuid);\r
+ if (!EFI_ERROR (Status)) {\r
+ FvNameGuidIsFound = TRUE;\r
+ }\r
+ }\r
+ CoreFreePool (FwVolHeader);\r
+ }\r
+\r
+ if (FvNameGuidIsFound) {\r
+ //\r
+ // Check whether the FV image with the found FvNameGuid has been processed.\r
+ //\r
+ for (Link = mFvHandleList.ForwardLink; Link != &mFvHandleList; Link = Link->ForwardLink) {\r
+ KnownHandle = CR(Link, KNOWN_HANDLE, Link, KNOWN_HANDLE_SIGNATURE);\r
+ if (CompareGuid (&FvNameGuid, &KnownHandle->FvNameGuid)) {\r
+ DEBUG ((EFI_D_ERROR, "FvImage on FvHandle %p and %p has the same FvNameGuid %g.\n", FvHandle, KnownHandle->Handle, FvNameGuid));\r
+ return NULL;\r
+ }\r
+ }\r
+ }\r
+\r
+ KnownHandle = AllocateZeroPool (sizeof (KNOWN_HANDLE));\r
ASSERT (KnownHandle != NULL);\r
\r
KnownHandle->Signature = KNOWN_HANDLE_SIGNATURE;\r
KnownHandle->Handle = FvHandle;\r
+ if (FvNameGuidIsFound) {\r
+ CopyGuid (&KnownHandle->FvNameGuid, &FvNameGuid);\r
+ }\r
InsertTailList (&mFvHandleList, &KnownHandle->Link);\r
+ return KnownHandle;\r
}\r
\r
\r
Check if a FV Image type file (EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) is\r
described by a EFI_HOB_FIRMWARE_VOLUME2 Hob.\r
\r
- @param FvHandle The handle which FVB protocol installed on.\r
+ @param FvNameGuid The FV image guid specified.\r
@param DriverName The driver guid specified.\r
\r
@retval TRUE This file is found in a EFI_HOB_FIRMWARE_VOLUME2\r
**/\r
BOOLEAN\r
FvFoundInHobFv2 (\r
- IN EFI_HANDLE FvHandle,\r
+ IN CONST EFI_GUID *FvNameGuid,\r
IN CONST EFI_GUID *DriverName\r
)\r
{\r
HobFv2.Raw = GetHobList ();\r
\r
while ((HobFv2.Raw = GetNextHob (EFI_HOB_TYPE_FV2, HobFv2.Raw)) != NULL) {\r
- if (CompareGuid (DriverName, &HobFv2.FirmwareVolume2->FileName)) {\r
+ //\r
+ // Compare parent FvNameGuid and FileGuid both.\r
+ //\r
+ if (CompareGuid (DriverName, &HobFv2.FirmwareVolume2->FileName) &&\r
+ CompareGuid (FvNameGuid, &HobFv2.FirmwareVolume2->FvName)) {\r
return TRUE;\r
}\r
HobFv2.Raw = GET_NEXT_HOB (HobFv2);\r
UINT32 AuthenticationStatus;\r
UINTN SizeOfBuffer;\r
VOID *DepexBuffer;\r
+ KNOWN_HANDLE *KnownHandle;\r
\r
while (TRUE) {\r
BufferSize = sizeof (EFI_HANDLE);\r
//\r
// Since we are about to process this Fv mark it as processed.\r
//\r
- FvIsBeingProcesssed (FvHandle);\r
+ KnownHandle = FvIsBeingProcesssed (FvHandle);\r
+ if (KnownHandle == NULL) {\r
+ //\r
+ // The FV with the same FV name guid has already been processed. \r
+ // So lets skip it!\r
+ //\r
+ continue;\r
+ }\r
\r
Status = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv);\r
if (EFI_ERROR (Status) || Fv == NULL) {\r
// Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already\r
// been extracted.\r
//\r
- if (FvFoundInHobFv2 (FvHandle, &NameGuid)) {\r
+ if (FvFoundInHobFv2 (&KnownHandle->FvNameGuid, &NameGuid)) {\r
continue;\r
}\r
\r
UINTN Signature;\r
LIST_ENTRY Link; // mFvHandleList\r
EFI_HANDLE Handle;\r
+ EFI_GUID FvNameGuid;\r
} KNOWN_HANDLE;\r
\r
\r
IN VOID *Context\r
);\r
\r
+/**\r
+ Read data from Firmware Block by FVB protocol Read. \r
+ The data may cross the multi block ranges.\r
+\r
+ @param Fvb The FW_VOL_BLOCK_PROTOCOL instance from which to read data.\r
+ @param StartLba Pointer to StartLba.\r
+ On input, the start logical block index from which to read.\r
+ On output,the end logical block index after reading.\r
+ @param Offset Pointer to Offset\r
+ On input, offset into the block at which to begin reading.\r
+ On output, offset into the end block after reading.\r
+ @param DataSize Size of data to be read.\r
+ @param Data Pointer to Buffer that the data will be read into.\r
+\r
+ @retval EFI_SUCCESS Successfully read data from firmware block.\r
+ @retval others\r
+**/\r
+EFI_STATUS\r
+ReadFvbData (\r
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb,\r
+ IN OUT EFI_LBA *StartLba,\r
+ IN OUT UINTN *Offset,\r
+ IN UINTN DataSize,\r
+ OUT UINT8 *Data\r
+ );\r
+\r
+/**\r
+ Given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and\r
+ copy the real length volume header into it.\r
+\r
+ @param Fvb The FW_VOL_BLOCK_PROTOCOL instance from which to\r
+ read the volume header\r
+ @param FwVolHeader Pointer to pointer to allocated buffer in which\r
+ the volume header is returned.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES No enough buffer could be allocated.\r
+ @retval EFI_SUCCESS Successfully read volume header to the allocated\r
+ buffer.\r
+\r
+**/\r
+EFI_STATUS\r
+GetFwVolHeader (\r
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb,\r
+ OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader\r
+ );\r
+\r
+/**\r
+ Verify checksum of the firmware volume header.\r
+\r
+ @param FvHeader Points to the firmware volume header to be checked\r
+\r
+ @retval TRUE Checksum verification passed\r
+ @retval FALSE Checksum verification failed\r
+\r
+**/\r
+BOOLEAN\r
+VerifyFvHeaderChecksum (\r
+ IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader\r
+ );\r
+\r
#endif\r