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