NorFlashDxe.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. /** @file NorFlashDxe.c
  2. Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
  3. Copyright (c) 2017, Socionext Inc. All rights reserved.<BR>
  4. Copyright (c) 2017, Linaro, Ltd. All rights reserved.<BR>
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include <Library/BaseMemoryLib.h>
  8. #include <Library/DxeServicesTableLib.h>
  9. #include <Library/HobLib.h>
  10. #include <Library/MemoryAllocationLib.h>
  11. #include <Library/NorFlashInfoLib.h>
  12. #include <Library/PcdLib.h>
  13. #include <Library/UefiBootServicesTableLib.h>
  14. #include <Library/UefiLib.h>
  15. #include <Library/UefiRuntimeLib.h>
  16. #include "NorFlash.h"
  17. //
  18. // Global variable declarations
  19. //
  20. STATIC NOR_FLASH_INSTANCE **mNorFlashInstances;
  21. STATIC UINT32 mNorFlashDeviceCount;
  22. STATIC EFI_EVENT mNorFlashVirtualAddrChangeEvent;
  23. EFI_STATUS
  24. EFIAPI
  25. NorFlashFvbInitialize (
  26. IN NOR_FLASH_INSTANCE* Instance
  27. )
  28. {
  29. EFI_STATUS Status;
  30. UINT32 FvbNumLba;
  31. EFI_BOOT_MODE BootMode;
  32. UINTN RuntimeMmioRegionSize;
  33. UINTN BlockSize;
  34. DEBUG ((DEBUG_BLKIO,"NorFlashFvbInitialize\n"));
  35. BlockSize = Instance->BlockSize;
  36. // FirmwareVolumeHeader->FvLength is declared to have the Variable area
  37. // AND the FTW working area AND the FTW Spare contiguous.
  38. ASSERT(PcdGet32(PcdFlashNvStorageVariableBase) +
  39. PcdGet32(PcdFlashNvStorageVariableSize) ==
  40. PcdGet32(PcdFlashNvStorageFtwWorkingBase));
  41. ASSERT(PcdGet32(PcdFlashNvStorageFtwWorkingBase) +
  42. PcdGet32(PcdFlashNvStorageFtwWorkingSize) ==
  43. PcdGet32(PcdFlashNvStorageFtwSpareBase));
  44. // Check if the size of the area is at least one block size
  45. ASSERT((PcdGet32(PcdFlashNvStorageVariableSize) > 0) &&
  46. (PcdGet32(PcdFlashNvStorageVariableSize) / BlockSize > 0));
  47. ASSERT((PcdGet32(PcdFlashNvStorageFtwWorkingSize) > 0) &&
  48. (PcdGet32(PcdFlashNvStorageFtwWorkingSize) / BlockSize > 0));
  49. ASSERT((PcdGet32(PcdFlashNvStorageFtwSpareSize) > 0) &&
  50. (PcdGet32(PcdFlashNvStorageFtwSpareSize) / BlockSize > 0));
  51. // Ensure the Variable areas are aligned on block size boundaries
  52. ASSERT((PcdGet32(PcdFlashNvStorageVariableBase) % BlockSize) == 0);
  53. ASSERT((PcdGet32(PcdFlashNvStorageFtwWorkingBase) % BlockSize) == 0);
  54. ASSERT((PcdGet32(PcdFlashNvStorageFtwSpareBase) % BlockSize) == 0);
  55. Instance->Initialized = TRUE;
  56. mFlashNvStorageVariableBase = FixedPcdGet32 (PcdFlashNvStorageVariableBase);
  57. // Set the index of the first LBA for the FVB
  58. Instance->StartLba = (PcdGet32 (PcdFlashNvStorageVariableBase) -
  59. Instance->RegionBaseAddress) / BlockSize;
  60. BootMode = GetBootModeHob ();
  61. if (BootMode == BOOT_WITH_DEFAULT_SETTINGS) {
  62. Status = EFI_INVALID_PARAMETER;
  63. } else {
  64. // Determine if there is a valid header at the beginning of the NorFlash
  65. Status = ValidateFvHeader (Instance);
  66. }
  67. // Install the Default FVB header if required
  68. if (EFI_ERROR(Status)) {
  69. // There is no valid header, so time to install one.
  70. DEBUG ((DEBUG_INFO, "%a: The FVB Header is not valid.\n", __FUNCTION__));
  71. DEBUG ((DEBUG_INFO, "%a: Installing a correct one for this volume.\n",
  72. __FUNCTION__));
  73. // Erase all the NorFlash that is reserved for variable storage
  74. FvbNumLba = (PcdGet32(PcdFlashNvStorageVariableSize) +
  75. PcdGet32(PcdFlashNvStorageFtwWorkingSize) +
  76. PcdGet32(PcdFlashNvStorageFtwSpareSize)) /
  77. Instance->BlockSize;
  78. Status = FvbEraseBlocks (&Instance->FvbProtocol, (EFI_LBA)0, FvbNumLba,
  79. EFI_LBA_LIST_TERMINATOR);
  80. if (EFI_ERROR(Status)) {
  81. return Status;
  82. }
  83. // Install all appropriate headers
  84. Status = InitializeFvAndVariableStoreHeaders (Instance);
  85. if (EFI_ERROR(Status)) {
  86. return Status;
  87. }
  88. }
  89. //
  90. // The driver implementing the variable read service can now be dispatched;
  91. // the varstore headers are in place.
  92. //
  93. Status = gBS->InstallProtocolInterface (&gImageHandle,
  94. &gEdkiiNvVarStoreFormattedGuid,
  95. EFI_NATIVE_INTERFACE,
  96. NULL);
  97. if (EFI_ERROR (Status)) {
  98. DEBUG ((DEBUG_ERROR,
  99. "%a: Failed to install gEdkiiNvVarStoreFormattedGuid\n",
  100. __FUNCTION__));
  101. return Status;
  102. }
  103. //
  104. // Declare the Non-Volatile storage as EFI_MEMORY_RUNTIME
  105. //
  106. RuntimeMmioRegionSize = Instance->Size;
  107. Status = gDS->AddMemorySpace (EfiGcdMemoryTypeMemoryMappedIo,
  108. Instance->RegionBaseAddress, RuntimeMmioRegionSize,
  109. EFI_MEMORY_UC | EFI_MEMORY_RUNTIME);
  110. ASSERT_EFI_ERROR (Status);
  111. Status = gDS->AddMemorySpace (EfiGcdMemoryTypeMemoryMappedIo,
  112. Instance->DeviceBaseAddress, SIZE_4KB,
  113. EFI_MEMORY_UC | EFI_MEMORY_RUNTIME);
  114. ASSERT_EFI_ERROR (Status);
  115. Status = gDS->SetMemorySpaceAttributes (Instance->RegionBaseAddress,
  116. RuntimeMmioRegionSize, EFI_MEMORY_UC | EFI_MEMORY_RUNTIME);
  117. ASSERT_EFI_ERROR (Status);
  118. Status = gDS->SetMemorySpaceAttributes (Instance->DeviceBaseAddress,
  119. SIZE_4KB, EFI_MEMORY_UC | EFI_MEMORY_RUNTIME);
  120. ASSERT_EFI_ERROR (Status);
  121. return Status;
  122. }
  123. /**
  124. Fixup internal data so that EFI can be call in virtual mode.
  125. Call the passed in Child Notify event and convert any pointers in
  126. lib to virtual mode.
  127. @param[in] Event The Event that is being processed
  128. @param[in] Context Event Context
  129. **/
  130. STATIC
  131. VOID
  132. EFIAPI
  133. NorFlashVirtualNotifyEvent (
  134. IN EFI_EVENT Event,
  135. IN VOID *Context
  136. )
  137. {
  138. UINTN Index;
  139. EfiConvertPointer (0x0, (VOID**)&mFlashNvStorageVariableBase);
  140. for (Index = 0; Index < mNorFlashDeviceCount; Index++) {
  141. EfiConvertPointer (0x0,
  142. (VOID**)&mNorFlashInstances[Index]->HostRegisterBaseAddress);
  143. EfiConvertPointer (0x0,
  144. (VOID**)&mNorFlashInstances[Index]->DeviceBaseAddress);
  145. EfiConvertPointer (0x0,
  146. (VOID**)&mNorFlashInstances[Index]->RegionBaseAddress);
  147. // Convert Fvb
  148. EfiConvertPointer (0x0,
  149. (VOID**)&mNorFlashInstances[Index]->FvbProtocol.EraseBlocks);
  150. EfiConvertPointer (0x0,
  151. (VOID**)&mNorFlashInstances[Index]->FvbProtocol.GetAttributes);
  152. EfiConvertPointer (0x0,
  153. (VOID**)&mNorFlashInstances[Index]->FvbProtocol.GetBlockSize);
  154. EfiConvertPointer (0x0,
  155. (VOID**)&mNorFlashInstances[Index]->FvbProtocol.GetPhysicalAddress);
  156. EfiConvertPointer (0x0,
  157. (VOID**)&mNorFlashInstances[Index]->FvbProtocol.Read);
  158. EfiConvertPointer (0x0,
  159. (VOID**)&mNorFlashInstances[Index]->FvbProtocol.SetAttributes);
  160. EfiConvertPointer (0x0,
  161. (VOID**)&mNorFlashInstances[Index]->FvbProtocol.Write);
  162. if (mNorFlashInstances[Index]->ShadowBuffer != NULL) {
  163. EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->ShadowBuffer);
  164. }
  165. }
  166. return;
  167. }
  168. EFI_STATUS
  169. EFIAPI
  170. NorFlashInitialise (
  171. IN EFI_HANDLE ImageHandle,
  172. IN EFI_SYSTEM_TABLE *SystemTable
  173. )
  174. {
  175. EFI_STATUS Status;
  176. EFI_PHYSICAL_ADDRESS HostRegisterBaseAddress;
  177. UINT32 Index;
  178. NOR_FLASH_DESCRIPTION* NorFlashDevices;
  179. BOOLEAN ContainVariableStorage;
  180. // Register HSSPI FIP006 register region
  181. HostRegisterBaseAddress = PcdGet32 (PcdFip006DxeRegBaseAddress);
  182. Status = gDS->AddMemorySpace (
  183. EfiGcdMemoryTypeMemoryMappedIo,
  184. HostRegisterBaseAddress, SIZE_4KB,
  185. EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
  186. );
  187. ASSERT_EFI_ERROR (Status);
  188. Status = gDS->SetMemorySpaceAttributes (
  189. HostRegisterBaseAddress, SIZE_4KB,
  190. EFI_MEMORY_UC | EFI_MEMORY_RUNTIME);
  191. ASSERT_EFI_ERROR (Status);
  192. // Initialize NOR flash instances
  193. Status = NorFlashPlatformGetDevices (&NorFlashDevices, &mNorFlashDeviceCount);
  194. if (EFI_ERROR (Status)) {
  195. DEBUG ((DEBUG_ERROR,"NorFlashInitialise: Fail to get Nor Flash devices\n"));
  196. return Status;
  197. }
  198. mNorFlashInstances = AllocateRuntimePool (sizeof(NOR_FLASH_INSTANCE*) *
  199. mNorFlashDeviceCount);
  200. for (Index = 0; Index < mNorFlashDeviceCount; Index++) {
  201. // Check if this NOR Flash device contain the variable storage region
  202. ContainVariableStorage =
  203. (NorFlashDevices[Index].RegionBaseAddress <=
  204. PcdGet32 (PcdFlashNvStorageVariableBase)) &&
  205. (PcdGet32 (PcdFlashNvStorageVariableBase) +
  206. PcdGet32 (PcdFlashNvStorageVariableSize) <=
  207. NorFlashDevices[Index].RegionBaseAddress + NorFlashDevices[Index].Size);
  208. Status = NorFlashCreateInstance (
  209. HostRegisterBaseAddress,
  210. NorFlashDevices[Index].DeviceBaseAddress,
  211. NorFlashDevices[Index].RegionBaseAddress,
  212. NorFlashDevices[Index].Size,
  213. Index,
  214. NorFlashDevices[Index].BlockSize,
  215. ContainVariableStorage,
  216. &mNorFlashInstances[Index]
  217. );
  218. if (EFI_ERROR (Status)) {
  219. DEBUG ((DEBUG_ERROR,
  220. "NorFlashInitialise: Fail to create instance for NorFlash[%d]\n",
  221. Index));
  222. continue;
  223. }
  224. Status = gBS->InstallMultipleProtocolInterfaces (
  225. &mNorFlashInstances[Index]->Handle,
  226. &gEfiDevicePathProtocolGuid, &mNorFlashInstances[Index]->DevicePath,
  227. &gEfiFirmwareVolumeBlockProtocolGuid, &mNorFlashInstances[Index]->FvbProtocol,
  228. NULL
  229. );
  230. ASSERT_EFI_ERROR (Status);
  231. }
  232. //
  233. // Register for the virtual address change event
  234. //
  235. Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_NOTIFY,
  236. NorFlashVirtualNotifyEvent, NULL,
  237. &gEfiEventVirtualAddressChangeGuid,
  238. &mNorFlashVirtualAddrChangeEvent);
  239. ASSERT_EFI_ERROR (Status);
  240. return Status;
  241. }
  242. VOID
  243. EFIAPI
  244. NorFlashLock (
  245. NOR_FLASH_LOCK_CONTEXT *Context
  246. )
  247. {
  248. if (!EfiAtRuntime ()) {
  249. // Raise TPL to TPL_HIGH to stop anyone from interrupting us.
  250. Context->OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
  251. } else {
  252. Context->InterruptsEnabled = SaveAndDisableInterrupts ();
  253. }
  254. }
  255. VOID
  256. EFIAPI
  257. NorFlashUnlock (
  258. NOR_FLASH_LOCK_CONTEXT *Context
  259. )
  260. {
  261. if (!EfiAtRuntime ()) {
  262. // Interruptions can resume.
  263. gBS->RestoreTPL (Context->OriginalTPL);
  264. } else if (Context->InterruptsEnabled) {
  265. SetInterruptState (TRUE);
  266. }
  267. }