]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.c
OvmfPkg: replace old EFI_D_ debug levels with new DEBUG_ ones
[mirror_edk2.git] / OvmfPkg / QemuFlashFvbServicesRuntimeDxe / QemuFlash.c
CommitLineData
a4ce9ffd
JJ
1/** @file\r
2 OVMF support for QEMU system firmware flash device\r
3\r
4 Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>\r
ea0d111e 5\r
b26f0cf9 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
a4ce9ffd
JJ
7\r
8**/\r
9\r
a4ce9ffd 10#include <Library/BaseMemoryLib.h>\r
0f2eb31c 11#include <Library/DebugLib.h>\r
a4ce9ffd 12#include <Library/PcdLib.h>\r
a4ce9ffd
JJ
13\r
14#include "QemuFlash.h"\r
15\r
16#define WRITE_BYTE_CMD 0x10\r
17#define BLOCK_ERASE_CMD 0x20\r
18#define CLEAR_STATUS_CMD 0x50\r
19#define READ_STATUS_CMD 0x70\r
20#define READ_DEVID_CMD 0x90\r
21#define BLOCK_ERASE_CONFIRM_CMD 0xd0\r
22#define READ_ARRAY_CMD 0xff\r
23\r
24#define CLEARED_ARRAY_STATUS 0x00\r
25\r
26\r
1767877a
LE
27UINT8 *mFlashBase;\r
28\r
a4ce9ffd
JJ
29STATIC UINTN mFdBlockSize = 0;\r
30STATIC UINTN mFdBlockCount = 0;\r
31\r
a4ce9ffd
JJ
32STATIC\r
33volatile UINT8*\r
34QemuFlashPtr (\r
35 IN EFI_LBA Lba,\r
36 IN UINTN Offset\r
37 )\r
38{\r
f7e899c7 39 return mFlashBase + ((UINTN)Lba * mFdBlockSize) + Offset;\r
a4ce9ffd
JJ
40}\r
41\r
42\r
43/**\r
44 Determines if the QEMU flash memory device is present.\r
45\r
46 @retval FALSE The QEMU flash device is not present.\r
47 @retval TRUE The QEMU flash device is present.\r
48\r
49**/\r
50STATIC\r
51BOOLEAN\r
52QemuFlashDetected (\r
53 VOID\r
54 )\r
55{\r
56 BOOLEAN FlashDetected;\r
57 volatile UINT8 *Ptr;\r
58\r
59 UINTN Offset;\r
60 UINT8 OriginalUint8;\r
61 UINT8 ProbeUint8;\r
62\r
63 FlashDetected = FALSE;\r
64 Ptr = QemuFlashPtr (0, 0);\r
65\r
66 for (Offset = 0; Offset < mFdBlockSize; Offset++) {\r
67 Ptr = QemuFlashPtr (0, Offset);\r
68 ProbeUint8 = *Ptr;\r
69 if (ProbeUint8 != CLEAR_STATUS_CMD &&\r
70 ProbeUint8 != READ_STATUS_CMD &&\r
71 ProbeUint8 != CLEARED_ARRAY_STATUS) {\r
72 break;\r
73 }\r
74 }\r
75\r
76 if (Offset >= mFdBlockSize) {\r
70d5086c 77 DEBUG ((DEBUG_INFO, "QEMU Flash: Failed to find probe location\n"));\r
a4ce9ffd
JJ
78 return FALSE;\r
79 }\r
80\r
70d5086c 81 DEBUG ((DEBUG_INFO, "QEMU Flash: Attempting flash detection at %p\n", Ptr));\r
a4ce9ffd
JJ
82\r
83 OriginalUint8 = *Ptr;\r
84 *Ptr = CLEAR_STATUS_CMD;\r
85 ProbeUint8 = *Ptr;\r
86 if (OriginalUint8 != CLEAR_STATUS_CMD &&\r
87 ProbeUint8 == CLEAR_STATUS_CMD) {\r
70d5086c 88 DEBUG ((DEBUG_INFO, "QemuFlashDetected => FD behaves as RAM\n"));\r
a4ce9ffd
JJ
89 *Ptr = OriginalUint8;\r
90 } else {\r
91 *Ptr = READ_STATUS_CMD;\r
92 ProbeUint8 = *Ptr;\r
93 if (ProbeUint8 == OriginalUint8) {\r
70d5086c 94 DEBUG ((DEBUG_INFO, "QemuFlashDetected => FD behaves as ROM\n"));\r
a4ce9ffd 95 } else if (ProbeUint8 == READ_STATUS_CMD) {\r
70d5086c 96 DEBUG ((DEBUG_INFO, "QemuFlashDetected => FD behaves as RAM\n"));\r
a4ce9ffd
JJ
97 *Ptr = OriginalUint8;\r
98 } else if (ProbeUint8 == CLEARED_ARRAY_STATUS) {\r
70d5086c 99 DEBUG ((DEBUG_INFO, "QemuFlashDetected => FD behaves as FLASH\n"));\r
a4ce9ffd
JJ
100 FlashDetected = TRUE;\r
101 *Ptr = READ_ARRAY_CMD;\r
102 }\r
103 }\r
104\r
70d5086c 105 DEBUG ((DEBUG_INFO, "QemuFlashDetected => %a\n",\r
a4ce9ffd
JJ
106 FlashDetected ? "Yes" : "No"));\r
107 return FlashDetected;\r
108}\r
109\r
110\r
111/**\r
112 Read from QEMU Flash\r
113\r
114 @param[in] Lba The starting logical block index to read from.\r
115 @param[in] Offset Offset into the block at which to begin reading.\r
116 @param[in] NumBytes On input, indicates the requested read size. On\r
117 output, indicates the actual number of bytes read\r
118 @param[in] Buffer Pointer to the buffer to read into.\r
119\r
120**/\r
121EFI_STATUS\r
122QemuFlashRead (\r
123 IN EFI_LBA Lba,\r
124 IN UINTN Offset,\r
125 IN UINTN *NumBytes,\r
126 IN UINT8 *Buffer\r
127 )\r
128{\r
129 UINT8 *Ptr;\r
130\r
131 //\r
132 // Only write to the first 64k. We don't bother saving the FTW Spare\r
133 // block into the flash memory.\r
134 //\r
135 if (Lba >= mFdBlockCount) {\r
136 return EFI_INVALID_PARAMETER;\r
137 }\r
138\r
139 //\r
140 // Get flash address\r
141 //\r
142 Ptr = (UINT8*) QemuFlashPtr (Lba, Offset);\r
143\r
144 CopyMem (Buffer, Ptr, *NumBytes);\r
145\r
146 return EFI_SUCCESS;\r
147}\r
148\r
149\r
150/**\r
151 Write to QEMU Flash\r
152\r
153 @param[in] Lba The starting logical block index to write to.\r
154 @param[in] Offset Offset into the block at which to begin writing.\r
155 @param[in] NumBytes On input, indicates the requested write size. On\r
156 output, indicates the actual number of bytes written\r
157 @param[in] Buffer Pointer to the data to write.\r
158\r
159**/\r
160EFI_STATUS\r
161QemuFlashWrite (\r
162 IN EFI_LBA Lba,\r
163 IN UINTN Offset,\r
164 IN UINTN *NumBytes,\r
165 IN UINT8 *Buffer\r
166 )\r
167{\r
168 volatile UINT8 *Ptr;\r
169 UINTN Loop;\r
170\r
171 //\r
172 // Only write to the first 64k. We don't bother saving the FTW Spare\r
173 // block into the flash memory.\r
174 //\r
175 if (Lba >= mFdBlockCount) {\r
176 return EFI_INVALID_PARAMETER;\r
177 }\r
178\r
179 //\r
180 // Program flash\r
181 //\r
182 Ptr = QemuFlashPtr (Lba, Offset);\r
183 for (Loop = 0; Loop < *NumBytes; Loop++) {\r
184 *Ptr = WRITE_BYTE_CMD;\r
185 *Ptr = Buffer[Loop];\r
186 Ptr++;\r
187 }\r
188\r
189 //\r
190 // Restore flash to read mode\r
191 //\r
192 if (*NumBytes > 0) {\r
06f1982a 193 *(Ptr - 1) = READ_ARRAY_CMD;\r
a4ce9ffd
JJ
194 }\r
195\r
196 return EFI_SUCCESS;\r
197}\r
198\r
199\r
200/**\r
201 Erase a QEMU Flash block\r
202\r
203 @param Lba The logical block index to erase.\r
204\r
205**/\r
206EFI_STATUS\r
207QemuFlashEraseBlock (\r
208 IN EFI_LBA Lba\r
209 )\r
210{\r
211 volatile UINT8 *Ptr;\r
212\r
213 if (Lba >= mFdBlockCount) {\r
214 return EFI_INVALID_PARAMETER;\r
215 }\r
216\r
217 Ptr = QemuFlashPtr (Lba, 0);\r
218 *Ptr = BLOCK_ERASE_CMD;\r
219 *Ptr = BLOCK_ERASE_CONFIRM_CMD;\r
220 return EFI_SUCCESS;\r
221}\r
222\r
223\r
224/**\r
225 Initializes QEMU flash memory support\r
226\r
227 @retval EFI_WRITE_PROTECTED The QEMU flash device is not present.\r
228 @retval EFI_SUCCESS The QEMU flash device is supported.\r
229\r
230**/\r
231EFI_STATUS\r
232QemuFlashInitialize (\r
233 VOID\r
234 )\r
235{\r
236 mFlashBase = (UINT8*)(UINTN) PcdGet32 (PcdOvmfFdBaseAddress);\r
237 mFdBlockSize = PcdGet32 (PcdOvmfFirmwareBlockSize);\r
238 ASSERT(PcdGet32 (PcdOvmfFirmwareFdSize) % mFdBlockSize == 0);\r
239 mFdBlockCount = PcdGet32 (PcdOvmfFirmwareFdSize) / mFdBlockSize;\r
240\r
e4a1d5a7
BS
241 //\r
242 // execute module specific hooks before probing the flash\r
243 //\r
244 QemuFlashBeforeProbe (\r
245 (EFI_PHYSICAL_ADDRESS)(UINTN) mFlashBase,\r
246 mFdBlockSize,\r
247 mFdBlockCount\r
248 );\r
249\r
a4ce9ffd 250 if (!QemuFlashDetected ()) {\r
b963ec49 251 ASSERT (!FeaturePcdGet (PcdSmmSmramRequire));\r
a4ce9ffd
JJ
252 return EFI_WRITE_PROTECTED;\r
253 }\r
254\r
255 return EFI_SUCCESS;\r
256}\r
257\r