4 Step #1 - When a FV protocol is added to the system every driver in the FV
5 is added to the mDiscoveredList. The SOR, Before, and After Depex are
6 pre-processed as drivers are added to the mDiscoveredList. If an Apriori
7 file exists in the FV those drivers are addeded to the
8 mScheduledQueue. The mFvHandleList is used to make sure a
9 FV is only processed once.
11 Step #2 - Dispatch. Remove driver from the mScheduledQueue and load and
12 start it. After mScheduledQueue is drained check the
13 mDiscoveredList to see if any item has a Depex that is ready to
14 be placed on the mScheduledQueue.
16 Step #3 - Adding to the mScheduledQueue requires that you process Before
17 and After dependencies. This is done recursively as the call to add
18 to the mScheduledQueue checks for Before and recursively adds
19 all Befores. It then addes the item that was passed in and then
20 processess the After dependecies by recursively calling the routine.
23 The rules for the dispatcher are in chapter 10 of the DXE CIS. Figure 10-3
24 is the state diagram for the DXE dispatcher
26 Depex - Dependency Expresion.
27 SOR - Schedule On Request - Don't schedule if this bit is set.
29 Copyright (c) 2006 - 2007, Intel Corporation
30 All rights reserved. This program and the accompanying materials
31 are licensed and made available under the terms and conditions of the BSD License
32 which accompanies this distribution. The full text of the license may be found at
33 http://opensource.org/licenses/bsd-license.php
35 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
36 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
43 // The Driver List contains one copy of every driver that has been discovered.
44 // Items are never removed from the driver list. List of EFI_CORE_DRIVER_ENTRY
46 LIST_ENTRY mDiscoveredList
= INITIALIZE_LIST_HEAD_VARIABLE (mDiscoveredList
);
49 // Queue of drivers that are ready to dispatch. This queue is a subset of the
50 // mDiscoveredList.list of EFI_CORE_DRIVER_ENTRY.
52 LIST_ENTRY mScheduledQueue
= INITIALIZE_LIST_HEAD_VARIABLE (mScheduledQueue
);
55 // List of handles who's Fv's have been parsed and added to the mFwDriverList.
57 LIST_ENTRY mFvHandleList
= INITIALIZE_LIST_HEAD_VARIABLE (mFvHandleList
); // list of KNOWN_HANDLE
60 // Lock for mDiscoveredList, mScheduledQueue, gDispatcherRunning.
62 EFI_LOCK mDispatcherLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_HIGH_LEVEL
);
66 // Flag for the DXE Dispacher. TRUE if dispatcher is execuing.
68 BOOLEAN gDispatcherRunning
= FALSE
;
71 // Module globals to manage the FwVol registration notification event
73 EFI_EVENT mFwVolEvent
;
74 VOID
*mFwVolEventRegistration
;
77 // List of file types supported by dispatcher
79 static EFI_FV_FILETYPE mDxeFileTypes
[] = {
80 EFI_FV_FILETYPE_DRIVER
,
81 EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
,
82 EFI_FV_FILETYPE_DXE_CORE
,
83 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
87 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH File
;
88 EFI_DEVICE_PATH_PROTOCOL End
;
89 } FV_FILEPATH_DEVICE_PATH
;
91 FV_FILEPATH_DEVICE_PATH mFvDevicePath
;
95 // Function Prototypes
99 CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (
100 IN EFI_CORE_DRIVER_ENTRY
*InsertedDriverEntry
106 CoreFwVolEventProtocolNotify (
112 EFI_DEVICE_PATH_PROTOCOL
*
114 IN EFI_FIRMWARE_VOLUME2_PROTOCOL
*Fv
,
115 IN EFI_HANDLE FvHandle
,
116 IN EFI_GUID
*DriverName
121 CoreAddToDriverList (
122 IN EFI_FIRMWARE_VOLUME2_PROTOCOL
*Fv
,
123 IN EFI_HANDLE FvHandle
,
124 IN EFI_GUID
*DriverName
129 CoreProcessFvImageFile (
130 IN EFI_FIRMWARE_VOLUME2_PROTOCOL
*Fv
,
131 IN EFI_HANDLE FvHandle
,
132 IN EFI_GUID
*DriverName
137 CoreAcquireDispatcherLock (
144 Enter critical section by gaining lock on mDispatcherLock
157 CoreAcquireLock (&mDispatcherLock
);
162 CoreReleaseDispatcherLock (
169 Exit critical section by releasing lock on mDispatcherLock
181 CoreReleaseLock (&mDispatcherLock
);
186 CoreGetDepexSectionAndPreProccess (
187 IN EFI_CORE_DRIVER_ENTRY
*DriverEntry
193 Read Depex and pre-process the Depex for Before and After. If Section Extraction
194 protocol returns an error via ReadSection defer the reading of the Depex.
198 DriverEntry - Driver to work on.
202 EFI_SUCCESS - Depex read and preprossesed
204 EFI_PROTOCOL_ERROR - The section extraction protocol returned an error and
205 Depex reading needs to be retried.
207 Other Error - DEPEX not found.
212 EFI_SECTION_TYPE SectionType
;
213 UINT32 AuthenticationStatus
;
214 EFI_FIRMWARE_VOLUME2_PROTOCOL
*Fv
;
217 Fv
= DriverEntry
->Fv
;
220 // Grab Depex info, it will never be free'ed.
222 SectionType
= EFI_SECTION_DXE_DEPEX
;
223 Status
= Fv
->ReadSection (
225 &DriverEntry
->FileName
,
229 (UINTN
*)&DriverEntry
->DepexSize
,
230 &AuthenticationStatus
232 if (EFI_ERROR (Status
)) {
233 if (Status
== EFI_PROTOCOL_ERROR
) {
235 // The section extraction protocol failed so set protocol error flag
237 DriverEntry
->DepexProtocolError
= TRUE
;
240 // If no Depex assume UEFI 2.0 driver model
242 DriverEntry
->Depex
= NULL
;
243 DriverEntry
->Dependent
= TRUE
;
244 DriverEntry
->DepexProtocolError
= FALSE
;
248 // Set Before, After, and Unrequested state information based on Depex
249 // Driver will be put in Dependent or Unrequested state
251 CorePreProcessDepex (DriverEntry
);
252 DriverEntry
->DepexProtocolError
= FALSE
;
262 IN EFI_HANDLE FirmwareVolumeHandle
,
263 IN EFI_GUID
*DriverName
269 Check every driver and locate a matching one. If the driver is found, the Unrequested
270 state flag is cleared.
274 FirmwareVolumeHandle - The handle of the Firmware Volume that contains the firmware
275 file specified by DriverName.
277 DriverName - The Driver name to put in the Dependent state.
281 EFI_SUCCESS - The DriverName was found and it's SOR bit was cleared
283 EFI_NOT_FOUND - The DriverName does not exist or it's SOR bit was not set.
288 EFI_CORE_DRIVER_ENTRY
*DriverEntry
;
291 // Check every driver
293 for (Link
= mDiscoveredList
.ForwardLink
; Link
!= &mDiscoveredList
; Link
= Link
->ForwardLink
) {
294 DriverEntry
= CR(Link
, EFI_CORE_DRIVER_ENTRY
, Link
, EFI_CORE_DRIVER_ENTRY_SIGNATURE
);
295 if (DriverEntry
->FvHandle
== FirmwareVolumeHandle
&&
296 DriverEntry
->Unrequested
&&
297 CompareGuid (DriverName
, &DriverEntry
->FileName
)) {
299 // Move the driver from the Unrequested to the Dependent state
301 CoreAcquireDispatcherLock ();
302 DriverEntry
->Unrequested
= FALSE
;
303 DriverEntry
->Dependent
= TRUE
;
304 CoreReleaseDispatcherLock ();
309 return EFI_NOT_FOUND
;
317 IN EFI_HANDLE FirmwareVolumeHandle
,
318 IN EFI_GUID
*DriverName
324 Convert a driver from the Untrused back to the Scheduled state
328 FirmwareVolumeHandle - The handle of the Firmware Volume that contains the firmware
329 file specified by DriverName.
331 DriverName - The Driver name to put in the Scheduled state
335 EFI_SUCCESS - The file was found in the untrusted state, and it was promoted
336 to the trusted state.
338 EFI_NOT_FOUND - The file was not found in the untrusted state.
343 EFI_CORE_DRIVER_ENTRY
*DriverEntry
;
346 // Check every driver
348 for (Link
= mDiscoveredList
.ForwardLink
; Link
!= &mDiscoveredList
; Link
= Link
->ForwardLink
) {
349 DriverEntry
= CR(Link
, EFI_CORE_DRIVER_ENTRY
, Link
, EFI_CORE_DRIVER_ENTRY_SIGNATURE
);
350 if (DriverEntry
->FvHandle
== FirmwareVolumeHandle
&&
351 DriverEntry
->Untrusted
&&
352 CompareGuid (DriverName
, &DriverEntry
->FileName
)) {
354 // Transition driver from Untrusted to Scheduled state.
356 CoreAcquireDispatcherLock ();
357 DriverEntry
->Untrusted
= FALSE
;
358 DriverEntry
->Scheduled
= TRUE
;
359 InsertTailList (&mScheduledQueue
, &DriverEntry
->ScheduledLink
);
360 CoreReleaseDispatcherLock ();
365 return EFI_NOT_FOUND
;
379 This is the main Dispatcher for DXE and it exits when there are no more
380 drivers to run. Drain the mScheduledQueue and load and start a PE
381 image for each driver. Search the mDiscoveredList to see if any driver can
382 be placed on the mScheduledQueue. If no drivers are placed on the
383 mScheduledQueue exit the function. On exit it is assumed the Bds()
384 will be called, and when the Bds() exits the Dispatcher will be called
393 EFI_ALREADY_STARTED - The DXE Dispatcher is already running
395 EFI_NOT_FOUND - No DXE Drivers were dispatched
397 EFI_SUCCESS - One or more DXE Drivers were dispatched
402 EFI_STATUS ReturnStatus
;
404 EFI_CORE_DRIVER_ENTRY
*DriverEntry
;
407 if (gDispatcherRunning
) {
409 // If the dispatcher is running don't let it be restarted.
411 return EFI_ALREADY_STARTED
;
414 gDispatcherRunning
= TRUE
;
417 ReturnStatus
= EFI_NOT_FOUND
;
420 // Drain the Scheduled Queue
422 while (!IsListEmpty (&mScheduledQueue
)) {
424 mScheduledQueue
.ForwardLink
,
425 EFI_CORE_DRIVER_ENTRY
,
427 EFI_CORE_DRIVER_ENTRY_SIGNATURE
431 // Load the DXE Driver image into memory. If the Driver was transitioned from
432 // Untrused to Scheduled it would have already been loaded so we may need to
433 // skip the LoadImage
435 if (DriverEntry
->ImageHandle
== NULL
) {
436 Status
= CoreLoadImage (
439 DriverEntry
->FvFileDevicePath
,
442 &DriverEntry
->ImageHandle
446 // Update the driver state to reflect that it's been loaded
448 if (EFI_ERROR (Status
)) {
449 CoreAcquireDispatcherLock ();
451 if (Status
== EFI_SECURITY_VIOLATION
) {
453 // Take driver from Scheduled to Untrused state
455 DriverEntry
->Untrusted
= TRUE
;
458 // The DXE Driver could not be loaded, and do not attempt to load or start it again.
459 // Take driver from Scheduled to Initialized.
461 // This case include the Never Trusted state if EFI_ACCESS_DENIED is returned
463 DriverEntry
->Initialized
= TRUE
;
466 DriverEntry
->Scheduled
= FALSE
;
467 RemoveEntryList (&DriverEntry
->ScheduledLink
);
469 CoreReleaseDispatcherLock ();
472 // If it's an error don't try the StartImage
478 CoreAcquireDispatcherLock ();
480 DriverEntry
->Scheduled
= FALSE
;
481 DriverEntry
->Initialized
= TRUE
;
482 RemoveEntryList (&DriverEntry
->ScheduledLink
);
484 CoreReleaseDispatcherLock ();
486 CoreReportProgressCodeSpecific (
487 FixedPcdGet32(PcdStatusCodeValueDxeDriverBegin
),
488 DriverEntry
->ImageHandle
490 Status
= CoreStartImage (DriverEntry
->ImageHandle
, NULL
, NULL
);
491 CoreReportProgressCodeSpecific (
492 FixedPcdGet32(PcdStatusCodeValueDxeDriverEnd
),
493 DriverEntry
->ImageHandle
496 ReturnStatus
= EFI_SUCCESS
;
500 // Search DriverList for items to place on Scheduled Queue
503 for (Link
= mDiscoveredList
.ForwardLink
; Link
!= &mDiscoveredList
; Link
= Link
->ForwardLink
) {
504 DriverEntry
= CR (Link
, EFI_CORE_DRIVER_ENTRY
, Link
, EFI_CORE_DRIVER_ENTRY_SIGNATURE
);
506 if (DriverEntry
->DepexProtocolError
){
508 // If Section Extraction Protocol did not let the Depex be read before retry the read
510 Status
= CoreGetDepexSectionAndPreProccess (DriverEntry
);
513 if (DriverEntry
->Dependent
) {
514 if (CoreIsSchedulable (DriverEntry
)) {
515 CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry
);
520 } while (ReadyToRun
);
522 gDispatcherRunning
= FALSE
;
529 CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (
530 IN EFI_CORE_DRIVER_ENTRY
*InsertedDriverEntry
536 Insert InsertedDriverEntry onto the mScheduledQueue. To do this you
537 must add any driver with a before dependency on InsertedDriverEntry first.
538 You do this by recursively calling this routine. After all the Befores are
539 processed you can add InsertedDriverEntry to the mScheduledQueue.
540 Then you can add any driver with an After dependency on InsertedDriverEntry
541 by recursively calling this routine.
545 InsertedDriverEntry - The driver to insert on the ScheduledLink Queue
554 EFI_CORE_DRIVER_ENTRY
*DriverEntry
;
557 // Process Before Dependency
559 for (Link
= mDiscoveredList
.ForwardLink
; Link
!= &mDiscoveredList
; Link
= Link
->ForwardLink
) {
560 DriverEntry
= CR(Link
, EFI_CORE_DRIVER_ENTRY
, Link
, EFI_CORE_DRIVER_ENTRY_SIGNATURE
);
561 if (DriverEntry
->Before
&& DriverEntry
->Dependent
) {
562 if (CompareGuid (&InsertedDriverEntry
->FileName
, &DriverEntry
->BeforeAfterGuid
)) {
564 // Recursively process BEFORE
566 CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry
);
572 // Convert driver from Dependent to Scheduled state
574 CoreAcquireDispatcherLock ();
576 InsertedDriverEntry
->Dependent
= FALSE
;
577 InsertedDriverEntry
->Scheduled
= TRUE
;
578 InsertTailList (&mScheduledQueue
, &InsertedDriverEntry
->ScheduledLink
);
580 CoreReleaseDispatcherLock ();
583 // Process After Dependency
585 for (Link
= mDiscoveredList
.ForwardLink
; Link
!= &mDiscoveredList
; Link
= Link
->ForwardLink
) {
586 DriverEntry
= CR(Link
, EFI_CORE_DRIVER_ENTRY
, Link
, EFI_CORE_DRIVER_ENTRY_SIGNATURE
);
587 if (DriverEntry
->After
&& DriverEntry
->Dependent
) {
588 if (CompareGuid (&InsertedDriverEntry
->FileName
, &DriverEntry
->BeforeAfterGuid
)) {
590 // Recursively process AFTER
592 CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry
);
601 IN EFI_HANDLE FvHandle
607 Return TRUE if the Fv has been processed, FALSE if not.
611 FvHandle - The handle of a FV that's being tested
615 TRUE - Fv protocol on FvHandle has been processed
617 FALSE - Fv protocol on FvHandle has not yet been processed
622 KNOWN_HANDLE
*KnownHandle
;
624 for (Link
= mFvHandleList
.ForwardLink
; Link
!= &mFvHandleList
; Link
= Link
->ForwardLink
) {
625 KnownHandle
= CR(Link
, KNOWN_HANDLE
, Link
, KNOWN_HANDLE_SIGNATURE
);
626 if (KnownHandle
->Handle
== FvHandle
) {
635 FvIsBeingProcesssed (
636 IN EFI_HANDLE FvHandle
642 Remember that Fv protocol on FvHandle has had it's drivers placed on the
643 mDiscoveredList. This fucntion adds entries on the mFvHandleList. Items are
644 never removed/freed from the mFvHandleList.
648 FvHandle - The handle of a FV that has been processed
656 KNOWN_HANDLE
*KnownHandle
;
658 KnownHandle
= CoreAllocateBootServicesPool (sizeof (KNOWN_HANDLE
));
659 ASSERT (KnownHandle
!= NULL
);
661 KnownHandle
->Signature
= KNOWN_HANDLE_SIGNATURE
;
662 KnownHandle
->Handle
= FvHandle
;
663 InsertTailList (&mFvHandleList
, &KnownHandle
->Link
);
669 EFI_DEVICE_PATH_PROTOCOL
*
671 IN EFI_FIRMWARE_VOLUME2_PROTOCOL
*Fv
,
672 IN EFI_HANDLE FvHandle
,
673 IN EFI_GUID
*DriverName
679 Convert FvHandle and DriverName into an EFI device path
683 Fv - Fv protocol, needed to read Depex info out of FLASH.
685 FvHandle - Handle for Fv, needed in the EFI_CORE_DRIVER_ENTRY so that the
686 PE image can be read out of the FV at a later time.
688 DriverName - Name of driver to add to mDiscoveredList.
692 Pointer to device path constructed from FvHandle and DriverName
697 EFI_DEVICE_PATH_PROTOCOL
*FvDevicePath
;
698 EFI_DEVICE_PATH_PROTOCOL
*FileNameDevicePath
;
701 // Remember the device path of the FV
703 Status
= CoreHandleProtocol (FvHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&FvDevicePath
);
704 if (EFI_ERROR (Status
)) {
705 FileNameDevicePath
= NULL
;
708 // Build a device path to the file in the FV to pass into gBS->LoadImage
710 EfiInitializeFwVolDevicepathNode (&mFvDevicePath
.File
, DriverName
);
711 mFvDevicePath
.End
.Type
= EFI_END_ENTIRE_DEVICE_PATH
;
712 mFvDevicePath
.End
.SubType
= END_ENTIRE_DEVICE_PATH_SUBTYPE
;
713 SetDevicePathNodeLength (&mFvDevicePath
.End
, sizeof (EFI_DEVICE_PATH_PROTOCOL
));
715 FileNameDevicePath
= CoreAppendDevicePath (
717 (EFI_DEVICE_PATH_PROTOCOL
*)&mFvDevicePath
721 return FileNameDevicePath
;
727 CoreAddToDriverList (
728 IN EFI_FIRMWARE_VOLUME2_PROTOCOL
*Fv
,
729 IN EFI_HANDLE FvHandle
,
730 IN EFI_GUID
*DriverName
736 Add an entry to the mDiscoveredList. Allocate memory to store the DriverEntry,
737 and initilize any state variables. Read the Depex from the FV and store it
738 in DriverEntry. Pre-process the Depex to set the SOR, Before and After state.
739 The Discovered list is never free'ed and contains booleans that represent the
740 other possible DXE driver states.
744 Fv - Fv protocol, needed to read Depex info out of FLASH.
746 FvHandle - Handle for Fv, needed in the EFI_CORE_DRIVER_ENTRY so that the
747 PE image can be read out of the FV at a later time.
749 DriverName - Name of driver to add to mDiscoveredList.
753 EFI_SUCCESS - If driver was added to the mDiscoveredList.
755 EFI_ALREADY_STARTED - The driver has already been started. Only one DriverName
756 may be active in the system at any one time.
760 EFI_CORE_DRIVER_ENTRY
*DriverEntry
;
764 // Create the Driver Entry for the list. ZeroPool initializes lots of variables to
767 DriverEntry
= CoreAllocateZeroBootServicesPool (sizeof (EFI_CORE_DRIVER_ENTRY
));
768 ASSERT (DriverEntry
!= NULL
);
770 DriverEntry
->Signature
= EFI_CORE_DRIVER_ENTRY_SIGNATURE
;
771 CopyMem (&DriverEntry
->FileName
, DriverName
, sizeof (EFI_GUID
));
772 DriverEntry
->FvHandle
= FvHandle
;
773 DriverEntry
->Fv
= Fv
;
774 DriverEntry
->FvFileDevicePath
= CoreFvToDevicePath (Fv
, FvHandle
, DriverName
);
776 CoreGetDepexSectionAndPreProccess (DriverEntry
);
778 CoreAcquireDispatcherLock ();
780 InsertTailList (&mDiscoveredList
, &DriverEntry
->Link
);
782 CoreReleaseDispatcherLock ();
790 IN EFI_HANDLE FvHandle
,
791 IN CONST EFI_GUID
*DriverName
797 Check if a FV Image type file (EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) is
798 described by a EFI_HOB_FIRMWARE_VOLUME2 Hob.
802 FvHandle - The handle which FVB protocol installed on.
803 DriverName - The driver guid specified.
807 TRUE - This file is found in a EFI_HOB_FIRMWARE_VOLUME2 Hob.
814 EFI_PEI_HOB_POINTERS HobFv2
;
816 HobFv2
.Raw
= GetHobList ();
818 while ((HobFv2
.Raw
= GetNextHob (EFI_HOB_TYPE_FV2
, HobFv2
.Raw
)) != NULL
) {
819 if (CompareGuid (DriverName
, &HobFv2
.FirmwareVolume2
->FileName
)) {
822 HobFv2
.Raw
= GET_NEXT_HOB (HobFv2
);
830 CoreProcessFvImageFile (
831 IN EFI_FIRMWARE_VOLUME2_PROTOCOL
*Fv
,
832 IN EFI_HANDLE FvHandle
,
833 IN EFI_GUID
*DriverName
839 Get the driver from the FV through driver name, and produce a FVB protocol on FvHandle.
843 Fv - The FIRMWARE_VOLUME protocol installed on the FV.
844 FvHandle - The handle which FVB protocol installed on.
845 DriverName - The driver guid specified.
849 EFI_OUT_OF_RESOURCES - No enough memory or other resource.
851 EFI_VOLUME_CORRUPTED - Corrupted volume.
853 EFI_SUCCESS - Function successfully returned.
859 EFI_SECTION_TYPE SectionType
;
860 UINT32 AuthenticationStatus
;
865 // Read the first (and only the first) firmware volume section
867 SectionType
= EFI_SECTION_FIRMWARE_VOLUME_IMAGE
;
870 Status
= Fv
->ReadSection (
877 &AuthenticationStatus
879 if (!EFI_ERROR (Status
)) {
881 // Produce a FVB protocol for the file
883 Status
= ProduceFVBProtocolOnBuffer (
884 (EFI_PHYSICAL_ADDRESS
) (UINTN
) Buffer
,
891 if (EFI_ERROR (Status
) && (Buffer
!= NULL
)) {
893 // ReadSection or Produce FVB failed, Free data buffer
895 CoreFreePool (Buffer
);
905 CoreFwVolEventProtocolNotify (
913 Event notification that is fired every time a FV dispatch protocol is added.
914 More than one protocol may have been added when this event is fired, so you
915 must loop on CoreLocateHandle () to see how many protocols were added and
916 do the following to each FV:
918 If the Fv has already been processed, skip it. If the Fv has not been
919 processed then mark it as being processed, as we are about to process it.
921 Read the Fv and add any driver in the Fv to the mDiscoveredList.The
922 mDiscoveredList is never free'ed and contains variables that define
923 the other states the DXE driver transitions to..
925 While you are at it read the A Priori file into memory.
926 Place drivers in the A Priori list onto the mScheduledQueue.
930 Event - The Event that is being processed, not used.
932 Context - Event Context, not used.
941 EFI_STATUS GetNextFileStatus
;
942 EFI_STATUS SecurityStatus
;
943 EFI_FIRMWARE_VOLUME2_PROTOCOL
*Fv
;
944 EFI_DEVICE_PATH_PROTOCOL
*FvDevicePath
;
949 EFI_FV_FILETYPE Type
;
950 EFI_FV_FILE_ATTRIBUTES Attributes
;
952 EFI_CORE_DRIVER_ENTRY
*DriverEntry
;
953 EFI_GUID
*AprioriFile
;
954 UINTN AprioriEntryCount
;
957 UINT32 AuthenticationStatus
;
962 BufferSize
= sizeof (EFI_HANDLE
);
963 Status
= CoreLocateHandle (
966 mFwVolEventRegistration
,
970 if (EFI_ERROR (Status
)) {
972 // If no more notification events exit
977 if (FvHasBeenProcessed (FvHandle
)) {
979 // This Fv has already been processed so lets skip it!
984 Status
= CoreHandleProtocol (FvHandle
, &gEfiFirmwareVolumeDispatchProtocolGuid
, (VOID
**)&Fv
);
985 if (EFI_ERROR (Status
)) {
987 // If no dispatch protocol then skip, but do not marked as being processed as it
988 // may show up later.
994 // Since we are about to process this Fv mark it as processed.
996 FvIsBeingProcesssed (FvHandle
);
999 Status
= CoreHandleProtocol (FvHandle
, &gEfiFirmwareVolume2ProtocolGuid
, (VOID
**)&Fv
);
1000 if (EFI_ERROR (Status
)) {
1002 // The Handle has a FirmwareVolumeDispatch protocol and should also contiain
1003 // a FirmwareVolume protocol thus we should never get here.
1009 Status
= CoreHandleProtocol (FvHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&FvDevicePath
);
1010 if (EFI_ERROR (Status
)) {
1012 // The Firmware volume doesn't have device path, can't be dispatched.
1018 // Evaluate the authentication status of the Firmware Volume through
1019 // Security Architectural Protocol
1021 if (gSecurity
!= NULL
) {
1022 SecurityStatus
= gSecurity
->FileAuthenticationState (
1027 if (SecurityStatus
!= EFI_SUCCESS
) {
1029 // Security check failed. The firmware volume should not be used for any purpose.
1036 // Discover Drivers in FV and add them to the Discovered Driver List.
1037 // Process EFI_FV_FILETYPE_DRIVER type and then EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
1038 // EFI_FV_FILETYPE_DXE_CORE is processed to produce a Loaded Image protocol for the core
1039 // EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE is processed to create a Fvb
1041 for (Index
= 0; Index
< sizeof (mDxeFileTypes
)/sizeof (EFI_FV_FILETYPE
); Index
++) {
1043 // Initialize the search key
1047 Type
= mDxeFileTypes
[Index
];
1048 GetNextFileStatus
= Fv
->GetNextFile (
1056 if (!EFI_ERROR (GetNextFileStatus
)) {
1057 if (Type
== EFI_FV_FILETYPE_DXE_CORE
) {
1059 // If this is the DXE core fill in it's DevicePath & DeviceHandle
1061 if (gDxeCoreLoadedImage
->FilePath
== NULL
) {
1062 if (CompareGuid (&NameGuid
, gDxeCoreFileName
)) {
1064 // Maybe One specail Fv cantains only one DXE_CORE module, so its device path must
1065 // be initialized completely.
1067 EfiInitializeFwVolDevicepathNode (&mFvDevicePath
.File
, &NameGuid
);
1068 mFvDevicePath
.End
.Type
= EFI_END_ENTIRE_DEVICE_PATH
;
1069 mFvDevicePath
.End
.SubType
= END_ENTIRE_DEVICE_PATH_SUBTYPE
;
1070 SetDevicePathNodeLength (&mFvDevicePath
.End
, sizeof (EFI_DEVICE_PATH_PROTOCOL
));
1072 gDxeCoreLoadedImage
->FilePath
= CoreDuplicateDevicePath (
1073 (EFI_DEVICE_PATH_PROTOCOL
*)&mFvDevicePath
1075 gDxeCoreLoadedImage
->DeviceHandle
= FvHandle
;
1078 } else if (Type
== EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
) {
1080 // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already
1083 if (FvFoundInHobFv2 (FvHandle
, &NameGuid
)) {
1087 // Found a firmware volume image. Produce a firmware volume block
1088 // protocol for it so it gets dispatched from. This is usually a
1091 CoreProcessFvImageFile (Fv
, FvHandle
, &NameGuid
);
1094 // Transition driver from Undiscovered to Discovered state
1096 CoreAddToDriverList (Fv
, FvHandle
, &NameGuid
);
1099 } while (!EFI_ERROR (GetNextFileStatus
));
1103 // Read the array of GUIDs from the Apriori file if it is present in the firmware volume
1106 Status
= Fv
->ReadSection (
1111 (VOID
**)&AprioriFile
,
1113 &AuthenticationStatus
1115 if (!EFI_ERROR (Status
)) {
1116 AprioriEntryCount
= SizeOfBuffer
/ sizeof (EFI_GUID
);
1118 AprioriEntryCount
= 0;
1122 // Put drivers on Apriori List on the Scheduled queue. The Discovered List includes
1123 // drivers not in the current FV and these must be skipped since the a priori list
1124 // is only valid for the FV that it resided in.
1126 CoreAcquireDispatcherLock ();
1128 for (Index
= 0; Index
< AprioriEntryCount
; Index
++) {
1129 for (Link
= mDiscoveredList
.ForwardLink
; Link
!= &mDiscoveredList
; Link
= Link
->ForwardLink
) {
1130 DriverEntry
= CR(Link
, EFI_CORE_DRIVER_ENTRY
, Link
, EFI_CORE_DRIVER_ENTRY_SIGNATURE
);
1131 if (CompareGuid (&DriverEntry
->FileName
, &AprioriFile
[Index
]) &&
1132 (FvHandle
== DriverEntry
->FvHandle
)) {
1133 DriverEntry
->Dependent
= FALSE
;
1134 DriverEntry
->Scheduled
= TRUE
;
1135 InsertTailList (&mScheduledQueue
, &DriverEntry
->ScheduledLink
);
1141 CoreReleaseDispatcherLock ();
1144 // Free data allocated by Fv->ReadSection ()
1146 CoreFreePool (AprioriFile
);
1152 CoreInitializeDispatcher (
1157 Routine Description:
1159 Initialize the dispatcher. Initialize the notification function that runs when
1160 a FV protocol is added to the system.
1172 mFwVolEvent
= CoreCreateProtocolNotifyEvent (
1173 &gEfiFirmwareVolume2ProtocolGuid
,
1175 CoreFwVolEventProtocolNotify
,
1177 &mFwVolEventRegistration
,
1183 // Function only used in debug builds
1186 CoreDisplayDiscoveredNotDispatched (
1191 Routine Description:
1193 Traverse the discovered list for any drivers that were discovered but not loaded
1194 because the dependency experessions evaluated to false
1207 EFI_CORE_DRIVER_ENTRY
*DriverEntry
;
1209 for (Link
= mDiscoveredList
.ForwardLink
;Link
!=&mDiscoveredList
; Link
= Link
->ForwardLink
) {
1210 DriverEntry
= CR(Link
, EFI_CORE_DRIVER_ENTRY
, Link
, EFI_CORE_DRIVER_ENTRY_SIGNATURE
);
1211 if (DriverEntry
->Dependent
) {
1212 DEBUG ((EFI_D_LOAD
, "Driver %g was discovered but not loaded!!\n", &DriverEntry
->FileName
));