]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Dxe/Dispatcher/Dispatcher.c
Clean up: update "EFI" to "UEFI" if applicable.
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Dispatcher / Dispatcher.c
1 /*++
2
3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 Dispatcher.c
15
16 Abstract:
17
18 Tiano DXE Dispatcher.
19
20 Step #1 - When a FV protocol is added to the system every driver in the FV
21 is added to the mDiscoveredList. The SOR, Before, and After Depex are
22 pre-processed as drivers are added to the mDiscoveredList. If an Apriori
23 file exists in the FV those drivers are addeded to the
24 mScheduledQueue. The mFvHandleList is used to make sure a
25 FV is only processed once.
26
27 Step #2 - Dispatch. Remove driver from the mScheduledQueue and load and
28 start it. After mScheduledQueue is drained check the
29 mDiscoveredList to see if any item has a Depex that is ready to
30 be placed on the mScheduledQueue.
31
32 Step #3 - Adding to the mScheduledQueue requires that you process Before
33 and After dependencies. This is done recursively as the call to add
34 to the mScheduledQueue checks for Before and recursively adds
35 all Befores. It then addes the item that was passed in and then
36 processess the After dependecies by recursively calling the routine.
37
38 Dispatcher Rules:
39 The rules for the dispatcher are in chapter 10 of the DXE CIS. Figure 10-3
40 is the state diagram for the DXE dispatcher
41
42 Depex - Dependency Expresion.
43 SOR - Schedule On Request - Don't schedule if this bit is set.
44
45 --*/
46
47 #include <DxeMain.h>
48
49 //
50 // The Driver List contains one copy of every driver that has been discovered.
51 // Items are never removed from the driver list. List of EFI_CORE_DRIVER_ENTRY
52 //
53 LIST_ENTRY mDiscoveredList = INITIALIZE_LIST_HEAD_VARIABLE (mDiscoveredList);
54
55 //
56 // Queue of drivers that are ready to dispatch. This queue is a subset of the
57 // mDiscoveredList.list of EFI_CORE_DRIVER_ENTRY.
58 //
59 LIST_ENTRY mScheduledQueue = INITIALIZE_LIST_HEAD_VARIABLE (mScheduledQueue);
60
61 //
62 // List of handles who's Fv's have been parsed and added to the mFwDriverList.
63 //
64 LIST_ENTRY mFvHandleList = INITIALIZE_LIST_HEAD_VARIABLE (mFvHandleList); // list of KNOWN_HANDLE
65
66 //
67 // Lock for mDiscoveredList, mScheduledQueue, gDispatcherRunning.
68 //
69 EFI_LOCK mDispatcherLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_HIGH_LEVEL);
70
71
72 //
73 // Flag for the DXE Dispacher. TRUE if dispatcher is execuing.
74 //
75 BOOLEAN gDispatcherRunning = FALSE;
76
77 //
78 // Module globals to manage the FwVol registration notification event
79 //
80 EFI_EVENT mFwVolEvent;
81 VOID *mFwVolEventRegistration;
82
83 //
84 // List of file types supported by dispatcher
85 //
86 static EFI_FV_FILETYPE mDxeFileTypes[] = {
87 EFI_FV_FILETYPE_DRIVER,
88 EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER,
89 EFI_FV_FILETYPE_DXE_CORE,
90 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
91 };
92
93 typedef struct {
94 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH File;
95 EFI_DEVICE_PATH_PROTOCOL End;
96 } FV_FILEPATH_DEVICE_PATH;
97
98 FV_FILEPATH_DEVICE_PATH mFvDevicePath;
99
100
101 //
102 // Function Prototypes
103 //
104 STATIC
105 VOID
106 CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (
107 IN EFI_CORE_DRIVER_ENTRY *InsertedDriverEntry
108 );
109
110 STATIC
111 VOID
112 EFIAPI
113 CoreFwVolEventProtocolNotify (
114 IN EFI_EVENT Event,
115 IN VOID *Context
116 );
117
118 STATIC
119 EFI_DEVICE_PATH_PROTOCOL *
120 CoreFvToDevicePath (
121 IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv,
122 IN EFI_HANDLE FvHandle,
123 IN EFI_GUID *DriverName
124 );
125
126 STATIC
127 EFI_STATUS
128 CoreAddToDriverList (
129 IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv,
130 IN EFI_HANDLE FvHandle,
131 IN EFI_GUID *DriverName
132 );
133
134 STATIC
135 EFI_STATUS
136 CoreProcessFvImageFile (
137 IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv,
138 IN EFI_HANDLE FvHandle,
139 IN EFI_GUID *DriverName
140 );
141
142 STATIC
143 VOID
144 CoreAcquireDispatcherLock (
145 VOID
146 )
147 /*++
148
149 Routine Description:
150
151 Enter critical section by gaining lock on mDispatcherLock
152
153 Arguments:
154
155 None
156
157 Returns:
158
159 None
160
161 --*/
162
163 {
164 CoreAcquireLock (&mDispatcherLock);
165 }
166
167 STATIC
168 VOID
169 CoreReleaseDispatcherLock (
170 VOID
171 )
172 /*++
173
174 Routine Description:
175
176 Exit critical section by releasing lock on mDispatcherLock
177
178 Arguments:
179
180 None
181
182 Returns:
183
184 None
185
186 --*/
187 {
188 CoreReleaseLock (&mDispatcherLock);
189 }
190
191 STATIC
192 EFI_STATUS
193 CoreGetDepexSectionAndPreProccess (
194 IN EFI_CORE_DRIVER_ENTRY *DriverEntry
195 )
196 /*++
197
198 Routine Description:
199
200 Read Depex and pre-process the Depex for Before and After. If Section Extraction
201 protocol returns an error via ReadSection defer the reading of the Depex.
202
203 Arguments:
204
205 DriverEntry - Driver to work on.
206
207 Returns:
208
209 EFI_SUCCESS - Depex read and preprossesed
210
211 EFI_PROTOCOL_ERROR - The section extraction protocol returned an error and
212 Depex reading needs to be retried.
213
214 Other Error - DEPEX not found.
215
216 --*/
217 {
218 EFI_STATUS Status;
219 EFI_SECTION_TYPE SectionType;
220 UINT32 AuthenticationStatus;
221 EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
222
223
224 Fv = DriverEntry->Fv;
225
226 //
227 // Grab Depex info, it will never be free'ed.
228 //
229 SectionType = EFI_SECTION_DXE_DEPEX;
230 Status = Fv->ReadSection (
231 DriverEntry->Fv,
232 &DriverEntry->FileName,
233 SectionType,
234 0,
235 &DriverEntry->Depex,
236 (UINTN *)&DriverEntry->DepexSize,
237 &AuthenticationStatus
238 );
239 if (EFI_ERROR (Status)) {
240 if (Status == EFI_PROTOCOL_ERROR) {
241 //
242 // The section extraction protocol failed so set protocol error flag
243 //
244 DriverEntry->DepexProtocolError = TRUE;
245 } else {
246 //
247 // If no Depex assume UEFI 2.0 driver model
248 //
249 DriverEntry->Depex = NULL;
250 DriverEntry->Dependent = TRUE;
251 DriverEntry->DepexProtocolError = FALSE;
252 }
253 } else {
254 //
255 // Set Before, After, and Unrequested state information based on Depex
256 // Driver will be put in Dependent or Unrequested state
257 //
258 CorePreProcessDepex (DriverEntry);
259 DriverEntry->DepexProtocolError = FALSE;
260 }
261
262 return Status;
263 }
264
265 EFI_DXESERVICE
266 EFI_STATUS
267 EFIAPI
268 CoreSchedule (
269 IN EFI_HANDLE FirmwareVolumeHandle,
270 IN EFI_GUID *DriverName
271 )
272 /*++
273
274 Routine Description:
275
276 Check every driver and locate a matching one. If the driver is found, the Unrequested
277 state flag is cleared.
278
279 Arguments:
280
281 FirmwareVolumeHandle - The handle of the Firmware Volume that contains the firmware
282 file specified by DriverName.
283
284 DriverName - The Driver name to put in the Dependent state.
285
286 Returns:
287
288 EFI_SUCCESS - The DriverName was found and it's SOR bit was cleared
289
290 EFI_NOT_FOUND - The DriverName does not exist or it's SOR bit was not set.
291
292 --*/
293 {
294 LIST_ENTRY *Link;
295 EFI_CORE_DRIVER_ENTRY *DriverEntry;
296
297 //
298 // Check every driver
299 //
300 for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
301 DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
302 if (DriverEntry->FvHandle == FirmwareVolumeHandle &&
303 DriverEntry->Unrequested &&
304 CompareGuid (DriverName, &DriverEntry->FileName)) {
305 //
306 // Move the driver from the Unrequested to the Dependent state
307 //
308 CoreAcquireDispatcherLock ();
309 DriverEntry->Unrequested = FALSE;
310 DriverEntry->Dependent = TRUE;
311 CoreReleaseDispatcherLock ();
312
313 return EFI_SUCCESS;
314 }
315 }
316 return EFI_NOT_FOUND;
317 }
318
319
320 EFI_DXESERVICE
321 EFI_STATUS
322 EFIAPI
323 CoreTrust (
324 IN EFI_HANDLE FirmwareVolumeHandle,
325 IN EFI_GUID *DriverName
326 )
327 /*++
328
329 Routine Description:
330
331 Convert a driver from the Untrused back to the Scheduled state
332
333 Arguments:
334
335 FirmwareVolumeHandle - The handle of the Firmware Volume that contains the firmware
336 file specified by DriverName.
337
338 DriverName - The Driver name to put in the Scheduled state
339
340 Returns:
341
342 EFI_SUCCESS - The file was found in the untrusted state, and it was promoted
343 to the trusted state.
344
345 EFI_NOT_FOUND - The file was not found in the untrusted state.
346
347 --*/
348 {
349 LIST_ENTRY *Link;
350 EFI_CORE_DRIVER_ENTRY *DriverEntry;
351
352 //
353 // Check every driver
354 //
355 for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
356 DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
357 if (DriverEntry->FvHandle == FirmwareVolumeHandle &&
358 DriverEntry->Untrusted &&
359 CompareGuid (DriverName, &DriverEntry->FileName)) {
360 //
361 // Transition driver from Untrusted to Scheduled state.
362 //
363 CoreAcquireDispatcherLock ();
364 DriverEntry->Untrusted = FALSE;
365 DriverEntry->Scheduled = TRUE;
366 InsertTailList (&mScheduledQueue, &DriverEntry->ScheduledLink);
367 CoreReleaseDispatcherLock ();
368
369 return EFI_SUCCESS;
370 }
371 }
372 return EFI_NOT_FOUND;
373 }
374
375
376 EFI_DXESERVICE
377 EFI_STATUS
378 EFIAPI
379 CoreDispatcher (
380 VOID
381 )
382 /*++
383
384 Routine Description:
385
386 This is the main Dispatcher for DXE and it exits when there are no more
387 drivers to run. Drain the mScheduledQueue and load and start a PE
388 image for each driver. Search the mDiscoveredList to see if any driver can
389 be placed on the mScheduledQueue. If no drivers are placed on the
390 mScheduledQueue exit the function. On exit it is assumed the Bds()
391 will be called, and when the Bds() exits the Dispatcher will be called
392 again.
393
394 Arguments:
395
396 NONE
397
398 Returns:
399
400 EFI_ALREADY_STARTED - The DXE Dispatcher is already running
401
402 EFI_NOT_FOUND - No DXE Drivers were dispatched
403
404 EFI_SUCCESS - One or more DXE Drivers were dispatched
405
406 --*/
407 {
408 EFI_STATUS Status;
409 EFI_STATUS ReturnStatus;
410 LIST_ENTRY *Link;
411 EFI_CORE_DRIVER_ENTRY *DriverEntry;
412 BOOLEAN ReadyToRun;
413
414 if (gDispatcherRunning) {
415 //
416 // If the dispatcher is running don't let it be restarted.
417 //
418 return EFI_ALREADY_STARTED;
419 }
420
421 gDispatcherRunning = TRUE;
422
423
424 ReturnStatus = EFI_NOT_FOUND;
425 do {
426 //
427 // Drain the Scheduled Queue
428 //
429 while (!IsListEmpty (&mScheduledQueue)) {
430 DriverEntry = CR (
431 mScheduledQueue.ForwardLink,
432 EFI_CORE_DRIVER_ENTRY,
433 ScheduledLink,
434 EFI_CORE_DRIVER_ENTRY_SIGNATURE
435 );
436
437 //
438 // Load the DXE Driver image into memory. If the Driver was transitioned from
439 // Untrused to Scheduled it would have already been loaded so we may need to
440 // skip the LoadImage
441 //
442 if (DriverEntry->ImageHandle == NULL) {
443 Status = CoreLoadImage (
444 FALSE,
445 gDxeCoreImageHandle,
446 DriverEntry->FvFileDevicePath,
447 NULL,
448 0,
449 &DriverEntry->ImageHandle
450 );
451
452 //
453 // Update the driver state to reflect that it's been loaded
454 //
455 if (EFI_ERROR (Status)) {
456 CoreAcquireDispatcherLock ();
457
458 if (Status == EFI_SECURITY_VIOLATION) {
459 //
460 // Take driver from Scheduled to Untrused state
461 //
462 DriverEntry->Untrusted = TRUE;
463 } else {
464 //
465 // The DXE Driver could not be loaded, and do not attempt to load or start it again.
466 // Take driver from Scheduled to Initialized.
467 //
468 // This case include the Never Trusted state if EFI_ACCESS_DENIED is returned
469 //
470 DriverEntry->Initialized = TRUE;
471 }
472
473 DriverEntry->Scheduled = FALSE;
474 RemoveEntryList (&DriverEntry->ScheduledLink);
475
476 CoreReleaseDispatcherLock ();
477
478 //
479 // If it's an error don't try the StartImage
480 //
481 continue;
482 }
483 }
484
485 CoreAcquireDispatcherLock ();
486
487 DriverEntry->Scheduled = FALSE;
488 DriverEntry->Initialized = TRUE;
489 RemoveEntryList (&DriverEntry->ScheduledLink);
490
491 CoreReleaseDispatcherLock ();
492
493 CoreReportProgressCodeSpecific (EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_BEGIN, DriverEntry->ImageHandle);
494 Status = CoreStartImage (DriverEntry->ImageHandle, NULL, NULL);
495 CoreReportProgressCodeSpecific (EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_END, DriverEntry->ImageHandle);
496
497 ReturnStatus = EFI_SUCCESS;
498 }
499
500 //
501 // Search DriverList for items to place on Scheduled Queue
502 //
503 ReadyToRun = FALSE;
504 for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
505 DriverEntry = CR (Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
506
507 if (DriverEntry->DepexProtocolError){
508 //
509 // If Section Extraction Protocol did not let the Depex be read before retry the read
510 //
511 Status = CoreGetDepexSectionAndPreProccess (DriverEntry);
512 }
513
514 if (DriverEntry->Dependent) {
515 if (CoreIsSchedulable (DriverEntry)) {
516 CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);
517 ReadyToRun = TRUE;
518 }
519 }
520 }
521 } while (ReadyToRun);
522
523 gDispatcherRunning = FALSE;
524
525 return ReturnStatus;
526 }
527
528 STATIC
529 VOID
530 CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (
531 IN EFI_CORE_DRIVER_ENTRY *InsertedDriverEntry
532 )
533 /*++
534
535 Routine Description:
536
537 Insert InsertedDriverEntry onto the mScheduledQueue. To do this you
538 must add any driver with a before dependency on InsertedDriverEntry first.
539 You do this by recursively calling this routine. After all the Befores are
540 processed you can add InsertedDriverEntry to the mScheduledQueue.
541 Then you can add any driver with an After dependency on InsertedDriverEntry
542 by recursively calling this routine.
543
544 Arguments:
545
546 InsertedDriverEntry - The driver to insert on the ScheduledLink Queue
547
548 Returns:
549
550 NONE
551
552 --*/
553 {
554 LIST_ENTRY *Link;
555 EFI_CORE_DRIVER_ENTRY *DriverEntry;
556
557 //
558 // Process Before Dependency
559 //
560 for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
561 DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
562 if (DriverEntry->Before && DriverEntry->Dependent) {
563 if (CompareGuid (&InsertedDriverEntry->FileName, &DriverEntry->BeforeAfterGuid)) {
564 //
565 // Recursively process BEFORE
566 //
567 CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);
568 }
569 }
570 }
571
572 //
573 // Convert driver from Dependent to Scheduled state
574 //
575 CoreAcquireDispatcherLock ();
576
577 InsertedDriverEntry->Dependent = FALSE;
578 InsertedDriverEntry->Scheduled = TRUE;
579 InsertTailList (&mScheduledQueue, &InsertedDriverEntry->ScheduledLink);
580
581 CoreReleaseDispatcherLock ();
582
583 //
584 // Process After Dependency
585 //
586 for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
587 DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
588 if (DriverEntry->After && DriverEntry->Dependent) {
589 if (CompareGuid (&InsertedDriverEntry->FileName, &DriverEntry->BeforeAfterGuid)) {
590 //
591 // Recursively process AFTER
592 //
593 CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);
594 }
595 }
596 }
597 }
598
599 STATIC
600 BOOLEAN
601 FvHasBeenProcessed (
602 IN EFI_HANDLE FvHandle
603 )
604 /*++
605
606 Routine Description:
607
608 Return TRUE if the Fv has been processed, FALSE if not.
609
610 Arguments:
611
612 FvHandle - The handle of a FV that's being tested
613
614 Returns:
615
616 TRUE - Fv protocol on FvHandle has been processed
617
618 FALSE - Fv protocol on FvHandle has not yet been processed
619
620 --*/
621 {
622 LIST_ENTRY *Link;
623 KNOWN_HANDLE *KnownHandle;
624
625 for (Link = mFvHandleList.ForwardLink; Link != &mFvHandleList; Link = Link->ForwardLink) {
626 KnownHandle = CR(Link, KNOWN_HANDLE, Link, KNOWN_HANDLE_SIGNATURE);
627 if (KnownHandle->Handle == FvHandle) {
628 return TRUE;
629 }
630 }
631 return FALSE;
632 }
633
634 STATIC
635 VOID
636 FvIsBeingProcesssed (
637 IN EFI_HANDLE FvHandle
638 )
639 /*++
640
641 Routine Description:
642
643 Remember that Fv protocol on FvHandle has had it's drivers placed on the
644 mDiscoveredList. This fucntion adds entries on the mFvHandleList. Items are
645 never removed/freed from the mFvHandleList.
646
647 Arguments:
648
649 FvHandle - The handle of a FV that has been processed
650
651 Returns:
652
653 None
654
655 --*/
656 {
657 KNOWN_HANDLE *KnownHandle;
658
659 KnownHandle = CoreAllocateBootServicesPool (sizeof (KNOWN_HANDLE));
660 ASSERT (KnownHandle != NULL);
661
662 KnownHandle->Signature = KNOWN_HANDLE_SIGNATURE;
663 KnownHandle->Handle = FvHandle;
664 InsertTailList (&mFvHandleList, &KnownHandle->Link);
665 }
666
667
668
669 STATIC
670 EFI_DEVICE_PATH_PROTOCOL *
671 CoreFvToDevicePath (
672 IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv,
673 IN EFI_HANDLE FvHandle,
674 IN EFI_GUID *DriverName
675 )
676 /*++
677
678 Routine Description:
679
680 Convert FvHandle and DriverName into an EFI device path
681
682 Arguments:
683
684 Fv - Fv protocol, needed to read Depex info out of FLASH.
685
686 FvHandle - Handle for Fv, needed in the EFI_CORE_DRIVER_ENTRY so that the
687 PE image can be read out of the FV at a later time.
688
689 DriverName - Name of driver to add to mDiscoveredList.
690
691 Returns:
692
693 Pointer to device path constructed from FvHandle and DriverName
694
695 --*/
696 {
697 EFI_STATUS Status;
698 EFI_DEVICE_PATH_PROTOCOL *FvDevicePath;
699 EFI_DEVICE_PATH_PROTOCOL *FileNameDevicePath;
700
701 //
702 // Remember the device path of the FV
703 //
704 Status = CoreHandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath);
705 if (EFI_ERROR (Status)) {
706 FileNameDevicePath = NULL;
707 } else {
708 //
709 // Build a device path to the file in the FV to pass into gBS->LoadImage
710 //
711 EfiInitializeFwVolDevicepathNode (&mFvDevicePath.File, DriverName);
712 mFvDevicePath.End.Type = EFI_END_ENTIRE_DEVICE_PATH;
713 mFvDevicePath.End.SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
714 SetDevicePathNodeLength (&mFvDevicePath.End, sizeof (EFI_DEVICE_PATH_PROTOCOL));
715
716 FileNameDevicePath = CoreAppendDevicePath (
717 FvDevicePath,
718 (EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath
719 );
720 }
721
722 return FileNameDevicePath;
723 }
724
725
726
727 EFI_STATUS
728 CoreAddToDriverList (
729 IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv,
730 IN EFI_HANDLE FvHandle,
731 IN EFI_GUID *DriverName
732 )
733 /*++
734
735 Routine Description:
736
737 Add an entry to the mDiscoveredList. Allocate memory to store the DriverEntry,
738 and initilize any state variables. Read the Depex from the FV and store it
739 in DriverEntry. Pre-process the Depex to set the SOR, Before and After state.
740 The Discovered list is never free'ed and contains booleans that represent the
741 other possible DXE driver states.
742
743 Arguments:
744
745 Fv - Fv protocol, needed to read Depex info out of FLASH.
746
747 FvHandle - Handle for Fv, needed in the EFI_CORE_DRIVER_ENTRY so that the
748 PE image can be read out of the FV at a later time.
749
750 DriverName - Name of driver to add to mDiscoveredList.
751
752 Returns:
753
754 EFI_SUCCESS - If driver was added to the mDiscoveredList.
755
756 EFI_ALREADY_STARTED - The driver has already been started. Only one DriverName
757 may be active in the system at any one time.
758
759 --*/
760 {
761 EFI_CORE_DRIVER_ENTRY *DriverEntry;
762
763
764 //
765 // Create the Driver Entry for the list. ZeroPool initializes lots of variables to
766 // NULL or FALSE.
767 //
768 DriverEntry = CoreAllocateZeroBootServicesPool (sizeof (EFI_CORE_DRIVER_ENTRY));
769 ASSERT (DriverEntry != NULL);
770
771 DriverEntry->Signature = EFI_CORE_DRIVER_ENTRY_SIGNATURE;
772 CopyMem (&DriverEntry->FileName, DriverName, sizeof (EFI_GUID));
773 DriverEntry->FvHandle = FvHandle;
774 DriverEntry->Fv = Fv;
775 DriverEntry->FvFileDevicePath = CoreFvToDevicePath (Fv, FvHandle, DriverName);
776
777 CoreGetDepexSectionAndPreProccess (DriverEntry);
778
779 CoreAcquireDispatcherLock ();
780
781 InsertTailList (&mDiscoveredList, &DriverEntry->Link);
782
783 CoreReleaseDispatcherLock ();
784
785 return EFI_SUCCESS;
786 }
787
788 STATIC
789 BOOLEAN
790 FvFoundInHobFv2 (
791 IN EFI_HANDLE FvHandle,
792 IN CONST EFI_GUID *DriverName
793 )
794 /*++
795
796 Routine Description:
797
798 Check if a FV Image type file (EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) is
799 described by a EFI_HOB_FIRMWARE_VOLUME2 Hob.
800
801 Arguments:
802
803 FvHandle - The handle which FVB protocol installed on.
804 DriverName - The driver guid specified.
805
806 Returns:
807
808 TRUE - This file is found in a EFI_HOB_FIRMWARE_VOLUME2 Hob.
809
810 FALSE - Not found.
811
812
813 --*/
814 {
815 EFI_PEI_HOB_POINTERS HobFv2;
816
817 HobFv2.Raw = GetHobList ();
818
819 while ((HobFv2.Raw = GetNextHob (EFI_HOB_TYPE_FV2, HobFv2.Raw)) != NULL) {
820 if (CompareGuid (DriverName, &HobFv2.FirmwareVolume2->FileName)) {
821 return TRUE;
822 }
823 HobFv2.Raw = GET_NEXT_HOB (HobFv2);
824 }
825
826 return FALSE;
827 }
828
829
830 EFI_STATUS
831 CoreProcessFvImageFile (
832 IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv,
833 IN EFI_HANDLE FvHandle,
834 IN EFI_GUID *DriverName
835 )
836 /*++
837
838 Routine Description:
839
840 Get the driver from the FV through driver name, and produce a FVB protocol on FvHandle.
841
842 Arguments:
843
844 Fv - The FIRMWARE_VOLUME protocol installed on the FV.
845 FvHandle - The handle which FVB protocol installed on.
846 DriverName - The driver guid specified.
847
848 Returns:
849
850 EFI_OUT_OF_RESOURCES - No enough memory or other resource.
851
852 EFI_VOLUME_CORRUPTED - Corrupted volume.
853
854 EFI_SUCCESS - Function successfully returned.
855
856
857 --*/
858 {
859 EFI_STATUS Status;
860 EFI_SECTION_TYPE SectionType;
861 UINT32 AuthenticationStatus;
862 VOID *Buffer;
863 UINTN BufferSize;
864
865 //
866 // Read the first (and only the first) firmware volume section
867 //
868 SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;
869 Buffer = NULL;
870 BufferSize = 0;
871 Status = Fv->ReadSection (
872 Fv,
873 DriverName,
874 SectionType,
875 0,
876 &Buffer,
877 &BufferSize,
878 &AuthenticationStatus
879 );
880 if (!EFI_ERROR (Status)) {
881 //
882 // Produce a FVB protocol for the file
883 //
884 Status = ProduceFVBProtocolOnBuffer (
885 (EFI_PHYSICAL_ADDRESS) (UINTN) Buffer,
886 (UINT64)BufferSize,
887 FvHandle,
888 NULL
889 );
890 }
891
892 if (EFI_ERROR (Status) && (Buffer != NULL)) {
893 //
894 // ReadSection or Produce FVB failed, Free data buffer
895 //
896 CoreFreePool (Buffer);
897
898 }
899
900 return Status;
901 }
902
903 STATIC
904 VOID
905 EFIAPI
906 CoreFwVolEventProtocolNotify (
907 IN EFI_EVENT Event,
908 IN VOID *Context
909 )
910 /*++
911
912 Routine Description:
913
914 Event notification that is fired every time a FV dispatch protocol is added.
915 More than one protocol may have been added when this event is fired, so you
916 must loop on CoreLocateHandle () to see how many protocols were added and
917 do the following to each FV:
918
919 If the Fv has already been processed, skip it. If the Fv has not been
920 processed then mark it as being processed, as we are about to process it.
921
922 Read the Fv and add any driver in the Fv to the mDiscoveredList.The
923 mDiscoveredList is never free'ed and contains variables that define
924 the other states the DXE driver transitions to..
925
926 While you are at it read the A Priori file into memory.
927 Place drivers in the A Priori list onto the mScheduledQueue.
928
929 Arguments:
930
931 Event - The Event that is being processed, not used.
932
933 Context - Event Context, not used.
934
935 Returns:
936
937 None
938
939 --*/
940 {
941 EFI_STATUS Status;
942 EFI_STATUS GetNextFileStatus;
943 EFI_STATUS SecurityStatus;
944 EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
945 EFI_DEVICE_PATH_PROTOCOL *FvDevicePath;
946 EFI_HANDLE FvHandle;
947 UINTN BufferSize;
948 EFI_GUID NameGuid;
949 UINTN Key;
950 EFI_FV_FILETYPE Type;
951 EFI_FV_FILE_ATTRIBUTES Attributes;
952 UINTN Size;
953 EFI_CORE_DRIVER_ENTRY *DriverEntry;
954 EFI_GUID *AprioriFile;
955 UINTN AprioriEntryCount;
956 UINTN Index;
957 LIST_ENTRY *Link;
958 UINT32 AuthenticationStatus;
959 UINTN SizeOfBuffer;
960
961
962 while (TRUE) {
963 BufferSize = sizeof (EFI_HANDLE);
964 Status = CoreLocateHandle (
965 ByRegisterNotify,
966 NULL,
967 mFwVolEventRegistration,
968 &BufferSize,
969 &FvHandle
970 );
971 if (EFI_ERROR (Status)) {
972 //
973 // If no more notification events exit
974 //
975 return;
976 }
977
978 if (FvHasBeenProcessed (FvHandle)) {
979 //
980 // This Fv has already been processed so lets skip it!
981 //
982 continue;
983 }
984
985 Status = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolumeDispatchProtocolGuid, (VOID **)&Fv);
986 if (EFI_ERROR (Status)) {
987 //
988 // If no dispatch protocol then skip, but do not marked as being processed as it
989 // may show up later.
990 //
991 continue;
992 }
993
994 //
995 // Since we are about to process this Fv mark it as processed.
996 //
997 FvIsBeingProcesssed (FvHandle);
998
999
1000 Status = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv);
1001 if (EFI_ERROR (Status)) {
1002 //
1003 // The Handle has a FirmwareVolumeDispatch protocol and should also contiain
1004 // a FirmwareVolume protocol thus we should never get here.
1005 //
1006 ASSERT (FALSE);
1007 continue;
1008 }
1009
1010 Status = CoreHandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath);
1011 if (EFI_ERROR (Status)) {
1012 //
1013 // The Firmware volume doesn't have device path, can't be dispatched.
1014 //
1015 continue;
1016 }
1017
1018 //
1019 // Evaluate the authentication status of the Firmware Volume through
1020 // Security Architectural Protocol
1021 //
1022 if (gSecurity != NULL) {
1023 SecurityStatus = gSecurity->FileAuthenticationState (
1024 gSecurity,
1025 0,
1026 FvDevicePath
1027 );
1028 if (SecurityStatus != EFI_SUCCESS) {
1029 //
1030 // Security check failed. The firmware volume should not be used for any purpose.
1031 //
1032 continue;
1033 }
1034 }
1035
1036 //
1037 // Discover Drivers in FV and add them to the Discovered Driver List.
1038 // Process EFI_FV_FILETYPE_DRIVER type and then EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
1039 // EFI_FV_FILETYPE_DXE_CORE is processed to produce a Loaded Image protocol for the core
1040 // EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE is processed to create a Fvb
1041 //
1042 for (Index = 0; Index < sizeof (mDxeFileTypes)/sizeof (EFI_FV_FILETYPE); Index++) {
1043 //
1044 // Initialize the search key
1045 //
1046 Key = 0;
1047 do {
1048 Type = mDxeFileTypes[Index];
1049 GetNextFileStatus = Fv->GetNextFile (
1050 Fv,
1051 &Key,
1052 &Type,
1053 &NameGuid,
1054 &Attributes,
1055 &Size
1056 );
1057 if (!EFI_ERROR (GetNextFileStatus)) {
1058 if (Type == EFI_FV_FILETYPE_DXE_CORE) {
1059 //
1060 // If this is the DXE core fill in it's DevicePath & DeviceHandle
1061 //
1062 if (gDxeCoreLoadedImage->FilePath == NULL) {
1063 if (CompareGuid (&NameGuid, gDxeCoreFileName)) {
1064 //
1065 // Maybe One specail Fv cantains only one DXE_CORE module, so its device path must
1066 // be initialized completely.
1067 //
1068 EfiInitializeFwVolDevicepathNode (&mFvDevicePath.File, &NameGuid);
1069 mFvDevicePath.End.Type = EFI_END_ENTIRE_DEVICE_PATH;
1070 mFvDevicePath.End.SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
1071 SetDevicePathNodeLength (&mFvDevicePath.End, sizeof (EFI_DEVICE_PATH_PROTOCOL));
1072
1073 gDxeCoreLoadedImage->FilePath = CoreDuplicateDevicePath (
1074 (EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath
1075 );
1076 gDxeCoreLoadedImage->DeviceHandle = FvHandle;
1077 }
1078 }
1079 } else if (Type == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
1080 //
1081 // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already
1082 // been extracted.
1083 //
1084 if (FvFoundInHobFv2 (FvHandle, &NameGuid)) {
1085 continue;
1086 }
1087
1088 //
1089 // Found a firmware volume image. Produce a firmware volume block
1090 // protocol for it so it gets dispatched from. This is usually a
1091 // capsule.
1092 //
1093 CoreProcessFvImageFile (Fv, FvHandle, &NameGuid);
1094 } else {
1095 //
1096 // Transition driver from Undiscovered to Discovered state
1097 //
1098 CoreAddToDriverList (Fv, FvHandle, &NameGuid);
1099 }
1100 }
1101 } while (!EFI_ERROR (GetNextFileStatus));
1102 }
1103
1104 //
1105 // Read the array of GUIDs from the Apriori file if it is present in the firmware volume
1106 //
1107 AprioriFile = NULL;
1108 Status = Fv->ReadSection (
1109 Fv,
1110 &gAprioriGuid,
1111 EFI_SECTION_RAW,
1112 0,
1113 (VOID **)&AprioriFile,
1114 &SizeOfBuffer,
1115 &AuthenticationStatus
1116 );
1117 if (!EFI_ERROR (Status)) {
1118 AprioriEntryCount = SizeOfBuffer / sizeof (EFI_GUID);
1119 } else {
1120 AprioriEntryCount = 0;
1121 }
1122
1123 //
1124 // Put drivers on Apriori List on the Scheduled queue. The Discovered List includes
1125 // drivers not in the current FV and these must be skipped since the a priori list
1126 // is only valid for the FV that it resided in.
1127 //
1128 CoreAcquireDispatcherLock ();
1129
1130 for (Index = 0; Index < AprioriEntryCount; Index++) {
1131 for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
1132 DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
1133 if (CompareGuid (&DriverEntry->FileName, &AprioriFile[Index]) &&
1134 (FvHandle == DriverEntry->FvHandle)) {
1135 DriverEntry->Dependent = FALSE;
1136 DriverEntry->Scheduled = TRUE;
1137 InsertTailList (&mScheduledQueue, &DriverEntry->ScheduledLink);
1138 break;
1139 }
1140 }
1141 }
1142
1143 CoreReleaseDispatcherLock ();
1144
1145 //
1146 // Free data allocated by Fv->ReadSection ()
1147 //
1148 CoreFreePool (AprioriFile);
1149 }
1150 }
1151
1152
1153 VOID
1154 CoreInitializeDispatcher (
1155 VOID
1156 )
1157 /*++
1158
1159 Routine Description:
1160
1161 Initialize the dispatcher. Initialize the notification function that runs when
1162 a FV protocol is added to the system.
1163
1164 Arguments:
1165
1166 NONE
1167
1168 Returns:
1169
1170 NONE
1171
1172 --*/
1173 {
1174 mFwVolEvent = CoreCreateProtocolNotifyEvent (
1175 &gEfiFirmwareVolume2ProtocolGuid,
1176 TPL_CALLBACK,
1177 CoreFwVolEventProtocolNotify,
1178 NULL,
1179 &mFwVolEventRegistration,
1180 TRUE
1181 );
1182 }
1183
1184 //
1185 // Function only used in debug builds
1186 //
1187 VOID
1188 CoreDisplayDiscoveredNotDispatched (
1189 VOID
1190 )
1191 /*++
1192
1193 Routine Description:
1194
1195 Traverse the discovered list for any drivers that were discovered but not loaded
1196 because the dependency experessions evaluated to false
1197
1198 Arguments:
1199
1200 NONE
1201
1202 Returns:
1203
1204 NONE
1205
1206 --*/
1207 {
1208 LIST_ENTRY *Link;
1209 EFI_CORE_DRIVER_ENTRY *DriverEntry;
1210
1211 for (Link = mDiscoveredList.ForwardLink;Link !=&mDiscoveredList; Link = Link->ForwardLink) {
1212 DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
1213 if (DriverEntry->Dependent) {
1214 DEBUG ((EFI_D_LOAD, "Driver %g was discovered but not loaded!!\n", &DriverEntry->FileName));
1215 }
1216 }
1217 }