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
28EFI_PEI_PPI_DESCRIPTOR      mPeiPostPciEnumerationPpi = {
29  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
30  &gEfiPciEnumerationCompleteProtocolGuid,
31  NULL
32};
33
34EFI_PEI_PPI_DESCRIPTOR      mPeiReadyToBootPpi = {
35  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
36  &gEfiEventReadyToBootGuid,
37  NULL
38};
39
40
41UINT32  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**/
55EFI_STATUS
56EFIAPI
57FspNotificationHandler (
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**/
95VOID
96EFIAPI
97FspInitDone (
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**/
148VOID
149FspWaitForNotify (
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