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