2 EFI PEI Core dispatch services
4 Copyright (c) 2006 - 2019, 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
)
77 ASSERT (TempFileHandles
!= NULL
);
80 Private
->TempFileHandles
,
81 sizeof (EFI_PEI_FILE_HANDLE
) * Private
->TempPeimCount
83 Private
->TempFileHandles
= TempFileHandles
;
84 TempFileGuid
= AllocatePool (
85 sizeof (EFI_GUID
) * (Private
->TempPeimCount
+ TEMP_FILE_GROWTH_STEP
)
87 ASSERT (TempFileGuid
!= NULL
);
90 Private
->TempFileGuid
,
91 sizeof (EFI_GUID
) * Private
->TempPeimCount
93 Private
->TempFileGuid
= TempFileGuid
;
94 Private
->TempPeimCount
= Private
->TempPeimCount
+ TEMP_FILE_GROWTH_STEP
;
97 TempFileHandles
[PeimCount
++] = FileHandle
;
99 } while (!EFI_ERROR (Status
));
103 "%a(): Found 0x%x PEI FFS files in the %dth FV\n",
106 Private
->CurrentPeimFvCount
109 if (PeimCount
== 0) {
111 // No PEIM FFS file is found, set ScanFv flag and return.
113 CoreFileHandle
->ScanFv
= TRUE
;
118 // Record PeimCount, allocate buffer for PeimState and FvFileHandles.
120 CoreFileHandle
->PeimCount
= PeimCount
;
121 CoreFileHandle
->PeimState
= AllocateZeroPool (sizeof (UINT8
) * PeimCount
);
122 ASSERT (CoreFileHandle
->PeimState
!= NULL
);
123 CoreFileHandle
->FvFileHandles
= AllocateZeroPool (sizeof (EFI_PEI_FILE_HANDLE
) * PeimCount
);
124 ASSERT (CoreFileHandle
->FvFileHandles
!= NULL
);
127 // Get Apriori File handle
129 Private
->AprioriCount
= 0;
130 Status
= FvPpi
->FindFileByName (FvPpi
, &gPeiAprioriFileNameGuid
, &CoreFileHandle
->FvHandle
, &AprioriFileHandle
);
131 if (!EFI_ERROR (Status
) && (AprioriFileHandle
!= NULL
)) {
133 // Read the Apriori file
135 Status
= FvPpi
->FindSectionByType (FvPpi
, EFI_SECTION_RAW
, AprioriFileHandle
, (VOID
**)&Apriori
);
136 if (!EFI_ERROR (Status
)) {
138 // Calculate the number of PEIMs in the Apriori file
140 Status
= FvPpi
->GetFileInfo (FvPpi
, AprioriFileHandle
, &FileInfo
);
141 ASSERT_EFI_ERROR (Status
);
142 Private
->AprioriCount
= FileInfo
.BufferSize
;
143 if (IS_SECTION2 (FileInfo
.Buffer
)) {
144 Private
->AprioriCount
-= sizeof (EFI_COMMON_SECTION_HEADER2
);
146 Private
->AprioriCount
-= sizeof (EFI_COMMON_SECTION_HEADER
);
149 Private
->AprioriCount
/= sizeof (EFI_GUID
);
151 for (Index
= 0; Index
< PeimCount
; Index
++) {
153 // Make an array of file name GUIDs that matches the FileHandle array so we can convert
154 // quickly from file name to file handle
156 Status
= FvPpi
->GetFileInfo (FvPpi
, TempFileHandles
[Index
], &FileInfo
);
157 ASSERT_EFI_ERROR (Status
);
158 CopyMem (&TempFileGuid
[Index
], &FileInfo
.FileName
, sizeof (EFI_GUID
));
162 // Walk through TempFileGuid array to find out who is invalid PEIM GUID in Apriori file.
163 // Add available PEIMs in Apriori file into FvFileHandles array.
166 for (Index2
= 0; Index2
< Private
->AprioriCount
; Index2
++) {
167 Guid
= ScanGuid (TempFileGuid
, PeimCount
* sizeof (EFI_GUID
), &Apriori
[Index2
]);
169 PeimIndex
= ((UINTN
)Guid
- (UINTN
)&TempFileGuid
[0])/sizeof (EFI_GUID
);
170 CoreFileHandle
->FvFileHandles
[Index
++] = TempFileHandles
[PeimIndex
];
173 // Since we have copied the file handle we can remove it from this list.
175 TempFileHandles
[PeimIndex
] = NULL
;
180 // Update valid AprioriCount
182 Private
->AprioriCount
= Index
;
185 // Add in any PEIMs not in the Apriori file
187 for (Index2
= 0; Index2
< PeimCount
; Index2
++) {
188 if (TempFileHandles
[Index2
] != NULL
) {
189 CoreFileHandle
->FvFileHandles
[Index
++] = TempFileHandles
[Index2
];
190 TempFileHandles
[Index2
] = NULL
;
194 ASSERT (Index
== PeimCount
);
197 CopyMem (CoreFileHandle
->FvFileHandles
, TempFileHandles
, sizeof (EFI_PEI_FILE_HANDLE
) * PeimCount
);
201 // The current FV File Handles have been cached. So that we don't have to scan the FV again.
202 // Instead, we can retrieve the file handles within this FV from cached records.
204 CoreFileHandle
->ScanFv
= TRUE
;
205 Private
->CurrentFvFileHandles
= CoreFileHandle
->FvFileHandles
;
209 // This is the minimum memory required by DxeCore initialization. When LMFA feature enabled,
210 // This part of memory still need reserved on the very top of memory so that the DXE Core could
211 // use these memory for data initialization. This macro should be sync with the same marco
212 // defined in DXE Core.
214 #define MINIMUM_INITIAL_MEMORY_SIZE 0x10000
217 This function is to test if the memory range described in resource HOB is available or not.
219 This function should only be invoked when Loading Module at Fixed Address(LMFA) feature is enabled. Some platform may allocate the
220 memory before PeiLoadFixAddressHook in invoked. so this function is to test if the memory range described by the input resource HOB is
223 @param PrivateData Pointer to the private data passed in from caller
224 @param ResourceHob Pointer to a resource HOB which described the memory range described by the input resource HOB
227 PeiLoadFixAddressIsMemoryRangeAvailable (
228 IN PEI_CORE_INSTANCE
*PrivateData
,
229 IN EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
232 EFI_HOB_MEMORY_ALLOCATION
*MemoryHob
;
234 EFI_PEI_HOB_POINTERS Hob
;
237 if ((PrivateData
== NULL
) || (ResourceHob
== NULL
)) {
242 // test if the memory range describe in the HOB is already allocated.
244 for (Hob
.Raw
= PrivateData
->HobList
.Raw
; !END_OF_HOB_LIST (Hob
); Hob
.Raw
= GET_NEXT_HOB (Hob
)) {
246 // See if this is a memory allocation HOB
248 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_MEMORY_ALLOCATION
) {
249 MemoryHob
= Hob
.MemoryAllocation
;
250 if ((MemoryHob
->AllocDescriptor
.MemoryBaseAddress
== ResourceHob
->PhysicalStart
) &&
251 (MemoryHob
->AllocDescriptor
.MemoryBaseAddress
+ MemoryHob
->AllocDescriptor
.MemoryLength
== ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
))
263 Hook function for Loading Module at Fixed Address feature
265 This function should only be invoked when Loading Module at Fixed Address(LMFA) feature is enabled. When feature is
266 configured as Load Modules at Fix Absolute Address, this function is to validate the top address assigned by user. When
267 feature is configured as Load Modules at Fixed Offset, the function is to find the top address which is TOLM-TSEG in general.
268 And also the function will re-install PEI memory.
270 @param PrivateData Pointer to the private data passed in from caller
274 PeiLoadFixAddressHook (
275 IN PEI_CORE_INSTANCE
*PrivateData
278 EFI_PHYSICAL_ADDRESS TopLoadingAddress
;
279 UINT64 PeiMemorySize
;
280 UINT64 TotalReservedMemorySize
;
281 UINT64 MemoryRangeEnd
;
282 EFI_PHYSICAL_ADDRESS HighAddress
;
283 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
284 EFI_HOB_RESOURCE_DESCRIPTOR
*NextResourceHob
;
285 EFI_HOB_RESOURCE_DESCRIPTOR
*CurrentResourceHob
;
286 EFI_PEI_HOB_POINTERS CurrentHob
;
287 EFI_PEI_HOB_POINTERS Hob
;
288 EFI_PEI_HOB_POINTERS NextHob
;
289 EFI_HOB_MEMORY_ALLOCATION
*MemoryHob
;
292 // Initialize Local Variables
294 CurrentResourceHob
= NULL
;
296 NextResourceHob
= NULL
;
298 TopLoadingAddress
= 0;
300 CurrentHob
.Raw
= PrivateData
->HobList
.Raw
;
301 PeiMemorySize
= PrivateData
->PhysicalMemoryLength
;
303 // The top reserved memory include 3 parts: the topest range is for DXE core initialization with the size MINIMUM_INITIAL_MEMORY_SIZE
304 // then RuntimeCodePage range and Boot time code range.
306 TotalReservedMemorySize
= MINIMUM_INITIAL_MEMORY_SIZE
+ EFI_PAGES_TO_SIZE (PcdGet32 (PcdLoadFixAddressRuntimeCodePageNumber
));
307 TotalReservedMemorySize
+= EFI_PAGES_TO_SIZE (PcdGet32 (PcdLoadFixAddressBootTimeCodePageNumber
));
309 // PEI memory range lies below the top reserved memory
311 TotalReservedMemorySize
+= PeiMemorySize
;
313 DEBUG ((DEBUG_INFO
, "LOADING MODULE FIXED INFO: PcdLoadFixAddressRuntimeCodePageNumber= 0x%x.\n", PcdGet32 (PcdLoadFixAddressRuntimeCodePageNumber
)));
314 DEBUG ((DEBUG_INFO
, "LOADING MODULE FIXED INFO: PcdLoadFixAddressBootTimeCodePageNumber= 0x%x.\n", PcdGet32 (PcdLoadFixAddressBootTimeCodePageNumber
)));
315 DEBUG ((DEBUG_INFO
, "LOADING MODULE FIXED INFO: PcdLoadFixAddressPeiCodePageNumber= 0x%x.\n", PcdGet32 (PcdLoadFixAddressPeiCodePageNumber
)));
316 DEBUG ((DEBUG_INFO
, "LOADING MODULE FIXED INFO: Total Reserved Memory Size = 0x%lx.\n", TotalReservedMemorySize
));
318 // Loop through the system memory typed HOB to merge the adjacent memory range
320 for (Hob
.Raw
= PrivateData
->HobList
.Raw
; !END_OF_HOB_LIST (Hob
); Hob
.Raw
= GET_NEXT_HOB (Hob
)) {
322 // See if this is a resource descriptor HOB
324 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
325 ResourceHob
= Hob
.ResourceDescriptor
;
327 // If range described in this HOB is not system memory or higher than MAX_ADDRESS, ignored.
329 if ((ResourceHob
->ResourceType
!= EFI_RESOURCE_SYSTEM_MEMORY
) ||
330 (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
> MAX_ADDRESS
))
335 for (NextHob
.Raw
= PrivateData
->HobList
.Raw
; !END_OF_HOB_LIST (NextHob
); NextHob
.Raw
= GET_NEXT_HOB (NextHob
)) {
336 if (NextHob
.Raw
== Hob
.Raw
) {
341 // See if this is a resource descriptor HOB
343 if (GET_HOB_TYPE (NextHob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
344 NextResourceHob
= NextHob
.ResourceDescriptor
;
346 // test if range described in this NextResourceHob is system memory and have the same attribute.
347 // Note: Here is a assumption that system memory should always be healthy even without test.
349 if ((NextResourceHob
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
) &&
350 (((NextResourceHob
->ResourceAttribute
^ResourceHob
->ResourceAttribute
)&(~EFI_RESOURCE_ATTRIBUTE_TESTED
)) == 0))
353 // See if the memory range described in ResourceHob and NextResourceHob is adjacent
355 if (((ResourceHob
->PhysicalStart
<= NextResourceHob
->PhysicalStart
) &&
356 (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
>= NextResourceHob
->PhysicalStart
)) ||
357 ((ResourceHob
->PhysicalStart
>= NextResourceHob
->PhysicalStart
) &&
358 (ResourceHob
->PhysicalStart
<= NextResourceHob
->PhysicalStart
+ NextResourceHob
->ResourceLength
)))
360 MemoryRangeEnd
= ((ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
) > (NextResourceHob
->PhysicalStart
+ NextResourceHob
->ResourceLength
)) ?
361 (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
) : (NextResourceHob
->PhysicalStart
+ NextResourceHob
->ResourceLength
);
363 ResourceHob
->PhysicalStart
= (ResourceHob
->PhysicalStart
< NextResourceHob
->PhysicalStart
) ?
364 ResourceHob
->PhysicalStart
: NextResourceHob
->PhysicalStart
;
366 ResourceHob
->ResourceLength
= (MemoryRangeEnd
- ResourceHob
->PhysicalStart
);
368 ResourceHob
->ResourceAttribute
= ResourceHob
->ResourceAttribute
& (~EFI_RESOURCE_ATTRIBUTE_TESTED
);
370 // Delete the NextResourceHob by marking it as unused.
372 GET_HOB_TYPE (NextHob
) = EFI_HOB_TYPE_UNUSED
;
381 // Some platform is already allocated pages before the HOB re-org. Here to build dedicated resource HOB to describe
382 // the allocated memory range
384 for (Hob
.Raw
= PrivateData
->HobList
.Raw
; !END_OF_HOB_LIST (Hob
); Hob
.Raw
= GET_NEXT_HOB (Hob
)) {
386 // See if this is a memory allocation HOB
388 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_MEMORY_ALLOCATION
) {
389 MemoryHob
= Hob
.MemoryAllocation
;
390 for (NextHob
.Raw
= PrivateData
->HobList
.Raw
; !END_OF_HOB_LIST (NextHob
); NextHob
.Raw
= GET_NEXT_HOB (NextHob
)) {
392 // See if this is a resource descriptor HOB
394 if (GET_HOB_TYPE (NextHob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
395 NextResourceHob
= NextHob
.ResourceDescriptor
;
397 // If range described in this HOB is not system memory or higher than MAX_ADDRESS, ignored.
399 if ((NextResourceHob
->ResourceType
!= EFI_RESOURCE_SYSTEM_MEMORY
) || (NextResourceHob
->PhysicalStart
+ NextResourceHob
->ResourceLength
> MAX_ADDRESS
)) {
404 // If the range describe in memory allocation HOB belongs to the memory range described by the resource HOB
406 if ((MemoryHob
->AllocDescriptor
.MemoryBaseAddress
>= NextResourceHob
->PhysicalStart
) &&
407 (MemoryHob
->AllocDescriptor
.MemoryBaseAddress
+ MemoryHob
->AllocDescriptor
.MemoryLength
<= NextResourceHob
->PhysicalStart
+ NextResourceHob
->ResourceLength
))
410 // Build separate resource HOB for this allocated range
412 if (MemoryHob
->AllocDescriptor
.MemoryBaseAddress
> NextResourceHob
->PhysicalStart
) {
413 BuildResourceDescriptorHob (
414 EFI_RESOURCE_SYSTEM_MEMORY
,
415 NextResourceHob
->ResourceAttribute
,
416 NextResourceHob
->PhysicalStart
,
417 (MemoryHob
->AllocDescriptor
.MemoryBaseAddress
- NextResourceHob
->PhysicalStart
)
421 if (MemoryHob
->AllocDescriptor
.MemoryBaseAddress
+ MemoryHob
->AllocDescriptor
.MemoryLength
< NextResourceHob
->PhysicalStart
+ NextResourceHob
->ResourceLength
) {
422 BuildResourceDescriptorHob (
423 EFI_RESOURCE_SYSTEM_MEMORY
,
424 NextResourceHob
->ResourceAttribute
,
425 MemoryHob
->AllocDescriptor
.MemoryBaseAddress
+ MemoryHob
->AllocDescriptor
.MemoryLength
,
426 (NextResourceHob
->PhysicalStart
+ NextResourceHob
->ResourceLength
-(MemoryHob
->AllocDescriptor
.MemoryBaseAddress
+ MemoryHob
->AllocDescriptor
.MemoryLength
))
430 NextResourceHob
->PhysicalStart
= MemoryHob
->AllocDescriptor
.MemoryBaseAddress
;
431 NextResourceHob
->ResourceLength
= MemoryHob
->AllocDescriptor
.MemoryLength
;
440 // Try to find and validate the TOP address.
442 if ((INT64
)PcdGet64 (PcdLoadModuleAtFixAddressEnable
) > 0 ) {
444 // The LMFA feature is enabled as load module at fixed absolute address.
446 TopLoadingAddress
= (EFI_PHYSICAL_ADDRESS
)PcdGet64 (PcdLoadModuleAtFixAddressEnable
);
447 DEBUG ((DEBUG_INFO
, "LOADING MODULE FIXED INFO: Loading module at fixed absolute address.\n"));
449 // validate the Address. Loop the resource descriptor HOB to make sure the address is in valid memory range
451 if ((TopLoadingAddress
& EFI_PAGE_MASK
) != 0) {
452 DEBUG ((DEBUG_INFO
, "LOADING MODULE FIXED ERROR:Top Address 0x%lx is invalid since top address should be page align. \n", TopLoadingAddress
));
457 // Search for a memory region that is below MAX_ADDRESS and in which TopLoadingAddress lies
459 for (Hob
.Raw
= PrivateData
->HobList
.Raw
; !END_OF_HOB_LIST (Hob
); Hob
.Raw
= GET_NEXT_HOB (Hob
)) {
461 // See if this is a resource descriptor HOB
463 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
464 ResourceHob
= Hob
.ResourceDescriptor
;
466 // See if this resource descriptor HOB describes tested system memory below MAX_ADDRESS
468 if ((ResourceHob
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
) &&
469 (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
<= MAX_ADDRESS
))
472 // See if Top address specified by user is valid.
474 if ((ResourceHob
->PhysicalStart
+ TotalReservedMemorySize
< TopLoadingAddress
) &&
475 ((ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
- MINIMUM_INITIAL_MEMORY_SIZE
) >= TopLoadingAddress
) &&
476 PeiLoadFixAddressIsMemoryRangeAvailable (PrivateData
, ResourceHob
))
478 CurrentResourceHob
= ResourceHob
;
486 if (CurrentResourceHob
!= NULL
) {
487 DEBUG ((DEBUG_INFO
, "LOADING MODULE FIXED INFO:Top Address 0x%lx is valid \n", TopLoadingAddress
));
488 TopLoadingAddress
+= MINIMUM_INITIAL_MEMORY_SIZE
;
490 DEBUG ((DEBUG_INFO
, "LOADING MODULE FIXED ERROR:Top Address 0x%lx is invalid \n", TopLoadingAddress
));
491 DEBUG ((DEBUG_INFO
, "LOADING MODULE FIXED ERROR:The recommended Top Address for the platform is: \n"));
493 // Print the recommended Top address range.
495 for (Hob
.Raw
= PrivateData
->HobList
.Raw
; !END_OF_HOB_LIST (Hob
); Hob
.Raw
= GET_NEXT_HOB (Hob
)) {
497 // See if this is a resource descriptor HOB
499 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
500 ResourceHob
= Hob
.ResourceDescriptor
;
502 // See if this resource descriptor HOB describes tested system memory below MAX_ADDRESS
504 if ((ResourceHob
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
) &&
505 (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
<= MAX_ADDRESS
))
508 // See if Top address specified by user is valid.
510 if ((ResourceHob
->ResourceLength
> TotalReservedMemorySize
) && PeiLoadFixAddressIsMemoryRangeAvailable (PrivateData
, ResourceHob
)) {
514 (ResourceHob
->PhysicalStart
+ TotalReservedMemorySize
-MINIMUM_INITIAL_MEMORY_SIZE
),
515 (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
-MINIMUM_INITIAL_MEMORY_SIZE
)
530 // The LMFA feature is enabled as load module at fixed offset relative to TOLM
531 // Parse the Hob list to find the topest available memory. Generally it is (TOLM - TSEG)
534 // Search for a tested memory region that is below MAX_ADDRESS
536 for (Hob
.Raw
= PrivateData
->HobList
.Raw
; !END_OF_HOB_LIST (Hob
); Hob
.Raw
= GET_NEXT_HOB (Hob
)) {
538 // See if this is a resource descriptor HOB
540 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
541 ResourceHob
= Hob
.ResourceDescriptor
;
543 // See if this resource descriptor HOB describes tested system memory below MAX_ADDRESS
545 if ((ResourceHob
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
) &&
546 (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
<= MAX_ADDRESS
) &&
547 (ResourceHob
->ResourceLength
> TotalReservedMemorySize
) && PeiLoadFixAddressIsMemoryRangeAvailable (PrivateData
, ResourceHob
))
550 // See if this is the highest largest system memory region below MaxAddress
552 if (ResourceHob
->PhysicalStart
> HighAddress
) {
553 CurrentResourceHob
= ResourceHob
;
555 HighAddress
= CurrentResourceHob
->PhysicalStart
;
561 if (CurrentResourceHob
== NULL
) {
562 DEBUG ((DEBUG_INFO
, "LOADING MODULE FIXED ERROR:The System Memory is too small\n"));
569 TopLoadingAddress
= CurrentResourceHob
->PhysicalStart
+ CurrentResourceHob
->ResourceLength
;
573 if (CurrentResourceHob
!= NULL
) {
575 // rebuild resource HOB for PEI memory and reserved memory
577 BuildResourceDescriptorHob (
578 EFI_RESOURCE_SYSTEM_MEMORY
,
580 EFI_RESOURCE_ATTRIBUTE_PRESENT
|
581 EFI_RESOURCE_ATTRIBUTE_INITIALIZED
|
582 EFI_RESOURCE_ATTRIBUTE_TESTED
|
583 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE
|
584 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE
|
585 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE
|
586 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
588 (TopLoadingAddress
- TotalReservedMemorySize
),
589 TotalReservedMemorySize
592 // rebuild resource for the remain memory if necessary
594 if (CurrentResourceHob
->PhysicalStart
< TopLoadingAddress
- TotalReservedMemorySize
) {
595 BuildResourceDescriptorHob (
596 EFI_RESOURCE_SYSTEM_MEMORY
,
598 EFI_RESOURCE_ATTRIBUTE_PRESENT
|
599 EFI_RESOURCE_ATTRIBUTE_INITIALIZED
|
600 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE
|
601 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE
|
602 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE
|
603 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
605 CurrentResourceHob
->PhysicalStart
,
606 (TopLoadingAddress
- TotalReservedMemorySize
- CurrentResourceHob
->PhysicalStart
)
610 if (CurrentResourceHob
->PhysicalStart
+ CurrentResourceHob
->ResourceLength
> TopLoadingAddress
) {
611 BuildResourceDescriptorHob (
612 EFI_RESOURCE_SYSTEM_MEMORY
,
614 EFI_RESOURCE_ATTRIBUTE_PRESENT
|
615 EFI_RESOURCE_ATTRIBUTE_INITIALIZED
|
616 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE
|
617 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE
|
618 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE
|
619 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
622 (CurrentResourceHob
->PhysicalStart
+ CurrentResourceHob
->ResourceLength
- TopLoadingAddress
)
627 // Delete CurrentHob by marking it as unused since the memory range described by is rebuilt.
629 GET_HOB_TYPE (CurrentHob
) = EFI_HOB_TYPE_UNUSED
;
633 // Cache the top address for Loading Module at Fixed Address feature
635 PrivateData
->LoadModuleAtFixAddressTopAddress
= TopLoadingAddress
- MINIMUM_INITIAL_MEMORY_SIZE
;
636 DEBUG ((DEBUG_INFO
, "LOADING MODULE FIXED INFO: Top address = 0x%lx\n", PrivateData
->LoadModuleAtFixAddressTopAddress
));
638 // reinstall the PEI memory relative to TopLoadingAddress
640 PrivateData
->PhysicalMemoryBegin
= TopLoadingAddress
- TotalReservedMemorySize
;
641 PrivateData
->FreePhysicalMemoryTop
= PrivateData
->PhysicalMemoryBegin
+ PeiMemorySize
;
645 This routine is invoked in switch stack as PeiCore Entry.
647 @param SecCoreData Points to a data structure containing information about the PEI core's operating
648 environment, such as the size and location of temporary RAM, the stack location and
650 @param Private Pointer to old core data that is used to initialize the
656 IN CONST EFI_SEC_PEI_HAND_OFF
*SecCoreData
,
657 IN PEI_CORE_INSTANCE
*Private
663 PeiCore (SecCoreData
, NULL
, Private
);
667 Check SwitchStackSignal and switch stack if SwitchStackSignal is TRUE.
669 @param[in] SecCoreData Points to a data structure containing information about the PEI core's operating
670 environment, such as the size and location of temporary RAM, the stack location and
672 @param[in] Private Pointer to the private data passed in from caller.
676 PeiCheckAndSwitchStack (
677 IN CONST EFI_SEC_PEI_HAND_OFF
*SecCoreData
,
678 IN PEI_CORE_INSTANCE
*Private
681 VOID
*LoadFixPeiCodeBegin
;
683 CONST EFI_PEI_SERVICES
**PeiServices
;
685 EFI_PHYSICAL_ADDRESS TopOfOldStack
;
686 EFI_PHYSICAL_ADDRESS TopOfNewStack
;
688 BOOLEAN StackOffsetPositive
;
689 EFI_PHYSICAL_ADDRESS TemporaryRamBase
;
690 UINTN TemporaryRamSize
;
691 UINTN TemporaryStackSize
;
692 VOID
*TemporaryStackBase
;
693 UINTN PeiTemporaryRamSize
;
694 VOID
*PeiTemporaryRamBase
;
695 EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI
*TemporaryRamSupportPpi
;
696 EFI_PHYSICAL_ADDRESS BaseOfNewHeap
;
697 EFI_PHYSICAL_ADDRESS HoleMemBase
;
699 UINTN HeapTemporaryRamSize
;
700 EFI_PHYSICAL_ADDRESS TempBase1
;
702 EFI_PHYSICAL_ADDRESS TempBase2
;
706 PeiServices
= (CONST EFI_PEI_SERVICES
**)&Private
->Ps
;
708 if (Private
->SwitchStackSignal
) {
710 // Before switch stack from temporary memory to permanent memory, calculate the heap and stack
711 // usage in temporary memory for debugging.
714 UINT32
*StackPointer
;
715 EFI_PEI_HOB_POINTERS Hob
;
717 for ( StackPointer
= (UINT32
*)SecCoreData
->StackBase
;
718 (StackPointer
< (UINT32
*)((UINTN
)SecCoreData
->StackBase
+ SecCoreData
->StackSize
)) \
719 && (*StackPointer
== PcdGet32 (PcdInitValueInTempStack
));
724 DEBUG ((DEBUG_INFO
, "Temp Stack : BaseAddress=0x%p Length=0x%X\n", SecCoreData
->StackBase
, (UINT32
)SecCoreData
->StackSize
));
725 DEBUG ((DEBUG_INFO
, "Temp Heap : BaseAddress=0x%p Length=0x%X\n", SecCoreData
->PeiTemporaryRamBase
, (UINT32
)SecCoreData
->PeiTemporaryRamSize
));
726 DEBUG ((DEBUG_INFO
, "Total temporary memory: %d bytes.\n", (UINT32
)SecCoreData
->TemporaryRamSize
));
729 " temporary memory stack ever used: %d bytes.\n",
730 (UINT32
)(SecCoreData
->StackSize
- ((UINTN
)StackPointer
- (UINTN
)SecCoreData
->StackBase
))
734 " temporary memory heap used for HobList: %d bytes.\n",
735 (UINT32
)((UINTN
)Private
->HobList
.HandoffInformationTable
->EfiFreeMemoryBottom
- (UINTN
)Private
->HobList
.Raw
)
739 " temporary memory heap occupied by memory pages: %d bytes.\n",
740 (UINT32
)(UINTN
)(Private
->HobList
.HandoffInformationTable
->EfiMemoryTop
- Private
->HobList
.HandoffInformationTable
->EfiFreeMemoryTop
)
742 for (Hob
.Raw
= Private
->HobList
.Raw
; !END_OF_HOB_LIST (Hob
); Hob
.Raw
= GET_NEXT_HOB (Hob
)) {
743 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_MEMORY_ALLOCATION
) {
746 "Memory Allocation 0x%08x 0x%0lx - 0x%0lx\n", \
747 Hob
.MemoryAllocation
->AllocDescriptor
.MemoryType
, \
748 Hob
.MemoryAllocation
->AllocDescriptor
.MemoryBaseAddress
, \
749 Hob
.MemoryAllocation
->AllocDescriptor
.MemoryBaseAddress
+ Hob
.MemoryAllocation
->AllocDescriptor
.MemoryLength
- 1
756 if ((PcdGet64 (PcdLoadModuleAtFixAddressEnable
) != 0) && (Private
->HobList
.HandoffInformationTable
->BootMode
!= BOOT_ON_S3_RESUME
)) {
758 // Loading Module at Fixed Address is enabled
760 PeiLoadFixAddressHook (Private
);
763 // If Loading Module at Fixed Address is enabled, Allocating memory range for Pei code range.
765 LoadFixPeiCodeBegin
= AllocatePages ((UINTN
)PcdGet32 (PcdLoadFixAddressPeiCodePageNumber
));
766 DEBUG ((DEBUG_INFO
, "LOADING MODULE FIXED INFO: PeiCodeBegin = 0x%lX, PeiCodeTop= 0x%lX\n", (UINT64
)(UINTN
)LoadFixPeiCodeBegin
, (UINT64
)((UINTN
)LoadFixPeiCodeBegin
+ PcdGet32 (PcdLoadFixAddressPeiCodePageNumber
) * EFI_PAGE_SIZE
)));
770 // Reserve the size of new stack at bottom of physical memory
772 // The size of new stack in permanent memory must be the same size
773 // or larger than the size of old stack in temporary memory.
774 // But if new stack is smaller than the size of old stack, we also reserve
775 // the size of old stack at bottom of permanent memory.
777 NewStackSize
= RShiftU64 (Private
->PhysicalMemoryLength
, 1);
778 NewStackSize
= ALIGN_VALUE (NewStackSize
, EFI_PAGE_SIZE
);
779 NewStackSize
= MIN (PcdGet32 (PcdPeiCoreMaxPeiStackSize
), NewStackSize
);
780 DEBUG ((DEBUG_INFO
, "Old Stack size %d, New stack size %d\n", (UINT32
)SecCoreData
->StackSize
, (UINT32
)NewStackSize
));
781 ASSERT (NewStackSize
>= SecCoreData
->StackSize
);
784 // Calculate stack offset and heap offset between temporary memory and new permanent
785 // memory separately.
787 TopOfOldStack
= (UINTN
)SecCoreData
->StackBase
+ SecCoreData
->StackSize
;
788 TopOfNewStack
= Private
->PhysicalMemoryBegin
+ NewStackSize
;
789 if (TopOfNewStack
>= TopOfOldStack
) {
790 StackOffsetPositive
= TRUE
;
791 StackOffset
= (UINTN
)(TopOfNewStack
- TopOfOldStack
);
793 StackOffsetPositive
= FALSE
;
794 StackOffset
= (UINTN
)(TopOfOldStack
- TopOfNewStack
);
797 Private
->StackOffsetPositive
= StackOffsetPositive
;
798 Private
->StackOffset
= StackOffset
;
801 // Build Stack HOB that describes the permanent memory stack
803 DEBUG ((DEBUG_INFO
, "Stack Hob: BaseAddress=0x%lX Length=0x%lX\n", TopOfNewStack
- NewStackSize
, NewStackSize
));
804 BuildStackHob (TopOfNewStack
- NewStackSize
, NewStackSize
);
807 // Cache information from SecCoreData into locals before SecCoreData is converted to a permanent memory address
809 TemporaryRamBase
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)SecCoreData
->TemporaryRamBase
;
810 TemporaryRamSize
= SecCoreData
->TemporaryRamSize
;
811 TemporaryStackSize
= SecCoreData
->StackSize
;
812 TemporaryStackBase
= SecCoreData
->StackBase
;
813 PeiTemporaryRamSize
= SecCoreData
->PeiTemporaryRamSize
;
814 PeiTemporaryRamBase
= SecCoreData
->PeiTemporaryRamBase
;
817 // TemporaryRamSupportPpi is produced by platform's SEC
819 Status
= PeiServicesLocatePpi (
820 &gEfiTemporaryRamSupportPpiGuid
,
823 (VOID
**)&TemporaryRamSupportPpi
825 if (!EFI_ERROR (Status
)) {
829 BaseOfNewHeap
= TopOfNewStack
;
830 if (BaseOfNewHeap
>= (UINTN
)SecCoreData
->PeiTemporaryRamBase
) {
831 Private
->HeapOffsetPositive
= TRUE
;
832 Private
->HeapOffset
= (UINTN
)(BaseOfNewHeap
- (UINTN
)SecCoreData
->PeiTemporaryRamBase
);
834 Private
->HeapOffsetPositive
= FALSE
;
835 Private
->HeapOffset
= (UINTN
)((UINTN
)SecCoreData
->PeiTemporaryRamBase
- BaseOfNewHeap
);
838 DEBUG ((DEBUG_INFO
, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (UINT64
)Private
->HeapOffset
, (UINT64
)Private
->StackOffset
));
841 // Calculate new HandOffTable and PrivateData address in permanent memory's stack
843 if (StackOffsetPositive
) {
844 SecCoreData
= (CONST EFI_SEC_PEI_HAND_OFF
*)((UINTN
)(VOID
*)SecCoreData
+ StackOffset
);
845 Private
= (PEI_CORE_INSTANCE
*)((UINTN
)(VOID
*)Private
+ StackOffset
);
847 SecCoreData
= (CONST EFI_SEC_PEI_HAND_OFF
*)((UINTN
)(VOID
*)SecCoreData
- StackOffset
);
848 Private
= (PEI_CORE_INSTANCE
*)((UINTN
)(VOID
*)Private
- StackOffset
);
852 // Temporary Ram Support PPI is provided by platform, it will copy
853 // temporary memory to permanent memory and do stack switching.
854 // After invoking Temporary Ram Support PPI, the following code's
855 // stack is in permanent memory.
857 TemporaryRamSupportPpi
->TemporaryRamMigration (
860 (EFI_PHYSICAL_ADDRESS
)(UINTN
)(TopOfNewStack
- TemporaryStackSize
),
865 // Migrate memory pages allocated in pre-memory phase.
866 // It could not be called before calling TemporaryRamSupportPpi->TemporaryRamMigration()
867 // as the migrated memory pages may be overridden by TemporaryRamSupportPpi->TemporaryRamMigration().
869 MigrateMemoryPages (Private
, TRUE
);
874 PeiCore (SecCoreData
, NULL
, Private
);
877 // Migrate memory pages allocated in pre-memory phase.
879 MigrateMemoryPages (Private
, FALSE
);
882 // Migrate the PEI Services Table pointer from temporary RAM to permanent RAM.
884 MigratePeiServicesTablePointer ();
889 BaseOfNewHeap
= TopOfNewStack
;
890 HoleMemBase
= TopOfNewStack
;
891 HoleMemSize
= TemporaryRamSize
- PeiTemporaryRamSize
- TemporaryStackSize
;
892 if (HoleMemSize
!= 0) {
894 // Make sure HOB List start address is 8 byte alignment.
896 BaseOfNewHeap
= ALIGN_VALUE (BaseOfNewHeap
+ HoleMemSize
, 8);
899 if (BaseOfNewHeap
>= (UINTN
)SecCoreData
->PeiTemporaryRamBase
) {
900 Private
->HeapOffsetPositive
= TRUE
;
901 Private
->HeapOffset
= (UINTN
)(BaseOfNewHeap
- (UINTN
)SecCoreData
->PeiTemporaryRamBase
);
903 Private
->HeapOffsetPositive
= FALSE
;
904 Private
->HeapOffset
= (UINTN
)((UINTN
)SecCoreData
->PeiTemporaryRamBase
- BaseOfNewHeap
);
907 DEBUG ((DEBUG_INFO
, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (UINT64
)Private
->HeapOffset
, (UINT64
)Private
->StackOffset
));
912 HeapTemporaryRamSize
= (UINTN
)(Private
->HobList
.HandoffInformationTable
->EfiFreeMemoryBottom
- Private
->HobList
.HandoffInformationTable
->EfiMemoryBottom
);
913 ASSERT (BaseOfNewHeap
+ HeapTemporaryRamSize
<= Private
->FreePhysicalMemoryTop
);
914 CopyMem ((UINT8
*)(UINTN
)BaseOfNewHeap
, PeiTemporaryRamBase
, HeapTemporaryRamSize
);
919 CopyMem ((UINT8
*)(UINTN
)(TopOfNewStack
- TemporaryStackSize
), TemporaryStackBase
, TemporaryStackSize
);
922 // Copy Hole Range Data
924 if (HoleMemSize
!= 0) {
928 if (PeiTemporaryRamBase
< TemporaryStackBase
) {
929 TempBase1
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)PeiTemporaryRamBase
;
930 TempSize1
= PeiTemporaryRamSize
;
931 TempBase2
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)TemporaryStackBase
;
932 TempSize2
= TemporaryStackSize
;
934 TempBase1
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)TemporaryStackBase
;
935 TempSize1
= TemporaryStackSize
;
936 TempBase2
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)PeiTemporaryRamBase
;
937 TempSize2
= PeiTemporaryRamSize
;
940 if (TemporaryRamBase
< TempBase1
) {
941 Private
->HoleData
[0].Base
= TemporaryRamBase
;
942 Private
->HoleData
[0].Size
= (UINTN
)(TempBase1
- TemporaryRamBase
);
945 if (TempBase1
+ TempSize1
< TempBase2
) {
946 Private
->HoleData
[1].Base
= TempBase1
+ TempSize1
;
947 Private
->HoleData
[1].Size
= (UINTN
)(TempBase2
- TempBase1
- TempSize1
);
950 if (TempBase2
+ TempSize2
< TemporaryRamBase
+ TemporaryRamSize
) {
951 Private
->HoleData
[2].Base
= TempBase2
+ TempSize2
;
952 Private
->HoleData
[2].Size
= (UINTN
)(TemporaryRamBase
+ TemporaryRamSize
- TempBase2
- TempSize2
);
956 // Copy Hole Range data.
958 for (Index
= 0; Index
< HOLE_MAX_NUMBER
; Index
++) {
959 if (Private
->HoleData
[Index
].Size
> 0) {
960 if (HoleMemBase
> Private
->HoleData
[Index
].Base
) {
961 Private
->HoleData
[Index
].OffsetPositive
= TRUE
;
962 Private
->HoleData
[Index
].Offset
= (UINTN
)(HoleMemBase
- Private
->HoleData
[Index
].Base
);
964 Private
->HoleData
[Index
].OffsetPositive
= FALSE
;
965 Private
->HoleData
[Index
].Offset
= (UINTN
)(Private
->HoleData
[Index
].Base
- HoleMemBase
);
968 CopyMem ((VOID
*)(UINTN
)HoleMemBase
, (VOID
*)(UINTN
)Private
->HoleData
[Index
].Base
, Private
->HoleData
[Index
].Size
);
969 HoleMemBase
= HoleMemBase
+ Private
->HoleData
[Index
].Size
;
978 (SWITCH_STACK_ENTRY_POINT
)(UINTN
)PeiCoreEntry
,
981 (VOID
*)(UINTN
)TopOfNewStack
986 // Code should not come here
993 Migrate a PEIM from temporary RAM to permanent memory.
995 @param PeimFileHandle Pointer to the FFS file header of the image.
996 @param MigratedFileHandle Pointer to the FFS file header of the migrated image.
998 @retval EFI_SUCCESS Successfully migrated the PEIM to permanent memory.
1004 IN EFI_PEI_FILE_HANDLE FileHandle
,
1005 IN EFI_PEI_FILE_HANDLE MigratedFileHandle
1009 EFI_FFS_FILE_HEADER
*FileHeader
;
1015 Status
= EFI_SUCCESS
;
1017 FileHeader
= (EFI_FFS_FILE_HEADER
*)FileHandle
;
1018 ASSERT (!IS_FFS_FILE2 (FileHeader
));
1020 ImageAddress
= NULL
;
1021 PeiGetPe32Data (MigratedFileHandle
, &ImageAddress
);
1022 if (ImageAddress
!= NULL
) {
1023 DEBUG_CODE_BEGIN ();
1024 AsciiString
= PeCoffLoaderGetPdbPointer (ImageAddress
);
1025 for (Index
= 0; AsciiString
[Index
] != 0; Index
++) {
1026 if ((AsciiString
[Index
] == '\\') || (AsciiString
[Index
] == '/')) {
1027 AsciiString
= AsciiString
+ Index
+ 1;
1029 } else if (AsciiString
[Index
] == '.') {
1030 AsciiString
[Index
] = 0;
1034 DEBUG ((DEBUG_VERBOSE
, "%a", AsciiString
));
1037 Pe32Data
= (VOID
*)((UINTN
)ImageAddress
- (UINTN
)MigratedFileHandle
+ (UINTN
)FileHandle
);
1038 Status
= LoadAndRelocatePeCoffImageInPlace (Pe32Data
, ImageAddress
);
1039 ASSERT_EFI_ERROR (Status
);
1046 Migrate Status Code Callback function pointers inside an FV from temporary memory to permanent memory.
1048 @param OrgFvHandle Address of FV handle in temporary memory.
1049 @param FvHandle Address of FV handle in permanent memory.
1050 @param FvSize Size of the FV.
1054 ConvertStatusCodeCallbacks (
1055 IN UINTN OrgFvHandle
,
1060 EFI_PEI_HOB_POINTERS Hob
;
1061 UINTN
*NumberOfEntries
;
1062 UINTN
*CallbackEntry
;
1065 Hob
.Raw
= GetFirstGuidHob (&gStatusCodeCallbackGuid
);
1066 while (Hob
.Raw
!= NULL
) {
1067 NumberOfEntries
= GET_GUID_HOB_DATA (Hob
);
1068 CallbackEntry
= NumberOfEntries
+ 1;
1069 for (Index
= 0; Index
< *NumberOfEntries
; Index
++) {
1070 if (((VOID
*)CallbackEntry
[Index
]) != NULL
) {
1071 if ((CallbackEntry
[Index
] >= OrgFvHandle
) && (CallbackEntry
[Index
] < (OrgFvHandle
+ FvSize
))) {
1074 "Migrating CallbackEntry[%Lu] from 0x%0*Lx to ",
1076 (sizeof CallbackEntry
[Index
]) * 2,
1077 (UINT64
)CallbackEntry
[Index
]
1079 if (OrgFvHandle
> FvHandle
) {
1080 CallbackEntry
[Index
] = CallbackEntry
[Index
] - (OrgFvHandle
- FvHandle
);
1082 CallbackEntry
[Index
] = CallbackEntry
[Index
] + (FvHandle
- OrgFvHandle
);
1088 (sizeof CallbackEntry
[Index
]) * 2,
1089 (UINT64
)CallbackEntry
[Index
]
1095 Hob
.Raw
= GET_NEXT_HOB (Hob
);
1096 Hob
.Raw
= GetNextGuidHob (&gStatusCodeCallbackGuid
, Hob
.Raw
);
1101 Migrates PEIMs in the given firmware volume.
1103 @param Private Pointer to the PeiCore's private data structure.
1104 @param FvIndex The firmware volume index to migrate.
1105 @param OrgFvHandle The handle to the firmware volume in temporary memory.
1106 @param FvHandle The handle to the firmware volume in permanent memory.
1108 @retval EFI_SUCCESS The PEIMs in the FV were migrated successfully
1109 @retval EFI_INVALID_PARAMETER The Private pointer is NULL or FvCount is invalid.
1115 IN PEI_CORE_INSTANCE
*Private
,
1117 IN UINTN OrgFvHandle
,
1122 volatile UINTN FileIndex
;
1123 EFI_PEI_FILE_HANDLE MigratedFileHandle
;
1124 EFI_PEI_FILE_HANDLE FileHandle
;
1126 if ((Private
== NULL
) || (FvIndex
>= Private
->FvCount
)) {
1127 return EFI_INVALID_PARAMETER
;
1130 if (Private
->Fv
[FvIndex
].ScanFv
) {
1131 for (FileIndex
= 0; FileIndex
< Private
->Fv
[FvIndex
].PeimCount
; FileIndex
++) {
1132 if (Private
->Fv
[FvIndex
].FvFileHandles
[FileIndex
] != NULL
) {
1133 FileHandle
= Private
->Fv
[FvIndex
].FvFileHandles
[FileIndex
];
1135 MigratedFileHandle
= (EFI_PEI_FILE_HANDLE
)((UINTN
)FileHandle
- OrgFvHandle
+ FvHandle
);
1137 DEBUG ((DEBUG_VERBOSE
, " Migrating FileHandle %2d ", FileIndex
));
1138 Status
= MigratePeim (FileHandle
, MigratedFileHandle
);
1139 DEBUG ((DEBUG_VERBOSE
, "\n"));
1140 ASSERT_EFI_ERROR (Status
);
1142 if (!EFI_ERROR (Status
)) {
1143 Private
->Fv
[FvIndex
].FvFileHandles
[FileIndex
] = MigratedFileHandle
;
1144 if (FvIndex
== Private
->CurrentPeimFvCount
) {
1145 Private
->CurrentFvFileHandles
[FileIndex
] = MigratedFileHandle
;
1156 Migrate FVs out of temporary RAM before the cache is flushed.
1158 @param Private PeiCore's private data structure
1159 @param SecCoreData Points to a data structure containing information about the PEI core's operating
1160 environment, such as the size and location of temporary RAM, the stack location and
1163 @retval EFI_SUCCESS Successfully migrated installed FVs from temporary RAM to permanent memory.
1164 @retval EFI_OUT_OF_RESOURCES Insufficient memory exists to allocate needed pages.
1170 IN PEI_CORE_INSTANCE
*Private
,
1171 IN CONST EFI_SEC_PEI_HAND_OFF
*SecCoreData
1175 volatile UINTN FvIndex
;
1176 volatile UINTN FvChildIndex
;
1177 UINTN ChildFvOffset
;
1178 EFI_PHYSICAL_ADDRESS FvHeaderAddress
;
1179 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
1180 EFI_FIRMWARE_VOLUME_HEADER
*ChildFvHeader
;
1181 EFI_FIRMWARE_VOLUME_HEADER
*MigratedFvHeader
;
1182 EFI_FIRMWARE_VOLUME_HEADER
*RawDataFvHeader
;
1183 EFI_FIRMWARE_VOLUME_HEADER
*MigratedChildFvHeader
;
1185 PEI_CORE_FV_HANDLE PeiCoreFvHandle
;
1186 EFI_PEI_CORE_FV_LOCATION_PPI
*PeiCoreFvLocationPpi
;
1187 EDKII_MIGRATED_FV_INFO MigratedFvInfo
;
1189 ASSERT (Private
->PeiMemoryInstalled
);
1191 DEBUG ((DEBUG_VERBOSE
, "Beginning evacuation of content in temporary RAM.\n"));
1194 // Migrate PPI Pointers of PEI_CORE from temporary memory to newly loaded PEI_CORE in permanent memory.
1196 Status
= PeiLocatePpi ((CONST EFI_PEI_SERVICES
**)&Private
->Ps
, &gEfiPeiCoreFvLocationPpiGuid
, 0, NULL
, (VOID
**)&PeiCoreFvLocationPpi
);
1197 if (!EFI_ERROR (Status
) && (PeiCoreFvLocationPpi
->PeiCoreFvLocation
!= NULL
)) {
1198 PeiCoreFvHandle
.FvHandle
= (EFI_PEI_FV_HANDLE
)PeiCoreFvLocationPpi
->PeiCoreFvLocation
;
1200 PeiCoreFvHandle
.FvHandle
= (EFI_PEI_FV_HANDLE
)SecCoreData
->BootFirmwareVolumeBase
;
1203 for (FvIndex
= 0; FvIndex
< Private
->FvCount
; FvIndex
++) {
1204 if (Private
->Fv
[FvIndex
].FvHandle
== PeiCoreFvHandle
.FvHandle
) {
1205 CopyMem (&PeiCoreFvHandle
, &Private
->Fv
[FvIndex
], sizeof (PEI_CORE_FV_HANDLE
));
1210 Status
= EFI_SUCCESS
;
1212 ConvertPeiCorePpiPointers (Private
, &PeiCoreFvHandle
);
1214 for (FvIndex
= 0; FvIndex
< Private
->FvCount
; FvIndex
++) {
1215 FvHeader
= Private
->Fv
[FvIndex
].FvHeader
;
1216 ASSERT (FvHeader
!= NULL
);
1217 ASSERT (FvIndex
< Private
->FvCount
);
1219 DEBUG ((DEBUG_VERBOSE
, "FV[%02d] at 0x%x.\n", FvIndex
, (UINTN
)FvHeader
));
1222 ((EFI_PHYSICAL_ADDRESS
)(UINTN
)FvHeader
>= Private
->PhysicalMemoryBegin
) &&
1223 (((EFI_PHYSICAL_ADDRESS
)(UINTN
)FvHeader
+ (FvHeader
->FvLength
- 1)) < Private
->FreePhysicalMemoryTop
)
1228 // Allocate page to save the rebased PEIMs, the PEIMs will get dispatched later.
1230 Status
= PeiServicesAllocatePages (
1231 EfiBootServicesCode
,
1232 EFI_SIZE_TO_PAGES ((UINTN
)FvHeader
->FvLength
),
1235 ASSERT_EFI_ERROR (Status
);
1236 MigratedFvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
)FvHeaderAddress
;
1239 // Allocate pool to save the raw PEIMs, which is used to keep consistent context across
1240 // multiple boot and PCR0 will keep the same no matter if the address of allocated page is changed.
1242 Status
= PeiServicesAllocatePages (
1243 EfiBootServicesCode
,
1244 EFI_SIZE_TO_PAGES ((UINTN
)FvHeader
->FvLength
),
1247 ASSERT_EFI_ERROR (Status
);
1248 RawDataFvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
)FvHeaderAddress
;
1252 " Migrating FV[%d] from 0x%08X to 0x%08X\n",
1255 (UINTN
)MigratedFvHeader
1259 // Copy the context to the rebased pages and raw pages, and create hob to save the
1260 // information. The MigratedFvInfo HOB will never be produced when
1261 // PcdMigrateTemporaryRamFirmwareVolumes is FALSE, because the PCD control the
1264 CopyMem (MigratedFvHeader
, FvHeader
, (UINTN
)FvHeader
->FvLength
);
1265 CopyMem (RawDataFvHeader
, MigratedFvHeader
, (UINTN
)FvHeader
->FvLength
);
1266 MigratedFvInfo
.FvOrgBase
= (UINT32
)(UINTN
)FvHeader
;
1267 MigratedFvInfo
.FvNewBase
= (UINT32
)(UINTN
)MigratedFvHeader
;
1268 MigratedFvInfo
.FvDataBase
= (UINT32
)(UINTN
)RawDataFvHeader
;
1269 MigratedFvInfo
.FvLength
= (UINT32
)(UINTN
)FvHeader
->FvLength
;
1270 BuildGuidDataHob (&gEdkiiMigratedFvInfoGuid
, &MigratedFvInfo
, sizeof (MigratedFvInfo
));
1273 // Migrate any children for this FV now
1275 for (FvChildIndex
= FvIndex
; FvChildIndex
< Private
->FvCount
; FvChildIndex
++) {
1276 ChildFvHeader
= Private
->Fv
[FvChildIndex
].FvHeader
;
1278 ((UINTN
)ChildFvHeader
> (UINTN
)FvHeader
) &&
1279 (((UINTN
)ChildFvHeader
+ ChildFvHeader
->FvLength
) < ((UINTN
)FvHeader
) + FvHeader
->FvLength
)
1282 DEBUG ((DEBUG_VERBOSE
, " Child FV[%02d] is being migrated.\n", FvChildIndex
));
1283 ChildFvOffset
= (UINTN
)ChildFvHeader
- (UINTN
)FvHeader
;
1284 DEBUG ((DEBUG_VERBOSE
, " Child FV offset = 0x%x.\n", ChildFvOffset
));
1285 MigratedChildFvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*)((UINTN
)MigratedFvHeader
+ ChildFvOffset
);
1286 Private
->Fv
[FvChildIndex
].FvHeader
= MigratedChildFvHeader
;
1287 Private
->Fv
[FvChildIndex
].FvHandle
= (EFI_PEI_FV_HANDLE
)MigratedChildFvHeader
;
1288 DEBUG ((DEBUG_VERBOSE
, " Child migrated FV header at 0x%x.\n", (UINTN
)MigratedChildFvHeader
));
1290 Status
= MigratePeimsInFv (Private
, FvChildIndex
, (UINTN
)ChildFvHeader
, (UINTN
)MigratedChildFvHeader
);
1291 ASSERT_EFI_ERROR (Status
);
1293 ConvertPpiPointersFv (
1295 (UINTN
)ChildFvHeader
,
1296 (UINTN
)MigratedChildFvHeader
,
1297 (UINTN
)ChildFvHeader
->FvLength
- 1
1300 ConvertStatusCodeCallbacks (
1301 (UINTN
)ChildFvHeader
,
1302 (UINTN
)MigratedChildFvHeader
,
1303 (UINTN
)ChildFvHeader
->FvLength
- 1
1306 ConvertFvHob (Private
, (UINTN
)ChildFvHeader
, (UINTN
)MigratedChildFvHeader
);
1310 Private
->Fv
[FvIndex
].FvHeader
= MigratedFvHeader
;
1311 Private
->Fv
[FvIndex
].FvHandle
= (EFI_PEI_FV_HANDLE
)MigratedFvHeader
;
1313 Status
= MigratePeimsInFv (Private
, FvIndex
, (UINTN
)FvHeader
, (UINTN
)MigratedFvHeader
);
1314 ASSERT_EFI_ERROR (Status
);
1316 ConvertPpiPointersFv (
1319 (UINTN
)MigratedFvHeader
,
1320 (UINTN
)FvHeader
->FvLength
- 1
1323 ConvertStatusCodeCallbacks (
1325 (UINTN
)MigratedFvHeader
,
1326 (UINTN
)FvHeader
->FvLength
- 1
1329 ConvertFvHob (Private
, (UINTN
)FvHeader
, (UINTN
)MigratedFvHeader
);
1333 RemoveFvHobsInTemporaryMemory (Private
);
1339 Conduct PEIM dispatch.
1341 @param SecCoreData Points to a data structure containing information about the PEI core's operating
1342 environment, such as the size and location of temporary RAM, the stack location and
1344 @param Private Pointer to the private data passed in from caller
1349 IN CONST EFI_SEC_PEI_HAND_OFF
*SecCoreData
,
1350 IN PEI_CORE_INSTANCE
*Private
1356 CONST EFI_PEI_SERVICES
**PeiServices
;
1357 EFI_PEI_FILE_HANDLE PeimFileHandle
;
1360 UINT32 AuthenticationState
;
1361 EFI_PHYSICAL_ADDRESS EntryPoint
;
1362 EFI_PEIM_ENTRY_POINT2 PeimEntryPoint
;
1363 UINTN SaveCurrentPeimCount
;
1364 UINTN SaveCurrentFvCount
;
1365 EFI_PEI_FILE_HANDLE SaveCurrentFileHandle
;
1366 EFI_FV_FILE_INFO FvFileInfo
;
1367 PEI_CORE_FV_HANDLE
*CoreFvHandle
;
1369 PeiServices
= (CONST EFI_PEI_SERVICES
**)&Private
->Ps
;
1370 PeimEntryPoint
= NULL
;
1371 PeimFileHandle
= NULL
;
1374 if ((Private
->PeiMemoryInstalled
) &&
1375 (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes
) ||
1376 (Private
->HobList
.HandoffInformationTable
->BootMode
!= BOOT_ON_S3_RESUME
) ||
1377 PcdGetBool (PcdShadowPeimOnS3Boot
))
1381 // Once real memory is available, shadow the RegisterForShadow modules. And meanwhile
1382 // update the modules' status from PEIM_STATE_REGISTER_FOR_SHADOW to PEIM_STATE_DONE.
1384 SaveCurrentPeimCount
= Private
->CurrentPeimCount
;
1385 SaveCurrentFvCount
= Private
->CurrentPeimFvCount
;
1386 SaveCurrentFileHandle
= Private
->CurrentFileHandle
;
1388 for (Index1
= 0; Index1
< Private
->FvCount
; Index1
++) {
1389 for (Index2
= 0; Index2
< Private
->Fv
[Index1
].PeimCount
; Index2
++) {
1390 if (Private
->Fv
[Index1
].PeimState
[Index2
] == PEIM_STATE_REGISTER_FOR_SHADOW
) {
1391 PeimFileHandle
= Private
->Fv
[Index1
].FvFileHandles
[Index2
];
1392 Private
->CurrentFileHandle
= PeimFileHandle
;
1393 Private
->CurrentPeimFvCount
= Index1
;
1394 Private
->CurrentPeimCount
= Index2
;
1395 Status
= PeiLoadImage (
1396 (CONST EFI_PEI_SERVICES
**)&Private
->Ps
,
1398 PEIM_STATE_REGISTER_FOR_SHADOW
,
1400 &AuthenticationState
1402 if (Status
== EFI_SUCCESS
) {
1404 // PEIM_STATE_REGISTER_FOR_SHADOW move to PEIM_STATE_DONE
1406 Private
->Fv
[Index1
].PeimState
[Index2
]++;
1408 // Call the PEIM entry point
1410 PeimEntryPoint
= (EFI_PEIM_ENTRY_POINT2
)(UINTN
)EntryPoint
;
1412 PERF_START_IMAGE_BEGIN (PeimFileHandle
);
1413 PeimEntryPoint (PeimFileHandle
, (const EFI_PEI_SERVICES
**)&Private
->Ps
);
1414 PERF_START_IMAGE_END (PeimFileHandle
);
1418 // Process the Notify list and dispatch any notifies for
1419 // newly installed PPIs.
1421 ProcessDispatchNotifyList (Private
);
1426 Private
->CurrentFileHandle
= SaveCurrentFileHandle
;
1427 Private
->CurrentPeimFvCount
= SaveCurrentFvCount
;
1428 Private
->CurrentPeimCount
= SaveCurrentPeimCount
;
1432 // This is the main dispatch loop. It will search known FVs for PEIMs and
1433 // attempt to dispatch them. If any PEIM gets dispatched through a single
1434 // pass of the dispatcher, it will start over from the BFV again to see
1435 // if any new PEIMs dependencies got satisfied. With a well ordered
1436 // FV where PEIMs are found in the order their dependencies are also
1437 // satisfied, this dispatcher should run only once.
1441 // In case that reenter PeiCore happens, the last pass record is still available.
1443 if (!Private
->PeimDispatcherReenter
) {
1444 Private
->PeimNeedingDispatch
= FALSE
;
1445 Private
->PeimDispatchOnThisPass
= FALSE
;
1447 Private
->PeimDispatcherReenter
= FALSE
;
1450 for (FvCount
= Private
->CurrentPeimFvCount
; FvCount
< Private
->FvCount
; FvCount
++) {
1451 CoreFvHandle
= FindNextCoreFvHandle (Private
, FvCount
);
1452 ASSERT (CoreFvHandle
!= NULL
);
1455 // If the FV has corresponding EFI_PEI_FIRMWARE_VOLUME_PPI instance, then dispatch it.
1457 if (CoreFvHandle
->FvPpi
== NULL
) {
1461 Private
->CurrentPeimFvCount
= FvCount
;
1463 if (Private
->CurrentPeimCount
== 0) {
1465 // When going through each FV, at first, search Apriori file to
1466 // reorder all PEIMs to ensure the PEIMs in Apriori file to get
1467 // dispatch at first.
1469 DiscoverPeimsAndOrderWithApriori (Private
, CoreFvHandle
);
1473 // Start to dispatch all modules within the current FV.
1475 for (PeimCount
= Private
->CurrentPeimCount
;
1476 PeimCount
< Private
->Fv
[FvCount
].PeimCount
;
1479 Private
->CurrentPeimCount
= PeimCount
;
1480 PeimFileHandle
= Private
->CurrentFileHandle
= Private
->CurrentFvFileHandles
[PeimCount
];
1482 if (Private
->Fv
[FvCount
].PeimState
[PeimCount
] == PEIM_STATE_NOT_DISPATCHED
) {
1483 if (!DepexSatisfied (Private
, PeimFileHandle
, PeimCount
)) {
1484 Private
->PeimNeedingDispatch
= TRUE
;
1486 Status
= CoreFvHandle
->FvPpi
->GetFileInfo (CoreFvHandle
->FvPpi
, PeimFileHandle
, &FvFileInfo
);
1487 ASSERT_EFI_ERROR (Status
);
1488 if (FvFileInfo
.FileType
== EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
) {
1490 // For FV type file, Produce new FvInfo PPI and FV HOB
1492 Status
= ProcessFvFile (Private
, &Private
->Fv
[FvCount
], PeimFileHandle
);
1493 if (Status
== EFI_SUCCESS
) {
1495 // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED
1497 Private
->Fv
[FvCount
].PeimState
[PeimCount
]++;
1498 Private
->PeimDispatchOnThisPass
= TRUE
;
1501 // The related GuidedSectionExtraction/Decompress PPI for the
1502 // encapsulated FV image section may be installed in the rest
1503 // of this do-while loop, so need to make another pass.
1505 Private
->PeimNeedingDispatch
= TRUE
;
1509 // For PEIM driver, Load its entry point
1511 Status
= PeiLoadImage (
1514 PEIM_STATE_NOT_DISPATCHED
,
1516 &AuthenticationState
1518 if (Status
== EFI_SUCCESS
) {
1520 // The PEIM has its dependencies satisfied, and its entry point
1521 // has been found, so invoke it.
1523 PERF_START_IMAGE_BEGIN (PeimFileHandle
);
1525 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
1527 (EFI_SOFTWARE_PEI_CORE
| EFI_SW_PC_INIT_BEGIN
),
1528 (VOID
*)(&PeimFileHandle
),
1529 sizeof (PeimFileHandle
)
1532 Status
= VerifyPeim (Private
, CoreFvHandle
->FvHandle
, PeimFileHandle
, AuthenticationState
);
1533 if (Status
!= EFI_SECURITY_VIOLATION
) {
1535 // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED
1537 Private
->Fv
[FvCount
].PeimState
[PeimCount
]++;
1539 // Call the PEIM entry point for PEIM driver
1541 PeimEntryPoint
= (EFI_PEIM_ENTRY_POINT2
)(UINTN
)EntryPoint
;
1542 PeimEntryPoint (PeimFileHandle
, (const EFI_PEI_SERVICES
**)PeiServices
);
1543 Private
->PeimDispatchOnThisPass
= TRUE
;
1546 // The related GuidedSectionExtraction PPI for the
1547 // signed PEIM image section may be installed in the rest
1548 // of this do-while loop, so need to make another pass.
1550 Private
->PeimNeedingDispatch
= TRUE
;
1553 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
1555 (EFI_SOFTWARE_PEI_CORE
| EFI_SW_PC_INIT_END
),
1556 (VOID
*)(&PeimFileHandle
),
1557 sizeof (PeimFileHandle
)
1559 PERF_START_IMAGE_END (PeimFileHandle
);
1563 PeiCheckAndSwitchStack (SecCoreData
, Private
);
1566 // Process the Notify list and dispatch any notifies for
1567 // newly installed PPIs.
1569 ProcessDispatchNotifyList (Private
);
1572 // Recheck SwitchStackSignal after ProcessDispatchNotifyList()
1573 // in case PeiInstallPeiMemory() is done in a callback with
1574 // EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH.
1576 PeiCheckAndSwitchStack (SecCoreData
, Private
);
1578 if ((Private
->PeiMemoryInstalled
) && (Private
->Fv
[FvCount
].PeimState
[PeimCount
] == PEIM_STATE_REGISTER_FOR_SHADOW
) && \
1579 (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes
) ||
1580 (Private
->HobList
.HandoffInformationTable
->BootMode
!= BOOT_ON_S3_RESUME
) ||
1581 PcdGetBool (PcdShadowPeimOnS3Boot
))
1585 // If memory is available we shadow images by default for performance reasons.
1586 // We call the entry point a 2nd time so the module knows it's shadowed.
1588 // PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0);
1589 if ((Private
->HobList
.HandoffInformationTable
->BootMode
!= BOOT_ON_S3_RESUME
) && !PcdGetBool (PcdShadowPeimOnBoot
) &&
1590 !PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes
))
1593 // Load PEIM into Memory for Register for shadow PEIM.
1595 Status
= PeiLoadImage (
1598 PEIM_STATE_REGISTER_FOR_SHADOW
,
1600 &AuthenticationState
1602 if (Status
== EFI_SUCCESS
) {
1603 PeimEntryPoint
= (EFI_PEIM_ENTRY_POINT2
)(UINTN
)EntryPoint
;
1607 ASSERT (PeimEntryPoint
!= NULL
);
1608 PeimEntryPoint (PeimFileHandle
, (const EFI_PEI_SERVICES
**)PeiServices
);
1609 // PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0);
1612 // PEIM_STATE_REGISTER_FOR_SHADOW move to PEIM_STATE_DONE
1614 Private
->Fv
[FvCount
].PeimState
[PeimCount
]++;
1617 // Process the Notify list and dispatch any notifies for
1618 // newly installed PPIs.
1620 ProcessDispatchNotifyList (Private
);
1627 // Before walking through the next FV, we should set them to NULL/0 to
1628 // start at the beginning of the next FV.
1630 Private
->CurrentFileHandle
= NULL
;
1631 Private
->CurrentPeimCount
= 0;
1632 Private
->CurrentFvFileHandles
= NULL
;
1636 // Before making another pass, we should set it to 0 to
1637 // go through all the FVs.
1639 Private
->CurrentPeimFvCount
= 0;
1642 // PeimNeedingDispatch being TRUE means we found a PEIM/FV that did not get
1643 // dispatched. So we need to make another pass
1645 // PeimDispatchOnThisPass being TRUE means we dispatched a PEIM/FV on this
1646 // pass. If we did not dispatch a PEIM/FV there is no point in trying again
1647 // as it will fail the next time too (nothing has changed).
1649 } while (Private
->PeimNeedingDispatch
&& Private
->PeimDispatchOnThisPass
);
1653 Initialize the Dispatcher's data members
1655 @param PrivateData PeiCore's private data structure
1656 @param OldCoreData Old data from SecCore
1657 NULL if being run in non-permanent memory mode.
1658 @param SecCoreData Points to a data structure containing information about the PEI core's operating
1659 environment, such as the size and location of temporary RAM, the stack location and
1666 InitializeDispatcherData (
1667 IN PEI_CORE_INSTANCE
*PrivateData
,
1668 IN PEI_CORE_INSTANCE
*OldCoreData
,
1669 IN CONST EFI_SEC_PEI_HAND_OFF
*SecCoreData
1672 if (OldCoreData
== NULL
) {
1673 PrivateData
->PeimDispatcherReenter
= FALSE
;
1674 PeiInitializeFv (PrivateData
, SecCoreData
);
1676 PeiReinitializeFv (PrivateData
);
1683 This routine parses the Dependency Expression, if available, and
1684 decides if the module can be executed.
1687 @param Private PeiCore's private data structure
1688 @param FileHandle PEIM's file handle
1689 @param PeimCount Peim count in all dispatched PEIMs.
1691 @retval TRUE Can be dispatched
1692 @retval FALSE Cannot be dispatched
1697 IN PEI_CORE_INSTANCE
*Private
,
1698 IN EFI_PEI_FILE_HANDLE FileHandle
,
1704 EFI_FV_FILE_INFO FileInfo
;
1706 Status
= PeiServicesFfsGetFileInfo (FileHandle
, &FileInfo
);
1707 if (EFI_ERROR (Status
)) {
1708 DEBUG ((DEBUG_DISPATCH
, "Evaluate PEI DEPEX for FFS(Unknown)\n"));
1710 DEBUG ((DEBUG_DISPATCH
, "Evaluate PEI DEPEX for FFS(%g)\n", &FileInfo
.FileName
));
1713 if (PeimCount
< Private
->AprioriCount
) {
1715 // If it's in the Apriori file then we set DEPEX to TRUE
1717 DEBUG ((DEBUG_DISPATCH
, " RESULT = TRUE (Apriori)\n"));
1722 // Depex section not in the encapsulated section.
1724 Status
= PeiServicesFfsFindSectionData (
1725 EFI_SECTION_PEI_DEPEX
,
1730 if (EFI_ERROR (Status
)) {
1732 // If there is no DEPEX, assume the module can be executed
1734 DEBUG ((DEBUG_DISPATCH
, " RESULT = TRUE (No DEPEX)\n"));
1739 // Evaluate a given DEPEX
1741 return PeimDispatchReadiness (&Private
->Ps
, DepexData
);
1745 This routine enables a PEIM to register itself for shadow when the PEI Foundation
1746 discovers permanent memory.
1748 @param FileHandle File handle of a PEIM.
1750 @retval EFI_NOT_FOUND The file handle doesn't point to PEIM itself.
1751 @retval EFI_ALREADY_STARTED Indicate that the PEIM has been registered itself.
1752 @retval EFI_SUCCESS Successfully to register itself.
1757 PeiRegisterForShadow (
1758 IN EFI_PEI_FILE_HANDLE FileHandle
1761 PEI_CORE_INSTANCE
*Private
;
1763 Private
= PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());
1765 if (Private
->CurrentFileHandle
!= FileHandle
) {
1767 // The FileHandle must be for the current PEIM
1769 return EFI_NOT_FOUND
;
1772 if (Private
->Fv
[Private
->CurrentPeimFvCount
].PeimState
[Private
->CurrentPeimCount
] >= PEIM_STATE_REGISTER_FOR_SHADOW
) {
1774 // If the PEIM has already entered the PEIM_STATE_REGISTER_FOR_SHADOW or PEIM_STATE_DONE then it's already been started
1776 return EFI_ALREADY_STARTED
;
1779 Private
->Fv
[Private
->CurrentPeimFvCount
].PeimState
[Private
->CurrentPeimCount
] = PEIM_STATE_REGISTER_FOR_SHADOW
;