Enhance DXE dispatcher logic to check the duplicated FV image bases on FvHob2 and FvNameGuid per PI spec.

Signed-off-by: lgao4
Reviewed-by: rsun3

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12874 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
lgao4 2011-12-15 06:50:54 +00:00
parent 22675de35c
commit 2fc46f86f9
4 changed files with 161 additions and 27 deletions

View File

@ -708,25 +708,102 @@ FvHasBeenProcessed (
/** /**
Remember that Fv protocol on FvHandle has had it's drivers placed on the Remember that Fv protocol on FvHandle has had it's drivers placed on the
mDiscoveredList. This fucntion adds entries on the mFvHandleList. Items are mDiscoveredList. This fucntion adds entries on the mFvHandleList if new
never removed/freed from the mFvHandleList. entry is different from one in mFvHandleList by checking FvImage Guid.
Items are never removed/freed from the mFvHandleList.
@param FvHandle The handle of a FV that has been processed @param FvHandle The handle of a FV that has been processed
@return A point to new added FvHandle entry. If FvHandle with the same FvImage guid
has been added, NULL will return.
**/ **/
VOID KNOWN_HANDLE *
FvIsBeingProcesssed ( FvIsBeingProcesssed (
IN EFI_HANDLE FvHandle IN EFI_HANDLE FvHandle
) )
{ {
EFI_STATUS Status;
EFI_GUID FvNameGuid;
BOOLEAN FvNameGuidIsFound;
UINT32 ExtHeaderOffset;
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
EFI_FV_BLOCK_MAP_ENTRY *BlockMap;
UINTN LbaOffset;
UINTN Index;
EFI_LBA LbaIndex;
LIST_ENTRY *Link;
KNOWN_HANDLE *KnownHandle; KNOWN_HANDLE *KnownHandle;
KnownHandle = AllocatePool (sizeof (KNOWN_HANDLE)); //
// Get the FirmwareVolumeBlock protocol on that handle
//
FvNameGuidIsFound = FALSE;
Status = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **)&Fvb);
if (!EFI_ERROR (Status)) {
//
// Get the full FV header based on FVB protocol.
//
Status = GetFwVolHeader (Fvb, &FwVolHeader);
if (EFI_ERROR (Status)) {
FwVolHeader = NULL;
} else if (VerifyFvHeaderChecksum (FwVolHeader) && FwVolHeader->ExtHeaderOffset != 0) {
ExtHeaderOffset = (UINT32) FwVolHeader->ExtHeaderOffset;
BlockMap = FwVolHeader->BlockMap;
LbaIndex = 0;
LbaOffset = 0;
//
// Find LbaIndex and LbaOffset for FV extension header based on BlockMap.
//
while ((BlockMap->NumBlocks != 0) || (BlockMap->Length != 0)) {
for (Index = 0; Index < BlockMap->NumBlocks && ExtHeaderOffset >= BlockMap->Length; Index ++) {
ExtHeaderOffset -= BlockMap->Length;
LbaIndex ++;
}
//
// Check whether FvExtHeader is crossing the multi block range.
//
if (Index < BlockMap->NumBlocks) {
LbaOffset = ExtHeaderOffset;
break;
}
BlockMap++;
}
//
// Read FvNameGuid from FV extension header.
//
Status = ReadFvbData (Fvb, &LbaIndex, &LbaOffset, sizeof (FvNameGuid), (UINT8 *) &FvNameGuid);
if (!EFI_ERROR (Status)) {
FvNameGuidIsFound = TRUE;
}
}
CoreFreePool (FwVolHeader);
}
if (FvNameGuidIsFound) {
//
// Check whether the FV image with the found FvNameGuid has been processed.
//
for (Link = mFvHandleList.ForwardLink; Link != &mFvHandleList; Link = Link->ForwardLink) {
KnownHandle = CR(Link, KNOWN_HANDLE, Link, KNOWN_HANDLE_SIGNATURE);
if (CompareGuid (&FvNameGuid, &KnownHandle->FvNameGuid)) {
DEBUG ((EFI_D_ERROR, "FvImage on FvHandle %p and %p has the same FvNameGuid %g.\n", FvHandle, KnownHandle->Handle, FvNameGuid));
return NULL;
}
}
}
KnownHandle = AllocateZeroPool (sizeof (KNOWN_HANDLE));
ASSERT (KnownHandle != NULL); ASSERT (KnownHandle != NULL);
KnownHandle->Signature = KNOWN_HANDLE_SIGNATURE; KnownHandle->Signature = KNOWN_HANDLE_SIGNATURE;
KnownHandle->Handle = FvHandle; KnownHandle->Handle = FvHandle;
if (FvNameGuidIsFound) {
CopyGuid (&KnownHandle->FvNameGuid, &FvNameGuid);
}
InsertTailList (&mFvHandleList, &KnownHandle->Link); InsertTailList (&mFvHandleList, &KnownHandle->Link);
return KnownHandle;
} }
@ -844,7 +921,7 @@ CoreAddToDriverList (
Check if a FV Image type file (EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) is Check if a FV Image type file (EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) is
described by a EFI_HOB_FIRMWARE_VOLUME2 Hob. described by a EFI_HOB_FIRMWARE_VOLUME2 Hob.
@param FvHandle The handle which FVB protocol installed on. @param FvNameGuid The FV image guid specified.
@param DriverName The driver guid specified. @param DriverName The driver guid specified.
@retval TRUE This file is found in a EFI_HOB_FIRMWARE_VOLUME2 @retval TRUE This file is found in a EFI_HOB_FIRMWARE_VOLUME2
@ -854,7 +931,7 @@ CoreAddToDriverList (
**/ **/
BOOLEAN BOOLEAN
FvFoundInHobFv2 ( FvFoundInHobFv2 (
IN EFI_HANDLE FvHandle, IN CONST EFI_GUID *FvNameGuid,
IN CONST EFI_GUID *DriverName IN CONST EFI_GUID *DriverName
) )
{ {
@ -863,7 +940,11 @@ FvFoundInHobFv2 (
HobFv2.Raw = GetHobList (); HobFv2.Raw = GetHobList ();
while ((HobFv2.Raw = GetNextHob (EFI_HOB_TYPE_FV2, HobFv2.Raw)) != NULL) { while ((HobFv2.Raw = GetNextHob (EFI_HOB_TYPE_FV2, HobFv2.Raw)) != NULL) {
if (CompareGuid (DriverName, &HobFv2.FirmwareVolume2->FileName)) { //
// Compare parent FvNameGuid and FileGuid both.
//
if (CompareGuid (DriverName, &HobFv2.FirmwareVolume2->FileName) &&
CompareGuid (FvNameGuid, &HobFv2.FirmwareVolume2->FvName)) {
return TRUE; return TRUE;
} }
HobFv2.Raw = GET_NEXT_HOB (HobFv2); HobFv2.Raw = GET_NEXT_HOB (HobFv2);
@ -1021,6 +1102,7 @@ CoreFwVolEventProtocolNotify (
UINT32 AuthenticationStatus; UINT32 AuthenticationStatus;
UINTN SizeOfBuffer; UINTN SizeOfBuffer;
VOID *DepexBuffer; VOID *DepexBuffer;
KNOWN_HANDLE *KnownHandle;
while (TRUE) { while (TRUE) {
BufferSize = sizeof (EFI_HANDLE); BufferSize = sizeof (EFI_HANDLE);
@ -1048,7 +1130,14 @@ CoreFwVolEventProtocolNotify (
// //
// Since we are about to process this Fv mark it as processed. // Since we are about to process this Fv mark it as processed.
// //
FvIsBeingProcesssed (FvHandle); KnownHandle = FvIsBeingProcesssed (FvHandle);
if (KnownHandle == NULL) {
//
// The FV with the same FV name guid has already been processed.
// So lets skip it!
//
continue;
}
Status = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv); Status = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv);
if (EFI_ERROR (Status) || Fv == NULL) { if (EFI_ERROR (Status) || Fv == NULL) {
@ -1131,7 +1220,7 @@ CoreFwVolEventProtocolNotify (
// Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already
// been extracted. // been extracted.
// //
if (FvFoundInHobFv2 (FvHandle, &NameGuid)) { if (FvFoundInHobFv2 (&KnownHandle->FvNameGuid, &NameGuid)) {
continue; continue;
} }

View File

@ -134,6 +134,7 @@ typedef struct {
UINTN Signature; UINTN Signature;
LIST_ENTRY Link; // mFvHandleList LIST_ENTRY Link; // mFvHandleList
EFI_HANDLE Handle; EFI_HANDLE Handle;
EFI_GUID FvNameGuid;
} KNOWN_HANDLE; } KNOWN_HANDLE;
@ -2489,4 +2490,64 @@ CoreEmptyCallbackFunction (
IN VOID *Context IN VOID *Context
); );
/**
Read data from Firmware Block by FVB protocol Read.
The data may cross the multi block ranges.
@param Fvb The FW_VOL_BLOCK_PROTOCOL instance from which to read data.
@param StartLba Pointer to StartLba.
On input, the start logical block index from which to read.
On output,the end logical block index after reading.
@param Offset Pointer to Offset
On input, offset into the block at which to begin reading.
On output, offset into the end block after reading.
@param DataSize Size of data to be read.
@param Data Pointer to Buffer that the data will be read into.
@retval EFI_SUCCESS Successfully read data from firmware block.
@retval others
**/
EFI_STATUS
ReadFvbData (
IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb,
IN OUT EFI_LBA *StartLba,
IN OUT UINTN *Offset,
IN UINTN DataSize,
OUT UINT8 *Data
);
/**
Given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and
copy the real length volume header into it.
@param Fvb The FW_VOL_BLOCK_PROTOCOL instance from which to
read the volume header
@param FwVolHeader Pointer to pointer to allocated buffer in which
the volume header is returned.
@retval EFI_OUT_OF_RESOURCES No enough buffer could be allocated.
@retval EFI_SUCCESS Successfully read volume header to the allocated
buffer.
**/
EFI_STATUS
GetFwVolHeader (
IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb,
OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader
);
/**
Verify checksum of the firmware volume header.
@param FvHeader Points to the firmware volume header to be checked
@retval TRUE Checksum verification passed
@retval FALSE Checksum verification failed
**/
BOOLEAN
VerifyFvHeaderChecksum (
IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader
);
#endif #endif

View File

@ -357,7 +357,7 @@ FvCheck (
// //
// Check whether FvHeader is crossing the multi block range. // Check whether FvHeader is crossing the multi block range.
// //
if (HeaderSize > BlockMap->Length) { if (Index >= BlockMap->NumBlocks) {
BlockMap++; BlockMap++;
continue; continue;
} else if (HeaderSize > 0) { } else if (HeaderSize > 0) {

View File

@ -366,22 +366,6 @@ SetFileState (
IN EFI_FFS_FILE_HEADER *FfsHeader IN EFI_FFS_FILE_HEADER *FfsHeader
); );
/**
Verify checksum of the firmware volume header.
@param FvHeader Points to the firmware volume header to be checked
@retval TRUE Checksum verification passed
@retval FALSE Checksum verification failed
**/
BOOLEAN
VerifyFvHeaderChecksum (
IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader
);
/** /**
Check if it's a valid FFS file header. Check if it's a valid FFS file header.