]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
f64003db38d925c0a2ed8b8ebbcddb53d3f46203
[mirror_edk2.git] / MdeModulePkg / Core / Pei / Dispatcher / Dispatcher.c
1 /** @file
2 EFI PEI Core dispatch services
3
4 Copyright (c) 2006 - 2009, 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 VolumeHandle - Fv handle.
35
36 **/
37 VOID
38 DiscoverPeimsAndOrderWithApriori (
39 IN PEI_CORE_INSTANCE *Private,
40 IN EFI_PEI_FV_HANDLE VolumeHandle
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
55 //
56 // Walk the FV and find all the PEIMs and the Apriori file.
57 //
58 AprioriFileHandle = NULL;
59 Private->CurrentFvFileHandles[0] = NULL;
60 Guid = NULL;
61 FileHandle = NULL;
62
63 //
64 // If the current Fv has been scanned, directly get its cachable record.
65 //
66 if (Private->Fv[Private->CurrentPeimFvCount].ScanFv) {
67 CopyMem (Private->CurrentFvFileHandles, Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, sizeof (Private->CurrentFvFileHandles));
68 return;
69 }
70
71 //
72 // Go ahead to scan this Fv, and cache FileHandles within it.
73 //
74 for (PeimCount = 0; PeimCount < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv); PeimCount++) {
75 Status = PeiFindFileEx (
76 VolumeHandle,
77 NULL,
78 PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE,
79 &FileHandle,
80 &AprioriFileHandle
81 );
82 if (Status != EFI_SUCCESS) {
83 break;
84 }
85
86 Private->CurrentFvFileHandles[PeimCount] = FileHandle;
87 }
88
89 //
90 // Check whether the count of Peims exceeds the max support PEIMs in a FV image
91 // If more Peims are required in a FV image, PcdPeiCoreMaxPeimPerFv can be set to a larger value in DSC file.
92 //
93 ASSERT (PeimCount < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv));
94
95 Private->AprioriCount = 0;
96 if (AprioriFileHandle != NULL) {
97 //
98 // Read the Apriori file
99 //
100 Status = PeiServicesFfsFindSectionData (EFI_SECTION_RAW, AprioriFileHandle, (VOID **) &Apriori);
101 if (!EFI_ERROR (Status)) {
102 //
103 // Calculate the number of PEIMs in the A Priori list
104 //
105 Private->AprioriCount = *(UINT32 *)(((EFI_FFS_FILE_HEADER *)AprioriFileHandle)->Size) & 0x00FFFFFF;
106 Private->AprioriCount -= sizeof (EFI_FFS_FILE_HEADER) - sizeof (EFI_COMMON_SECTION_HEADER);
107 Private->AprioriCount /= sizeof (EFI_GUID);
108
109 ZeroMem (FileGuid, sizeof (FileGuid));
110 for (Index = 0; Index < PeimCount; Index++) {
111 //
112 // Make an array of file name guids that matches the FileHandle array so we can convert
113 // quickly from file name to file handle
114 //
115 CopyMem (&FileGuid[Index], &((EFI_FFS_FILE_HEADER *)Private->CurrentFvFileHandles[Index])->Name,sizeof(EFI_GUID));
116 }
117
118 //
119 // Walk through FileGuid array to find out who is invalid PEIM guid in Apriori file.
120 // Add avalible PEIMs in Apriori file into TempFileHandles array at first.
121 //
122 Index2 = 0;
123 for (Index = 0; Index2 < Private->AprioriCount; Index++) {
124 while (Index2 < Private->AprioriCount) {
125 Guid = ScanGuid (FileGuid, PeimCount * sizeof (EFI_GUID), &Apriori[Index2++]);
126 if (Guid != NULL) {
127 break;
128 }
129 }
130 if (Guid == NULL) {
131 break;
132 }
133 PeimIndex = ((UINTN)Guid - (UINTN)&FileGuid[0])/sizeof (EFI_GUID);
134 TempFileHandles[Index] = Private->CurrentFvFileHandles[PeimIndex];
135
136 //
137 // Since we have copied the file handle we can remove it from this list.
138 //
139 Private->CurrentFvFileHandles[PeimIndex] = NULL;
140 }
141
142 //
143 // Update valid Aprioricount
144 //
145 Private->AprioriCount = Index;
146
147 //
148 // Add in any PEIMs not in the Apriori file
149 //
150 for (;Index < PeimCount; Index++) {
151 for (Index2 = 0; Index2 < PeimCount; Index2++) {
152 if (Private->CurrentFvFileHandles[Index2] != NULL) {
153 TempFileHandles[Index] = Private->CurrentFvFileHandles[Index2];
154 Private->CurrentFvFileHandles[Index2] = NULL;
155 break;
156 }
157 }
158 }
159 //
160 //Index the end of array contains re-range Pei moudle.
161 //
162 TempFileHandles[Index] = NULL;
163
164 //
165 // Private->CurrentFvFileHandles is currently in PEIM in the FV order.
166 // We need to update it to start with files in the A Priori list and
167 // then the remaining files in PEIM order.
168 //
169 CopyMem (Private->CurrentFvFileHandles, TempFileHandles, sizeof (Private->CurrentFvFileHandles));
170 }
171 }
172 //
173 // Cache the current Fv File Handle. So that we don't have to scan the Fv again.
174 // Instead, we can retrieve the file handles within this Fv from cachable data.
175 //
176 Private->Fv[Private->CurrentPeimFvCount].ScanFv = TRUE;
177 CopyMem (Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, Private->CurrentFvFileHandles, sizeof (Private->CurrentFvFileHandles));
178
179 }
180
181 /**
182 Shadow PeiCore module from flash to installed memory.
183
184 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
185 @param PrivateInMem PeiCore's private data structure
186
187 @return PeiCore function address after shadowing.
188 **/
189 VOID*
190 ShadowPeiCore(
191 IN CONST EFI_PEI_SERVICES **PeiServices,
192 IN PEI_CORE_INSTANCE *PrivateInMem
193 )
194 {
195 EFI_PEI_FILE_HANDLE PeiCoreFileHandle;
196 EFI_PHYSICAL_ADDRESS EntryPoint;
197 EFI_STATUS Status;
198 UINT32 AuthenticationState;
199
200 PeiCoreFileHandle = NULL;
201
202 //
203 // Find the PEI Core in the BFV
204 //
205 Status = PeiFindFileEx (
206 (EFI_PEI_FV_HANDLE)PrivateInMem->Fv[0].FvHeader,
207 NULL,
208 EFI_FV_FILETYPE_PEI_CORE,
209 &PeiCoreFileHandle,
210 NULL
211 );
212 ASSERT_EFI_ERROR (Status);
213
214 //
215 // Shadow PEI Core into memory so it will run faster
216 //
217 Status = PeiLoadImage (
218 PeiServices,
219 *((EFI_PEI_FILE_HANDLE*)&PeiCoreFileHandle),
220 &EntryPoint,
221 &AuthenticationState
222 );
223 ASSERT_EFI_ERROR (Status);
224
225 //
226 // Compute the PeiCore's function address after shaowed PeiCore.
227 // _ModuleEntryPoint is PeiCore main function entry
228 //
229 return (VOID*) ((UINTN) EntryPoint + (UINTN) PeiCore - (UINTN) _ModuleEntryPoint);
230 }
231
232 /**
233 Conduct PEIM dispatch.
234
235 @param SecCoreData Points to a data structure containing information about the PEI core's operating
236 environment, such as the size and location of temporary RAM, the stack location and
237 the BFV location.
238 @param Private Pointer to the private data passed in from caller
239
240 **/
241 VOID
242 PeiDispatcher (
243 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
244 IN PEI_CORE_INSTANCE *Private
245 )
246 {
247 EFI_STATUS Status;
248 UINT32 Index1;
249 UINT32 Index2;
250 CONST EFI_PEI_SERVICES **PeiServices;
251 EFI_PEI_FV_HANDLE VolumeHandle;
252 EFI_PEI_FILE_HANDLE PeimFileHandle;
253 UINTN FvCount;
254 UINTN PeimCount;
255 UINT32 AuthenticationState;
256 EFI_PHYSICAL_ADDRESS EntryPoint;
257 EFI_PEIM_ENTRY_POINT2 PeimEntryPoint;
258 UINTN SaveCurrentPeimCount;
259 UINTN SaveCurrentFvCount;
260 EFI_PEI_FILE_HANDLE SaveCurrentFileHandle;
261 PEIM_FILE_HANDLE_EXTENDED_DATA ExtendedData;
262 EFI_PHYSICAL_ADDRESS NewPermenentMemoryBase;
263 TEMPORARY_RAM_SUPPORT_PPI *TemporaryRamSupportPpi;
264 EFI_HOB_HANDOFF_INFO_TABLE *OldHandOffTable;
265 EFI_HOB_HANDOFF_INFO_TABLE *NewHandOffTable;
266 INTN StackOffset;
267 INTN HeapOffset;
268 PEI_CORE_INSTANCE *PrivateInMem;
269 UINT64 NewPeiStackSize;
270 UINT64 OldPeiStackSize;
271 UINT64 StackGap;
272 EFI_FV_FILE_INFO FvFileInfo;
273 UINTN OldCheckingTop;
274 UINTN OldCheckingBottom;
275
276
277 PeiServices = (CONST EFI_PEI_SERVICES **) &Private->PS;
278 PeimEntryPoint = NULL;
279 PeimFileHandle = NULL;
280 EntryPoint = 0;
281
282 if ((Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
283 //
284 // Once real memory is available, shadow the RegisterForShadow modules. And meanwhile
285 // update the modules' status from PEIM_STATE_REGISITER_FOR_SHADOW to PEIM_STATE_DONE.
286 //
287 SaveCurrentPeimCount = Private->CurrentPeimCount;
288 SaveCurrentFvCount = Private->CurrentPeimFvCount;
289 SaveCurrentFileHandle = Private->CurrentFileHandle;
290
291 for (Index1 = 0; Index1 <= SaveCurrentFvCount; Index1++) {
292 for (Index2 = 0; (Index2 < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->Fv[Index1].FvFileHandles[Index2] != NULL); Index2++) {
293 if (Private->Fv[Index1].PeimState[Index2] == PEIM_STATE_REGISITER_FOR_SHADOW) {
294 PeimFileHandle = Private->Fv[Index1].FvFileHandles[Index2];
295 Status = PeiLoadImage (
296 (CONST EFI_PEI_SERVICES **) &Private->PS,
297 PeimFileHandle,
298 &EntryPoint,
299 &AuthenticationState
300 );
301 if (Status == EFI_SUCCESS) {
302 //
303 // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE
304 //
305 Private->Fv[Index1].PeimState[Index2]++;
306 Private->CurrentFileHandle = PeimFileHandle;
307 Private->CurrentPeimFvCount = Index1;
308 Private->CurrentPeimCount = Index2;
309 //
310 // Call the PEIM entry point
311 //
312 PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;
313
314 PERF_START (0, "PEIM", NULL, 0);
315 PeimEntryPoint(PeimFileHandle, (const EFI_PEI_SERVICES **) &Private->PS);
316 PERF_END (0, "PEIM", NULL, 0);
317 }
318
319 //
320 // Process the Notify list and dispatch any notifies for
321 // newly installed PPIs.
322 //
323 ProcessNotifyList (Private);
324 }
325 }
326 }
327 Private->CurrentFileHandle = SaveCurrentFileHandle;
328 Private->CurrentPeimFvCount = SaveCurrentFvCount;
329 Private->CurrentPeimCount = SaveCurrentPeimCount;
330 }
331
332 //
333 // This is the main dispatch loop. It will search known FVs for PEIMs and
334 // attempt to dispatch them. If any PEIM gets dispatched through a single
335 // pass of the dispatcher, it will start over from the Bfv again to see
336 // if any new PEIMs dependencies got satisfied. With a well ordered
337 // FV where PEIMs are found in the order their dependencies are also
338 // satisfied, this dipatcher should run only once.
339 //
340 do {
341 //
342 // In case that reenter PeiCore happens, the last pass record is still available.
343 //
344 if (!Private->PeimDispatcherReenter) {
345 Private->PeimNeedingDispatch = FALSE;
346 Private->PeimDispatchOnThisPass = FALSE;
347 } else {
348 Private->PeimDispatcherReenter = FALSE;
349 }
350
351 for (FvCount = Private->CurrentPeimFvCount; FvCount < Private->FvCount; FvCount++) {
352 Private->CurrentPeimFvCount = FvCount;
353 //
354 // Get this Fv Handle by PeiService FvFindNextVolume.
355 //
356 PeiFvFindNextVolume (PeiServices, FvCount, &VolumeHandle);
357
358 if (Private->CurrentPeimCount == 0) {
359 //
360 // When going through each FV, at first, search Apriori file to
361 // reorder all PEIMs to ensure the PEIMs in Apriori file to get
362 // dispatch at first.
363 //
364 DiscoverPeimsAndOrderWithApriori (Private, VolumeHandle);
365 }
366
367 //
368 // Start to dispatch all modules within the current Fv.
369 //
370 for (PeimCount = Private->CurrentPeimCount;
371 (PeimCount < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->CurrentFvFileHandles[PeimCount] != NULL);
372 PeimCount++) {
373 Private->CurrentPeimCount = PeimCount;
374 PeimFileHandle = Private->CurrentFileHandle = Private->CurrentFvFileHandles[PeimCount];
375
376 if (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_NOT_DISPATCHED) {
377 if (!DepexSatisfied (Private, PeimFileHandle, PeimCount)) {
378 Private->PeimNeedingDispatch = TRUE;
379 } else {
380 Status = PeiFfsGetFileInfo (PeimFileHandle, &FvFileInfo);
381 ASSERT_EFI_ERROR (Status);
382 if (FvFileInfo.FileType == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
383 //
384 // For Fv type file, Produce new FV PPI and FV hob
385 //
386 Status = ProcessFvFile (PeiServices, VolumeHandle, PeimFileHandle, &AuthenticationState);
387 } else {
388 //
389 // For PEIM driver, Load its entry point
390 //
391 Status = PeiLoadImage (
392 PeiServices,
393 PeimFileHandle,
394 &EntryPoint,
395 &AuthenticationState
396 );
397 }
398
399 if ((Status == EFI_SUCCESS)) {
400 //
401 // The PEIM has its dependencies satisfied, and its entry point
402 // has been found, so invoke it.
403 //
404 PERF_START (0, "PEIM", NULL, 0);
405
406 ExtendedData.Handle = (EFI_HANDLE)PeimFileHandle;
407
408 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
409 EFI_PROGRESS_CODE,
410 FixedPcdGet32(PcdStatusCodeValuePeimDispatch),
411 (VOID *)(&ExtendedData),
412 sizeof (ExtendedData)
413 );
414
415 Status = VerifyPeim (Private, VolumeHandle, PeimFileHandle);
416 if (Status != EFI_SECURITY_VIOLATION && (AuthenticationState == 0)) {
417 //
418 // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED
419 //
420 Private->Fv[FvCount].PeimState[PeimCount]++;
421
422 if (FvFileInfo.FileType != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
423 //
424 // Call the PEIM entry point for PEIM driver
425 //
426 PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;
427 PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);
428 }
429
430 Private->PeimDispatchOnThisPass = TRUE;
431 }
432
433 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
434 EFI_PROGRESS_CODE,
435 FixedPcdGet32(PcdStatusCodeValuePeimDispatch),
436 (VOID *)(&ExtendedData),
437 sizeof (ExtendedData)
438 );
439 PERF_END (0, "PEIM", NULL, 0);
440
441 }
442
443 if (Private->SwitchStackSignal) {
444 //
445 // Before switch stack from temporary memory to permenent memory, caculate the heap and stack
446 // usage in temporary memory for debuging.
447 //
448 DEBUG_CODE_BEGIN ();
449 UINT32 *StackPointer;
450
451 for (StackPointer = (UINT32*)SecCoreData->StackBase;
452 (StackPointer < (UINT32*)((UINTN)SecCoreData->StackBase + SecCoreData->StackSize)) \
453 && (*StackPointer == INIT_CAR_VALUE);
454 StackPointer ++);
455
456 DEBUG ((EFI_D_INFO, "Total temporary memory: %d bytes.\n", (UINT32)SecCoreData->TemporaryRamSize));
457 DEBUG ((EFI_D_INFO, " temporary memory stack ever used: %d bytes.\n",
458 (SecCoreData->StackSize - ((UINTN) StackPointer - (UINTN)SecCoreData->StackBase))
459 ));
460 DEBUG ((EFI_D_INFO, " temporary memory heap used: %d bytes.\n",
461 ((UINTN) Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom -
462 (UINTN) Private->HobList.Raw)
463 ));
464 DEBUG_CODE_END ();
465
466 //
467 // Reserve the size of new stack at bottom of physical memory
468 //
469 OldPeiStackSize = (UINT64) SecCoreData->StackSize;
470 NewPeiStackSize = (RShiftU64 (Private->PhysicalMemoryLength, 1) + EFI_PAGE_MASK) & ~EFI_PAGE_MASK;
471 if (FixedPcdGet32(PcdPeiCoreMaxPeiStackSize) > (UINT32) NewPeiStackSize) {
472 Private->StackSize = NewPeiStackSize;
473 } else {
474 Private->StackSize = FixedPcdGet32(PcdPeiCoreMaxPeiStackSize);
475 }
476
477 //
478 // In theory, the size of new stack in permenent memory should large than
479 // size of old stack in temporary memory.
480 // But if new stack is smaller than the size of old stack, we also reserve
481 // the size of old stack at bottom of permenent memory.
482 //
483 DEBUG ((EFI_D_INFO, "Old Stack size %d, New stack size %d\n", (INT32) OldPeiStackSize, (INT32) Private->StackSize));
484 ASSERT (Private->StackSize >= OldPeiStackSize);
485 StackGap = Private->StackSize - OldPeiStackSize;
486
487 //
488 // Update HandOffHob for new installed permenent memory
489 //
490 OldHandOffTable = Private->HobList.HandoffInformationTable;
491 OldCheckingBottom = (UINTN)(SecCoreData->TemporaryRamBase);
492 OldCheckingTop = (UINTN)(OldCheckingBottom + SecCoreData->TemporaryRamSize);
493
494 //
495 // The whole temporary memory will be migrated to physical memory.
496 // CAUTION: The new base is computed accounding to gap of new stack.
497 //
498 NewPermenentMemoryBase = Private->PhysicalMemoryBegin + StackGap;
499
500 //
501 // Caculate stack offset and heap offset between temporary memory and new permement
502 // memory seperately.
503 //
504 StackOffset = (UINTN) NewPermenentMemoryBase - (UINTN) SecCoreData->StackBase;
505 HeapOffset = (INTN) ((UINTN) Private->PhysicalMemoryBegin + Private->StackSize - \
506 (UINTN) SecCoreData->PeiTemporaryRamBase);
507 DEBUG ((EFI_D_INFO, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (INT64)HeapOffset, (INT64)StackOffset));
508
509 //
510 // Caculate new HandOffTable and PrivateData address in permenet memory's stack
511 //
512 NewHandOffTable = (EFI_HOB_HANDOFF_INFO_TABLE *)((UINTN)OldHandOffTable + HeapOffset);
513 PrivateInMem = (PEI_CORE_INSTANCE *)((UINTN) (VOID*) Private + StackOffset);
514
515 //
516 // TemporaryRamSupportPpi is produced by platform's SEC
517 //
518 Status = PeiLocatePpi (
519 (CONST EFI_PEI_SERVICES **) PeiServices,
520 &gEfiTemporaryRamSupportPpiGuid,
521 0,
522 NULL,
523 (VOID**)&TemporaryRamSupportPpi
524 );
525
526
527 if (!EFI_ERROR (Status)) {
528 //
529 // Temporary Ram support Ppi is provided by platform, it will copy
530 // temporary memory to permenent memory and do stack switching.
531 // After invoken temporary Ram support, following code's stack is in
532 // memory but not in temporary memory.
533 //
534 TemporaryRamSupportPpi->TemporaryRamMigration (
535 (CONST EFI_PEI_SERVICES **) PeiServices,
536 (EFI_PHYSICAL_ADDRESS)(UINTN) SecCoreData->TemporaryRamBase,
537 (EFI_PHYSICAL_ADDRESS)(UINTN) NewPermenentMemoryBase,
538 SecCoreData->TemporaryRamSize
539 );
540
541 } else {
542 //
543 // In IA32/x64/Itanium architecture, we need platform provide
544 // TEMPORAY_RAM_MIGRATION_PPI.
545 //
546 ASSERT (FALSE);
547 }
548
549
550 //
551 //
552 // Fixup the PeiCore's private data
553 //
554 PrivateInMem->PS = &PrivateInMem->ServiceTableShadow;
555 PrivateInMem->CpuIo = &PrivateInMem->ServiceTableShadow.CpuIo;
556 PrivateInMem->HobList.Raw = (VOID*) ((UINTN) PrivateInMem->HobList.Raw + HeapOffset);
557 PrivateInMem->StackBase = (EFI_PHYSICAL_ADDRESS)(((UINTN)PrivateInMem->PhysicalMemoryBegin + EFI_PAGE_MASK) & ~EFI_PAGE_MASK);
558
559 PeiServices = (CONST EFI_PEI_SERVICES **) &PrivateInMem->PS;
560
561 //
562 // Fixup for PeiService's address
563 //
564 SetPeiServicesTablePointer(PeiServices);
565
566 //
567 // Update HandOffHob for new installed permenent memory
568 //
569 NewHandOffTable->EfiEndOfHobList =
570 (EFI_PHYSICAL_ADDRESS)((UINTN) NewHandOffTable->EfiEndOfHobList + HeapOffset);
571 NewHandOffTable->EfiMemoryTop = PrivateInMem->PhysicalMemoryBegin +
572 PrivateInMem->PhysicalMemoryLength;
573 NewHandOffTable->EfiMemoryBottom = PrivateInMem->PhysicalMemoryBegin;
574 NewHandOffTable->EfiFreeMemoryTop = PrivateInMem->FreePhysicalMemoryTop;
575 NewHandOffTable->EfiFreeMemoryBottom = NewHandOffTable->EfiEndOfHobList +
576 sizeof (EFI_HOB_GENERIC_HEADER);
577
578 //
579 // We need convert the PPI desciptor's pointer
580 //
581 ConvertPpiPointers (PrivateInMem,
582 OldCheckingBottom,
583 OldCheckingTop,
584 HeapOffset
585 );
586
587 DEBUG ((EFI_D_INFO, "Stack Hob: BaseAddress=0x%lX Length=0x%lX\n",
588 PrivateInMem->StackBase,
589 PrivateInMem->StackSize));
590 BuildStackHob (PrivateInMem->StackBase, PrivateInMem->StackSize);
591
592 //
593 // After the whole temporary memory is migrated, then we can allocate page in
594 // permenent memory.
595 //
596 PrivateInMem->PeiMemoryInstalled = TRUE;
597
598 //
599 // Indicate that PeiCore reenter
600 //
601 PrivateInMem->PeimDispatcherReenter = TRUE;
602
603 //
604 // Shadow PEI Core. When permanent memory is avaiable, shadow
605 // PEI Core and PEIMs to get high performance.
606 //
607 PrivateInMem->ShadowedPeiCore = ShadowPeiCore (
608 PeiServices,
609 PrivateInMem
610 );
611 //
612 // Process the Notify list and dispatch any notifies for
613 // newly installed PPIs.
614 //
615 ProcessNotifyList (PrivateInMem);
616
617 //
618 // Entry PEI Phase 2
619 //
620 PeiCore (SecCoreData, NULL, PrivateInMem);
621
622 //
623 // Code should not come here
624 //
625 ASSERT_EFI_ERROR(FALSE);
626 }
627
628 //
629 // Process the Notify list and dispatch any notifies for
630 // newly installed PPIs.
631 //
632 ProcessNotifyList (Private);
633
634 if ((Private->PeiMemoryInstalled) && (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_REGISITER_FOR_SHADOW) && \
635 (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
636 //
637 // If memory is availble we shadow images by default for performance reasons.
638 // We call the entry point a 2nd time so the module knows it's shadowed.
639 //
640 //PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0);
641 ASSERT (PeimEntryPoint != NULL);
642 PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);
643 //PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0);
644
645 //
646 // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE
647 //
648 Private->Fv[FvCount].PeimState[PeimCount]++;
649
650 //
651 // Process the Notify list and dispatch any notifies for
652 // newly installed PPIs.
653 //
654 ProcessNotifyList (Private);
655 }
656 }
657 }
658 }
659
660 //
661 // We set to NULL here to optimize the 2nd entry to this routine after
662 // memory is found. This reprevents rescanning of the FV. We set to
663 // NULL here so we start at the begining of the next FV
664 //
665 Private->CurrentFileHandle = NULL;
666 Private->CurrentPeimCount = 0;
667 //
668 // Before walking through the next FV,Private->CurrentFvFileHandles[]should set to NULL
669 //
670 SetMem (Private->CurrentFvFileHandles, sizeof (Private->CurrentFvFileHandles), 0);
671 }
672
673 //
674 // Before making another pass, we should set Private->CurrentPeimFvCount =0 to go
675 // through all the FV.
676 //
677 Private->CurrentPeimFvCount = 0;
678
679 //
680 // PeimNeedingDispatch being TRUE means we found a PEIM that did not get
681 // dispatched. So we need to make another pass
682 //
683 // PeimDispatchOnThisPass being TRUE means we dispatched a PEIM on this
684 // pass. If we did not dispatch a PEIM there is no point in trying again
685 // as it will fail the next time too (nothing has changed).
686 //
687 } while (Private->PeimNeedingDispatch && Private->PeimDispatchOnThisPass);
688
689 }
690
691 /**
692 Initialize the Dispatcher's data members
693
694 @param PrivateData PeiCore's private data structure
695 @param OldCoreData Old data from SecCore
696 NULL if being run in non-permament memory mode.
697 @param SecCoreData Points to a data structure containing information about the PEI core's operating
698 environment, such as the size and location of temporary RAM, the stack location and
699 the BFV location.
700
701 @return None.
702
703 **/
704 VOID
705 InitializeDispatcherData (
706 IN PEI_CORE_INSTANCE *PrivateData,
707 IN PEI_CORE_INSTANCE *OldCoreData,
708 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData
709 )
710 {
711 if (OldCoreData == NULL) {
712 PrivateData->PeimDispatcherReenter = FALSE;
713 PeiInitializeFv (PrivateData, SecCoreData);
714 }
715
716 return;
717 }
718
719 /**
720 This routine parses the Dependency Expression, if available, and
721 decides if the module can be executed.
722
723
724 @param Private PeiCore's private data structure
725 @param FileHandle PEIM's file handle
726 @param PeimCount Peim count in all dispatched PEIMs.
727
728 @retval TRUE Can be dispatched
729 @retval FALSE Cannot be dispatched
730
731 **/
732 BOOLEAN
733 DepexSatisfied (
734 IN PEI_CORE_INSTANCE *Private,
735 IN EFI_PEI_FILE_HANDLE FileHandle,
736 IN UINTN PeimCount
737 )
738 {
739 EFI_STATUS Status;
740 VOID *DepexData;
741
742 if (PeimCount < Private->AprioriCount) {
743 //
744 // If its in the A priori file then we set Depex to TRUE
745 //
746 return TRUE;
747 }
748
749 //
750 // Depex section not in the encapsulated section.
751 //
752 Status = PeiServicesFfsFindSectionData (
753 EFI_SECTION_PEI_DEPEX,
754 FileHandle,
755 (VOID **)&DepexData
756 );
757
758 if (EFI_ERROR (Status)) {
759 //
760 // If there is no DEPEX, assume the module can be executed
761 //
762 return TRUE;
763 }
764
765 //
766 // Evaluate a given DEPEX
767 //
768 return PeimDispatchReadiness (&Private->PS, DepexData);
769 }
770
771 /**
772 This routine enable a PEIM to register itself to shadow when PEI Foundation
773 discovery permanent memory.
774
775 @param FileHandle File handle of a PEIM.
776
777 @retval EFI_NOT_FOUND The file handle doesn't point to PEIM itself.
778 @retval EFI_ALREADY_STARTED Indicate that the PEIM has been registered itself.
779 @retval EFI_SUCCESS Successfully to register itself.
780
781 **/
782 EFI_STATUS
783 EFIAPI
784 PeiRegisterForShadow (
785 IN EFI_PEI_FILE_HANDLE FileHandle
786 )
787 {
788 PEI_CORE_INSTANCE *Private;
789 Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());
790
791 if (Private->CurrentFileHandle != FileHandle) {
792 //
793 // The FileHandle must be for the current PEIM
794 //
795 return EFI_NOT_FOUND;
796 }
797
798 if (Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] >= PEIM_STATE_REGISITER_FOR_SHADOW) {
799 //
800 // If the PEIM has already entered the PEIM_STATE_REGISTER_FOR_SHADOW or PEIM_STATE_DONE then it's already been started
801 //
802 return EFI_ALREADY_STARTED;
803 }
804
805 Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] = PEIM_STATE_REGISITER_FOR_SHADOW;
806
807 return EFI_SUCCESS;
808 }
809