2 EFI PEI Core dispatch services
4 Copyright (c) 2006, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 /// CAR is filled with this initial value during SEC phase
20 #define INIT_CAR_VALUE 0x5AA55AA5
23 EFI_STATUS_CODE_DATA DataHeader
;
25 } PEIM_FILE_HANDLE_EXTENDED_DATA
;
29 Discover all Peims and optional Apriori file in one FV. There is at most one
30 Apriori file in one FV.
33 @param Private - Pointer to the private data passed in from caller
34 @param VolumeHandle - Fv handle.
38 DiscoverPeimsAndOrderWithApriori (
39 IN PEI_CORE_INSTANCE
*Private
,
40 IN EFI_PEI_FV_HANDLE VolumeHandle
44 EFI_PEI_FV_HANDLE FileHandle
;
45 EFI_PEI_FILE_HANDLE AprioriFileHandle
;
52 EFI_PEI_FV_HANDLE TempFileHandles
[FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv
)];
53 EFI_GUID FileGuid
[FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv
)];
56 // Walk the FV and find all the PEIMs and the Apriori file.
58 AprioriFileHandle
= NULL
;
59 Private
->CurrentFvFileHandles
[0] = NULL
;
64 // If the current Fv has been scanned, directly get its cachable record.
66 if (Private
->Fv
[Private
->CurrentPeimFvCount
].ScanFv
) {
67 CopyMem (Private
->CurrentFvFileHandles
, Private
->Fv
[Private
->CurrentPeimFvCount
].FvFileHandles
, sizeof (Private
->CurrentFvFileHandles
));
72 // Go ahead to scan this Fv, and cache FileHandles within it.
74 for (PeimCount
= 0; PeimCount
< FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv
); PeimCount
++) {
75 Status
= PeiFindFileEx (
78 PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE
,
82 if (Status
!= EFI_SUCCESS
) {
86 Private
->CurrentFvFileHandles
[PeimCount
] = FileHandle
;
89 Private
->AprioriCount
= 0;
90 if (AprioriFileHandle
!= NULL
) {
92 // Read the Apriori file
94 Status
= PeiServicesFfsFindSectionData (EFI_SECTION_RAW
, AprioriFileHandle
, (VOID
**) &Apriori
);
95 if (!EFI_ERROR (Status
)) {
97 // Calculate the number of PEIMs in the A Priori list
99 Private
->AprioriCount
= *(UINT32
*)(((EFI_FFS_FILE_HEADER
*)AprioriFileHandle
)->Size
) & 0x00FFFFFF;
100 Private
->AprioriCount
-= sizeof (EFI_FFS_FILE_HEADER
) - sizeof (EFI_COMMON_SECTION_HEADER
);
101 Private
->AprioriCount
/= sizeof (EFI_GUID
);
103 ZeroMem (FileGuid
, sizeof (FileGuid
));
104 for (Index
= 0; Index
< PeimCount
; Index
++) {
106 // Make an array of file name guids that matches the FileHandle array so we can convert
107 // quickly from file name to file handle
109 CopyMem (&FileGuid
[Index
], &((EFI_FFS_FILE_HEADER
*)Private
->CurrentFvFileHandles
[Index
])->Name
,sizeof(EFI_GUID
));
113 // Walk through FileGuid array to find out who is invalid PEIM guid in Apriori file.
114 // Add avalible PEIMs in Apriori file into TempFileHandles array at first.
117 for (Index
= 0; Index2
< Private
->AprioriCount
; Index
++) {
118 while (Index2
< Private
->AprioriCount
) {
119 Guid
= ScanGuid (FileGuid
, PeimCount
* sizeof (EFI_GUID
), &Apriori
[Index2
++]);
127 PeimIndex
= ((UINTN
)Guid
- (UINTN
)&FileGuid
[0])/sizeof (EFI_GUID
);
128 TempFileHandles
[Index
] = Private
->CurrentFvFileHandles
[PeimIndex
];
131 // Since we have copied the file handle we can remove it from this list.
133 Private
->CurrentFvFileHandles
[PeimIndex
] = NULL
;
137 // Update valid Aprioricount
139 Private
->AprioriCount
= Index
;
142 // Add in any PEIMs not in the Apriori file
144 for (;Index
< PeimCount
; Index
++) {
145 for (Index2
= 0; Index2
< PeimCount
; Index2
++) {
146 if (Private
->CurrentFvFileHandles
[Index2
] != NULL
) {
147 TempFileHandles
[Index
] = Private
->CurrentFvFileHandles
[Index2
];
148 Private
->CurrentFvFileHandles
[Index2
] = NULL
;
154 //Index the end of array contains re-range Pei moudle.
156 TempFileHandles
[Index
] = NULL
;
159 // Private->CurrentFvFileHandles is currently in PEIM in the FV order.
160 // We need to update it to start with files in the A Priori list and
161 // then the remaining files in PEIM order.
163 CopyMem (Private
->CurrentFvFileHandles
, TempFileHandles
, sizeof (Private
->CurrentFvFileHandles
));
167 // Cache the current Fv File Handle. So that we don't have to scan the Fv again.
168 // Instead, we can retrieve the file handles within this Fv from cachable data.
170 Private
->Fv
[Private
->CurrentPeimFvCount
].ScanFv
= TRUE
;
171 CopyMem (Private
->Fv
[Private
->CurrentPeimFvCount
].FvFileHandles
, Private
->CurrentFvFileHandles
, sizeof (Private
->CurrentFvFileHandles
));
176 Shadow PeiCore module from flash to installed memory.
178 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
179 @param PrivateInMem PeiCore's private data structure
181 @return PeiCore function address after shadowing.
185 EFI_PEI_SERVICES
**PeiServices
,
186 PEI_CORE_INSTANCE
*PrivateInMem
189 EFI_PEI_FILE_HANDLE PeiCoreFileHandle
;
190 EFI_PHYSICAL_ADDRESS EntryPoint
;
192 UINT32 AuthenticationState
;
194 PeiCoreFileHandle
= NULL
;
197 // Find the PEI Core in the BFV
199 Status
= PeiFindFileEx (
200 (EFI_PEI_FV_HANDLE
)PrivateInMem
->Fv
[0].FvHeader
,
202 EFI_FV_FILETYPE_PEI_CORE
,
206 ASSERT_EFI_ERROR (Status
);
209 // Shadow PEI Core into memory so it will run faster
211 Status
= PeiLoadImage (
213 *((EFI_PEI_FILE_HANDLE
*)&PeiCoreFileHandle
),
217 ASSERT_EFI_ERROR (Status
);
220 // Compute the PeiCore's function address after shaowed PeiCore.
221 // _ModuleEntryPoint is PeiCore main function entry
223 return (VOID
*) ((UINTN
) EntryPoint
+ (UINTN
) PeiCore
- (UINTN
) _ModuleEntryPoint
);
227 Conduct PEIM dispatch.
229 @param SecCoreData Points to a data structure containing information about the PEI core's operating
230 environment, such as the size and location of temporary RAM, the stack location and
232 @param Private Pointer to the private data passed in from caller
234 @retval EFI_SUCCESS - Successfully dispatched PEIM.
235 @retval EFI_NOT_FOUND - The dispatch failed.
240 IN CONST EFI_SEC_PEI_HAND_OFF
*SecCoreData
,
241 IN PEI_CORE_INSTANCE
*Private
247 EFI_PEI_SERVICES
**PeiServices
;
248 EFI_PEI_FV_HANDLE VolumeHandle
;
249 EFI_PEI_FILE_HANDLE PeimFileHandle
;
252 UINT32 AuthenticationState
;
253 EFI_PHYSICAL_ADDRESS EntryPoint
;
254 EFI_PEIM_ENTRY_POINT2 PeimEntryPoint
;
255 UINTN SaveCurrentPeimCount
;
256 UINTN SaveCurrentFvCount
;
257 EFI_PEI_FILE_HANDLE SaveCurrentFileHandle
;
258 PEIM_FILE_HANDLE_EXTENDED_DATA ExtendedData
;
259 EFI_PHYSICAL_ADDRESS NewPermenentMemoryBase
;
260 TEMPORARY_RAM_SUPPORT_PPI
*TemporaryRamSupportPpi
;
261 EFI_HOB_HANDOFF_INFO_TABLE
*OldHandOffTable
;
262 EFI_HOB_HANDOFF_INFO_TABLE
*NewHandOffTable
;
265 PEI_CORE_INSTANCE
*PrivateInMem
;
266 UINT64 NewPeiStackSize
;
267 UINT64 OldPeiStackSize
;
269 EFI_FV_FILE_INFO FvFileInfo
;
270 UINTN OldCheckingTop
;
271 UINTN OldCheckingBottom
;
274 PeiServices
= &Private
->PS
;
275 PeimEntryPoint
= NULL
;
276 PeimFileHandle
= NULL
;
279 if ((Private
->PeiMemoryInstalled
) && (Private
->HobList
.HandoffInformationTable
->BootMode
!= BOOT_ON_S3_RESUME
)) {
281 // Once real memory is available, shadow the RegisterForShadow modules. And meanwhile
282 // update the modules' status from PEIM_STATE_REGISITER_FOR_SHADOW to PEIM_STATE_DONE.
284 SaveCurrentPeimCount
= Private
->CurrentPeimCount
;
285 SaveCurrentFvCount
= Private
->CurrentPeimFvCount
;
286 SaveCurrentFileHandle
= Private
->CurrentFileHandle
;
288 for (Index1
= 0; Index1
<= SaveCurrentFvCount
; Index1
++) {
289 for (Index2
= 0; (Index2
< FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv
)) && (Private
->Fv
[Index1
].FvFileHandles
[Index2
] != NULL
); Index2
++) {
290 if (Private
->Fv
[Index1
].PeimState
[Index2
] == PEIM_STATE_REGISITER_FOR_SHADOW
) {
291 PeimFileHandle
= Private
->Fv
[Index1
].FvFileHandles
[Index2
];
292 Status
= PeiLoadImage (
298 if (Status
== EFI_SUCCESS
) {
300 // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE
302 Private
->Fv
[Index1
].PeimState
[Index2
]++;
303 Private
->CurrentFileHandle
= PeimFileHandle
;
304 Private
->CurrentPeimFvCount
= Index1
;
305 Private
->CurrentPeimCount
= Index2
;
307 // Call the PEIM entry point
309 PeimEntryPoint
= (EFI_PEIM_ENTRY_POINT2
)(UINTN
)EntryPoint
;
311 PERF_START (0, "PEIM", NULL
, 0);
312 PeimEntryPoint(PeimFileHandle
, (const EFI_PEI_SERVICES
**) &Private
->PS
);
313 PERF_END (0, "PEIM", NULL
, 0);
317 // Process the Notify list and dispatch any notifies for
318 // newly installed PPIs.
320 ProcessNotifyList (Private
);
324 Private
->CurrentFileHandle
= SaveCurrentFileHandle
;
325 Private
->CurrentPeimFvCount
= SaveCurrentFvCount
;
326 Private
->CurrentPeimCount
= SaveCurrentPeimCount
;
330 // This is the main dispatch loop. It will search known FVs for PEIMs and
331 // attempt to dispatch them. If any PEIM gets dispatched through a single
332 // pass of the dispatcher, it will start over from the Bfv again to see
333 // if any new PEIMs dependencies got satisfied. With a well ordered
334 // FV where PEIMs are found in the order their dependencies are also
335 // satisfied, this dipatcher should run only once.
339 // In case that reenter PeiCore happens, the last pass record is still available.
341 if (!Private
->PeimDispatcherReenter
) {
342 Private
->PeimNeedingDispatch
= FALSE
;
343 Private
->PeimDispatchOnThisPass
= FALSE
;
345 Private
->PeimDispatcherReenter
= FALSE
;
348 for (FvCount
= Private
->CurrentPeimFvCount
; FvCount
< Private
->FvCount
; FvCount
++) {
349 Private
->CurrentPeimFvCount
= FvCount
;
351 // Get this Fv Handle by PeiService FvFindNextVolume.
353 PeiFvFindNextVolume ((CONST EFI_PEI_SERVICES
**) PeiServices
, FvCount
, &VolumeHandle
);
355 if (Private
->CurrentPeimCount
== 0) {
357 // When going through each FV, at first, search Apriori file to
358 // reorder all PEIMs to ensure the PEIMs in Apriori file to get
359 // dispatch at first.
361 DiscoverPeimsAndOrderWithApriori (Private
, VolumeHandle
);
365 // Start to dispatch all modules within the current Fv.
367 for (PeimCount
= Private
->CurrentPeimCount
;
368 (PeimCount
< FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv
)) && (Private
->CurrentFvFileHandles
[PeimCount
] != NULL
);
370 Private
->CurrentPeimCount
= PeimCount
;
371 PeimFileHandle
= Private
->CurrentFileHandle
= Private
->CurrentFvFileHandles
[PeimCount
];
373 if (Private
->Fv
[FvCount
].PeimState
[PeimCount
] == PEIM_STATE_NOT_DISPATCHED
) {
374 if (!DepexSatisfied (Private
, PeimFileHandle
, PeimCount
)) {
375 Private
->PeimNeedingDispatch
= TRUE
;
377 Status
= PeiFfsGetFileInfo (PeimFileHandle
, &FvFileInfo
);
378 ASSERT_EFI_ERROR (Status
);
379 if (FvFileInfo
.FileType
== EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
) {
381 // For Fv type file, Produce new FV PPI and FV hob
383 Status
= ProcessFvFile (PeiServices
, PeimFileHandle
, &AuthenticationState
);
386 // For PEIM driver, Load its entry point
388 Status
= PeiLoadImage (
396 if ((Status
== EFI_SUCCESS
)) {
398 // The PEIM has its dependencies satisfied, and its entry point
399 // has been found, so invoke it.
401 PERF_START (0, "PEIM", NULL
, 0);
403 ExtendedData
.Handle
= (EFI_HANDLE
)PeimFileHandle
;
405 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
407 FixedPcdGet32(PcdStatusCodeValuePeimDispatch
),
408 (VOID
*)(&ExtendedData
),
409 sizeof (ExtendedData
)
412 Status
= VerifyPeim (Private
, VolumeHandle
, PeimFileHandle
);
413 if (Status
!= EFI_SECURITY_VIOLATION
&& (AuthenticationState
== 0)) {
415 // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED
417 Private
->Fv
[FvCount
].PeimState
[PeimCount
]++;
419 if (FvFileInfo
.FileType
!= EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
) {
421 // Call the PEIM entry point for PEIM driver
423 PeimEntryPoint
= (EFI_PEIM_ENTRY_POINT2
)(UINTN
)EntryPoint
;
424 PeimEntryPoint (PeimFileHandle
, (const EFI_PEI_SERVICES
**) PeiServices
);
427 Private
->PeimDispatchOnThisPass
= TRUE
;
430 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
432 FixedPcdGet32(PcdStatusCodeValuePeimDispatch
),
433 (VOID
*)(&ExtendedData
),
434 sizeof (ExtendedData
)
436 PERF_END (0, "PEIM", NULL
, 0);
440 if (Private
->SwitchStackSignal
) {
442 // Before switch stack from CAR to permenent memory, caculate the heap and stack
443 // usage in temporary memory for debuging.
446 UINT32
*StackPointer
;
448 for (StackPointer
= (UINT32
*)SecCoreData
->StackBase
;
449 (StackPointer
< (UINT32
*)((UINTN
)SecCoreData
->StackBase
+ SecCoreData
->StackSize
)) \
450 && (*StackPointer
== INIT_CAR_VALUE
);
453 DEBUG ((EFI_D_INFO
, "Total Cache as RAM: %d bytes.\n", SecCoreData
->TemporaryRamSize
));
454 DEBUG ((EFI_D_INFO
, " CAR stack ever used: %d bytes.\n",
455 (SecCoreData
->StackSize
- ((UINTN
) StackPointer
- (UINTN
)SecCoreData
->StackBase
))
457 DEBUG ((EFI_D_INFO
, " CAR heap used: %d bytes.\n",
458 ((UINTN
) Private
->HobList
.HandoffInformationTable
->EfiFreeMemoryBottom
-
459 (UINTN
) Private
->HobList
.Raw
)
464 // Reserve the size of new stack at bottom of physical memory
466 OldPeiStackSize
= Private
->StackSize
;
467 NewPeiStackSize
= (RShiftU64 (Private
->PhysicalMemoryLength
, 1) + EFI_PAGE_MASK
) & ~EFI_PAGE_MASK
;
468 if (FixedPcdGet32(PcdPeiCoreMaxPeiStackSize
) > (UINT32
) NewPeiStackSize
) {
469 Private
->StackSize
= NewPeiStackSize
;
471 Private
->StackSize
= FixedPcdGet32(PcdPeiCoreMaxPeiStackSize
);
475 // In theory, the size of new stack in permenent memory should large than
476 // size of old stack in temporary memory.
477 // But if new stack is smaller than the size of old stack, we also reserve
478 // the size of old stack at bottom of permenent memory.
481 if (Private
->StackSize
> OldPeiStackSize
) {
482 StackGap
= Private
->StackSize
- OldPeiStackSize
;
486 // Update HandOffHob for new installed permenent memory
488 OldHandOffTable
= Private
->HobList
.HandoffInformationTable
;
489 OldCheckingBottom
= (UINTN
)(SecCoreData
->TemporaryRamBase
);
490 OldCheckingTop
= (UINTN
)(OldCheckingBottom
+ SecCoreData
->TemporaryRamSize
);
493 // The whole temporary memory will be migrated to physical memory.
494 // CAUTION: The new base is computed accounding to gap of new stack.
496 NewPermenentMemoryBase
= Private
->PhysicalMemoryBegin
+ StackGap
;
499 // Caculate stack offset and heap offset between CAR and new permement
500 // memory seperately.
502 StackOffset
= (UINTN
) NewPermenentMemoryBase
- (UINTN
) SecCoreData
->StackBase
;
503 HeapOffset
= (INTN
) ((UINTN
) Private
->PhysicalMemoryBegin
+ Private
->StackSize
- \
504 (UINTN
) SecCoreData
->PeiTemporaryRamBase
);
505 DEBUG ((EFI_D_INFO
, "Heap Offset = 0x%X Stack Offset = 0x%X\n", HeapOffset
, StackOffset
));
508 // Caculate new HandOffTable and PrivateData address in permenet memory's stack
510 NewHandOffTable
= (EFI_HOB_HANDOFF_INFO_TABLE
*)((UINTN
)OldHandOffTable
+ HeapOffset
);
511 PrivateInMem
= (PEI_CORE_INSTANCE
*)((UINTN
) (VOID
*) Private
+ StackOffset
);
514 // TemporaryRamSupportPpi is produced by platform's SEC
516 Status
= PeiLocatePpi (
517 (CONST EFI_PEI_SERVICES
**) PeiServices
,
518 &gEfiTemporaryRamSupportPpiGuid
,
521 (VOID
**)&TemporaryRamSupportPpi
525 if (!EFI_ERROR (Status
)) {
527 // Temporary Ram support Ppi is provided by platform, it will copy
528 // temporary memory to permenent memory and do stack switching.
529 // After invoken temporary Ram support, following code's stack is in
530 // memory but not in CAR.
532 TemporaryRamSupportPpi
->TemporaryRamMigration (
533 (CONST EFI_PEI_SERVICES
**) PeiServices
,
534 (EFI_PHYSICAL_ADDRESS
)(UINTN
) SecCoreData
->TemporaryRamBase
,
535 (EFI_PHYSICAL_ADDRESS
)(UINTN
) NewPermenentMemoryBase
,
536 SecCoreData
->TemporaryRamSize
541 // In IA32/x64/Itanium architecture, we need platform provide
542 // TEMPORAY_RAM_MIGRATION_PPI.
550 // Fixup the PeiCore's private data
552 PrivateInMem
->PS
= &PrivateInMem
->ServiceTableShadow
;
553 PrivateInMem
->CpuIo
= &PrivateInMem
->ServiceTableShadow
.CpuIo
;
554 PrivateInMem
->HobList
.Raw
= (VOID
*) ((UINTN
) PrivateInMem
->HobList
.Raw
+ HeapOffset
);
555 PrivateInMem
->StackBase
= (EFI_PHYSICAL_ADDRESS
)(((UINTN
)PrivateInMem
->PhysicalMemoryBegin
+ EFI_PAGE_MASK
) & ~EFI_PAGE_MASK
);
557 PeiServices
= &PrivateInMem
->PS
;
560 // Fixup for PeiService's address
562 SetPeiServicesTablePointer(PeiServices
);
565 // Update HandOffHob for new installed permenent memory
567 NewHandOffTable
->EfiEndOfHobList
=
568 (EFI_PHYSICAL_ADDRESS
)((UINTN
) NewHandOffTable
->EfiEndOfHobList
+ HeapOffset
);
569 NewHandOffTable
->EfiMemoryTop
= PrivateInMem
->PhysicalMemoryBegin
+
570 PrivateInMem
->PhysicalMemoryLength
;
571 NewHandOffTable
->EfiMemoryBottom
= PrivateInMem
->PhysicalMemoryBegin
;
572 NewHandOffTable
->EfiFreeMemoryTop
= PrivateInMem
->FreePhysicalMemoryTop
;
573 NewHandOffTable
->EfiFreeMemoryBottom
= NewHandOffTable
->EfiEndOfHobList
+
574 sizeof (EFI_HOB_GENERIC_HEADER
);
577 // We need convert the PPI desciptor's pointer
579 ConvertPpiPointers (PrivateInMem
,
585 DEBUG ((EFI_D_INFO
, "Stack Hob: BaseAddress=0x%X Length=0x%X\n",
586 (UINTN
)PrivateInMem
->StackBase
,
587 PrivateInMem
->StackSize
));
588 BuildStackHob (PrivateInMem
->StackBase
, PrivateInMem
->StackSize
);
591 // After the whole temporary memory is migrated, then we can allocate page in
594 PrivateInMem
->PeiMemoryInstalled
= TRUE
;
597 // Indicate that PeiCore reenter
599 PrivateInMem
->PeimDispatcherReenter
= TRUE
;
602 // Shadow PEI Core. When permanent memory is avaiable, shadow
603 // PEI Core and PEIMs to get high performance.
605 PrivateInMem
->ShadowedPeiCore
= ShadowPeiCore (
610 // Process the Notify list and dispatch any notifies for
611 // newly installed PPIs.
613 ProcessNotifyList (PrivateInMem
);
618 PeiCore (SecCoreData
, NULL
, PrivateInMem
);
621 // Code should not come here
623 ASSERT_EFI_ERROR(FALSE
);
627 // Process the Notify list and dispatch any notifies for
628 // newly installed PPIs.
630 ProcessNotifyList (Private
);
632 if ((Private
->PeiMemoryInstalled
) && (Private
->Fv
[FvCount
].PeimState
[PeimCount
] == PEIM_STATE_REGISITER_FOR_SHADOW
) && \
633 (Private
->HobList
.HandoffInformationTable
->BootMode
!= BOOT_ON_S3_RESUME
)) {
635 // If memory is availble we shadow images by default for performance reasons.
636 // We call the entry point a 2nd time so the module knows it's shadowed.
638 //PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0);
639 PeimEntryPoint (PeimFileHandle
, (const EFI_PEI_SERVICES
**) PeiServices
);
640 //PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0);
643 // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE
645 Private
->Fv
[FvCount
].PeimState
[PeimCount
]++;
648 // Process the Notify list and dispatch any notifies for
649 // newly installed PPIs.
651 ProcessNotifyList (Private
);
658 // We set to NULL here to optimize the 2nd entry to this routine after
659 // memory is found. This reprevents rescanning of the FV. We set to
660 // NULL here so we start at the begining of the next FV
662 Private
->CurrentFileHandle
= NULL
;
663 Private
->CurrentPeimCount
= 0;
665 // Before walking through the next FV,Private->CurrentFvFileHandles[]should set to NULL
667 SetMem (Private
->CurrentFvFileHandles
, sizeof (Private
->CurrentFvFileHandles
), 0);
671 // Before making another pass, we should set Private->CurrentPeimFvCount =0 to go
672 // through all the FV.
674 Private
->CurrentPeimFvCount
= 0;
677 // PeimNeedingDispatch being TRUE means we found a PEIM that did not get
678 // dispatched. So we need to make another pass
680 // PeimDispatchOnThisPass being TRUE means we dispatched a PEIM on this
681 // pass. If we did not dispatch a PEIM there is no point in trying again
682 // as it will fail the next time too (nothing has changed).
684 } while (Private
->PeimNeedingDispatch
&& Private
->PeimDispatchOnThisPass
);
689 Initialize the Dispatcher's data members
691 @param PrivateData PeiCore's private data structure
692 @param OldCoreData Old data from SecCore
693 NULL if being run in non-permament memory mode.
694 @param SecCoreData Points to a data structure containing information about the PEI core's operating
695 environment, such as the size and location of temporary RAM, the stack location and
702 InitializeDispatcherData (
703 IN PEI_CORE_INSTANCE
*PrivateData
,
704 IN PEI_CORE_INSTANCE
*OldCoreData
,
705 IN CONST EFI_SEC_PEI_HAND_OFF
*SecCoreData
708 if (OldCoreData
== NULL
) {
709 PrivateData
->PeimDispatcherReenter
= FALSE
;
710 PeiInitializeFv (PrivateData
, SecCoreData
);
717 This routine parses the Dependency Expression, if available, and
718 decides if the module can be executed.
721 @param Private PeiCore's private data structure
722 @param FileHandle PEIM's file handle
723 @param PeimCount Peim count in all dispatched PEIMs.
725 @retval TRUE Can be dispatched
726 @retval FALSE Cannot be dispatched
731 IN PEI_CORE_INSTANCE
*Private
,
732 IN EFI_PEI_FILE_HANDLE FileHandle
,
739 if (PeimCount
< Private
->AprioriCount
) {
741 // If its in the A priori file then we set Depex to TRUE
747 // Depex section not in the encapsulated section.
749 Status
= PeiServicesFfsFindSectionData (
750 EFI_SECTION_PEI_DEPEX
,
755 if (EFI_ERROR (Status
)) {
757 // If there is no DEPEX, assume the module can be executed
763 // Evaluate a given DEPEX
765 return PeimDispatchReadiness (&Private
->PS
, DepexData
);
769 This routine enable a PEIM to register itself to shadow when PEI Foundation
770 discovery permanent memory.
772 @param FileHandle File handle of a PEIM.
774 @retval EFI_NOT_FOUND The file handle doesn't point to PEIM itself.
775 @retval EFI_ALREADY_STARTED Indicate that the PEIM has been registered itself.
776 @retval EFI_SUCCESS Successfully to register itself.
781 PeiRegisterForShadow (
782 IN EFI_PEI_FILE_HANDLE FileHandle
785 PEI_CORE_INSTANCE
*Private
;
786 Private
= PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());
788 if (Private
->CurrentFileHandle
!= FileHandle
) {
790 // The FileHandle must be for the current PEIM
792 return EFI_NOT_FOUND
;
795 if (Private
->Fv
[Private
->CurrentPeimFvCount
].PeimState
[Private
->CurrentPeimCount
] >= PEIM_STATE_REGISITER_FOR_SHADOW
) {
797 // If the PEIM has already entered the PEIM_STATE_REGISTER_FOR_SHADOW or PEIM_STATE_DONE then it's already been started
799 return EFI_ALREADY_STARTED
;
802 Private
->Fv
[Private
->CurrentPeimFvCount
].PeimState
[Private
->CurrentPeimCount
] = PEIM_STATE_REGISITER_FOR_SHADOW
;
808 Get Fv image from the FV type file, then install FV INFO ppi, Build FV hob.
810 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
811 @param FvFileHandle File handle of a Fv type file.
812 @param AuthenticationState Pointer to attestation authentication state of image.
815 @retval EFI_NOT_FOUND FV image can't be found.
816 @retval EFI_SUCCESS Successfully to process it.
817 @retval EFI_OUT_OF_RESOURCES Can not allocate page when aligning FV image
818 @retval Others Can not find EFI_SECTION_FIRMWARE_VOLUME_IMAGE section
823 IN EFI_PEI_SERVICES
**PeiServices
,
824 IN EFI_PEI_FILE_HANDLE FvFileHandle
,
825 OUT UINT32
*AuthenticationState
829 EFI_PEI_FV_HANDLE FvImageHandle
;
830 EFI_FV_INFO FvImageInfo
;
833 EFI_PEI_HOB_POINTERS HobPtr
;
836 *AuthenticationState
= 0;
839 // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already
842 HobPtr
.Raw
= GetHobList ();
843 while ((HobPtr
.Raw
= GetNextHob (EFI_HOB_TYPE_FV2
, HobPtr
.Raw
)) != NULL
) {
844 if (CompareGuid (&(((EFI_FFS_FILE_HEADER
*)FvFileHandle
)->Name
), &HobPtr
.FirmwareVolume2
->FileName
)) {
846 // this FILE has been dispatched, it will not be dispatched again.
850 HobPtr
.Raw
= GET_NEXT_HOB (HobPtr
);
854 // Find FvImage in FvFile
856 Status
= PeiFfsFindSectionData (
857 (CONST EFI_PEI_SERVICES
**) PeiServices
,
858 EFI_SECTION_FIRMWARE_VOLUME_IMAGE
,
860 (VOID
**)&FvImageHandle
863 if (EFI_ERROR (Status
)) {
868 // Collect FvImage Info.
870 Status
= PeiFfsGetVolumeInfo (FvImageHandle
, &FvImageInfo
);
871 ASSERT_EFI_ERROR (Status
);
874 // FvAlignment must be more than 8 bytes required by FvHeader structure.
876 FvAlignment
= 1 << ((FvImageInfo
.FvAttributes
& EFI_FVB2_ALIGNMENT
) >> 16);
877 if (FvAlignment
< 8) {
884 if ((UINTN
) FvImageInfo
.FvStart
% FvAlignment
!= 0) {
885 FvBuffer
= AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINT32
) FvImageInfo
.FvSize
), FvAlignment
);
886 if (FvBuffer
== NULL
) {
887 return EFI_OUT_OF_RESOURCES
;
889 CopyMem (FvBuffer
, FvImageInfo
.FvStart
, (UINTN
) FvImageInfo
.FvSize
);
891 // Update FvImageInfo after reload FvImage to new aligned memory
893 PeiFfsGetVolumeInfo ((EFI_PEI_FV_HANDLE
) FvBuffer
, &FvImageInfo
);
897 // Install FvPpi and Build FvHob
899 PiLibInstallFvInfoPpi (
902 (UINT32
) FvImageInfo
.FvSize
,
903 &(FvImageInfo
.FvName
),
904 &(((EFI_FFS_FILE_HEADER
*)FvFileHandle
)->Name
)
908 // Inform the extracted FvImage to Fv HOB consumer phase, i.e. DXE phase
909 // based on its parent Fvimage is informed or not.
910 // If FvHob of its parent fvimage is built, the extracted FvImage will be built also.
911 // Or, the extracted FvImage will not be built.
913 HobPtr
.Raw
= GetHobList ();
914 while ((HobPtr
.Raw
= GetNextHob (EFI_HOB_TYPE_FV
, HobPtr
.Raw
)) != NULL
) {
915 if (((EFI_PHYSICAL_ADDRESS
) (UINTN
)FvFileHandle
> HobPtr
.FirmwareVolume
->BaseAddress
) &&
916 ((EFI_PHYSICAL_ADDRESS
) (UINTN
)FvFileHandle
< HobPtr
.FirmwareVolume
->BaseAddress
+ HobPtr
.FirmwareVolume
->Length
)) {
918 (EFI_PHYSICAL_ADDRESS
) (UINTN
) FvImageInfo
.FvStart
,
923 HobPtr
.Raw
= GET_NEXT_HOB (HobPtr
);
927 // Makes the encapsulated volume show up in DXE phase to skip processing of
928 // encapsulated file again.
931 (EFI_PHYSICAL_ADDRESS
) (UINTN
) FvImageInfo
.FvStart
,
934 &(((EFI_FFS_FILE_HEADER
*)FvFileHandle
)->Name
)