VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.c@ 81913

Last change on this file since 81913 was 80721, checked in by vboxsync, 6 years ago

Devices/EFI/FirmwareNew: Start upgrade process to edk2-stable201908 (compiles on Windows and works to some extent), bugref:4643

  • Property svn:eol-style set to native
File size: 5.9 KB
Line 
1/** @file
2 OVMF support for QEMU system firmware flash device
3
4 Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8**/
9
10#include <Library/BaseMemoryLib.h>
11#include <Library/DebugLib.h>
12#include <Library/PcdLib.h>
13
14#include "QemuFlash.h"
15
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
23
24#define CLEARED_ARRAY_STATUS 0x00
25
26
27UINT8 *mFlashBase;
28
29STATIC UINTN mFdBlockSize = 0;
30STATIC UINTN mFdBlockCount = 0;
31
32STATIC
33volatile UINT8*
34QemuFlashPtr (
35 IN EFI_LBA Lba,
36 IN UINTN Offset
37 )
38{
39 return mFlashBase + ((UINTN)Lba * mFdBlockSize) + Offset;
40}
41
42
43/**
44 Determines if the QEMU flash memory device is present.
45
46 @retval FALSE The QEMU flash device is not present.
47 @retval TRUE The QEMU flash device is present.
48
49**/
50STATIC
51BOOLEAN
52QemuFlashDetected (
53 VOID
54 )
55{
56 BOOLEAN FlashDetected;
57 volatile UINT8 *Ptr;
58
59 UINTN Offset;
60 UINT8 OriginalUint8;
61 UINT8 ProbeUint8;
62
63 FlashDetected = FALSE;
64 Ptr = QemuFlashPtr (0, 0);
65
66 for (Offset = 0; Offset < mFdBlockSize; Offset++) {
67 Ptr = QemuFlashPtr (0, Offset);
68 ProbeUint8 = *Ptr;
69 if (ProbeUint8 != CLEAR_STATUS_CMD &&
70 ProbeUint8 != READ_STATUS_CMD &&
71 ProbeUint8 != CLEARED_ARRAY_STATUS) {
72 break;
73 }
74 }
75
76 if (Offset >= mFdBlockSize) {
77 DEBUG ((EFI_D_INFO, "QEMU Flash: Failed to find probe location\n"));
78 return FALSE;
79 }
80
81 DEBUG ((EFI_D_INFO, "QEMU Flash: Attempting flash detection at %p\n", Ptr));
82
83 OriginalUint8 = *Ptr;
84 *Ptr = CLEAR_STATUS_CMD;
85 ProbeUint8 = *Ptr;
86 if (OriginalUint8 != CLEAR_STATUS_CMD &&
87 ProbeUint8 == CLEAR_STATUS_CMD) {
88 DEBUG ((EFI_D_INFO, "QemuFlashDetected => FD behaves as RAM\n"));
89 *Ptr = OriginalUint8;
90 } else {
91 *Ptr = READ_STATUS_CMD;
92 ProbeUint8 = *Ptr;
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"));
97 *Ptr = OriginalUint8;
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;
102 }
103 }
104
105 DEBUG ((EFI_D_INFO, "QemuFlashDetected => %a\n",
106 FlashDetected ? "Yes" : "No"));
107 return FlashDetected;
108}
109
110
111/**
112 Read from QEMU Flash
113
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.
119
120**/
121EFI_STATUS
122QemuFlashRead (
123 IN EFI_LBA Lba,
124 IN UINTN Offset,
125 IN UINTN *NumBytes,
126 IN UINT8 *Buffer
127 )
128{
129 UINT8 *Ptr;
130
131 //
132 // Only write to the first 64k. We don't bother saving the FTW Spare
133 // block into the flash memory.
134 //
135 if (Lba >= mFdBlockCount) {
136 return EFI_INVALID_PARAMETER;
137 }
138
139 //
140 // Get flash address
141 //
142 Ptr = (UINT8*) QemuFlashPtr (Lba, Offset);
143
144 CopyMem (Buffer, Ptr, *NumBytes);
145
146 return EFI_SUCCESS;
147}
148
149
150/**
151 Write to QEMU Flash
152
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.
158
159**/
160EFI_STATUS
161QemuFlashWrite (
162 IN EFI_LBA Lba,
163 IN UINTN Offset,
164 IN UINTN *NumBytes,
165 IN UINT8 *Buffer
166 )
167{
168 volatile UINT8 *Ptr;
169 UINTN Loop;
170
171 //
172 // Only write to the first 64k. We don't bother saving the FTW Spare
173 // block into the flash memory.
174 //
175 if (Lba >= mFdBlockCount) {
176 return EFI_INVALID_PARAMETER;
177 }
178
179 //
180 // Program flash
181 //
182 Ptr = QemuFlashPtr (Lba, Offset);
183 for (Loop = 0; Loop < *NumBytes; Loop++) {
184 *Ptr = WRITE_BYTE_CMD;
185 *Ptr = Buffer[Loop];
186 Ptr++;
187 }
188
189 //
190 // Restore flash to read mode
191 //
192 if (*NumBytes > 0) {
193 *(Ptr - 1) = READ_ARRAY_CMD;
194 }
195
196 return EFI_SUCCESS;
197}
198
199
200/**
201 Erase a QEMU Flash block
202
203 @param Lba The logical block index to erase.
204
205**/
206EFI_STATUS
207QemuFlashEraseBlock (
208 IN EFI_LBA Lba
209 )
210{
211 volatile UINT8 *Ptr;
212
213 if (Lba >= mFdBlockCount) {
214 return EFI_INVALID_PARAMETER;
215 }
216
217 Ptr = QemuFlashPtr (Lba, 0);
218 *Ptr = BLOCK_ERASE_CMD;
219 *Ptr = BLOCK_ERASE_CONFIRM_CMD;
220 return EFI_SUCCESS;
221}
222
223
224/**
225 Initializes QEMU flash memory support
226
227 @retval EFI_WRITE_PROTECTED The QEMU flash device is not present.
228 @retval EFI_SUCCESS The QEMU flash device is supported.
229
230**/
231EFI_STATUS
232QemuFlashInitialize (
233 VOID
234 )
235{
236 mFlashBase = (UINT8*)(UINTN) PcdGet32 (PcdOvmfFdBaseAddress);
237 mFdBlockSize = PcdGet32 (PcdOvmfFirmwareBlockSize);
238 ASSERT(PcdGet32 (PcdOvmfFirmwareFdSize) % mFdBlockSize == 0);
239 mFdBlockCount = PcdGet32 (PcdOvmfFirmwareFdSize) / mFdBlockSize;
240
241 //
242 // execute module specific hooks before probing the flash
243 //
244 QemuFlashBeforeProbe (
245 (EFI_PHYSICAL_ADDRESS)(UINTN) mFlashBase,
246 mFdBlockSize,
247 mFdBlockCount
248 );
249
250 if (!QemuFlashDetected ()) {
251 ASSERT (!FeaturePcdGet (PcdSmmSmramRequire));
252 return EFI_WRITE_PROTECTED;
253 }
254
255 return EFI_SUCCESS;
256}
257
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette