3 Stateful and implicitly initialized fw_cfg library implementation.
5 Copyright (C) 2013 - 2014, Red Hat, Inc.
6 Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
8 This program and the accompanying materials are licensed and made available
9 under the terms and conditions of the BSD License which accompanies this
10 distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
14 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 #include <Library/BaseLib.h>
20 #include <Library/BaseMemoryLib.h>
21 #include <Library/DebugLib.h>
22 #include <Library/IoLib.h>
23 #include <Library/QemuFwCfgLib.h>
24 #include <Library/UefiBootServicesTableLib.h>
26 #include <Protocol/FdtClient.h>
28 STATIC UINTN mFwCfgSelectorAddress
;
29 STATIC UINTN mFwCfgDataAddress
;
30 STATIC UINTN mFwCfgDmaAddress
;
33 Reads firmware configuration bytes into a buffer
35 @param[in] Size Size in bytes to read
36 @param[in] Buffer Buffer to store data into (OPTIONAL if Size is 0)
40 VOID (EFIAPI READ_BYTES_FUNCTION
) (
42 IN VOID
*Buffer OPTIONAL
46 Writes bytes from a buffer to firmware configuration
48 @param[in] Size Size in bytes to write
49 @param[in] Buffer Buffer to transfer data from (OPTIONAL if Size is 0)
53 VOID (EFIAPI WRITE_BYTES_FUNCTION
) (
55 IN VOID
*Buffer OPTIONAL
59 Skips bytes in firmware configuration
61 @param[in] Size Size in bytes to skip
65 VOID (EFIAPI SKIP_BYTES_FUNCTION
) (
70 // Forward declaration of the two implementations we have.
72 STATIC READ_BYTES_FUNCTION MmioReadBytes
;
73 STATIC WRITE_BYTES_FUNCTION MmioWriteBytes
;
74 STATIC SKIP_BYTES_FUNCTION MmioSkipBytes
;
75 STATIC READ_BYTES_FUNCTION DmaReadBytes
;
76 STATIC WRITE_BYTES_FUNCTION DmaWriteBytes
;
77 STATIC SKIP_BYTES_FUNCTION DmaSkipBytes
;
80 // These correspond to the implementation we detect at runtime.
82 STATIC READ_BYTES_FUNCTION
*InternalQemuFwCfgReadBytes
= MmioReadBytes
;
83 STATIC WRITE_BYTES_FUNCTION
*InternalQemuFwCfgWriteBytes
= MmioWriteBytes
;
84 STATIC SKIP_BYTES_FUNCTION
*InternalQemuFwCfgSkipBytes
= MmioSkipBytes
;
88 Returns a boolean indicating if the firmware configuration interface
91 This function may change fw_cfg state.
93 @retval TRUE The interface is available
94 @retval FALSE The interface is not available
99 QemuFwCfgIsAvailable (
103 return (BOOLEAN
)(mFwCfgSelectorAddress
!= 0 && mFwCfgDataAddress
!= 0);
109 QemuFwCfgInitialize (
114 FDT_CLIENT_PROTOCOL
*FdtClient
;
117 UINTN AddressCells
, SizeCells
;
118 UINT64 FwCfgSelectorAddress
;
119 UINT64 FwCfgSelectorSize
;
120 UINT64 FwCfgDataAddress
;
121 UINT64 FwCfgDataSize
;
122 UINT64 FwCfgDmaAddress
;
125 Status
= gBS
->LocateProtocol (&gFdtClientProtocolGuid
, NULL
,
126 (VOID
**)&FdtClient
);
127 ASSERT_EFI_ERROR (Status
);
129 Status
= FdtClient
->FindCompatibleNodeReg (FdtClient
, "qemu,fw-cfg-mmio",
130 (CONST VOID
**)&Reg
, &AddressCells
, &SizeCells
,
132 if (EFI_ERROR (Status
)) {
134 "%a: No 'qemu,fw-cfg-mmio' compatible DT node found (Status == %r)\n",
135 __FUNCTION__
, Status
));
139 ASSERT (AddressCells
== 2);
140 ASSERT (SizeCells
== 2);
141 ASSERT (RegSize
== 2 * sizeof (UINT64
));
143 FwCfgDataAddress
= SwapBytes64 (Reg
[0]);
145 FwCfgSelectorAddress
= FwCfgDataAddress
+ FwCfgDataSize
;
146 FwCfgSelectorSize
= 2;
149 // The following ASSERT()s express
151 // Address + Size - 1 <= MAX_UINTN
153 // for both registers, that is, that the last byte in each MMIO range is
154 // expressible as a MAX_UINTN. The form below is mathematically
155 // equivalent, and it also prevents any unsigned overflow before the
158 ASSERT (FwCfgSelectorAddress
<= MAX_UINTN
- FwCfgSelectorSize
+ 1);
159 ASSERT (FwCfgDataAddress
<= MAX_UINTN
- FwCfgDataSize
+ 1);
161 mFwCfgSelectorAddress
= FwCfgSelectorAddress
;
162 mFwCfgDataAddress
= FwCfgDataAddress
;
164 DEBUG ((EFI_D_INFO
, "Found FwCfg @ 0x%Lx/0x%Lx\n", FwCfgSelectorAddress
,
167 if (SwapBytes64 (Reg
[1]) >= 0x18) {
168 FwCfgDmaAddress
= FwCfgDataAddress
+ 0x10;
172 // See explanation above.
174 ASSERT (FwCfgDmaAddress
<= MAX_UINTN
- FwCfgDmaSize
+ 1);
176 DEBUG ((EFI_D_INFO
, "Found FwCfg DMA @ 0x%Lx\n", FwCfgDmaAddress
));
181 if (QemuFwCfgIsAvailable ()) {
184 QemuFwCfgSelectItem (QemuFwCfgItemSignature
);
185 Signature
= QemuFwCfgRead32 ();
186 if (Signature
== SIGNATURE_32 ('Q', 'E', 'M', 'U')) {
188 // For DMA support, we require the DTB to advertise the register, and the
189 // feature bitmap (which we read without DMA) to confirm the feature.
191 if (FwCfgDmaAddress
!= 0) {
194 QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion
);
195 Features
= QemuFwCfgRead32 ();
196 if ((Features
& FW_CFG_F_DMA
) != 0) {
197 mFwCfgDmaAddress
= FwCfgDmaAddress
;
198 InternalQemuFwCfgReadBytes
= DmaReadBytes
;
199 InternalQemuFwCfgWriteBytes
= DmaWriteBytes
;
200 InternalQemuFwCfgSkipBytes
= DmaSkipBytes
;
204 mFwCfgSelectorAddress
= 0;
205 mFwCfgDataAddress
= 0;
208 return RETURN_SUCCESS
;
213 Selects a firmware configuration item for reading.
215 Following this call, any data read from this item will start from the
216 beginning of the configuration item's data.
218 @param[in] QemuFwCfgItem Firmware Configuration item to read
223 QemuFwCfgSelectItem (
224 IN FIRMWARE_CONFIG_ITEM QemuFwCfgItem
227 if (QemuFwCfgIsAvailable ()) {
228 MmioWrite16 (mFwCfgSelectorAddress
, SwapBytes16 ((UINT16
)QemuFwCfgItem
));
234 Slow READ_BYTES_FUNCTION.
241 IN VOID
*Buffer OPTIONAL
248 #ifdef MDE_CPU_AARCH64
258 #ifdef MDE_CPU_AARCH64
260 *(UINT64
*)Ptr
= MmioRead64 (mFwCfgDataAddress
);
264 *(UINT32
*)Ptr
= MmioRead32 (mFwCfgDataAddress
);
269 *(UINT32
*)Ptr
= MmioRead32 (mFwCfgDataAddress
);
275 *(UINT16
*)Ptr
= MmioRead16 (mFwCfgDataAddress
);
279 *Ptr
= MmioRead8 (mFwCfgDataAddress
);
285 Transfer an array of bytes, or skip a number of bytes, using the DMA
288 @param[in] Size Size in bytes to transfer or skip.
290 @param[in,out] Buffer Buffer to read data into or write data from. Ignored,
291 and may be NULL, if Size is zero, or Control is
294 @param[in] Control One of the following:
295 FW_CFG_DMA_CTL_WRITE - write to fw_cfg from Buffer.
296 FW_CFG_DMA_CTL_READ - read from fw_cfg into Buffer.
297 FW_CFG_DMA_CTL_SKIP - skip bytes in fw_cfg.
303 IN OUT VOID
*Buffer OPTIONAL
,
307 volatile FW_CFG_DMA_ACCESS Access
;
310 ASSERT (Control
== FW_CFG_DMA_CTL_WRITE
|| Control
== FW_CFG_DMA_CTL_READ
||
311 Control
== FW_CFG_DMA_CTL_SKIP
);
317 ASSERT (Size
<= MAX_UINT32
);
319 Access
.Control
= SwapBytes32 (Control
);
320 Access
.Length
= SwapBytes32 ((UINT32
)Size
);
321 Access
.Address
= SwapBytes64 ((UINT64
)(UINTN
)Buffer
);
324 // We shouldn't start the transfer before setting up Access.
329 // This will fire off the transfer.
331 #ifdef MDE_CPU_AARCH64
332 MmioWrite64 (mFwCfgDmaAddress
, SwapBytes64 ((UINT64
)&Access
));
334 MmioWrite32 ((UINT32
)(mFwCfgDmaAddress
+ 4), SwapBytes32 ((UINT32
)&Access
));
338 // We shouldn't look at Access.Control before starting the transfer.
343 Status
= SwapBytes32 (Access
.Control
);
344 ASSERT ((Status
& FW_CFG_DMA_CTL_ERROR
) == 0);
345 } while (Status
!= 0);
348 // The caller will want to access the transferred data.
355 Fast READ_BYTES_FUNCTION.
362 IN VOID
*Buffer OPTIONAL
365 DmaTransferBytes (Size
, Buffer
, FW_CFG_DMA_CTL_READ
);
370 Reads firmware configuration bytes into a buffer
372 If called multiple times, then the data read will continue at the offset of
373 the firmware configuration item where the previous read ended.
375 @param[in] Size Size in bytes to read
376 @param[in] Buffer Buffer to store data into
386 if (QemuFwCfgIsAvailable ()) {
387 InternalQemuFwCfgReadBytes (Size
, Buffer
);
389 ZeroMem (Buffer
, Size
);
395 Slow WRITE_BYTES_FUNCTION.
402 IN VOID
*Buffer OPTIONAL
407 for (Idx
= 0; Idx
< Size
; ++Idx
) {
408 MmioWrite8 (mFwCfgDataAddress
, ((UINT8
*)Buffer
)[Idx
]);
414 Fast WRITE_BYTES_FUNCTION.
421 IN VOID
*Buffer OPTIONAL
424 DmaTransferBytes (Size
, Buffer
, FW_CFG_DMA_CTL_WRITE
);
429 Write firmware configuration bytes from a buffer
431 If called multiple times, then the data written will continue at the offset
432 of the firmware configuration item where the previous write ended.
434 @param[in] Size Size in bytes to write
435 @param[in] Buffer Buffer to read data from
440 QemuFwCfgWriteBytes (
445 if (QemuFwCfgIsAvailable ()) {
446 InternalQemuFwCfgWriteBytes (Size
, Buffer
);
452 Slow SKIP_BYTES_FUNCTION.
462 UINT8 SkipBuffer
[256];
465 // Emulate the skip by reading data in chunks, and throwing it away. The
466 // implementation below doesn't affect the static data footprint for client
467 // modules. Large skips are not expected, therefore this fallback is not
468 // performance critical. The size of SkipBuffer is thought not to exert a
469 // large pressure on the stack.
472 ChunkSize
= MIN (Size
, sizeof SkipBuffer
);
473 MmioReadBytes (ChunkSize
, SkipBuffer
);
480 Fast SKIP_BYTES_FUNCTION.
489 DmaTransferBytes (Size
, NULL
, FW_CFG_DMA_CTL_SKIP
);
494 Skip bytes in the firmware configuration item.
496 Increase the offset of the firmware configuration item without transferring
497 bytes between the item and a caller-provided buffer. Subsequent read, write
498 or skip operations will commence at the increased offset.
500 @param[in] Size Number of bytes to skip.
508 if (QemuFwCfgIsAvailable ()) {
509 InternalQemuFwCfgSkipBytes (Size
);
515 Reads a UINT8 firmware configuration value
517 @return Value of Firmware Configuration item read
528 QemuFwCfgReadBytes (sizeof Result
, &Result
);
534 Reads a UINT16 firmware configuration value
536 @return Value of Firmware Configuration item read
547 QemuFwCfgReadBytes (sizeof Result
, &Result
);
553 Reads a UINT32 firmware configuration value
555 @return Value of Firmware Configuration item read
566 QemuFwCfgReadBytes (sizeof Result
, &Result
);
572 Reads a UINT64 firmware configuration value
574 @return Value of Firmware Configuration item read
585 QemuFwCfgReadBytes (sizeof Result
, &Result
);
591 Find the configuration item corresponding to the firmware configuration file.
593 @param[in] Name Name of file to look up.
594 @param[out] Item Configuration item corresponding to the file, to be passed
595 to QemuFwCfgSelectItem ().
596 @param[out] Size Number of bytes in the file.
598 @retval RETURN_SUCCESS If file is found.
599 @retval RETURN_NOT_FOUND If file is not found.
600 @retval RETURN_UNSUPPORTED If firmware configuration is unavailable.
606 IN CONST CHAR8
*Name
,
607 OUT FIRMWARE_CONFIG_ITEM
*Item
,
614 if (!QemuFwCfgIsAvailable ()) {
615 return RETURN_UNSUPPORTED
;
618 QemuFwCfgSelectItem (QemuFwCfgItemFileDir
);
619 Count
= SwapBytes32 (QemuFwCfgRead32 ());
621 for (Idx
= 0; Idx
< Count
; ++Idx
) {
624 CHAR8 FName
[QEMU_FW_CFG_FNAME_SIZE
];
626 FileSize
= QemuFwCfgRead32 ();
627 FileSelect
= QemuFwCfgRead16 ();
628 QemuFwCfgRead16 (); // skip the field called "reserved"
629 InternalQemuFwCfgReadBytes (sizeof (FName
), FName
);
631 if (AsciiStrCmp (Name
, FName
) == 0) {
632 *Item
= (FIRMWARE_CONFIG_ITEM
) SwapBytes16 (FileSelect
);
633 *Size
= SwapBytes32 (FileSize
);
634 return RETURN_SUCCESS
;
638 return RETURN_NOT_FOUND
;
643 Determine if S3 support is explicitly enabled.
645 @retval TRUE if S3 support is explicitly enabled.
646 FALSE otherwise. This includes unavailability of the firmware
647 configuration interface.