]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
MdeModulePkg/PeiCore: Remove MigrateSecModulesInFv()
[mirror_edk2.git] / MdeModulePkg / Core / Pei / Dispatcher / Dispatcher.c
1 /** @file
2 EFI PEI Core dispatch services
3
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
7
8 **/
9
10 #include "PeiMain.h"
11
12 /**
13
14 Discover all PEIMs and optional Apriori file in one FV. There is at most one
15 Apriori file in one FV.
16
17
18 @param Private Pointer to the private data passed in from caller
19 @param CoreFileHandle The instance of PEI_CORE_FV_HANDLE.
20
21 **/
22 VOID
23 DiscoverPeimsAndOrderWithApriori (
24 IN PEI_CORE_INSTANCE *Private,
25 IN PEI_CORE_FV_HANDLE *CoreFileHandle
26 )
27 {
28 EFI_STATUS Status;
29 EFI_PEI_FILE_HANDLE FileHandle;
30 EFI_PEI_FILE_HANDLE AprioriFileHandle;
31 EFI_GUID *Apriori;
32 UINTN Index;
33 UINTN Index2;
34 UINTN PeimIndex;
35 UINTN PeimCount;
36 EFI_GUID *Guid;
37 EFI_PEI_FILE_HANDLE *TempFileHandles;
38 EFI_GUID *TempFileGuid;
39 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
40 EFI_FV_FILE_INFO FileInfo;
41
42 FvPpi = CoreFileHandle->FvPpi;
43
44 //
45 // Walk the FV and find all the PEIMs and the Apriori file.
46 //
47 AprioriFileHandle = NULL;
48 Private->CurrentFvFileHandles = NULL;
49 Guid = NULL;
50
51 //
52 // If the current FV has been scanned, directly get its cached records.
53 //
54 if (CoreFileHandle->ScanFv) {
55 Private->CurrentFvFileHandles = CoreFileHandle->FvFileHandles;
56 return;
57 }
58
59 TempFileHandles = Private->TempFileHandles;
60 TempFileGuid = Private->TempFileGuid;
61
62 //
63 // Go ahead to scan this FV, get PeimCount and cache FileHandles within it to TempFileHandles.
64 //
65 PeimCount = 0;
66 FileHandle = NULL;
67 do {
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) {
71 //
72 // Run out of room, grow the buffer.
73 //
74 TempFileHandles = AllocatePool (
75 sizeof (EFI_PEI_FILE_HANDLE) * (Private->TempPeimCount + TEMP_FILE_GROWTH_STEP));
76 ASSERT (TempFileHandles != NULL);
77 CopyMem (
78 TempFileHandles,
79 Private->TempFileHandles,
80 sizeof (EFI_PEI_FILE_HANDLE) * Private->TempPeimCount
81 );
82 Private->TempFileHandles = TempFileHandles;
83 TempFileGuid = AllocatePool (
84 sizeof (EFI_GUID) * (Private->TempPeimCount + TEMP_FILE_GROWTH_STEP));
85 ASSERT (TempFileGuid != NULL);
86 CopyMem (
87 TempFileGuid,
88 Private->TempFileGuid,
89 sizeof (EFI_GUID) * Private->TempPeimCount
90 );
91 Private->TempFileGuid = TempFileGuid;
92 Private->TempPeimCount = Private->TempPeimCount + TEMP_FILE_GROWTH_STEP;
93 }
94
95 TempFileHandles[PeimCount++] = FileHandle;
96 }
97 } while (!EFI_ERROR (Status));
98
99 DEBUG ((
100 DEBUG_INFO,
101 "%a(): Found 0x%x PEI FFS files in the %dth FV\n",
102 __FUNCTION__,
103 PeimCount,
104 Private->CurrentPeimFvCount
105 ));
106
107 if (PeimCount == 0) {
108 //
109 // No PEIM FFS file is found, set ScanFv flag and return.
110 //
111 CoreFileHandle->ScanFv = TRUE;
112 return;
113 }
114
115 //
116 // Record PeimCount, allocate buffer for PeimState and FvFileHandles.
117 //
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);
123
124 //
125 // Get Apriori File handle
126 //
127 Private->AprioriCount = 0;
128 Status = FvPpi->FindFileByName (FvPpi, &gPeiAprioriFileNameGuid, &CoreFileHandle->FvHandle, &AprioriFileHandle);
129 if (!EFI_ERROR(Status) && AprioriFileHandle != NULL) {
130 //
131 // Read the Apriori file
132 //
133 Status = FvPpi->FindSectionByType (FvPpi, EFI_SECTION_RAW, AprioriFileHandle, (VOID **) &Apriori);
134 if (!EFI_ERROR (Status)) {
135 //
136 // Calculate the number of PEIMs in the Apriori file
137 //
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);
143 } else {
144 Private->AprioriCount -= sizeof (EFI_COMMON_SECTION_HEADER);
145 }
146 Private->AprioriCount /= sizeof (EFI_GUID);
147
148 for (Index = 0; Index < PeimCount; Index++) {
149 //
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
152 //
153 Status = FvPpi->GetFileInfo (FvPpi, TempFileHandles[Index], &FileInfo);
154 ASSERT_EFI_ERROR (Status);
155 CopyMem (&TempFileGuid[Index], &FileInfo.FileName, sizeof(EFI_GUID));
156 }
157
158 //
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.
161 //
162 Index = 0;
163 for (Index2 = 0; Index2 < Private->AprioriCount; Index2++) {
164 Guid = ScanGuid (TempFileGuid, PeimCount * sizeof (EFI_GUID), &Apriori[Index2]);
165 if (Guid != NULL) {
166 PeimIndex = ((UINTN)Guid - (UINTN)&TempFileGuid[0])/sizeof (EFI_GUID);
167 CoreFileHandle->FvFileHandles[Index++] = TempFileHandles[PeimIndex];
168
169 //
170 // Since we have copied the file handle we can remove it from this list.
171 //
172 TempFileHandles[PeimIndex] = NULL;
173 }
174 }
175
176 //
177 // Update valid AprioriCount
178 //
179 Private->AprioriCount = Index;
180
181 //
182 // Add in any PEIMs not in the Apriori file
183 //
184 for (Index2 = 0; Index2 < PeimCount; Index2++) {
185 if (TempFileHandles[Index2] != NULL) {
186 CoreFileHandle->FvFileHandles[Index++] = TempFileHandles[Index2];
187 TempFileHandles[Index2] = NULL;
188 }
189 }
190 ASSERT (Index == PeimCount);
191 }
192 } else {
193 CopyMem (CoreFileHandle->FvFileHandles, TempFileHandles, sizeof (EFI_PEI_FILE_HANDLE) * PeimCount);
194 }
195
196 //
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.
199 //
200 CoreFileHandle->ScanFv = TRUE;
201 Private->CurrentFvFileHandles = CoreFileHandle->FvFileHandles;
202 }
203
204 //
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.
209 //
210 #define MINIMUM_INITIAL_MEMORY_SIZE 0x10000
211 /**
212 This function is to test if the memory range described in resource HOB is available or not.
213
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
216 available or not.
217
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
220 **/
221 BOOLEAN
222 PeiLoadFixAddressIsMemoryRangeAvailable (
223 IN PEI_CORE_INSTANCE *PrivateData,
224 IN EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob
225 )
226 {
227 EFI_HOB_MEMORY_ALLOCATION *MemoryHob;
228 BOOLEAN IsAvailable;
229 EFI_PEI_HOB_POINTERS Hob;
230
231 IsAvailable = TRUE;
232 if (PrivateData == NULL || ResourceHob == NULL) {
233 return FALSE;
234 }
235 //
236 // test if the memory range describe in the HOB is already allocated.
237 //
238 for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
239 //
240 // See if this is a memory allocation HOB
241 //
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) {
246 IsAvailable = FALSE;
247 break;
248 }
249 }
250 }
251
252 return IsAvailable;
253
254 }
255 /**
256 Hook function for Loading Module at Fixed Address feature
257
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 function is to find the top address which is TOLM-TSEG in general.
261 And also the function will re-install PEI memory.
262
263 @param PrivateData Pointer to the private data passed in from caller
264
265 **/
266 VOID
267 PeiLoadFixAddressHook(
268 IN PEI_CORE_INSTANCE *PrivateData
269 )
270 {
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;
283 //
284 // Initialize Local Variables
285 //
286 CurrentResourceHob = NULL;
287 ResourceHob = NULL;
288 NextResourceHob = NULL;
289 HighAddress = 0;
290 TopLoadingAddress = 0;
291 MemoryRangeEnd = 0;
292 CurrentHob.Raw = PrivateData->HobList.Raw;
293 PeiMemorySize = PrivateData->PhysicalMemoryLength;
294 //
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.
297 //
298 TotalReservedMemorySize = MINIMUM_INITIAL_MEMORY_SIZE + EFI_PAGES_TO_SIZE(PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber));
299 TotalReservedMemorySize+= EFI_PAGES_TO_SIZE(PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber)) ;
300 //
301 // PEI memory range lies below the top reserved memory
302 //
303 TotalReservedMemorySize += PeiMemorySize;
304
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));
309 //
310 // Loop through the system memory typed HOB to merge the adjacent memory range
311 //
312 for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
313 //
314 // See if this is a resource descriptor HOB
315 //
316 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
317
318 ResourceHob = Hob.ResourceDescriptor;
319 //
320 // If range described in this HOB is not system memory or higher than MAX_ADDRESS, ignored.
321 //
322 if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY ||
323 ResourceHob->PhysicalStart + ResourceHob->ResourceLength > MAX_ADDRESS) {
324 continue;
325 }
326
327 for (NextHob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(NextHob); NextHob.Raw = GET_NEXT_HOB(NextHob)) {
328 if (NextHob.Raw == Hob.Raw){
329 continue;
330 }
331 //
332 // See if this is a resource descriptor HOB
333 //
334 if (GET_HOB_TYPE (NextHob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
335
336 NextResourceHob = NextHob.ResourceDescriptor;
337 //
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.
340 //
341 if (NextResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&
342 (((NextResourceHob->ResourceAttribute^ResourceHob->ResourceAttribute)&(~EFI_RESOURCE_ATTRIBUTE_TESTED)) == 0)){
343
344 //
345 // See if the memory range described in ResourceHob and NextResourceHob is adjacent
346 //
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)) {
351
352 MemoryRangeEnd = ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength)>(NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength)) ?
353 (ResourceHob->PhysicalStart + ResourceHob->ResourceLength):(NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength);
354
355 ResourceHob->PhysicalStart = (ResourceHob->PhysicalStart < NextResourceHob->PhysicalStart) ?
356 ResourceHob->PhysicalStart : NextResourceHob->PhysicalStart;
357
358
359 ResourceHob->ResourceLength = (MemoryRangeEnd - ResourceHob->PhysicalStart);
360
361 ResourceHob->ResourceAttribute = ResourceHob->ResourceAttribute & (~EFI_RESOURCE_ATTRIBUTE_TESTED);
362 //
363 // Delete the NextResourceHob by marking it as unused.
364 //
365 GET_HOB_TYPE (NextHob) = EFI_HOB_TYPE_UNUSED;
366
367 }
368 }
369 }
370 }
371 }
372 }
373 //
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
376 //
377 for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
378 //
379 // See if this is a memory allocation HOB
380 //
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)) {
384 //
385 // See if this is a resource descriptor HOB
386 //
387 if (GET_HOB_TYPE (NextHob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
388 NextResourceHob = NextHob.ResourceDescriptor;
389 //
390 // If range described in this HOB is not system memory or higher than MAX_ADDRESS, ignored.
391 //
392 if (NextResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY || NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength > MAX_ADDRESS) {
393 continue;
394 }
395 //
396 // If the range describe in memory allocation HOB belongs to the memory range described by the resource HOB
397 //
398 if (MemoryHob->AllocDescriptor.MemoryBaseAddress >= NextResourceHob->PhysicalStart &&
399 MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength <= NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength) {
400 //
401 // Build separate resource HOB for this allocated range
402 //
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)
409 );
410 }
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))
417 );
418 }
419 NextResourceHob->PhysicalStart = MemoryHob->AllocDescriptor.MemoryBaseAddress;
420 NextResourceHob->ResourceLength = MemoryHob->AllocDescriptor.MemoryLength;
421 break;
422 }
423 }
424 }
425 }
426 }
427
428 //
429 // Try to find and validate the TOP address.
430 //
431 if ((INT64)PcdGet64(PcdLoadModuleAtFixAddressEnable) > 0 ) {
432 //
433 // The LMFA feature is enabled as load module at fixed absolute address.
434 //
435 TopLoadingAddress = (EFI_PHYSICAL_ADDRESS)PcdGet64(PcdLoadModuleAtFixAddressEnable);
436 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: Loading module at fixed absolute address.\n"));
437 //
438 // validate the Address. Loop the resource descriptor HOB to make sure the address is in valid memory range
439 //
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));
442 ASSERT (FALSE);
443 }
444 //
445 // Search for a memory region that is below MAX_ADDRESS and in which TopLoadingAddress lies
446 //
447 for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
448 //
449 // See if this is a resource descriptor HOB
450 //
451 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
452
453 ResourceHob = Hob.ResourceDescriptor;
454 //
455 // See if this resource descriptor HOB describes tested system memory below MAX_ADDRESS
456 //
457 if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&
458 ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS) {
459 //
460 // See if Top address specified by user is valid.
461 //
462 if (ResourceHob->PhysicalStart + TotalReservedMemorySize < TopLoadingAddress &&
463 (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MINIMUM_INITIAL_MEMORY_SIZE) >= TopLoadingAddress &&
464 PeiLoadFixAddressIsMemoryRangeAvailable(PrivateData, ResourceHob)) {
465 CurrentResourceHob = ResourceHob;
466 CurrentHob = Hob;
467 break;
468 }
469 }
470 }
471 }
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;
475 } else {
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"));
478 //
479 // Print the recommended Top address range.
480 //
481 for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
482 //
483 // See if this is a resource descriptor HOB
484 //
485 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
486
487 ResourceHob = Hob.ResourceDescriptor;
488 //
489 // See if this resource descriptor HOB describes tested system memory below MAX_ADDRESS
490 //
491 if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&
492 ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS) {
493 //
494 // See if Top address specified by user is valid.
495 //
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)
500 ));
501 }
502 }
503 }
504 }
505 //
506 // Assert here
507 //
508 ASSERT (FALSE);
509 return;
510 }
511 } else {
512 //
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)
515 //
516 //
517 // Search for a tested memory region that is below MAX_ADDRESS
518 //
519 for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
520 //
521 // See if this is a resource descriptor HOB
522 //
523 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
524
525 ResourceHob = Hob.ResourceDescriptor;
526 //
527 // See if this resource descriptor HOB describes tested system memory below MAX_ADDRESS
528 //
529 if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&
530 ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS &&
531 ResourceHob->ResourceLength > TotalReservedMemorySize && PeiLoadFixAddressIsMemoryRangeAvailable(PrivateData, ResourceHob)) {
532 //
533 // See if this is the highest largest system memory region below MaxAddress
534 //
535 if (ResourceHob->PhysicalStart > HighAddress) {
536 CurrentResourceHob = ResourceHob;
537 CurrentHob = Hob;
538 HighAddress = CurrentResourceHob->PhysicalStart;
539 }
540 }
541 }
542 }
543 if (CurrentResourceHob == NULL) {
544 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR:The System Memory is too small\n"));
545 //
546 // Assert here
547 //
548 ASSERT (FALSE);
549 return;
550 } else {
551 TopLoadingAddress = CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength ;
552 }
553 }
554
555 if (CurrentResourceHob != NULL) {
556 //
557 // rebuild resource HOB for PEI memory and reserved memory
558 //
559 BuildResourceDescriptorHob (
560 EFI_RESOURCE_SYSTEM_MEMORY,
561 (
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
569 ),
570 (TopLoadingAddress - TotalReservedMemorySize),
571 TotalReservedMemorySize
572 );
573 //
574 // rebuild resource for the remain memory if necessary
575 //
576 if (CurrentResourceHob->PhysicalStart < TopLoadingAddress - TotalReservedMemorySize) {
577 BuildResourceDescriptorHob (
578 EFI_RESOURCE_SYSTEM_MEMORY,
579 (
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
586 ),
587 CurrentResourceHob->PhysicalStart,
588 (TopLoadingAddress - TotalReservedMemorySize - CurrentResourceHob->PhysicalStart)
589 );
590 }
591 if (CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength > TopLoadingAddress ) {
592 BuildResourceDescriptorHob (
593 EFI_RESOURCE_SYSTEM_MEMORY,
594 (
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
601 ),
602 TopLoadingAddress,
603 (CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength - TopLoadingAddress)
604 );
605 }
606 //
607 // Delete CurrentHob by marking it as unused since the memory range described by is rebuilt.
608 //
609 GET_HOB_TYPE (CurrentHob) = EFI_HOB_TYPE_UNUSED;
610 }
611
612 //
613 // Cache the top address for Loading Module at Fixed Address feature
614 //
615 PrivateData->LoadModuleAtFixAddressTopAddress = TopLoadingAddress - MINIMUM_INITIAL_MEMORY_SIZE;
616 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: Top address = 0x%lx\n", PrivateData->LoadModuleAtFixAddressTopAddress));
617 //
618 // reinstall the PEI memory relative to TopLoadingAddress
619 //
620 PrivateData->PhysicalMemoryBegin = TopLoadingAddress - TotalReservedMemorySize;
621 PrivateData->FreePhysicalMemoryTop = PrivateData->PhysicalMemoryBegin + PeiMemorySize;
622 }
623
624 /**
625 This routine is invoked in switch stack as PeiCore Entry.
626
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
629 the BFV location.
630 @param Private Pointer to old core data that is used to initialize the
631 core's data areas.
632 **/
633 VOID
634 EFIAPI
635 PeiCoreEntry (
636 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
637 IN PEI_CORE_INSTANCE *Private
638 )
639 {
640 //
641 // Entry PEI Phase 2
642 //
643 PeiCore (SecCoreData, NULL, Private);
644 }
645
646 /**
647 Check SwitchStackSignal and switch stack if SwitchStackSignal is TRUE.
648
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
651 the BFV location.
652 @param[in] Private Pointer to the private data passed in from caller.
653
654 **/
655 VOID
656 PeiCheckAndSwitchStack (
657 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
658 IN PEI_CORE_INSTANCE *Private
659 )
660 {
661 VOID *LoadFixPeiCodeBegin;
662 EFI_STATUS Status;
663 CONST EFI_PEI_SERVICES **PeiServices;
664 UINT64 NewStackSize;
665 EFI_PHYSICAL_ADDRESS TopOfOldStack;
666 EFI_PHYSICAL_ADDRESS TopOfNewStack;
667 UINTN StackOffset;
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;
678 UINTN HoleMemSize;
679 UINTN HeapTemporaryRamSize;
680 EFI_PHYSICAL_ADDRESS TempBase1;
681 UINTN TempSize1;
682 EFI_PHYSICAL_ADDRESS TempBase2;
683 UINTN TempSize2;
684 UINTN Index;
685
686 PeiServices = (CONST EFI_PEI_SERVICES **) &Private->Ps;
687
688 if (Private->SwitchStackSignal) {
689 //
690 // Before switch stack from temporary memory to permanent memory, calculate the heap and stack
691 // usage in temporary memory for debugging.
692 //
693 DEBUG_CODE_BEGIN ();
694 UINT32 *StackPointer;
695 EFI_PEI_HOB_POINTERS Hob;
696
697 for (StackPointer = (UINT32*)SecCoreData->StackBase;
698 (StackPointer < (UINT32*)((UINTN)SecCoreData->StackBase + SecCoreData->StackSize)) \
699 && (*StackPointer == PcdGet32 (PcdInitValueInTempStack));
700 StackPointer ++) {
701 }
702
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))
708 ));
709 DEBUG ((DEBUG_INFO, " temporary memory heap used for HobList: %d bytes.\n",
710 (UINT32)((UINTN)Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - (UINTN)Private->HobList.Raw)
711 ));
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)
714 ));
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));
721 }
722 }
723 DEBUG_CODE_END ();
724
725 if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0 && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
726 //
727 // Loading Module at Fixed Address is enabled
728 //
729 PeiLoadFixAddressHook (Private);
730
731 //
732 // If Loading Module at Fixed Address is enabled, Allocating memory range for Pei code range.
733 //
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)));
736 }
737
738 //
739 // Reserve the size of new stack at bottom of physical memory
740 //
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.
745 //
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);
751
752 //
753 // Calculate stack offset and heap offset between temporary memory and new permanent
754 // memory separately.
755 //
756 TopOfOldStack = (UINTN)SecCoreData->StackBase + SecCoreData->StackSize;
757 TopOfNewStack = Private->PhysicalMemoryBegin + NewStackSize;
758 if (TopOfNewStack >= TopOfOldStack) {
759 StackOffsetPositive = TRUE;
760 StackOffset = (UINTN)(TopOfNewStack - TopOfOldStack);
761 } else {
762 StackOffsetPositive = FALSE;
763 StackOffset = (UINTN)(TopOfOldStack - TopOfNewStack);
764 }
765 Private->StackOffsetPositive = StackOffsetPositive;
766 Private->StackOffset = StackOffset;
767
768 //
769 // Build Stack HOB that describes the permanent memory stack
770 //
771 DEBUG ((EFI_D_INFO, "Stack Hob: BaseAddress=0x%lX Length=0x%lX\n", TopOfNewStack - NewStackSize, NewStackSize));
772 BuildStackHob (TopOfNewStack - NewStackSize, NewStackSize);
773
774 //
775 // Cache information from SecCoreData into locals before SecCoreData is converted to a permanent memory address
776 //
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;
783
784 //
785 // TemporaryRamSupportPpi is produced by platform's SEC
786 //
787 Status = PeiServicesLocatePpi (
788 &gEfiTemporaryRamSupportPpiGuid,
789 0,
790 NULL,
791 (VOID**)&TemporaryRamSupportPpi
792 );
793 if (!EFI_ERROR (Status)) {
794 //
795 // Heap Offset
796 //
797 BaseOfNewHeap = TopOfNewStack;
798 if (BaseOfNewHeap >= (UINTN)SecCoreData->PeiTemporaryRamBase) {
799 Private->HeapOffsetPositive = TRUE;
800 Private->HeapOffset = (UINTN)(BaseOfNewHeap - (UINTN)SecCoreData->PeiTemporaryRamBase);
801 } else {
802 Private->HeapOffsetPositive = FALSE;
803 Private->HeapOffset = (UINTN)((UINTN)SecCoreData->PeiTemporaryRamBase - BaseOfNewHeap);
804 }
805
806 DEBUG ((EFI_D_INFO, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (UINT64) Private->HeapOffset, (UINT64) Private->StackOffset));
807
808 //
809 // Calculate new HandOffTable and PrivateData address in permanent memory's stack
810 //
811 if (StackOffsetPositive) {
812 SecCoreData = (CONST EFI_SEC_PEI_HAND_OFF *)((UINTN)(VOID *)SecCoreData + StackOffset);
813 Private = (PEI_CORE_INSTANCE *)((UINTN)(VOID *)Private + StackOffset);
814 } else {
815 SecCoreData = (CONST EFI_SEC_PEI_HAND_OFF *)((UINTN)(VOID *)SecCoreData - StackOffset);
816 Private = (PEI_CORE_INSTANCE *)((UINTN)(VOID *)Private - StackOffset);
817 }
818
819 //
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.
824 //
825 TemporaryRamSupportPpi->TemporaryRamMigration (
826 PeiServices,
827 TemporaryRamBase,
828 (EFI_PHYSICAL_ADDRESS)(UINTN)(TopOfNewStack - TemporaryStackSize),
829 TemporaryRamSize
830 );
831
832 //
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().
836 //
837 MigrateMemoryPages (Private, TRUE);
838
839 //
840 // Entry PEI Phase 2
841 //
842 PeiCore (SecCoreData, NULL, Private);
843 } else {
844 //
845 // Migrate memory pages allocated in pre-memory phase.
846 //
847 MigrateMemoryPages (Private, FALSE);
848
849 //
850 // Migrate the PEI Services Table pointer from temporary RAM to permanent RAM.
851 //
852 MigratePeiServicesTablePointer ();
853
854 //
855 // Heap Offset
856 //
857 BaseOfNewHeap = TopOfNewStack;
858 HoleMemBase = TopOfNewStack;
859 HoleMemSize = TemporaryRamSize - PeiTemporaryRamSize - TemporaryStackSize;
860 if (HoleMemSize != 0) {
861 //
862 // Make sure HOB List start address is 8 byte alignment.
863 //
864 BaseOfNewHeap = ALIGN_VALUE (BaseOfNewHeap + HoleMemSize, 8);
865 }
866 if (BaseOfNewHeap >= (UINTN)SecCoreData->PeiTemporaryRamBase) {
867 Private->HeapOffsetPositive = TRUE;
868 Private->HeapOffset = (UINTN)(BaseOfNewHeap - (UINTN)SecCoreData->PeiTemporaryRamBase);
869 } else {
870 Private->HeapOffsetPositive = FALSE;
871 Private->HeapOffset = (UINTN)((UINTN)SecCoreData->PeiTemporaryRamBase - BaseOfNewHeap);
872 }
873
874 DEBUG ((EFI_D_INFO, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (UINT64) Private->HeapOffset, (UINT64) Private->StackOffset));
875
876 //
877 // Migrate Heap
878 //
879 HeapTemporaryRamSize = (UINTN) (Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - Private->HobList.HandoffInformationTable->EfiMemoryBottom);
880 ASSERT (BaseOfNewHeap + HeapTemporaryRamSize <= Private->FreePhysicalMemoryTop);
881 CopyMem ((UINT8 *) (UINTN) BaseOfNewHeap, PeiTemporaryRamBase, HeapTemporaryRamSize);
882
883 //
884 // Migrate Stack
885 //
886 CopyMem ((UINT8 *) (UINTN) (TopOfNewStack - TemporaryStackSize), TemporaryStackBase, TemporaryStackSize);
887
888 //
889 // Copy Hole Range Data
890 //
891 if (HoleMemSize != 0) {
892 //
893 // Prepare Hole
894 //
895 if (PeiTemporaryRamBase < TemporaryStackBase) {
896 TempBase1 = (EFI_PHYSICAL_ADDRESS) (UINTN) PeiTemporaryRamBase;
897 TempSize1 = PeiTemporaryRamSize;
898 TempBase2 = (EFI_PHYSICAL_ADDRESS) (UINTN) TemporaryStackBase;
899 TempSize2 = TemporaryStackSize;
900 } else {
901 TempBase1 = (EFI_PHYSICAL_ADDRESS) (UINTN) TemporaryStackBase;
902 TempSize1 = TemporaryStackSize;
903 TempBase2 =(EFI_PHYSICAL_ADDRESS) (UINTN) PeiTemporaryRamBase;
904 TempSize2 = PeiTemporaryRamSize;
905 }
906 if (TemporaryRamBase < TempBase1) {
907 Private->HoleData[0].Base = TemporaryRamBase;
908 Private->HoleData[0].Size = (UINTN) (TempBase1 - TemporaryRamBase);
909 }
910 if (TempBase1 + TempSize1 < TempBase2) {
911 Private->HoleData[1].Base = TempBase1 + TempSize1;
912 Private->HoleData[1].Size = (UINTN) (TempBase2 - TempBase1 - TempSize1);
913 }
914 if (TempBase2 + TempSize2 < TemporaryRamBase + TemporaryRamSize) {
915 Private->HoleData[2].Base = TempBase2 + TempSize2;
916 Private->HoleData[2].Size = (UINTN) (TemporaryRamBase + TemporaryRamSize - TempBase2 - TempSize2);
917 }
918
919 //
920 // Copy Hole Range data.
921 //
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);
927 } else {
928 Private->HoleData[Index].OffsetPositive = FALSE;
929 Private->HoleData[Index].Offset = (UINTN) (Private->HoleData[Index].Base - HoleMemBase);
930 }
931 CopyMem ((VOID *) (UINTN) HoleMemBase, (VOID *) (UINTN) Private->HoleData[Index].Base, Private->HoleData[Index].Size);
932 HoleMemBase = HoleMemBase + Private->HoleData[Index].Size;
933 }
934 }
935 }
936
937 //
938 // Switch new stack
939 //
940 SwitchStack (
941 (SWITCH_STACK_ENTRY_POINT)(UINTN)PeiCoreEntry,
942 (VOID *) SecCoreData,
943 (VOID *) Private,
944 (VOID *) (UINTN) TopOfNewStack
945 );
946 }
947
948 //
949 // Code should not come here
950 //
951 ASSERT (FALSE);
952 }
953 }
954
955 /**
956 Migrate a PEIM from temporary RAM to permanent memory.
957
958 @param PeimFileHandle Pointer to the FFS file header of the image.
959 @param MigratedFileHandle Pointer to the FFS file header of the migrated image.
960
961 @retval EFI_SUCCESS Sucessfully migrated the PEIM to permanent memory.
962
963 **/
964 EFI_STATUS
965 EFIAPI
966 MigratePeim (
967 IN EFI_PEI_FILE_HANDLE FileHandle,
968 IN EFI_PEI_FILE_HANDLE MigratedFileHandle
969 )
970 {
971 EFI_STATUS Status;
972 EFI_FFS_FILE_HEADER *FileHeader;
973 VOID *Pe32Data;
974 VOID *ImageAddress;
975 CHAR8 *AsciiString;
976 UINTN Index;
977
978 Status = EFI_SUCCESS;
979
980 FileHeader = (EFI_FFS_FILE_HEADER *) FileHandle;
981 ASSERT (!IS_FFS_FILE2 (FileHeader));
982
983 ImageAddress = NULL;
984 PeiGetPe32Data (MigratedFileHandle, &ImageAddress);
985 if (ImageAddress != NULL) {
986 DEBUG_CODE_BEGIN ();
987 AsciiString = PeCoffLoaderGetPdbPointer (ImageAddress);
988 for (Index = 0; AsciiString[Index] != 0; Index++) {
989 if (AsciiString[Index] == '\\' || AsciiString[Index] == '/') {
990 AsciiString = AsciiString + Index + 1;
991 Index = 0;
992 } else if (AsciiString[Index] == '.') {
993 AsciiString[Index] = 0;
994 }
995 }
996 DEBUG ((DEBUG_INFO, "%a", AsciiString));
997 DEBUG_CODE_END ();
998
999 Pe32Data = (VOID *) ((UINTN) ImageAddress - (UINTN) MigratedFileHandle + (UINTN) FileHandle);
1000 Status = LoadAndRelocatePeCoffImageInPlace (Pe32Data, ImageAddress);
1001 ASSERT_EFI_ERROR (Status);
1002 }
1003
1004 return Status;
1005 }
1006
1007 /**
1008 Migrate Status Code Callback function pointers inside an FV from temporary memory to permanent memory.
1009
1010 @param OrgFvHandle Address of FV handle in temporary memory.
1011 @param FvHandle Address of FV handle in permanent memory.
1012 @param FvSize Size of the FV.
1013
1014 **/
1015 VOID
1016 ConvertStatusCodeCallbacks (
1017 IN UINTN OrgFvHandle,
1018 IN UINTN FvHandle,
1019 IN UINTN FvSize
1020 )
1021 {
1022 EFI_PEI_HOB_POINTERS Hob;
1023 UINTN *NumberOfEntries;
1024 UINTN *CallbackEntry;
1025 UINTN Index;
1026
1027 Hob.Raw = GetFirstGuidHob (&gStatusCodeCallbackGuid);
1028 while (Hob.Raw != NULL) {
1029 NumberOfEntries = GET_GUID_HOB_DATA (Hob);
1030 CallbackEntry = NumberOfEntries + 1;
1031 for (Index = 0; Index < *NumberOfEntries; Index++) {
1032 if (((VOID *) CallbackEntry[Index]) != NULL) {
1033 if ((CallbackEntry[Index] >= OrgFvHandle) && (CallbackEntry[Index] < (OrgFvHandle + FvSize))) {
1034 DEBUG ((
1035 DEBUG_INFO,
1036 "Migrating CallbackEntry[%Lu] from 0x%0*Lx to ",
1037 (UINT64)Index,
1038 (sizeof CallbackEntry[Index]) * 2,
1039 (UINT64)CallbackEntry[Index]
1040 ));
1041 if (OrgFvHandle > FvHandle) {
1042 CallbackEntry[Index] = CallbackEntry[Index] - (OrgFvHandle - FvHandle);
1043 } else {
1044 CallbackEntry[Index] = CallbackEntry[Index] + (FvHandle - OrgFvHandle);
1045 }
1046 DEBUG ((
1047 DEBUG_INFO,
1048 "0x%0*Lx\n",
1049 (sizeof CallbackEntry[Index]) * 2,
1050 (UINT64)CallbackEntry[Index]
1051 ));
1052 }
1053 }
1054 }
1055 Hob.Raw = GET_NEXT_HOB (Hob);
1056 Hob.Raw = GetNextGuidHob (&gStatusCodeCallbackGuid, Hob.Raw);
1057 }
1058 }
1059
1060 /**
1061 Migrates PEIMs in the given firmware volume.
1062
1063 @param Private Pointer to the PeiCore's private data structure.
1064 @param FvIndex The firmware volume index to migrate.
1065 @param OrgFvHandle The handle to the firmware volume in temporary memory.
1066 @param FvHandle The handle to the firmware volume in permanent memory.
1067
1068 @retval EFI_SUCCESS The PEIMs in the FV were migrated successfully
1069 @retval EFI_INVALID_PARAMETER The Private pointer is NULL or FvCount is invalid.
1070
1071 **/
1072 EFI_STATUS
1073 EFIAPI
1074 MigratePeimsInFv (
1075 IN PEI_CORE_INSTANCE *Private,
1076 IN UINTN FvIndex,
1077 IN UINTN OrgFvHandle,
1078 IN UINTN FvHandle
1079 )
1080 {
1081 EFI_STATUS Status;
1082 volatile UINTN FileIndex;
1083 EFI_PEI_FILE_HANDLE MigratedFileHandle;
1084 EFI_PEI_FILE_HANDLE FileHandle;
1085
1086 if (Private == NULL || FvIndex >= Private->FvCount) {
1087 return EFI_INVALID_PARAMETER;
1088 }
1089
1090 if (Private->Fv[FvIndex].ScanFv) {
1091 for (FileIndex = 0; FileIndex < Private->Fv[FvIndex].PeimCount; FileIndex++) {
1092 if (Private->Fv[FvIndex].FvFileHandles[FileIndex] != NULL) {
1093 FileHandle = Private->Fv[FvIndex].FvFileHandles[FileIndex];
1094
1095 MigratedFileHandle = (EFI_PEI_FILE_HANDLE) ((UINTN) FileHandle - OrgFvHandle + FvHandle);
1096
1097 DEBUG ((DEBUG_VERBOSE, " Migrating FileHandle %2d ", FileIndex));
1098 Status = MigratePeim (FileHandle, MigratedFileHandle);
1099 DEBUG ((DEBUG_VERBOSE, "\n"));
1100 ASSERT_EFI_ERROR (Status);
1101
1102 if (!EFI_ERROR (Status)) {
1103 Private->Fv[FvIndex].FvFileHandles[FileIndex] = MigratedFileHandle;
1104 if (FvIndex == Private->CurrentPeimFvCount) {
1105 Private->CurrentFvFileHandles[FileIndex] = MigratedFileHandle;
1106 }
1107 }
1108 }
1109 }
1110 }
1111
1112 return EFI_SUCCESS;
1113 }
1114
1115 /**
1116 Migrate FVs out of temporary RAM before the cache is flushed.
1117
1118 @param Private PeiCore's private data structure
1119 @param SecCoreData Points to a data structure containing information about the PEI core's operating
1120 environment, such as the size and location of temporary RAM, the stack location and
1121 the BFV location.
1122
1123 @retval EFI_SUCCESS Succesfully migrated installed FVs from temporary RAM to permanent memory.
1124 @retval EFI_OUT_OF_RESOURCES Insufficient memory exists to allocate needed pages.
1125
1126 **/
1127 EFI_STATUS
1128 EFIAPI
1129 EvacuateTempRam (
1130 IN PEI_CORE_INSTANCE *Private,
1131 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData
1132 )
1133 {
1134 EFI_STATUS Status;
1135 volatile UINTN FvIndex;
1136 volatile UINTN FvChildIndex;
1137 UINTN ChildFvOffset;
1138 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
1139 EFI_FIRMWARE_VOLUME_HEADER *ChildFvHeader;
1140 EFI_FIRMWARE_VOLUME_HEADER *MigratedFvHeader;
1141 EFI_FIRMWARE_VOLUME_HEADER *RawDataFvHeader;
1142 EFI_FIRMWARE_VOLUME_HEADER *MigratedChildFvHeader;
1143
1144 PEI_CORE_FV_HANDLE PeiCoreFvHandle;
1145 EFI_PEI_CORE_FV_LOCATION_PPI *PeiCoreFvLocationPpi;
1146 EDKII_MIGRATED_FV_INFO MigratedFvInfo;
1147
1148 ASSERT (Private->PeiMemoryInstalled);
1149
1150 DEBUG ((DEBUG_VERBOSE, "Beginning evacuation of content in temporary RAM.\n"));
1151
1152 //
1153 // Migrate PPI Pointers of PEI_CORE from temporary memory to newly loaded PEI_CORE in permanent memory.
1154 //
1155 Status = PeiLocatePpi ((CONST EFI_PEI_SERVICES **) &Private->Ps, &gEfiPeiCoreFvLocationPpiGuid, 0, NULL, (VOID **) &PeiCoreFvLocationPpi);
1156 if (!EFI_ERROR (Status) && (PeiCoreFvLocationPpi->PeiCoreFvLocation != NULL)) {
1157 PeiCoreFvHandle.FvHandle = (EFI_PEI_FV_HANDLE) PeiCoreFvLocationPpi->PeiCoreFvLocation;
1158 } else {
1159 PeiCoreFvHandle.FvHandle = (EFI_PEI_FV_HANDLE) SecCoreData->BootFirmwareVolumeBase;
1160 }
1161 for (FvIndex = 0; FvIndex < Private->FvCount; FvIndex++) {
1162 if (Private->Fv[FvIndex].FvHandle == PeiCoreFvHandle.FvHandle) {
1163 CopyMem (&PeiCoreFvHandle, &Private->Fv[FvIndex], sizeof (PEI_CORE_FV_HANDLE));
1164 break;
1165 }
1166 }
1167 Status = EFI_SUCCESS;
1168
1169 ConvertPeiCorePpiPointers (Private, &PeiCoreFvHandle);
1170
1171 for (FvIndex = 0; FvIndex < Private->FvCount; FvIndex++) {
1172 FvHeader = Private->Fv[FvIndex].FvHeader;
1173 ASSERT (FvHeader != NULL);
1174 ASSERT (FvIndex < Private->FvCount);
1175
1176 DEBUG ((DEBUG_VERBOSE, "FV[%02d] at 0x%x.\n", FvIndex, (UINTN) FvHeader));
1177 if (
1178 !(
1179 ((EFI_PHYSICAL_ADDRESS)(UINTN) FvHeader >= Private->PhysicalMemoryBegin) &&
1180 (((EFI_PHYSICAL_ADDRESS)(UINTN) FvHeader + (FvHeader->FvLength - 1)) < Private->FreePhysicalMemoryTop)
1181 )
1182 ) {
1183 //
1184 // Allocate page to save the rebased PEIMs, the PEIMs will get dispatched later.
1185 //
1186 Status = PeiServicesAllocatePages (
1187 EfiBootServicesCode,
1188 EFI_SIZE_TO_PAGES ((UINTN) FvHeader->FvLength),
1189 (EFI_PHYSICAL_ADDRESS *) &MigratedFvHeader
1190 );
1191 ASSERT_EFI_ERROR (Status);
1192
1193 //
1194 // Allocate pool to save the raw PEIMs, which is used to keep consistent context across
1195 // multiple boot and PCR0 will keep the same no matter if the address of allocated page is changed.
1196 //
1197 Status = PeiServicesAllocatePages (
1198 EfiBootServicesCode,
1199 EFI_SIZE_TO_PAGES ((UINTN) FvHeader->FvLength),
1200 (EFI_PHYSICAL_ADDRESS *) &RawDataFvHeader
1201 );
1202 ASSERT_EFI_ERROR (Status);
1203
1204 DEBUG ((
1205 DEBUG_VERBOSE,
1206 " Migrating FV[%d] from 0x%08X to 0x%08X\n",
1207 FvIndex,
1208 (UINTN) FvHeader,
1209 (UINTN) MigratedFvHeader
1210 ));
1211
1212 //
1213 // Copy the context to the rebased pages and raw pages, and create hob to save the
1214 // information. The MigratedFvInfo HOB will never be produced when
1215 // PcdMigrateTemporaryRamFirmwareVolumes is FALSE, because the PCD control the
1216 // feature.
1217 //
1218 CopyMem (MigratedFvHeader, FvHeader, (UINTN) FvHeader->FvLength);
1219 CopyMem (RawDataFvHeader, MigratedFvHeader, (UINTN) FvHeader->FvLength);
1220 MigratedFvInfo.FvOrgBase = (UINT32) (UINTN) FvHeader;
1221 MigratedFvInfo.FvNewBase = (UINT32) (UINTN) MigratedFvHeader;
1222 MigratedFvInfo.FvDataBase = (UINT32) (UINTN) RawDataFvHeader;
1223 MigratedFvInfo.FvLength = (UINT32) (UINTN) FvHeader->FvLength;
1224 BuildGuidDataHob (&gEdkiiMigratedFvInfoGuid, &MigratedFvInfo, sizeof (MigratedFvInfo));
1225
1226 //
1227 // Migrate any children for this FV now
1228 //
1229 for (FvChildIndex = FvIndex; FvChildIndex < Private->FvCount; FvChildIndex++) {
1230 ChildFvHeader = Private->Fv[FvChildIndex].FvHeader;
1231 if (
1232 ((UINTN) ChildFvHeader > (UINTN) FvHeader) &&
1233 (((UINTN) ChildFvHeader + ChildFvHeader->FvLength) < ((UINTN) FvHeader) + FvHeader->FvLength)
1234 ) {
1235 DEBUG ((DEBUG_VERBOSE, " Child FV[%02d] is being migrated.\n", FvChildIndex));
1236 ChildFvOffset = (UINTN) ChildFvHeader - (UINTN) FvHeader;
1237 DEBUG ((DEBUG_VERBOSE, " Child FV offset = 0x%x.\n", ChildFvOffset));
1238 MigratedChildFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) MigratedFvHeader + ChildFvOffset);
1239 Private->Fv[FvChildIndex].FvHeader = MigratedChildFvHeader;
1240 Private->Fv[FvChildIndex].FvHandle = (EFI_PEI_FV_HANDLE) MigratedChildFvHeader;
1241 DEBUG ((DEBUG_VERBOSE, " Child migrated FV header at 0x%x.\n", (UINTN) MigratedChildFvHeader));
1242
1243 Status = MigratePeimsInFv (Private, FvChildIndex, (UINTN) ChildFvHeader, (UINTN) MigratedChildFvHeader);
1244 ASSERT_EFI_ERROR (Status);
1245
1246 ConvertPpiPointersFv (
1247 Private,
1248 (UINTN) ChildFvHeader,
1249 (UINTN) MigratedChildFvHeader,
1250 (UINTN) ChildFvHeader->FvLength - 1
1251 );
1252
1253 ConvertStatusCodeCallbacks (
1254 (UINTN) ChildFvHeader,
1255 (UINTN) MigratedChildFvHeader,
1256 (UINTN) ChildFvHeader->FvLength - 1
1257 );
1258
1259 ConvertFvHob (Private, (UINTN) ChildFvHeader, (UINTN) MigratedChildFvHeader);
1260 }
1261 }
1262 Private->Fv[FvIndex].FvHeader = MigratedFvHeader;
1263 Private->Fv[FvIndex].FvHandle = (EFI_PEI_FV_HANDLE) MigratedFvHeader;
1264
1265 Status = MigratePeimsInFv (Private, FvIndex, (UINTN) FvHeader, (UINTN) MigratedFvHeader);
1266 ASSERT_EFI_ERROR (Status);
1267
1268 ConvertPpiPointersFv (
1269 Private,
1270 (UINTN) FvHeader,
1271 (UINTN) MigratedFvHeader,
1272 (UINTN) FvHeader->FvLength - 1
1273 );
1274
1275 ConvertStatusCodeCallbacks (
1276 (UINTN) FvHeader,
1277 (UINTN) MigratedFvHeader,
1278 (UINTN) FvHeader->FvLength - 1
1279 );
1280
1281 ConvertFvHob (Private, (UINTN) FvHeader, (UINTN) MigratedFvHeader);
1282 }
1283 }
1284
1285 RemoveFvHobsInTemporaryMemory (Private);
1286
1287 return Status;
1288 }
1289
1290 /**
1291 Conduct PEIM dispatch.
1292
1293 @param SecCoreData Points to a data structure containing information about the PEI core's operating
1294 environment, such as the size and location of temporary RAM, the stack location and
1295 the BFV location.
1296 @param Private Pointer to the private data passed in from caller
1297
1298 **/
1299 VOID
1300 PeiDispatcher (
1301 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
1302 IN PEI_CORE_INSTANCE *Private
1303 )
1304 {
1305 EFI_STATUS Status;
1306 UINT32 Index1;
1307 UINT32 Index2;
1308 CONST EFI_PEI_SERVICES **PeiServices;
1309 EFI_PEI_FILE_HANDLE PeimFileHandle;
1310 UINTN FvCount;
1311 UINTN PeimCount;
1312 UINT32 AuthenticationState;
1313 EFI_PHYSICAL_ADDRESS EntryPoint;
1314 EFI_PEIM_ENTRY_POINT2 PeimEntryPoint;
1315 UINTN SaveCurrentPeimCount;
1316 UINTN SaveCurrentFvCount;
1317 EFI_PEI_FILE_HANDLE SaveCurrentFileHandle;
1318 EFI_FV_FILE_INFO FvFileInfo;
1319 PEI_CORE_FV_HANDLE *CoreFvHandle;
1320
1321 PeiServices = (CONST EFI_PEI_SERVICES **) &Private->Ps;
1322 PeimEntryPoint = NULL;
1323 PeimFileHandle = NULL;
1324 EntryPoint = 0;
1325
1326 if ((Private->PeiMemoryInstalled) &&
1327 (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||
1328 (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) ||
1329 PcdGetBool (PcdShadowPeimOnS3Boot))
1330 ) {
1331 //
1332 // Once real memory is available, shadow the RegisterForShadow modules. And meanwhile
1333 // update the modules' status from PEIM_STATE_REGISTER_FOR_SHADOW to PEIM_STATE_DONE.
1334 //
1335 SaveCurrentPeimCount = Private->CurrentPeimCount;
1336 SaveCurrentFvCount = Private->CurrentPeimFvCount;
1337 SaveCurrentFileHandle = Private->CurrentFileHandle;
1338
1339 for (Index1 = 0; Index1 < Private->FvCount; Index1++) {
1340 for (Index2 = 0; Index2 < Private->Fv[Index1].PeimCount; Index2++) {
1341 if (Private->Fv[Index1].PeimState[Index2] == PEIM_STATE_REGISTER_FOR_SHADOW) {
1342 PeimFileHandle = Private->Fv[Index1].FvFileHandles[Index2];
1343 Private->CurrentFileHandle = PeimFileHandle;
1344 Private->CurrentPeimFvCount = Index1;
1345 Private->CurrentPeimCount = Index2;
1346 Status = PeiLoadImage (
1347 (CONST EFI_PEI_SERVICES **) &Private->Ps,
1348 PeimFileHandle,
1349 PEIM_STATE_REGISTER_FOR_SHADOW,
1350 &EntryPoint,
1351 &AuthenticationState
1352 );
1353 if (Status == EFI_SUCCESS) {
1354 //
1355 // PEIM_STATE_REGISTER_FOR_SHADOW move to PEIM_STATE_DONE
1356 //
1357 Private->Fv[Index1].PeimState[Index2]++;
1358 //
1359 // Call the PEIM entry point
1360 //
1361 PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;
1362
1363 PERF_START_IMAGE_BEGIN (PeimFileHandle);
1364 PeimEntryPoint(PeimFileHandle, (const EFI_PEI_SERVICES **) &Private->Ps);
1365 PERF_START_IMAGE_END (PeimFileHandle);
1366 }
1367
1368 //
1369 // Process the Notify list and dispatch any notifies for
1370 // newly installed PPIs.
1371 //
1372 ProcessDispatchNotifyList (Private);
1373 }
1374 }
1375 }
1376 Private->CurrentFileHandle = SaveCurrentFileHandle;
1377 Private->CurrentPeimFvCount = SaveCurrentFvCount;
1378 Private->CurrentPeimCount = SaveCurrentPeimCount;
1379 }
1380
1381 //
1382 // This is the main dispatch loop. It will search known FVs for PEIMs and
1383 // attempt to dispatch them. If any PEIM gets dispatched through a single
1384 // pass of the dispatcher, it will start over from the BFV again to see
1385 // if any new PEIMs dependencies got satisfied. With a well ordered
1386 // FV where PEIMs are found in the order their dependencies are also
1387 // satisfied, this dispatcher should run only once.
1388 //
1389 do {
1390 //
1391 // In case that reenter PeiCore happens, the last pass record is still available.
1392 //
1393 if (!Private->PeimDispatcherReenter) {
1394 Private->PeimNeedingDispatch = FALSE;
1395 Private->PeimDispatchOnThisPass = FALSE;
1396 } else {
1397 Private->PeimDispatcherReenter = FALSE;
1398 }
1399
1400 for (FvCount = Private->CurrentPeimFvCount; FvCount < Private->FvCount; FvCount++) {
1401 CoreFvHandle = FindNextCoreFvHandle (Private, FvCount);
1402 ASSERT (CoreFvHandle != NULL);
1403
1404 //
1405 // If the FV has corresponding EFI_PEI_FIRMWARE_VOLUME_PPI instance, then dispatch it.
1406 //
1407 if (CoreFvHandle->FvPpi == NULL) {
1408 continue;
1409 }
1410
1411 Private->CurrentPeimFvCount = FvCount;
1412
1413 if (Private->CurrentPeimCount == 0) {
1414 //
1415 // When going through each FV, at first, search Apriori file to
1416 // reorder all PEIMs to ensure the PEIMs in Apriori file to get
1417 // dispatch at first.
1418 //
1419 DiscoverPeimsAndOrderWithApriori (Private, CoreFvHandle);
1420 }
1421
1422 //
1423 // Start to dispatch all modules within the current FV.
1424 //
1425 for (PeimCount = Private->CurrentPeimCount;
1426 PeimCount < Private->Fv[FvCount].PeimCount;
1427 PeimCount++) {
1428 Private->CurrentPeimCount = PeimCount;
1429 PeimFileHandle = Private->CurrentFileHandle = Private->CurrentFvFileHandles[PeimCount];
1430
1431 if (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_NOT_DISPATCHED) {
1432 if (!DepexSatisfied (Private, PeimFileHandle, PeimCount)) {
1433 Private->PeimNeedingDispatch = TRUE;
1434 } else {
1435 Status = CoreFvHandle->FvPpi->GetFileInfo (CoreFvHandle->FvPpi, PeimFileHandle, &FvFileInfo);
1436 ASSERT_EFI_ERROR (Status);
1437 if (FvFileInfo.FileType == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
1438 //
1439 // For FV type file, Produce new FvInfo PPI and FV HOB
1440 //
1441 Status = ProcessFvFile (Private, &Private->Fv[FvCount], PeimFileHandle);
1442 if (Status == EFI_SUCCESS) {
1443 //
1444 // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED
1445 //
1446 Private->Fv[FvCount].PeimState[PeimCount]++;
1447 Private->PeimDispatchOnThisPass = TRUE;
1448 } else {
1449 //
1450 // The related GuidedSectionExtraction/Decompress PPI for the
1451 // encapsulated FV image section may be installed in the rest
1452 // of this do-while loop, so need to make another pass.
1453 //
1454 Private->PeimNeedingDispatch = TRUE;
1455 }
1456 } else {
1457 //
1458 // For PEIM driver, Load its entry point
1459 //
1460 Status = PeiLoadImage (
1461 PeiServices,
1462 PeimFileHandle,
1463 PEIM_STATE_NOT_DISPATCHED,
1464 &EntryPoint,
1465 &AuthenticationState
1466 );
1467 if (Status == EFI_SUCCESS) {
1468 //
1469 // The PEIM has its dependencies satisfied, and its entry point
1470 // has been found, so invoke it.
1471 //
1472 PERF_START_IMAGE_BEGIN (PeimFileHandle);
1473
1474 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
1475 EFI_PROGRESS_CODE,
1476 (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN),
1477 (VOID *)(&PeimFileHandle),
1478 sizeof (PeimFileHandle)
1479 );
1480
1481 Status = VerifyPeim (Private, CoreFvHandle->FvHandle, PeimFileHandle, AuthenticationState);
1482 if (Status != EFI_SECURITY_VIOLATION) {
1483 //
1484 // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED
1485 //
1486 Private->Fv[FvCount].PeimState[PeimCount]++;
1487 //
1488 // Call the PEIM entry point for PEIM driver
1489 //
1490 PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;
1491 PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);
1492 Private->PeimDispatchOnThisPass = TRUE;
1493 } else {
1494 //
1495 // The related GuidedSectionExtraction PPI for the
1496 // signed PEIM image section may be installed in the rest
1497 // of this do-while loop, so need to make another pass.
1498 //
1499 Private->PeimNeedingDispatch = TRUE;
1500 }
1501
1502 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
1503 EFI_PROGRESS_CODE,
1504 (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_END),
1505 (VOID *)(&PeimFileHandle),
1506 sizeof (PeimFileHandle)
1507 );
1508 PERF_START_IMAGE_END (PeimFileHandle);
1509
1510 }
1511 }
1512
1513 PeiCheckAndSwitchStack (SecCoreData, Private);
1514
1515 //
1516 // Process the Notify list and dispatch any notifies for
1517 // newly installed PPIs.
1518 //
1519 ProcessDispatchNotifyList (Private);
1520
1521 //
1522 // Recheck SwitchStackSignal after ProcessDispatchNotifyList()
1523 // in case PeiInstallPeiMemory() is done in a callback with
1524 // EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH.
1525 //
1526 PeiCheckAndSwitchStack (SecCoreData, Private);
1527
1528 if ((Private->PeiMemoryInstalled) && (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_REGISTER_FOR_SHADOW) && \
1529 (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||
1530 (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) ||
1531 PcdGetBool (PcdShadowPeimOnS3Boot))
1532 ) {
1533 //
1534 // If memory is available we shadow images by default for performance reasons.
1535 // We call the entry point a 2nd time so the module knows it's shadowed.
1536 //
1537 //PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0);
1538 if ((Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) && !PcdGetBool (PcdShadowPeimOnBoot) &&
1539 !PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) {
1540 //
1541 // Load PEIM into Memory for Register for shadow PEIM.
1542 //
1543 Status = PeiLoadImage (
1544 PeiServices,
1545 PeimFileHandle,
1546 PEIM_STATE_REGISTER_FOR_SHADOW,
1547 &EntryPoint,
1548 &AuthenticationState
1549 );
1550 if (Status == EFI_SUCCESS) {
1551 PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;
1552 }
1553 }
1554 ASSERT (PeimEntryPoint != NULL);
1555 PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);
1556 //PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0);
1557
1558 //
1559 // PEIM_STATE_REGISTER_FOR_SHADOW move to PEIM_STATE_DONE
1560 //
1561 Private->Fv[FvCount].PeimState[PeimCount]++;
1562
1563 //
1564 // Process the Notify list and dispatch any notifies for
1565 // newly installed PPIs.
1566 //
1567 ProcessDispatchNotifyList (Private);
1568 }
1569 }
1570 }
1571 }
1572
1573 //
1574 // Before walking through the next FV, we should set them to NULL/0 to
1575 // start at the beginning of the next FV.
1576 //
1577 Private->CurrentFileHandle = NULL;
1578 Private->CurrentPeimCount = 0;
1579 Private->CurrentFvFileHandles = NULL;
1580 }
1581
1582 //
1583 // Before making another pass, we should set it to 0 to
1584 // go through all the FVs.
1585 //
1586 Private->CurrentPeimFvCount = 0;
1587
1588 //
1589 // PeimNeedingDispatch being TRUE means we found a PEIM/FV that did not get
1590 // dispatched. So we need to make another pass
1591 //
1592 // PeimDispatchOnThisPass being TRUE means we dispatched a PEIM/FV on this
1593 // pass. If we did not dispatch a PEIM/FV there is no point in trying again
1594 // as it will fail the next time too (nothing has changed).
1595 //
1596 } while (Private->PeimNeedingDispatch && Private->PeimDispatchOnThisPass);
1597
1598 }
1599
1600 /**
1601 Initialize the Dispatcher's data members
1602
1603 @param PrivateData PeiCore's private data structure
1604 @param OldCoreData Old data from SecCore
1605 NULL if being run in non-permanent memory mode.
1606 @param SecCoreData Points to a data structure containing information about the PEI core's operating
1607 environment, such as the size and location of temporary RAM, the stack location and
1608 the BFV location.
1609
1610 @return None.
1611
1612 **/
1613 VOID
1614 InitializeDispatcherData (
1615 IN PEI_CORE_INSTANCE *PrivateData,
1616 IN PEI_CORE_INSTANCE *OldCoreData,
1617 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData
1618 )
1619 {
1620 if (OldCoreData == NULL) {
1621 PrivateData->PeimDispatcherReenter = FALSE;
1622 PeiInitializeFv (PrivateData, SecCoreData);
1623 } else {
1624 PeiReinitializeFv (PrivateData);
1625 }
1626
1627 return;
1628 }
1629
1630 /**
1631 This routine parses the Dependency Expression, if available, and
1632 decides if the module can be executed.
1633
1634
1635 @param Private PeiCore's private data structure
1636 @param FileHandle PEIM's file handle
1637 @param PeimCount Peim count in all dispatched PEIMs.
1638
1639 @retval TRUE Can be dispatched
1640 @retval FALSE Cannot be dispatched
1641
1642 **/
1643 BOOLEAN
1644 DepexSatisfied (
1645 IN PEI_CORE_INSTANCE *Private,
1646 IN EFI_PEI_FILE_HANDLE FileHandle,
1647 IN UINTN PeimCount
1648 )
1649 {
1650 EFI_STATUS Status;
1651 VOID *DepexData;
1652 EFI_FV_FILE_INFO FileInfo;
1653
1654 Status = PeiServicesFfsGetFileInfo (FileHandle, &FileInfo);
1655 if (EFI_ERROR (Status)) {
1656 DEBUG ((DEBUG_DISPATCH, "Evaluate PEI DEPEX for FFS(Unknown)\n"));
1657 } else {
1658 DEBUG ((DEBUG_DISPATCH, "Evaluate PEI DEPEX for FFS(%g)\n", &FileInfo.FileName));
1659 }
1660
1661 if (PeimCount < Private->AprioriCount) {
1662 //
1663 // If it's in the Apriori file then we set DEPEX to TRUE
1664 //
1665 DEBUG ((DEBUG_DISPATCH, " RESULT = TRUE (Apriori)\n"));
1666 return TRUE;
1667 }
1668
1669 //
1670 // Depex section not in the encapsulated section.
1671 //
1672 Status = PeiServicesFfsFindSectionData (
1673 EFI_SECTION_PEI_DEPEX,
1674 FileHandle,
1675 (VOID **)&DepexData
1676 );
1677
1678 if (EFI_ERROR (Status)) {
1679 //
1680 // If there is no DEPEX, assume the module can be executed
1681 //
1682 DEBUG ((DEBUG_DISPATCH, " RESULT = TRUE (No DEPEX)\n"));
1683 return TRUE;
1684 }
1685
1686 //
1687 // Evaluate a given DEPEX
1688 //
1689 return PeimDispatchReadiness (&Private->Ps, DepexData);
1690 }
1691
1692 /**
1693 This routine enables a PEIM to register itself for shadow when the PEI Foundation
1694 discovers permanent memory.
1695
1696 @param FileHandle File handle of a PEIM.
1697
1698 @retval EFI_NOT_FOUND The file handle doesn't point to PEIM itself.
1699 @retval EFI_ALREADY_STARTED Indicate that the PEIM has been registered itself.
1700 @retval EFI_SUCCESS Successfully to register itself.
1701
1702 **/
1703 EFI_STATUS
1704 EFIAPI
1705 PeiRegisterForShadow (
1706 IN EFI_PEI_FILE_HANDLE FileHandle
1707 )
1708 {
1709 PEI_CORE_INSTANCE *Private;
1710 Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());
1711
1712 if (Private->CurrentFileHandle != FileHandle) {
1713 //
1714 // The FileHandle must be for the current PEIM
1715 //
1716 return EFI_NOT_FOUND;
1717 }
1718
1719 if (Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] >= PEIM_STATE_REGISTER_FOR_SHADOW) {
1720 //
1721 // If the PEIM has already entered the PEIM_STATE_REGISTER_FOR_SHADOW or PEIM_STATE_DONE then it's already been started
1722 //
1723 return EFI_ALREADY_STARTED;
1724 }
1725
1726 Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] = PEIM_STATE_REGISTER_FOR_SHADOW;
1727
1728 return EFI_SUCCESS;
1729 }
1730
1731
1732