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