]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c
IntelFrameworkPkg/DxeIoLibCpuIo: Add new Fifo routines in IoLib class
[mirror_edk2.git] / OvmfPkg / Library / QemuFwCfgLib / QemuFwCfgLib.c
CommitLineData
f1ec65ba 1/** @file\r
2\r
29874a8c 3 Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>\r
0dc231c9 4 Copyright (C) 2013, Red Hat, Inc.\r
f1ec65ba 5\r
6 This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution. The full text of the license may be found at\r
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
16#include "Uefi.h"\r
17#include <Library/BaseLib.h>\r
18#include <Library/BaseMemoryLib.h>\r
19#include <Library/DebugLib.h>\r
20#include <Library/IoLib.h>\r
21#include <Library/QemuFwCfgLib.h>\r
22#include <Library/MemoryAllocationLib.h>\r
23#include <Library/UefiBootServicesTableLib.h>\r
24\r
5297c0bf
LE
25#include "QemuFwCfgLibInternal.h"\r
26\r
f1ec65ba 27\r
28/**\r
29 Reads an 8-bit I/O port fifo into a block of memory.\r
30\r
31 Reads the 8-bit I/O fifo port specified by Port.\r
32\r
33 The port is read Count times, and the read data is\r
34 stored in the provided Buffer.\r
35\r
36 This function must guarantee that all I/O read and write operations are\r
37 serialized.\r
38\r
39 If 8-bit I/O port operations are not supported, then ASSERT().\r
40\r
41 @param Port The I/O port to read.\r
42 @param Count The number of times to read I/O port.\r
43 @param Buffer The buffer to store the read data into.\r
44\r
45**/\r
46VOID\r
47EFIAPI\r
48IoReadFifo8 (\r
49 IN UINTN Port,\r
50 IN UINTN Count,\r
51 OUT VOID *Buffer\r
52 );\r
53\r
29874a8c 54/**\r
55 Writes an 8-bit I/O port fifo from a block of memory.\r
56\r
57 Writes the 8-bit I/O fifo port specified by Port.\r
58\r
59 The port is written Count times, and the data are obtained\r
60 from the provided Buffer.\r
61\r
62 This function must guarantee that all I/O read and write operations are\r
63 serialized.\r
64\r
65 If 8-bit I/O port operations are not supported, then ASSERT().\r
66\r
67 @param Port The I/O port to read.\r
68 @param Count The number of times to read I/O port.\r
69 @param Buffer The buffer to store the read data into.\r
70\r
71**/\r
72VOID\r
73EFIAPI\r
74IoWriteFifo8 (\r
75 IN UINTN Port,\r
76 IN UINTN Count,\r
77 OUT VOID *Buffer\r
78 );\r
79\r
f1ec65ba 80\r
f1ec65ba 81/**\r
82 Selects a firmware configuration item for reading.\r
83 \r
84 Following this call, any data read from this item will start from\r
85 the beginning of the configuration item's data.\r
86\r
87 @param[in] QemuFwCfgItem - Firmware Configuration item to read\r
88\r
89**/\r
90VOID\r
91EFIAPI\r
92QemuFwCfgSelectItem (\r
93 IN FIRMWARE_CONFIG_ITEM QemuFwCfgItem\r
94 )\r
95{\r
96 DEBUG ((EFI_D_INFO, "Select Item: 0x%x\n", (UINT16)(UINTN) QemuFwCfgItem));\r
97 IoWrite16 (0x510, (UINT16)(UINTN) QemuFwCfgItem);\r
98}\r
99\r
100\r
2c8dcbc6
LE
101/**\r
102 Transfer an array of bytes using the DMA interface.\r
103\r
104 @param[in] Size Size in bytes to transfer.\r
105 @param[in,out] Buffer Buffer to read data into or write data from. May be\r
106 NULL if Size is zero.\r
107 @param[in] Write TRUE if writing to fw_cfg from Buffer, FALSE if\r
108 reading from fw_cfg into Buffer.\r
109**/\r
110VOID\r
111InternalQemuFwCfgDmaBytes (\r
112 IN UINT32 Size,\r
113 IN OUT VOID *Buffer OPTIONAL,\r
114 IN BOOLEAN Write\r
115 )\r
116{\r
117 volatile FW_CFG_DMA_ACCESS Access;\r
118 UINT32 AccessHigh, AccessLow;\r
119 UINT32 Status;\r
120\r
121 if (Size == 0) {\r
122 return;\r
123 }\r
124\r
125 Access.Control = SwapBytes32 (\r
126 Write ? FW_CFG_DMA_CTL_WRITE : FW_CFG_DMA_CTL_READ\r
127 );\r
128 Access.Length = SwapBytes32 (Size);\r
129 Access.Address = SwapBytes64 ((UINTN)Buffer);\r
130\r
131 //\r
132 // Delimit the transfer from (a) modifications to Access, (b) in case of a\r
133 // write, from writes to Buffer by the caller.\r
134 //\r
135 MemoryFence ();\r
136\r
137 //\r
138 // Start the transfer.\r
139 //\r
140 AccessHigh = (UINT32)RShiftU64 ((UINTN)&Access, 32);\r
141 AccessLow = (UINT32)(UINTN)&Access;\r
142 IoWrite32 (0x514, SwapBytes32 (AccessHigh));\r
143 IoWrite32 (0x518, SwapBytes32 (AccessLow));\r
144\r
145 //\r
146 // Don't look at Access.Control before starting the transfer.\r
147 //\r
148 MemoryFence ();\r
149\r
150 //\r
151 // Wait for the transfer to complete.\r
152 //\r
153 do {\r
154 Status = SwapBytes32 (Access.Control);\r
155 ASSERT ((Status & FW_CFG_DMA_CTL_ERROR) == 0);\r
156 } while (Status != 0);\r
157\r
158 //\r
159 // After a read, the caller will want to use Buffer.\r
160 //\r
161 MemoryFence ();\r
162}\r
163\r
164\r
f1ec65ba 165/**\r
166 Reads firmware configuration bytes into a buffer\r
167\r
168 @param[in] Size - Size in bytes to read\r
169 @param[in] Buffer - Buffer to store data into (OPTIONAL if Size is 0)\r
170\r
171**/\r
172VOID\r
173EFIAPI\r
174InternalQemuFwCfgReadBytes (\r
175 IN UINTN Size,\r
176 IN VOID *Buffer OPTIONAL\r
177 )\r
178{\r
2c8dcbc6
LE
179 if (InternalQemuFwCfgDmaIsAvailable () && Size <= MAX_UINT32) {\r
180 InternalQemuFwCfgDmaBytes ((UINT32)Size, Buffer, FALSE);\r
181 return;\r
182 }\r
f1ec65ba 183 IoReadFifo8 (0x511, Size, Buffer);\r
184}\r
185\r
186\r
187/**\r
188 Reads firmware configuration bytes into a buffer\r
189\r
190 If called multiple times, then the data read will\r
191 continue at the offset of the firmware configuration\r
192 item where the previous read ended.\r
193\r
194 @param[in] Size - Size in bytes to read\r
195 @param[in] Buffer - Buffer to store data into\r
196\r
197**/\r
198VOID\r
199EFIAPI\r
200QemuFwCfgReadBytes (\r
201 IN UINTN Size,\r
202 IN VOID *Buffer\r
203 )\r
204{\r
0dc231c9 205 if (InternalQemuFwCfgIsAvailable ()) {\r
f1ec65ba 206 InternalQemuFwCfgReadBytes (Size, Buffer);\r
207 } else {\r
208 ZeroMem (Buffer, Size);\r
209 }\r
210}\r
211\r
29874a8c 212/**\r
213 Write firmware configuration bytes from a buffer\r
214\r
215 If called multiple times, then the data written will\r
216 continue at the offset of the firmware configuration\r
217 item where the previous write ended.\r
218\r
219 @param[in] Size - Size in bytes to write\r
220 @param[in] Buffer - Buffer to read data from\r
221\r
222**/\r
223VOID\r
224EFIAPI\r
225QemuFwCfgWriteBytes (\r
226 IN UINTN Size,\r
227 IN VOID *Buffer\r
228 )\r
229{\r
0dc231c9 230 if (InternalQemuFwCfgIsAvailable ()) {\r
2c8dcbc6
LE
231 if (InternalQemuFwCfgDmaIsAvailable () && Size <= MAX_UINT32) {\r
232 InternalQemuFwCfgDmaBytes ((UINT32)Size, Buffer, TRUE);\r
233 return;\r
234 }\r
29874a8c 235 IoWriteFifo8 (0x511, Size, Buffer);\r
236 }\r
237}\r
238\r
f1ec65ba 239\r
240/**\r
241 Reads a UINT8 firmware configuration value\r
242\r
243 @return Value of Firmware Configuration item read\r
244\r
245**/\r
246UINT8\r
247EFIAPI\r
248QemuFwCfgRead8 (\r
249 VOID\r
250 )\r
251{\r
252 UINT8 Result;\r
253\r
254 QemuFwCfgReadBytes (sizeof (Result), &Result);\r
255\r
256 return Result;\r
257}\r
258\r
259\r
260/**\r
261 Reads a UINT16 firmware configuration value\r
262\r
263 @return Value of Firmware Configuration item read\r
264\r
265**/\r
266UINT16\r
267EFIAPI\r
268QemuFwCfgRead16 (\r
269 VOID\r
270 )\r
271{\r
272 UINT16 Result;\r
273\r
274 QemuFwCfgReadBytes (sizeof (Result), &Result);\r
275\r
276 return Result;\r
277}\r
278\r
279\r
280/**\r
281 Reads a UINT32 firmware configuration value\r
282\r
283 @return Value of Firmware Configuration item read\r
284\r
285**/\r
286UINT32\r
287EFIAPI\r
288QemuFwCfgRead32 (\r
289 VOID\r
290 )\r
291{\r
292 UINT32 Result;\r
293\r
294 QemuFwCfgReadBytes (sizeof (Result), &Result);\r
295\r
296 return Result;\r
297}\r
298\r
299\r
300/**\r
301 Reads a UINT64 firmware configuration value\r
302\r
303 @return Value of Firmware Configuration item read\r
304\r
305**/\r
306UINT64\r
307EFIAPI\r
308QemuFwCfgRead64 (\r
309 VOID\r
310 )\r
311{\r
312 UINT64 Result;\r
313\r
314 QemuFwCfgReadBytes (sizeof (Result), &Result);\r
315\r
316 return Result;\r
317}\r
318\r
319\r
0ac9bc9b 320/**\r
321 Find the configuration item corresponding to the firmware configuration file.\r
322\r
323 @param[in] Name - Name of file to look up.\r
324 @param[out] Item - Configuration item corresponding to the file, to be passed\r
325 to QemuFwCfgSelectItem ().\r
326 @param[out] Size - Number of bytes in the file.\r
327\r
328 @return RETURN_SUCCESS If file is found.\r
329 RETURN_NOT_FOUND If file is not found.\r
330 RETURN_UNSUPPORTED If firmware configuration is unavailable.\r
331\r
332**/\r
333RETURN_STATUS\r
334EFIAPI\r
335QemuFwCfgFindFile (\r
336 IN CONST CHAR8 *Name,\r
337 OUT FIRMWARE_CONFIG_ITEM *Item,\r
338 OUT UINTN *Size\r
339 )\r
340{\r
341 UINT32 Count;\r
342 UINT32 Idx;\r
343\r
0dc231c9 344 if (!InternalQemuFwCfgIsAvailable ()) {\r
0ac9bc9b 345 return RETURN_UNSUPPORTED;\r
346 }\r
347\r
348 QemuFwCfgSelectItem (QemuFwCfgItemFileDir);\r
349 Count = SwapBytes32 (QemuFwCfgRead32 ());\r
350\r
351 for (Idx = 0; Idx < Count; ++Idx) {\r
352 UINT32 FileSize;\r
353 UINT16 FileSelect;\r
354 UINT16 FileReserved;\r
6a904296 355 CHAR8 FName[QEMU_FW_CFG_FNAME_SIZE];\r
0ac9bc9b 356\r
357 FileSize = QemuFwCfgRead32 ();\r
358 FileSelect = QemuFwCfgRead16 ();\r
359 FileReserved = QemuFwCfgRead16 ();\r
c6910aed 360 (VOID) FileReserved; /* Force a do-nothing reference. */\r
0ac9bc9b 361 InternalQemuFwCfgReadBytes (sizeof (FName), FName);\r
362\r
363 if (AsciiStrCmp (Name, FName) == 0) {\r
364 *Item = SwapBytes16 (FileSelect);\r
365 *Size = SwapBytes32 (FileSize);\r
366 return RETURN_SUCCESS;\r
367 }\r
368 }\r
369\r
370 return RETURN_NOT_FOUND;\r
371}\r
14eb7a5b
LE
372\r
373\r
374/**\r
375 Determine if S3 support is explicitly enabled.\r
376\r
377 @retval TRUE if S3 support is explicitly enabled.\r
378 FALSE otherwise. This includes unavailability of the firmware\r
379 configuration interface.\r
380**/\r
381BOOLEAN\r
382EFIAPI\r
383QemuFwCfgS3Enabled (\r
384 VOID\r
385 )\r
386{\r
387 RETURN_STATUS Status;\r
388 FIRMWARE_CONFIG_ITEM FwCfgItem;\r
389 UINTN FwCfgSize;\r
390 UINT8 SystemStates[6];\r
391\r
392 Status = QemuFwCfgFindFile ("etc/system-states", &FwCfgItem, &FwCfgSize);\r
393 if (Status != RETURN_SUCCESS || FwCfgSize != sizeof SystemStates) {\r
394 return FALSE;\r
395 }\r
396 QemuFwCfgSelectItem (FwCfgItem);\r
397 QemuFwCfgReadBytes (sizeof SystemStates, SystemStates);\r
398 return (BOOLEAN) (SystemStates[3] & BIT7);\r
399}\r