]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.c
OvmfPkg: QemuFlashFvbServicesRuntimeDxe: rewrap source code to 79 chars
[mirror_edk2.git] / OvmfPkg / QemuFlashFvbServicesRuntimeDxe / QemuFlash.c
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 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
10
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.
13
14 **/
15
16 #include "PiDxe.h"
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>
23
24 #include "QemuFlash.h"
25
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
33
34 #define CLEARED_ARRAY_STATUS 0x00
35
36
37 STATIC UINT8 *mFlashBase = NULL;
38 STATIC UINTN mFdBlockSize = 0;
39 STATIC UINTN mFdBlockCount = 0;
40
41
42 VOID
43 QemuFlashConvertPointers (
44 VOID
45 )
46 {
47 EfiConvertPointer (0x0, (VOID **) &mFlashBase);
48 }
49
50
51 STATIC
52 volatile UINT8*
53 QemuFlashPtr (
54 IN EFI_LBA Lba,
55 IN UINTN Offset
56 )
57 {
58 return mFlashBase + ((UINTN)Lba * mFdBlockSize) + Offset;
59 }
60
61
62 /**
63 Determines if the QEMU flash memory device is present.
64
65 @retval FALSE The QEMU flash device is not present.
66 @retval TRUE The QEMU flash device is present.
67
68 **/
69 STATIC
70 BOOLEAN
71 QemuFlashDetected (
72 VOID
73 )
74 {
75 BOOLEAN FlashDetected;
76 volatile UINT8 *Ptr;
77
78 UINTN Offset;
79 UINT8 OriginalUint8;
80 UINT8 ProbeUint8;
81
82 FlashDetected = FALSE;
83 Ptr = QemuFlashPtr (0, 0);
84
85 for (Offset = 0; Offset < mFdBlockSize; Offset++) {
86 Ptr = QemuFlashPtr (0, Offset);
87 ProbeUint8 = *Ptr;
88 if (ProbeUint8 != CLEAR_STATUS_CMD &&
89 ProbeUint8 != READ_STATUS_CMD &&
90 ProbeUint8 != CLEARED_ARRAY_STATUS) {
91 break;
92 }
93 }
94
95 if (Offset >= mFdBlockSize) {
96 DEBUG ((EFI_D_INFO, "QEMU Flash: Failed to find probe location\n"));
97 return FALSE;
98 }
99
100 DEBUG ((EFI_D_INFO, "QEMU Flash: Attempting flash detection at %p\n", Ptr));
101
102 OriginalUint8 = *Ptr;
103 *Ptr = CLEAR_STATUS_CMD;
104 ProbeUint8 = *Ptr;
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;
109 } else {
110 *Ptr = READ_STATUS_CMD;
111 ProbeUint8 = *Ptr;
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;
121 }
122 }
123
124 DEBUG ((EFI_D_INFO, "QemuFlashDetected => %a\n",
125 FlashDetected ? "Yes" : "No"));
126 return FlashDetected;
127 }
128
129
130 /**
131 Read from QEMU Flash
132
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.
138
139 **/
140 EFI_STATUS
141 QemuFlashRead (
142 IN EFI_LBA Lba,
143 IN UINTN Offset,
144 IN UINTN *NumBytes,
145 IN UINT8 *Buffer
146 )
147 {
148 UINT8 *Ptr;
149
150 //
151 // Only write to the first 64k. We don't bother saving the FTW Spare
152 // block into the flash memory.
153 //
154 if (Lba >= mFdBlockCount) {
155 return EFI_INVALID_PARAMETER;
156 }
157
158 //
159 // Get flash address
160 //
161 Ptr = (UINT8*) QemuFlashPtr (Lba, Offset);
162
163 CopyMem (Buffer, Ptr, *NumBytes);
164
165 return EFI_SUCCESS;
166 }
167
168
169 /**
170 Write to QEMU Flash
171
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.
177
178 **/
179 EFI_STATUS
180 QemuFlashWrite (
181 IN EFI_LBA Lba,
182 IN UINTN Offset,
183 IN UINTN *NumBytes,
184 IN UINT8 *Buffer
185 )
186 {
187 volatile UINT8 *Ptr;
188 UINTN Loop;
189
190 //
191 // Only write to the first 64k. We don't bother saving the FTW Spare
192 // block into the flash memory.
193 //
194 if (Lba >= mFdBlockCount) {
195 return EFI_INVALID_PARAMETER;
196 }
197
198 //
199 // Program flash
200 //
201 Ptr = QemuFlashPtr (Lba, Offset);
202 for (Loop = 0; Loop < *NumBytes; Loop++) {
203 *Ptr = WRITE_BYTE_CMD;
204 *Ptr = Buffer[Loop];
205 Ptr++;
206 }
207
208 //
209 // Restore flash to read mode
210 //
211 if (*NumBytes > 0) {
212 *(Ptr - 1) = READ_ARRAY_CMD;
213 }
214
215 return EFI_SUCCESS;
216 }
217
218
219 /**
220 Erase a QEMU Flash block
221
222 @param Lba The logical block index to erase.
223
224 **/
225 EFI_STATUS
226 QemuFlashEraseBlock (
227 IN EFI_LBA Lba
228 )
229 {
230 volatile UINT8 *Ptr;
231
232 if (Lba >= mFdBlockCount) {
233 return EFI_INVALID_PARAMETER;
234 }
235
236 Ptr = QemuFlashPtr (Lba, 0);
237 *Ptr = BLOCK_ERASE_CMD;
238 *Ptr = BLOCK_ERASE_CONFIRM_CMD;
239 return EFI_SUCCESS;
240 }
241
242
243 /**
244 Initializes QEMU flash memory support
245
246 @retval EFI_WRITE_PROTECTED The QEMU flash device is not present.
247 @retval EFI_SUCCESS The QEMU flash device is supported.
248
249 **/
250 EFI_STATUS
251 QemuFlashInitialize (
252 VOID
253 )
254 {
255 mFlashBase = (UINT8*)(UINTN) PcdGet32 (PcdOvmfFdBaseAddress);
256 mFdBlockSize = PcdGet32 (PcdOvmfFirmwareBlockSize);
257 ASSERT(PcdGet32 (PcdOvmfFirmwareFdSize) % mFdBlockSize == 0);
258 mFdBlockCount = PcdGet32 (PcdOvmfFirmwareFdSize) / mFdBlockSize;
259
260 if (!QemuFlashDetected ()) {
261 return EFI_WRITE_PROTECTED;
262 }
263
264 return EFI_SUCCESS;
265 }
266