Home | History | Annotate | Download | only in BaseFspPlatformLib
      1 /** @file
      2 
      3   Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
      4   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 **/
     13 
     14 #include <PiPei.h>
     15 #include <Library/PeiServicesLib.h>
     16 #include <Library/PeiServicesTablePointerLib.h>
     17 #include <Library/BaseLib.h>
     18 #include <Library/BaseMemoryLib.h>
     19 #include <Library/PcdLib.h>
     20 #include <Library/DebugLib.h>
     21 #include <Library/HobLib.h>
     22 #include <Library/FspSwitchStackLib.h>
     23 #include <Library/FspCommonLib.h>
     24 #include <Guid/EventGroup.h>
     25 #include <FspEas.h>
     26 #include <FspStatusCode.h>
     27 #include <Protocol/PciEnumerationComplete.h>
     28 #include <Library/ReportStatusCodeLib.h>
     29 #include <Library/PerformanceLib.h>
     30 extern EFI_GUID gFspPerformanceDataGuid;
     31 
     32 EFI_PEI_PPI_DESCRIPTOR      mPeiPostPciEnumerationPpi = {
     33   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
     34   &gEfiPciEnumerationCompleteProtocolGuid,
     35   NULL
     36 };
     37 
     38 EFI_PEI_PPI_DESCRIPTOR      mPeiReadyToBootPpi = {
     39   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
     40   &gEfiEventReadyToBootGuid,
     41   NULL
     42 };
     43 
     44 EFI_PEI_PPI_DESCRIPTOR      mPeiEndOfFirmwarePpi = {
     45   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
     46   &gFspEventEndOfFirmwareGuid,
     47   NULL
     48 };
     49 
     50 UINT32  mFspNotifySequence[] = {
     51   EnumInitPhaseAfterPciEnumeration,
     52   EnumInitPhaseReadyToBoot,
     53   EnumInitPhaseEndOfFirmware
     54 };
     55 
     56 /**
     57   Install FSP notification.
     58 
     59   @param[in] NotificationCode  FSP notification code
     60 
     61   @retval EFI_SUCCESS            Notify FSP successfully
     62   @retval EFI_INVALID_PARAMETER  NotificationCode is invalid
     63 
     64 **/
     65 EFI_STATUS
     66 EFIAPI
     67 FspNotificationHandler (
     68   IN  UINT32     NotificationCode
     69   )
     70 {
     71   EFI_STATUS                Status;
     72 
     73   Status   = EFI_SUCCESS;
     74 
     75   switch (NotificationCode) {
     76   case EnumInitPhaseAfterPciEnumeration:
     77     //
     78     // Do POST PCI initialization if needed
     79     //
     80     DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP Post PCI Enumeration ...\n"));
     81     PeiServicesInstallPpi (&mPeiPostPciEnumerationPpi);
     82     break;
     83 
     84   case EnumInitPhaseReadyToBoot:
     85     //
     86     // Ready To Boot
     87     //
     88     DEBUG ((DEBUG_INFO| DEBUG_INIT, "FSP Ready To Boot ...\n"));
     89     PeiServicesInstallPpi (&mPeiReadyToBootPpi);
     90     break;
     91 
     92   case EnumInitPhaseEndOfFirmware:
     93     //
     94     // End of Firmware
     95     //
     96     DEBUG ((DEBUG_INFO| DEBUG_INIT, "FSP End of Firmware ...\n"));
     97     PeiServicesInstallPpi (&mPeiEndOfFirmwarePpi);
     98     break;
     99 
    100   default:
    101     Status = EFI_INVALID_PARAMETER;
    102     break;
    103   }
    104 
    105   return Status;
    106 }
    107 
    108 /**
    109   This function transfer control back to BootLoader after FspSiliconInit.
    110 
    111   @param[in] Status return status for the FspSiliconInit.
    112 
    113 **/
    114 VOID
    115 EFIAPI
    116 FspSiliconInitDone2 (
    117   IN EFI_STATUS Status
    118   )
    119 {
    120   //
    121   // Convert to FSP EAS defined API return codes
    122   //
    123   switch (Status) {
    124     case EFI_SUCCESS:
    125     case EFI_INVALID_PARAMETER:
    126     case EFI_UNSUPPORTED:
    127     case EFI_DEVICE_ERROR:
    128       break;
    129     default:
    130       DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspSiliconInitApi() Invalid Error - [Status: 0x%08X]\n", Status));
    131       Status = EFI_DEVICE_ERROR;  // Force to known error.
    132       break;
    133   }
    134   //
    135   // This is the end of the FspSiliconInit API
    136   // Give control back to the boot loader
    137   //
    138   SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_EXIT);
    139   DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspSiliconInitApi() - [Status: 0x%08X] - End\n", Status));
    140   PERF_END_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
    141   REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
    142   do {
    143     SetFspApiReturnStatus (Status);
    144     Pei2LoaderSwitchStack ();
    145     if (Status != EFI_SUCCESS) {
    146       DEBUG ((DEBUG_ERROR, "!!!ERROR: FspSiliconInitApi() - [Status: 0x%08X] - Error encountered during previous API and cannot proceed further\n", Status));
    147     }
    148   } while (Status != EFI_SUCCESS);
    149 }
    150 
    151 /**
    152   This function returns control to BootLoader after MemoryInitApi.
    153 
    154   @param[in] Status return status for the MemoryInitApi.
    155   @param[in,out] HobListPtr The address of HobList pointer, if NULL, will get value from GetFspApiParameter2 ()
    156 **/
    157 VOID
    158 EFIAPI
    159 FspMemoryInitDone2 (
    160   IN EFI_STATUS Status,
    161   IN OUT VOID   **HobListPtr
    162   )
    163 {
    164   FSP_GLOBAL_DATA   *FspData;
    165   //
    166   // Calling use FspMemoryInit API
    167   // Update HOB and return the control directly
    168   //
    169   if (HobListPtr == NULL) {
    170     HobListPtr = (VOID **)GetFspApiParameter2 ();
    171   }
    172   if (HobListPtr != NULL) {
    173     *HobListPtr = (VOID *) GetHobList ();
    174   }
    175   //
    176   // Convert to FSP EAS defined API return codes
    177   //
    178   switch (Status) {
    179     case EFI_SUCCESS:
    180     case EFI_INVALID_PARAMETER:
    181     case EFI_UNSUPPORTED:
    182     case EFI_DEVICE_ERROR:
    183     case EFI_OUT_OF_RESOURCES:
    184       break;
    185     default:
    186       DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspMemoryInitApi() Invalid Error [Status: 0x%08X]\n", Status));
    187       Status = EFI_DEVICE_ERROR;  // Force to known error.
    188       break;
    189   }
    190   //
    191   // This is the end of the FspMemoryInit API
    192   // Give control back to the boot loader
    193   //
    194   DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspMemoryInitApi() - [Status: 0x%08X] - End\n", Status));
    195   SetFspMeasurePoint (FSP_PERF_ID_API_FSP_MEMORY_INIT_EXIT);
    196   FspData = GetFspGlobalDataPointer ();
    197   PERF_START_EX(&gFspPerformanceDataGuid, "EventRec", NULL, (FspData->PerfData[0] & FSP_PERFORMANCE_DATA_TIMER_MASK), FSP_STATUS_CODE_TEMP_RAM_INIT | FSP_STATUS_CODE_COMMON_CODE| FSP_STATUS_CODE_API_ENTRY);
    198   PERF_END_EX(&gFspPerformanceDataGuid, "EventRec", NULL, (FspData->PerfData[1] & FSP_PERFORMANCE_DATA_TIMER_MASK), FSP_STATUS_CODE_TEMP_RAM_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
    199   PERF_START_EX(&gFspPerformanceDataGuid, "EventRec", NULL, (FspData->PerfData[2] & FSP_PERFORMANCE_DATA_TIMER_MASK), FSP_STATUS_CODE_MEMORY_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
    200   PERF_END_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_MEMORY_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
    201   REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_MEMORY_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
    202   do {
    203     SetFspApiReturnStatus (Status);
    204     Pei2LoaderSwitchStack ();
    205     if (Status != EFI_SUCCESS) {
    206       DEBUG ((DEBUG_ERROR, "!!!ERROR: FspMemoryInitApi() - [Status: 0x%08X] - Error encountered during previous API and cannot proceed further\n", Status));
    207     }
    208   } while (Status != EFI_SUCCESS);
    209 
    210   //
    211   // The TempRamExitApi is called
    212   //
    213   if (GetFspApiCallingIndex () == TempRamExitApiIndex) {
    214     SetPhaseStatusCode (FSP_STATUS_CODE_TEMP_RAM_EXIT);
    215     SetFspMeasurePoint (FSP_PERF_ID_API_TEMP_RAM_EXIT_ENTRY);
    216     PERF_START_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_TEMP_RAM_EXIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
    217     REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_TEMP_RAM_EXIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
    218     DEBUG ((DEBUG_INFO | DEBUG_INIT, "TempRamExitApi() - Begin\n"));
    219   } else {
    220     SetPhaseStatusCode (FSP_STATUS_CODE_SILICON_INIT);
    221     SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_ENTRY);
    222     PERF_START_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
    223     REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
    224     DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspSiliconInitApi() - Begin\n"));
    225   }
    226 }
    227 
    228 /**
    229   This function returns control to BootLoader after TempRamExitApi.
    230 
    231   @param[in] Status return status for the TempRamExitApi.
    232 
    233 **/
    234 VOID
    235 EFIAPI
    236 FspTempRamExitDone2 (
    237   IN EFI_STATUS Status
    238   )
    239 {
    240   //
    241   // Convert to FSP EAS defined API return codes
    242   //
    243   switch (Status) {
    244     case EFI_SUCCESS:
    245     case EFI_INVALID_PARAMETER:
    246     case EFI_UNSUPPORTED:
    247     case EFI_DEVICE_ERROR:
    248       break;
    249     default:
    250       DEBUG ((DEBUG_INFO | DEBUG_INIT, "TempRamExitApi() Invalid Error - [Status: 0x%08X]\n", Status));
    251       Status = EFI_DEVICE_ERROR;  // Force to known error.
    252       break;
    253   }
    254   //
    255   // This is the end of the TempRamExit API
    256   // Give control back to the boot loader
    257   //
    258   DEBUG ((DEBUG_INFO | DEBUG_INIT, "TempRamExitApi() - [Status: 0x%08X] - End\n", Status));
    259   SetFspMeasurePoint (FSP_PERF_ID_API_TEMP_RAM_EXIT_EXIT);
    260   PERF_END_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_TEMP_RAM_EXIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
    261   REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_TEMP_RAM_EXIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
    262   do {
    263     SetFspApiReturnStatus (Status);
    264     Pei2LoaderSwitchStack ();
    265     if (Status != EFI_SUCCESS) {
    266       DEBUG ((DEBUG_ERROR, "!!!ERROR: TempRamExitApi() - [Status: 0x%08X] - Error encountered during previous API and cannot proceed further\n", Status));
    267     }
    268   } while (Status != EFI_SUCCESS);
    269   SetPhaseStatusCode (FSP_STATUS_CODE_SILICON_INIT);
    270   SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_ENTRY);
    271   PERF_START_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
    272   REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
    273   DEBUG ((DEBUG_INFO | DEBUG_INIT, "SiliconInitApi() - Begin\n"));
    274 }
    275 
    276 /**
    277   This function handle NotifyPhase API call from the BootLoader.
    278   It gives control back to the BootLoader after it is handled. If the
    279   Notification code is a ReadyToBoot event, this function will return
    280   and FSP continues the remaining execution until it reaches the DxeIpl.
    281 
    282 **/
    283 VOID
    284 FspWaitForNotify (
    285   VOID
    286   )
    287 {
    288   EFI_STATUS                 Status;
    289   UINT32                     NotificationValue;
    290   UINT32                     NotificationCount;
    291   UINT8                      Count;
    292 
    293   NotificationCount = 0;
    294   while (NotificationCount < sizeof(mFspNotifySequence) / sizeof(UINT32)) {
    295 
    296     Count = (UINT8)((NotificationCount << 1) & 0x07);
    297     SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POST_PCI_ENTRY + Count);
    298 
    299     if (NotificationCount == 0) {
    300       SetPhaseStatusCode (FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION);
    301       PERF_START_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
    302       REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
    303     } else if (NotificationCount == 1) {
    304       SetPhaseStatusCode (FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION);
    305       PERF_START_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
    306       REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
    307     } else if (NotificationCount == 2) {
    308       SetPhaseStatusCode (FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION);
    309       PERF_START_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
    310       REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
    311     }
    312 
    313     NotificationValue = ((NOTIFY_PHASE_PARAMS *)(UINTN)GetFspApiParameter ())->Phase;
    314     DEBUG ((DEBUG_INFO | DEBUG_INIT, "NotifyPhaseApi() - Begin  [Phase: %08X]\n", NotificationValue));
    315     if (mFspNotifySequence[NotificationCount] != NotificationValue) {
    316       //
    317       // Notify code does not follow the predefined order
    318       //
    319       DEBUG ((DEBUG_INFO, "Unsupported FSP Notification Value\n"));
    320       Status = EFI_UNSUPPORTED;
    321     } else {
    322       //
    323       // Process Notification and Give control back to the boot loader framework caller
    324       //
    325       Status = FspNotificationHandler (NotificationValue);
    326       if (!EFI_ERROR(Status)) {
    327         NotificationCount++;
    328       }
    329     }
    330 
    331     DEBUG ((DEBUG_INFO | DEBUG_INIT, "NotifyPhaseApi() - End  [Status: 0x%08X]\n", Status));
    332     SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POST_PCI_EXIT + Count);
    333 
    334     if ((NotificationCount - 1) == 0) {
    335       PERF_END_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
    336       REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
    337     } else if ((NotificationCount - 1) == 1) {
    338       PERF_END_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
    339       REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
    340     } else if ((NotificationCount - 1) == 2) {
    341       PERF_END_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
    342       REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
    343     }
    344     do {
    345       SetFspApiReturnStatus(Status);
    346       Pei2LoaderSwitchStack();
    347       if (Status != EFI_SUCCESS) {
    348         DEBUG ((DEBUG_ERROR, "!!!ERROR: NotifyPhaseApi() [Phase: %08X] - Failed - [Status: 0x%08X]\n", NotificationValue, Status));
    349       }
    350     } while (Status != EFI_SUCCESS);
    351   }
    352 
    353   //
    354   // Control goes back to the PEI Core and it dispatches further PEIMs.
    355   // DXEIPL is the final one to transfer control back to the boot loader.
    356   //
    357 }
    358 
    359 /**
    360   This function transfer control back to BootLoader after FspSiliconInit.
    361 
    362 **/
    363 VOID
    364 EFIAPI
    365 FspSiliconInitDone (
    366   VOID
    367   )
    368 {
    369   FspSiliconInitDone2 (EFI_SUCCESS);
    370 }
    371 
    372 /**
    373   This function returns control to BootLoader after MemoryInitApi.
    374 
    375   @param[in,out] HobListPtr The address of HobList pointer.
    376 **/
    377 VOID
    378 EFIAPI
    379 FspMemoryInitDone (
    380   IN OUT VOID   **HobListPtr
    381   )
    382 {
    383   FspMemoryInitDone2 (EFI_SUCCESS, HobListPtr);
    384 }
    385 
    386 /**
    387   This function returns control to BootLoader after TempRamExitApi.
    388 
    389 **/
    390 VOID
    391 EFIAPI
    392 FspTempRamExitDone (
    393   VOID
    394   )
    395 {
    396   FspTempRamExitDone2 (EFI_SUCCESS);
    397 }
    398