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