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