]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Dxe/Dispatcher/Dispatcher.c
Move sure FvImage buffer at its alignment when install FVB protocol on it.
[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
898 AlignedBuffer = AllocateAlignedPool ((UINTN) BufferSize, (UINTN) FvAlignment);
899 if (AlignedBuffer == NULL) {
900 Status = EFI_OUT_OF_RESOURCES;
901 } else {
902 //
903 // Move FvImage into the aligned buffer and release the original buffer.
904 //
905 CopyMem (AlignedBuffer, Buffer, BufferSize);
906 CoreFreePool (Buffer);
907 Buffer = NULL;
908 //
909 // Produce a FVB protocol for the file
910 //
911 Status = ProduceFVBProtocolOnBuffer (
912 (EFI_PHYSICAL_ADDRESS) (UINTN) AlignedBuffer,
913 (UINT64)BufferSize,
914 FvHandle,
915 NULL
916 );
917 }
918 }
919
920 if (EFI_ERROR (Status)) {
921 //
922 // ReadSection or Produce FVB failed, Free data buffer
923 //
924 if (Buffer != NULL) {
925 CoreFreePool (Buffer);
926 }
927
928 if (AlignedBuffer != NULL) {
929 FreeAlignedPool (AlignedBuffer);
930 }
931 }
932
933 return Status;
934 }
935
936 STATIC
937 VOID
938 EFIAPI
939 CoreFwVolEventProtocolNotify (
940 IN EFI_EVENT Event,
941 IN VOID *Context
942 )
943 /*++
944
945 Routine Description:
946
947 Event notification that is fired every time a FV dispatch protocol is added.
948 More than one protocol may have been added when this event is fired, so you
949 must loop on CoreLocateHandle () to see how many protocols were added and
950 do the following to each FV:
951
952 If the Fv has already been processed, skip it. If the Fv has not been
953 processed then mark it as being processed, as we are about to process it.
954
955 Read the Fv and add any driver in the Fv to the mDiscoveredList.The
956 mDiscoveredList is never free'ed and contains variables that define
957 the other states the DXE driver transitions to..
958
959 While you are at it read the A Priori file into memory.
960 Place drivers in the A Priori list onto the mScheduledQueue.
961
962 Arguments:
963
964 Event - The Event that is being processed, not used.
965
966 Context - Event Context, not used.
967
968 Returns:
969
970 None
971
972 --*/
973 {
974 EFI_STATUS Status;
975 EFI_STATUS GetNextFileStatus;
976 EFI_STATUS SecurityStatus;
977 EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
978 EFI_DEVICE_PATH_PROTOCOL *FvDevicePath;
979 EFI_HANDLE FvHandle;
980 UINTN BufferSize;
981 EFI_GUID NameGuid;
982 UINTN Key;
983 EFI_FV_FILETYPE Type;
984 EFI_FV_FILE_ATTRIBUTES Attributes;
985 UINTN Size;
986 EFI_CORE_DRIVER_ENTRY *DriverEntry;
987 EFI_GUID *AprioriFile;
988 UINTN AprioriEntryCount;
989 UINTN Index;
990 LIST_ENTRY *Link;
991 UINT32 AuthenticationStatus;
992 UINTN SizeOfBuffer;
993
994
995 while (TRUE) {
996 BufferSize = sizeof (EFI_HANDLE);
997 Status = CoreLocateHandle (
998 ByRegisterNotify,
999 NULL,
1000 mFwVolEventRegistration,
1001 &BufferSize,
1002 &FvHandle
1003 );
1004 if (EFI_ERROR (Status)) {
1005 //
1006 // If no more notification events exit
1007 //
1008 return;
1009 }
1010
1011 if (FvHasBeenProcessed (FvHandle)) {
1012 //
1013 // This Fv has already been processed so lets skip it!
1014 //
1015 continue;
1016 }
1017
1018 Status = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolumeDispatchProtocolGuid, (VOID **)&Fv);
1019 if (EFI_ERROR (Status)) {
1020 //
1021 // If no dispatch protocol then skip, but do not marked as being processed as it
1022 // may show up later.
1023 //
1024 continue;
1025 }
1026
1027 //
1028 // Since we are about to process this Fv mark it as processed.
1029 //
1030 FvIsBeingProcesssed (FvHandle);
1031
1032
1033 Status = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv);
1034 if (EFI_ERROR (Status)) {
1035 //
1036 // The Handle has a FirmwareVolumeDispatch protocol and should also contiain
1037 // a FirmwareVolume protocol thus we should never get here.
1038 //
1039 ASSERT (FALSE);
1040 continue;
1041 }
1042
1043 Status = CoreHandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath);
1044 if (EFI_ERROR (Status)) {
1045 //
1046 // The Firmware volume doesn't have device path, can't be dispatched.
1047 //
1048 continue;
1049 }
1050
1051 //
1052 // Evaluate the authentication status of the Firmware Volume through
1053 // Security Architectural Protocol
1054 //
1055 if (gSecurity != NULL) {
1056 SecurityStatus = gSecurity->FileAuthenticationState (
1057 gSecurity,
1058 0,
1059 FvDevicePath
1060 );
1061 if (SecurityStatus != EFI_SUCCESS) {
1062 //
1063 // Security check failed. The firmware volume should not be used for any purpose.
1064 //
1065 continue;
1066 }
1067 }
1068
1069 //
1070 // Discover Drivers in FV and add them to the Discovered Driver List.
1071 // Process EFI_FV_FILETYPE_DRIVER type and then EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
1072 // EFI_FV_FILETYPE_DXE_CORE is processed to produce a Loaded Image protocol for the core
1073 // EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE is processed to create a Fvb
1074 //
1075 for (Index = 0; Index < sizeof (mDxeFileTypes)/sizeof (EFI_FV_FILETYPE); Index++) {
1076 //
1077 // Initialize the search key
1078 //
1079 Key = 0;
1080 do {
1081 Type = mDxeFileTypes[Index];
1082 GetNextFileStatus = Fv->GetNextFile (
1083 Fv,
1084 &Key,
1085 &Type,
1086 &NameGuid,
1087 &Attributes,
1088 &Size
1089 );
1090 if (!EFI_ERROR (GetNextFileStatus)) {
1091 if (Type == EFI_FV_FILETYPE_DXE_CORE) {
1092 //
1093 // If this is the DXE core fill in it's DevicePath & DeviceHandle
1094 //
1095 if (gDxeCoreLoadedImage->FilePath == NULL) {
1096 if (CompareGuid (&NameGuid, gDxeCoreFileName)) {
1097 //
1098 // Maybe One specail Fv cantains only one DXE_CORE module, so its device path must
1099 // be initialized completely.
1100 //
1101 EfiInitializeFwVolDevicepathNode (&mFvDevicePath.File, &NameGuid);
1102 mFvDevicePath.End.Type = EFI_END_ENTIRE_DEVICE_PATH;
1103 mFvDevicePath.End.SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
1104 SetDevicePathNodeLength (&mFvDevicePath.End, sizeof (EFI_DEVICE_PATH_PROTOCOL));
1105
1106 gDxeCoreLoadedImage->FilePath = CoreDuplicateDevicePath (
1107 (EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath
1108 );
1109 gDxeCoreLoadedImage->DeviceHandle = FvHandle;
1110 }
1111 }
1112 } else if (Type == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
1113 //
1114 // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already
1115 // been extracted.
1116 //
1117 if (FvFoundInHobFv2 (FvHandle, &NameGuid)) {
1118 continue;
1119 }
1120 //
1121 // Found a firmware volume image. Produce a firmware volume block
1122 // protocol for it so it gets dispatched from. This is usually a
1123 // capsule.
1124 //
1125 CoreProcessFvImageFile (Fv, FvHandle, &NameGuid);
1126 } else {
1127 //
1128 // Transition driver from Undiscovered to Discovered state
1129 //
1130 CoreAddToDriverList (Fv, FvHandle, &NameGuid);
1131 }
1132 }
1133 } while (!EFI_ERROR (GetNextFileStatus));
1134 }
1135
1136 //
1137 // Read the array of GUIDs from the Apriori file if it is present in the firmware volume
1138 //
1139 AprioriFile = NULL;
1140 Status = Fv->ReadSection (
1141 Fv,
1142 &gAprioriGuid,
1143 EFI_SECTION_RAW,
1144 0,
1145 (VOID **)&AprioriFile,
1146 &SizeOfBuffer,
1147 &AuthenticationStatus
1148 );
1149 if (!EFI_ERROR (Status)) {
1150 AprioriEntryCount = SizeOfBuffer / sizeof (EFI_GUID);
1151 } else {
1152 AprioriEntryCount = 0;
1153 }
1154
1155 //
1156 // Put drivers on Apriori List on the Scheduled queue. The Discovered List includes
1157 // drivers not in the current FV and these must be skipped since the a priori list
1158 // is only valid for the FV that it resided in.
1159 //
1160 CoreAcquireDispatcherLock ();
1161
1162 for (Index = 0; Index < AprioriEntryCount; Index++) {
1163 for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
1164 DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
1165 if (CompareGuid (&DriverEntry->FileName, &AprioriFile[Index]) &&
1166 (FvHandle == DriverEntry->FvHandle)) {
1167 DriverEntry->Dependent = FALSE;
1168 DriverEntry->Scheduled = TRUE;
1169 InsertTailList (&mScheduledQueue, &DriverEntry->ScheduledLink);
1170 break;
1171 }
1172 }
1173 }
1174
1175 CoreReleaseDispatcherLock ();
1176
1177 //
1178 // Free data allocated by Fv->ReadSection ()
1179 //
1180 CoreFreePool (AprioriFile);
1181 }
1182 }
1183
1184
1185 VOID
1186 CoreInitializeDispatcher (
1187 VOID
1188 )
1189 /*++
1190
1191 Routine Description:
1192
1193 Initialize the dispatcher. Initialize the notification function that runs when
1194 a FV protocol is added to the system.
1195
1196 Arguments:
1197
1198 NONE
1199
1200 Returns:
1201
1202 NONE
1203
1204 --*/
1205 {
1206 mFwVolEvent = CoreCreateProtocolNotifyEvent (
1207 &gEfiFirmwareVolume2ProtocolGuid,
1208 TPL_CALLBACK,
1209 CoreFwVolEventProtocolNotify,
1210 NULL,
1211 &mFwVolEventRegistration,
1212 TRUE
1213 );
1214 }
1215
1216 //
1217 // Function only used in debug builds
1218 //
1219 VOID
1220 CoreDisplayDiscoveredNotDispatched (
1221 VOID
1222 )
1223 /*++
1224
1225 Routine Description:
1226
1227 Traverse the discovered list for any drivers that were discovered but not loaded
1228 because the dependency experessions evaluated to false
1229
1230 Arguments:
1231
1232 NONE
1233
1234 Returns:
1235
1236 NONE
1237
1238 --*/
1239 {
1240 LIST_ENTRY *Link;
1241 EFI_CORE_DRIVER_ENTRY *DriverEntry;
1242
1243 for (Link = mDiscoveredList.ForwardLink;Link !=&mDiscoveredList; Link = Link->ForwardLink) {
1244 DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
1245 if (DriverEntry->Dependent) {
1246 DEBUG ((EFI_D_LOAD, "Driver %g was discovered but not loaded!!\n", &DriverEntry->FileName));
1247 }
1248 }
1249 }