2 OVMF support for QEMU system firmware flash device
4 Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include <Library/BaseMemoryLib.h>
11 #include <Library/DebugLib.h>
12 #include <Library/PcdLib.h>
14 #include "QemuFlash.h"
16 #define WRITE_BYTE_CMD 0x10
17 #define BLOCK_ERASE_CMD 0x20
18 #define CLEAR_STATUS_CMD 0x50
19 #define READ_STATUS_CMD 0x70
20 #define READ_DEVID_CMD 0x90
21 #define BLOCK_ERASE_CONFIRM_CMD 0xd0
22 #define READ_ARRAY_CMD 0xff
24 #define CLEARED_ARRAY_STATUS 0x00
29 STATIC UINTN mFdBlockSize
= 0;
30 STATIC UINTN mFdBlockCount
= 0;
39 return mFlashBase
+ ((UINTN
)Lba
* mFdBlockSize
) + Offset
;
44 Determines if the QEMU flash memory device is present.
46 @retval FALSE The QEMU flash device is not present.
47 @retval TRUE The QEMU flash device is present.
56 BOOLEAN FlashDetected
;
63 FlashDetected
= FALSE
;
64 Ptr
= QemuFlashPtr (0, 0);
66 for (Offset
= 0; Offset
< mFdBlockSize
; Offset
++) {
67 Ptr
= QemuFlashPtr (0, Offset
);
69 if (ProbeUint8
!= CLEAR_STATUS_CMD
&&
70 ProbeUint8
!= READ_STATUS_CMD
&&
71 ProbeUint8
!= CLEARED_ARRAY_STATUS
) {
76 if (Offset
>= mFdBlockSize
) {
77 DEBUG ((EFI_D_INFO
, "QEMU Flash: Failed to find probe location\n"));
81 DEBUG ((EFI_D_INFO
, "QEMU Flash: Attempting flash detection at %p\n", Ptr
));
84 *Ptr
= CLEAR_STATUS_CMD
;
86 if (OriginalUint8
!= CLEAR_STATUS_CMD
&&
87 ProbeUint8
== CLEAR_STATUS_CMD
) {
88 DEBUG ((EFI_D_INFO
, "QemuFlashDetected => FD behaves as RAM\n"));
91 *Ptr
= READ_STATUS_CMD
;
93 if (ProbeUint8
== OriginalUint8
) {
94 DEBUG ((EFI_D_INFO
, "QemuFlashDetected => FD behaves as ROM\n"));
95 } else if (ProbeUint8
== READ_STATUS_CMD
) {
96 DEBUG ((EFI_D_INFO
, "QemuFlashDetected => FD behaves as RAM\n"));
98 } else if (ProbeUint8
== CLEARED_ARRAY_STATUS
) {
99 DEBUG ((EFI_D_INFO
, "QemuFlashDetected => FD behaves as FLASH\n"));
100 FlashDetected
= TRUE
;
101 *Ptr
= READ_ARRAY_CMD
;
105 DEBUG ((EFI_D_INFO
, "QemuFlashDetected => %a\n",
106 FlashDetected
? "Yes" : "No"));
107 return FlashDetected
;
114 @param[in] Lba The starting logical block index to read from.
115 @param[in] Offset Offset into the block at which to begin reading.
116 @param[in] NumBytes On input, indicates the requested read size. On
117 output, indicates the actual number of bytes read
118 @param[in] Buffer Pointer to the buffer to read into.
132 // Only write to the first 64k. We don't bother saving the FTW Spare
133 // block into the flash memory.
135 if (Lba
>= mFdBlockCount
) {
136 return EFI_INVALID_PARAMETER
;
142 Ptr
= (UINT8
*) QemuFlashPtr (Lba
, Offset
);
144 CopyMem (Buffer
, Ptr
, *NumBytes
);
153 @param[in] Lba The starting logical block index to write to.
154 @param[in] Offset Offset into the block at which to begin writing.
155 @param[in] NumBytes On input, indicates the requested write size. On
156 output, indicates the actual number of bytes written
157 @param[in] Buffer Pointer to the data to write.
172 // Only write to the first 64k. We don't bother saving the FTW Spare
173 // block into the flash memory.
175 if (Lba
>= mFdBlockCount
) {
176 return EFI_INVALID_PARAMETER
;
182 Ptr
= QemuFlashPtr (Lba
, Offset
);
183 for (Loop
= 0; Loop
< *NumBytes
; Loop
++) {
184 *Ptr
= WRITE_BYTE_CMD
;
190 // Restore flash to read mode
193 *(Ptr
- 1) = READ_ARRAY_CMD
;
201 Erase a QEMU Flash block
203 @param Lba The logical block index to erase.
207 QemuFlashEraseBlock (
213 if (Lba
>= mFdBlockCount
) {
214 return EFI_INVALID_PARAMETER
;
217 Ptr
= QemuFlashPtr (Lba
, 0);
218 *Ptr
= BLOCK_ERASE_CMD
;
219 *Ptr
= BLOCK_ERASE_CONFIRM_CMD
;
225 Initializes QEMU flash memory support
227 @retval EFI_WRITE_PROTECTED The QEMU flash device is not present.
228 @retval EFI_SUCCESS The QEMU flash device is supported.
232 QemuFlashInitialize (
236 mFlashBase
= (UINT8
*)(UINTN
) PcdGet32 (PcdOvmfFdBaseAddress
);
237 mFdBlockSize
= PcdGet32 (PcdOvmfFirmwareBlockSize
);
238 ASSERT(PcdGet32 (PcdOvmfFirmwareFdSize
) % mFdBlockSize
== 0);
239 mFdBlockCount
= PcdGet32 (PcdOvmfFirmwareFdSize
) / mFdBlockSize
;
242 // execute module specific hooks before probing the flash
244 QemuFlashBeforeProbe (
245 (EFI_PHYSICAL_ADDRESS
)(UINTN
) mFlashBase
,
250 if (!QemuFlashDetected ()) {
251 ASSERT (!FeaturePcdGet (PcdSmmSmramRequire
));
252 return EFI_WRITE_PROTECTED
;