PlatformHelperDxe.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. /** @file
  2. Implementation of helper routines for DXE environment.
  3. Copyright (c) 2013 - 2016 Intel Corporation.
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include <PiDxe.h>
  7. #include <Library/UefiBootServicesTableLib.h>
  8. #include <Library/S3BootScriptLib.h>
  9. #include <Library/DxeServicesLib.h>
  10. #include <Library/UefiRuntimeServicesTableLib.h>
  11. #include <Protocol/SmmBase2.h>
  12. #include <Protocol/Spi.h>
  13. #include <Protocol/VariableLock.h>
  14. #include <Guid/MemoryConfigData.h>
  15. #include <Guid/QuarkVariableLock.h>
  16. #include "CommonHeader.h"
  17. #define FLASH_BLOCK_SIZE SIZE_4KB
  18. //
  19. // Global variables.
  20. //
  21. EFI_SPI_PROTOCOL *mPlatHelpSpiProtocolRef = NULL;
  22. //
  23. // Routines defined in other source modules of this component.
  24. //
  25. //
  26. // Routines local to this component.
  27. //
  28. //
  29. // Routines shared with other souce modules in this component.
  30. //
  31. EFI_SPI_PROTOCOL *
  32. LocateSpiProtocol (
  33. IN EFI_SMM_SYSTEM_TABLE2 *Smst
  34. )
  35. {
  36. if (mPlatHelpSpiProtocolRef == NULL) {
  37. if (Smst != NULL) {
  38. Smst->SmmLocateProtocol (
  39. &gEfiSmmSpiProtocolGuid,
  40. NULL,
  41. (VOID **) &mPlatHelpSpiProtocolRef
  42. );
  43. } else {
  44. gBS->LocateProtocol (
  45. &gEfiSpiProtocolGuid,
  46. NULL,
  47. (VOID **) &mPlatHelpSpiProtocolRef
  48. );
  49. }
  50. ASSERT (mPlatHelpSpiProtocolRef != NULL);
  51. }
  52. return mPlatHelpSpiProtocolRef;
  53. }
  54. //
  55. // Routines exported by this source module.
  56. //
  57. /**
  58. Find pointer to RAW data in Firmware volume file.
  59. @param FvNameGuid Firmware volume to search. If == NULL search all.
  60. @param FileNameGuid Firmware volume file to search for.
  61. @param SectionData Pointer to RAW data section of found file.
  62. @param SectionDataSize Pointer to UNITN to get size of RAW data.
  63. @retval EFI_SUCCESS Raw Data found.
  64. @retval EFI_INVALID_PARAMETER FileNameGuid == NULL.
  65. @retval EFI_NOT_FOUND Firmware volume file not found.
  66. @retval EFI_UNSUPPORTED Unsupported in current enviroment (PEI or DXE).
  67. **/
  68. EFI_STATUS
  69. EFIAPI
  70. PlatformFindFvFileRawDataSection (
  71. IN CONST EFI_GUID *FvNameGuid OPTIONAL,
  72. IN CONST EFI_GUID *FileNameGuid,
  73. OUT VOID **SectionData,
  74. OUT UINTN *SectionDataSize
  75. )
  76. {
  77. if (FileNameGuid == NULL || SectionData == NULL || SectionDataSize == NULL) {
  78. return EFI_INVALID_PARAMETER;
  79. }
  80. if (FvNameGuid != NULL) {
  81. return EFI_UNSUPPORTED; // Searching in specific FV unsupported in DXE.
  82. }
  83. return GetSectionFromAnyFv (FileNameGuid, EFI_SECTION_RAW, 0, SectionData, SectionDataSize);
  84. }
  85. /**
  86. Find free spi protect register and write to it to protect a flash region.
  87. @param DirectValue Value to directly write to register.
  88. if DirectValue == 0 the use Base & Length below.
  89. @param BaseAddress Base address of region in Flash Memory Map.
  90. @param Length Length of region to protect.
  91. @retval EFI_SUCCESS Free spi protect register found & written.
  92. @retval EFI_NOT_FOUND Free Spi protect register not found.
  93. @retval EFI_DEVICE_ERROR Unable to write to spi protect register.
  94. **/
  95. EFI_STATUS
  96. EFIAPI
  97. PlatformWriteFirstFreeSpiProtect (
  98. IN CONST UINT32 DirectValue,
  99. IN CONST UINT32 BaseAddress,
  100. IN CONST UINT32 Length
  101. )
  102. {
  103. UINT32 FreeOffset;
  104. UINT32 PchRootComplexBar;
  105. EFI_STATUS Status;
  106. PchRootComplexBar = QNC_RCRB_BASE;
  107. Status = WriteFirstFreeSpiProtect (
  108. PchRootComplexBar,
  109. DirectValue,
  110. BaseAddress,
  111. Length,
  112. &FreeOffset
  113. );
  114. if (!EFI_ERROR (Status)) {
  115. S3BootScriptSaveMemWrite (
  116. S3BootScriptWidthUint32,
  117. (UINTN) (PchRootComplexBar + FreeOffset),
  118. 1,
  119. (VOID *) (UINTN) (PchRootComplexBar + FreeOffset)
  120. );
  121. }
  122. return Status;
  123. }
  124. /**
  125. Lock legacy SPI static configuration information.
  126. Function will assert if unable to lock config.
  127. **/
  128. VOID
  129. EFIAPI
  130. PlatformFlashLockConfig (
  131. VOID
  132. )
  133. {
  134. EFI_STATUS Status;
  135. EFI_SPI_PROTOCOL *SpiProtocol;
  136. //
  137. // Enable lock of legacy SPI static configuration information.
  138. //
  139. SpiProtocol = LocateSpiProtocol (NULL); // This routine will not be called in SMM.
  140. ASSERT (SpiProtocol != NULL);
  141. if (SpiProtocol != NULL) {
  142. Status = SpiProtocol->Lock (SpiProtocol);
  143. if (!EFI_ERROR (Status)) {
  144. DEBUG ((EFI_D_INFO, "Platform: Spi Config Locked Down\n"));
  145. } else if (Status == EFI_ACCESS_DENIED) {
  146. DEBUG ((EFI_D_INFO, "Platform: Spi Config already locked down\n"));
  147. } else {
  148. ASSERT_EFI_ERROR (Status);
  149. }
  150. }
  151. }
  152. /**
  153. Platform Variable Lock.
  154. @retval EFI_SUCCESS Platform Variable Lock successful.
  155. @retval EFI_NOT_FOUND No protocol instances were found that match Protocol and
  156. Registration.
  157. **/
  158. VOID
  159. EFIAPI
  160. PlatformVariableLock (
  161. )
  162. {
  163. EFI_STATUS Status;
  164. EDKII_VARIABLE_LOCK_PROTOCOL *VariableLockProtocol;
  165. Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLockProtocol);
  166. ASSERT_EFI_ERROR (Status);
  167. Status = VariableLockProtocol->RequestToLock (
  168. VariableLockProtocol,
  169. QUARK_VARIABLE_LOCK_NAME,
  170. &gQuarkVariableLockGuid
  171. );
  172. ASSERT_EFI_ERROR (Status);
  173. // Memory Config Data shouldn't be writable when Quark Variable Lock is enabled.
  174. Status = VariableLockProtocol->RequestToLock (
  175. VariableLockProtocol,
  176. EFI_MEMORY_CONFIG_DATA_NAME,
  177. &gEfiMemoryConfigDataGuid
  178. );
  179. ASSERT_EFI_ERROR (Status);
  180. }
  181. /**
  182. Lock regions and config of SPI flash given the policy for this platform.
  183. Function will assert if unable to lock regions or config.
  184. @param PreBootPolicy If TRUE do Pre Boot Flash Lock Policy.
  185. **/
  186. VOID
  187. EFIAPI
  188. PlatformFlashLockPolicy (
  189. IN CONST BOOLEAN PreBootPolicy
  190. )
  191. {
  192. EFI_STATUS Status;
  193. UINT64 CpuAddressNvStorage;
  194. UINT64 CpuAddressFlashDevice;
  195. UINT64 SpiAddress;
  196. EFI_BOOT_MODE BootMode;
  197. UINTN SpiFlashDeviceSize;
  198. BootMode = GetBootModeHob ();
  199. SpiFlashDeviceSize = (UINTN) PcdGet32 (PcdSpiFlashDeviceSize);
  200. CpuAddressFlashDevice = SIZE_4GB - SpiFlashDeviceSize;
  201. DEBUG (
  202. (EFI_D_INFO,
  203. "Platform:FlashDeviceSize = 0x%08x Bytes\n",
  204. SpiFlashDeviceSize)
  205. );
  206. //
  207. // If not in update or recovery mode, lock stuff down
  208. //
  209. if ((BootMode != BOOT_IN_RECOVERY_MODE) && (BootMode != BOOT_ON_FLASH_UPDATE)) {
  210. //
  211. // Lock regions
  212. //
  213. CpuAddressNvStorage = (UINT64) PcdGet32 (PcdFlashNvStorageVariableBase);
  214. //
  215. // Lock from start of flash device up to Smi writable flash storage areas.
  216. //
  217. SpiAddress = 0;
  218. if (!PlatformIsSpiRangeProtected ((UINT32) SpiAddress, (UINT32) (CpuAddressNvStorage - CpuAddressFlashDevice))) {
  219. DEBUG (
  220. (EFI_D_INFO,
  221. "Platform: Protect Region Base:Len 0x%08x:0x%08x\n",
  222. (UINTN) SpiAddress, (UINTN)(CpuAddressNvStorage - CpuAddressFlashDevice))
  223. );
  224. Status = PlatformWriteFirstFreeSpiProtect (
  225. 0,
  226. (UINT32) SpiAddress,
  227. (UINT32) (CpuAddressNvStorage - CpuAddressFlashDevice)
  228. );
  229. ASSERT_EFI_ERROR (Status);
  230. }
  231. //
  232. // Move Spi Address to after Smi writable flash storage areas.
  233. //
  234. SpiAddress = CpuAddressNvStorage - CpuAddressFlashDevice;
  235. SpiAddress += ((UINT64) PcdGet32 (PcdFlashNvStorageVariableSize));
  236. //
  237. // Lock from end of OEM area to end of flash part.
  238. //
  239. if (!PlatformIsSpiRangeProtected ((UINT32) SpiAddress, SpiFlashDeviceSize - ((UINT32) SpiAddress))) {
  240. DEBUG (
  241. (EFI_D_INFO,
  242. "Platform: Protect Region Base:Len 0x%08x:0x%08x\n",
  243. (UINTN) SpiAddress,
  244. (UINTN) (SpiFlashDeviceSize - ((UINT32) SpiAddress)))
  245. );
  246. ASSERT (SpiAddress < ((UINT64) SpiFlashDeviceSize));
  247. Status = PlatformWriteFirstFreeSpiProtect (
  248. 0,
  249. (UINT32) SpiAddress,
  250. SpiFlashDeviceSize - ((UINT32) SpiAddress)
  251. );
  252. ASSERT_EFI_ERROR (Status);
  253. }
  254. }
  255. //
  256. // Always Lock flash config registers if about to boot a boot option
  257. // else lock depending on boot mode.
  258. //
  259. if (PreBootPolicy || (BootMode != BOOT_ON_FLASH_UPDATE)) {
  260. PlatformFlashLockConfig ();
  261. }
  262. //
  263. // Enable Quark Variable lock if PreBootPolicy.
  264. //
  265. if (PreBootPolicy) {
  266. PlatformVariableLock ();
  267. }
  268. }
  269. /** Check if System booted with recovery Boot Stage1 image.
  270. @retval TRUE If system booted with recovery Boot Stage1 image.
  271. @retval FALSE If system booted with normal stage1 image.
  272. **/
  273. BOOLEAN
  274. EFIAPI
  275. PlatformIsBootWithRecoveryStage1 (
  276. VOID
  277. )
  278. {
  279. ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
  280. return FALSE;
  281. }