]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c
OvmfPkg: Modify QemuFwCfgLib to use new IoLib class library
[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 using the DMA interface.
51
52 @param[in] Size Size in bytes to transfer.
53 @param[in,out] Buffer Buffer to read data into or write data from. May be
54 NULL if Size is zero.
55 @param[in] Write TRUE if writing to fw_cfg from Buffer, FALSE if
56 reading from fw_cfg into Buffer.
57 **/
58 VOID
59 InternalQemuFwCfgDmaBytes (
60 IN UINT32 Size,
61 IN OUT VOID *Buffer OPTIONAL,
62 IN BOOLEAN Write
63 )
64 {
65 volatile FW_CFG_DMA_ACCESS Access;
66 UINT32 AccessHigh, AccessLow;
67 UINT32 Status;
68
69 if (Size == 0) {
70 return;
71 }
72
73 Access.Control = SwapBytes32 (
74 Write ? FW_CFG_DMA_CTL_WRITE : FW_CFG_DMA_CTL_READ
75 );
76 Access.Length = SwapBytes32 (Size);
77 Access.Address = SwapBytes64 ((UINTN)Buffer);
78
79 //
80 // Delimit the transfer from (a) modifications to Access, (b) in case of a
81 // write, from writes to Buffer by the caller.
82 //
83 MemoryFence ();
84
85 //
86 // Start the transfer.
87 //
88 AccessHigh = (UINT32)RShiftU64 ((UINTN)&Access, 32);
89 AccessLow = (UINT32)(UINTN)&Access;
90 IoWrite32 (0x514, SwapBytes32 (AccessHigh));
91 IoWrite32 (0x518, SwapBytes32 (AccessLow));
92
93 //
94 // Don't look at Access.Control before starting the transfer.
95 //
96 MemoryFence ();
97
98 //
99 // Wait for the transfer to complete.
100 //
101 do {
102 Status = SwapBytes32 (Access.Control);
103 ASSERT ((Status & FW_CFG_DMA_CTL_ERROR) == 0);
104 } while (Status != 0);
105
106 //
107 // After a read, the caller will want to use Buffer.
108 //
109 MemoryFence ();
110 }
111
112
113 /**
114 Reads firmware configuration bytes into a buffer
115
116 @param[in] Size - Size in bytes to read
117 @param[in] Buffer - Buffer to store data into (OPTIONAL if Size is 0)
118
119 **/
120 VOID
121 EFIAPI
122 InternalQemuFwCfgReadBytes (
123 IN UINTN Size,
124 IN VOID *Buffer OPTIONAL
125 )
126 {
127 if (InternalQemuFwCfgDmaIsAvailable () && Size <= MAX_UINT32) {
128 InternalQemuFwCfgDmaBytes ((UINT32)Size, Buffer, FALSE);
129 return;
130 }
131 IoReadFifo8 (0x511, Size, Buffer);
132 }
133
134
135 /**
136 Reads firmware configuration bytes into a buffer
137
138 If called multiple times, then the data read will
139 continue at the offset of the firmware configuration
140 item where the previous read ended.
141
142 @param[in] Size - Size in bytes to read
143 @param[in] Buffer - Buffer to store data into
144
145 **/
146 VOID
147 EFIAPI
148 QemuFwCfgReadBytes (
149 IN UINTN Size,
150 IN VOID *Buffer
151 )
152 {
153 if (InternalQemuFwCfgIsAvailable ()) {
154 InternalQemuFwCfgReadBytes (Size, Buffer);
155 } else {
156 ZeroMem (Buffer, Size);
157 }
158 }
159
160 /**
161 Write firmware configuration bytes from a buffer
162
163 If called multiple times, then the data written will
164 continue at the offset of the firmware configuration
165 item where the previous write ended.
166
167 @param[in] Size - Size in bytes to write
168 @param[in] Buffer - Buffer to read data from
169
170 **/
171 VOID
172 EFIAPI
173 QemuFwCfgWriteBytes (
174 IN UINTN Size,
175 IN VOID *Buffer
176 )
177 {
178 if (InternalQemuFwCfgIsAvailable ()) {
179 if (InternalQemuFwCfgDmaIsAvailable () && Size <= MAX_UINT32) {
180 InternalQemuFwCfgDmaBytes ((UINT32)Size, Buffer, TRUE);
181 return;
182 }
183 IoWriteFifo8 (0x511, Size, Buffer);
184 }
185 }
186
187
188 /**
189 Reads a UINT8 firmware configuration value
190
191 @return Value of Firmware Configuration item read
192
193 **/
194 UINT8
195 EFIAPI
196 QemuFwCfgRead8 (
197 VOID
198 )
199 {
200 UINT8 Result;
201
202 QemuFwCfgReadBytes (sizeof (Result), &Result);
203
204 return Result;
205 }
206
207
208 /**
209 Reads a UINT16 firmware configuration value
210
211 @return Value of Firmware Configuration item read
212
213 **/
214 UINT16
215 EFIAPI
216 QemuFwCfgRead16 (
217 VOID
218 )
219 {
220 UINT16 Result;
221
222 QemuFwCfgReadBytes (sizeof (Result), &Result);
223
224 return Result;
225 }
226
227
228 /**
229 Reads a UINT32 firmware configuration value
230
231 @return Value of Firmware Configuration item read
232
233 **/
234 UINT32
235 EFIAPI
236 QemuFwCfgRead32 (
237 VOID
238 )
239 {
240 UINT32 Result;
241
242 QemuFwCfgReadBytes (sizeof (Result), &Result);
243
244 return Result;
245 }
246
247
248 /**
249 Reads a UINT64 firmware configuration value
250
251 @return Value of Firmware Configuration item read
252
253 **/
254 UINT64
255 EFIAPI
256 QemuFwCfgRead64 (
257 VOID
258 )
259 {
260 UINT64 Result;
261
262 QemuFwCfgReadBytes (sizeof (Result), &Result);
263
264 return Result;
265 }
266
267
268 /**
269 Find the configuration item corresponding to the firmware configuration file.
270
271 @param[in] Name - Name of file to look up.
272 @param[out] Item - Configuration item corresponding to the file, to be passed
273 to QemuFwCfgSelectItem ().
274 @param[out] Size - Number of bytes in the file.
275
276 @return RETURN_SUCCESS If file is found.
277 RETURN_NOT_FOUND If file is not found.
278 RETURN_UNSUPPORTED If firmware configuration is unavailable.
279
280 **/
281 RETURN_STATUS
282 EFIAPI
283 QemuFwCfgFindFile (
284 IN CONST CHAR8 *Name,
285 OUT FIRMWARE_CONFIG_ITEM *Item,
286 OUT UINTN *Size
287 )
288 {
289 UINT32 Count;
290 UINT32 Idx;
291
292 if (!InternalQemuFwCfgIsAvailable ()) {
293 return RETURN_UNSUPPORTED;
294 }
295
296 QemuFwCfgSelectItem (QemuFwCfgItemFileDir);
297 Count = SwapBytes32 (QemuFwCfgRead32 ());
298
299 for (Idx = 0; Idx < Count; ++Idx) {
300 UINT32 FileSize;
301 UINT16 FileSelect;
302 UINT16 FileReserved;
303 CHAR8 FName[QEMU_FW_CFG_FNAME_SIZE];
304
305 FileSize = QemuFwCfgRead32 ();
306 FileSelect = QemuFwCfgRead16 ();
307 FileReserved = QemuFwCfgRead16 ();
308 (VOID) FileReserved; /* Force a do-nothing reference. */
309 InternalQemuFwCfgReadBytes (sizeof (FName), FName);
310
311 if (AsciiStrCmp (Name, FName) == 0) {
312 *Item = SwapBytes16 (FileSelect);
313 *Size = SwapBytes32 (FileSize);
314 return RETURN_SUCCESS;
315 }
316 }
317
318 return RETURN_NOT_FOUND;
319 }
320
321
322 /**
323 Determine if S3 support is explicitly enabled.
324
325 @retval TRUE if S3 support is explicitly enabled.
326 FALSE otherwise. This includes unavailability of the firmware
327 configuration interface.
328 **/
329 BOOLEAN
330 EFIAPI
331 QemuFwCfgS3Enabled (
332 VOID
333 )
334 {
335 RETURN_STATUS Status;
336 FIRMWARE_CONFIG_ITEM FwCfgItem;
337 UINTN FwCfgSize;
338 UINT8 SystemStates[6];
339
340 Status = QemuFwCfgFindFile ("etc/system-states", &FwCfgItem, &FwCfgSize);
341 if (Status != RETURN_SUCCESS || FwCfgSize != sizeof SystemStates) {
342 return FALSE;
343 }
344 QemuFwCfgSelectItem (FwCfgItem);
345 QemuFwCfgReadBytes (sizeof SystemStates, SystemStates);
346 return (BOOLEAN) (SystemStates[3] & BIT7);
347 }