]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c
4d2c43cb8fd76e6cc0296e2d44d870925efc0197
[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 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10
11 #include "Uefi.h"
12 #include <Library/BaseLib.h>
13 #include <Library/BaseMemoryLib.h>
14 #include <Library/DebugLib.h>
15 #include <Library/IoLib.h>
16 #include <Library/QemuFwCfgLib.h>
17 #include <Library/MemoryAllocationLib.h>
18 #include <Library/UefiBootServicesTableLib.h>
19
20 #include "QemuFwCfgLibInternal.h"
21
22
23 /**
24 Selects a firmware configuration item for reading.
25
26 Following this call, any data read from this item will start from
27 the beginning of the configuration item's data.
28
29 @param[in] QemuFwCfgItem - Firmware Configuration item to read
30
31 **/
32 VOID
33 EFIAPI
34 QemuFwCfgSelectItem (
35 IN FIRMWARE_CONFIG_ITEM QemuFwCfgItem
36 )
37 {
38 DEBUG ((EFI_D_INFO, "Select Item: 0x%x\n", (UINT16)(UINTN) QemuFwCfgItem));
39 IoWrite16 (FW_CFG_IO_SELECTOR, (UINT16)(UINTN) QemuFwCfgItem);
40 }
41
42 /**
43 Reads firmware configuration bytes into a buffer
44
45 @param[in] Size - Size in bytes to read
46 @param[in] Buffer - Buffer to store data into (OPTIONAL if Size is 0)
47
48 **/
49 VOID
50 EFIAPI
51 InternalQemuFwCfgReadBytes (
52 IN UINTN Size,
53 IN VOID *Buffer OPTIONAL
54 )
55 {
56 if (InternalQemuFwCfgDmaIsAvailable () && Size <= MAX_UINT32) {
57 InternalQemuFwCfgDmaBytes ((UINT32)Size, Buffer, FW_CFG_DMA_CTL_READ);
58 return;
59 }
60 IoReadFifo8 (FW_CFG_IO_DATA, Size, Buffer);
61 }
62
63
64 /**
65 Reads firmware configuration bytes into a buffer
66
67 If called multiple times, then the data read will
68 continue at the offset of the firmware configuration
69 item where the previous read ended.
70
71 @param[in] Size - Size in bytes to read
72 @param[in] Buffer - Buffer to store data into
73
74 **/
75 VOID
76 EFIAPI
77 QemuFwCfgReadBytes (
78 IN UINTN Size,
79 IN VOID *Buffer
80 )
81 {
82 if (InternalQemuFwCfgIsAvailable ()) {
83 InternalQemuFwCfgReadBytes (Size, Buffer);
84 } else {
85 ZeroMem (Buffer, Size);
86 }
87 }
88
89 /**
90 Write firmware configuration bytes from a buffer
91
92 If called multiple times, then the data written will
93 continue at the offset of the firmware configuration
94 item where the previous write ended.
95
96 @param[in] Size - Size in bytes to write
97 @param[in] Buffer - Buffer to read data from
98
99 **/
100 VOID
101 EFIAPI
102 QemuFwCfgWriteBytes (
103 IN UINTN Size,
104 IN VOID *Buffer
105 )
106 {
107 if (InternalQemuFwCfgIsAvailable ()) {
108 if (InternalQemuFwCfgDmaIsAvailable () && Size <= MAX_UINT32) {
109 InternalQemuFwCfgDmaBytes ((UINT32)Size, Buffer, FW_CFG_DMA_CTL_WRITE);
110 return;
111 }
112 IoWriteFifo8 (FW_CFG_IO_DATA, Size, Buffer);
113 }
114 }
115
116
117 /**
118 Skip bytes in the firmware configuration item.
119
120 Increase the offset of the firmware configuration item without transferring
121 bytes between the item and a caller-provided buffer. Subsequent read, write
122 or skip operations will commence at the increased offset.
123
124 @param[in] Size Number of bytes to skip.
125 **/
126 VOID
127 EFIAPI
128 QemuFwCfgSkipBytes (
129 IN UINTN Size
130 )
131 {
132 UINTN ChunkSize;
133 UINT8 SkipBuffer[256];
134
135 if (!InternalQemuFwCfgIsAvailable ()) {
136 return;
137 }
138
139 if (InternalQemuFwCfgDmaIsAvailable () && Size <= MAX_UINT32) {
140 InternalQemuFwCfgDmaBytes ((UINT32)Size, NULL, FW_CFG_DMA_CTL_SKIP);
141 return;
142 }
143
144 //
145 // Emulate the skip by reading data in chunks, and throwing it away. The
146 // implementation below is suitable even for phases where RAM or dynamic
147 // allocation is not available or appropriate. It also doesn't affect the
148 // static data footprint for client modules. Large skips are not expected,
149 // therefore this fallback is not performance critical. The size of
150 // SkipBuffer is thought not to exert a large pressure on the stack in any
151 // phase.
152 //
153 while (Size > 0) {
154 ChunkSize = MIN (Size, sizeof SkipBuffer);
155 IoReadFifo8 (FW_CFG_IO_DATA, ChunkSize, SkipBuffer);
156 Size -= ChunkSize;
157 }
158 }
159
160
161 /**
162 Reads a UINT8 firmware configuration value
163
164 @return Value of Firmware Configuration item read
165
166 **/
167 UINT8
168 EFIAPI
169 QemuFwCfgRead8 (
170 VOID
171 )
172 {
173 UINT8 Result;
174
175 QemuFwCfgReadBytes (sizeof (Result), &Result);
176
177 return Result;
178 }
179
180
181 /**
182 Reads a UINT16 firmware configuration value
183
184 @return Value of Firmware Configuration item read
185
186 **/
187 UINT16
188 EFIAPI
189 QemuFwCfgRead16 (
190 VOID
191 )
192 {
193 UINT16 Result;
194
195 QemuFwCfgReadBytes (sizeof (Result), &Result);
196
197 return Result;
198 }
199
200
201 /**
202 Reads a UINT32 firmware configuration value
203
204 @return Value of Firmware Configuration item read
205
206 **/
207 UINT32
208 EFIAPI
209 QemuFwCfgRead32 (
210 VOID
211 )
212 {
213 UINT32 Result;
214
215 QemuFwCfgReadBytes (sizeof (Result), &Result);
216
217 return Result;
218 }
219
220
221 /**
222 Reads a UINT64 firmware configuration value
223
224 @return Value of Firmware Configuration item read
225
226 **/
227 UINT64
228 EFIAPI
229 QemuFwCfgRead64 (
230 VOID
231 )
232 {
233 UINT64 Result;
234
235 QemuFwCfgReadBytes (sizeof (Result), &Result);
236
237 return Result;
238 }
239
240
241 /**
242 Find the configuration item corresponding to the firmware configuration file.
243
244 @param[in] Name - Name of file to look up.
245 @param[out] Item - Configuration item corresponding to the file, to be passed
246 to QemuFwCfgSelectItem ().
247 @param[out] Size - Number of bytes in the file.
248
249 @return RETURN_SUCCESS If file is found.
250 RETURN_NOT_FOUND If file is not found.
251 RETURN_UNSUPPORTED If firmware configuration is unavailable.
252
253 **/
254 RETURN_STATUS
255 EFIAPI
256 QemuFwCfgFindFile (
257 IN CONST CHAR8 *Name,
258 OUT FIRMWARE_CONFIG_ITEM *Item,
259 OUT UINTN *Size
260 )
261 {
262 UINT32 Count;
263 UINT32 Idx;
264
265 if (!InternalQemuFwCfgIsAvailable ()) {
266 return RETURN_UNSUPPORTED;
267 }
268
269 QemuFwCfgSelectItem (QemuFwCfgItemFileDir);
270 Count = SwapBytes32 (QemuFwCfgRead32 ());
271
272 for (Idx = 0; Idx < Count; ++Idx) {
273 UINT32 FileSize;
274 UINT16 FileSelect;
275 UINT16 FileReserved;
276 CHAR8 FName[QEMU_FW_CFG_FNAME_SIZE];
277
278 FileSize = QemuFwCfgRead32 ();
279 FileSelect = QemuFwCfgRead16 ();
280 FileReserved = QemuFwCfgRead16 ();
281 (VOID) FileReserved; /* Force a do-nothing reference. */
282 InternalQemuFwCfgReadBytes (sizeof (FName), FName);
283
284 if (AsciiStrCmp (Name, FName) == 0) {
285 *Item = SwapBytes16 (FileSelect);
286 *Size = SwapBytes32 (FileSize);
287 return RETURN_SUCCESS;
288 }
289 }
290
291 return RETURN_NOT_FOUND;
292 }