SecFsp.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. /** @file
  2. Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
  3. SPDX-License-Identifier: BSD-2-Clause-Patent
  4. **/
  5. #include "SecFsp.h"
  6. /**
  7. Calculate the FSP IDT gate descriptor.
  8. @param[in] IdtEntryTemplate IDT gate descriptor template.
  9. @return FSP specific IDT gate descriptor.
  10. **/
  11. UINT64
  12. FspGetExceptionHandler(
  13. IN UINT64 IdtEntryTemplate
  14. )
  15. {
  16. UINT32 Entry;
  17. UINT64 ExceptionHandler;
  18. IA32_IDT_GATE_DESCRIPTOR *IdtGateDescriptor;
  19. FSP_INFO_HEADER *FspInfoHeader;
  20. FspInfoHeader = (FSP_INFO_HEADER *)AsmGetFspInfoHeader();
  21. ExceptionHandler = IdtEntryTemplate;
  22. IdtGateDescriptor = (IA32_IDT_GATE_DESCRIPTOR *)&ExceptionHandler;
  23. Entry = (IdtGateDescriptor->Bits.OffsetHigh << 16) | IdtGateDescriptor->Bits.OffsetLow;
  24. Entry = FspInfoHeader->ImageBase + FspInfoHeader->ImageSize - (~Entry + 1);
  25. IdtGateDescriptor->Bits.OffsetHigh = (UINT16)(Entry >> 16);
  26. IdtGateDescriptor->Bits.OffsetLow = (UINT16)Entry;
  27. return ExceptionHandler;
  28. }
  29. /**
  30. This function gets the FSP UPD region offset in flash.
  31. @return the offset of the UPD region.
  32. **/
  33. UINT32
  34. EFIAPI
  35. GetFspUpdRegionOffset (
  36. VOID
  37. )
  38. {
  39. FSP_GLOBAL_DATA *FspData;
  40. UINT32 *Offset;
  41. FspData = GetFspGlobalDataPointer ();
  42. //
  43. // It is required to put PcdUpdRegionOffset at offset 0x000C
  44. // for all FSPs.
  45. // gPlatformFspPkgTokenSpaceGuid.PcdUpdRegionOffset | 0x000C | 0x12345678
  46. //
  47. Offset = (UINT32 *)(FspData->FspInfoHeader->ImageBase + \
  48. FspData->FspInfoHeader->CfgRegionOffset + 0x0C);
  49. return *Offset;
  50. }
  51. /**
  52. This interface fills platform specific data.
  53. @param[in,out] FspData Pointer to the FSP global data.
  54. **/
  55. VOID
  56. EFIAPI
  57. SecGetPlatformData (
  58. IN OUT FSP_GLOBAL_DATA *FspData
  59. )
  60. {
  61. FSP_PLAT_DATA *FspPlatformData;
  62. UINT32 TopOfCar;
  63. UINT32 *StackPtr;
  64. UINT32 DwordSize;
  65. FspPlatformData = &FspData->PlatformData;
  66. //
  67. // The entries of platform information, together with the number of them,
  68. // reside in the bottom of stack, left untouched by normal stack operation.
  69. //
  70. TopOfCar = PcdGet32 (PcdTemporaryRamBase) + PcdGet32 (PcdTemporaryRamSize);
  71. FspPlatformData->DataPtr = NULL;
  72. FspPlatformData->MicrocodeRegionBase = 0;
  73. FspPlatformData->MicrocodeRegionSize = 0;
  74. FspPlatformData->CodeRegionBase = 0;
  75. FspPlatformData->CodeRegionSize = 0;
  76. //
  77. // Pointer to the size field
  78. //
  79. StackPtr = (UINT32 *)(TopOfCar - sizeof(UINT32));
  80. while (*StackPtr != 0) {
  81. if (*(StackPtr - 1) == FSP_MCUD_SIGNATURE) {
  82. //
  83. // This following data was pushed onto stack after TempRamInit API
  84. //
  85. DwordSize = 4;
  86. StackPtr = StackPtr - 1 - DwordSize;
  87. CopyMem (&(FspPlatformData->MicrocodeRegionBase), StackPtr, (DwordSize << 2));
  88. StackPtr--;
  89. } else if (*(StackPtr - 1) == FSP_PER0_SIGNATURE) {
  90. //
  91. // This is the performance data for InitTempMemory API entry/exit
  92. //
  93. DwordSize = 4;
  94. StackPtr = StackPtr - 1 - DwordSize;
  95. CopyMem (FspData->PerfData, StackPtr, (DwordSize << 2));
  96. ((UINT8 *)(&FspData->PerfData[0]))[7] = FSP_PERF_ID_API_TMPRAMINIT_ENTRY;
  97. ((UINT8 *)(&FspData->PerfData[1]))[7] = FSP_PERF_ID_API_TMPRAMINIT_EXIT;
  98. StackPtr--;
  99. } else {
  100. StackPtr -= (*StackPtr);
  101. }
  102. }
  103. }
  104. /**
  105. Initialize the FSP global data region.
  106. It needs to be done as soon as possible after the stack is setup.
  107. @param[in,out] PeiFspData Pointer of the FSP global data.
  108. @param[in] BootLoaderStack BootLoader stack.
  109. @param[in] ApiIdx The index of the FSP API.
  110. **/
  111. VOID
  112. FspGlobalDataInit (
  113. IN OUT FSP_GLOBAL_DATA *PeiFspData,
  114. IN UINT32 BootLoaderStack,
  115. IN UINT8 ApiIdx
  116. )
  117. {
  118. VOID *UpdDataRgnPtr;
  119. FSP_INIT_PARAMS *FspInitParams;
  120. CHAR8 ImageId[9];
  121. UINTN Idx;
  122. //
  123. // Init PCIE_BAR with value and set global FSP data pointer.
  124. // PciExpress Base should have been programmed by platform already.
  125. //
  126. SetFspGlobalDataPointer (PeiFspData);
  127. ZeroMem ((VOID *)PeiFspData, sizeof(FSP_GLOBAL_DATA));
  128. PeiFspData->Signature = FSP_GLOBAL_DATA_SIGNATURE;
  129. PeiFspData->CoreStack = BootLoaderStack;
  130. PeiFspData->PerfIdx = 2;
  131. SetFspMeasurePoint (FSP_PERF_ID_API_FSPINIT_ENTRY);
  132. //
  133. // Get FSP Header offset
  134. // It may have multiple FVs, so look into the last one for FSP header
  135. //
  136. PeiFspData->FspInfoHeader = (FSP_INFO_HEADER *)AsmGetFspInfoHeader();
  137. SecGetPlatformData (PeiFspData);
  138. //
  139. // Set API calling mode
  140. //
  141. SetFspApiCallingMode (ApiIdx == 1 ? 0 : 1);
  142. //
  143. // Initialize UPD pointer.
  144. //
  145. FspInitParams = (FSP_INIT_PARAMS *)GetFspApiParameter ();
  146. UpdDataRgnPtr = ((FSP_INIT_RT_COMMON_BUFFER *)FspInitParams->RtBufferPtr)->UpdDataRgnPtr;
  147. if (UpdDataRgnPtr == NULL) {
  148. UpdDataRgnPtr = (VOID *)(PeiFspData->FspInfoHeader->ImageBase + GetFspUpdRegionOffset());
  149. }
  150. SetFspUpdDataPointer (UpdDataRgnPtr);
  151. //
  152. // Initialize serial port
  153. // It might have been done in ProcessLibraryConstructorList(), however,
  154. // the FSP global data is not initialized at that time. So do it again
  155. // for safe.
  156. //
  157. SerialPortInitialize ();
  158. //
  159. // Ensure the golbal data pointer is valid
  160. //
  161. ASSERT (GetFspGlobalDataPointer () == PeiFspData);
  162. for (Idx = 0; Idx < 8; Idx++) {
  163. ImageId[Idx] = PeiFspData->FspInfoHeader->ImageId[Idx];
  164. }
  165. ImageId[Idx] = 0;
  166. DEBUG ((DEBUG_INFO | DEBUG_INIT, "\n============= PEIM FSP v1.%x (%a v%x.%x.%x.%x) =============\n", \
  167. PeiFspData->FspInfoHeader->HeaderRevision - 1, \
  168. ImageId, \
  169. (PeiFspData->FspInfoHeader->ImageRevision >> 24) & 0xff, \
  170. (PeiFspData->FspInfoHeader->ImageRevision >> 16) & 0xff, \
  171. (PeiFspData->FspInfoHeader->ImageRevision >> 8) & 0xff, \
  172. (PeiFspData->FspInfoHeader->ImageRevision >> 0) & 0xff));
  173. }
  174. /**
  175. Adjust the FSP data pointers after the stack is migrated to memory.
  176. @param[in] OffsetGap The offset gap between the old stack and the new stack.
  177. **/
  178. VOID
  179. FspDataPointerFixUp (
  180. IN UINT32 OffsetGap
  181. )
  182. {
  183. FSP_GLOBAL_DATA *NewFspData;
  184. NewFspData = (FSP_GLOBAL_DATA *)((UINTN)GetFspGlobalDataPointer() + (UINTN)OffsetGap);
  185. SetFspGlobalDataPointer (NewFspData);
  186. }
  187. /**
  188. This function check the FSP API calling condition.
  189. @param[in] ApiIdx Internal index of the FSP API.
  190. @param[in] ApiParam Parameter of the FSP API.
  191. **/
  192. EFI_STATUS
  193. EFIAPI
  194. FspApiCallingCheck (
  195. IN UINT32 ApiIdx,
  196. IN VOID *ApiParam
  197. )
  198. {
  199. EFI_STATUS Status;
  200. FSP_GLOBAL_DATA *FspData;
  201. FSP_INIT_PARAMS *FspInitParams;
  202. FSP_INIT_RT_COMMON_BUFFER *FspRtBuffer;
  203. FspInitParams = (FSP_INIT_PARAMS *) ApiParam;
  204. FspRtBuffer = ((FSP_INIT_RT_COMMON_BUFFER *)FspInitParams->RtBufferPtr);
  205. Status = EFI_SUCCESS;
  206. FspData = GetFspGlobalDataPointer ();
  207. if (ApiIdx == 1) {
  208. //
  209. // FspInit check
  210. //
  211. if ((UINT32)FspData != 0xFFFFFFFF) {
  212. Status = EFI_UNSUPPORTED;
  213. } else if ((FspRtBuffer == NULL) || ((FspRtBuffer->BootLoaderTolumSize % EFI_PAGE_SIZE) != 0) || (EFI_ERROR(FspUpdSignatureCheck(ApiIdx, ApiParam)))) {
  214. Status = EFI_INVALID_PARAMETER;
  215. }
  216. } else if (ApiIdx == 2) {
  217. //
  218. // NotifyPhase check
  219. //
  220. if ((FspData == NULL) || ((UINT32)FspData == 0xFFFFFFFF)) {
  221. Status = EFI_UNSUPPORTED;
  222. } else {
  223. if (FspData->Signature != FSP_GLOBAL_DATA_SIGNATURE) {
  224. Status = EFI_UNSUPPORTED;
  225. }
  226. }
  227. } else if (ApiIdx == 3) {
  228. //
  229. // FspMemoryInit check
  230. //
  231. if ((UINT32)FspData != 0xFFFFFFFF) {
  232. Status = EFI_UNSUPPORTED;
  233. } else if ((FspRtBuffer == NULL) || ((FspRtBuffer->BootLoaderTolumSize % EFI_PAGE_SIZE) != 0) || (EFI_ERROR(FspUpdSignatureCheck(ApiIdx, ApiParam)))) {
  234. Status = EFI_INVALID_PARAMETER;
  235. }
  236. } else if (ApiIdx == 4) {
  237. //
  238. // TempRamExit check
  239. //
  240. if ((FspData == NULL) || ((UINT32)FspData == 0xFFFFFFFF)) {
  241. Status = EFI_UNSUPPORTED;
  242. } else {
  243. if (FspData->Signature != FSP_GLOBAL_DATA_SIGNATURE) {
  244. Status = EFI_UNSUPPORTED;
  245. }
  246. }
  247. } else if (ApiIdx == 5) {
  248. //
  249. // FspSiliconInit check
  250. //
  251. if ((FspData == NULL) || ((UINT32)FspData == 0xFFFFFFFF)) {
  252. Status = EFI_UNSUPPORTED;
  253. } else {
  254. if (FspData->Signature != FSP_GLOBAL_DATA_SIGNATURE) {
  255. Status = EFI_UNSUPPORTED;
  256. } else if (EFI_ERROR(FspUpdSignatureCheck(ApiIdx, ApiParam))) {
  257. Status = EFI_INVALID_PARAMETER;
  258. }
  259. }
  260. } else {
  261. Status = EFI_UNSUPPORTED;
  262. }
  263. return Status;
  264. }
  265. /**
  266. This function gets the boot FV offset in FSP.
  267. @return the boot firmware volumen offset inside FSP binary
  268. **/
  269. UINT32
  270. EFIAPI
  271. GetBootFirmwareVolumeOffset (
  272. VOID
  273. )
  274. {
  275. return PcdGet32 (PcdFspBootFirmwareVolumeBase) - PcdGet32 (PcdFspAreaBaseAddress);
  276. }