PeiFspWrapperMultiPhaseProcessLib.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. /** @file
  2. Support FSP Wrapper MultiPhase process.
  3. Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include <Library/BaseLib.h>
  7. #include <Library/DebugLib.h>
  8. #include <Library/PcdLib.h>
  9. #include <Library/FspWrapperApiLib.h>
  10. #include <Library/FspWrapperPlatformLib.h>
  11. #include <FspEas.h>
  12. #include <FspGlobalData.h>
  13. #include <Ppi/ReadOnlyVariable2.h>
  14. #include <Ppi/Variable.h>
  15. #include <Library/PeiServicesLib.h>
  16. #include <Library/FspWrapperPlatformMultiPhaseLib.h>
  17. /**
  18. Execute 32-bit FSP API entry code.
  19. @param[in] Function The 32bit code entry to be executed.
  20. @param[in] Param1 The first parameter to pass to 32bit code.
  21. @param[in] Param2 The second parameter to pass to 32bit code.
  22. @return EFI_STATUS.
  23. **/
  24. EFI_STATUS
  25. Execute32BitCode (
  26. IN UINT64 Function,
  27. IN UINT64 Param1,
  28. IN UINT64 Param2
  29. );
  30. /**
  31. Execute 64-bit FSP API entry code.
  32. @param[in] Function The 64bit code entry to be executed.
  33. @param[in] Param1 The first parameter to pass to 64bit code.
  34. @param[in] Param2 The second parameter to pass to 64bit code.
  35. @return EFI_STATUS.
  36. **/
  37. EFI_STATUS
  38. Execute64BitCode (
  39. IN UINT64 Function,
  40. IN UINT64 Param1,
  41. IN UINT64 Param2
  42. );
  43. /**
  44. Call FspsMultiPhase API.
  45. @param[in] FspsMultiPhaseParams - Parameters for MultiPhase API.
  46. @param[in] FspHobListPtr - Pointer to FSP HobList (valid after FSP-M completed)
  47. @param[in] ComponentIndex - FSP Component which executing MultiPhase initialization.
  48. @return EFI_UNSUPPORTED - the requested FspsMultiPhase API is not supported.
  49. @return EFI_DEVICE_ERROR - the FSP header was not found.
  50. @return EFI status returned by FspsMultiPhase API.
  51. **/
  52. EFI_STATUS
  53. EFIAPI
  54. CallFspMultiPhaseEntry (
  55. IN VOID *FspMultiPhaseParams,
  56. IN OUT VOID **FspHobListPtr,
  57. IN UINT8 ComponentIndex
  58. )
  59. {
  60. FSP_INFO_HEADER *FspHeader;
  61. //
  62. // FSP_MULTI_PHASE_INIT and FSP_MULTI_PHASE_SI_INIT API functions having same prototype.
  63. //
  64. UINTN FspMultiPhaseApiEntry;
  65. UINTN FspMultiPhaseApiOffset;
  66. EFI_STATUS Status;
  67. BOOLEAN InterruptState;
  68. BOOLEAN IsVariableServiceRequest;
  69. FSP_MULTI_PHASE_PARAMS *FspMultiPhaseParamsPtr;
  70. FspMultiPhaseParamsPtr = (FSP_MULTI_PHASE_PARAMS *)FspMultiPhaseParams;
  71. IsVariableServiceRequest = FALSE;
  72. if ((FspMultiPhaseParamsPtr->MultiPhaseAction == EnumMultiPhaseGetVariableRequestInfo) ||
  73. (FspMultiPhaseParamsPtr->MultiPhaseAction == EnumMultiPhaseCompleteVariableRequest))
  74. {
  75. IsVariableServiceRequest = TRUE;
  76. }
  77. if (ComponentIndex == FspMultiPhaseMemInitApiIndex) {
  78. FspHeader = (FSP_INFO_HEADER *)FspFindFspHeader (PcdGet32 (PcdFspmBaseAddress));
  79. if (FspHeader == NULL) {
  80. return EFI_DEVICE_ERROR;
  81. } else if (FspHeader->SpecVersion < 0x24) {
  82. return EFI_UNSUPPORTED;
  83. }
  84. FspMultiPhaseApiOffset = FspHeader->FspMultiPhaseMemInitEntryOffset;
  85. } else if (ComponentIndex == FspMultiPhaseSiInitApiIndex) {
  86. FspHeader = (FSP_INFO_HEADER *)FspFindFspHeader (PcdGet32 (PcdFspsBaseAddress));
  87. if (FspHeader == NULL) {
  88. return EFI_DEVICE_ERROR;
  89. } else if (FspHeader->SpecVersion < 0x22) {
  90. return EFI_UNSUPPORTED;
  91. } else if ((FspHeader->SpecVersion < 0x24) && (IsVariableServiceRequest == TRUE)) {
  92. return EFI_UNSUPPORTED;
  93. }
  94. FspMultiPhaseApiOffset = FspHeader->FspMultiPhaseSiInitEntryOffset;
  95. }
  96. if (FspMultiPhaseApiOffset == 0) {
  97. return EFI_UNSUPPORTED;
  98. }
  99. FspMultiPhaseApiEntry = FspHeader->ImageBase + FspMultiPhaseApiOffset;
  100. InterruptState = SaveAndDisableInterrupts ();
  101. if ((FspHeader->ImageAttribute & BIT2) == 0) {
  102. // BIT2: IMAGE_ATTRIBUTE_64BIT_MODE_SUPPORT
  103. Status = Execute32BitCode ((UINTN)FspMultiPhaseApiEntry, (UINTN)FspMultiPhaseParams, (UINTN)NULL);
  104. } else {
  105. Status = Execute64BitCode ((UINTN)FspMultiPhaseApiEntry, (UINTN)FspMultiPhaseParams, (UINTN)NULL);
  106. }
  107. SetInterruptState (InterruptState);
  108. DEBUG ((DEBUG_ERROR, "CallFspMultiPhaseEntry return Status %r \n", Status));
  109. return Status;
  110. }
  111. /**
  112. FSP Wrapper Variable Request Handler
  113. @param[in, out] FspHobListPtr - Pointer to FSP HobList (valid after FSP-M completed)
  114. @param[in] ComponentIndex - FSP Component which executing MultiPhase initialization.
  115. @retval EFI_UNSUPPORTED FSP Wrapper cannot support the specific variable request,
  116. or FSP does not support VariableService
  117. @retval EFI_STATUS Return FSP returned status
  118. **/
  119. EFI_STATUS
  120. EFIAPI
  121. FspWrapperVariableRequestHandler (
  122. IN OUT VOID **FspHobListPtr,
  123. IN UINT8 ComponentIndex
  124. )
  125. {
  126. EFI_STATUS Status;
  127. FSP_MULTI_PHASE_PARAMS FspMultiPhaseParams;
  128. FSP_MULTI_PHASE_VARIABLE_REQUEST_INFO_PARAMS *FspVariableRequestParams;
  129. EFI_PEI_READ_ONLY_VARIABLE2_PPI *ReadOnlyVariablePpi;
  130. EDKII_PEI_VARIABLE_PPI *VariablePpi;
  131. BOOLEAN WriteVariableSupport;
  132. FSP_MULTI_PHASE_COMPLETE_VARIABLE_REQUEST_PARAMS CompleteVariableRequestParams;
  133. WriteVariableSupport = TRUE;
  134. Status = PeiServicesLocatePpi (
  135. &gEdkiiPeiVariablePpiGuid,
  136. 0,
  137. NULL,
  138. (VOID **)&VariablePpi
  139. );
  140. if (EFI_ERROR (Status)) {
  141. WriteVariableSupport = FALSE;
  142. Status = PeiServicesLocatePpi (
  143. &gEfiPeiReadOnlyVariable2PpiGuid,
  144. 0,
  145. NULL,
  146. (VOID **)&ReadOnlyVariablePpi
  147. );
  148. ASSERT_EFI_ERROR (Status);
  149. if (EFI_ERROR (Status)) {
  150. return EFI_UNSUPPORTED;
  151. }
  152. }
  153. Status = FSP_STATUS_VARIABLE_REQUEST;
  154. while (Status == FSP_STATUS_VARIABLE_REQUEST) {
  155. //
  156. // Get the variable request information from FSP.
  157. //
  158. FspMultiPhaseParams.MultiPhaseAction = EnumMultiPhaseGetVariableRequestInfo;
  159. FspMultiPhaseParams.PhaseIndex = 0;
  160. Status = CallFspMultiPhaseEntry (&FspMultiPhaseParams, FspHobListPtr, ComponentIndex);
  161. ASSERT_EFI_ERROR (Status);
  162. //
  163. // FSP should output this pointer for variable request information.
  164. //
  165. FspVariableRequestParams = (FSP_MULTI_PHASE_VARIABLE_REQUEST_INFO_PARAMS *)FspMultiPhaseParams.MultiPhaseParamPtr;
  166. switch (FspVariableRequestParams->VariableRequest) {
  167. case EnumFspVariableRequestGetVariable:
  168. if (WriteVariableSupport) {
  169. Status = VariablePpi->GetVariable (
  170. VariablePpi,
  171. FspVariableRequestParams->VariableName,
  172. FspVariableRequestParams->VariableGuid,
  173. FspVariableRequestParams->Attributes,
  174. (UINTN *)FspVariableRequestParams->DataSize,
  175. FspVariableRequestParams->Data
  176. );
  177. } else {
  178. Status = ReadOnlyVariablePpi->GetVariable (
  179. ReadOnlyVariablePpi,
  180. FspVariableRequestParams->VariableName,
  181. FspVariableRequestParams->VariableGuid,
  182. FspVariableRequestParams->Attributes,
  183. (UINTN *)FspVariableRequestParams->DataSize,
  184. FspVariableRequestParams->Data
  185. );
  186. }
  187. CompleteVariableRequestParams.VariableRequestStatus = Status;
  188. FspMultiPhaseParams.MultiPhaseParamPtr = (VOID *)&CompleteVariableRequestParams;
  189. FspMultiPhaseParams.MultiPhaseAction = EnumMultiPhaseCompleteVariableRequest;
  190. Status = CallFspMultiPhaseEntry (&FspMultiPhaseParams, FspHobListPtr, ComponentIndex);
  191. break;
  192. case EnumFspVariableRequestSetVariable:
  193. if (WriteVariableSupport) {
  194. Status = VariablePpi->SetVariable (
  195. VariablePpi,
  196. FspVariableRequestParams->VariableName,
  197. FspVariableRequestParams->VariableGuid,
  198. *FspVariableRequestParams->Attributes,
  199. (UINTN)*FspVariableRequestParams->DataSize,
  200. FspVariableRequestParams->Data
  201. );
  202. } else {
  203. Status = EFI_UNSUPPORTED;
  204. }
  205. CompleteVariableRequestParams.VariableRequestStatus = Status;
  206. FspMultiPhaseParams.MultiPhaseParamPtr = (VOID *)&CompleteVariableRequestParams;
  207. FspMultiPhaseParams.MultiPhaseAction = EnumMultiPhaseCompleteVariableRequest;
  208. Status = CallFspMultiPhaseEntry (&FspMultiPhaseParams, FspHobListPtr, ComponentIndex);
  209. break;
  210. case EnumFspVariableRequestGetNextVariableName:
  211. if (WriteVariableSupport) {
  212. Status = VariablePpi->GetNextVariableName (
  213. VariablePpi,
  214. (UINTN *)FspVariableRequestParams->VariableNameSize,
  215. FspVariableRequestParams->VariableName,
  216. FspVariableRequestParams->VariableGuid
  217. );
  218. } else {
  219. Status = ReadOnlyVariablePpi->NextVariableName (
  220. ReadOnlyVariablePpi,
  221. (UINTN *)FspVariableRequestParams->VariableNameSize,
  222. FspVariableRequestParams->VariableName,
  223. FspVariableRequestParams->VariableGuid
  224. );
  225. }
  226. CompleteVariableRequestParams.VariableRequestStatus = Status;
  227. FspMultiPhaseParams.MultiPhaseParamPtr = (VOID *)&CompleteVariableRequestParams;
  228. FspMultiPhaseParams.MultiPhaseAction = EnumMultiPhaseCompleteVariableRequest;
  229. Status = CallFspMultiPhaseEntry (&FspMultiPhaseParams, FspHobListPtr, ComponentIndex);
  230. break;
  231. case EnumFspVariableRequestQueryVariableInfo:
  232. if (WriteVariableSupport) {
  233. Status = VariablePpi->QueryVariableInfo (
  234. VariablePpi,
  235. *FspVariableRequestParams->Attributes,
  236. FspVariableRequestParams->MaximumVariableStorageSize,
  237. FspVariableRequestParams->RemainingVariableStorageSize,
  238. FspVariableRequestParams->MaximumVariableSize
  239. );
  240. } else {
  241. Status = EFI_UNSUPPORTED;
  242. }
  243. CompleteVariableRequestParams.VariableRequestStatus = Status;
  244. FspMultiPhaseParams.MultiPhaseParamPtr = (VOID *)&CompleteVariableRequestParams;
  245. FspMultiPhaseParams.MultiPhaseAction = EnumMultiPhaseCompleteVariableRequest;
  246. Status = CallFspMultiPhaseEntry (&FspMultiPhaseParams, FspHobListPtr, ComponentIndex);
  247. break;
  248. default:
  249. DEBUG ((DEBUG_ERROR, "Unknown VariableRequest type!\n"));
  250. Status = EFI_UNSUPPORTED;
  251. break;
  252. }
  253. }
  254. //
  255. // Reset the system if FSP API returned FSP_STATUS_RESET_REQUIRED status
  256. //
  257. if ((Status >= FSP_STATUS_RESET_REQUIRED_COLD) && (Status <= FSP_STATUS_RESET_REQUIRED_8)) {
  258. DEBUG ((DEBUG_INFO, "FspMultiPhaseApi-0x%x requested reset %r\n", ComponentIndex, Status));
  259. CallFspWrapperResetSystem ((UINTN)Status);
  260. }
  261. return Status;
  262. }
  263. /**
  264. FSP Wrapper MultiPhase Handler
  265. @param[in, out] FspHobListPtr - Pointer to FSP HobList (valid after FSP-M completed)
  266. @param[in] ComponentIndex - FSP Component which executing MultiPhase initialization.
  267. @retval EFI_UNSUPPORTED Specific MultiPhase action was not supported.
  268. @retval EFI_SUCCESS MultiPhase action were completed successfully.
  269. **/
  270. EFI_STATUS
  271. EFIAPI
  272. FspWrapperMultiPhaseHandler (
  273. IN OUT VOID **FspHobListPtr,
  274. IN UINT8 ComponentIndex
  275. )
  276. {
  277. EFI_STATUS Status;
  278. FSP_MULTI_PHASE_PARAMS FspMultiPhaseParams;
  279. FSP_MULTI_PHASE_GET_NUMBER_OF_PHASES_PARAMS FspMultiPhaseGetNumber;
  280. UINT32 Index;
  281. UINT32 NumOfPhases;
  282. //
  283. // Query FSP for the number of phases supported.
  284. //
  285. FspMultiPhaseParams.MultiPhaseAction = EnumMultiPhaseGetNumberOfPhases;
  286. FspMultiPhaseParams.PhaseIndex = 0;
  287. FspMultiPhaseParams.MultiPhaseParamPtr = (VOID *)&FspMultiPhaseGetNumber;
  288. Status = CallFspMultiPhaseEntry (&FspMultiPhaseParams, FspHobListPtr, ComponentIndex);
  289. if (Status == EFI_UNSUPPORTED) {
  290. //
  291. // MultiPhase API was not supported
  292. //
  293. return Status;
  294. } else {
  295. ASSERT_EFI_ERROR (Status);
  296. }
  297. NumOfPhases = FspMultiPhaseGetNumber.NumberOfPhases;
  298. for (Index = 1; Index <= NumOfPhases; Index++) {
  299. DEBUG ((DEBUG_ERROR, "MultiPhase Index/NumOfPhases = %d of %d\n", Index, NumOfPhases));
  300. //
  301. // Platform actions can be added in below function for each component and phase before returning control back to FSP.
  302. //
  303. FspWrapperPlatformMultiPhaseHandler (FspHobListPtr, ComponentIndex, Index);
  304. FspMultiPhaseParams.MultiPhaseAction = EnumMultiPhaseExecutePhase;
  305. FspMultiPhaseParams.PhaseIndex = Index;
  306. FspMultiPhaseParams.MultiPhaseParamPtr = NULL;
  307. Status = CallFspMultiPhaseEntry (&FspMultiPhaseParams, FspHobListPtr, ComponentIndex);
  308. if (Status == FSP_STATUS_VARIABLE_REQUEST) {
  309. //
  310. // call to Variable request handler
  311. //
  312. FspWrapperVariableRequestHandler (FspHobListPtr, ComponentIndex);
  313. }
  314. //
  315. // Reset the system if FSP API returned FSP_STATUS_RESET_REQUIRED status
  316. //
  317. if ((Status >= FSP_STATUS_RESET_REQUIRED_COLD) && (Status <= FSP_STATUS_RESET_REQUIRED_8)) {
  318. DEBUG ((DEBUG_INFO, "FspMultiPhaseApi-0x%x requested reset %r\n", ComponentIndex, Status));
  319. CallFspWrapperResetSystem ((UINTN)Status);
  320. }
  321. ASSERT_EFI_ERROR (Status);
  322. }
  323. return EFI_SUCCESS;
  324. }