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