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