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