• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Pei Core Main Entry Point
3 
4 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution.  The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9 
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include "PeiMain.h"
16 
17 EFI_PEI_PPI_DESCRIPTOR mMemoryDiscoveredPpi = {
18   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
19   &gEfiPeiMemoryDiscoveredPpiGuid,
20   NULL
21 };
22 
23 ///
24 /// Pei service instance
25 ///
26 EFI_PEI_SERVICES  gPs = {
27   {
28     PEI_SERVICES_SIGNATURE,
29     PEI_SERVICES_REVISION,
30     sizeof (EFI_PEI_SERVICES),
31     0,
32     0
33   },
34   PeiInstallPpi,
35   PeiReInstallPpi,
36   PeiLocatePpi,
37   PeiNotifyPpi,
38 
39   PeiGetBootMode,
40   PeiSetBootMode,
41 
42   PeiGetHobList,
43   PeiCreateHob,
44 
45   PeiFfsFindNextVolume,
46   PeiFfsFindNextFile,
47   PeiFfsFindSectionData,
48 
49   PeiInstallPeiMemory,
50   PeiAllocatePages,
51   PeiAllocatePool,
52   (EFI_PEI_COPY_MEM)CopyMem,
53   (EFI_PEI_SET_MEM)SetMem,
54 
55   PeiReportStatusCode,
56   PeiResetSystem,
57 
58   &gPeiDefaultCpuIoPpi,
59   &gPeiDefaultPciCfg2Ppi,
60 
61   PeiFfsFindFileByName,
62   PeiFfsGetFileInfo,
63   PeiFfsGetVolumeInfo,
64   PeiRegisterForShadow,
65   PeiFfsFindSectionData3,
66   PeiFfsGetFileInfo2,
67   PeiResetSystem2
68 };
69 
70 /**
71   Shadow PeiCore module from flash to installed memory.
72 
73   @param PrivateData    PeiCore's private data structure
74 
75   @return PeiCore function address after shadowing.
76 **/
77 PEICORE_FUNCTION_POINTER
ShadowPeiCore(IN PEI_CORE_INSTANCE * PrivateData)78 ShadowPeiCore (
79   IN PEI_CORE_INSTANCE  *PrivateData
80   )
81 {
82   EFI_PEI_FILE_HANDLE  PeiCoreFileHandle;
83   EFI_PHYSICAL_ADDRESS EntryPoint;
84   EFI_STATUS           Status;
85   UINT32               AuthenticationState;
86 
87   PeiCoreFileHandle = NULL;
88 
89   //
90   // Find the PEI Core in the BFV
91   //
92   Status = PrivateData->Fv[0].FvPpi->FindFileByType (
93                                        PrivateData->Fv[0].FvPpi,
94                                        EFI_FV_FILETYPE_PEI_CORE,
95                                        PrivateData->Fv[0].FvHandle,
96                                        &PeiCoreFileHandle
97                                        );
98   ASSERT_EFI_ERROR (Status);
99 
100   //
101   // Shadow PEI Core into memory so it will run faster
102   //
103   Status = PeiLoadImage (
104               GetPeiServicesTablePointer (),
105               *((EFI_PEI_FILE_HANDLE*)&PeiCoreFileHandle),
106               PEIM_STATE_REGISITER_FOR_SHADOW,
107               &EntryPoint,
108               &AuthenticationState
109               );
110   ASSERT_EFI_ERROR (Status);
111 
112   //
113   // Compute the PeiCore's function address after shaowed PeiCore.
114   // _ModuleEntryPoint is PeiCore main function entry
115   //
116   return (PEICORE_FUNCTION_POINTER)((UINTN) EntryPoint + (UINTN) PeiCore - (UINTN) _ModuleEntryPoint);
117 }
118 
119 /**
120   This routine is invoked by main entry of PeiMain module during transition
121   from SEC to PEI. After switching stack in the PEI core, it will restart
122   with the old core data.
123 
124   @param SecCoreDataPtr  Points to a data structure containing information about the PEI core's operating
125                          environment, such as the size and location of temporary RAM, the stack location and
126                          the BFV location.
127   @param PpiList         Points to a list of one or more PPI descriptors to be installed initially by the PEI core.
128                          An empty PPI list consists of a single descriptor with the end-tag
129                          EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST. As part of its initialization
130                          phase, the PEI Foundation will add these SEC-hosted PPIs to its PPI database such
131                          that both the PEI Foundation and any modules can leverage the associated service
132                          calls and/or code in these early PPIs
133   @param Data            Pointer to old core data that is used to initialize the
134                          core's data areas.
135                          If NULL, it is first PeiCore entering.
136 
137 **/
138 VOID
139 EFIAPI
PeiCore(IN CONST EFI_SEC_PEI_HAND_OFF * SecCoreDataPtr,IN CONST EFI_PEI_PPI_DESCRIPTOR * PpiList,IN VOID * Data)140 PeiCore (
141   IN CONST EFI_SEC_PEI_HAND_OFF        *SecCoreDataPtr,
142   IN CONST EFI_PEI_PPI_DESCRIPTOR      *PpiList,
143   IN VOID                              *Data
144   )
145 {
146   PEI_CORE_INSTANCE           PrivateData;
147   EFI_SEC_PEI_HAND_OFF        *SecCoreData;
148   EFI_SEC_PEI_HAND_OFF        NewSecCoreData;
149   EFI_STATUS                  Status;
150   PEI_CORE_TEMP_POINTERS      TempPtr;
151   PEI_CORE_INSTANCE           *OldCoreData;
152   EFI_PEI_CPU_IO_PPI          *CpuIo;
153   EFI_PEI_PCI_CFG2_PPI        *PciCfg;
154   EFI_HOB_HANDOFF_INFO_TABLE  *HandoffInformationTable;
155   EFI_PEI_TEMPORARY_RAM_DONE_PPI *TemporaryRamDonePpi;
156   UINTN                       Index;
157 
158   //
159   // Retrieve context passed into PEI Core
160   //
161   OldCoreData = (PEI_CORE_INSTANCE *) Data;
162   SecCoreData = (EFI_SEC_PEI_HAND_OFF *) SecCoreDataPtr;
163 
164   //
165   // Perform PEI Core phase specific actions.
166   //
167   if (OldCoreData == NULL) {
168     //
169     // If OldCoreData is NULL, means current is the first entry into the PEI Core before memory is available.
170     //
171     ZeroMem (&PrivateData, sizeof (PEI_CORE_INSTANCE));
172     PrivateData.Signature = PEI_CORE_HANDLE_SIGNATURE;
173     CopyMem (&PrivateData.ServiceTableShadow, &gPs, sizeof (gPs));
174   } else {
175     //
176     // Memory is available to the PEI Core.  See if the PEI Core has been shadowed to memory yet.
177     //
178     if (OldCoreData->ShadowedPeiCore == NULL) {
179       //
180       // Fixup the PeiCore's private data
181       //
182       OldCoreData->Ps    = &OldCoreData->ServiceTableShadow;
183       OldCoreData->CpuIo = &OldCoreData->ServiceTableShadow.CpuIo;
184       if (OldCoreData->HeapOffsetPositive) {
185         OldCoreData->HobList.Raw = (VOID *)(OldCoreData->HobList.Raw + OldCoreData->HeapOffset);
186         OldCoreData->UnknownFvInfo        = (PEI_CORE_UNKNOW_FORMAT_FV_INFO *) ((UINT8 *) OldCoreData->UnknownFvInfo + OldCoreData->HeapOffset);
187         OldCoreData->CurrentFvFileHandles = (EFI_PEI_FILE_HANDLE *) ((UINT8 *) OldCoreData->CurrentFvFileHandles + OldCoreData->HeapOffset);
188         OldCoreData->PpiData.PpiListPtrs  = (PEI_PPI_LIST_POINTERS *) ((UINT8 *) OldCoreData->PpiData.PpiListPtrs + OldCoreData->HeapOffset);
189         OldCoreData->Fv                   = (PEI_CORE_FV_HANDLE *) ((UINT8 *) OldCoreData->Fv + OldCoreData->HeapOffset);
190         for (Index = 0; Index < PcdGet32 (PcdPeiCoreMaxFvSupported); Index ++) {
191           OldCoreData->Fv[Index].PeimState     = (UINT8 *) OldCoreData->Fv[Index].PeimState + OldCoreData->HeapOffset;
192           OldCoreData->Fv[Index].FvFileHandles = (EFI_PEI_FILE_HANDLE *) ((UINT8 *) OldCoreData->Fv[Index].FvFileHandles + OldCoreData->HeapOffset);
193         }
194         OldCoreData->FileGuid             = (EFI_GUID *) ((UINT8 *) OldCoreData->FileGuid + OldCoreData->HeapOffset);
195         OldCoreData->FileHandles          = (EFI_PEI_FILE_HANDLE *) ((UINT8 *) OldCoreData->FileHandles + OldCoreData->HeapOffset);
196       } else {
197         OldCoreData->HobList.Raw = (VOID *)(OldCoreData->HobList.Raw - OldCoreData->HeapOffset);
198         OldCoreData->UnknownFvInfo        = (PEI_CORE_UNKNOW_FORMAT_FV_INFO *) ((UINT8 *) OldCoreData->UnknownFvInfo - OldCoreData->HeapOffset);
199         OldCoreData->CurrentFvFileHandles = (EFI_PEI_FILE_HANDLE *) ((UINT8 *) OldCoreData->CurrentFvFileHandles - OldCoreData->HeapOffset);
200         OldCoreData->PpiData.PpiListPtrs  = (PEI_PPI_LIST_POINTERS *) ((UINT8 *) OldCoreData->PpiData.PpiListPtrs - OldCoreData->HeapOffset);
201         OldCoreData->Fv                   = (PEI_CORE_FV_HANDLE *) ((UINT8 *) OldCoreData->Fv - OldCoreData->HeapOffset);
202         for (Index = 0; Index < PcdGet32 (PcdPeiCoreMaxFvSupported); Index ++) {
203           OldCoreData->Fv[Index].PeimState     = (UINT8 *) OldCoreData->Fv[Index].PeimState - OldCoreData->HeapOffset;
204           OldCoreData->Fv[Index].FvFileHandles = (EFI_PEI_FILE_HANDLE *) ((UINT8 *) OldCoreData->Fv[Index].FvFileHandles - OldCoreData->HeapOffset);
205         }
206         OldCoreData->FileGuid             = (EFI_GUID *) ((UINT8 *) OldCoreData->FileGuid - OldCoreData->HeapOffset);
207         OldCoreData->FileHandles          = (EFI_PEI_FILE_HANDLE *) ((UINT8 *) OldCoreData->FileHandles - OldCoreData->HeapOffset);
208       }
209 
210       //
211       // Fixup for PeiService's address
212       //
213       SetPeiServicesTablePointer ((CONST EFI_PEI_SERVICES **)&OldCoreData->Ps);
214 
215       //
216       // Initialize libraries that the PEI Core is linked against
217       //
218       ProcessLibraryConstructorList (NULL, (CONST EFI_PEI_SERVICES **)&OldCoreData->Ps);
219 
220       //
221       // Update HandOffHob for new installed permanent memory
222       //
223       HandoffInformationTable = OldCoreData->HobList.HandoffInformationTable;
224       if (OldCoreData->HeapOffsetPositive) {
225         HandoffInformationTable->EfiEndOfHobList   = HandoffInformationTable->EfiEndOfHobList + OldCoreData->HeapOffset;
226       } else {
227         HandoffInformationTable->EfiEndOfHobList   = HandoffInformationTable->EfiEndOfHobList - OldCoreData->HeapOffset;
228       }
229       HandoffInformationTable->EfiMemoryTop        = OldCoreData->PhysicalMemoryBegin + OldCoreData->PhysicalMemoryLength;
230       HandoffInformationTable->EfiMemoryBottom     = OldCoreData->PhysicalMemoryBegin;
231       HandoffInformationTable->EfiFreeMemoryTop    = OldCoreData->FreePhysicalMemoryTop;
232       HandoffInformationTable->EfiFreeMemoryBottom = HandoffInformationTable->EfiEndOfHobList + sizeof (EFI_HOB_GENERIC_HEADER);
233 
234       //
235       // We need convert the PPI descriptor's pointer
236       //
237       ConvertPpiPointers (SecCoreData, OldCoreData);
238 
239       //
240       // After the whole temporary memory is migrated, then we can allocate page in
241       // permanent memory.
242       //
243       OldCoreData->PeiMemoryInstalled = TRUE;
244 
245       //
246       // Indicate that PeiCore reenter
247       //
248       OldCoreData->PeimDispatcherReenter = TRUE;
249 
250       if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0 && (OldCoreData->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
251         //
252         // if Loading Module at Fixed Address is enabled, allocate the PEI code memory range usage bit map array.
253         // Every bit in the array indicate the status of the corresponding memory page available or not
254         //
255         OldCoreData->PeiCodeMemoryRangeUsageBitMap = AllocateZeroPool (((PcdGet32(PcdLoadFixAddressPeiCodePageNumber)>>6) + 1)*sizeof(UINT64));
256       }
257 
258       //
259       // Shadow PEI Core. When permanent memory is avaiable, shadow
260       // PEI Core and PEIMs to get high performance.
261       //
262       OldCoreData->ShadowedPeiCore = (PEICORE_FUNCTION_POINTER) (UINTN) PeiCore;
263       if ((HandoffInformationTable->BootMode == BOOT_ON_S3_RESUME && PcdGetBool (PcdShadowPeimOnS3Boot))
264           || (HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME && PcdGetBool (PcdShadowPeimOnBoot))) {
265         OldCoreData->ShadowedPeiCore = ShadowPeiCore (OldCoreData);
266       }
267 
268       //
269       // PEI Core has now been shadowed to memory.  Restart PEI Core in memory.
270       //
271       OldCoreData->ShadowedPeiCore (SecCoreData, PpiList, OldCoreData);
272 
273       //
274       // Should never reach here.
275       //
276       ASSERT (FALSE);
277       CpuDeadLoop();
278 
279       UNREACHABLE ();
280     }
281 
282     //
283     // Memory is available to the PEI Core and the PEI Core has been shadowed to memory.
284     //
285     CopyMem (&NewSecCoreData, SecCoreDataPtr, sizeof (NewSecCoreData));
286     SecCoreData = &NewSecCoreData;
287 
288     CopyMem (&PrivateData, OldCoreData, sizeof (PrivateData));
289 
290     CpuIo = (VOID*)PrivateData.ServiceTableShadow.CpuIo;
291     PciCfg = (VOID*)PrivateData.ServiceTableShadow.PciCfg;
292 
293     CopyMem (&PrivateData.ServiceTableShadow, &gPs, sizeof (gPs));
294 
295     PrivateData.ServiceTableShadow.CpuIo  = CpuIo;
296     PrivateData.ServiceTableShadow.PciCfg = PciCfg;
297   }
298 
299   //
300   // Cache a pointer to the PEI Services Table that is either in temporary memory or permanent memory
301   //
302   PrivateData.Ps = &PrivateData.ServiceTableShadow;
303 
304   //
305   // Save PeiServicePointer so that it can be retrieved anywhere.
306   //
307   SetPeiServicesTablePointer ((CONST EFI_PEI_SERVICES **)&PrivateData.Ps);
308 
309   //
310   // Initialize libraries that the PEI Core is linked against
311   //
312   ProcessLibraryConstructorList (NULL, (CONST EFI_PEI_SERVICES **)&PrivateData.Ps);
313 
314   //
315   // Initialize PEI Core Services
316   //
317   InitializeMemoryServices   (&PrivateData,    SecCoreData, OldCoreData);
318   if (OldCoreData == NULL) {
319     //
320     // Initialize PEI Core Private Data Buffer
321     //
322     PrivateData.PpiData.PpiListPtrs  = AllocateZeroPool (sizeof (PEI_PPI_LIST_POINTERS) * PcdGet32 (PcdPeiCoreMaxPpiSupported));
323     ASSERT (PrivateData.PpiData.PpiListPtrs != NULL);
324     PrivateData.Fv                   = AllocateZeroPool (sizeof (PEI_CORE_FV_HANDLE) * PcdGet32 (PcdPeiCoreMaxFvSupported));
325     ASSERT (PrivateData.Fv != NULL);
326     PrivateData.Fv[0].PeimState      = AllocateZeroPool (sizeof (UINT8) * PcdGet32 (PcdPeiCoreMaxPeimPerFv) * PcdGet32 (PcdPeiCoreMaxFvSupported));
327     ASSERT (PrivateData.Fv[0].PeimState != NULL);
328     PrivateData.Fv[0].FvFileHandles  = AllocateZeroPool (sizeof (EFI_PEI_FILE_HANDLE) * PcdGet32 (PcdPeiCoreMaxPeimPerFv) * PcdGet32 (PcdPeiCoreMaxFvSupported));
329     ASSERT (PrivateData.Fv[0].FvFileHandles != NULL);
330     for (Index = 1; Index < PcdGet32 (PcdPeiCoreMaxFvSupported); Index ++) {
331       PrivateData.Fv[Index].PeimState     = PrivateData.Fv[Index - 1].PeimState + PcdGet32 (PcdPeiCoreMaxPeimPerFv);
332       PrivateData.Fv[Index].FvFileHandles = PrivateData.Fv[Index - 1].FvFileHandles + PcdGet32 (PcdPeiCoreMaxPeimPerFv);
333     }
334     PrivateData.UnknownFvInfo        = AllocateZeroPool (sizeof (PEI_CORE_UNKNOW_FORMAT_FV_INFO) * PcdGet32 (PcdPeiCoreMaxFvSupported));
335     ASSERT (PrivateData.UnknownFvInfo != NULL);
336     PrivateData.CurrentFvFileHandles = AllocateZeroPool (sizeof (EFI_PEI_FILE_HANDLE) * PcdGet32 (PcdPeiCoreMaxPeimPerFv));
337     ASSERT (PrivateData.CurrentFvFileHandles != NULL);
338     PrivateData.FileGuid             = AllocatePool (sizeof (EFI_GUID) * PcdGet32 (PcdPeiCoreMaxPeimPerFv));
339     ASSERT (PrivateData.FileGuid != NULL);
340     PrivateData.FileHandles          = AllocatePool (sizeof (EFI_PEI_FILE_HANDLE) * (PcdGet32 (PcdPeiCoreMaxPeimPerFv) + 1));
341     ASSERT (PrivateData.FileHandles != NULL);
342   }
343   InitializePpiServices      (&PrivateData,    OldCoreData);
344 
345   //
346   // Update performance measurements
347   //
348   if (OldCoreData == NULL) {
349     PERF_START (NULL, "SEC", NULL, 1);
350     PERF_END   (NULL, "SEC", NULL, 0);
351 
352     //
353     // If first pass, start performance measurement.
354     //
355     PERF_START (NULL,"PEI",    NULL, 0);
356     PERF_START (NULL,"PreMem", NULL, 0);
357 
358   } else {
359     PERF_END   (NULL,"PreMem",  NULL, 0);
360     PERF_START (NULL,"PostMem", NULL, 0);
361   }
362 
363   //
364   // Complete PEI Core Service initialization
365   //
366   InitializeSecurityServices (&PrivateData.Ps, OldCoreData);
367   InitializeDispatcherData   (&PrivateData,    OldCoreData, SecCoreData);
368   InitializeImageServices    (&PrivateData,    OldCoreData);
369 
370   //
371   // Perform PEI Core Phase specific actions
372   //
373   if (OldCoreData == NULL) {
374     //
375     // Report Status Code EFI_SW_PC_INIT
376     //
377     REPORT_STATUS_CODE (
378       EFI_PROGRESS_CODE,
379       (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT)
380       );
381 
382     //
383     // If SEC provided any PPI services to PEI, install them.
384     //
385     if (PpiList != NULL) {
386       Status = PeiServicesInstallPpi (PpiList);
387       ASSERT_EFI_ERROR (Status);
388     }
389   } else {
390     //
391     // Try to locate Temporary RAM Done Ppi.
392     //
393     Status = PeiServicesLocatePpi (
394                &gEfiTemporaryRamDonePpiGuid,
395                0,
396                NULL,
397                (VOID**)&TemporaryRamDonePpi
398                );
399     if (!EFI_ERROR (Status)) {
400       //
401       // Disable the use of Temporary RAM after the transition from Temporary RAM to Permanent RAM is complete.
402       //
403       TemporaryRamDonePpi->TemporaryRamDone ();
404     }
405 
406     //
407     // Alert any listeners that there is permanent memory available
408     //
409     PERF_START (NULL,"DisMem", NULL, 0);
410     Status = PeiServicesInstallPpi (&mMemoryDiscoveredPpi);
411 
412     //
413     // Process the Notify list and dispatch any notifies for the Memory Discovered PPI
414     //
415     ProcessNotifyList (&PrivateData);
416 
417     PERF_END (NULL,"DisMem", NULL, 0);
418   }
419 
420   //
421   // Call PEIM dispatcher
422   //
423   PeiDispatcher (SecCoreData, &PrivateData);
424 
425   if (PrivateData.HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) {
426     //
427     // Check if InstallPeiMemory service was called on non-S3 resume boot path.
428     //
429     ASSERT(PrivateData.PeiMemoryInstalled == TRUE);
430   }
431 
432   //
433   // Measure PEI Core execution time.
434   //
435   PERF_END (NULL, "PostMem", NULL, 0);
436 
437   //
438   // Lookup DXE IPL PPI
439   //
440   Status = PeiServicesLocatePpi (
441              &gEfiDxeIplPpiGuid,
442              0,
443              NULL,
444              (VOID **)&TempPtr.DxeIpl
445              );
446   ASSERT_EFI_ERROR (Status);
447 
448   if (EFI_ERROR (Status)) {
449     //
450     // Report status code to indicate DXE IPL PPI could not be found.
451     //
452     REPORT_STATUS_CODE (
453       EFI_ERROR_CODE | EFI_ERROR_MAJOR,
454       (EFI_SOFTWARE_PEI_CORE | EFI_SW_PEI_CORE_EC_DXEIPL_NOT_FOUND)
455       );
456     CpuDeadLoop ();
457   }
458 
459   //
460   // Enter DxeIpl to load Dxe core.
461   //
462   DEBUG ((EFI_D_INFO, "DXE IPL Entry\n"));
463   Status = TempPtr.DxeIpl->Entry (
464                              TempPtr.DxeIpl,
465                              &PrivateData.Ps,
466                              PrivateData.HobList
467                              );
468   //
469   // Should never reach here.
470   //
471   ASSERT_EFI_ERROR (Status);
472   CpuDeadLoop();
473 
474   UNREACHABLE ();
475 }
476