NorFlashDxe.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. /** @file
  2. *
  3. * Copyright (c) 2015, Hisilicon Limited. All rights reserved.
  4. * Copyright (c) 2015, Linaro Limited. All rights reserved.
  5. *
  6. * This program and the accompanying materials
  7. * are licensed and made available under the terms and conditions of the BSD License
  8. * which accompanies this distribution. The full text of the license may be found at
  9. * http://opensource.org/licenses/bsd-license.php
  10. *
  11. * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
  13. *
  14. **/
  15. #include <Uefi.h>
  16. #include <Library/DebugLib.h>
  17. #include <Library/UefiBootServicesTableLib.h>
  18. #include <Library/ArmLib.h>
  19. #include <Library/PcdLib.h>
  20. #include <Protocol/NorFlashProtocol.h>
  21. #include <Library/DxeServicesTableLib.h>
  22. #include <Protocol/Cpu.h>
  23. #include "NorFlashHw.h"
  24. EFI_STATUS Erase(
  25. IN UNI_NOR_FLASH_PROTOCOL *This,
  26. IN UINT32 Offset,
  27. IN UINT32 Length
  28. );
  29. EFI_STATUS Write(
  30. IN UNI_NOR_FLASH_PROTOCOL *This,
  31. IN UINT32 Offset,
  32. IN UINT8 *Buffer,
  33. UINT32 ulLength
  34. );
  35. EFI_STATUS Read(
  36. IN UNI_NOR_FLASH_PROTOCOL *This,
  37. IN UINT32 Offset,
  38. IN OUT UINT8 *Buffer,
  39. IN UINT32 ulLen
  40. );
  41. UNI_NOR_FLASH_PROTOCOL gUniNorFlash = {
  42. Erase,
  43. Write,
  44. Read
  45. };
  46. EFI_STATUS
  47. EFIAPI Read(
  48. IN UNI_NOR_FLASH_PROTOCOL *This,
  49. IN UINT32 Offset,
  50. IN OUT UINT8 *Buffer,
  51. IN UINT32 ulLen
  52. )
  53. {
  54. UINT32 index;
  55. UINT64 ullAddr;
  56. UINT32 ullCnt = 0;
  57. UINT32 *puiBuffer32 = NULL;
  58. UINT32 *puiDst32 = NULL;
  59. UINT8 *pucBuffer8 = NULL;
  60. UINT8 *pucDst8 = NULL;
  61. if (Offset + ulLen > (gFlashInfo[gIndex.InfIndex].SingleChipSize * gFlashInfo[gIndex.InfIndex].ParallelNum))
  62. {
  63. DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Exceed the flash scope!\n", __FUNCTION__,__LINE__));
  64. return EFI_INVALID_PARAMETER;
  65. }
  66. if (0 == ulLen)
  67. {
  68. DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Length is Zero!\n", __FUNCTION__,__LINE__));
  69. return EFI_INVALID_PARAMETER;
  70. }
  71. if (NULL == Buffer)
  72. {
  73. DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Buffer is NULL!\n", __FUNCTION__,__LINE__));
  74. return EFI_BAD_BUFFER_SIZE;
  75. }
  76. ullAddr = gIndex.Base + Offset;
  77. pucBuffer8 = (UINT8 *)Buffer;
  78. pucDst8 = (UINT8 *)((UINTN)ullAddr);
  79. if (ulLen < FOUR_BYTE_UNIT)
  80. {
  81. for(index = 0; index< ulLen; index++)
  82. {
  83. *pucBuffer8++ = *pucDst8++;
  84. }
  85. }
  86. else
  87. {
  88. ullCnt = Offset % FOUR_BYTE_UNIT;
  89. ullCnt = FOUR_BYTE_UNIT - ullCnt;
  90. for(index = 0; index < ullCnt; index++)
  91. {
  92. *pucBuffer8++ = *pucDst8++;
  93. }
  94. ulLen -= ullCnt;
  95. puiBuffer32 = (UINT32 *)pucBuffer8;
  96. puiDst32 = (UINT32 *)pucDst8;
  97. ullCnt = ulLen / FOUR_BYTE_UNIT;
  98. for(index = 0; index < ullCnt; index++)
  99. {
  100. *puiBuffer32++ = *puiDst32++;
  101. }
  102. ullCnt = ulLen % FOUR_BYTE_UNIT;
  103. pucBuffer8 = (UINT8 *)puiBuffer32;
  104. pucDst8 = (UINT8 *)puiDst32;
  105. for(index = 0; index < ullCnt; index++)
  106. {
  107. *pucBuffer8++ = *pucDst8++;
  108. }
  109. }
  110. return EFI_SUCCESS;
  111. }
  112. static EFI_STATUS WriteAfterErase_Fill(
  113. IN const UINT32 Offset,
  114. IN const UINT8 *Buffer,
  115. IN const UINT32 Length
  116. )
  117. {
  118. EFI_STATUS Status;
  119. UINT32 Loop;
  120. UINT32 DataOffset;
  121. UINT32 NewOffset;
  122. UINT8 *NewDataUnit;
  123. UINT32 FlashUnitLength;
  124. FlashUnitLength = gFlashInfo[gIndex.InfIndex].BufferProgramSize << gFlashInfo[gIndex.InfIndex].ParallelNum;
  125. if (0 == Length)
  126. {
  127. return EFI_SUCCESS;
  128. }
  129. if ((Offset % FlashUnitLength + Length) > FlashUnitLength)
  130. {
  131. DEBUG ((EFI_D_INFO, "[%a]:[%dL]:Exceed the Flash Size!\n", __FUNCTION__,__LINE__));
  132. return EFI_UNSUPPORTED;
  133. }
  134. Status = gBS->AllocatePool(EfiBootServicesData, FlashUnitLength, (VOID *)&NewDataUnit);
  135. if (EFI_ERROR(Status))
  136. {
  137. DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Allocate Pool failed, %r!\n", __FUNCTION__,__LINE__, Status));
  138. return Status;
  139. }
  140. NewOffset = Offset - (Offset % FlashUnitLength);
  141. gBS->CopyMem((VOID *)NewDataUnit, (VOID *)(UINTN)(gIndex.Base + NewOffset), FlashUnitLength);
  142. DataOffset = Offset % FlashUnitLength;
  143. for (Loop = 0; Loop < Length; Loop ++)
  144. {
  145. NewDataUnit[(UINT32)(DataOffset + Loop)] = Buffer[Loop];
  146. }
  147. Status = BufferWrite(NewOffset, (void *)NewDataUnit, FlashUnitLength);
  148. if (EFI_ERROR(Status))
  149. {
  150. DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:BufferWrite %r!\n", __FUNCTION__,__LINE__, Status));
  151. return Status;
  152. }
  153. (void)gBS->FreePool((VOID *)NewDataUnit);
  154. return Status;
  155. }
  156. static EFI_STATUS WriteAfterErase_Final(
  157. IN UINT32 Offset,
  158. IN UINT8 *Buffer,
  159. IN UINT32 Length
  160. )
  161. {
  162. EFI_STATUS Status;
  163. UINT32 Loop;
  164. UINT32 FlashUnitLength;
  165. FlashUnitLength = gFlashInfo[gIndex.InfIndex].BufferProgramSize << gFlashInfo[gIndex.InfIndex].ParallelNum;
  166. if (0 == Length)
  167. {
  168. return EFI_SUCCESS;
  169. }
  170. if (0 != (Offset % FlashUnitLength))
  171. {
  172. DEBUG ((EFI_D_ERROR, "[%a]:[%dL]: Offset must be a multiple of 0x%x!\n", __FUNCTION__,__LINE__,FlashUnitLength));
  173. return EFI_UNSUPPORTED;
  174. }
  175. Loop = Length / FlashUnitLength;
  176. while (Loop --)
  177. {
  178. Status = BufferWrite(Offset, (void *)Buffer, FlashUnitLength);
  179. if (EFI_ERROR(Status))
  180. {
  181. DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:BufferWrite Failed: %r!\n", __FUNCTION__,__LINE__, Status));
  182. return EFI_DEVICE_ERROR;
  183. }
  184. Offset += FlashUnitLength;
  185. Buffer += FlashUnitLength;
  186. }
  187. Length = Length % FlashUnitLength;
  188. if (Length)
  189. {
  190. Status = WriteAfterErase_Fill(Offset, Buffer, Length);
  191. if (EFI_ERROR(Status))
  192. {
  193. DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:WriteAfterErase_Fill failed,%r!\n", __FUNCTION__,__LINE__, Status));
  194. return Status;
  195. }
  196. }
  197. return EFI_SUCCESS;
  198. }
  199. EFI_STATUS
  200. WriteAfterErase(
  201. UINT32 TempBase,
  202. UINT32 Offset,
  203. UINT8 *Buffer,
  204. UINT32 Length
  205. )
  206. {
  207. EFI_STATUS Status;
  208. UINT32 FlashUnitLength;
  209. FlashUnitLength = gFlashInfo[gIndex.InfIndex].BufferProgramSize << gFlashInfo[gIndex.InfIndex].ParallelNum;
  210. if (0 == Length)
  211. {
  212. return EFI_SUCCESS;
  213. }
  214. if (Offset % FlashUnitLength)
  215. {
  216. UINT32 TempLength;
  217. TempLength = FlashUnitLength - (Offset % FlashUnitLength);
  218. if (TempLength > Length)
  219. {
  220. TempLength = Length;
  221. }
  222. Status = WriteAfterErase_Fill(Offset, Buffer, TempLength);
  223. if (EFI_ERROR(Status))
  224. {
  225. DEBUG ((EFI_D_ERROR, "[%a]:[%dL]: %r!\n", __FUNCTION__,__LINE__, Status));
  226. return Status;
  227. }
  228. Offset += TempLength;
  229. Length -= TempLength;
  230. Buffer += TempLength;
  231. //Desc:if Offset >= gOneFlashSize,modify base
  232. if (0 < (Offset / gFlashInfo[gIndex.InfIndex].SingleChipSize))
  233. {
  234. TempBase += gFlashInfo[gIndex.InfIndex].SingleChipSize;
  235. gIndex.Base = TempBase;
  236. Offset = 0;
  237. }
  238. }
  239. Status = WriteAfterErase_Final(Offset, Buffer, Length);
  240. if (EFI_ERROR(Status))
  241. {
  242. DEBUG ((EFI_D_ERROR, "[%a]:[%dL]: %r!\n", __FUNCTION__,__LINE__, Status));
  243. return Status;
  244. }
  245. return EFI_SUCCESS;
  246. }
  247. EFI_STATUS
  248. FlashSectorErase(
  249. UINT32 TempBase,
  250. UINT32 Offset,
  251. UINT32 Length
  252. )
  253. {
  254. EFI_STATUS Status;
  255. UINT32 SectorOffset;
  256. UINT8 *StaticBuffer;
  257. UINT8 *Buffer;
  258. UINT32 TempOffset;
  259. UINT32 TempLength;
  260. UINT32 LeftLength;
  261. if (0 == Length)
  262. {
  263. return EFI_SUCCESS;
  264. }
  265. LeftLength = gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum - (Offset % (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum));
  266. if (LeftLength < Length)
  267. {
  268. return EFI_UNSUPPORTED;
  269. }
  270. SectorOffset = Offset - (Offset % (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum));
  271. Status = gBS->AllocatePool(EfiBootServicesData, gFlashInfo[gIndex.InfIndex].BlockSize * (UINTN)gFlashInfo[gIndex.InfIndex].ParallelNum, (VOID *)&StaticBuffer);
  272. if (EFI_ERROR(Status))
  273. {
  274. return Status;
  275. }
  276. Buffer = StaticBuffer;
  277. gBS->CopyMem((VOID *)Buffer, (VOID *)(UINTN)(TempBase + SectorOffset),
  278. (gFlashInfo[gIndex.InfIndex].BlockSize * (UINTN)gFlashInfo[gIndex.InfIndex].ParallelNum));
  279. Status = SectorErase(TempBase, SectorOffset);
  280. if (EFI_ERROR(Status))
  281. {
  282. goto DO;
  283. }
  284. TempOffset = SectorOffset;
  285. TempLength = Offset % (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum);
  286. Status = WriteAfterErase(TempBase, TempOffset, Buffer, TempLength);
  287. if (EFI_ERROR(Status))
  288. {
  289. goto DO;
  290. }
  291. Buffer = Buffer + TempLength + Length;
  292. TempOffset = Offset + Length;
  293. TempLength = SectorOffset + (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum) - TempOffset;
  294. Status = WriteAfterErase(TempBase, TempOffset, Buffer, TempLength);
  295. if (EFI_ERROR(Status))
  296. {
  297. DEBUG ((EFI_D_ERROR, "[%a]:[%dL]: %r!\n", __FUNCTION__,__LINE__,Status));
  298. goto DO;
  299. }
  300. (void)gBS->FreePool((VOID *)StaticBuffer);
  301. return EFI_SUCCESS;
  302. DO:
  303. (void)gBS->FreePool((VOID *)StaticBuffer);
  304. return Status;
  305. }
  306. EFI_STATUS
  307. EFIAPI Erase(
  308. IN UNI_NOR_FLASH_PROTOCOL *This,
  309. IN UINT32 Offset,
  310. IN UINT32 Length
  311. )
  312. {
  313. EFI_STATUS Status = EFI_SUCCESS;
  314. UINT32 Sectors;
  315. UINT32 TempLength;
  316. UINT32 TempBase;
  317. UINT32 Loop;
  318. if (Offset + Length > (gFlashInfo[gIndex.InfIndex].SingleChipSize * gFlashInfo[gIndex.InfIndex].ParallelNum))
  319. {
  320. DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Exceed the Flash Size!\n", __FUNCTION__,__LINE__));
  321. return EFI_ABORTED;
  322. }
  323. if (0 == Length)
  324. {
  325. return EFI_SUCCESS;
  326. }
  327. Sectors = ((Offset + Length - 1) / (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum)) - (Offset / (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum)) + 1;
  328. TempBase = gIndex.Base;
  329. //if Offset >= gOneFlashSize,modify base
  330. if(0 < (Offset / gFlashInfo[gIndex.InfIndex].SingleChipSize))
  331. {
  332. TempBase += gFlashInfo[gIndex.InfIndex].SingleChipSize * (Offset/gFlashInfo[gIndex.InfIndex].SingleChipSize);
  333. Offset = Offset - (Offset & gFlashInfo[gIndex.InfIndex].SingleChipSize);
  334. }
  335. for (Loop = 0; Loop <= Sectors; Loop ++)
  336. {
  337. TempLength = gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum - (Offset % (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum));
  338. if (TempLength > Length)
  339. {
  340. TempLength = Length;
  341. }
  342. Status = FlashSectorErase(TempBase, Offset, TempLength);
  343. if (EFI_ERROR(Status))
  344. {
  345. DEBUG ((EFI_D_ERROR, "[%a]:[%dL]: FlashErase One Sector Error, Status = %r!\n", __FUNCTION__,__LINE__,Status));
  346. return Status;
  347. }
  348. Offset += TempLength;
  349. //if Offset >= gOneFlashSize,modify base
  350. if (0 < (Offset / gFlashInfo[gIndex.InfIndex].SingleChipSize))
  351. {
  352. TempBase += gFlashInfo[gIndex.InfIndex].SingleChipSize;
  353. Offset = 0;
  354. }
  355. Length -= TempLength;
  356. }
  357. return Status;
  358. }
  359. EFI_STATUS
  360. EFIAPI Write(
  361. IN UNI_NOR_FLASH_PROTOCOL *This,
  362. IN UINT32 Offset,
  363. IN UINT8 *Buffer,
  364. UINT32 ulLength
  365. )
  366. {
  367. EFI_STATUS Status;
  368. UINT32 TempLength;
  369. UINT32 TempBase;
  370. UINT32 Loop;
  371. UINT32 Sectors;
  372. if((Offset + ulLength) > (gFlashInfo[gIndex.InfIndex].SingleChipSize * gFlashInfo[gIndex.InfIndex].ParallelNum))
  373. {
  374. DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Exceed the Flash Size!\n", __FUNCTION__,__LINE__));
  375. return EFI_INVALID_PARAMETER;
  376. }
  377. if (0 == ulLength)
  378. {
  379. return EFI_SUCCESS;
  380. }
  381. Sectors = ((Offset + ulLength - 1) / (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum)) - (Offset / (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum)) + 1;
  382. TempBase = gIndex.Base;
  383. //if Offset >= gOneFlashSize,modify base
  384. if(0 < (Offset / gFlashInfo[gIndex.InfIndex].SingleChipSize))
  385. {
  386. TempBase += gFlashInfo[gIndex.InfIndex].SingleChipSize * (Offset/gFlashInfo[gIndex.InfIndex].SingleChipSize);
  387. Offset = Offset - (Offset & gFlashInfo[gIndex.InfIndex].SingleChipSize);
  388. }
  389. for (Loop = 0; Loop <= Sectors; Loop ++)
  390. {
  391. TempLength = gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum - (Offset % (gFlashInfo[gIndex.InfIndex].BlockSize * gFlashInfo[gIndex.InfIndex].ParallelNum));
  392. if (TempLength > ulLength)
  393. {
  394. TempLength = ulLength;
  395. }
  396. if (TRUE == IsNeedToWrite(TempBase, Offset, Buffer, TempLength))
  397. {
  398. Status = FlashSectorErase(TempBase, Offset, TempLength);
  399. if (EFI_ERROR(Status))
  400. {
  401. DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:FlashErase One Sector Error, Status = %r!\n", __FUNCTION__,__LINE__,Status));
  402. return Status;
  403. }
  404. Status = WriteAfterErase(TempBase, Offset, Buffer, TempLength);
  405. if (EFI_ERROR(Status))
  406. {
  407. DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:WriteAfterErase Status = %r!\n", __FUNCTION__,__LINE__,Status));
  408. return Status;
  409. }
  410. }
  411. Offset += TempLength;
  412. Buffer += TempLength;
  413. //if Offset >= gOneFlashSize,modify base
  414. if (0 < (Offset / gFlashInfo[gIndex.InfIndex].SingleChipSize))
  415. {
  416. TempBase += gFlashInfo[gIndex.InfIndex].SingleChipSize;
  417. Offset = 0;
  418. }
  419. ulLength -= TempLength;
  420. }
  421. return EFI_SUCCESS;
  422. }
  423. VOID SetFlashAttributeToUncache(VOID)
  424. {
  425. EFI_CPU_ARCH_PROTOCOL *gCpu = NULL;
  426. EFI_STATUS Status;
  427. Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&gCpu);
  428. if (EFI_ERROR(Status))
  429. {
  430. DEBUG((EFI_D_ERROR, "LocateProtocol gEfiCpuArchProtocolGuid Status = %r !\n", Status));
  431. }
  432. Status = gCpu->SetMemoryAttributes(
  433. gCpu,
  434. PcdGet64(PcdNORFlashBase),
  435. PcdGet32(PcdNORFlashCachableSize),
  436. EFI_MEMORY_UC
  437. );
  438. if (EFI_ERROR(Status))
  439. {
  440. DEBUG((EFI_D_ERROR, "gCpu->SetMemoryAttributes Status = %r !\n", Status));
  441. }
  442. }
  443. EFI_STATUS
  444. EFIAPI InitializeFlash (
  445. IN EFI_HANDLE ImageHandle,
  446. IN EFI_SYSTEM_TABLE *SystemTable)
  447. {
  448. EFI_STATUS Status;
  449. gIndex.Base = (UINT32)PcdGet64(PcdNORFlashBase);
  450. SetFlashAttributeToUncache();
  451. Status = FlashInit(gIndex.Base);
  452. if (EFI_ERROR(Status))
  453. {
  454. DEBUG((EFI_D_ERROR, "Init Flash Error !\n"));
  455. return Status;
  456. }
  457. else
  458. {
  459. DEBUG((EFI_D_ERROR, "Init Flash OK!\n"));
  460. }
  461. Status = gBS->InstallProtocolInterface (
  462. &ImageHandle,
  463. &gUniNorFlashProtocolGuid,
  464. EFI_NATIVE_INTERFACE,
  465. &gUniNorFlash);
  466. if(EFI_SUCCESS != Status)
  467. {
  468. DEBUG ((EFI_D_ERROR, "[%a]:[%dL]:Install Protocol Interface %r!\n", __FUNCTION__,__LINE__,Status));
  469. }
  470. return Status;
  471. }