]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
TempRamSupportPpi is architectural required for IA32/x64/IPF.
[mirror_edk2.git] / MdeModulePkg / Core / Pei / Dispatcher / Dispatcher.c
1 /** @file
2
3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 Dispatcher.c
15
16 Abstract:
17
18 EFI PEI Core dispatch services
19
20 Revision History
21
22 **/
23
24 #include <PeiMain.h>
25
26 //
27 //CAR is filled with this initial value during SEC phase
28 //
29 #define INIT_CAR_VALUE 0x5AA55AA5
30
31 typedef struct {
32 EFI_STATUS_CODE_DATA DataHeader;
33 EFI_HANDLE Handle;
34 } PEIM_FILE_HANDLE_EXTENDED_DATA;
35
36 VOID
37 DiscoverPeimsAndOrderWithApriori (
38 IN PEI_CORE_INSTANCE *Private,
39 IN EFI_PEI_FV_HANDLE VolumeHandle
40 )
41 /*++
42
43 Routine Description:
44
45 Discover all Peims and optional Apriori file in one FV. There is at most one
46 Apriori file in one FV.
47
48 Arguments:
49
50 Private - Pointer to the private data passed in from caller
51 VolumeHandle - Fv handle.
52 Returns:
53
54 NONE
55
56 --*/
57 {
58 EFI_STATUS Status;
59 EFI_PEI_FV_HANDLE FileHandle;
60 EFI_PEI_FILE_HANDLE AprioriFileHandle;
61 EFI_GUID *Apriori;
62 UINTN Index;
63 UINTN Index2;
64 UINTN PeimIndex;
65 UINTN PeimCount;
66 EFI_GUID *Guid;
67 EFI_PEI_FV_HANDLE TempFileHandles[FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)];
68 EFI_GUID FileGuid[FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)];
69
70 //
71 // Walk the FV and find all the PEIMs and the Apriori file.
72 //
73 AprioriFileHandle = NULL;
74 Private->CurrentFvFileHandles[0] = NULL;
75 Guid = NULL;
76 FileHandle = NULL;
77
78 //
79 // If the current Fv has been scanned, directly get its cachable record.
80 //
81 if (Private->Fv[Private->CurrentPeimFvCount].ScanFv) {
82 CopyMem (Private->CurrentFvFileHandles, Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, sizeof (Private->CurrentFvFileHandles));
83 return;
84 }
85
86 //
87 // Go ahead to scan this Fv, and cache FileHandles within it.
88 //
89 for (PeimCount = 0; PeimCount < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv); PeimCount++) {
90 Status = PeiFindFileEx (
91 VolumeHandle,
92 NULL,
93 PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE,
94 &FileHandle,
95 &AprioriFileHandle
96 );
97 if (Status != EFI_SUCCESS) {
98 break;
99 }
100
101 Private->CurrentFvFileHandles[PeimCount] = FileHandle;
102 }
103
104 Private->AprioriCount = 0;
105 if (AprioriFileHandle != NULL) {
106 //
107 // Read the Apriori file
108 //
109 Status = PeiServicesFfsFindSectionData (EFI_SECTION_RAW, AprioriFileHandle, (VOID **) &Apriori);
110 if (!EFI_ERROR (Status)) {
111 //
112 // Calculate the number of PEIMs in the A Priori list
113 //
114 Private->AprioriCount = *(UINT32 *)(((EFI_FFS_FILE_HEADER *)AprioriFileHandle)->Size) & 0x00FFFFFF;
115 Private->AprioriCount -= sizeof (EFI_FFS_FILE_HEADER) - sizeof (EFI_COMMON_SECTION_HEADER);
116 Private->AprioriCount /= sizeof (EFI_GUID);
117
118 SetMem (FileGuid, sizeof (FileGuid), 0);
119 for (Index = 0; Index < PeimCount; Index++) {
120 //
121 // Make an array of file name guids that matches the FileHandle array so we can convert
122 // quickly from file name to file handle
123 //
124 CopyMem (&FileGuid[Index], &((EFI_FFS_FILE_HEADER *)Private->CurrentFvFileHandles[Index])->Name,sizeof(EFI_GUID));
125 }
126
127 //
128 // Walk through FileGuid array to find out who is invalid PEIM guid in Apriori file.
129 // Add avalible PEIMs in Apriori file into TempFileHandles array at first.
130 //
131 Index2 = 0;
132 for (Index = 0; Index2 < Private->AprioriCount; Index++) {
133 while (Index2 < Private->AprioriCount) {
134 Guid = ScanGuid (FileGuid, PeimCount * sizeof (EFI_GUID), &Apriori[Index2++]);
135 if (Guid != NULL) {
136 break;
137 }
138 }
139 if (Guid == NULL) {
140 break;
141 }
142 PeimIndex = ((UINTN)Guid - (UINTN)&FileGuid[0])/sizeof (EFI_GUID);
143 TempFileHandles[Index] = Private->CurrentFvFileHandles[PeimIndex];
144
145 //
146 // Since we have copied the file handle we can remove it from this list.
147 //
148 Private->CurrentFvFileHandles[PeimIndex] = NULL;
149 }
150
151 //
152 // Update valid Aprioricount
153 //
154 Private->AprioriCount = Index;
155
156 //
157 // Add in any PEIMs not in the Apriori file
158 //
159 for (;Index < PeimCount; Index++) {
160 for (Index2 = 0; Index2 < PeimCount; Index2++) {
161 if (Private->CurrentFvFileHandles[Index2] != NULL) {
162 TempFileHandles[Index] = Private->CurrentFvFileHandles[Index2];
163 Private->CurrentFvFileHandles[Index2] = NULL;
164 break;
165 }
166 }
167 }
168 //
169 //Index the end of array contains re-range Pei moudle.
170 //
171 TempFileHandles[Index] = NULL;
172
173 //
174 // Private->CurrentFvFileHandles is currently in PEIM in the FV order.
175 // We need to update it to start with files in the A Priori list and
176 // then the remaining files in PEIM order.
177 //
178 CopyMem (Private->CurrentFvFileHandles, TempFileHandles, sizeof (Private->CurrentFvFileHandles));
179 }
180 }
181 //
182 // Cache the current Fv File Handle. So that we don't have to scan the Fv again.
183 // Instead, we can retrieve the file handles within this Fv from cachable data.
184 //
185 Private->Fv[Private->CurrentPeimFvCount].ScanFv = TRUE;
186 CopyMem (Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, Private->CurrentFvFileHandles, sizeof (Private->CurrentFvFileHandles));
187
188 }
189
190 VOID*
191 ShadowPeiCore(
192 EFI_PEI_SERVICES **PeiServices,
193 PEI_CORE_INSTANCE *PrivateInMem
194 )
195 {
196 EFI_PEI_FILE_HANDLE PeiCoreFileHandle;
197 EFI_PHYSICAL_ADDRESS EntryPoint;
198 EFI_STATUS Status;
199 UINT32 AuthenticationState;
200
201 PeiCoreFileHandle = NULL;
202
203 //
204 // Find the PEI Core in the BFV
205 //
206 Status = PeiFindFileEx (
207 (EFI_PEI_FV_HANDLE)PrivateInMem->Fv[0].FvHeader,
208 NULL,
209 EFI_FV_FILETYPE_PEI_CORE,
210 &PeiCoreFileHandle,
211 NULL
212 );
213 ASSERT_EFI_ERROR (Status);
214
215 //
216 // Shadow PEI Core into memory so it will run faster
217 //
218 Status = PeiLoadImage (
219 PeiServices,
220 *((EFI_PEI_FILE_HANDLE*)&PeiCoreFileHandle),
221 &EntryPoint,
222 &AuthenticationState
223 );
224 ASSERT_EFI_ERROR (Status);
225
226 return (VOID*) ((UINTN) EntryPoint + (UINTN) PeiCore - (UINTN) _ModuleEntryPoint);
227 }
228
229 VOID
230 PeiDispatcher (
231 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
232 IN PEI_CORE_INSTANCE *Private
233 )
234
235 /*++
236
237 Routine Description:
238
239 Conduct PEIM dispatch.
240
241 Arguments:
242
243 SecCoreData - Points to a data structure containing information about the PEI core's operating
244 environment, such as the size and location of temporary RAM, the stack location and
245 the BFV location.
246 PrivateData - Pointer to the private data passed in from caller
247 DispatchData - Pointer to PEI_CORE_DISPATCH_DATA data.
248
249 Returns:
250
251 EFI_SUCCESS - Successfully dispatched PEIM.
252 EFI_NOT_FOUND - The dispatch failed.
253
254 --*/
255 {
256 EFI_STATUS Status;
257 UINT32 Index1;
258 UINT32 Index2;
259 EFI_PEI_SERVICES **PeiServices;
260 EFI_PEI_FV_HANDLE VolumeHandle;
261 EFI_PEI_FILE_HANDLE PeimFileHandle;
262 UINTN FvCount;
263 UINTN PeimCount;
264 UINT32 AuthenticationState;
265 EFI_PHYSICAL_ADDRESS EntryPoint;
266 EFI_PEIM_ENTRY_POINT2 PeimEntryPoint;
267 BOOLEAN PeimNeedingDispatch;
268 BOOLEAN PeimDispatchOnThisPass;
269 UINTN SaveCurrentPeimCount;
270 UINTN SaveCurrentFvCount;
271 EFI_PEI_FILE_HANDLE SaveCurrentFileHandle;
272 PEIM_FILE_HANDLE_EXTENDED_DATA ExtendedData;
273 EFI_PHYSICAL_ADDRESS NewPermenentMemoryBase;
274 TEMPORARY_RAM_SUPPORT_PPI *TemporaryRamSupportPpi;
275 EFI_HOB_HANDOFF_INFO_TABLE *OldHandOffTable;
276 EFI_HOB_HANDOFF_INFO_TABLE *NewHandOffTable;
277 INTN StackOffset;
278 INTN HeapOffset;
279 PEI_CORE_INSTANCE *PrivateInMem;
280 UINT64 NewPeiStackSize;
281 UINT64 OldPeiStackSize;
282 UINT64 StackGap;
283 EFI_FV_FILE_INFO FvFileInfo;
284 UINTN OldCheckingTop;
285 UINTN OldCheckingBottom;
286
287
288 PeiServices = &Private->PS;
289 PeimEntryPoint = NULL;
290 PeimFileHandle = NULL;
291 EntryPoint = 0;
292
293 if ((Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
294 //
295 // Once real memory is available, shadow the RegisterForShadow modules. And meanwhile
296 // update the modules' status from PEIM_STATE_REGISITER_FOR_SHADOW to PEIM_STATE_DONE.
297 //
298 SaveCurrentPeimCount = Private->CurrentPeimCount;
299 SaveCurrentFvCount = Private->CurrentPeimFvCount;
300 SaveCurrentFileHandle = Private->CurrentFileHandle;
301
302 for (Index1 = 0; Index1 <= SaveCurrentFvCount; Index1++) {
303 for (Index2 = 0; (Index2 < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->Fv[Index1].FvFileHandles[Index2] != NULL); Index2++) {
304 if (Private->Fv[Index1].PeimState[Index2] == PEIM_STATE_REGISITER_FOR_SHADOW) {
305 PeimFileHandle = Private->Fv[Index1].FvFileHandles[Index2];
306 Status = PeiLoadImage (
307 &Private->PS,
308 PeimFileHandle,
309 &EntryPoint,
310 &AuthenticationState
311 );
312 if (Status == EFI_SUCCESS) {
313 //
314 // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE
315 //
316 Private->Fv[Index1].PeimState[Index2]++;
317 Private->CurrentFileHandle = PeimFileHandle;
318 Private->CurrentPeimFvCount = Index1;
319 Private->CurrentPeimCount = Index2;
320 //
321 // Call the PEIM entry point
322 //
323 PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;
324
325 PERF_START (0, "PEIM", NULL, 0);
326 PeimEntryPoint(PeimFileHandle, (const EFI_PEI_SERVICES **) &Private->PS);
327 PERF_END (0, "PEIM", NULL, 0);
328 }
329
330 //
331 // Process the Notify list and dispatch any notifies for
332 // newly installed PPIs.
333 //
334 ProcessNotifyList (Private);
335 }
336 }
337 }
338 Private->CurrentFileHandle = SaveCurrentFileHandle;
339 Private->CurrentPeimFvCount = SaveCurrentFvCount;
340 Private->CurrentPeimCount = SaveCurrentPeimCount;
341 }
342
343 //
344 // This is the main dispatch loop. It will search known FVs for PEIMs and
345 // attempt to dispatch them. If any PEIM gets dispatched through a single
346 // pass of the dispatcher, it will start over from the Bfv again to see
347 // if any new PEIMs dependencies got satisfied. With a well ordered
348 // FV where PEIMs are found in the order their dependencies are also
349 // satisfied, this dipatcher should run only once.
350 //
351 do {
352 PeimNeedingDispatch = FALSE;
353 PeimDispatchOnThisPass = FALSE;
354
355 for (FvCount = Private->CurrentPeimFvCount; FvCount < Private->FvCount; FvCount++) {
356 Private->CurrentPeimFvCount = FvCount;
357 VolumeHandle = Private->Fv[FvCount].FvHeader;
358
359 if (Private->CurrentPeimCount == 0) {
360 //
361 // When going through each FV, at first, search Apriori file to
362 // reorder all PEIMs to ensure the PEIMs in Apriori file to get
363 // dispatch at first.
364 //
365 DiscoverPeimsAndOrderWithApriori (Private, VolumeHandle);
366 }
367
368 //
369 // Start to dispatch all modules within the current Fv.
370 //
371 for (PeimCount = Private->CurrentPeimCount;
372 (PeimCount < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->CurrentFvFileHandles[PeimCount] != NULL);
373 PeimCount++) {
374 Private->CurrentPeimCount = PeimCount;
375 PeimFileHandle = Private->CurrentFileHandle = Private->CurrentFvFileHandles[PeimCount];
376
377 if (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_NOT_DISPATCHED) {
378 if (!DepexSatisfied (Private, PeimFileHandle, PeimCount)) {
379 PeimNeedingDispatch = TRUE;
380 } else {
381 Status = PeiFfsGetFileInfo (PeimFileHandle, &FvFileInfo);
382 ASSERT_EFI_ERROR (Status);
383 if (FvFileInfo.FileType == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
384 //
385 // For Fv type file, Produce new FV PPI and FV hob
386 //
387 Status = ProcessFvFile (PeiServices, PeimFileHandle, &AuthenticationState);
388 } else {
389 //
390 // For PEIM driver, Load its entry point
391 //
392 Status = PeiLoadImage (
393 PeiServices,
394 PeimFileHandle,
395 &EntryPoint,
396 &AuthenticationState
397 );
398 }
399
400 if ((Status == EFI_SUCCESS)) {
401 //
402 // The PEIM has its dependencies satisfied, and its entry point
403 // has been found, so invoke it.
404 //
405 PERF_START (0, "PEIM", NULL, 0);
406
407 ExtendedData.Handle = (EFI_HANDLE)PeimFileHandle;
408
409 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
410 EFI_PROGRESS_CODE,
411 FixedPcdGet32(PcdStatusCodeValuePeimDispatch),
412 (VOID *)(&ExtendedData),
413 sizeof (ExtendedData)
414 );
415
416 Status = VerifyPeim (Private, VolumeHandle, PeimFileHandle);
417 if (Status != EFI_SECURITY_VIOLATION && (AuthenticationState == 0)) {
418 //
419 // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED
420 //
421 Private->Fv[FvCount].PeimState[PeimCount]++;
422
423 if (FvFileInfo.FileType != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
424 //
425 // Call the PEIM entry point for PEIM driver
426 //
427 PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;
428 PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);
429 }
430
431 PeimDispatchOnThisPass = TRUE;
432 }
433
434 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
435 EFI_PROGRESS_CODE,
436 FixedPcdGet32(PcdStatusCodeValuePeimDispatch),
437 (VOID *)(&ExtendedData),
438 sizeof (ExtendedData)
439 );
440 PERF_END (0, "PEIM", NULL, 0);
441
442 }
443
444 if (Private->SwitchStackSignal) {
445 //
446 // Before switch stack from CAR to permenent memory, caculate the heap and stack
447 // usage in temporary memory for debuging.
448 //
449 DEBUG_CODE_BEGIN ();
450 UINT32 *StackPointer;
451
452 for (StackPointer = (UINT32*)SecCoreData->StackBase;
453 (StackPointer < (UINT32*)((UINTN)SecCoreData->StackBase + SecCoreData->StackSize)) \
454 && (*StackPointer == INIT_CAR_VALUE);
455 StackPointer ++);
456
457 DEBUG ((EFI_D_INFO, "Total Cache as RAM: %d bytes.\n", SecCoreData->TemporaryRamSize));
458 DEBUG ((EFI_D_INFO, " CAR stack ever used: %d bytes.\n",
459 (SecCoreData->StackSize - ((UINTN) StackPointer - (UINTN)SecCoreData->StackBase))
460 ));
461 DEBUG ((EFI_D_INFO, " CAR heap used: %d bytes.\n",
462 ((UINTN) Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom -
463 (UINTN) Private->HobList.Raw)
464 ));
465 DEBUG_CODE_END ();
466
467 //
468 // Reserve the size of new stack at bottom of physical memory
469 //
470 OldPeiStackSize = Private->StackSize;
471 NewPeiStackSize = (RShiftU64 (Private->PhysicalMemoryLength, 1) + EFI_PAGE_MASK) & ~EFI_PAGE_MASK;
472 if (FixedPcdGet32(PcdPeiCoreMaxPeiStackSize) > (UINT32) NewPeiStackSize) {
473 Private->StackSize = NewPeiStackSize;
474 } else {
475 Private->StackSize = FixedPcdGet32(PcdPeiCoreMaxPeiStackSize);
476 }
477
478 //
479 // In theory, the size of new stack in permenent memory should large than
480 // size of old stack in temporary memory.
481 // But if new stack is smaller than the size of old stack, we also reserve
482 // the size of old stack at bottom of permenent memory.
483 //
484 StackGap = 0;
485 if (Private->StackSize > OldPeiStackSize) {
486 StackGap = Private->StackSize - OldPeiStackSize;
487 }
488
489 //
490 // Update HandOffHob for new installed permenent memory
491 //
492 OldHandOffTable = Private->HobList.HandoffInformationTable;
493 OldCheckingBottom = (UINTN)OldHandOffTable;
494 OldCheckingTop = (UINTN)(OldCheckingBottom + SecCoreData->TemporaryRamSize);
495
496 //
497 // The whole temporary memory will be migrated to physical memory.
498 // CAUTION: The new base is computed accounding to gap of new stack.
499 //
500 NewPermenentMemoryBase = Private->PhysicalMemoryBegin + StackGap;
501 StackOffset = (UINTN) NewPermenentMemoryBase - (UINTN) SecCoreData->StackBase;
502 HeapOffset = (INTN) ((UINTN) Private->PhysicalMemoryBegin + Private->StackSize - \
503 (UINTN) SecCoreData->PeiTemporaryRamBase);
504 DEBUG ((EFI_D_INFO, "Heap Offset = 0x%X Stack Offset = 0x%X\n", HeapOffset, StackOffset));
505
506 NewHandOffTable = (EFI_HOB_HANDOFF_INFO_TABLE *)((UINTN)OldHandOffTable + HeapOffset);
507 PrivateInMem = (PEI_CORE_INSTANCE *)((UINTN) (VOID*) Private + StackOffset);
508
509 //
510 // TemporaryRamSupportPpi is produced by platform's SEC
511 //
512 Status = PeiLocatePpi (
513 (CONST EFI_PEI_SERVICES **) PeiServices,
514 &gEfiTemporaryRamSupportPpiGuid,
515 0,
516 NULL,
517 (VOID**)&TemporaryRamSupportPpi
518 );
519
520
521 if (!EFI_ERROR (Status)) {
522 TemporaryRamSupportPpi->TemporaryRamMigration (
523 (CONST EFI_PEI_SERVICES **) PeiServices,
524 (EFI_PHYSICAL_ADDRESS)(UINTN) SecCoreData->TemporaryRamBase,
525 (EFI_PHYSICAL_ADDRESS)(UINTN) NewPermenentMemoryBase,
526 SecCoreData->TemporaryRamSize
527 );
528
529 } else {
530 //
531 // In IA32/x64/Itanium architecture, we need platform provide
532 // TEMPORAY_RAM_MIGRATION_PPI.
533 //
534 ASSERT (FALSE);
535 }
536
537
538 //
539 //
540 // Fixup the PeiCore's private data
541 //
542 PrivateInMem->PS = &PrivateInMem->ServiceTableShadow;
543 PrivateInMem->CpuIo = &PrivateInMem->ServiceTableShadow.CpuIo;
544 PrivateInMem->HobList.Raw = (VOID*) ((UINTN) PrivateInMem->HobList.Raw + HeapOffset);
545 PrivateInMem->StackBase = (EFI_PHYSICAL_ADDRESS)(((UINTN)PrivateInMem->PhysicalMemoryBegin + EFI_PAGE_MASK) & ~EFI_PAGE_MASK);
546
547 PeiServices = &PrivateInMem->PS;
548
549 //
550 // Fixup for PeiService's address
551 //
552 SetPeiServicesTablePointer(PeiServices);
553
554 //
555 // Update HandOffHob for new installed permenent memory
556 //
557 NewHandOffTable->EfiEndOfHobList =
558 (EFI_PHYSICAL_ADDRESS)((UINTN) NewHandOffTable->EfiEndOfHobList + HeapOffset);
559 NewHandOffTable->EfiMemoryTop = PrivateInMem->PhysicalMemoryBegin +
560 PrivateInMem->PhysicalMemoryLength;
561 NewHandOffTable->EfiMemoryBottom = PrivateInMem->PhysicalMemoryBegin;
562 NewHandOffTable->EfiFreeMemoryTop = PrivateInMem->FreePhysicalMemoryTop;
563 NewHandOffTable->EfiFreeMemoryBottom = NewHandOffTable->EfiEndOfHobList +
564 sizeof (EFI_HOB_GENERIC_HEADER);
565
566 //
567 // We need convert the PPI desciptor's pointer
568 //
569 ConvertPpiPointers ((CONST EFI_PEI_SERVICES **)PeiServices,
570 OldCheckingBottom,
571 OldCheckingTop,
572 NewHandOffTable);
573
574 DEBUG ((EFI_D_INFO, "Stack Hob: BaseAddress=0x%X Length=0x%X\n",
575 (UINTN)PrivateInMem->StackBase,
576 PrivateInMem->StackSize));
577 BuildStackHob (PrivateInMem->StackBase, PrivateInMem->StackSize);
578
579 //
580 // After the whole temporary memory is migrated, then we can allocate page in
581 // permenent memory.
582 //
583 PrivateInMem->PeiMemoryInstalled = TRUE;
584
585 //
586 // Restart scan of all PEIMs on next pass
587 //
588 PrivateInMem->CurrentPeimCount = 0;
589
590 //
591 // Shadow PEI Core. When permanent memory is avaiable, shadow
592 // PEI Core and PEIMs to get high performance.
593 //
594 PrivateInMem->ShadowedPeiCore = ShadowPeiCore (
595 PeiServices,
596 PrivateInMem
597 );
598 //
599 // Process the Notify list and dispatch any notifies for
600 // newly installed PPIs.
601 //
602 ProcessNotifyList (PrivateInMem);
603
604 //
605 // Entry PEI Phase 2
606 //
607 PeiCore (SecCoreData, NULL, PrivateInMem);
608
609 //
610 // Code should not come here
611 //
612 ASSERT_EFI_ERROR(FALSE);
613 }
614
615 //
616 // Process the Notify list and dispatch any notifies for
617 // newly installed PPIs.
618 //
619 ProcessNotifyList (Private);
620
621 if ((Private->PeiMemoryInstalled) && (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_REGISITER_FOR_SHADOW) && \
622 (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
623 //
624 // If memory is availble we shadow images by default for performance reasons.
625 // We call the entry point a 2nd time so the module knows it's shadowed.
626 //
627 //PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0);
628 PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);
629 //PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0);
630
631 //
632 // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE
633 //
634 Private->Fv[FvCount].PeimState[PeimCount]++;
635
636 //
637 // Process the Notify list and dispatch any notifies for
638 // newly installed PPIs.
639 //
640 ProcessNotifyList (Private);
641 }
642 }
643 }
644 }
645
646 //
647 // We set to NULL here to optimize the 2nd entry to this routine after
648 // memory is found. This reprevents rescanning of the FV. We set to
649 // NULL here so we start at the begining of the next FV
650 //
651 Private->CurrentFileHandle = NULL;
652 Private->CurrentPeimCount = 0;
653 //
654 // Before walking through the next FV,Private->CurrentFvFileHandles[]should set to NULL
655 //
656 SetMem (Private->CurrentFvFileHandles, sizeof (Private->CurrentFvFileHandles), 0);
657 }
658
659 //
660 // Before making another pass, we should set Private->CurrentPeimFvCount =0 to go
661 // through all the FV.
662 //
663 Private->CurrentPeimFvCount = 0;
664
665 //
666 // PeimNeedingDispatch being TRUE means we found a PEIM that did not get
667 // dispatched. So we need to make another pass
668 //
669 // PeimDispatchOnThisPass being TRUE means we dispatched a PEIM on this
670 // pass. If we did not dispatch a PEIM there is no point in trying again
671 // as it will fail the next time too (nothing has changed).
672 //
673 } while (PeimNeedingDispatch && PeimDispatchOnThisPass);
674
675 }
676
677 VOID
678 InitializeDispatcherData (
679 IN PEI_CORE_INSTANCE *PrivateData,
680 IN PEI_CORE_INSTANCE *OldCoreData,
681 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData
682 )
683 /*++
684
685 Routine Description:
686
687 Initialize the Dispatcher's data members
688
689 Arguments:
690
691 PeiServices - The PEI core services table.
692 OldCoreData - Pointer to old core data (before switching stack).
693 NULL if being run in non-permament memory mode.
694 SecCoreData - Points to a data structure containing information about the PEI core's operating
695 environment, such as the size and location of temporary RAM, the stack location and
696 the BFV location.
697
698 Returns:
699
700 None.
701
702 --*/
703 {
704 if (OldCoreData == NULL) {
705 PeiInitializeFv (PrivateData, SecCoreData);
706 }
707
708 return;
709 }
710
711
712 BOOLEAN
713 DepexSatisfied (
714 IN PEI_CORE_INSTANCE *Private,
715 IN EFI_PEI_FILE_HANDLE FileHandle,
716 IN UINTN PeimCount
717 )
718 /*++
719
720 Routine Description:
721
722 This routine parses the Dependency Expression, if available, and
723 decides if the module can be executed.
724
725 Arguments:
726 PeiServices - The PEI Service Table
727 CurrentPeimAddress - Address of the PEIM Firmware File under investigation
728
729 Returns:
730 TRUE - Can be dispatched
731 FALSE - Cannot be dispatched
732
733 --*/
734 {
735 EFI_STATUS Status;
736 VOID *DepexData;
737
738 if (PeimCount < Private->AprioriCount) {
739 //
740 // If its in the A priori file then we set Depex to TRUE
741 //
742 return TRUE;
743 }
744
745 //
746 // Depex section not in the encapsulated section.
747 //
748 Status = PeiServicesFfsFindSectionData (
749 EFI_SECTION_PEI_DEPEX,
750 FileHandle,
751 (VOID **)&DepexData
752 );
753
754 if (EFI_ERROR (Status)) {
755 //
756 // If there is no DEPEX, assume the module can be executed
757 //
758 return TRUE;
759 }
760
761 //
762 // Evaluate a given DEPEX
763 //
764 return PeimDispatchReadiness (&Private->PS, DepexData);
765 }
766
767 /**
768 This routine enable a PEIM to register itself to shadow when PEI Foundation
769 discovery permanent memory.
770
771 @param FileHandle File handle of a PEIM.
772
773 @retval EFI_NOT_FOUND The file handle doesn't point to PEIM itself.
774 @retval EFI_ALREADY_STARTED Indicate that the PEIM has been registered itself.
775 @retval EFI_SUCCESS Successfully to register itself.
776
777 **/
778 EFI_STATUS
779 EFIAPI
780 PeiRegisterForShadow (
781 IN EFI_PEI_FILE_HANDLE FileHandle
782 )
783 {
784 PEI_CORE_INSTANCE *Private;
785 Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());
786
787 if (Private->CurrentFileHandle != FileHandle) {
788 //
789 // The FileHandle must be for the current PEIM
790 //
791 return EFI_NOT_FOUND;
792 }
793
794 if (Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] >= PEIM_STATE_REGISITER_FOR_SHADOW) {
795 //
796 // If the PEIM has already entered the PEIM_STATE_REGISTER_FOR_SHADOW or PEIM_STATE_DONE then it's already been started
797 //
798 return EFI_ALREADY_STARTED;
799 }
800
801 Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] = PEIM_STATE_REGISITER_FOR_SHADOW;
802
803 return EFI_SUCCESS;
804 }
805
806
807
808 /**
809 Get Fv image from the FV type file, then install FV INFO ppi, Build FV hob.
810
811 @param PeiServices Pointer to the PEI Core Services Table.
812 @param FileHandle File handle of a Fv type file.
813 @param AuthenticationState Pointer to attestation authentication state of image.
814
815
816 @retval EFI_NOT_FOUND FV image can't be found.
817 @retval EFI_SUCCESS Successfully to process it.
818
819 **/
820 EFI_STATUS
821 ProcessFvFile (
822 IN EFI_PEI_SERVICES **PeiServices,
823 IN EFI_PEI_FILE_HANDLE FvFileHandle,
824 OUT UINT32 *AuthenticationState
825 )
826 {
827 EFI_STATUS Status;
828 EFI_PEI_FV_HANDLE FvImageHandle;
829 EFI_FV_INFO FvImageInfo;
830 UINT32 FvAlignment;
831 VOID *FvBuffer;
832 EFI_PEI_HOB_POINTERS HobFv2;
833
834 FvBuffer = NULL;
835 *AuthenticationState = 0;
836
837 //
838 // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already
839 // been extracted.
840 //
841 HobFv2.Raw = GetHobList ();
842 while ((HobFv2.Raw = GetNextHob (EFI_HOB_TYPE_FV2, HobFv2.Raw)) != NULL) {
843 if (CompareGuid (&(((EFI_FFS_FILE_HEADER *)FvFileHandle)->Name), &HobFv2.FirmwareVolume2->FileName)) {
844 //
845 // this FILE has been dispatched, it will not be dispatched again.
846 //
847 return EFI_SUCCESS;
848 }
849 HobFv2.Raw = GET_NEXT_HOB (HobFv2);
850 }
851
852 //
853 // Find FvImage in FvFile
854 //
855 Status = PeiFfsFindSectionData (
856 (CONST EFI_PEI_SERVICES **) PeiServices,
857 EFI_SECTION_FIRMWARE_VOLUME_IMAGE,
858 FvFileHandle,
859 (VOID **)&FvImageHandle
860 );
861
862 if (EFI_ERROR (Status)) {
863 return Status;
864 }
865 //
866 // Collect FvImage Info.
867 //
868 Status = PeiFfsGetVolumeInfo (FvImageHandle, &FvImageInfo);
869 ASSERT_EFI_ERROR (Status);
870 //
871 // FvAlignment must be more than 8 bytes required by FvHeader structure.
872 //
873 FvAlignment = 1 << ((FvImageInfo.FvAttributes & EFI_FVB2_ALIGNMENT) >> 16);
874 if (FvAlignment < 8) {
875 FvAlignment = 8;
876 }
877 //
878 // Check FvImage
879 //
880 if ((UINTN) FvImageInfo.FvStart % FvAlignment != 0) {
881 FvBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINT32) FvImageInfo.FvSize), FvAlignment);
882 if (FvBuffer == NULL) {
883 return EFI_OUT_OF_RESOURCES;
884 }
885 CopyMem (FvBuffer, FvImageInfo.FvStart, (UINTN) FvImageInfo.FvSize);
886 //
887 // Update FvImageInfo after reload FvImage to new aligned memory
888 //
889 PeiFfsGetVolumeInfo ((EFI_PEI_FV_HANDLE) FvBuffer, &FvImageInfo);
890 }
891
892 //
893 // Install FvPpi and Build FvHob
894 //
895 PiLibInstallFvInfoPpi (
896 NULL,
897 FvImageInfo.FvStart,
898 (UINT32) FvImageInfo.FvSize,
899 &(FvImageInfo.FvName),
900 &(((EFI_FFS_FILE_HEADER*)FvFileHandle)->Name)
901 );
902
903 //
904 // Inform HOB consumer phase, i.e. DXE core, the existance of this FV
905 //
906 BuildFvHob (
907 (EFI_PHYSICAL_ADDRESS) (UINTN) FvImageInfo.FvStart,
908 FvImageInfo.FvSize
909 );
910 //
911 // Makes the encapsulated volume show up in DXE phase to skip processing of
912 // encapsulated file again.
913 //
914 BuildFv2Hob (
915 (EFI_PHYSICAL_ADDRESS) (UINTN) FvImageInfo.FvStart,
916 FvImageInfo.FvSize,
917 &FvImageInfo.FvName,
918 &(((EFI_FFS_FILE_HEADER *)FvFileHandle)->Name)
919 );
920
921 return EFI_SUCCESS;
922 }