• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Pei Core Main Entry Point
3 
4 Copyright (c) 2006 - 2015, 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       // Initialize libraries that the PEI Core is linked against
212       //
213       ProcessLibraryConstructorList (NULL, (CONST EFI_PEI_SERVICES **)&OldCoreData->Ps);
214 
215       //
216       // Fixup for PeiService's address
217       //
218       SetPeiServicesTablePointer ((CONST EFI_PEI_SERVICES **)&OldCoreData->Ps);
219 
220       //
221       // Update HandOffHob for new installed permenent 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       // permenent 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 
280     //
281     // Memory is available to the PEI Core and the PEI Core has been shadowed to memory.
282     //
283     CopyMem (&NewSecCoreData, SecCoreDataPtr, sizeof (NewSecCoreData));
284     SecCoreData = &NewSecCoreData;
285 
286     CopyMem (&PrivateData, OldCoreData, sizeof (PrivateData));
287 
288     CpuIo = (VOID*)PrivateData.ServiceTableShadow.CpuIo;
289     PciCfg = (VOID*)PrivateData.ServiceTableShadow.PciCfg;
290 
291     CopyMem (&PrivateData.ServiceTableShadow, &gPs, sizeof (gPs));
292 
293     PrivateData.ServiceTableShadow.CpuIo  = CpuIo;
294     PrivateData.ServiceTableShadow.PciCfg = PciCfg;
295   }
296 
297   //
298   // Cache a pointer to the PEI Services Table that is either in temporary memory or permanent memory
299   //
300   PrivateData.Ps = &PrivateData.ServiceTableShadow;
301 
302   //
303   // Initialize libraries that the PEI Core is linked against
304   //
305   ProcessLibraryConstructorList (NULL, (CONST EFI_PEI_SERVICES **)&PrivateData.Ps);
306 
307   //
308   // Save PeiServicePointer so that it can be retrieved anywhere.
309   //
310   SetPeiServicesTablePointer ((CONST EFI_PEI_SERVICES **)&PrivateData.Ps);
311 
312   //
313   // Initialize PEI Core Services
314   //
315   InitializeMemoryServices   (&PrivateData,    SecCoreData, OldCoreData);
316   if (OldCoreData == NULL) {
317     //
318     // Initialize PEI Core Private Data Buffer
319     //
320     PrivateData.PpiData.PpiListPtrs  = AllocateZeroPool (sizeof (PEI_PPI_LIST_POINTERS) * PcdGet32 (PcdPeiCoreMaxPpiSupported));
321     ASSERT (PrivateData.PpiData.PpiListPtrs != NULL);
322     PrivateData.Fv                   = AllocateZeroPool (sizeof (PEI_CORE_FV_HANDLE) * PcdGet32 (PcdPeiCoreMaxFvSupported));
323     ASSERT (PrivateData.Fv != NULL);
324     PrivateData.Fv[0].PeimState      = AllocateZeroPool (sizeof (UINT8) * PcdGet32 (PcdPeiCoreMaxPeimPerFv) * PcdGet32 (PcdPeiCoreMaxFvSupported));
325     ASSERT (PrivateData.Fv[0].PeimState != NULL);
326     PrivateData.Fv[0].FvFileHandles  = AllocateZeroPool (sizeof (EFI_PEI_FILE_HANDLE) * PcdGet32 (PcdPeiCoreMaxPeimPerFv) * PcdGet32 (PcdPeiCoreMaxFvSupported));
327     ASSERT (PrivateData.Fv[0].FvFileHandles != NULL);
328     for (Index = 1; Index < PcdGet32 (PcdPeiCoreMaxFvSupported); Index ++) {
329       PrivateData.Fv[Index].PeimState     = PrivateData.Fv[Index - 1].PeimState + PcdGet32 (PcdPeiCoreMaxPeimPerFv);
330       PrivateData.Fv[Index].FvFileHandles = PrivateData.Fv[Index - 1].FvFileHandles + PcdGet32 (PcdPeiCoreMaxPeimPerFv);
331     }
332     PrivateData.UnknownFvInfo        = AllocateZeroPool (sizeof (PEI_CORE_UNKNOW_FORMAT_FV_INFO) * PcdGet32 (PcdPeiCoreMaxFvSupported));
333     ASSERT (PrivateData.UnknownFvInfo != NULL);
334     PrivateData.CurrentFvFileHandles = AllocateZeroPool (sizeof (EFI_PEI_FILE_HANDLE) * PcdGet32 (PcdPeiCoreMaxPeimPerFv));
335     ASSERT (PrivateData.CurrentFvFileHandles != NULL);
336     PrivateData.FileGuid             = AllocatePool (sizeof (EFI_GUID) * PcdGet32 (PcdPeiCoreMaxPeimPerFv));
337     ASSERT (PrivateData.FileGuid != NULL);
338     PrivateData.FileHandles          = AllocatePool (sizeof (EFI_PEI_FILE_HANDLE) * (PcdGet32 (PcdPeiCoreMaxPeimPerFv) + 1));
339     ASSERT (PrivateData.FileHandles != NULL);
340   }
341   InitializePpiServices      (&PrivateData,    OldCoreData);
342 
343   //
344   // Update performance measurements
345   //
346   if (OldCoreData == NULL) {
347     PERF_START (NULL, "SEC", NULL, 1);
348     PERF_END   (NULL, "SEC", NULL, 0);
349 
350     //
351     // If first pass, start performance measurement.
352     //
353     PERF_START (NULL,"PEI",    NULL, 0);
354     PERF_START (NULL,"PreMem", NULL, 0);
355 
356   } else {
357     PERF_END   (NULL,"PreMem",  NULL, 0);
358     PERF_START (NULL,"PostMem", NULL, 0);
359   }
360 
361   //
362   // Complete PEI Core Service initialization
363   //
364   InitializeSecurityServices (&PrivateData.Ps, OldCoreData);
365   InitializeDispatcherData   (&PrivateData,    OldCoreData, SecCoreData);
366   InitializeImageServices    (&PrivateData,    OldCoreData);
367 
368   //
369   // Perform PEI Core Phase specific actions
370   //
371   if (OldCoreData == NULL) {
372     //
373     // Report Status Code EFI_SW_PC_INIT
374     //
375     REPORT_STATUS_CODE (
376       EFI_PROGRESS_CODE,
377       (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT)
378       );
379 
380     //
381     // If SEC provided any PPI services to PEI, install them.
382     //
383     if (PpiList != NULL) {
384       Status = PeiServicesInstallPpi (PpiList);
385       ASSERT_EFI_ERROR (Status);
386     }
387   } else {
388     //
389     // Try to locate Temporary RAM Done Ppi.
390     //
391     Status = PeiServicesLocatePpi (
392                &gEfiTemporaryRamDonePpiGuid,
393                0,
394                NULL,
395                (VOID**)&TemporaryRamDonePpi
396                );
397     if (!EFI_ERROR (Status)) {
398       //
399       // Disable the use of Temporary RAM after the transition from Temporary RAM to Permanent RAM is complete.
400       //
401       TemporaryRamDonePpi->TemporaryRamDone ();
402     }
403 
404     //
405     // Alert any listeners that there is permanent memory available
406     //
407     PERF_START (NULL,"DisMem", NULL, 0);
408     Status = PeiServicesInstallPpi (&mMemoryDiscoveredPpi);
409 
410     //
411     // Process the Notify list and dispatch any notifies for the Memory Discovered PPI
412     //
413     ProcessNotifyList (&PrivateData);
414 
415     PERF_END (NULL,"DisMem", NULL, 0);
416   }
417 
418   //
419   // Call PEIM dispatcher
420   //
421   PeiDispatcher (SecCoreData, &PrivateData);
422 
423   //
424   // Check if InstallPeiMemory service was called.
425   //
426   ASSERT(PrivateData.PeiMemoryInstalled == TRUE);
427 
428   //
429   // Measure PEI Core execution time.
430   //
431   PERF_END (NULL, "PostMem", NULL, 0);
432 
433   //
434   // Lookup DXE IPL PPI
435   //
436   Status = PeiServicesLocatePpi (
437              &gEfiDxeIplPpiGuid,
438              0,
439              NULL,
440              (VOID **)&TempPtr.DxeIpl
441              );
442   ASSERT_EFI_ERROR (Status);
443 
444   if (EFI_ERROR (Status)) {
445     //
446     // Report status code to indicate DXE IPL PPI could not be found.
447     //
448     REPORT_STATUS_CODE (
449       EFI_ERROR_CODE | EFI_ERROR_MAJOR,
450       (EFI_SOFTWARE_PEI_CORE | EFI_SW_PEI_CORE_EC_DXEIPL_NOT_FOUND)
451       );
452     CpuDeadLoop ();
453   }
454 
455   //
456   // Enter DxeIpl to load Dxe core.
457   //
458   DEBUG ((EFI_D_INFO, "DXE IPL Entry\n"));
459   Status = TempPtr.DxeIpl->Entry (
460                              TempPtr.DxeIpl,
461                              &PrivateData.Ps,
462                              PrivateData.HobList
463                              );
464   //
465   // Should never reach here.
466   //
467   ASSERT_EFI_ERROR (Status);
468   CpuDeadLoop();
469 }
470