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