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