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