]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
Remove reference to PCDs of status code value. Use macros introduced in PI1.2 instead.
[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 < FixedPcdGet32 (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 < FixedPcdGet32 (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 /**
238 Conduct PEIM dispatch.
239
240 @param SecCoreData Points to a data structure containing information about the PEI core's operating
241 environment, such as the size and location of temporary RAM, the stack location and
242 the BFV location.
243 @param Private Pointer to the private data passed in from caller
244
245 **/
246 VOID
247 PeiDispatcher (
248 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
249 IN PEI_CORE_INSTANCE *Private
250 )
251 {
252 EFI_STATUS Status;
253 UINT32 Index1;
254 UINT32 Index2;
255 CONST EFI_PEI_SERVICES **PeiServices;
256 EFI_PEI_FILE_HANDLE PeimFileHandle;
257 UINTN FvCount;
258 UINTN PeimCount;
259 UINT32 AuthenticationState;
260 EFI_PHYSICAL_ADDRESS EntryPoint;
261 EFI_PEIM_ENTRY_POINT2 PeimEntryPoint;
262 UINTN SaveCurrentPeimCount;
263 UINTN SaveCurrentFvCount;
264 EFI_PEI_FILE_HANDLE SaveCurrentFileHandle;
265 PEIM_FILE_HANDLE_EXTENDED_DATA ExtendedData;
266 EFI_PHYSICAL_ADDRESS NewPermenentMemoryBase;
267 TEMPORARY_RAM_SUPPORT_PPI *TemporaryRamSupportPpi;
268 EFI_HOB_HANDOFF_INFO_TABLE *OldHandOffTable;
269 EFI_HOB_HANDOFF_INFO_TABLE *NewHandOffTable;
270 INTN StackOffset;
271 INTN HeapOffset;
272 PEI_CORE_INSTANCE *PrivateInMem;
273 UINT64 NewPeiStackSize;
274 UINT64 OldPeiStackSize;
275 UINT64 StackGap;
276 EFI_FV_FILE_INFO FvFileInfo;
277 UINTN OldCheckingTop;
278 UINTN OldCheckingBottom;
279 PEI_CORE_FV_HANDLE *CoreFvHandle;
280
281 PeiServices = (CONST EFI_PEI_SERVICES **) &Private->PS;
282 PeimEntryPoint = NULL;
283 PeimFileHandle = NULL;
284 EntryPoint = 0;
285
286 if ((Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
287 //
288 // Once real memory is available, shadow the RegisterForShadow modules. And meanwhile
289 // update the modules' status from PEIM_STATE_REGISITER_FOR_SHADOW to PEIM_STATE_DONE.
290 //
291 SaveCurrentPeimCount = Private->CurrentPeimCount;
292 SaveCurrentFvCount = Private->CurrentPeimFvCount;
293 SaveCurrentFileHandle = Private->CurrentFileHandle;
294
295 for (Index1 = 0; Index1 <= SaveCurrentFvCount; Index1++) {
296 for (Index2 = 0; (Index2 < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->Fv[Index1].FvFileHandles[Index2] != NULL); Index2++) {
297 if (Private->Fv[Index1].PeimState[Index2] == PEIM_STATE_REGISITER_FOR_SHADOW) {
298 PeimFileHandle = Private->Fv[Index1].FvFileHandles[Index2];
299 Status = PeiLoadImage (
300 (CONST EFI_PEI_SERVICES **) &Private->PS,
301 PeimFileHandle,
302 PEIM_STATE_REGISITER_FOR_SHADOW,
303 &EntryPoint,
304 &AuthenticationState
305 );
306 if (Status == EFI_SUCCESS) {
307 //
308 // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE
309 //
310 Private->Fv[Index1].PeimState[Index2]++;
311 Private->CurrentFileHandle = PeimFileHandle;
312 Private->CurrentPeimFvCount = Index1;
313 Private->CurrentPeimCount = Index2;
314 //
315 // Call the PEIM entry point
316 //
317 PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;
318
319 PERF_START (0, "PEIM", NULL, 0);
320 PeimEntryPoint(PeimFileHandle, (const EFI_PEI_SERVICES **) &Private->PS);
321 PERF_END (0, "PEIM", NULL, 0);
322 }
323
324 //
325 // Process the Notify list and dispatch any notifies for
326 // newly installed PPIs.
327 //
328 ProcessNotifyList (Private);
329 }
330 }
331 }
332 Private->CurrentFileHandle = SaveCurrentFileHandle;
333 Private->CurrentPeimFvCount = SaveCurrentFvCount;
334 Private->CurrentPeimCount = SaveCurrentPeimCount;
335 }
336
337 //
338 // This is the main dispatch loop. It will search known FVs for PEIMs and
339 // attempt to dispatch them. If any PEIM gets dispatched through a single
340 // pass of the dispatcher, it will start over from the Bfv again to see
341 // if any new PEIMs dependencies got satisfied. With a well ordered
342 // FV where PEIMs are found in the order their dependencies are also
343 // satisfied, this dipatcher should run only once.
344 //
345 do {
346 //
347 // In case that reenter PeiCore happens, the last pass record is still available.
348 //
349 if (!Private->PeimDispatcherReenter) {
350 Private->PeimNeedingDispatch = FALSE;
351 Private->PeimDispatchOnThisPass = FALSE;
352 } else {
353 Private->PeimDispatcherReenter = FALSE;
354 }
355
356 for (FvCount = Private->CurrentPeimFvCount; FvCount < Private->FvCount; FvCount++) {
357 CoreFvHandle = FindNextCoreFvHandle (Private, FvCount);
358 ASSERT (CoreFvHandle != NULL);
359
360 //
361 // If the FV has corresponding EFI_PEI_FIRMWARE_VOLUME_PPI instance, then dispatch it.
362 //
363 if (CoreFvHandle->FvPpi == NULL) {
364 continue;
365 }
366
367 Private->CurrentPeimFvCount = FvCount;
368
369 if (Private->CurrentPeimCount == 0) {
370 //
371 // When going through each FV, at first, search Apriori file to
372 // reorder all PEIMs to ensure the PEIMs in Apriori file to get
373 // dispatch at first.
374 //
375 DiscoverPeimsAndOrderWithApriori (Private, CoreFvHandle);
376 }
377
378 //
379 // Start to dispatch all modules within the current Fv.
380 //
381 for (PeimCount = Private->CurrentPeimCount;
382 (PeimCount < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->CurrentFvFileHandles[PeimCount] != NULL);
383 PeimCount++) {
384 Private->CurrentPeimCount = PeimCount;
385 PeimFileHandle = Private->CurrentFileHandle = Private->CurrentFvFileHandles[PeimCount];
386
387 if (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_NOT_DISPATCHED) {
388 if (!DepexSatisfied (Private, PeimFileHandle, PeimCount)) {
389 Private->PeimNeedingDispatch = TRUE;
390 } else {
391 Status = CoreFvHandle->FvPpi->GetFileInfo (CoreFvHandle->FvPpi, PeimFileHandle, &FvFileInfo);
392 ASSERT_EFI_ERROR (Status);
393 if (FvFileInfo.FileType == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
394 //
395 // For Fv type file, Produce new FV PPI and FV hob
396 //
397 Status = ProcessFvFile (&Private->Fv[FvCount], PeimFileHandle);
398 AuthenticationState = 0;
399 } else {
400 //
401 // For PEIM driver, Load its entry point
402 //
403 Status = PeiLoadImage (
404 PeiServices,
405 PeimFileHandle,
406 PEIM_STATE_NOT_DISPATCHED,
407 &EntryPoint,
408 &AuthenticationState
409 );
410 }
411
412 if ((Status == EFI_SUCCESS)) {
413 //
414 // The PEIM has its dependencies satisfied, and its entry point
415 // has been found, so invoke it.
416 //
417 PERF_START (0, "PEIM", NULL, 0);
418
419 ExtendedData.Handle = (EFI_HANDLE)PeimFileHandle;
420
421 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
422 EFI_PROGRESS_CODE,
423 (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN),
424 (VOID *)(&ExtendedData),
425 sizeof (ExtendedData)
426 );
427
428 Status = VerifyPeim (Private, CoreFvHandle->FvHandle, PeimFileHandle);
429 if (Status != EFI_SECURITY_VIOLATION && (AuthenticationState == 0)) {
430 //
431 // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED
432 //
433 Private->Fv[FvCount].PeimState[PeimCount]++;
434
435 if (FvFileInfo.FileType != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
436 //
437 // Call the PEIM entry point for PEIM driver
438 //
439 PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;
440 PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);
441 }
442
443 Private->PeimDispatchOnThisPass = TRUE;
444 }
445
446 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
447 EFI_PROGRESS_CODE,
448 (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN),
449 (VOID *)(&ExtendedData),
450 sizeof (ExtendedData)
451 );
452 PERF_END (0, "PEIM", NULL, 0);
453
454 }
455
456 if (Private->SwitchStackSignal) {
457 //
458 // Before switch stack from temporary memory to permenent memory, caculate the heap and stack
459 // usage in temporary memory for debuging.
460 //
461 DEBUG_CODE_BEGIN ();
462 UINT32 *StackPointer;
463
464 for (StackPointer = (UINT32*)SecCoreData->StackBase;
465 (StackPointer < (UINT32*)((UINTN)SecCoreData->StackBase + SecCoreData->StackSize)) \
466 && (*StackPointer == INIT_CAR_VALUE);
467 StackPointer ++);
468
469 DEBUG ((EFI_D_INFO, "Total temporary memory: %d bytes.\n", (UINT32)SecCoreData->TemporaryRamSize));
470 DEBUG ((EFI_D_INFO, " temporary memory stack ever used: %d bytes.\n",
471 (SecCoreData->StackSize - ((UINTN) StackPointer - (UINTN)SecCoreData->StackBase))
472 ));
473 DEBUG ((EFI_D_INFO, " temporary memory heap used: %d bytes.\n",
474 ((UINTN) Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom -
475 (UINTN) Private->HobList.Raw)
476 ));
477 DEBUG_CODE_END ();
478
479 //
480 // Reserve the size of new stack at bottom of physical memory
481 //
482 OldPeiStackSize = (UINT64) SecCoreData->StackSize;
483 NewPeiStackSize = (RShiftU64 (Private->PhysicalMemoryLength, 1) + EFI_PAGE_MASK) & ~EFI_PAGE_MASK;
484 if (PcdGet32(PcdPeiCoreMaxPeiStackSize) > (UINT32) NewPeiStackSize) {
485 Private->StackSize = NewPeiStackSize;
486 } else {
487 Private->StackSize = PcdGet32(PcdPeiCoreMaxPeiStackSize);
488 }
489
490 //
491 // In theory, the size of new stack in permenent memory should large than
492 // size of old stack in temporary memory.
493 // But if new stack is smaller than the size of old stack, we also reserve
494 // the size of old stack at bottom of permenent memory.
495 //
496 DEBUG ((EFI_D_INFO, "Old Stack size %d, New stack size %d\n", (INT32) OldPeiStackSize, (INT32) Private->StackSize));
497 ASSERT (Private->StackSize >= OldPeiStackSize);
498 StackGap = Private->StackSize - OldPeiStackSize;
499
500 //
501 // Update HandOffHob for new installed permenent memory
502 //
503 OldHandOffTable = Private->HobList.HandoffInformationTable;
504 OldCheckingBottom = (UINTN)(SecCoreData->TemporaryRamBase);
505 OldCheckingTop = (UINTN)(OldCheckingBottom + SecCoreData->TemporaryRamSize);
506
507 //
508 // The whole temporary memory will be migrated to physical memory.
509 // CAUTION: The new base is computed accounding to gap of new stack.
510 //
511 NewPermenentMemoryBase = Private->PhysicalMemoryBegin + StackGap;
512
513 //
514 // Caculate stack offset and heap offset between temporary memory and new permement
515 // memory seperately.
516 //
517 StackOffset = (UINTN) NewPermenentMemoryBase - (UINTN) SecCoreData->StackBase;
518 HeapOffset = (INTN) ((UINTN) Private->PhysicalMemoryBegin + Private->StackSize - \
519 (UINTN) SecCoreData->PeiTemporaryRamBase);
520 DEBUG ((EFI_D_INFO, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (INT64)HeapOffset, (INT64)StackOffset));
521
522 //
523 // Caculate new HandOffTable and PrivateData address in permenet memory's stack
524 //
525 NewHandOffTable = (EFI_HOB_HANDOFF_INFO_TABLE *)((UINTN)OldHandOffTable + HeapOffset);
526 PrivateInMem = (PEI_CORE_INSTANCE *)((UINTN) (VOID*) Private + StackOffset);
527
528 //
529 // TemporaryRamSupportPpi is produced by platform's SEC
530 //
531 Status = PeiLocatePpi (
532 (CONST EFI_PEI_SERVICES **) PeiServices,
533 &gEfiTemporaryRamSupportPpiGuid,
534 0,
535 NULL,
536 (VOID**)&TemporaryRamSupportPpi
537 );
538
539
540 if (!EFI_ERROR (Status)) {
541 //
542 // Temporary Ram support Ppi is provided by platform, it will copy
543 // temporary memory to permenent memory and do stack switching.
544 // After invoken temporary Ram support, following code's stack is in
545 // memory but not in temporary memory.
546 //
547 TemporaryRamSupportPpi->TemporaryRamMigration (
548 (CONST EFI_PEI_SERVICES **) PeiServices,
549 (EFI_PHYSICAL_ADDRESS)(UINTN) SecCoreData->TemporaryRamBase,
550 (EFI_PHYSICAL_ADDRESS)(UINTN) NewPermenentMemoryBase,
551 SecCoreData->TemporaryRamSize
552 );
553
554 } else {
555 //
556 // In IA32/x64/Itanium architecture, we need platform provide
557 // TEMPORAY_RAM_MIGRATION_PPI.
558 //
559 ASSERT (FALSE);
560 }
561
562
563 //
564 //
565 // Fixup the PeiCore's private data
566 //
567 PrivateInMem->PS = &PrivateInMem->ServiceTableShadow;
568 PrivateInMem->CpuIo = &PrivateInMem->ServiceTableShadow.CpuIo;
569 PrivateInMem->HobList.Raw = (VOID*) ((UINTN) PrivateInMem->HobList.Raw + HeapOffset);
570 PrivateInMem->StackBase = (EFI_PHYSICAL_ADDRESS)(((UINTN)PrivateInMem->PhysicalMemoryBegin + EFI_PAGE_MASK) & ~EFI_PAGE_MASK);
571
572 PeiServices = (CONST EFI_PEI_SERVICES **) &PrivateInMem->PS;
573
574 //
575 // Fixup for PeiService's address
576 //
577 SetPeiServicesTablePointer(PeiServices);
578
579 //
580 // Update HandOffHob for new installed permenent memory
581 //
582 NewHandOffTable->EfiEndOfHobList =
583 (EFI_PHYSICAL_ADDRESS)((UINTN) NewHandOffTable->EfiEndOfHobList + HeapOffset);
584 NewHandOffTable->EfiMemoryTop = PrivateInMem->PhysicalMemoryBegin +
585 PrivateInMem->PhysicalMemoryLength;
586 NewHandOffTable->EfiMemoryBottom = PrivateInMem->PhysicalMemoryBegin;
587 NewHandOffTable->EfiFreeMemoryTop = PrivateInMem->FreePhysicalMemoryTop;
588 NewHandOffTable->EfiFreeMemoryBottom = NewHandOffTable->EfiEndOfHobList +
589 sizeof (EFI_HOB_GENERIC_HEADER);
590
591 //
592 // We need convert the PPI desciptor's pointer
593 //
594 ConvertPpiPointers (PrivateInMem,
595 OldCheckingBottom,
596 OldCheckingTop,
597 HeapOffset
598 );
599
600 DEBUG ((EFI_D_INFO, "Stack Hob: BaseAddress=0x%lX Length=0x%lX\n",
601 PrivateInMem->StackBase,
602 PrivateInMem->StackSize));
603 BuildStackHob (PrivateInMem->StackBase, PrivateInMem->StackSize);
604
605 //
606 // After the whole temporary memory is migrated, then we can allocate page in
607 // permenent memory.
608 //
609 PrivateInMem->PeiMemoryInstalled = TRUE;
610
611 //
612 // Indicate that PeiCore reenter
613 //
614 PrivateInMem->PeimDispatcherReenter = TRUE;
615
616 //
617 // Shadow PEI Core. When permanent memory is avaiable, shadow
618 // PEI Core and PEIMs to get high performance.
619 //
620 PrivateInMem->ShadowedPeiCore = ShadowPeiCore (
621 PeiServices,
622 PrivateInMem
623 );
624 //
625 // Process the Notify list and dispatch any notifies for
626 // newly installed PPIs.
627 //
628 ProcessNotifyList (PrivateInMem);
629
630 //
631 // Entry PEI Phase 2
632 //
633 PeiCore (SecCoreData, NULL, PrivateInMem);
634
635 //
636 // Code should not come here
637 //
638 ASSERT_EFI_ERROR(FALSE);
639 }
640
641 //
642 // Process the Notify list and dispatch any notifies for
643 // newly installed PPIs.
644 //
645 ProcessNotifyList (Private);
646
647 if ((Private->PeiMemoryInstalled) && (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_REGISITER_FOR_SHADOW) && \
648 (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
649 //
650 // If memory is availble we shadow images by default for performance reasons.
651 // We call the entry point a 2nd time so the module knows it's shadowed.
652 //
653 //PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0);
654 ASSERT (PeimEntryPoint != NULL);
655 PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);
656 //PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0);
657
658 //
659 // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE
660 //
661 Private->Fv[FvCount].PeimState[PeimCount]++;
662
663 //
664 // Process the Notify list and dispatch any notifies for
665 // newly installed PPIs.
666 //
667 ProcessNotifyList (Private);
668 }
669 }
670 }
671 }
672
673 //
674 // We set to NULL here to optimize the 2nd entry to this routine after
675 // memory is found. This reprevents rescanning of the FV. We set to
676 // NULL here so we start at the begining of the next FV
677 //
678 Private->CurrentFileHandle = NULL;
679 Private->CurrentPeimCount = 0;
680 //
681 // Before walking through the next FV,Private->CurrentFvFileHandles[]should set to NULL
682 //
683 SetMem (Private->CurrentFvFileHandles, sizeof (Private->CurrentFvFileHandles), 0);
684 }
685
686 //
687 // Before making another pass, we should set Private->CurrentPeimFvCount =0 to go
688 // through all the FV.
689 //
690 Private->CurrentPeimFvCount = 0;
691
692 //
693 // PeimNeedingDispatch being TRUE means we found a PEIM that did not get
694 // dispatched. So we need to make another pass
695 //
696 // PeimDispatchOnThisPass being TRUE means we dispatched a PEIM on this
697 // pass. If we did not dispatch a PEIM there is no point in trying again
698 // as it will fail the next time too (nothing has changed).
699 //
700 } while (Private->PeimNeedingDispatch && Private->PeimDispatchOnThisPass);
701
702 }
703
704 /**
705 Initialize the Dispatcher's data members
706
707 @param PrivateData PeiCore's private data structure
708 @param OldCoreData Old data from SecCore
709 NULL if being run in non-permament memory mode.
710 @param SecCoreData Points to a data structure containing information about the PEI core's operating
711 environment, such as the size and location of temporary RAM, the stack location and
712 the BFV location.
713
714 @return None.
715
716 **/
717 VOID
718 InitializeDispatcherData (
719 IN PEI_CORE_INSTANCE *PrivateData,
720 IN PEI_CORE_INSTANCE *OldCoreData,
721 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData
722 )
723 {
724 if (OldCoreData == NULL) {
725 PrivateData->PeimDispatcherReenter = FALSE;
726 PeiInitializeFv (PrivateData, SecCoreData);
727 } else {
728 PeiReinitializeFv (PrivateData);
729 }
730
731 return;
732 }
733
734 /**
735 This routine parses the Dependency Expression, if available, and
736 decides if the module can be executed.
737
738
739 @param Private PeiCore's private data structure
740 @param FileHandle PEIM's file handle
741 @param PeimCount Peim count in all dispatched PEIMs.
742
743 @retval TRUE Can be dispatched
744 @retval FALSE Cannot be dispatched
745
746 **/
747 BOOLEAN
748 DepexSatisfied (
749 IN PEI_CORE_INSTANCE *Private,
750 IN EFI_PEI_FILE_HANDLE FileHandle,
751 IN UINTN PeimCount
752 )
753 {
754 EFI_STATUS Status;
755 VOID *DepexData;
756
757 if (PeimCount < Private->AprioriCount) {
758 //
759 // If its in the A priori file then we set Depex to TRUE
760 //
761 return TRUE;
762 }
763
764 //
765 // Depex section not in the encapsulated section.
766 //
767 Status = PeiServicesFfsFindSectionData (
768 EFI_SECTION_PEI_DEPEX,
769 FileHandle,
770 (VOID **)&DepexData
771 );
772
773 if (EFI_ERROR (Status)) {
774 //
775 // If there is no DEPEX, assume the module can be executed
776 //
777 return TRUE;
778 }
779
780 //
781 // Evaluate a given DEPEX
782 //
783 return PeimDispatchReadiness (&Private->PS, DepexData);
784 }
785
786 /**
787 This routine enable a PEIM to register itself to shadow when PEI Foundation
788 discovery permanent memory.
789
790 @param FileHandle File handle of a PEIM.
791
792 @retval EFI_NOT_FOUND The file handle doesn't point to PEIM itself.
793 @retval EFI_ALREADY_STARTED Indicate that the PEIM has been registered itself.
794 @retval EFI_SUCCESS Successfully to register itself.
795
796 **/
797 EFI_STATUS
798 EFIAPI
799 PeiRegisterForShadow (
800 IN EFI_PEI_FILE_HANDLE FileHandle
801 )
802 {
803 PEI_CORE_INSTANCE *Private;
804 Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());
805
806 if (Private->CurrentFileHandle != FileHandle) {
807 //
808 // The FileHandle must be for the current PEIM
809 //
810 return EFI_NOT_FOUND;
811 }
812
813 if (Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] >= PEIM_STATE_REGISITER_FOR_SHADOW) {
814 //
815 // If the PEIM has already entered the PEIM_STATE_REGISTER_FOR_SHADOW or PEIM_STATE_DONE then it's already been started
816 //
817 return EFI_ALREADY_STARTED;
818 }
819
820 Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] = PEIM_STATE_REGISITER_FOR_SHADOW;
821
822 return EFI_SUCCESS;
823 }
824
825
826