Home | History | Annotate | Download | only in PeiMain
      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
     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
    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