Home | History | Annotate | Download | only in BaseFspPlatformLib
      1 /** @file
      2 
      3   Copyright (c) 2014 - 2015, 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 <FspApi.h>
     26 #include <Protocol/PciEnumerationComplete.h>
     27 
     28 EFI_PEI_PPI_DESCRIPTOR      mPeiPostPciEnumerationPpi = {
     29   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
     30   &gEfiPciEnumerationCompleteProtocolGuid,
     31   NULL
     32 };
     33 
     34 EFI_PEI_PPI_DESCRIPTOR      mPeiReadyToBootPpi = {
     35   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
     36   &gEfiEventReadyToBootGuid,
     37   NULL
     38 };
     39 
     40 
     41 UINT32  mFspNotifySequence[] = {
     42   EnumInitPhaseAfterPciEnumeration,
     43   EnumInitPhaseReadyToBoot
     44 };
     45 
     46 /**
     47   Install FSP notification.
     48 
     49   @param[in] NotificationCode  FSP notification code
     50 
     51   @retval EFI_SUCCESS            Notify FSP successfully
     52   @retval EFI_INVALID_PARAMETER  NotificationCode is invalid
     53 
     54 **/
     55 EFI_STATUS
     56 EFIAPI
     57 FspNotificationHandler (
     58   IN  UINT32     NotificationCode
     59   )
     60 {
     61   EFI_STATUS                Status;
     62 
     63   Status   = EFI_SUCCESS;
     64 
     65   switch (NotificationCode) {
     66   case EnumInitPhaseAfterPciEnumeration:
     67     //
     68     // Do POST PCI initialization if needed
     69     //
     70     DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP Post PCI Enumeration ...\n"));
     71     PeiServicesInstallPpi (&mPeiPostPciEnumerationPpi);
     72     break;
     73 
     74   case EnumInitPhaseReadyToBoot:
     75     //
     76     // Ready To Boot
     77     //
     78     DEBUG ((DEBUG_INFO| DEBUG_INIT, "FSP Ready To Boot ...\n"));
     79     PeiServicesInstallPpi (&mPeiReadyToBootPpi);
     80     break;
     81 
     82   default:
     83     Status = EFI_INVALID_PARAMETER;
     84     break;
     85   }
     86 
     87   return Status;
     88 }
     89 
     90 /**
     91   This function transfer control to the ContinuationFunc passed in by the
     92   BootLoader.
     93 
     94 **/
     95 VOID
     96 EFIAPI
     97 FspInitDone (
     98   VOID
     99   )
    100 {
    101   FSP_INIT_PARAMS        *FspInitParams;
    102 
    103   if (GetFspApiCallingMode() == 0) {
    104     //
    105     // FspInit API is used, so jump into the ContinuationFunc
    106     //
    107     FspInitParams   = (FSP_INIT_PARAMS *)GetFspApiParameter ();
    108 
    109     //
    110     // Modify the parameters for ContinuationFunc
    111     //
    112     SetFspContinuationFuncParameter(EFI_SUCCESS, 0);
    113     SetFspContinuationFuncParameter((UINT32)GetHobList(), 1);
    114 
    115     //
    116     // Modify the return address to ContinuationFunc
    117     //
    118     SetFspApiReturnAddress((UINT32)FspInitParams->ContinuationFunc);
    119 
    120     //
    121     // Give control back to the boot loader framework caller after FspInit is done
    122     // It is done throught the continuation function
    123     //
    124     SetFspMeasurePoint (FSP_PERF_ID_API_FSPINIT_EXIT);
    125   } else {
    126     //
    127     // FspMemoryInit API is used, so return directly
    128     //
    129 
    130     //
    131     // This is the end of the FspSiliconInit API
    132     // Give control back to the boot loader
    133     //
    134     DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspSiliconInitApi() - End\n"));
    135     SetFspApiReturnStatus (EFI_SUCCESS);
    136   }
    137 
    138   Pei2LoaderSwitchStack();
    139 }
    140 
    141 /**
    142   This function handle NotifyPhase API call from the BootLoader.
    143   It gives control back to the BootLoader after it is handled. If the
    144   Notification code is a ReadyToBoot event, this function will return
    145   and FSP continues the remaining execution until it reaches the DxeIpl.
    146 
    147 **/
    148 VOID
    149 FspWaitForNotify (
    150   VOID
    151   )
    152 {
    153   EFI_STATUS                 Status;
    154   UINT32                     NotificationValue;
    155   UINT32                     NotificationCount;
    156   UINT8                      Count;
    157 
    158   NotificationCount = 0;
    159   while (NotificationCount < sizeof(mFspNotifySequence) / sizeof(UINT32)) {
    160 
    161     Count = (UINT8)((NotificationCount << 1) & 0x07);
    162     SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POSTPCI_ENTRY + Count);
    163 
    164     NotificationValue = ((NOTIFY_PHASE_PARAMS *)(UINTN)GetFspApiParameter ())->Phase;
    165     DEBUG ((DEBUG_INFO, "FSP Got Notification. Notification Value : 0x%08X\n", NotificationValue));
    166 
    167     if (mFspNotifySequence[NotificationCount] != NotificationValue) {
    168       //
    169       // Notify code does not follow the predefined order
    170       //
    171       DEBUG ((DEBUG_INFO, "Unsupported FSP Notification Value\n"));
    172       SetFspApiReturnStatus(EFI_UNSUPPORTED);
    173     } else {
    174       //
    175       // Process Notification and Give control back to the boot loader framework caller
    176       //
    177       Status = FspNotificationHandler (NotificationValue);
    178       DEBUG ((DEBUG_INFO, "FSP Notification Handler Returns : 0x%08X\n", Status));
    179       SetFspApiReturnStatus(Status);
    180       if (!EFI_ERROR(Status)) {
    181         NotificationCount++;
    182         SetFspApiReturnStatus(EFI_SUCCESS);
    183         if (NotificationValue == EnumInitPhaseReadyToBoot) {
    184           break;
    185         }
    186       }
    187     }
    188     SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POSTPCI_EXIT + Count);
    189     Pei2LoaderSwitchStack();
    190   }
    191 
    192   //
    193   // Control goes back to the PEI Core and it dispatches further PEIMs.
    194   // DXEIPL is the final one to transfer control back to the boot loader.
    195   //
    196 }
    197 
    198