2 OVMF support for QEMU system firmware flash device
4 Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials are licensed and made available
7 under the terms and conditions of the BSD License which accompanies this
8 distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
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.
16 #include <Library/BaseMemoryLib.h>
17 #include <Library/DebugLib.h>
18 #include <Library/PcdLib.h>
20 #include "QemuFlash.h"
22 #define WRITE_BYTE_CMD 0x10
23 #define BLOCK_ERASE_CMD 0x20
24 #define CLEAR_STATUS_CMD 0x50
25 #define READ_STATUS_CMD 0x70
26 #define READ_DEVID_CMD 0x90
27 #define BLOCK_ERASE_CONFIRM_CMD 0xd0
28 #define READ_ARRAY_CMD 0xff
30 #define CLEARED_ARRAY_STATUS 0x00
35 STATIC UINTN mFdBlockSize
= 0;
36 STATIC UINTN mFdBlockCount
= 0;
45 return mFlashBase
+ ((UINTN
)Lba
* mFdBlockSize
) + Offset
;
50 Determines if the QEMU flash memory device is present.
52 @retval FALSE The QEMU flash device is not present.
53 @retval TRUE The QEMU flash device is present.
62 BOOLEAN FlashDetected
;
69 FlashDetected
= FALSE
;
70 Ptr
= QemuFlashPtr (0, 0);
72 for (Offset
= 0; Offset
< mFdBlockSize
; Offset
++) {
73 Ptr
= QemuFlashPtr (0, Offset
);
75 if (ProbeUint8
!= CLEAR_STATUS_CMD
&&
76 ProbeUint8
!= READ_STATUS_CMD
&&
77 ProbeUint8
!= CLEARED_ARRAY_STATUS
) {
82 if (Offset
>= mFdBlockSize
) {
83 DEBUG ((EFI_D_INFO
, "QEMU Flash: Failed to find probe location\n"));
87 DEBUG ((EFI_D_INFO
, "QEMU Flash: Attempting flash detection at %p\n", Ptr
));
90 *Ptr
= CLEAR_STATUS_CMD
;
92 if (OriginalUint8
!= CLEAR_STATUS_CMD
&&
93 ProbeUint8
== CLEAR_STATUS_CMD
) {
94 DEBUG ((EFI_D_INFO
, "QemuFlashDetected => FD behaves as RAM\n"));
97 *Ptr
= READ_STATUS_CMD
;
99 if (ProbeUint8
== OriginalUint8
) {
100 DEBUG ((EFI_D_INFO
, "QemuFlashDetected => FD behaves as ROM\n"));
101 } else if (ProbeUint8
== READ_STATUS_CMD
) {
102 DEBUG ((EFI_D_INFO
, "QemuFlashDetected => FD behaves as RAM\n"));
103 *Ptr
= OriginalUint8
;
104 } else if (ProbeUint8
== CLEARED_ARRAY_STATUS
) {
105 DEBUG ((EFI_D_INFO
, "QemuFlashDetected => FD behaves as FLASH\n"));
106 FlashDetected
= TRUE
;
107 *Ptr
= READ_ARRAY_CMD
;
111 DEBUG ((EFI_D_INFO
, "QemuFlashDetected => %a\n",
112 FlashDetected
? "Yes" : "No"));
113 return FlashDetected
;
120 @param[in] Lba The starting logical block index to read from.
121 @param[in] Offset Offset into the block at which to begin reading.
122 @param[in] NumBytes On input, indicates the requested read size. On
123 output, indicates the actual number of bytes read
124 @param[in] Buffer Pointer to the buffer to read into.
138 // Only write to the first 64k. We don't bother saving the FTW Spare
139 // block into the flash memory.
141 if (Lba
>= mFdBlockCount
) {
142 return EFI_INVALID_PARAMETER
;
148 Ptr
= (UINT8
*) QemuFlashPtr (Lba
, Offset
);
150 CopyMem (Buffer
, Ptr
, *NumBytes
);
159 @param[in] Lba The starting logical block index to write to.
160 @param[in] Offset Offset into the block at which to begin writing.
161 @param[in] NumBytes On input, indicates the requested write size. On
162 output, indicates the actual number of bytes written
163 @param[in] Buffer Pointer to the data to write.
178 // Only write to the first 64k. We don't bother saving the FTW Spare
179 // block into the flash memory.
181 if (Lba
>= mFdBlockCount
) {
182 return EFI_INVALID_PARAMETER
;
188 Ptr
= QemuFlashPtr (Lba
, Offset
);
189 for (Loop
= 0; Loop
< *NumBytes
; Loop
++) {
190 *Ptr
= WRITE_BYTE_CMD
;
196 // Restore flash to read mode
199 *(Ptr
- 1) = READ_ARRAY_CMD
;
207 Erase a QEMU Flash block
209 @param Lba The logical block index to erase.
213 QemuFlashEraseBlock (
219 if (Lba
>= mFdBlockCount
) {
220 return EFI_INVALID_PARAMETER
;
223 Ptr
= QemuFlashPtr (Lba
, 0);
224 *Ptr
= BLOCK_ERASE_CMD
;
225 *Ptr
= BLOCK_ERASE_CONFIRM_CMD
;
231 Initializes QEMU flash memory support
233 @retval EFI_WRITE_PROTECTED The QEMU flash device is not present.
234 @retval EFI_SUCCESS The QEMU flash device is supported.
238 QemuFlashInitialize (
242 mFlashBase
= (UINT8
*)(UINTN
) PcdGet32 (PcdOvmfFdBaseAddress
);
243 mFdBlockSize
= PcdGet32 (PcdOvmfFirmwareBlockSize
);
244 ASSERT(PcdGet32 (PcdOvmfFirmwareFdSize
) % mFdBlockSize
== 0);
245 mFdBlockCount
= PcdGet32 (PcdOvmfFirmwareFdSize
) / mFdBlockSize
;
247 if (!QemuFlashDetected ()) {
248 ASSERT (!FeaturePcdGet (PcdSmmSmramRequire
));
249 return EFI_WRITE_PROTECTED
;