2 EFI PEI Core dispatch services
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
14 Discover all Peims and optional Apriori file in one FV. There is at most one
15 Apriori file in one FV.
18 @param Private Pointer to the private data passed in from caller
19 @param CoreFileHandle The instance of PEI_CORE_FV_HANDLE.
23 DiscoverPeimsAndOrderWithApriori (
24 IN PEI_CORE_INSTANCE
*Private
,
25 IN PEI_CORE_FV_HANDLE
*CoreFileHandle
29 EFI_PEI_FILE_HANDLE FileHandle
;
30 EFI_PEI_FILE_HANDLE AprioriFileHandle
;
37 EFI_PEI_FILE_HANDLE
*TempFileHandles
;
38 EFI_GUID
*TempFileGuid
;
39 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
40 EFI_FV_FILE_INFO FileInfo
;
42 FvPpi
= CoreFileHandle
->FvPpi
;
45 // Walk the FV and find all the PEIMs and the Apriori file.
47 AprioriFileHandle
= NULL
;
48 Private
->CurrentFvFileHandles
= NULL
;
52 // If the current Fv has been scanned, directly get its cached records.
54 if (CoreFileHandle
->ScanFv
) {
55 Private
->CurrentFvFileHandles
= CoreFileHandle
->FvFileHandles
;
59 TempFileHandles
= Private
->TempFileHandles
;
60 TempFileGuid
= Private
->TempFileGuid
;
63 // Go ahead to scan this Fv, get PeimCount and cache FileHandles within it to TempFileHandles.
68 Status
= FvPpi
->FindFileByType (FvPpi
, PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE
, CoreFileHandle
->FvHandle
, &FileHandle
);
69 if (!EFI_ERROR (Status
)) {
70 if (PeimCount
>= Private
->TempPeimCount
) {
72 // Run out of room, grow the buffer.
74 TempFileHandles
= AllocatePool (
75 sizeof (EFI_PEI_FILE_HANDLE
) * (Private
->TempPeimCount
+ TEMP_FILE_GROWTH_STEP
));
76 ASSERT (TempFileHandles
!= NULL
);
79 Private
->TempFileHandles
,
80 sizeof (EFI_PEI_FILE_HANDLE
) * Private
->TempPeimCount
82 Private
->TempFileHandles
= TempFileHandles
;
83 TempFileGuid
= AllocatePool (
84 sizeof (EFI_GUID
) * (Private
->TempPeimCount
+ TEMP_FILE_GROWTH_STEP
));
85 ASSERT (TempFileGuid
!= NULL
);
88 Private
->TempFileGuid
,
89 sizeof (EFI_GUID
) * Private
->TempPeimCount
91 Private
->TempFileGuid
= TempFileGuid
;
92 Private
->TempPeimCount
= Private
->TempPeimCount
+ TEMP_FILE_GROWTH_STEP
;
95 TempFileHandles
[PeimCount
++] = FileHandle
;
97 } while (!EFI_ERROR (Status
));
101 "%a(): Found 0x%x PEI FFS files in the %dth FV\n",
104 Private
->CurrentPeimFvCount
107 if (PeimCount
== 0) {
109 // No PEIM FFS file is found, set ScanFv flag and return.
111 CoreFileHandle
->ScanFv
= TRUE
;
116 // Record PeimCount, allocate buffer for PeimState and FvFileHandles.
118 CoreFileHandle
->PeimCount
= PeimCount
;
119 CoreFileHandle
->PeimState
= AllocateZeroPool (sizeof (UINT8
) * PeimCount
);
120 ASSERT (CoreFileHandle
->PeimState
!= NULL
);
121 CoreFileHandle
->FvFileHandles
= AllocateZeroPool (sizeof (EFI_PEI_FILE_HANDLE
) * PeimCount
);
122 ASSERT (CoreFileHandle
->FvFileHandles
!= NULL
);
125 // Get Apriori File handle
127 Private
->AprioriCount
= 0;
128 Status
= FvPpi
->FindFileByName (FvPpi
, &gPeiAprioriFileNameGuid
, &CoreFileHandle
->FvHandle
, &AprioriFileHandle
);
129 if (!EFI_ERROR(Status
) && AprioriFileHandle
!= NULL
) {
131 // Read the Apriori file
133 Status
= FvPpi
->FindSectionByType (FvPpi
, EFI_SECTION_RAW
, AprioriFileHandle
, (VOID
**) &Apriori
);
134 if (!EFI_ERROR (Status
)) {
136 // Calculate the number of PEIMs in the Apriori file
138 Status
= FvPpi
->GetFileInfo (FvPpi
, AprioriFileHandle
, &FileInfo
);
139 ASSERT_EFI_ERROR (Status
);
140 Private
->AprioriCount
= FileInfo
.BufferSize
;
141 if (IS_SECTION2 (FileInfo
.Buffer
)) {
142 Private
->AprioriCount
-= sizeof (EFI_COMMON_SECTION_HEADER2
);
144 Private
->AprioriCount
-= sizeof (EFI_COMMON_SECTION_HEADER
);
146 Private
->AprioriCount
/= sizeof (EFI_GUID
);
148 for (Index
= 0; Index
< PeimCount
; Index
++) {
150 // Make an array of file name guids that matches the FileHandle array so we can convert
151 // quickly from file name to file handle
153 Status
= FvPpi
->GetFileInfo (FvPpi
, TempFileHandles
[Index
], &FileInfo
);
154 ASSERT_EFI_ERROR (Status
);
155 CopyMem (&TempFileGuid
[Index
], &FileInfo
.FileName
, sizeof(EFI_GUID
));
159 // Walk through TempFileGuid array to find out who is invalid PEIM guid in Apriori file.
160 // Add available PEIMs in Apriori file into FvFileHandles array.
163 for (Index2
= 0; Index2
< Private
->AprioriCount
; Index2
++) {
164 Guid
= ScanGuid (TempFileGuid
, PeimCount
* sizeof (EFI_GUID
), &Apriori
[Index2
]);
166 PeimIndex
= ((UINTN
)Guid
- (UINTN
)&TempFileGuid
[0])/sizeof (EFI_GUID
);
167 CoreFileHandle
->FvFileHandles
[Index
++] = TempFileHandles
[PeimIndex
];
170 // Since we have copied the file handle we can remove it from this list.
172 TempFileHandles
[PeimIndex
] = NULL
;
177 // Update valid AprioriCount
179 Private
->AprioriCount
= Index
;
182 // Add in any PEIMs not in the Apriori file
184 for (Index2
= 0; Index2
< PeimCount
; Index2
++) {
185 if (TempFileHandles
[Index2
] != NULL
) {
186 CoreFileHandle
->FvFileHandles
[Index
++] = TempFileHandles
[Index2
];
187 TempFileHandles
[Index2
] = NULL
;
190 ASSERT (Index
== PeimCount
);
193 CopyMem (CoreFileHandle
->FvFileHandles
, TempFileHandles
, sizeof (EFI_PEI_FILE_HANDLE
) * PeimCount
);
197 // The current Fv File Handles have been cached. So that we don't have to scan the Fv again.
198 // Instead, we can retrieve the file handles within this Fv from cached records.
200 CoreFileHandle
->ScanFv
= TRUE
;
201 Private
->CurrentFvFileHandles
= CoreFileHandle
->FvFileHandles
;
205 // This is the minimum memory required by DxeCore initialization. When LMFA feature enabled,
206 // This part of memory still need reserved on the very top of memory so that the DXE Core could
207 // use these memory for data initialization. This macro should be sync with the same marco
208 // defined in DXE Core.
210 #define MINIMUM_INITIAL_MEMORY_SIZE 0x10000
212 This function is to test if the memory range described in resource HOB is available or not.
214 This function should only be invoked when Loading Module at Fixed Address(LMFA) feature is enabled. Some platform may allocate the
215 memory before PeiLoadFixAddressHook in invoked. so this function is to test if the memory range described by the input resource HOB is
218 @param PrivateData Pointer to the private data passed in from caller
219 @param ResourceHob Pointer to a resource HOB which described the memory range described by the input resource HOB
222 PeiLoadFixAddressIsMemoryRangeAvailable (
223 IN PEI_CORE_INSTANCE
*PrivateData
,
224 IN EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
227 EFI_HOB_MEMORY_ALLOCATION
*MemoryHob
;
229 EFI_PEI_HOB_POINTERS Hob
;
232 if (PrivateData
== NULL
|| ResourceHob
== NULL
) {
236 // test if the memory range describe in the HOB is already allocated.
238 for (Hob
.Raw
= PrivateData
->HobList
.Raw
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
240 // See if this is a memory allocation HOB
242 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_MEMORY_ALLOCATION
) {
243 MemoryHob
= Hob
.MemoryAllocation
;
244 if(MemoryHob
->AllocDescriptor
.MemoryBaseAddress
== ResourceHob
->PhysicalStart
&&
245 MemoryHob
->AllocDescriptor
.MemoryBaseAddress
+ MemoryHob
->AllocDescriptor
.MemoryLength
== ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
) {
256 Hook function for Loading Module at Fixed Address feature
258 This function should only be invoked when Loading Module at Fixed Address(LMFA) feature is enabled. When feature is
259 configured as Load Modules at Fix Absolute Address, this function is to validate the top address assigned by user. When
260 feature is configured as Load Modules at Fixed Offset, the functino is to find the top address which is TOLM-TSEG in general.
261 And also the function will re-install PEI memory.
263 @param PrivateData Pointer to the private data passed in from caller
267 PeiLoadFixAddressHook(
268 IN PEI_CORE_INSTANCE
*PrivateData
271 EFI_PHYSICAL_ADDRESS TopLoadingAddress
;
272 UINT64 PeiMemorySize
;
273 UINT64 TotalReservedMemorySize
;
274 UINT64 MemoryRangeEnd
;
275 EFI_PHYSICAL_ADDRESS HighAddress
;
276 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
277 EFI_HOB_RESOURCE_DESCRIPTOR
*NextResourceHob
;
278 EFI_HOB_RESOURCE_DESCRIPTOR
*CurrentResourceHob
;
279 EFI_PEI_HOB_POINTERS CurrentHob
;
280 EFI_PEI_HOB_POINTERS Hob
;
281 EFI_PEI_HOB_POINTERS NextHob
;
282 EFI_HOB_MEMORY_ALLOCATION
*MemoryHob
;
284 // Initialize Local Variables
286 CurrentResourceHob
= NULL
;
288 NextResourceHob
= NULL
;
290 TopLoadingAddress
= 0;
292 CurrentHob
.Raw
= PrivateData
->HobList
.Raw
;
293 PeiMemorySize
= PrivateData
->PhysicalMemoryLength
;
295 // The top reserved memory include 3 parts: the topest range is for DXE core initialization with the size MINIMUM_INITIAL_MEMORY_SIZE
296 // then RuntimeCodePage range and Boot time code range.
298 TotalReservedMemorySize
= MINIMUM_INITIAL_MEMORY_SIZE
+ EFI_PAGES_TO_SIZE(PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber
));
299 TotalReservedMemorySize
+= EFI_PAGES_TO_SIZE(PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber
)) ;
301 // PEI memory range lies below the top reserved memory
303 TotalReservedMemorySize
+= PeiMemorySize
;
305 DEBUG ((EFI_D_INFO
, "LOADING MODULE FIXED INFO: PcdLoadFixAddressRuntimeCodePageNumber= 0x%x.\n", PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber
)));
306 DEBUG ((EFI_D_INFO
, "LOADING MODULE FIXED INFO: PcdLoadFixAddressBootTimeCodePageNumber= 0x%x.\n", PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber
)));
307 DEBUG ((EFI_D_INFO
, "LOADING MODULE FIXED INFO: PcdLoadFixAddressPeiCodePageNumber= 0x%x.\n", PcdGet32(PcdLoadFixAddressPeiCodePageNumber
)));
308 DEBUG ((EFI_D_INFO
, "LOADING MODULE FIXED INFO: Total Reserved Memory Size = 0x%lx.\n", TotalReservedMemorySize
));
310 // Loop through the system memory typed hob to merge the adjacent memory range
312 for (Hob
.Raw
= PrivateData
->HobList
.Raw
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
314 // See if this is a resource descriptor HOB
316 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
318 ResourceHob
= Hob
.ResourceDescriptor
;
320 // If range described in this hob is not system memory or heigher than MAX_ADDRESS, ignored.
322 if (ResourceHob
->ResourceType
!= EFI_RESOURCE_SYSTEM_MEMORY
||
323 ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
> MAX_ADDRESS
) {
327 for (NextHob
.Raw
= PrivateData
->HobList
.Raw
; !END_OF_HOB_LIST(NextHob
); NextHob
.Raw
= GET_NEXT_HOB(NextHob
)) {
328 if (NextHob
.Raw
== Hob
.Raw
){
332 // See if this is a resource descriptor HOB
334 if (GET_HOB_TYPE (NextHob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
336 NextResourceHob
= NextHob
.ResourceDescriptor
;
338 // test if range described in this NextResourceHob is system memory and have the same attribute.
339 // Note: Here is a assumption that system memory should always be healthy even without test.
341 if (NextResourceHob
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
&&
342 (((NextResourceHob
->ResourceAttribute
^ResourceHob
->ResourceAttribute
)&(~EFI_RESOURCE_ATTRIBUTE_TESTED
)) == 0)){
345 // See if the memory range described in ResourceHob and NextResourceHob is adjacent
347 if ((ResourceHob
->PhysicalStart
<= NextResourceHob
->PhysicalStart
&&
348 ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
>= NextResourceHob
->PhysicalStart
)||
349 (ResourceHob
->PhysicalStart
>= NextResourceHob
->PhysicalStart
&&
350 ResourceHob
->PhysicalStart
<= NextResourceHob
->PhysicalStart
+ NextResourceHob
->ResourceLength
)) {
352 MemoryRangeEnd
= ((ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
)>(NextResourceHob
->PhysicalStart
+ NextResourceHob
->ResourceLength
)) ?
353 (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
):(NextResourceHob
->PhysicalStart
+ NextResourceHob
->ResourceLength
);
355 ResourceHob
->PhysicalStart
= (ResourceHob
->PhysicalStart
< NextResourceHob
->PhysicalStart
) ?
356 ResourceHob
->PhysicalStart
: NextResourceHob
->PhysicalStart
;
359 ResourceHob
->ResourceLength
= (MemoryRangeEnd
- ResourceHob
->PhysicalStart
);
361 ResourceHob
->ResourceAttribute
= ResourceHob
->ResourceAttribute
& (~EFI_RESOURCE_ATTRIBUTE_TESTED
);
363 // Delete the NextResourceHob by marking it as unused.
365 GET_HOB_TYPE (NextHob
) = EFI_HOB_TYPE_UNUSED
;
374 // Some platform is already allocated pages before the HOB re-org. Here to build dedicated resource HOB to describe
375 // the allocated memory range
377 for (Hob
.Raw
= PrivateData
->HobList
.Raw
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
379 // See if this is a memory allocation HOB
381 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_MEMORY_ALLOCATION
) {
382 MemoryHob
= Hob
.MemoryAllocation
;
383 for (NextHob
.Raw
= PrivateData
->HobList
.Raw
; !END_OF_HOB_LIST(NextHob
); NextHob
.Raw
= GET_NEXT_HOB(NextHob
)) {
385 // See if this is a resource descriptor HOB
387 if (GET_HOB_TYPE (NextHob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
388 NextResourceHob
= NextHob
.ResourceDescriptor
;
390 // If range described in this hob is not system memory or heigher than MAX_ADDRESS, ignored.
392 if (NextResourceHob
->ResourceType
!= EFI_RESOURCE_SYSTEM_MEMORY
|| NextResourceHob
->PhysicalStart
+ NextResourceHob
->ResourceLength
> MAX_ADDRESS
) {
396 // If the range describe in memory allocation HOB belongs to the memroy range described by the resource hob
398 if (MemoryHob
->AllocDescriptor
.MemoryBaseAddress
>= NextResourceHob
->PhysicalStart
&&
399 MemoryHob
->AllocDescriptor
.MemoryBaseAddress
+ MemoryHob
->AllocDescriptor
.MemoryLength
<= NextResourceHob
->PhysicalStart
+ NextResourceHob
->ResourceLength
) {
401 // Build seperate resource hob for this allocated range
403 if (MemoryHob
->AllocDescriptor
.MemoryBaseAddress
> NextResourceHob
->PhysicalStart
) {
404 BuildResourceDescriptorHob (
405 EFI_RESOURCE_SYSTEM_MEMORY
,
406 NextResourceHob
->ResourceAttribute
,
407 NextResourceHob
->PhysicalStart
,
408 (MemoryHob
->AllocDescriptor
.MemoryBaseAddress
- NextResourceHob
->PhysicalStart
)
411 if (MemoryHob
->AllocDescriptor
.MemoryBaseAddress
+ MemoryHob
->AllocDescriptor
.MemoryLength
< NextResourceHob
->PhysicalStart
+ NextResourceHob
->ResourceLength
) {
412 BuildResourceDescriptorHob (
413 EFI_RESOURCE_SYSTEM_MEMORY
,
414 NextResourceHob
->ResourceAttribute
,
415 MemoryHob
->AllocDescriptor
.MemoryBaseAddress
+ MemoryHob
->AllocDescriptor
.MemoryLength
,
416 (NextResourceHob
->PhysicalStart
+ NextResourceHob
->ResourceLength
-(MemoryHob
->AllocDescriptor
.MemoryBaseAddress
+ MemoryHob
->AllocDescriptor
.MemoryLength
))
419 NextResourceHob
->PhysicalStart
= MemoryHob
->AllocDescriptor
.MemoryBaseAddress
;
420 NextResourceHob
->ResourceLength
= MemoryHob
->AllocDescriptor
.MemoryLength
;
429 // Try to find and validate the TOP address.
431 if ((INT64
)PcdGet64(PcdLoadModuleAtFixAddressEnable
) > 0 ) {
433 // The LMFA feature is enabled as load module at fixed absolute address.
435 TopLoadingAddress
= (EFI_PHYSICAL_ADDRESS
)PcdGet64(PcdLoadModuleAtFixAddressEnable
);
436 DEBUG ((EFI_D_INFO
, "LOADING MODULE FIXED INFO: Loading module at fixed absolute address.\n"));
438 // validate the Address. Loop the resource descriptor HOB to make sure the address is in valid memory range
440 if ((TopLoadingAddress
& EFI_PAGE_MASK
) != 0) {
441 DEBUG ((EFI_D_INFO
, "LOADING MODULE FIXED ERROR:Top Address 0x%lx is invalid since top address should be page align. \n", TopLoadingAddress
));
445 // Search for a memory region that is below MAX_ADDRESS and in which TopLoadingAddress lies
447 for (Hob
.Raw
= PrivateData
->HobList
.Raw
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
449 // See if this is a resource descriptor HOB
451 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
453 ResourceHob
= Hob
.ResourceDescriptor
;
455 // See if this resource descrior HOB describes tested system memory below MAX_ADDRESS
457 if (ResourceHob
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
&&
458 ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
<= MAX_ADDRESS
) {
460 // See if Top address specified by user is valid.
462 if (ResourceHob
->PhysicalStart
+ TotalReservedMemorySize
< TopLoadingAddress
&&
463 (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
- MINIMUM_INITIAL_MEMORY_SIZE
) >= TopLoadingAddress
&&
464 PeiLoadFixAddressIsMemoryRangeAvailable(PrivateData
, ResourceHob
)) {
465 CurrentResourceHob
= ResourceHob
;
472 if (CurrentResourceHob
!= NULL
) {
473 DEBUG ((EFI_D_INFO
, "LOADING MODULE FIXED INFO:Top Address 0x%lx is valid \n", TopLoadingAddress
));
474 TopLoadingAddress
+= MINIMUM_INITIAL_MEMORY_SIZE
;
476 DEBUG ((EFI_D_INFO
, "LOADING MODULE FIXED ERROR:Top Address 0x%lx is invalid \n", TopLoadingAddress
));
477 DEBUG ((EFI_D_INFO
, "LOADING MODULE FIXED ERROR:The recommended Top Address for the platform is: \n"));
479 // Print the recomended Top address range.
481 for (Hob
.Raw
= PrivateData
->HobList
.Raw
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
483 // See if this is a resource descriptor HOB
485 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
487 ResourceHob
= Hob
.ResourceDescriptor
;
489 // See if this resource descrior HOB describes tested system memory below MAX_ADDRESS
491 if (ResourceHob
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
&&
492 ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
<= MAX_ADDRESS
) {
494 // See if Top address specified by user is valid.
496 if (ResourceHob
->ResourceLength
> TotalReservedMemorySize
&& PeiLoadFixAddressIsMemoryRangeAvailable(PrivateData
, ResourceHob
)) {
497 DEBUG ((EFI_D_INFO
, "(0x%lx, 0x%lx)\n",
498 (ResourceHob
->PhysicalStart
+ TotalReservedMemorySize
-MINIMUM_INITIAL_MEMORY_SIZE
),
499 (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
-MINIMUM_INITIAL_MEMORY_SIZE
)
513 // The LMFA feature is enabled as load module at fixed offset relative to TOLM
514 // Parse the Hob list to find the topest available memory. Generally it is (TOLM - TSEG)
517 // Search for a tested memory region that is below MAX_ADDRESS
519 for (Hob
.Raw
= PrivateData
->HobList
.Raw
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
521 // See if this is a resource descriptor HOB
523 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
525 ResourceHob
= Hob
.ResourceDescriptor
;
527 // See if this resource descrior HOB describes tested system memory below MAX_ADDRESS
529 if (ResourceHob
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
&&
530 ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
<= MAX_ADDRESS
&&
531 ResourceHob
->ResourceLength
> TotalReservedMemorySize
&& PeiLoadFixAddressIsMemoryRangeAvailable(PrivateData
, ResourceHob
)) {
533 // See if this is the highest largest system memory region below MaxAddress
535 if (ResourceHob
->PhysicalStart
> HighAddress
) {
536 CurrentResourceHob
= ResourceHob
;
538 HighAddress
= CurrentResourceHob
->PhysicalStart
;
543 if (CurrentResourceHob
== NULL
) {
544 DEBUG ((EFI_D_INFO
, "LOADING MODULE FIXED ERROR:The System Memory is too small\n"));
551 TopLoadingAddress
= CurrentResourceHob
->PhysicalStart
+ CurrentResourceHob
->ResourceLength
;
555 if (CurrentResourceHob
!= NULL
) {
557 // rebuild resource HOB for PEI memmory and reserved memory
559 BuildResourceDescriptorHob (
560 EFI_RESOURCE_SYSTEM_MEMORY
,
562 EFI_RESOURCE_ATTRIBUTE_PRESENT
|
563 EFI_RESOURCE_ATTRIBUTE_INITIALIZED
|
564 EFI_RESOURCE_ATTRIBUTE_TESTED
|
565 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE
|
566 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE
|
567 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE
|
568 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
570 (TopLoadingAddress
- TotalReservedMemorySize
),
571 TotalReservedMemorySize
574 // rebuild resource for the remain memory if necessary
576 if (CurrentResourceHob
->PhysicalStart
< TopLoadingAddress
- TotalReservedMemorySize
) {
577 BuildResourceDescriptorHob (
578 EFI_RESOURCE_SYSTEM_MEMORY
,
580 EFI_RESOURCE_ATTRIBUTE_PRESENT
|
581 EFI_RESOURCE_ATTRIBUTE_INITIALIZED
|
582 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE
|
583 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE
|
584 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE
|
585 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
587 CurrentResourceHob
->PhysicalStart
,
588 (TopLoadingAddress
- TotalReservedMemorySize
- CurrentResourceHob
->PhysicalStart
)
591 if (CurrentResourceHob
->PhysicalStart
+ CurrentResourceHob
->ResourceLength
> TopLoadingAddress
) {
592 BuildResourceDescriptorHob (
593 EFI_RESOURCE_SYSTEM_MEMORY
,
595 EFI_RESOURCE_ATTRIBUTE_PRESENT
|
596 EFI_RESOURCE_ATTRIBUTE_INITIALIZED
|
597 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE
|
598 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE
|
599 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE
|
600 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
603 (CurrentResourceHob
->PhysicalStart
+ CurrentResourceHob
->ResourceLength
- TopLoadingAddress
)
607 // Delete CurrentHob by marking it as unused since the the memory range described by is rebuilt.
609 GET_HOB_TYPE (CurrentHob
) = EFI_HOB_TYPE_UNUSED
;
613 // Cache the top address for Loading Module at Fixed Address feature
615 PrivateData
->LoadModuleAtFixAddressTopAddress
= TopLoadingAddress
- MINIMUM_INITIAL_MEMORY_SIZE
;
616 DEBUG ((EFI_D_INFO
, "LOADING MODULE FIXED INFO: Top address = 0x%lx\n", PrivateData
->LoadModuleAtFixAddressTopAddress
));
618 // reinstall the PEI memory relative to TopLoadingAddress
620 PrivateData
->PhysicalMemoryBegin
= TopLoadingAddress
- TotalReservedMemorySize
;
621 PrivateData
->FreePhysicalMemoryTop
= PrivateData
->PhysicalMemoryBegin
+ PeiMemorySize
;
625 This routine is invoked in switch stack as PeiCore Entry.
627 @param SecCoreData Points to a data structure containing information about the PEI core's operating
628 environment, such as the size and location of temporary RAM, the stack location and
630 @param Private Pointer to old core data that is used to initialize the
636 IN CONST EFI_SEC_PEI_HAND_OFF
*SecCoreData
,
637 IN PEI_CORE_INSTANCE
*Private
643 PeiCore (SecCoreData
, NULL
, Private
);
647 Check SwitchStackSignal and switch stack if SwitchStackSignal is TRUE.
649 @param[in] SecCoreData Points to a data structure containing information about the PEI core's operating
650 environment, such as the size and location of temporary RAM, the stack location and
652 @param[in] Private Pointer to the private data passed in from caller.
656 PeiCheckAndSwitchStack (
657 IN CONST EFI_SEC_PEI_HAND_OFF
*SecCoreData
,
658 IN PEI_CORE_INSTANCE
*Private
661 VOID
*LoadFixPeiCodeBegin
;
663 CONST EFI_PEI_SERVICES
**PeiServices
;
665 EFI_PHYSICAL_ADDRESS TopOfOldStack
;
666 EFI_PHYSICAL_ADDRESS TopOfNewStack
;
668 BOOLEAN StackOffsetPositive
;
669 EFI_PHYSICAL_ADDRESS TemporaryRamBase
;
670 UINTN TemporaryRamSize
;
671 UINTN TemporaryStackSize
;
672 VOID
*TemporaryStackBase
;
673 UINTN PeiTemporaryRamSize
;
674 VOID
*PeiTemporaryRamBase
;
675 EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI
*TemporaryRamSupportPpi
;
676 EFI_PHYSICAL_ADDRESS BaseOfNewHeap
;
677 EFI_PHYSICAL_ADDRESS HoleMemBase
;
679 UINTN HeapTemporaryRamSize
;
680 EFI_PHYSICAL_ADDRESS TempBase1
;
682 EFI_PHYSICAL_ADDRESS TempBase2
;
686 PeiServices
= (CONST EFI_PEI_SERVICES
**) &Private
->Ps
;
688 if (Private
->SwitchStackSignal
) {
690 // Before switch stack from temporary memory to permanent memory, calculate the heap and stack
691 // usage in temporary memory for debugging.
694 UINT32
*StackPointer
;
695 EFI_PEI_HOB_POINTERS Hob
;
697 for (StackPointer
= (UINT32
*)SecCoreData
->StackBase
;
698 (StackPointer
< (UINT32
*)((UINTN
)SecCoreData
->StackBase
+ SecCoreData
->StackSize
)) \
699 && (*StackPointer
== PcdGet32 (PcdInitValueInTempStack
));
703 DEBUG ((DEBUG_INFO
, "Temp Stack : BaseAddress=0x%p Length=0x%X\n", SecCoreData
->StackBase
, (UINT32
)SecCoreData
->StackSize
));
704 DEBUG ((DEBUG_INFO
, "Temp Heap : BaseAddress=0x%p Length=0x%X\n", SecCoreData
->PeiTemporaryRamBase
, (UINT32
)SecCoreData
->PeiTemporaryRamSize
));
705 DEBUG ((DEBUG_INFO
, "Total temporary memory: %d bytes.\n", (UINT32
)SecCoreData
->TemporaryRamSize
));
706 DEBUG ((DEBUG_INFO
, " temporary memory stack ever used: %d bytes.\n",
707 (UINT32
)(SecCoreData
->StackSize
- ((UINTN
) StackPointer
- (UINTN
)SecCoreData
->StackBase
))
709 DEBUG ((DEBUG_INFO
, " temporary memory heap used for HobList: %d bytes.\n",
710 (UINT32
)((UINTN
)Private
->HobList
.HandoffInformationTable
->EfiFreeMemoryBottom
- (UINTN
)Private
->HobList
.Raw
)
712 DEBUG ((DEBUG_INFO
, " temporary memory heap occupied by memory pages: %d bytes.\n",
713 (UINT32
)(UINTN
)(Private
->HobList
.HandoffInformationTable
->EfiMemoryTop
- Private
->HobList
.HandoffInformationTable
->EfiFreeMemoryTop
)
715 for (Hob
.Raw
= Private
->HobList
.Raw
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
716 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_MEMORY_ALLOCATION
) {
717 DEBUG ((DEBUG_INFO
, "Memory Allocation 0x%08x 0x%0lx - 0x%0lx\n", \
718 Hob
.MemoryAllocation
->AllocDescriptor
.MemoryType
, \
719 Hob
.MemoryAllocation
->AllocDescriptor
.MemoryBaseAddress
, \
720 Hob
.MemoryAllocation
->AllocDescriptor
.MemoryBaseAddress
+ Hob
.MemoryAllocation
->AllocDescriptor
.MemoryLength
- 1));
725 if (PcdGet64(PcdLoadModuleAtFixAddressEnable
) != 0 && (Private
->HobList
.HandoffInformationTable
->BootMode
!= BOOT_ON_S3_RESUME
)) {
727 // Loading Module at Fixed Address is enabled
729 PeiLoadFixAddressHook (Private
);
732 // If Loading Module at Fixed Address is enabled, Allocating memory range for Pei code range.
734 LoadFixPeiCodeBegin
= AllocatePages((UINTN
)PcdGet32(PcdLoadFixAddressPeiCodePageNumber
));
735 DEBUG ((EFI_D_INFO
, "LOADING MODULE FIXED INFO: PeiCodeBegin = 0x%lX, PeiCodeTop= 0x%lX\n", (UINT64
)(UINTN
)LoadFixPeiCodeBegin
, (UINT64
)((UINTN
)LoadFixPeiCodeBegin
+ PcdGet32(PcdLoadFixAddressPeiCodePageNumber
) * EFI_PAGE_SIZE
)));
739 // Reserve the size of new stack at bottom of physical memory
741 // The size of new stack in permanent memory must be the same size
742 // or larger than the size of old stack in temporary memory.
743 // But if new stack is smaller than the size of old stack, we also reserve
744 // the size of old stack at bottom of permanent memory.
746 NewStackSize
= RShiftU64 (Private
->PhysicalMemoryLength
, 1);
747 NewStackSize
= ALIGN_VALUE (NewStackSize
, EFI_PAGE_SIZE
);
748 NewStackSize
= MIN (PcdGet32(PcdPeiCoreMaxPeiStackSize
), NewStackSize
);
749 DEBUG ((EFI_D_INFO
, "Old Stack size %d, New stack size %d\n", (UINT32
)SecCoreData
->StackSize
, (UINT32
)NewStackSize
));
750 ASSERT (NewStackSize
>= SecCoreData
->StackSize
);
753 // Calculate stack offset and heap offset between temporary memory and new permement
754 // memory seperately.
756 TopOfOldStack
= (UINTN
)SecCoreData
->StackBase
+ SecCoreData
->StackSize
;
757 TopOfNewStack
= Private
->PhysicalMemoryBegin
+ NewStackSize
;
758 if (TopOfNewStack
>= TopOfOldStack
) {
759 StackOffsetPositive
= TRUE
;
760 StackOffset
= (UINTN
)(TopOfNewStack
- TopOfOldStack
);
762 StackOffsetPositive
= FALSE
;
763 StackOffset
= (UINTN
)(TopOfOldStack
- TopOfNewStack
);
765 Private
->StackOffsetPositive
= StackOffsetPositive
;
766 Private
->StackOffset
= StackOffset
;
769 // Build Stack HOB that describes the permanent memory stack
771 DEBUG ((EFI_D_INFO
, "Stack Hob: BaseAddress=0x%lX Length=0x%lX\n", TopOfNewStack
- NewStackSize
, NewStackSize
));
772 BuildStackHob (TopOfNewStack
- NewStackSize
, NewStackSize
);
775 // Cache information from SecCoreData into locals before SecCoreData is converted to a permanent memory address
777 TemporaryRamBase
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)SecCoreData
->TemporaryRamBase
;
778 TemporaryRamSize
= SecCoreData
->TemporaryRamSize
;
779 TemporaryStackSize
= SecCoreData
->StackSize
;
780 TemporaryStackBase
= SecCoreData
->StackBase
;
781 PeiTemporaryRamSize
= SecCoreData
->PeiTemporaryRamSize
;
782 PeiTemporaryRamBase
= SecCoreData
->PeiTemporaryRamBase
;
785 // TemporaryRamSupportPpi is produced by platform's SEC
787 Status
= PeiServicesLocatePpi (
788 &gEfiTemporaryRamSupportPpiGuid
,
791 (VOID
**)&TemporaryRamSupportPpi
793 if (!EFI_ERROR (Status
)) {
797 BaseOfNewHeap
= TopOfNewStack
;
798 if (BaseOfNewHeap
>= (UINTN
)SecCoreData
->PeiTemporaryRamBase
) {
799 Private
->HeapOffsetPositive
= TRUE
;
800 Private
->HeapOffset
= (UINTN
)(BaseOfNewHeap
- (UINTN
)SecCoreData
->PeiTemporaryRamBase
);
802 Private
->HeapOffsetPositive
= FALSE
;
803 Private
->HeapOffset
= (UINTN
)((UINTN
)SecCoreData
->PeiTemporaryRamBase
- BaseOfNewHeap
);
806 DEBUG ((EFI_D_INFO
, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (UINT64
) Private
->HeapOffset
, (UINT64
) Private
->StackOffset
));
809 // Calculate new HandOffTable and PrivateData address in permanent memory's stack
811 if (StackOffsetPositive
) {
812 SecCoreData
= (CONST EFI_SEC_PEI_HAND_OFF
*)((UINTN
)(VOID
*)SecCoreData
+ StackOffset
);
813 Private
= (PEI_CORE_INSTANCE
*)((UINTN
)(VOID
*)Private
+ StackOffset
);
815 SecCoreData
= (CONST EFI_SEC_PEI_HAND_OFF
*)((UINTN
)(VOID
*)SecCoreData
- StackOffset
);
816 Private
= (PEI_CORE_INSTANCE
*)((UINTN
)(VOID
*)Private
- StackOffset
);
820 // Temporary Ram Support PPI is provided by platform, it will copy
821 // temporary memory to permanent memory and do stack switching.
822 // After invoking Temporary Ram Support PPI, the following code's
823 // stack is in permanent memory.
825 TemporaryRamSupportPpi
->TemporaryRamMigration (
828 (EFI_PHYSICAL_ADDRESS
)(UINTN
)(TopOfNewStack
- TemporaryStackSize
),
833 // Migrate memory pages allocated in pre-memory phase.
834 // It could not be called before calling TemporaryRamSupportPpi->TemporaryRamMigration()
835 // as the migrated memory pages may be overridden by TemporaryRamSupportPpi->TemporaryRamMigration().
837 MigrateMemoryPages (Private
, TRUE
);
842 PeiCore (SecCoreData
, NULL
, Private
);
845 // Migrate memory pages allocated in pre-memory phase.
847 MigrateMemoryPages (Private
, FALSE
);
850 // Migrate the PEI Services Table pointer from temporary RAM to permanent RAM.
852 MigratePeiServicesTablePointer ();
857 BaseOfNewHeap
= TopOfNewStack
;
858 HoleMemBase
= TopOfNewStack
;
859 HoleMemSize
= TemporaryRamSize
- PeiTemporaryRamSize
- TemporaryStackSize
;
860 if (HoleMemSize
!= 0) {
862 // Make sure HOB List start address is 8 byte alignment.
864 BaseOfNewHeap
= ALIGN_VALUE (BaseOfNewHeap
+ HoleMemSize
, 8);
866 if (BaseOfNewHeap
>= (UINTN
)SecCoreData
->PeiTemporaryRamBase
) {
867 Private
->HeapOffsetPositive
= TRUE
;
868 Private
->HeapOffset
= (UINTN
)(BaseOfNewHeap
- (UINTN
)SecCoreData
->PeiTemporaryRamBase
);
870 Private
->HeapOffsetPositive
= FALSE
;
871 Private
->HeapOffset
= (UINTN
)((UINTN
)SecCoreData
->PeiTemporaryRamBase
- BaseOfNewHeap
);
874 DEBUG ((EFI_D_INFO
, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (UINT64
) Private
->HeapOffset
, (UINT64
) Private
->StackOffset
));
879 HeapTemporaryRamSize
= (UINTN
) (Private
->HobList
.HandoffInformationTable
->EfiFreeMemoryBottom
- Private
->HobList
.HandoffInformationTable
->EfiMemoryBottom
);
880 ASSERT (BaseOfNewHeap
+ HeapTemporaryRamSize
<= Private
->FreePhysicalMemoryTop
);
881 CopyMem ((UINT8
*) (UINTN
) BaseOfNewHeap
, PeiTemporaryRamBase
, HeapTemporaryRamSize
);
886 CopyMem ((UINT8
*) (UINTN
) (TopOfNewStack
- TemporaryStackSize
), TemporaryStackBase
, TemporaryStackSize
);
889 // Copy Hole Range Data
891 if (HoleMemSize
!= 0) {
895 if (PeiTemporaryRamBase
< TemporaryStackBase
) {
896 TempBase1
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) PeiTemporaryRamBase
;
897 TempSize1
= PeiTemporaryRamSize
;
898 TempBase2
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) TemporaryStackBase
;
899 TempSize2
= TemporaryStackSize
;
901 TempBase1
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) TemporaryStackBase
;
902 TempSize1
= TemporaryStackSize
;
903 TempBase2
=(EFI_PHYSICAL_ADDRESS
) (UINTN
) PeiTemporaryRamBase
;
904 TempSize2
= PeiTemporaryRamSize
;
906 if (TemporaryRamBase
< TempBase1
) {
907 Private
->HoleData
[0].Base
= TemporaryRamBase
;
908 Private
->HoleData
[0].Size
= (UINTN
) (TempBase1
- TemporaryRamBase
);
910 if (TempBase1
+ TempSize1
< TempBase2
) {
911 Private
->HoleData
[1].Base
= TempBase1
+ TempSize1
;
912 Private
->HoleData
[1].Size
= (UINTN
) (TempBase2
- TempBase1
- TempSize1
);
914 if (TempBase2
+ TempSize2
< TemporaryRamBase
+ TemporaryRamSize
) {
915 Private
->HoleData
[2].Base
= TempBase2
+ TempSize2
;
916 Private
->HoleData
[2].Size
= (UINTN
) (TemporaryRamBase
+ TemporaryRamSize
- TempBase2
- TempSize2
);
920 // Copy Hole Range data.
922 for (Index
= 0; Index
< HOLE_MAX_NUMBER
; Index
++) {
923 if (Private
->HoleData
[Index
].Size
> 0) {
924 if (HoleMemBase
> Private
->HoleData
[Index
].Base
) {
925 Private
->HoleData
[Index
].OffsetPositive
= TRUE
;
926 Private
->HoleData
[Index
].Offset
= (UINTN
) (HoleMemBase
- Private
->HoleData
[Index
].Base
);
928 Private
->HoleData
[Index
].OffsetPositive
= FALSE
;
929 Private
->HoleData
[Index
].Offset
= (UINTN
) (Private
->HoleData
[Index
].Base
- HoleMemBase
);
931 CopyMem ((VOID
*) (UINTN
) HoleMemBase
, (VOID
*) (UINTN
) Private
->HoleData
[Index
].Base
, Private
->HoleData
[Index
].Size
);
932 HoleMemBase
= HoleMemBase
+ Private
->HoleData
[Index
].Size
;
941 (SWITCH_STACK_ENTRY_POINT
)(UINTN
)PeiCoreEntry
,
942 (VOID
*) SecCoreData
,
944 (VOID
*) (UINTN
) TopOfNewStack
949 // Code should not come here
956 Conduct PEIM dispatch.
958 @param SecCoreData Points to a data structure containing information about the PEI core's operating
959 environment, such as the size and location of temporary RAM, the stack location and
961 @param Private Pointer to the private data passed in from caller
966 IN CONST EFI_SEC_PEI_HAND_OFF
*SecCoreData
,
967 IN PEI_CORE_INSTANCE
*Private
973 CONST EFI_PEI_SERVICES
**PeiServices
;
974 EFI_PEI_FILE_HANDLE PeimFileHandle
;
977 UINT32 AuthenticationState
;
978 EFI_PHYSICAL_ADDRESS EntryPoint
;
979 EFI_PEIM_ENTRY_POINT2 PeimEntryPoint
;
980 UINTN SaveCurrentPeimCount
;
981 UINTN SaveCurrentFvCount
;
982 EFI_PEI_FILE_HANDLE SaveCurrentFileHandle
;
983 EFI_FV_FILE_INFO FvFileInfo
;
984 PEI_CORE_FV_HANDLE
*CoreFvHandle
;
986 PeiServices
= (CONST EFI_PEI_SERVICES
**) &Private
->Ps
;
987 PeimEntryPoint
= NULL
;
988 PeimFileHandle
= NULL
;
991 if ((Private
->PeiMemoryInstalled
) && (Private
->HobList
.HandoffInformationTable
->BootMode
!= BOOT_ON_S3_RESUME
|| PcdGetBool (PcdShadowPeimOnS3Boot
))) {
993 // Once real memory is available, shadow the RegisterForShadow modules. And meanwhile
994 // update the modules' status from PEIM_STATE_REGISTER_FOR_SHADOW to PEIM_STATE_DONE.
996 SaveCurrentPeimCount
= Private
->CurrentPeimCount
;
997 SaveCurrentFvCount
= Private
->CurrentPeimFvCount
;
998 SaveCurrentFileHandle
= Private
->CurrentFileHandle
;
1000 for (Index1
= 0; Index1
< Private
->FvCount
; Index1
++) {
1001 for (Index2
= 0; Index2
< Private
->Fv
[Index1
].PeimCount
; Index2
++) {
1002 if (Private
->Fv
[Index1
].PeimState
[Index2
] == PEIM_STATE_REGISTER_FOR_SHADOW
) {
1003 PeimFileHandle
= Private
->Fv
[Index1
].FvFileHandles
[Index2
];
1004 Private
->CurrentFileHandle
= PeimFileHandle
;
1005 Private
->CurrentPeimFvCount
= Index1
;
1006 Private
->CurrentPeimCount
= Index2
;
1007 Status
= PeiLoadImage (
1008 (CONST EFI_PEI_SERVICES
**) &Private
->Ps
,
1010 PEIM_STATE_REGISTER_FOR_SHADOW
,
1012 &AuthenticationState
1014 if (Status
== EFI_SUCCESS
) {
1016 // PEIM_STATE_REGISTER_FOR_SHADOW move to PEIM_STATE_DONE
1018 Private
->Fv
[Index1
].PeimState
[Index2
]++;
1020 // Call the PEIM entry point
1022 PeimEntryPoint
= (EFI_PEIM_ENTRY_POINT2
)(UINTN
)EntryPoint
;
1024 PERF_START_IMAGE_BEGIN (PeimFileHandle
);
1025 PeimEntryPoint(PeimFileHandle
, (const EFI_PEI_SERVICES
**) &Private
->Ps
);
1026 PERF_START_IMAGE_END (PeimFileHandle
);
1030 // Process the Notify list and dispatch any notifies for
1031 // newly installed PPIs.
1033 ProcessDispatchNotifyList (Private
);
1037 Private
->CurrentFileHandle
= SaveCurrentFileHandle
;
1038 Private
->CurrentPeimFvCount
= SaveCurrentFvCount
;
1039 Private
->CurrentPeimCount
= SaveCurrentPeimCount
;
1043 // This is the main dispatch loop. It will search known FVs for PEIMs and
1044 // attempt to dispatch them. If any PEIM gets dispatched through a single
1045 // pass of the dispatcher, it will start over from the Bfv again to see
1046 // if any new PEIMs dependencies got satisfied. With a well ordered
1047 // FV where PEIMs are found in the order their dependencies are also
1048 // satisfied, this dipatcher should run only once.
1052 // In case that reenter PeiCore happens, the last pass record is still available.
1054 if (!Private
->PeimDispatcherReenter
) {
1055 Private
->PeimNeedingDispatch
= FALSE
;
1056 Private
->PeimDispatchOnThisPass
= FALSE
;
1058 Private
->PeimDispatcherReenter
= FALSE
;
1061 for (FvCount
= Private
->CurrentPeimFvCount
; FvCount
< Private
->FvCount
; FvCount
++) {
1062 CoreFvHandle
= FindNextCoreFvHandle (Private
, FvCount
);
1063 ASSERT (CoreFvHandle
!= NULL
);
1066 // If the FV has corresponding EFI_PEI_FIRMWARE_VOLUME_PPI instance, then dispatch it.
1068 if (CoreFvHandle
->FvPpi
== NULL
) {
1072 Private
->CurrentPeimFvCount
= FvCount
;
1074 if (Private
->CurrentPeimCount
== 0) {
1076 // When going through each FV, at first, search Apriori file to
1077 // reorder all PEIMs to ensure the PEIMs in Apriori file to get
1078 // dispatch at first.
1080 DiscoverPeimsAndOrderWithApriori (Private
, CoreFvHandle
);
1084 // Start to dispatch all modules within the current Fv.
1086 for (PeimCount
= Private
->CurrentPeimCount
;
1087 PeimCount
< Private
->Fv
[FvCount
].PeimCount
;
1089 Private
->CurrentPeimCount
= PeimCount
;
1090 PeimFileHandle
= Private
->CurrentFileHandle
= Private
->CurrentFvFileHandles
[PeimCount
];
1092 if (Private
->Fv
[FvCount
].PeimState
[PeimCount
] == PEIM_STATE_NOT_DISPATCHED
) {
1093 if (!DepexSatisfied (Private
, PeimFileHandle
, PeimCount
)) {
1094 Private
->PeimNeedingDispatch
= TRUE
;
1096 Status
= CoreFvHandle
->FvPpi
->GetFileInfo (CoreFvHandle
->FvPpi
, PeimFileHandle
, &FvFileInfo
);
1097 ASSERT_EFI_ERROR (Status
);
1098 if (FvFileInfo
.FileType
== EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
) {
1100 // For Fv type file, Produce new FvInfo PPI and FV hob
1102 Status
= ProcessFvFile (Private
, &Private
->Fv
[FvCount
], PeimFileHandle
);
1103 if (Status
== EFI_SUCCESS
) {
1105 // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED
1107 Private
->Fv
[FvCount
].PeimState
[PeimCount
]++;
1108 Private
->PeimDispatchOnThisPass
= TRUE
;
1111 // The related GuidedSectionExtraction/Decompress PPI for the
1112 // encapsulated FV image section may be installed in the rest
1113 // of this do-while loop, so need to make another pass.
1115 Private
->PeimNeedingDispatch
= TRUE
;
1119 // For PEIM driver, Load its entry point
1121 Status
= PeiLoadImage (
1124 PEIM_STATE_NOT_DISPATCHED
,
1126 &AuthenticationState
1128 if (Status
== EFI_SUCCESS
) {
1130 // The PEIM has its dependencies satisfied, and its entry point
1131 // has been found, so invoke it.
1133 PERF_START_IMAGE_BEGIN (PeimFileHandle
);
1135 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
1137 (EFI_SOFTWARE_PEI_CORE
| EFI_SW_PC_INIT_BEGIN
),
1138 (VOID
*)(&PeimFileHandle
),
1139 sizeof (PeimFileHandle
)
1142 Status
= VerifyPeim (Private
, CoreFvHandle
->FvHandle
, PeimFileHandle
, AuthenticationState
);
1143 if (Status
!= EFI_SECURITY_VIOLATION
) {
1145 // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED
1147 Private
->Fv
[FvCount
].PeimState
[PeimCount
]++;
1149 // Call the PEIM entry point for PEIM driver
1151 PeimEntryPoint
= (EFI_PEIM_ENTRY_POINT2
)(UINTN
)EntryPoint
;
1152 PeimEntryPoint (PeimFileHandle
, (const EFI_PEI_SERVICES
**) PeiServices
);
1153 Private
->PeimDispatchOnThisPass
= TRUE
;
1156 // The related GuidedSectionExtraction PPI for the
1157 // signed PEIM image section may be installed in the rest
1158 // of this do-while loop, so need to make another pass.
1160 Private
->PeimNeedingDispatch
= TRUE
;
1163 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
1165 (EFI_SOFTWARE_PEI_CORE
| EFI_SW_PC_INIT_END
),
1166 (VOID
*)(&PeimFileHandle
),
1167 sizeof (PeimFileHandle
)
1169 PERF_START_IMAGE_END (PeimFileHandle
);
1174 PeiCheckAndSwitchStack (SecCoreData
, Private
);
1177 // Process the Notify list and dispatch any notifies for
1178 // newly installed PPIs.
1180 ProcessDispatchNotifyList (Private
);
1183 // Recheck SwitchStackSignal after ProcessDispatchNotifyList()
1184 // in case PeiInstallPeiMemory() is done in a callback with
1185 // EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH.
1187 PeiCheckAndSwitchStack (SecCoreData
, Private
);
1189 if ((Private
->PeiMemoryInstalled
) && (Private
->Fv
[FvCount
].PeimState
[PeimCount
] == PEIM_STATE_REGISTER_FOR_SHADOW
) && \
1190 (Private
->HobList
.HandoffInformationTable
->BootMode
!= BOOT_ON_S3_RESUME
|| PcdGetBool (PcdShadowPeimOnS3Boot
))) {
1192 // If memory is available we shadow images by default for performance reasons.
1193 // We call the entry point a 2nd time so the module knows it's shadowed.
1195 //PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0);
1196 if ((Private
->HobList
.HandoffInformationTable
->BootMode
!= BOOT_ON_S3_RESUME
) && !PcdGetBool (PcdShadowPeimOnBoot
)) {
1198 // Load PEIM into Memory for Register for shadow PEIM.
1200 Status
= PeiLoadImage (
1203 PEIM_STATE_REGISTER_FOR_SHADOW
,
1205 &AuthenticationState
1207 if (Status
== EFI_SUCCESS
) {
1208 PeimEntryPoint
= (EFI_PEIM_ENTRY_POINT2
)(UINTN
)EntryPoint
;
1211 ASSERT (PeimEntryPoint
!= NULL
);
1212 PeimEntryPoint (PeimFileHandle
, (const EFI_PEI_SERVICES
**) PeiServices
);
1213 //PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0);
1216 // PEIM_STATE_REGISTER_FOR_SHADOW move to PEIM_STATE_DONE
1218 Private
->Fv
[FvCount
].PeimState
[PeimCount
]++;
1221 // Process the Notify list and dispatch any notifies for
1222 // newly installed PPIs.
1224 ProcessDispatchNotifyList (Private
);
1231 // Before walking through the next FV, we should set them to NULL/0 to
1232 // start at the begining of the next FV.
1234 Private
->CurrentFileHandle
= NULL
;
1235 Private
->CurrentPeimCount
= 0;
1236 Private
->CurrentFvFileHandles
= NULL
;
1240 // Before making another pass, we should set it to 0 to
1241 // go through all the FVs.
1243 Private
->CurrentPeimFvCount
= 0;
1246 // PeimNeedingDispatch being TRUE means we found a PEIM/FV that did not get
1247 // dispatched. So we need to make another pass
1249 // PeimDispatchOnThisPass being TRUE means we dispatched a PEIM/FV on this
1250 // pass. If we did not dispatch a PEIM/FV there is no point in trying again
1251 // as it will fail the next time too (nothing has changed).
1253 } while (Private
->PeimNeedingDispatch
&& Private
->PeimDispatchOnThisPass
);
1258 Initialize the Dispatcher's data members
1260 @param PrivateData PeiCore's private data structure
1261 @param OldCoreData Old data from SecCore
1262 NULL if being run in non-permament memory mode.
1263 @param SecCoreData Points to a data structure containing information about the PEI core's operating
1264 environment, such as the size and location of temporary RAM, the stack location and
1271 InitializeDispatcherData (
1272 IN PEI_CORE_INSTANCE
*PrivateData
,
1273 IN PEI_CORE_INSTANCE
*OldCoreData
,
1274 IN CONST EFI_SEC_PEI_HAND_OFF
*SecCoreData
1277 if (OldCoreData
== NULL
) {
1278 PrivateData
->PeimDispatcherReenter
= FALSE
;
1279 PeiInitializeFv (PrivateData
, SecCoreData
);
1281 PeiReinitializeFv (PrivateData
);
1288 This routine parses the Dependency Expression, if available, and
1289 decides if the module can be executed.
1292 @param Private PeiCore's private data structure
1293 @param FileHandle PEIM's file handle
1294 @param PeimCount Peim count in all dispatched PEIMs.
1296 @retval TRUE Can be dispatched
1297 @retval FALSE Cannot be dispatched
1302 IN PEI_CORE_INSTANCE
*Private
,
1303 IN EFI_PEI_FILE_HANDLE FileHandle
,
1309 EFI_FV_FILE_INFO FileInfo
;
1311 Status
= PeiServicesFfsGetFileInfo (FileHandle
, &FileInfo
);
1312 if (EFI_ERROR (Status
)) {
1313 DEBUG ((DEBUG_DISPATCH
, "Evaluate PEI DEPEX for FFS(Unknown)\n"));
1315 DEBUG ((DEBUG_DISPATCH
, "Evaluate PEI DEPEX for FFS(%g)\n", &FileInfo
.FileName
));
1318 if (PeimCount
< Private
->AprioriCount
) {
1320 // If it's in the Apriori file then we set Depex to TRUE
1322 DEBUG ((DEBUG_DISPATCH
, " RESULT = TRUE (Apriori)\n"));
1327 // Depex section not in the encapsulated section.
1329 Status
= PeiServicesFfsFindSectionData (
1330 EFI_SECTION_PEI_DEPEX
,
1335 if (EFI_ERROR (Status
)) {
1337 // If there is no DEPEX, assume the module can be executed
1339 DEBUG ((DEBUG_DISPATCH
, " RESULT = TRUE (No DEPEX)\n"));
1344 // Evaluate a given DEPEX
1346 return PeimDispatchReadiness (&Private
->Ps
, DepexData
);
1350 This routine enable a PEIM to register itself to shadow when PEI Foundation
1351 discovery permanent memory.
1353 @param FileHandle File handle of a PEIM.
1355 @retval EFI_NOT_FOUND The file handle doesn't point to PEIM itself.
1356 @retval EFI_ALREADY_STARTED Indicate that the PEIM has been registered itself.
1357 @retval EFI_SUCCESS Successfully to register itself.
1362 PeiRegisterForShadow (
1363 IN EFI_PEI_FILE_HANDLE FileHandle
1366 PEI_CORE_INSTANCE
*Private
;
1367 Private
= PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());
1369 if (Private
->CurrentFileHandle
!= FileHandle
) {
1371 // The FileHandle must be for the current PEIM
1373 return EFI_NOT_FOUND
;
1376 if (Private
->Fv
[Private
->CurrentPeimFvCount
].PeimState
[Private
->CurrentPeimCount
] >= PEIM_STATE_REGISTER_FOR_SHADOW
) {
1378 // If the PEIM has already entered the PEIM_STATE_REGISTER_FOR_SHADOW or PEIM_STATE_DONE then it's already been started
1380 return EFI_ALREADY_STARTED
;
1383 Private
->Fv
[Private
->CurrentPeimFvCount
].PeimState
[Private
->CurrentPeimCount
] = PEIM_STATE_REGISTER_FOR_SHADOW
;