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