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