Add IntelFsp2Pkg and IntelFsp2WrapperPkg.
[mirror_edk2.git] / IntelFsp2Pkg / Library / BaseFspPlatformLib / FspPlatformNotify.c
1 /** @file\r
2 \r
3   Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>\r
4   This program and the accompanying materials\r
5   are licensed and made available under the terms and conditions of the BSD License\r
6   which accompanies this distribution.  The full text of the license may be found at\r
7   http://opensource.org/licenses/bsd-license.php.\r
8 \r
9   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11 \r
12 **/\r
13 \r
14 #include <PiPei.h>\r
15 #include <Library/PeiServicesLib.h>\r
16 #include <Library/PeiServicesTablePointerLib.h>\r
17 #include <Library/BaseLib.h>\r
18 #include <Library/BaseMemoryLib.h>\r
19 #include <Library/PcdLib.h>\r
20 #include <Library/DebugLib.h>\r
21 #include <Library/HobLib.h>\r
22 #include <Library/FspSwitchStackLib.h>\r
23 #include <Library/FspCommonLib.h>\r
24 #include <Guid/EventGroup.h>\r
25 #include <FspEas.h>\r
26 #include <FspStatusCode.h>\r
27 #include <Protocol/PciEnumerationComplete.h>\r
28 #include <Library/ReportStatusCodeLib.h>\r
29 #include <Library/PerformanceLib.h>\r
30 extern EFI_GUID gFspPerformanceDataGuid;\r
31 \r
32 EFI_PEI_PPI_DESCRIPTOR      mPeiPostPciEnumerationPpi = {\r
33   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
34   &gEfiPciEnumerationCompleteProtocolGuid,\r
35   NULL\r
36 };\r
37 \r
38 EFI_PEI_PPI_DESCRIPTOR      mPeiReadyToBootPpi = {\r
39   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
40   &gEfiEventReadyToBootGuid,\r
41   NULL\r
42 };\r
43 \r
44 EFI_PEI_PPI_DESCRIPTOR      mPeiEndOfFirmwarePpi = {\r
45   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
46   &gFspEventEndOfFirmwareGuid,\r
47   NULL\r
48 };\r
49 \r
50 UINT32  mFspNotifySequence[] = {\r
51   EnumInitPhaseAfterPciEnumeration,\r
52   EnumInitPhaseReadyToBoot,\r
53   EnumInitPhaseEndOfFirmware\r
54 };\r
55 \r
56 /**\r
57   Install FSP notification.\r
58 \r
59   @param[in] NotificationCode  FSP notification code\r
60 \r
61   @retval EFI_SUCCESS            Notify FSP successfully\r
62   @retval EFI_INVALID_PARAMETER  NotificationCode is invalid\r
63 \r
64 **/\r
65 EFI_STATUS\r
66 EFIAPI\r
67 FspNotificationHandler (\r
68   IN  UINT32     NotificationCode\r
69   )\r
70 {\r
71   EFI_STATUS                Status;\r
72 \r
73   Status   = EFI_SUCCESS;\r
74 \r
75   switch (NotificationCode) {\r
76   case EnumInitPhaseAfterPciEnumeration:\r
77     //\r
78     // Do POST PCI initialization if needed\r
79     //\r
80     DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP Post PCI Enumeration ...\n"));\r
81     PeiServicesInstallPpi (&mPeiPostPciEnumerationPpi);\r
82     break;\r
83 \r
84   case EnumInitPhaseReadyToBoot:\r
85     //\r
86     // Ready To Boot\r
87     //\r
88     DEBUG ((DEBUG_INFO| DEBUG_INIT, "FSP Ready To Boot ...\n"));\r
89     PeiServicesInstallPpi (&mPeiReadyToBootPpi);\r
90     break;\r
91 \r
92   case EnumInitPhaseEndOfFirmware:\r
93     //\r
94     // End of Firmware\r
95     //\r
96     DEBUG ((DEBUG_INFO| DEBUG_INIT, "FSP End of Firmware ...\n"));\r
97     PeiServicesInstallPpi (&mPeiEndOfFirmwarePpi);\r
98     break;\r
99 \r
100   default:\r
101     Status = EFI_INVALID_PARAMETER;\r
102     break;\r
103   }\r
104 \r
105   return Status;\r
106 }\r
107 \r
108 /**\r
109   This function transfer control back to BootLoader after FspSiliconInit.\r
110 \r
111 **/\r
112 VOID\r
113 EFIAPI\r
114 FspSiliconInitDone (\r
115   VOID\r
116   )\r
117 {\r
118   //\r
119   // This is the end of the FspSiliconInit API\r
120   // Give control back to the boot loader\r
121   //\r
122   SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_EXIT);\r
123   DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspSiliconInitApi() - End\n"));\r
124 \r
125   PERF_END_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, 0x907F);\r
126 \r
127   REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);\r
128   SetFspApiReturnStatus (EFI_SUCCESS);\r
129 \r
130   Pei2LoaderSwitchStack();\r
131 \r
132   PERF_START_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, 0x6000);\r
133 }\r
134 \r
135 /**\r
136   This function returns control to BootLoader after MemoryInitApi.\r
137 \r
138   @param[in,out] HobListPtr The address of HobList pointer.\r
139 **/\r
140 VOID\r
141 EFIAPI\r
142 FspMemoryInitDone (\r
143   IN OUT VOID   **HobListPtr\r
144   )\r
145 {\r
146   //\r
147   // Calling use FspMemoryInit API\r
148   // Update HOB and return the control directly\r
149   //\r
150   if (HobListPtr != NULL) {\r
151     *HobListPtr = (VOID *) GetHobList ();\r
152   }\r
153 \r
154   //\r
155   // This is the end of the FspMemoryInit API\r
156   // Give control back to the boot loader\r
157   //\r
158   SetFspMeasurePoint (FSP_PERF_ID_API_FSP_MEMORY_INIT_EXIT);\r
159   DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspMemoryInitApi() - End\n"));\r
160   REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_MEMORY_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);\r
161   SetFspApiReturnStatus (EFI_SUCCESS);\r
162   Pei2LoaderSwitchStack ();\r
163 \r
164   //\r
165   // The TempRamExitApi is called\r
166   //\r
167   if (GetFspApiCallingIndex () == TempRamExitApiIndex) {\r
168     SetPhaseStatusCode (FSP_STATUS_CODE_TEMP_RAM_EXIT);\r
169     REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_TEMP_RAM_EXIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);\r
170     SetFspMeasurePoint (FSP_PERF_ID_API_TEMP_RAM_EXIT_ENTRY);\r
171     DEBUG ((DEBUG_INFO | DEBUG_INIT, "TempRamExitApi() - Begin\n"));\r
172   } else {\r
173     SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_ENTRY);\r
174     DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspSiliconInitApi() - Begin\n"));\r
175     SetPhaseStatusCode (FSP_STATUS_CODE_SILICON_INIT);\r
176     REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);\r
177   }\r
178 }\r
179 \r
180 /**\r
181   This function returns control to BootLoader after TempRamExitApi.\r
182 \r
183 **/\r
184 VOID\r
185 EFIAPI\r
186 FspTempRamExitDone (\r
187   VOID\r
188   )\r
189 {\r
190 \r
191   //\r
192   // This is the end of the TempRamExit API\r
193   // Give control back to the boot loader\r
194   //\r
195   SetFspMeasurePoint (FSP_PERF_ID_API_TEMP_RAM_EXIT_EXIT);\r
196   DEBUG ((DEBUG_INFO | DEBUG_INIT, "TempRamExitApi() - End\n"));\r
197   REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_TEMP_RAM_EXIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);\r
198   SetFspApiReturnStatus (EFI_SUCCESS);\r
199   Pei2LoaderSwitchStack ();\r
200 \r
201   SetPhaseStatusCode (FSP_STATUS_CODE_SILICON_INIT);\r
202   SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_ENTRY);\r
203   DEBUG ((DEBUG_INFO | DEBUG_INIT, "SiliconInitApi() - Begin\n"));\r
204   REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);\r
205 }\r
206 \r
207 /**\r
208   This function handle NotifyPhase API call from the BootLoader.\r
209   It gives control back to the BootLoader after it is handled. If the\r
210   Notification code is a ReadyToBoot event, this function will return\r
211   and FSP continues the remaining execution until it reaches the DxeIpl.\r
212 \r
213 **/\r
214 VOID\r
215 FspWaitForNotify (\r
216   VOID\r
217   )\r
218 {\r
219   EFI_STATUS                 Status;\r
220   UINT32                     NotificationValue;\r
221   UINT32                     NotificationCount;\r
222   UINT8                      Count;\r
223 \r
224   NotificationCount = 0;\r
225   while (NotificationCount < sizeof(mFspNotifySequence) / sizeof(UINT32)) {\r
226 \r
227     Count = (UINT8)((NotificationCount << 1) & 0x07);\r
228     SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POST_PCI_ENTRY + Count);\r
229 \r
230     if (NotificationCount == 0) {\r
231       SetPhaseStatusCode (FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION);\r
232       REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);\r
233     } else if (NotificationCount == 1) {\r
234       SetPhaseStatusCode (FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION);\r
235       REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);\r
236     } else if (NotificationCount == 2) {\r
237       SetPhaseStatusCode (FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION);\r
238       REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);\r
239     }\r
240 \r
241     NotificationValue = ((NOTIFY_PHASE_PARAMS *)(UINTN)GetFspApiParameter ())->Phase;\r
242     DEBUG ((DEBUG_INFO | DEBUG_INIT, "NotifyPhaseApi() - Begin  [Phase: %08X]\n", NotificationValue));\r
243     if (mFspNotifySequence[NotificationCount] != NotificationValue) {\r
244       //\r
245       // Notify code does not follow the predefined order\r
246       //\r
247       DEBUG ((DEBUG_INFO, "Unsupported FSP Notification Value\n"));\r
248       Status = EFI_UNSUPPORTED;\r
249     } else {\r
250       //\r
251       // Process Notification and Give control back to the boot loader framework caller\r
252       //\r
253       Status = FspNotificationHandler (NotificationValue);\r
254       if (!EFI_ERROR(Status)) {\r
255         NotificationCount++;\r
256       }\r
257     }\r
258 \r
259     SetFspApiReturnStatus(Status);\r
260     DEBUG ((DEBUG_INFO | DEBUG_INIT, "NotifyPhaseApi() - End  [Status: 0x%08X]\n", Status));\r
261 \r
262     SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POST_PCI_EXIT + Count);\r
263 \r
264     if ((NotificationCount - 1) == 0) {\r
265       REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);\r
266     } else if ((NotificationCount - 1) == 1) {\r
267       REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);\r
268     } else if ((NotificationCount - 1) == 2) {\r
269       REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);\r
270     }\r
271     Pei2LoaderSwitchStack();\r
272   }\r
273 \r
274   //\r
275   // Control goes back to the PEI Core and it dispatches further PEIMs.\r
276   // DXEIPL is the final one to transfer control back to the boot loader.\r
277   //\r
278 }\r
279 \r