]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
888887a418885086e314f4a4177c67027b532081
[mirror_edk2.git] / MdeModulePkg / Core / Pei / Dispatcher / Dispatcher.c
1 /** @file
2 EFI PEI Core dispatch services
3
4 Copyright (c) 2006 - 2010, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "PeiMain.h"
16
17 ///
18 /// temporary memory is filled with this initial value during SEC phase
19 ///
20 #define INIT_CAR_VALUE 0x5AA55AA5
21
22 typedef struct {
23 EFI_STATUS_CODE_DATA DataHeader;
24 EFI_HANDLE Handle;
25 } PEIM_FILE_HANDLE_EXTENDED_DATA;
26
27 /**
28
29 Discover all Peims and optional Apriori file in one FV. There is at most one
30 Apriori file in one FV.
31
32
33 @param Private Pointer to the private data passed in from caller
34 @param CoreFileHandle The instance of PEI_CORE_FV_HANDLE.
35
36 **/
37 VOID
38 DiscoverPeimsAndOrderWithApriori (
39 IN PEI_CORE_INSTANCE *Private,
40 IN PEI_CORE_FV_HANDLE *CoreFileHandle
41 )
42 {
43 EFI_STATUS Status;
44 EFI_PEI_FV_HANDLE FileHandle;
45 EFI_PEI_FILE_HANDLE AprioriFileHandle;
46 EFI_GUID *Apriori;
47 UINTN Index;
48 UINTN Index2;
49 UINTN PeimIndex;
50 UINTN PeimCount;
51 EFI_GUID *Guid;
52 EFI_PEI_FV_HANDLE TempFileHandles[FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)];
53 EFI_GUID FileGuid[FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)];
54 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
55 EFI_FV_FILE_INFO FileInfo;
56
57 FvPpi = CoreFileHandle->FvPpi;
58
59 //
60 // Walk the FV and find all the PEIMs and the Apriori file.
61 //
62 AprioriFileHandle = NULL;
63 Private->CurrentFvFileHandles[0] = NULL;
64 Guid = NULL;
65 FileHandle = NULL;
66
67 //
68 // If the current Fv has been scanned, directly get its cachable record.
69 //
70 if (Private->Fv[Private->CurrentPeimFvCount].ScanFv) {
71 CopyMem (Private->CurrentFvFileHandles, Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, sizeof (Private->CurrentFvFileHandles));
72 return;
73 }
74
75 //
76 // Go ahead to scan this Fv, and cache FileHandles within it.
77 //
78 for (PeimCount = 0; PeimCount < PcdGet32 (PcdPeiCoreMaxPeimPerFv); PeimCount++) {
79 Status = FvPpi->FindFileByType (FvPpi, PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE, CoreFileHandle->FvHandle, &FileHandle);
80 if (Status != EFI_SUCCESS) {
81 break;
82 }
83
84 Private->CurrentFvFileHandles[PeimCount] = FileHandle;
85 }
86
87 //
88 // Check whether the count of Peims exceeds the max support PEIMs in a FV image
89 // If more Peims are required in a FV image, PcdPeiCoreMaxPeimPerFv can be set to a larger value in DSC file.
90 //
91 ASSERT (PeimCount < PcdGet32 (PcdPeiCoreMaxPeimPerFv));
92
93 //
94 // Get Apriori File handle
95 //
96 Private->AprioriCount = 0;
97 Status = FvPpi->FindFileByName (FvPpi, &gPeiAprioriFileNameGuid, &CoreFileHandle->FvHandle, &AprioriFileHandle);
98 if (!EFI_ERROR(Status) && AprioriFileHandle != NULL) {
99 //
100 // Read the Apriori file
101 //
102 Status = FvPpi->FindSectionByType (FvPpi, EFI_SECTION_RAW, AprioriFileHandle, (VOID **) &Apriori);
103 if (!EFI_ERROR (Status)) {
104 //
105 // Calculate the number of PEIMs in the A Priori list
106 //
107 Status = FvPpi->GetFileInfo (FvPpi, AprioriFileHandle, &FileInfo);
108 ASSERT_EFI_ERROR (Status);
109 Private->AprioriCount = FileInfo.BufferSize & 0x00FFFFFF;
110 Private->AprioriCount -= sizeof (EFI_COMMON_SECTION_HEADER);
111 Private->AprioriCount /= sizeof (EFI_GUID);
112
113 ZeroMem (FileGuid, sizeof (FileGuid));
114 for (Index = 0; Index < PeimCount; Index++) {
115 //
116 // Make an array of file name guids that matches the FileHandle array so we can convert
117 // quickly from file name to file handle
118 //
119 Status = FvPpi->GetFileInfo (FvPpi, Private->CurrentFvFileHandles[Index], &FileInfo);
120 CopyMem (&FileGuid[Index], &FileInfo.FileName, sizeof(EFI_GUID));
121 }
122
123 //
124 // Walk through FileGuid array to find out who is invalid PEIM guid in Apriori file.
125 // Add avalible PEIMs in Apriori file into TempFileHandles array at first.
126 //
127 Index2 = 0;
128 for (Index = 0; Index2 < Private->AprioriCount; Index++) {
129 while (Index2 < Private->AprioriCount) {
130 Guid = ScanGuid (FileGuid, PeimCount * sizeof (EFI_GUID), &Apriori[Index2++]);
131 if (Guid != NULL) {
132 break;
133 }
134 }
135 if (Guid == NULL) {
136 break;
137 }
138 PeimIndex = ((UINTN)Guid - (UINTN)&FileGuid[0])/sizeof (EFI_GUID);
139 TempFileHandles[Index] = Private->CurrentFvFileHandles[PeimIndex];
140
141 //
142 // Since we have copied the file handle we can remove it from this list.
143 //
144 Private->CurrentFvFileHandles[PeimIndex] = NULL;
145 }
146
147 //
148 // Update valid Aprioricount
149 //
150 Private->AprioriCount = Index;
151
152 //
153 // Add in any PEIMs not in the Apriori file
154 //
155 for (;Index < PeimCount; Index++) {
156 for (Index2 = 0; Index2 < PeimCount; Index2++) {
157 if (Private->CurrentFvFileHandles[Index2] != NULL) {
158 TempFileHandles[Index] = Private->CurrentFvFileHandles[Index2];
159 Private->CurrentFvFileHandles[Index2] = NULL;
160 break;
161 }
162 }
163 }
164 //
165 //Index the end of array contains re-range Pei moudle.
166 //
167 TempFileHandles[Index] = NULL;
168
169 //
170 // Private->CurrentFvFileHandles is currently in PEIM in the FV order.
171 // We need to update it to start with files in the A Priori list and
172 // then the remaining files in PEIM order.
173 //
174 CopyMem (Private->CurrentFvFileHandles, TempFileHandles, sizeof (Private->CurrentFvFileHandles));
175 }
176 }
177 //
178 // Cache the current Fv File Handle. So that we don't have to scan the Fv again.
179 // Instead, we can retrieve the file handles within this Fv from cachable data.
180 //
181 Private->Fv[Private->CurrentPeimFvCount].ScanFv = TRUE;
182 CopyMem (Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, Private->CurrentFvFileHandles, sizeof (Private->CurrentFvFileHandles));
183
184 }
185
186 /**
187 Shadow PeiCore module from flash to installed memory.
188
189 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
190 @param PrivateInMem PeiCore's private data structure
191
192 @return PeiCore function address after shadowing.
193 **/
194 VOID*
195 ShadowPeiCore(
196 IN CONST EFI_PEI_SERVICES **PeiServices,
197 IN PEI_CORE_INSTANCE *PrivateInMem
198 )
199 {
200 EFI_PEI_FILE_HANDLE PeiCoreFileHandle;
201 EFI_PHYSICAL_ADDRESS EntryPoint;
202 EFI_STATUS Status;
203 UINT32 AuthenticationState;
204
205 PeiCoreFileHandle = NULL;
206
207 //
208 // Find the PEI Core in the BFV
209 //
210 Status = PrivateInMem->Fv[0].FvPpi->FindFileByType (
211 PrivateInMem->Fv[0].FvPpi,
212 EFI_FV_FILETYPE_PEI_CORE,
213 PrivateInMem->Fv[0].FvHandle,
214 &PeiCoreFileHandle
215 );
216 ASSERT_EFI_ERROR (Status);
217
218 //
219 // Shadow PEI Core into memory so it will run faster
220 //
221 Status = PeiLoadImage (
222 PeiServices,
223 *((EFI_PEI_FILE_HANDLE*)&PeiCoreFileHandle),
224 PEIM_STATE_REGISITER_FOR_SHADOW,
225 &EntryPoint,
226 &AuthenticationState
227 );
228 ASSERT_EFI_ERROR (Status);
229
230 //
231 // Compute the PeiCore's function address after shaowed PeiCore.
232 // _ModuleEntryPoint is PeiCore main function entry
233 //
234 return (VOID*) ((UINTN) EntryPoint + (UINTN) PeiCore - (UINTN) _ModuleEntryPoint);
235 }
236 //
237 // This is the minimum memory required by DxeCore initialization. When LMFA feature enabled,
238 // This part of memory still need reserved on the very top of memory so that the DXE Core could
239 // use these memory for data initialization. This macro should be sync with the same marco
240 // defined in DXE Core.
241 //
242 #define MINIMUM_INITIAL_MEMORY_SIZE 0x10000
243 /**
244 Hook function for Loading Module at Fixed Address feature
245
246 This function should only be invoked when Loading Module at Fixed Address(LMFA) feature is enabled. When feature is
247 configured as Load Modules at Fix Absolute Address, this function is to validate the top address assigned by user. When
248 feature is configured as Load Modules at Fixed Offset, the functino is to find the top address which is TOLM-TSEG in general.
249 And also the function will re-install PEI memory.
250
251 @param PrivateData Pointer to the private data passed in from caller
252
253 **/
254 VOID
255 PeiLoadFixAddressHook(
256 IN PEI_CORE_INSTANCE *PrivateData
257 )
258 {
259 EFI_PHYSICAL_ADDRESS TopLoadingAddress;
260 UINT64 PeiMemorySize;
261 UINT64 TotalReservedMemorySize;
262 UINT64 MemoryRangeEnd;
263 EFI_PHYSICAL_ADDRESS HighAddress;
264 EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
265 EFI_HOB_RESOURCE_DESCRIPTOR *NextResourceHob;
266 EFI_HOB_RESOURCE_DESCRIPTOR *CurrentResourceHob;
267 EFI_PEI_HOB_POINTERS CurrentHob;
268 EFI_PEI_HOB_POINTERS Hob;
269 EFI_PEI_HOB_POINTERS NextHob;
270 EFI_PHYSICAL_ADDRESS MaxMemoryBaseAddress;
271 UINT64 MaxMemoryLength;
272 //
273 // Initialize Local Variables
274 //
275 CurrentResourceHob = NULL;
276 ResourceHob = NULL;
277 NextResourceHob = NULL;
278 MaxMemoryBaseAddress = 0;
279 MaxMemoryLength = 0;
280 HighAddress = 0;
281 TopLoadingAddress = 0;
282 MemoryRangeEnd = 0;
283 CurrentHob.Raw = PrivateData->HobList.Raw;
284 PeiMemorySize = PrivateData->PhysicalMemoryLength;
285 //
286 // The top reserved memory include 3 parts: the topest range is for DXE core initialization with the size MINIMUM_INITIAL_MEMORY_SIZE
287 // then RuntimeCodePage range and Boot time code range.
288 //
289 TotalReservedMemorySize = MINIMUM_INITIAL_MEMORY_SIZE + EFI_PAGES_TO_SIZE(PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber));
290 TotalReservedMemorySize+= EFI_PAGES_TO_SIZE(PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber)) ;
291 //
292 // PEI memory range lies below the top reserved memory
293 //
294 TotalReservedMemorySize += PeiMemorySize;
295
296 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressRuntimeCodePageNumber= %x.\n", PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber)));
297 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressBootTimeCodePageNumber= %x.\n", PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber)));
298 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressPeiCodePageNumber= %x.\n", PcdGet32(PcdLoadFixAddressPeiCodePageNumber)));
299 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: Total Reserved Memory Size = %lx.\n", TotalReservedMemorySize));
300 //
301 // Loop through the system memory typed hob to merge the adjacent memory range
302 //
303 for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
304 //
305 // See if this is a resource descriptor HOB
306 //
307 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
308
309 ResourceHob = Hob.ResourceDescriptor;
310 //
311 // If range described in this hob is not system memory or heigher than MAX_ADDRESS, ignored.
312 //
313 if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY &&
314 ResourceHob->PhysicalStart + ResourceHob->ResourceLength > MAX_ADDRESS) {
315 continue;
316 }
317
318 for (NextHob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(NextHob); NextHob.Raw = GET_NEXT_HOB(NextHob)) {
319 if (NextHob.Raw == Hob.Raw){
320 continue;
321 }
322 //
323 // See if this is a resource descriptor HOB
324 //
325 if (GET_HOB_TYPE (NextHob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
326
327 NextResourceHob = NextHob.ResourceDescriptor;
328 //
329 // test if range described in this NextResourceHob is system memory and have the same attribute.
330 // Note: Here is a assumption that system memory should always be healthy even without test.
331 //
332 if (NextResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&
333 (((NextResourceHob->ResourceAttribute^ResourceHob->ResourceAttribute)&(~EFI_RESOURCE_ATTRIBUTE_TESTED)) == 0)){
334
335 //
336 // See if the memory range described in ResourceHob and NextResourceHob is adjacent
337 //
338 if ((ResourceHob->PhysicalStart <= NextResourceHob->PhysicalStart &&
339 ResourceHob->PhysicalStart + ResourceHob->ResourceLength >= NextResourceHob->PhysicalStart)||
340 (ResourceHob->PhysicalStart >= NextResourceHob->PhysicalStart&&
341 ResourceHob->PhysicalStart <= NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength)) {
342
343 MemoryRangeEnd = ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength)>(NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength)) ?
344 (ResourceHob->PhysicalStart + ResourceHob->ResourceLength):(NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength);
345
346 ResourceHob->PhysicalStart = (ResourceHob->PhysicalStart < NextResourceHob->PhysicalStart) ?
347 ResourceHob->PhysicalStart : NextResourceHob->PhysicalStart;
348
349
350 ResourceHob->ResourceLength = (MemoryRangeEnd - ResourceHob->PhysicalStart);
351
352 ResourceHob->ResourceAttribute = ResourceHob->ResourceAttribute & (~EFI_RESOURCE_ATTRIBUTE_TESTED);
353 //
354 // Delete the NextResourceHob by marking it as unused.
355 //
356 GET_HOB_TYPE (NextHob) = EFI_HOB_TYPE_UNUSED;
357
358 }
359 }
360 }
361 }
362 }
363 }
364 //
365 // Try to find and validate the TOP address.
366 //
367 if ((INT64)FixedPcdGet64(PcdLoadModuleAtFixAddressEnable) > 0 ) {
368 //
369 // The LMFA feature is enabled as load module at fixed absolute address.
370 //
371 TopLoadingAddress = (EFI_PHYSICAL_ADDRESS)FixedPcdGet64(PcdLoadModuleAtFixAddressEnable);
372 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: Loading module at fixed absolute address.\n"));
373 //
374 // validate the Address. Loop the resource descriptor HOB to make sure the address is in valid memory range
375 //
376 if ((TopLoadingAddress & EFI_PAGE_MASK) != 0) {
377 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR:Top Address %lx is invalid since top address should be page align. \n", TopLoadingAddress));
378 ASSERT (FALSE);
379 }
380 //
381 // Search for a memory region that is below MAX_ADDRESS and in which TopLoadingAddress lies
382 //
383 for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
384 //
385 // See if this is a resource descriptor HOB
386 //
387 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
388
389 ResourceHob = Hob.ResourceDescriptor;
390 //
391 // See if this resource descrior HOB describes tested system memory below MAX_ADDRESS
392 //
393 if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&
394 ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS) {
395 //
396 // See if Top address specified by user is valid.
397 //
398 if (ResourceHob->PhysicalStart + TotalReservedMemorySize < TopLoadingAddress &&
399 (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MINIMUM_INITIAL_MEMORY_SIZE) >= TopLoadingAddress) {
400 CurrentResourceHob = ResourceHob;
401 CurrentHob = Hob;
402 break;
403 }
404 }
405 }
406 }
407 if (CurrentResourceHob != NULL) {
408 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO:Top Address %lx is valid \n", TopLoadingAddress));
409 TopLoadingAddress += MINIMUM_INITIAL_MEMORY_SIZE;
410 } else {
411 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR:Top Address %lx is invalid \n", TopLoadingAddress));
412 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR:The recommended Top Address for the platform is: \n"));
413 //
414 // Print the recomended Top address range.
415 //
416 for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
417 //
418 // See if this is a resource descriptor HOB
419 //
420 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
421
422 ResourceHob = Hob.ResourceDescriptor;
423 //
424 // See if this resource descrior HOB describes tested system memory below MAX_ADDRESS
425 //
426 if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&
427 ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS) {
428 //
429 // See if Top address specified by user is valid.
430 //
431 if (ResourceHob->ResourceLength > TotalReservedMemorySize) {
432 DEBUG ((EFI_D_INFO, "(%lx, %lx)\n",
433 (ResourceHob->PhysicalStart + TotalReservedMemorySize -MINIMUM_INITIAL_MEMORY_SIZE),
434 (ResourceHob->PhysicalStart + ResourceHob->ResourceLength -MINIMUM_INITIAL_MEMORY_SIZE)
435 ));
436 }
437 }
438 }
439 }
440 //
441 // Assert here
442 //
443 ASSERT (FALSE);
444 }
445 } else {
446 //
447 // The LMFA feature is enabled as load module at fixed offset relative to TOLM
448 // Parse the Hob list to find the topest available memory. Generally it is (TOLM - TSEG)
449 //
450 //
451 // Search for a tested memory region that is below MAX_ADDRESS
452 //
453 for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
454 //
455 // See if this is a resource descriptor HOB
456 //
457 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
458
459 ResourceHob = Hob.ResourceDescriptor;
460 //
461 // See if this resource descrior HOB describes tested system memory below MAX_ADDRESS
462 //
463 if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&
464 ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS &&
465 ResourceHob->ResourceLength > TotalReservedMemorySize) {
466 //
467 // See if this is the highest largest system memory region below MaxAddress
468 //
469 if (ResourceHob->PhysicalStart > HighAddress) {
470 CurrentResourceHob = ResourceHob;
471 CurrentHob = Hob;
472 HighAddress = CurrentResourceHob->PhysicalStart;
473 }
474 }
475 }
476 }
477 if (CurrentResourceHob == NULL) {
478 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR:The System Memory is too small\n"));
479 //
480 // Assert here
481 //
482 ASSERT (FALSE);
483 } else {
484 TopLoadingAddress = CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength ;
485 }
486 }
487
488 if (CurrentResourceHob != NULL) {
489 //
490 // rebuild hob for PEI memmory and reserved memory
491 //
492 BuildResourceDescriptorHob (
493 EFI_RESOURCE_SYSTEM_MEMORY, // MemoryType,
494 (
495 EFI_RESOURCE_ATTRIBUTE_PRESENT |
496 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
497 EFI_RESOURCE_ATTRIBUTE_TESTED |
498 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
499 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
500 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
501 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
502 ),
503 (TopLoadingAddress - TotalReservedMemorySize), // MemoryBegin
504 TotalReservedMemorySize // MemoryLength
505 );
506 //
507 // rebuild hob for the remain memory if necessary
508 //
509 if (CurrentResourceHob->PhysicalStart < TopLoadingAddress - TotalReservedMemorySize) {
510 BuildResourceDescriptorHob (
511 EFI_RESOURCE_SYSTEM_MEMORY, // MemoryType,
512 (
513 EFI_RESOURCE_ATTRIBUTE_PRESENT |
514 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
515 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
516 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
517 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
518 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
519 ),
520 CurrentResourceHob->PhysicalStart, // MemoryBegin
521 (TopLoadingAddress - TotalReservedMemorySize - CurrentResourceHob->PhysicalStart) // MemoryLength
522 );
523 }
524 if (CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength > TopLoadingAddress ) {
525 BuildResourceDescriptorHob (
526 EFI_RESOURCE_SYSTEM_MEMORY,
527 (
528 EFI_RESOURCE_ATTRIBUTE_PRESENT |
529 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
530 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
531 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
532 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
533 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
534 ),
535 TopLoadingAddress,
536 (CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength - TopLoadingAddress)
537 );
538 }
539 //
540 // Delete CurrentHob by marking it as unused since the the memory range described by is rebuilt.
541 //
542 GET_HOB_TYPE (CurrentHob) = EFI_HOB_TYPE_UNUSED;
543 }
544
545 //
546 // Cache the top address for Loading Module at Fixed Address feature
547 //
548 PrivateData->LoadModuleAtFixAddressTopAddress = TopLoadingAddress - MINIMUM_INITIAL_MEMORY_SIZE;
549 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: Top address = %lx\n", PrivateData->LoadModuleAtFixAddressTopAddress));
550 //
551 // reinstall the PEI memory relative to TopLoadingAddress
552 //
553 PrivateData->PhysicalMemoryBegin = TopLoadingAddress - TotalReservedMemorySize;
554 PrivateData->FreePhysicalMemoryTop = PrivateData->PhysicalMemoryBegin + PeiMemorySize;
555 }
556 /**
557 Conduct PEIM dispatch.
558
559 @param SecCoreData Points to a data structure containing information about the PEI core's operating
560 environment, such as the size and location of temporary RAM, the stack location and
561 the BFV location.
562 @param Private Pointer to the private data passed in from caller
563
564 **/
565 VOID
566 PeiDispatcher (
567 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
568 IN PEI_CORE_INSTANCE *Private
569 )
570 {
571 EFI_STATUS Status;
572 UINT32 Index1;
573 UINT32 Index2;
574 CONST EFI_PEI_SERVICES **PeiServices;
575 EFI_PEI_FILE_HANDLE PeimFileHandle;
576 UINTN FvCount;
577 UINTN PeimCount;
578 UINT32 AuthenticationState;
579 EFI_PHYSICAL_ADDRESS EntryPoint;
580 EFI_PEIM_ENTRY_POINT2 PeimEntryPoint;
581 UINTN SaveCurrentPeimCount;
582 UINTN SaveCurrentFvCount;
583 EFI_PEI_FILE_HANDLE SaveCurrentFileHandle;
584 PEIM_FILE_HANDLE_EXTENDED_DATA ExtendedData;
585 EFI_PHYSICAL_ADDRESS NewPermenentMemoryBase;
586 TEMPORARY_RAM_SUPPORT_PPI *TemporaryRamSupportPpi;
587 EFI_HOB_HANDOFF_INFO_TABLE *OldHandOffTable;
588 EFI_HOB_HANDOFF_INFO_TABLE *NewHandOffTable;
589 INTN StackOffset;
590 INTN HeapOffset;
591 PEI_CORE_INSTANCE *PrivateInMem;
592 UINT64 NewPeiStackSize;
593 UINT64 OldPeiStackSize;
594 UINT64 StackGap;
595 EFI_FV_FILE_INFO FvFileInfo;
596 UINTN OldCheckingTop;
597 UINTN OldCheckingBottom;
598 PEI_CORE_FV_HANDLE *CoreFvHandle;
599 VOID *LoadFixPeiCodeBegin;
600
601 PeiServices = (CONST EFI_PEI_SERVICES **) &Private->PS;
602 PeimEntryPoint = NULL;
603 PeimFileHandle = NULL;
604 EntryPoint = 0;
605
606 if ((Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
607 //
608 // Once real memory is available, shadow the RegisterForShadow modules. And meanwhile
609 // update the modules' status from PEIM_STATE_REGISITER_FOR_SHADOW to PEIM_STATE_DONE.
610 //
611 SaveCurrentPeimCount = Private->CurrentPeimCount;
612 SaveCurrentFvCount = Private->CurrentPeimFvCount;
613 SaveCurrentFileHandle = Private->CurrentFileHandle;
614
615 for (Index1 = 0; Index1 <= SaveCurrentFvCount; Index1++) {
616 for (Index2 = 0; (Index2 < PcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->Fv[Index1].FvFileHandles[Index2] != NULL); Index2++) {
617 if (Private->Fv[Index1].PeimState[Index2] == PEIM_STATE_REGISITER_FOR_SHADOW) {
618 PeimFileHandle = Private->Fv[Index1].FvFileHandles[Index2];
619 Status = PeiLoadImage (
620 (CONST EFI_PEI_SERVICES **) &Private->PS,
621 PeimFileHandle,
622 PEIM_STATE_REGISITER_FOR_SHADOW,
623 &EntryPoint,
624 &AuthenticationState
625 );
626 if (Status == EFI_SUCCESS) {
627 //
628 // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE
629 //
630 Private->Fv[Index1].PeimState[Index2]++;
631 Private->CurrentFileHandle = PeimFileHandle;
632 Private->CurrentPeimFvCount = Index1;
633 Private->CurrentPeimCount = Index2;
634 //
635 // Call the PEIM entry point
636 //
637 PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;
638
639 PERF_START (PeimFileHandle, "PEIM", NULL, 0);
640 PeimEntryPoint(PeimFileHandle, (const EFI_PEI_SERVICES **) &Private->PS);
641 PERF_END (PeimFileHandle, "PEIM", NULL, 0);
642 }
643
644 //
645 // Process the Notify list and dispatch any notifies for
646 // newly installed PPIs.
647 //
648 ProcessNotifyList (Private);
649 }
650 }
651 }
652 Private->CurrentFileHandle = SaveCurrentFileHandle;
653 Private->CurrentPeimFvCount = SaveCurrentFvCount;
654 Private->CurrentPeimCount = SaveCurrentPeimCount;
655 }
656
657 //
658 // This is the main dispatch loop. It will search known FVs for PEIMs and
659 // attempt to dispatch them. If any PEIM gets dispatched through a single
660 // pass of the dispatcher, it will start over from the Bfv again to see
661 // if any new PEIMs dependencies got satisfied. With a well ordered
662 // FV where PEIMs are found in the order their dependencies are also
663 // satisfied, this dipatcher should run only once.
664 //
665 do {
666 //
667 // In case that reenter PeiCore happens, the last pass record is still available.
668 //
669 if (!Private->PeimDispatcherReenter) {
670 Private->PeimNeedingDispatch = FALSE;
671 Private->PeimDispatchOnThisPass = FALSE;
672 } else {
673 Private->PeimDispatcherReenter = FALSE;
674 }
675
676 for (FvCount = Private->CurrentPeimFvCount; FvCount < Private->FvCount; FvCount++) {
677 CoreFvHandle = FindNextCoreFvHandle (Private, FvCount);
678 ASSERT (CoreFvHandle != NULL);
679
680 //
681 // If the FV has corresponding EFI_PEI_FIRMWARE_VOLUME_PPI instance, then dispatch it.
682 //
683 if (CoreFvHandle->FvPpi == NULL) {
684 continue;
685 }
686
687 Private->CurrentPeimFvCount = FvCount;
688
689 if (Private->CurrentPeimCount == 0) {
690 //
691 // When going through each FV, at first, search Apriori file to
692 // reorder all PEIMs to ensure the PEIMs in Apriori file to get
693 // dispatch at first.
694 //
695 DiscoverPeimsAndOrderWithApriori (Private, CoreFvHandle);
696 }
697
698 //
699 // Start to dispatch all modules within the current Fv.
700 //
701 for (PeimCount = Private->CurrentPeimCount;
702 (PeimCount < PcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->CurrentFvFileHandles[PeimCount] != NULL);
703 PeimCount++) {
704 Private->CurrentPeimCount = PeimCount;
705 PeimFileHandle = Private->CurrentFileHandle = Private->CurrentFvFileHandles[PeimCount];
706
707 if (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_NOT_DISPATCHED) {
708 if (!DepexSatisfied (Private, PeimFileHandle, PeimCount)) {
709 Private->PeimNeedingDispatch = TRUE;
710 } else {
711 Status = CoreFvHandle->FvPpi->GetFileInfo (CoreFvHandle->FvPpi, PeimFileHandle, &FvFileInfo);
712 ASSERT_EFI_ERROR (Status);
713 if (FvFileInfo.FileType == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
714 //
715 // For Fv type file, Produce new FV PPI and FV hob
716 //
717 Status = ProcessFvFile (&Private->Fv[FvCount], PeimFileHandle);
718 AuthenticationState = 0;
719 } else {
720 //
721 // For PEIM driver, Load its entry point
722 //
723 Status = PeiLoadImage (
724 PeiServices,
725 PeimFileHandle,
726 PEIM_STATE_NOT_DISPATCHED,
727 &EntryPoint,
728 &AuthenticationState
729 );
730 }
731
732 if ((Status == EFI_SUCCESS)) {
733 //
734 // The PEIM has its dependencies satisfied, and its entry point
735 // has been found, so invoke it.
736 //
737 PERF_START (PeimFileHandle, "PEIM", NULL, 0);
738
739 ExtendedData.Handle = (EFI_HANDLE)PeimFileHandle;
740
741 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
742 EFI_PROGRESS_CODE,
743 (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN),
744 (VOID *)(&ExtendedData),
745 sizeof (ExtendedData)
746 );
747
748 Status = VerifyPeim (Private, CoreFvHandle->FvHandle, PeimFileHandle);
749 if (Status != EFI_SECURITY_VIOLATION && (AuthenticationState == 0)) {
750 //
751 // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED
752 //
753 Private->Fv[FvCount].PeimState[PeimCount]++;
754
755 if (FvFileInfo.FileType != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
756 //
757 // Call the PEIM entry point for PEIM driver
758 //
759 PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;
760 PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);
761 }
762
763 Private->PeimDispatchOnThisPass = TRUE;
764 }
765
766 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
767 EFI_PROGRESS_CODE,
768 (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN),
769 (VOID *)(&ExtendedData),
770 sizeof (ExtendedData)
771 );
772 PERF_END (PeimFileHandle, "PEIM", NULL, 0);
773
774 }
775
776 if (Private->SwitchStackSignal) {
777 //
778 // Before switch stack from temporary memory to permenent memory, caculate the heap and stack
779 // usage in temporary memory for debuging.
780 //
781 DEBUG_CODE_BEGIN ();
782 UINT32 *StackPointer;
783
784 for (StackPointer = (UINT32*)SecCoreData->StackBase;
785 (StackPointer < (UINT32*)((UINTN)SecCoreData->StackBase + SecCoreData->StackSize)) \
786 && (*StackPointer == INIT_CAR_VALUE);
787 StackPointer ++);
788
789 DEBUG ((EFI_D_INFO, "Total temporary memory: %d bytes.\n", (UINT32)SecCoreData->TemporaryRamSize));
790 DEBUG ((EFI_D_INFO, " temporary memory stack ever used: %d bytes.\n",
791 (SecCoreData->StackSize - ((UINTN) StackPointer - (UINTN)SecCoreData->StackBase))
792 ));
793 DEBUG ((EFI_D_INFO, " temporary memory heap used: %d bytes.\n",
794 ((UINTN) Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom -
795 (UINTN) Private->HobList.Raw)
796 ));
797 DEBUG_CODE_END ();
798
799 if (FixedPcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {
800 //
801 // Loading Module at Fixed Address is enabled
802 //
803 PeiLoadFixAddressHook(Private);
804 }
805
806 //
807 // Reserve the size of new stack at bottom of physical memory
808 //
809 OldPeiStackSize = (UINT64) SecCoreData->StackSize;
810 NewPeiStackSize = (RShiftU64 (Private->PhysicalMemoryLength, 1) + EFI_PAGE_MASK) & ~EFI_PAGE_MASK;
811 if (PcdGet32(PcdPeiCoreMaxPeiStackSize) > (UINT32) NewPeiStackSize) {
812 Private->StackSize = NewPeiStackSize;
813 } else {
814 Private->StackSize = PcdGet32(PcdPeiCoreMaxPeiStackSize);
815 }
816
817 //
818 // In theory, the size of new stack in permenent memory should large than
819 // size of old stack in temporary memory.
820 // But if new stack is smaller than the size of old stack, we also reserve
821 // the size of old stack at bottom of permenent memory.
822 //
823 DEBUG ((EFI_D_INFO, "Old Stack size %d, New stack size %d\n", (INT32) OldPeiStackSize, (INT32) Private->StackSize));
824 ASSERT (Private->StackSize >= OldPeiStackSize);
825 StackGap = Private->StackSize - OldPeiStackSize;
826
827 //
828 // Update HandOffHob for new installed permenent memory
829 //
830 OldHandOffTable = Private->HobList.HandoffInformationTable;
831 OldCheckingBottom = (UINTN)(SecCoreData->TemporaryRamBase);
832 OldCheckingTop = (UINTN)(OldCheckingBottom + SecCoreData->TemporaryRamSize);
833
834 //
835 // The whole temporary memory will be migrated to physical memory.
836 // CAUTION: The new base is computed accounding to gap of new stack.
837 //
838 NewPermenentMemoryBase = Private->PhysicalMemoryBegin + StackGap;
839
840 //
841 // Caculate stack offset and heap offset between temporary memory and new permement
842 // memory seperately.
843 //
844 StackOffset = (UINTN) NewPermenentMemoryBase - (UINTN) SecCoreData->StackBase;
845 HeapOffset = (INTN) ((UINTN) Private->PhysicalMemoryBegin + Private->StackSize - \
846 (UINTN) SecCoreData->PeiTemporaryRamBase);
847 DEBUG ((EFI_D_INFO, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (INT64)HeapOffset, (INT64)StackOffset));
848
849 //
850 // Caculate new HandOffTable and PrivateData address in permenet memory's stack
851 //
852 NewHandOffTable = (EFI_HOB_HANDOFF_INFO_TABLE *)((UINTN)OldHandOffTable + HeapOffset);
853 PrivateInMem = (PEI_CORE_INSTANCE *)((UINTN) (VOID*) Private + StackOffset);
854
855 //
856 // TemporaryRamSupportPpi is produced by platform's SEC
857 //
858 Status = PeiLocatePpi (
859 (CONST EFI_PEI_SERVICES **) PeiServices,
860 &gEfiTemporaryRamSupportPpiGuid,
861 0,
862 NULL,
863 (VOID**)&TemporaryRamSupportPpi
864 );
865
866
867 if (!EFI_ERROR (Status)) {
868 //
869 // Temporary Ram support Ppi is provided by platform, it will copy
870 // temporary memory to permenent memory and do stack switching.
871 // After invoken temporary Ram support, following code's stack is in
872 // memory but not in temporary memory.
873 //
874 TemporaryRamSupportPpi->TemporaryRamMigration (
875 (CONST EFI_PEI_SERVICES **) PeiServices,
876 (EFI_PHYSICAL_ADDRESS)(UINTN) SecCoreData->TemporaryRamBase,
877 (EFI_PHYSICAL_ADDRESS)(UINTN) NewPermenentMemoryBase,
878 SecCoreData->TemporaryRamSize
879 );
880
881 } else {
882 //
883 // In IA32/x64/Itanium architecture, we need platform provide
884 // TEMPORAY_RAM_MIGRATION_PPI.
885 //
886 ASSERT (FALSE);
887 }
888
889
890 //
891 //
892 // Fixup the PeiCore's private data
893 //
894 PrivateInMem->PS = &PrivateInMem->ServiceTableShadow;
895 PrivateInMem->CpuIo = &PrivateInMem->ServiceTableShadow.CpuIo;
896 PrivateInMem->HobList.Raw = (VOID*) ((UINTN) PrivateInMem->HobList.Raw + HeapOffset);
897 PrivateInMem->StackBase = (EFI_PHYSICAL_ADDRESS)(((UINTN)PrivateInMem->PhysicalMemoryBegin + EFI_PAGE_MASK) & ~EFI_PAGE_MASK);
898
899 PeiServices = (CONST EFI_PEI_SERVICES **) &PrivateInMem->PS;
900
901 //
902 // Fixup for PeiService's address
903 //
904 SetPeiServicesTablePointer(PeiServices);
905
906 //
907 // Update HandOffHob for new installed permenent memory
908 //
909 NewHandOffTable->EfiEndOfHobList =
910 (EFI_PHYSICAL_ADDRESS)((UINTN) NewHandOffTable->EfiEndOfHobList + HeapOffset);
911 NewHandOffTable->EfiMemoryTop = PrivateInMem->PhysicalMemoryBegin +
912 PrivateInMem->PhysicalMemoryLength;
913 NewHandOffTable->EfiMemoryBottom = PrivateInMem->PhysicalMemoryBegin;
914 NewHandOffTable->EfiFreeMemoryTop = PrivateInMem->FreePhysicalMemoryTop;
915 NewHandOffTable->EfiFreeMemoryBottom = NewHandOffTable->EfiEndOfHobList +
916 sizeof (EFI_HOB_GENERIC_HEADER);
917
918 //
919 // We need convert the PPI desciptor's pointer
920 //
921 ConvertPpiPointers (PrivateInMem,
922 OldCheckingBottom,
923 OldCheckingTop,
924 HeapOffset
925 );
926
927 DEBUG ((EFI_D_INFO, "Stack Hob: BaseAddress=0x%lX Length=0x%lX\n",
928 PrivateInMem->StackBase,
929 PrivateInMem->StackSize));
930 BuildStackHob (PrivateInMem->StackBase, PrivateInMem->StackSize);
931
932 //
933 // After the whole temporary memory is migrated, then we can allocate page in
934 // permenent memory.
935 //
936 PrivateInMem->PeiMemoryInstalled = TRUE;
937
938 //
939 // Indicate that PeiCore reenter
940 //
941 PrivateInMem->PeimDispatcherReenter = TRUE;
942
943 if (FixedPcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {
944 //
945 // if Loading Module at Fixed Address is enabled, This is the first invoke to page
946 // allocation for Pei Core segment. This memory segment should be reserved for loading PEIM
947 //
948 LoadFixPeiCodeBegin = AllocatePages((UINTN)PcdGet32(PcdLoadFixAddressPeiCodePageNumber));
949 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PeiCodeBegin = %x, PeiCodeTop= %x\n", (UINTN)LoadFixPeiCodeBegin, ((UINTN)LoadFixPeiCodeBegin) + PcdGet32(PcdLoadFixAddressPeiCodePageNumber) * EFI_PAGE_SIZE));
950 //
951 // if Loading Module at Fixed Address is enabled, allocate the PEI code memory range usage bit map array.
952 // Every bit in the array indicate the status of the corresponding memory page, available or not
953 //
954 PrivateInMem->PeiCodeMemoryRangeUsageBitMap = AllocateZeroPool (((PcdGet32(PcdLoadFixAddressPeiCodePageNumber)>>6) + 1)*sizeof(UINT64));
955 }
956 //
957 // Shadow PEI Core. When permanent memory is avaiable, shadow
958 // PEI Core and PEIMs to get high performance.
959 //
960 PrivateInMem->ShadowedPeiCore = ShadowPeiCore (
961 PeiServices,
962 PrivateInMem
963 );
964 //
965 // Process the Notify list and dispatch any notifies for
966 // newly installed PPIs.
967 //
968 ProcessNotifyList (PrivateInMem);
969
970 //
971 // Entry PEI Phase 2
972 //
973 PeiCore (SecCoreData, NULL, PrivateInMem);
974
975 //
976 // Code should not come here
977 //
978 ASSERT_EFI_ERROR(FALSE);
979 }
980
981 //
982 // Process the Notify list and dispatch any notifies for
983 // newly installed PPIs.
984 //
985 ProcessNotifyList (Private);
986
987 if ((Private->PeiMemoryInstalled) && (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_REGISITER_FOR_SHADOW) && \
988 (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
989 //
990 // If memory is availble we shadow images by default for performance reasons.
991 // We call the entry point a 2nd time so the module knows it's shadowed.
992 //
993 //PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0);
994 ASSERT (PeimEntryPoint != NULL);
995 PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);
996 //PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0);
997
998 //
999 // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE
1000 //
1001 Private->Fv[FvCount].PeimState[PeimCount]++;
1002
1003 //
1004 // Process the Notify list and dispatch any notifies for
1005 // newly installed PPIs.
1006 //
1007 ProcessNotifyList (Private);
1008 }
1009 }
1010 }
1011 }
1012
1013 //
1014 // We set to NULL here to optimize the 2nd entry to this routine after
1015 // memory is found. This reprevents rescanning of the FV. We set to
1016 // NULL here so we start at the begining of the next FV
1017 //
1018 Private->CurrentFileHandle = NULL;
1019 Private->CurrentPeimCount = 0;
1020 //
1021 // Before walking through the next FV,Private->CurrentFvFileHandles[]should set to NULL
1022 //
1023 SetMem (Private->CurrentFvFileHandles, sizeof (Private->CurrentFvFileHandles), 0);
1024 }
1025
1026 //
1027 // Before making another pass, we should set Private->CurrentPeimFvCount =0 to go
1028 // through all the FV.
1029 //
1030 Private->CurrentPeimFvCount = 0;
1031
1032 //
1033 // PeimNeedingDispatch being TRUE means we found a PEIM that did not get
1034 // dispatched. So we need to make another pass
1035 //
1036 // PeimDispatchOnThisPass being TRUE means we dispatched a PEIM on this
1037 // pass. If we did not dispatch a PEIM there is no point in trying again
1038 // as it will fail the next time too (nothing has changed).
1039 //
1040 } while (Private->PeimNeedingDispatch && Private->PeimDispatchOnThisPass);
1041
1042 }
1043
1044 /**
1045 Initialize the Dispatcher's data members
1046
1047 @param PrivateData PeiCore's private data structure
1048 @param OldCoreData Old data from SecCore
1049 NULL if being run in non-permament memory mode.
1050 @param SecCoreData Points to a data structure containing information about the PEI core's operating
1051 environment, such as the size and location of temporary RAM, the stack location and
1052 the BFV location.
1053
1054 @return None.
1055
1056 **/
1057 VOID
1058 InitializeDispatcherData (
1059 IN PEI_CORE_INSTANCE *PrivateData,
1060 IN PEI_CORE_INSTANCE *OldCoreData,
1061 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData
1062 )
1063 {
1064 if (OldCoreData == NULL) {
1065 PrivateData->PeimDispatcherReenter = FALSE;
1066 PeiInitializeFv (PrivateData, SecCoreData);
1067 } else {
1068 PeiReinitializeFv (PrivateData);
1069 }
1070
1071 return;
1072 }
1073
1074 /**
1075 This routine parses the Dependency Expression, if available, and
1076 decides if the module can be executed.
1077
1078
1079 @param Private PeiCore's private data structure
1080 @param FileHandle PEIM's file handle
1081 @param PeimCount Peim count in all dispatched PEIMs.
1082
1083 @retval TRUE Can be dispatched
1084 @retval FALSE Cannot be dispatched
1085
1086 **/
1087 BOOLEAN
1088 DepexSatisfied (
1089 IN PEI_CORE_INSTANCE *Private,
1090 IN EFI_PEI_FILE_HANDLE FileHandle,
1091 IN UINTN PeimCount
1092 )
1093 {
1094 EFI_STATUS Status;
1095 VOID *DepexData;
1096
1097 if (PeimCount < Private->AprioriCount) {
1098 //
1099 // If its in the A priori file then we set Depex to TRUE
1100 //
1101 return TRUE;
1102 }
1103
1104 //
1105 // Depex section not in the encapsulated section.
1106 //
1107 Status = PeiServicesFfsFindSectionData (
1108 EFI_SECTION_PEI_DEPEX,
1109 FileHandle,
1110 (VOID **)&DepexData
1111 );
1112
1113 if (EFI_ERROR (Status)) {
1114 //
1115 // If there is no DEPEX, assume the module can be executed
1116 //
1117 return TRUE;
1118 }
1119
1120 //
1121 // Evaluate a given DEPEX
1122 //
1123 return PeimDispatchReadiness (&Private->PS, DepexData);
1124 }
1125
1126 /**
1127 This routine enable a PEIM to register itself to shadow when PEI Foundation
1128 discovery permanent memory.
1129
1130 @param FileHandle File handle of a PEIM.
1131
1132 @retval EFI_NOT_FOUND The file handle doesn't point to PEIM itself.
1133 @retval EFI_ALREADY_STARTED Indicate that the PEIM has been registered itself.
1134 @retval EFI_SUCCESS Successfully to register itself.
1135
1136 **/
1137 EFI_STATUS
1138 EFIAPI
1139 PeiRegisterForShadow (
1140 IN EFI_PEI_FILE_HANDLE FileHandle
1141 )
1142 {
1143 PEI_CORE_INSTANCE *Private;
1144 Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());
1145
1146 if (Private->CurrentFileHandle != FileHandle) {
1147 //
1148 // The FileHandle must be for the current PEIM
1149 //
1150 return EFI_NOT_FOUND;
1151 }
1152
1153 if (Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] >= PEIM_STATE_REGISITER_FOR_SHADOW) {
1154 //
1155 // If the PEIM has already entered the PEIM_STATE_REGISTER_FOR_SHADOW or PEIM_STATE_DONE then it's already been started
1156 //
1157 return EFI_ALREADY_STARTED;
1158 }
1159
1160 Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] = PEIM_STATE_REGISITER_FOR_SHADOW;
1161
1162 return EFI_SUCCESS;
1163 }
1164
1165
1166