TianoCore EDK2 master
Loading...
Searching...
No Matches
QemuFwCfgLibMmio.c
Go to the documentation of this file.
1
11#include <Base.h>
12#include <Uefi.h>
13
14#include <Pi/PiBootMode.h>
15#include <Pi/PiHob.h>
16
17#include <Library/BaseLib.h>
19#include <Library/DebugLib.h>
20#include <Library/HobLib.h>
21#include <Library/IoLib.h>
24
25#include <Protocol/FdtClient.h>
26
28
29//
30// These correspond to the implementation we detect at runtime.
31//
32READ_BYTES_FUNCTION *InternalQemuFwCfgReadBytes = MmioReadBytes;
33WRITE_BYTES_FUNCTION *InternalQemuFwCfgWriteBytes = MmioWriteBytes;
34SKIP_BYTES_FUNCTION *InternalQemuFwCfgSkipBytes = MmioSkipBytes;
35
43VOID
45 IN QEMU_FW_CFG_RESOURCE *FwCfgResource
46 )
47{
49 &gQemuFirmwareResourceHobGuid,
50 (VOID *)FwCfgResource,
52 );
53}
54
65 VOID
66 )
67{
68 EFI_HOB_GUID_TYPE *GuidHob;
69
70 GuidHob = NULL;
71
72 GuidHob = GetFirstGuidHob (&gQemuFirmwareResourceHobGuid);
73 if (GuidHob == NULL) {
74 return NULL;
75 }
76
77 return (QEMU_FW_CFG_RESOURCE *)GET_GUID_HOB_DATA (GuidHob);
78}
79
90BOOLEAN
91EFIAPI
93 VOID
94 )
95{
96 return (BOOLEAN)(QemuGetFwCfgSelectorAddress () != 0 && QemuGetFwCfgDataAddress () != 0);
97}
98
108VOID
109EFIAPI
111 IN FIRMWARE_CONFIG_ITEM QemuFwCfgItem
112 )
113{
114 if (QemuFwCfgIsAvailable ()) {
115 MmioWrite16 (QemuGetFwCfgSelectorAddress (), SwapBytes16 ((UINT16)QemuFwCfgItem));
116 }
117}
118
122VOID
123EFIAPI
125 IN UINTN Size,
126 IN VOID *Buffer OPTIONAL
127 )
128{
129 UINTN Left;
130 UINT8 *Ptr;
131 UINT8 *End;
132
133 #if defined (MDE_CPU_AARCH64) || defined (MDE_CPU_RISCV64) || defined (MDE_CPU_LOONGARCH64)
134 Left = Size & 7;
135 #else
136 Left = Size & 3;
137 #endif
138
139 Size -= Left;
140 Ptr = Buffer;
141 End = Ptr + Size;
142
143 #if defined (MDE_CPU_AARCH64) || defined (MDE_CPU_RISCV64) || defined (MDE_CPU_LOONGARCH64)
144 while (Ptr < End) {
145 *(UINT64 *)Ptr = MmioRead64 (QemuGetFwCfgDataAddress ());
146 Ptr += 8;
147 }
148
149 if (Left & 4) {
150 *(UINT32 *)Ptr = MmioRead32 (QemuGetFwCfgDataAddress ());
151 Ptr += 4;
152 }
153
154 #else
155 while (Ptr < End) {
156 *(UINT32 *)Ptr = MmioRead32 (QemuGetFwCfgDataAddress ());
157 Ptr += 4;
158 }
159
160 #endif
161
162 if (Left & 2) {
163 *(UINT16 *)Ptr = MmioRead16 (QemuGetFwCfgDataAddress ());
164 Ptr += 2;
165 }
166
167 if (Left & 1) {
169 }
170}
171
187VOID
189 IN UINTN Size,
190 IN OUT VOID *Buffer OPTIONAL,
191 IN UINT32 Control
192 )
193{
194 volatile FW_CFG_DMA_ACCESS Access;
195 UINT32 Status;
196
197 ASSERT (
198 Control == FW_CFG_DMA_CTL_WRITE || Control == FW_CFG_DMA_CTL_READ ||
199 Control == FW_CFG_DMA_CTL_SKIP
200 );
201
202 if (Size == 0) {
203 return;
204 }
205
206 ASSERT (Size <= MAX_UINT32);
207
208 Access.Control = SwapBytes32 (Control);
209 Access.Length = SwapBytes32 ((UINT32)Size);
210 Access.Address = SwapBytes64 ((UINT64)(UINTN)Buffer);
211
212 //
213 // We shouldn't start the transfer before setting up Access.
214 //
215 MemoryFence ();
216
217 //
218 // This will fire off the transfer.
219 //
220 #if defined (MDE_CPU_AARCH64) || defined (MDE_CPU_RISCV64) || defined (MDE_CPU_LOONGARCH64)
221 MmioWrite64 (QemuGetFwCfgDmaAddress (), SwapBytes64 ((UINT64)&Access));
222 #else
223 MmioWrite32 ((UINT32)(QemuGetFwCfgDmaAddress () + 4), SwapBytes32 ((UINT32)&Access));
224 #endif
225
226 //
227 // We shouldn't look at Access.Control before starting the transfer.
228 //
229 MemoryFence ();
230
231 do {
232 Status = SwapBytes32 (Access.Control);
233 ASSERT ((Status & FW_CFG_DMA_CTL_ERROR) == 0);
234 } while (Status != 0);
235
236 //
237 // The caller will want to access the transferred data.
238 //
239 MemoryFence ();
240}
241
245VOID
246EFIAPI
248 IN UINTN Size,
249 IN VOID *Buffer OPTIONAL
250 )
251{
252 DmaTransferBytes (Size, Buffer, FW_CFG_DMA_CTL_READ);
253}
254
265VOID
266EFIAPI
268 IN UINTN Size,
269 IN VOID *Buffer
270 )
271{
272 if (QemuFwCfgIsAvailable ()) {
273 InternalQemuFwCfgReadBytes (Size, Buffer);
274 } else {
275 ZeroMem (Buffer, Size);
276 }
277}
278
282VOID
283EFIAPI
285 IN UINTN Size,
286 IN VOID *Buffer OPTIONAL
287 )
288{
289 UINTN Idx;
290
291 for (Idx = 0; Idx < Size; ++Idx) {
292 MmioWrite8 (QemuGetFwCfgDataAddress (), ((UINT8 *)Buffer)[Idx]);
293 }
294}
295
299VOID
300EFIAPI
302 IN UINTN Size,
303 IN VOID *Buffer OPTIONAL
304 )
305{
306 DmaTransferBytes (Size, Buffer, FW_CFG_DMA_CTL_WRITE);
307}
308
319VOID
320EFIAPI
322 IN UINTN Size,
323 IN VOID *Buffer
324 )
325{
326 if (QemuFwCfgIsAvailable ()) {
327 InternalQemuFwCfgWriteBytes (Size, Buffer);
328 }
329}
330
334VOID
335EFIAPI
337 IN UINTN Size
338 )
339{
340 UINTN ChunkSize;
341 UINT8 SkipBuffer[256];
342
343 //
344 // Emulate the skip by reading data in chunks, and throwing it away. The
345 // implementation below doesn't affect the static data footprint for client
346 // modules. Large skips are not expected, therefore this fallback is not
347 // performance critical. The size of SkipBuffer is thought not to exert a
348 // large pressure on the stack.
349 //
350 while (Size > 0) {
351 ChunkSize = MIN (Size, sizeof SkipBuffer);
352 MmioReadBytes (ChunkSize, SkipBuffer);
353 Size -= ChunkSize;
354 }
355}
356
360VOID
361EFIAPI
363 IN UINTN Size
364 )
365{
366 DmaTransferBytes (Size, NULL, FW_CFG_DMA_CTL_SKIP);
367}
368
378VOID
379EFIAPI
381 IN UINTN Size
382 )
383{
384 if (QemuFwCfgIsAvailable ()) {
385 InternalQemuFwCfgSkipBytes (Size);
386 }
387}
388
395UINT8
396EFIAPI
398 VOID
399 )
400{
401 UINT8 Result;
402
403 QemuFwCfgReadBytes (sizeof Result, &Result);
404 return Result;
405}
406
413UINT16
414EFIAPI
416 VOID
417 )
418{
419 UINT16 Result;
420
421 QemuFwCfgReadBytes (sizeof Result, &Result);
422 return Result;
423}
424
431UINT32
432EFIAPI
434 VOID
435 )
436{
437 UINT32 Result;
438
439 QemuFwCfgReadBytes (sizeof Result, &Result);
440 return Result;
441}
442
449UINT64
450EFIAPI
452 VOID
453 )
454{
455 UINT64 Result;
456
457 QemuFwCfgReadBytes (sizeof Result, &Result);
458 return Result;
459}
460
474RETURN_STATUS
475EFIAPI
477 IN CONST CHAR8 *Name,
478 OUT FIRMWARE_CONFIG_ITEM *Item,
479 OUT UINTN *Size
480 )
481{
482 UINT32 Count;
483 UINT32 Idx;
484
485 if (!QemuFwCfgIsAvailable ()) {
486 return RETURN_UNSUPPORTED;
487 }
488
489 QemuFwCfgSelectItem (QemuFwCfgItemFileDir);
490 Count = SwapBytes32 (QemuFwCfgRead32 ());
491
492 for (Idx = 0; Idx < Count; ++Idx) {
493 UINT32 FileSize;
494 UINT16 FileSelect;
495 CHAR8 FName[QEMU_FW_CFG_FNAME_SIZE];
496
497 FileSize = QemuFwCfgRead32 ();
498 FileSelect = QemuFwCfgRead16 ();
499 QemuFwCfgRead16 (); // skip the field called "reserved"
500 InternalQemuFwCfgReadBytes (sizeof (FName), FName);
501
502 if (AsciiStrCmp (Name, FName) == 0) {
503 *Item = (FIRMWARE_CONFIG_ITEM)SwapBytes16 (FileSelect);
504 *Size = SwapBytes32 (FileSize);
505 return RETURN_SUCCESS;
506 }
507 }
508
509 return RETURN_NOT_FOUND;
510}
UINT64 UINTN
VOID *EFIAPI GetFirstGuidHob(IN CONST EFI_GUID *Guid)
Definition: HobLib.c:215
VOID *EFIAPI BuildGuidDataHob(IN CONST EFI_GUID *Guid, IN VOID *Data, IN UINTN DataLength)
Definition: HobLib.c:375
UINT16 EFIAPI SwapBytes16(IN UINT16 Value)
Definition: SwapBytes16.c:25
INTN EFIAPI AsciiStrCmp(IN CONST CHAR8 *FirstString, IN CONST CHAR8 *SecondString)
Definition: String.c:716
VOID EFIAPI MemoryFence(VOID)
Definition: CpuBreakpoint.c:42
UINT32 EFIAPI SwapBytes32(IN UINT32 Value)
Definition: SwapBytes32.c:25
UINT64 EFIAPI SwapBytes64(IN UINT64 Value)
Definition: SwapBytes64.c:25
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
UINT64 EFIAPI MmioWrite64(IN UINTN Address, IN UINT64 Value)
Definition: IoLib.c:400
UINT64 EFIAPI MmioRead64(IN UINTN Address)
Definition: IoLib.c:355
UINT16 EFIAPI MmioRead16(IN UINTN Address)
Definition: IoLib.c:170
UINT8 EFIAPI MmioRead8(IN UINTN Address)
Definition: IoLib.c:82
UINT8 EFIAPI MmioWrite8(IN UINTN Address, IN UINT8 Value)
Definition: IoLib.c:126
UINT32 EFIAPI MmioRead32(IN UINTN Address)
Definition: IoLib.c:262
UINT16 EFIAPI MmioWrite16(IN UINTN Address, IN UINT16 Value)
Definition: IoLib.c:216
UINT32 EFIAPI MmioWrite32(IN UINTN Address, IN UINT32 Value)
Definition: IoLib.c:309
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define RETURN_NOT_FOUND
Definition: Base.h:1142
#define MIN(a, b)
Definition: Base.h:1007
#define RETURN_UNSUPPORTED
Definition: Base.h:1081
#define RETURN_SUCCESS
Definition: Base.h:1066
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
VOID EFIAPI DmaSkipBytes(IN UINTN Size)
UINT32 EFIAPI QemuFwCfgRead32(VOID)
QEMU_FW_CFG_RESOURCE * QemuGetFwCfgResourceHob(VOID)
VOID EFIAPI DmaReadBytes(IN UINTN Size, IN VOID *Buffer OPTIONAL)
VOID EFIAPI QemuFwCfgWriteBytes(IN UINTN Size, IN VOID *Buffer)
VOID QemuBuildFwCfgResourceHob(IN QEMU_FW_CFG_RESOURCE *FwCfgResource)
VOID DmaTransferBytes(IN UINTN Size, IN OUT VOID *Buffer OPTIONAL, IN UINT32 Control)
VOID EFIAPI MmioReadBytes(IN UINTN Size, IN VOID *Buffer OPTIONAL)
UINT16 EFIAPI QemuFwCfgRead16(VOID)
UINT8 EFIAPI QemuFwCfgRead8(VOID)
RETURN_STATUS EFIAPI QemuFwCfgFindFile(IN CONST CHAR8 *Name, OUT FIRMWARE_CONFIG_ITEM *Item, OUT UINTN *Size)
UINT64 EFIAPI QemuFwCfgRead64(VOID)
VOID EFIAPI MmioWriteBytes(IN UINTN Size, IN VOID *Buffer OPTIONAL)
VOID EFIAPI QemuFwCfgSelectItem(IN FIRMWARE_CONFIG_ITEM QemuFwCfgItem)
VOID EFIAPI QemuFwCfgSkipBytes(IN UINTN Size)
BOOLEAN EFIAPI QemuFwCfgIsAvailable(VOID)
VOID EFIAPI DmaWriteBytes(IN UINTN Size, IN VOID *Buffer OPTIONAL)
VOID EFIAPI MmioSkipBytes(IN UINTN Size)
VOID EFIAPI QemuFwCfgReadBytes(IN UINTN Size, IN VOID *Buffer)
UINTN EFIAPI QemuGetFwCfgDmaAddress(VOID)
UINTN EFIAPI QemuGetFwCfgDataAddress(VOID)
UINTN EFIAPI QemuGetFwCfgSelectorAddress(VOID)