Depex - Dependency Expresion.\r
SOR - Schedule On Request - Don't schedule if this bit is set.\r
\r
-Copyright (c) 2006 - 2010, 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
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
\r
FV_FILEPATH_DEVICE_PATH mFvDevicePath;\r
\r
-\r
//\r
// Function Prototypes\r
//\r
EFI_CORE_DRIVER_ENTRY so that the PE image can be\r
read out of the FV at a later time.\r
@param DriverName Name of driver to add to mDiscoveredList.\r
+ @param Type Fv File Type of file to add to mDiscoveredList.\r
\r
@retval EFI_SUCCESS If driver was added to the mDiscoveredList.\r
@retval EFI_ALREADY_STARTED The driver has already been started. Only one\r
CoreAddToDriverList (\r
IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv,\r
IN EFI_HANDLE FvHandle,\r
- IN EFI_GUID *DriverName\r
+ IN EFI_GUID *DriverName,\r
+ IN EFI_FV_FILETYPE Type\r
);\r
\r
/**\r
- Get the driver from the FV through driver name, and produce a FVB protocol on FvHandle.\r
+ Get Fv image(s) from the FV through file name, and produce FVB protocol for every Fv image(s).\r
\r
@param Fv The FIRMWARE_VOLUME protocol installed on the FV.\r
@param FvHandle The handle which FVB protocol installed on.\r
- @param DriverName The driver guid specified.\r
+ @param FileName The file name guid specified.\r
\r
@retval EFI_OUT_OF_RESOURCES No enough memory or other resource.\r
- @retval EFI_VOLUME_CORRUPTED Corrupted volume.\r
@retval EFI_SUCCESS Function successfully returned.\r
\r
**/\r
CoreProcessFvImageFile (\r
IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv,\r
IN EFI_HANDLE FvHandle,\r
- IN EFI_GUID *DriverName\r
+ IN EFI_GUID *FileName\r
);\r
\r
\r
DriverEntry->Dependent = TRUE;\r
CoreReleaseDispatcherLock ();\r
\r
+ DEBUG ((DEBUG_DISPATCH, "Schedule FFS(%g) - EFI_SUCCESS\n", DriverName));\r
+\r
return EFI_SUCCESS;\r
}\r
}\r
+\r
+ DEBUG ((DEBUG_DISPATCH, "Schedule FFS(%g) - EFI_NOT_FOUND\n", DriverName));\r
+\r
return EFI_NOT_FOUND;\r
}\r
\r
return EFI_NOT_FOUND;\r
}\r
\r
-\r
-/**\r
- An empty function to pass error checking of CreateEventEx ().\r
-\r
- @param Event Event whose notification function is being invoked.\r
- @param Context Pointer to the notification function's context,\r
- which is implementation-dependent.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-EmptyFuntion (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-{\r
- return;\r
-}\r
-\r
/**\r
This is the main Dispatcher for DXE and it exits when there are no more\r
drivers to run. Drain the mScheduledQueue and load and start a PE\r
EFI_CORE_DRIVER_ENTRY *DriverEntry;\r
BOOLEAN ReadyToRun;\r
EFI_EVENT DxeDispatchEvent;\r
- \r
+\r
+ PERF_FUNCTION_BEGIN ();\r
\r
if (gDispatcherRunning) {\r
//\r
Status = CoreCreateEventEx (\r
EVT_NOTIFY_SIGNAL,\r
TPL_NOTIFY,\r
- EmptyFuntion,\r
+ EfiEventEmptyFunction,\r
NULL,\r
&gEfiEventDxeDispatchGuid,\r
&DxeDispatchEvent\r
// Untrused to Scheduled it would have already been loaded so we may need to\r
// skip the LoadImage\r
//\r
- if (DriverEntry->ImageHandle == NULL) {\r
+ if (DriverEntry->ImageHandle == NULL && !DriverEntry->IsFvImage) {\r
DEBUG ((DEBUG_INFO, "Loading driver %g\n", &DriverEntry->FileName));\r
Status = CoreLoadImage (\r
FALSE,\r
\r
CoreReleaseDispatcherLock ();\r
\r
- \r
- REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
- EFI_PROGRESS_CODE,\r
- (EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_BEGIN),\r
- &DriverEntry->ImageHandle,\r
- sizeof (DriverEntry->ImageHandle)\r
- );\r
-\r
- Status = CoreStartImage (DriverEntry->ImageHandle, NULL, NULL);\r
\r
- REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
- EFI_PROGRESS_CODE,\r
- (EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_END),\r
- &DriverEntry->ImageHandle,\r
- sizeof (DriverEntry->ImageHandle)\r
- );\r
+ if (DriverEntry->IsFvImage) {\r
+ //\r
+ // Produce a firmware volume block protocol for FvImage so it gets dispatched from.\r
+ //\r
+ Status = CoreProcessFvImageFile (DriverEntry->Fv, DriverEntry->FvHandle, &DriverEntry->FileName);\r
+ } else {\r
+ REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
+ EFI_PROGRESS_CODE,\r
+ (EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_BEGIN),\r
+ &DriverEntry->ImageHandle,\r
+ sizeof (DriverEntry->ImageHandle)\r
+ );\r
+ ASSERT (DriverEntry->ImageHandle != NULL);\r
+\r
+ Status = CoreStartImage (DriverEntry->ImageHandle, NULL, NULL);\r
+\r
+ REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
+ EFI_PROGRESS_CODE,\r
+ (EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_END),\r
+ &DriverEntry->ImageHandle,\r
+ sizeof (DriverEntry->ImageHandle)\r
+ );\r
+ }\r
\r
ReturnStatus = EFI_SUCCESS;\r
}\r
\r
+ //\r
+ // Now DXE Dispatcher finished one round of dispatch, signal an event group\r
+ // so that SMM Dispatcher get chance to dispatch SMM Drivers which depend\r
+ // on UEFI protocols\r
+ //\r
+ if (!EFI_ERROR (ReturnStatus)) {\r
+ CoreSignalEvent (DxeDispatchEvent);\r
+ }\r
+\r
//\r
// Search DriverList for items to place on Scheduled Queue\r
//\r
CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);\r
ReadyToRun = TRUE;\r
}\r
+ } else {\r
+ if (DriverEntry->Unrequested) {\r
+ DEBUG ((DEBUG_DISPATCH, "Evaluate DXE DEPEX for FFS(%g)\n", &DriverEntry->FileName));\r
+ DEBUG ((DEBUG_DISPATCH, " SOR = Not Requested\n"));\r
+ DEBUG ((DEBUG_DISPATCH, " RESULT = FALSE\n"));\r
+ }\r
}\r
}\r
-\r
- //\r
- // Now DXE Dispatcher finished one round of dispatch, signal an event group\r
- // so that SMM Dispatcher get chance to dispatch SMM Drivers which depend\r
- // on UEFI protocols\r
- //\r
- if (!EFI_ERROR (ReturnStatus)) {\r
- CoreSignalEvent (DxeDispatchEvent);\r
- }\r
} while (ReadyToRun);\r
\r
//\r
\r
gDispatcherRunning = FALSE;\r
\r
+ PERF_FUNCTION_END ();\r
+\r
return ReturnStatus;\r
}\r
\r
//\r
for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {\r
DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);\r
- if (DriverEntry->Before && DriverEntry->Dependent) {\r
+ if (DriverEntry->Before && DriverEntry->Dependent && DriverEntry != InsertedDriverEntry) {\r
+ DEBUG ((DEBUG_DISPATCH, "Evaluate DXE DEPEX for FFS(%g)\n", &DriverEntry->FileName));\r
+ DEBUG ((DEBUG_DISPATCH, " BEFORE FFS(%g) = ", &DriverEntry->BeforeAfterGuid));\r
if (CompareGuid (&InsertedDriverEntry->FileName, &DriverEntry->BeforeAfterGuid)) {\r
//\r
// Recursively process BEFORE\r
//\r
+ DEBUG ((DEBUG_DISPATCH, "TRUE\n END\n RESULT = TRUE\n"));\r
CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);\r
+ } else {\r
+ DEBUG ((DEBUG_DISPATCH, "FALSE\n END\n RESULT = FALSE\n"));\r
}\r
}\r
}\r
//\r
for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {\r
DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);\r
- if (DriverEntry->After && DriverEntry->Dependent) {\r
+ if (DriverEntry->After && DriverEntry->Dependent && DriverEntry != InsertedDriverEntry) {\r
+ DEBUG ((DEBUG_DISPATCH, "Evaluate DXE DEPEX for FFS(%g)\n", &DriverEntry->FileName));\r
+ DEBUG ((DEBUG_DISPATCH, " AFTER FFS(%g) = ", &DriverEntry->BeforeAfterGuid));\r
if (CompareGuid (&InsertedDriverEntry->FileName, &DriverEntry->BeforeAfterGuid)) {\r
//\r
// Recursively process AFTER\r
//\r
+ DEBUG ((DEBUG_DISPATCH, "TRUE\n END\n RESULT = TRUE\n"));\r
CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);\r
+ } else {\r
+ DEBUG ((DEBUG_DISPATCH, "FALSE\n END\n RESULT = FALSE\n"));\r
}\r
}\r
}\r
\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
+ FwVolHeader = NULL;\r
+\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
+ ASSERT (Fvb != NULL);\r
+ Status = GetFwVolHeader (Fvb, &FwVolHeader);\r
+ if (!EFI_ERROR (Status)) {\r
+ ASSERT (FwVolHeader != NULL);\r
+ 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
\r
- KnownHandle = AllocatePool (sizeof (KNOWN_HANDLE));\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
EFI_CORE_DRIVER_ENTRY so that the PE image can be\r
read out of the FV at a later time.\r
@param DriverName Name of driver to add to mDiscoveredList.\r
+ @param Type Fv File Type of file to add to mDiscoveredList.\r
\r
@retval EFI_SUCCESS If driver was added to the mDiscoveredList.\r
@retval EFI_ALREADY_STARTED The driver has already been started. Only one\r
CoreAddToDriverList (\r
IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv,\r
IN EFI_HANDLE FvHandle,\r
- IN EFI_GUID *DriverName\r
+ IN EFI_GUID *DriverName,\r
+ IN EFI_FV_FILETYPE Type\r
)\r
{\r
EFI_CORE_DRIVER_ENTRY *DriverEntry;\r
//\r
DriverEntry = AllocateZeroPool (sizeof (EFI_CORE_DRIVER_ENTRY));\r
ASSERT (DriverEntry != NULL);\r
+ if (Type == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {\r
+ DriverEntry->IsFvImage = TRUE;\r
+ }\r
\r
DriverEntry->Signature = EFI_CORE_DRIVER_ENTRY_SIGNATURE;\r
CopyGuid (&DriverEntry->FileName, DriverName);\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
return FALSE;\r
}\r
\r
+/**\r
+ Find USED_SIZE FV_EXT_TYPE entry in FV extension header and get the FV used size.\r
+\r
+ @param[in] FvHeader Pointer to FV header.\r
+ @param[out] FvUsedSize Pointer to FV used size returned,\r
+ only valid if USED_SIZE FV_EXT_TYPE entry is found.\r
+ @param[out] EraseByte Pointer to erase byte returned,\r
+ only valid if USED_SIZE FV_EXT_TYPE entry is found.\r
\r
+ @retval TRUE USED_SIZE FV_EXT_TYPE entry is found,\r
+ FV used size and erase byte are returned.\r
+ @retval FALSE No USED_SIZE FV_EXT_TYPE entry found.\r
+\r
+**/\r
+BOOLEAN\r
+GetFvUsedSize (\r
+ IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader,\r
+ OUT UINT32 *FvUsedSize,\r
+ OUT UINT8 *EraseByte\r
+ )\r
+{\r
+ UINT16 ExtHeaderOffset;\r
+ EFI_FIRMWARE_VOLUME_EXT_HEADER *ExtHeader;\r
+ EFI_FIRMWARE_VOLUME_EXT_ENTRY *ExtEntryList;\r
+ EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE *ExtEntryUsedSize;\r
+\r
+ ExtHeaderOffset = ReadUnaligned16 (&FvHeader->ExtHeaderOffset);\r
+ if (ExtHeaderOffset != 0) {\r
+ ExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) ((UINT8 *) FvHeader + ExtHeaderOffset);\r
+ ExtEntryList = (EFI_FIRMWARE_VOLUME_EXT_ENTRY *) (ExtHeader + 1);\r
+ while ((UINTN) ExtEntryList < ((UINTN) ExtHeader + ReadUnaligned32 (&ExtHeader->ExtHeaderSize))) {\r
+ if (ReadUnaligned16 (&ExtEntryList->ExtEntryType) == EFI_FV_EXT_TYPE_USED_SIZE_TYPE) {\r
+ //\r
+ // USED_SIZE FV_EXT_TYPE entry is found.\r
+ //\r
+ ExtEntryUsedSize = (EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE *) ExtEntryList;\r
+ *FvUsedSize = ReadUnaligned32 (&ExtEntryUsedSize->UsedSize);\r
+ if ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_ERASE_POLARITY) != 0) {\r
+ *EraseByte = 0xFF;\r
+ } else {\r
+ *EraseByte = 0;\r
+ }\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "FV at 0x%x has 0x%x used size, and erase byte is 0x%02x\n",\r
+ FvHeader,\r
+ *FvUsedSize,\r
+ *EraseByte\r
+ ));\r
+ return TRUE;\r
+ }\r
+ ExtEntryList = (EFI_FIRMWARE_VOLUME_EXT_ENTRY *)\r
+ ((UINT8 *) ExtEntryList + ReadUnaligned16 (&ExtEntryList->ExtEntrySize));\r
+ }\r
+ }\r
+\r
+ //\r
+ // No USED_SIZE FV_EXT_TYPE entry found.\r
+ //\r
+ return FALSE;\r
+}\r
\r
/**\r
- Get the driver from the FV through driver name, and produce a FVB protocol on FvHandle.\r
+ Get Fv image(s) from the FV through file name, and produce FVB protocol for every Fv image(s).\r
\r
@param Fv The FIRMWARE_VOLUME protocol installed on the FV.\r
@param FvHandle The handle which FVB protocol installed on.\r
- @param DriverName The driver guid specified.\r
+ @param FileName The file name guid specified.\r
\r
@retval EFI_OUT_OF_RESOURCES No enough memory or other resource.\r
- @retval EFI_VOLUME_CORRUPTED Corrupted volume.\r
@retval EFI_SUCCESS Function successfully returned.\r
\r
**/\r
CoreProcessFvImageFile (\r
IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv,\r
IN EFI_HANDLE FvHandle,\r
- IN EFI_GUID *DriverName\r
+ IN EFI_GUID *FileName\r
)\r
{\r
EFI_STATUS Status;\r
UINTN BufferSize;\r
EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
UINT32 FvAlignment;\r
+ EFI_DEVICE_PATH_PROTOCOL *FvFileDevicePath;\r
+ UINT32 FvUsedSize;\r
+ UINT8 EraseByte;\r
+ UINTN Index;\r
\r
//\r
- // Read the first (and only the first) firmware volume section\r
+ // Read firmware volume section(s)\r
//\r
SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;\r
- FvHeader = NULL;\r
- FvAlignment = 0;\r
- Buffer = NULL;\r
- BufferSize = 0;\r
- AlignedBuffer = NULL;\r
- Status = Fv->ReadSection (\r
- Fv,\r
- DriverName,\r
- SectionType,\r
- 0,\r
- &Buffer,\r
- &BufferSize,\r
- &AuthenticationStatus\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // FvImage should be at its required alignment.\r
- //\r
- FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) Buffer;\r
- //\r
- // Get FvHeader alignment\r
- //\r
- FvAlignment = 1 << ((FvHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16);\r
- //\r
- // FvAlignment must be greater than or equal to 8 bytes of the minimum FFS alignment value. \r
- //\r
- if (FvAlignment < 8) {\r
- FvAlignment = 8;\r
- }\r
- //\r
- // Allocate the aligned buffer for the FvImage.\r
- //\r
- AlignedBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES (BufferSize), (UINTN) FvAlignment);\r
- if (AlignedBuffer == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- } else {\r
+\r
+ Index = 0;\r
+ do {\r
+ FvHeader = NULL;\r
+ FvAlignment = 0;\r
+ Buffer = NULL;\r
+ BufferSize = 0;\r
+ AlignedBuffer = NULL;\r
+ Status = Fv->ReadSection (\r
+ Fv,\r
+ FileName,\r
+ SectionType,\r
+ Index,\r
+ &Buffer,\r
+ &BufferSize,\r
+ &AuthenticationStatus\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Evaluate the authentication status of the Firmware Volume through\r
+ // Security Architectural Protocol\r
//\r
- // Move FvImage into the aligned buffer and release the original buffer.\r
+ if (gSecurity != NULL) {\r
+ FvFileDevicePath = CoreFvToDevicePath (Fv, FvHandle, FileName);\r
+ Status = gSecurity->FileAuthenticationState (\r
+ gSecurity,\r
+ AuthenticationStatus,\r
+ FvFileDevicePath\r
+ );\r
+ if (FvFileDevicePath != NULL) {\r
+ FreePool (FvFileDevicePath);\r
+ }\r
+\r
+ if (Status != EFI_SUCCESS) {\r
+ //\r
+ // Security check failed. The firmware volume should not be used for any purpose.\r
+ //\r
+ if (Buffer != NULL) {\r
+ FreePool (Buffer);\r
+ }\r
+ break;\r
+ }\r
+ }\r
+\r
//\r
- CopyMem (AlignedBuffer, Buffer, BufferSize);\r
- CoreFreePool (Buffer);\r
- Buffer = NULL;\r
+ // FvImage should be at its required alignment.\r
+ //\r
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) Buffer;\r
+ //\r
+ // If EFI_FVB2_WEAK_ALIGNMENT is set in the volume header then the first byte of the volume\r
+ // can be aligned on any power-of-two boundary. A weakly aligned volume can not be moved from\r
+ // its initial linked location and maintain its alignment.\r
+ //\r
+ if ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_WEAK_ALIGNMENT) != EFI_FVB2_WEAK_ALIGNMENT) {\r
+ //\r
+ // Get FvHeader alignment\r
+ //\r
+ FvAlignment = 1 << ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_ALIGNMENT) >> 16);\r
+ //\r
+ // FvAlignment must be greater than or equal to 8 bytes of the minimum FFS alignment value.\r
+ //\r
+ if (FvAlignment < 8) {\r
+ FvAlignment = 8;\r
+ }\r
+\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "%a() FV at 0x%x, FvAlignment required is 0x%x\n",\r
+ __FUNCTION__,\r
+ FvHeader,\r
+ FvAlignment\r
+ ));\r
+\r
+ //\r
+ // Check FvImage alignment.\r
+ //\r
+ if ((UINTN) FvHeader % FvAlignment != 0) {\r
+ //\r
+ // Allocate the aligned buffer for the FvImage.\r
+ //\r
+ AlignedBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES (BufferSize), (UINTN) FvAlignment);\r
+ if (AlignedBuffer == NULL) {\r
+ FreePool (Buffer);\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ break;\r
+ } else {\r
+ //\r
+ // Move FvImage into the aligned buffer and release the original buffer.\r
+ //\r
+ if (GetFvUsedSize (FvHeader, &FvUsedSize, &EraseByte)) {\r
+ //\r
+ // Copy the used bytes and fill the rest with the erase value.\r
+ //\r
+ CopyMem (AlignedBuffer, FvHeader, (UINTN) FvUsedSize);\r
+ SetMem (\r
+ (UINT8 *) AlignedBuffer + FvUsedSize,\r
+ (UINTN) (BufferSize - FvUsedSize),\r
+ EraseByte\r
+ );\r
+ } else {\r
+ CopyMem (AlignedBuffer, Buffer, BufferSize);\r
+ }\r
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) AlignedBuffer;\r
+ FreePool (Buffer);\r
+ Buffer = NULL;\r
+ }\r
+ }\r
+ }\r
//\r
// Produce a FVB protocol for the file\r
//\r
Status = ProduceFVBProtocolOnBuffer (\r
- (EFI_PHYSICAL_ADDRESS) (UINTN) AlignedBuffer,\r
+ (EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader,\r
(UINT64)BufferSize,\r
FvHandle,\r
+ AuthenticationStatus,\r
NULL\r
);\r
}\r
- }\r
\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // ReadSection or Produce FVB failed, Free data buffer\r
- //\r
- if (Buffer != NULL) {\r
- FreePool (Buffer);\r
- }\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // ReadSection or Produce FVB failed, Free data buffer\r
+ //\r
+ if (Buffer != NULL) {\r
+ FreePool (Buffer);\r
+ }\r
+\r
+ if (AlignedBuffer != NULL) {\r
+ FreeAlignedPages (AlignedBuffer, EFI_SIZE_TO_PAGES (BufferSize));\r
+ }\r
\r
- if (AlignedBuffer != NULL) {\r
- FreeAlignedPages (AlignedBuffer, EFI_SIZE_TO_PAGES (BufferSize));\r
+ break;\r
+ } else {\r
+ Index++;\r
}\r
- }\r
+ } while (TRUE);\r
\r
- return Status;\r
+ if (Index > 0) {\r
+ //\r
+ // At least one FvImage has been processed successfully.\r
+ //\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ return Status;\r
+ }\r
}\r
\r
\r
{\r
EFI_STATUS Status;\r
EFI_STATUS GetNextFileStatus;\r
- EFI_STATUS SecurityStatus;\r
EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r
EFI_DEVICE_PATH_PROTOCOL *FvDevicePath;\r
EFI_HANDLE FvHandle;\r
LIST_ENTRY *Link;\r
UINT32 AuthenticationStatus;\r
UINTN SizeOfBuffer;\r
+ VOID *DepexBuffer;\r
+ KNOWN_HANDLE *KnownHandle;\r
\r
+ FvHandle = NULL;\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
continue;\r
}\r
\r
- //\r
- // Evaluate the authentication status of the Firmware Volume through\r
- // Security Architectural Protocol\r
- //\r
- if (gSecurity != NULL) {\r
- SecurityStatus = gSecurity->FileAuthenticationState (\r
- gSecurity,\r
- 0,\r
- FvDevicePath\r
- );\r
- if (SecurityStatus != EFI_SUCCESS) {\r
- //\r
- // Security check failed. The firmware volume should not be used for any purpose.\r
- //\r
- continue;\r
- }\r
- }\r
-\r
//\r
// Discover Drivers in FV and add them to the Discovered Driver List.\r
// Process EFI_FV_FILETYPE_DRIVER type and then EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER\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
+ //\r
+ // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has SMM depex section.\r
+ //\r
+ DepexBuffer = NULL;\r
+ SizeOfBuffer = 0;\r
+ Status = Fv->ReadSection (\r
+ Fv,\r
+ &NameGuid,\r
+ EFI_SECTION_SMM_DEPEX,\r
+ 0,\r
+ &DepexBuffer,\r
+ &SizeOfBuffer,\r
+ &AuthenticationStatus\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // If SMM depex section is found, this FV image is invalid to be supported.\r
+ // ASSERT FALSE to report this FV image.\r
+ //\r
+ FreePool (DepexBuffer);\r
+ ASSERT (FALSE);\r
+ }\r
+\r
//\r
- // Found a firmware volume image. Produce a firmware volume block\r
- // protocol for it so it gets dispatched from. This is usually a\r
- // capsule.\r
+ // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has DXE depex section.\r
//\r
- CoreProcessFvImageFile (Fv, FvHandle, &NameGuid);\r
+ DepexBuffer = NULL;\r
+ SizeOfBuffer = 0;\r
+ Status = Fv->ReadSection (\r
+ Fv,\r
+ &NameGuid,\r
+ EFI_SECTION_DXE_DEPEX,\r
+ 0,\r
+ &DepexBuffer,\r
+ &SizeOfBuffer,\r
+ &AuthenticationStatus\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // If no depex section, produce a firmware volume block protocol for it so it gets dispatched from.\r
+ //\r
+ CoreProcessFvImageFile (Fv, FvHandle, &NameGuid);\r
+ } else {\r
+ //\r
+ // If depex section is found, this FV image will be dispatched until its depex is evaluated to TRUE.\r
+ //\r
+ FreePool (DepexBuffer);\r
+ CoreAddToDriverList (Fv, FvHandle, &NameGuid, Type);\r
+ }\r
} else {\r
//\r
// Transition driver from Undiscovered to Discovered state\r
//\r
- CoreAddToDriverList (Fv, FvHandle, &NameGuid);\r
+ CoreAddToDriverList (Fv, FvHandle, &NameGuid, Type);\r
}\r
}\r
} while (!EFI_ERROR (GetNextFileStatus));\r
// drivers not in the current FV and these must be skipped since the a priori list\r
// is only valid for the FV that it resided in.\r
//\r
- CoreAcquireDispatcherLock ();\r
\r
for (Index = 0; Index < AprioriEntryCount; Index++) {\r
for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {\r
DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);\r
if (CompareGuid (&DriverEntry->FileName, &AprioriFile[Index]) &&\r
(FvHandle == DriverEntry->FvHandle)) {\r
+ CoreAcquireDispatcherLock ();\r
DriverEntry->Dependent = FALSE;\r
DriverEntry->Scheduled = TRUE;\r
InsertTailList (&mScheduledQueue, &DriverEntry->ScheduledLink);\r
+ CoreReleaseDispatcherLock ();\r
+ DEBUG ((DEBUG_DISPATCH, "Evaluate DXE DEPEX for FFS(%g)\n", &DriverEntry->FileName));\r
+ DEBUG ((DEBUG_DISPATCH, " RESULT = TRUE (Apriori)\n"));\r
break;\r
}\r
}\r
}\r
\r
- CoreReleaseDispatcherLock ();\r
-\r
//\r
// Free data allocated by Fv->ReadSection ()\r
//\r
VOID\r
)\r
{\r
+ PERF_FUNCTION_BEGIN ();\r
+\r
mFwVolEvent = EfiCreateProtocolNotifyEvent (\r
&gEfiFirmwareVolume2ProtocolGuid,\r
TPL_CALLBACK,\r
NULL,\r
&mFwVolEventRegistration\r
);\r
+\r
+ PERF_FUNCTION_END ();\r
}\r
\r
//\r