QemuFlash.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. /** @file
  2. OVMF support for QEMU system firmware flash device
  3. Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include <Library/BaseMemoryLib.h>
  7. #include <Library/DebugLib.h>
  8. #include <Library/MemEncryptSevLib.h>
  9. #include <Library/PcdLib.h>
  10. #include "QemuFlash.h"
  11. #define WRITE_BYTE_CMD 0x10
  12. #define BLOCK_ERASE_CMD 0x20
  13. #define CLEAR_STATUS_CMD 0x50
  14. #define READ_STATUS_CMD 0x70
  15. #define READ_DEVID_CMD 0x90
  16. #define BLOCK_ERASE_CONFIRM_CMD 0xd0
  17. #define READ_ARRAY_CMD 0xff
  18. #define CLEARED_ARRAY_STATUS 0x00
  19. UINT8 *mFlashBase;
  20. STATIC UINTN mFdBlockSize = 0;
  21. STATIC UINTN mFdBlockCount = 0;
  22. STATIC
  23. volatile UINT8 *
  24. QemuFlashPtr (
  25. IN EFI_LBA Lba,
  26. IN UINTN Offset
  27. )
  28. {
  29. return mFlashBase + ((UINTN)Lba * mFdBlockSize) + Offset;
  30. }
  31. /**
  32. Determines if the QEMU flash memory device is present.
  33. @retval FALSE The QEMU flash device is not present.
  34. @retval TRUE The QEMU flash device is present.
  35. **/
  36. STATIC
  37. BOOLEAN
  38. QemuFlashDetected (
  39. VOID
  40. )
  41. {
  42. BOOLEAN FlashDetected;
  43. volatile UINT8 *Ptr;
  44. UINTN Offset;
  45. UINT8 OriginalUint8;
  46. UINT8 ProbeUint8;
  47. FlashDetected = FALSE;
  48. Ptr = QemuFlashPtr (0, 0);
  49. for (Offset = 0; Offset < mFdBlockSize; Offset++) {
  50. Ptr = QemuFlashPtr (0, Offset);
  51. ProbeUint8 = *Ptr;
  52. if ((ProbeUint8 != CLEAR_STATUS_CMD) &&
  53. (ProbeUint8 != READ_STATUS_CMD) &&
  54. (ProbeUint8 != CLEARED_ARRAY_STATUS))
  55. {
  56. break;
  57. }
  58. }
  59. if (Offset >= mFdBlockSize) {
  60. DEBUG ((DEBUG_INFO, "QEMU Flash: Failed to find probe location\n"));
  61. return FALSE;
  62. }
  63. DEBUG ((DEBUG_INFO, "QEMU Flash: Attempting flash detection at %p\n", Ptr));
  64. if (MemEncryptSevEsIsEnabled ()) {
  65. //
  66. // When SEV-ES is enabled, the check below can result in an infinite
  67. // loop with respect to a nested page fault. When the memslot is mapped
  68. // read-only, the nested page table entry is read-only. The check below
  69. // will cause a nested page fault that cannot be emulated, causing
  70. // the instruction to retried over and over. For SEV-ES, acknowledge that
  71. // the FD appears as ROM and not as FLASH, but report FLASH anyway because
  72. // FLASH behavior can be simulated using VMGEXIT.
  73. //
  74. DEBUG ((
  75. DEBUG_INFO,
  76. "QEMU Flash: SEV-ES enabled, assuming FD behaves as FLASH\n"
  77. ));
  78. return TRUE;
  79. }
  80. OriginalUint8 = *Ptr;
  81. *Ptr = CLEAR_STATUS_CMD;
  82. ProbeUint8 = *Ptr;
  83. if ((OriginalUint8 != CLEAR_STATUS_CMD) &&
  84. (ProbeUint8 == CLEAR_STATUS_CMD))
  85. {
  86. DEBUG ((DEBUG_INFO, "QemuFlashDetected => FD behaves as RAM\n"));
  87. *Ptr = OriginalUint8;
  88. } else {
  89. *Ptr = READ_STATUS_CMD;
  90. ProbeUint8 = *Ptr;
  91. if (ProbeUint8 == OriginalUint8) {
  92. DEBUG ((DEBUG_INFO, "QemuFlashDetected => FD behaves as ROM\n"));
  93. } else if (ProbeUint8 == READ_STATUS_CMD) {
  94. DEBUG ((DEBUG_INFO, "QemuFlashDetected => FD behaves as RAM\n"));
  95. *Ptr = OriginalUint8;
  96. } else if (ProbeUint8 == CLEARED_ARRAY_STATUS) {
  97. DEBUG ((DEBUG_INFO, "QemuFlashDetected => FD behaves as FLASH\n"));
  98. FlashDetected = TRUE;
  99. *Ptr = READ_ARRAY_CMD;
  100. }
  101. }
  102. DEBUG ((
  103. DEBUG_INFO,
  104. "QemuFlashDetected => %a\n",
  105. FlashDetected ? "Yes" : "No"
  106. ));
  107. return FlashDetected;
  108. }
  109. /**
  110. Read from QEMU Flash
  111. @param[in] Lba The starting logical block index to read from.
  112. @param[in] Offset Offset into the block at which to begin reading.
  113. @param[in] NumBytes On input, indicates the requested read size. On
  114. output, indicates the actual number of bytes read
  115. @param[in] Buffer Pointer to the buffer to read into.
  116. **/
  117. EFI_STATUS
  118. QemuFlashRead (
  119. IN EFI_LBA Lba,
  120. IN UINTN Offset,
  121. IN UINTN *NumBytes,
  122. IN UINT8 *Buffer
  123. )
  124. {
  125. UINT8 *Ptr;
  126. //
  127. // Only write to the first 64k. We don't bother saving the FTW Spare
  128. // block into the flash memory.
  129. //
  130. if (Lba >= mFdBlockCount) {
  131. return EFI_INVALID_PARAMETER;
  132. }
  133. //
  134. // Get flash address
  135. //
  136. Ptr = (UINT8 *)QemuFlashPtr (Lba, Offset);
  137. CopyMem (Buffer, Ptr, *NumBytes);
  138. return EFI_SUCCESS;
  139. }
  140. /**
  141. Write to QEMU Flash
  142. @param[in] Lba The starting logical block index to write to.
  143. @param[in] Offset Offset into the block at which to begin writing.
  144. @param[in] NumBytes On input, indicates the requested write size. On
  145. output, indicates the actual number of bytes written
  146. @param[in] Buffer Pointer to the data to write.
  147. **/
  148. EFI_STATUS
  149. QemuFlashWrite (
  150. IN EFI_LBA Lba,
  151. IN UINTN Offset,
  152. IN UINTN *NumBytes,
  153. IN UINT8 *Buffer
  154. )
  155. {
  156. volatile UINT8 *Ptr;
  157. UINTN Loop;
  158. //
  159. // Only write to the first 64k. We don't bother saving the FTW Spare
  160. // block into the flash memory.
  161. //
  162. if (Lba >= mFdBlockCount) {
  163. return EFI_INVALID_PARAMETER;
  164. }
  165. //
  166. // Program flash
  167. //
  168. Ptr = QemuFlashPtr (Lba, Offset);
  169. for (Loop = 0; Loop < *NumBytes; Loop++) {
  170. QemuFlashPtrWrite (Ptr, WRITE_BYTE_CMD);
  171. QemuFlashPtrWrite (Ptr, Buffer[Loop]);
  172. Ptr++;
  173. }
  174. //
  175. // Restore flash to read mode
  176. //
  177. if (*NumBytes > 0) {
  178. QemuFlashPtrWrite (Ptr - 1, READ_ARRAY_CMD);
  179. }
  180. return EFI_SUCCESS;
  181. }
  182. /**
  183. Erase a QEMU Flash block
  184. @param Lba The logical block index to erase.
  185. **/
  186. EFI_STATUS
  187. QemuFlashEraseBlock (
  188. IN EFI_LBA Lba
  189. )
  190. {
  191. volatile UINT8 *Ptr;
  192. if (Lba >= mFdBlockCount) {
  193. return EFI_INVALID_PARAMETER;
  194. }
  195. Ptr = QemuFlashPtr (Lba, 0);
  196. QemuFlashPtrWrite (Ptr, BLOCK_ERASE_CMD);
  197. QemuFlashPtrWrite (Ptr, BLOCK_ERASE_CONFIRM_CMD);
  198. return EFI_SUCCESS;
  199. }
  200. /**
  201. Initializes QEMU flash memory support
  202. @retval EFI_WRITE_PROTECTED The QEMU flash device is not present.
  203. @retval EFI_SUCCESS The QEMU flash device is supported.
  204. **/
  205. EFI_STATUS
  206. QemuFlashInitialize (
  207. VOID
  208. )
  209. {
  210. mFlashBase = (UINT8 *)(UINTN)PcdGet32 (PcdOvmfFdBaseAddress);
  211. mFdBlockSize = PcdGet32 (PcdOvmfFirmwareBlockSize);
  212. ASSERT (PcdGet32 (PcdOvmfFirmwareFdSize) % mFdBlockSize == 0);
  213. mFdBlockCount = PcdGet32 (PcdOvmfFirmwareFdSize) / mFdBlockSize;
  214. //
  215. // execute module specific hooks before probing the flash
  216. //
  217. QemuFlashBeforeProbe (
  218. (EFI_PHYSICAL_ADDRESS)(UINTN)mFlashBase,
  219. mFdBlockSize,
  220. mFdBlockCount
  221. );
  222. if (!QemuFlashDetected ()) {
  223. ASSERT (!FeaturePcdGet (PcdSmmSmramRequire));
  224. return EFI_WRITE_PROTECTED;
  225. }
  226. return EFI_SUCCESS;
  227. }