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.
17 #include <Library/DebugLib.h>
18 #include <Library/BaseMemoryLib.h>
19 #include <Library/PcdLib.h>
20 #include <Library/UefiBootServicesTableLib.h>
21 #include <Library/UefiRuntimeLib.h>
22 #include <Guid/EventGroup.h>
24 #include "QemuFlash.h"
26 #define WRITE_BYTE_CMD 0x10
27 #define BLOCK_ERASE_CMD 0x20
28 #define CLEAR_STATUS_CMD 0x50
29 #define READ_STATUS_CMD 0x70
30 #define READ_DEVID_CMD 0x90
31 #define BLOCK_ERASE_CONFIRM_CMD 0xd0
32 #define READ_ARRAY_CMD 0xff
34 #define CLEARED_ARRAY_STATUS 0x00
37 STATIC UINT8
*mFlashBase
= NULL
;
38 STATIC UINTN mFdBlockSize
= 0;
39 STATIC UINTN mFdBlockCount
= 0;
43 QemuFlashConvertPointers (
47 EfiConvertPointer (0x0, (VOID
**) &mFlashBase
);
58 return mFlashBase
+ ((UINTN
)Lba
* mFdBlockSize
) + Offset
;
63 Determines if the QEMU flash memory device is present.
65 @retval FALSE The QEMU flash device is not present.
66 @retval TRUE The QEMU flash device is present.
75 BOOLEAN FlashDetected
;
82 FlashDetected
= FALSE
;
83 Ptr
= QemuFlashPtr (0, 0);
85 for (Offset
= 0; Offset
< mFdBlockSize
; Offset
++) {
86 Ptr
= QemuFlashPtr (0, Offset
);
88 if (ProbeUint8
!= CLEAR_STATUS_CMD
&&
89 ProbeUint8
!= READ_STATUS_CMD
&&
90 ProbeUint8
!= CLEARED_ARRAY_STATUS
) {
95 if (Offset
>= mFdBlockSize
) {
96 DEBUG ((EFI_D_INFO
, "QEMU Flash: Failed to find probe location\n"));
100 DEBUG ((EFI_D_INFO
, "QEMU Flash: Attempting flash detection at %p\n", Ptr
));
102 OriginalUint8
= *Ptr
;
103 *Ptr
= CLEAR_STATUS_CMD
;
105 if (OriginalUint8
!= CLEAR_STATUS_CMD
&&
106 ProbeUint8
== CLEAR_STATUS_CMD
) {
107 DEBUG ((EFI_D_INFO
, "QemuFlashDetected => FD behaves as RAM\n"));
108 *Ptr
= OriginalUint8
;
110 *Ptr
= READ_STATUS_CMD
;
112 if (ProbeUint8
== OriginalUint8
) {
113 DEBUG ((EFI_D_INFO
, "QemuFlashDetected => FD behaves as ROM\n"));
114 } else if (ProbeUint8
== READ_STATUS_CMD
) {
115 DEBUG ((EFI_D_INFO
, "QemuFlashDetected => FD behaves as RAM\n"));
116 *Ptr
= OriginalUint8
;
117 } else if (ProbeUint8
== CLEARED_ARRAY_STATUS
) {
118 DEBUG ((EFI_D_INFO
, "QemuFlashDetected => FD behaves as FLASH\n"));
119 FlashDetected
= TRUE
;
120 *Ptr
= READ_ARRAY_CMD
;
124 DEBUG ((EFI_D_INFO
, "QemuFlashDetected => %a\n",
125 FlashDetected
? "Yes" : "No"));
126 return FlashDetected
;
133 @param[in] Lba The starting logical block index to read from.
134 @param[in] Offset Offset into the block at which to begin reading.
135 @param[in] NumBytes On input, indicates the requested read size. On
136 output, indicates the actual number of bytes read
137 @param[in] Buffer Pointer to the buffer to read into.
151 // Only write to the first 64k. We don't bother saving the FTW Spare
152 // block into the flash memory.
154 if (Lba
>= mFdBlockCount
) {
155 return EFI_INVALID_PARAMETER
;
161 Ptr
= (UINT8
*) QemuFlashPtr (Lba
, Offset
);
163 CopyMem (Buffer
, Ptr
, *NumBytes
);
172 @param[in] Lba The starting logical block index to write to.
173 @param[in] Offset Offset into the block at which to begin writing.
174 @param[in] NumBytes On input, indicates the requested write size. On
175 output, indicates the actual number of bytes written
176 @param[in] Buffer Pointer to the data to write.
191 // Only write to the first 64k. We don't bother saving the FTW Spare
192 // block into the flash memory.
194 if (Lba
>= mFdBlockCount
) {
195 return EFI_INVALID_PARAMETER
;
201 Ptr
= QemuFlashPtr (Lba
, Offset
);
202 for (Loop
= 0; Loop
< *NumBytes
; Loop
++) {
203 *Ptr
= WRITE_BYTE_CMD
;
209 // Restore flash to read mode
212 *(Ptr
- 1) = READ_ARRAY_CMD
;
220 Erase a QEMU Flash block
222 @param Lba The logical block index to erase.
226 QemuFlashEraseBlock (
232 if (Lba
>= mFdBlockCount
) {
233 return EFI_INVALID_PARAMETER
;
236 Ptr
= QemuFlashPtr (Lba
, 0);
237 *Ptr
= BLOCK_ERASE_CMD
;
238 *Ptr
= BLOCK_ERASE_CONFIRM_CMD
;
244 Initializes QEMU flash memory support
246 @retval EFI_WRITE_PROTECTED The QEMU flash device is not present.
247 @retval EFI_SUCCESS The QEMU flash device is supported.
251 QemuFlashInitialize (
255 mFlashBase
= (UINT8
*)(UINTN
) PcdGet32 (PcdOvmfFdBaseAddress
);
256 mFdBlockSize
= PcdGet32 (PcdOvmfFirmwareBlockSize
);
257 ASSERT(PcdGet32 (PcdOvmfFirmwareFdSize
) % mFdBlockSize
== 0);
258 mFdBlockCount
= PcdGet32 (PcdOvmfFirmwareFdSize
) / mFdBlockSize
;
260 if (!QemuFlashDetected ()) {
261 return EFI_WRITE_PROTECTED
;