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 // Forward declaration of the two implementations we have.
61 STATIC READ_BYTES_FUNCTION MmioReadBytes
;
62 STATIC WRITE_BYTES_FUNCTION MmioWriteBytes
;
63 STATIC READ_BYTES_FUNCTION DmaReadBytes
;
64 STATIC WRITE_BYTES_FUNCTION DmaWriteBytes
;
67 // These correspond to the implementation we detect at runtime.
69 STATIC READ_BYTES_FUNCTION
*InternalQemuFwCfgReadBytes
= MmioReadBytes
;
70 STATIC WRITE_BYTES_FUNCTION
*InternalQemuFwCfgWriteBytes
= MmioWriteBytes
;
74 Returns a boolean indicating if the firmware configuration interface
77 This function may change fw_cfg state.
79 @retval TRUE The interface is available
80 @retval FALSE The interface is not available
85 QemuFwCfgIsAvailable (
89 return (BOOLEAN
)(mFwCfgSelectorAddress
!= 0 && mFwCfgDataAddress
!= 0);
100 FDT_CLIENT_PROTOCOL
*FdtClient
;
103 UINTN AddressCells
, SizeCells
;
104 UINT64 FwCfgSelectorAddress
;
105 UINT64 FwCfgSelectorSize
;
106 UINT64 FwCfgDataAddress
;
107 UINT64 FwCfgDataSize
;
108 UINT64 FwCfgDmaAddress
;
111 Status
= gBS
->LocateProtocol (&gFdtClientProtocolGuid
, NULL
,
112 (VOID
**)&FdtClient
);
113 ASSERT_EFI_ERROR (Status
);
115 Status
= FdtClient
->FindCompatibleNodeReg (FdtClient
, "qemu,fw-cfg-mmio",
116 (CONST VOID
**)&Reg
, &AddressCells
, &SizeCells
,
118 if (EFI_ERROR (Status
)) {
120 "%a: No 'qemu,fw-cfg-mmio' compatible DT node found (Status == %r)\n",
121 __FUNCTION__
, Status
));
125 ASSERT (AddressCells
== 2);
126 ASSERT (SizeCells
== 2);
127 ASSERT (RegSize
== 2 * sizeof (UINT64
));
129 FwCfgDataAddress
= SwapBytes64 (Reg
[0]);
131 FwCfgSelectorAddress
= FwCfgDataAddress
+ FwCfgDataSize
;
132 FwCfgSelectorSize
= 2;
135 // The following ASSERT()s express
137 // Address + Size - 1 <= MAX_UINTN
139 // for both registers, that is, that the last byte in each MMIO range is
140 // expressible as a MAX_UINTN. The form below is mathematically
141 // equivalent, and it also prevents any unsigned overflow before the
144 ASSERT (FwCfgSelectorAddress
<= MAX_UINTN
- FwCfgSelectorSize
+ 1);
145 ASSERT (FwCfgDataAddress
<= MAX_UINTN
- FwCfgDataSize
+ 1);
147 mFwCfgSelectorAddress
= FwCfgSelectorAddress
;
148 mFwCfgDataAddress
= FwCfgDataAddress
;
150 DEBUG ((EFI_D_INFO
, "Found FwCfg @ 0x%Lx/0x%Lx\n", FwCfgSelectorAddress
,
153 if (SwapBytes64 (Reg
[1]) >= 0x18) {
154 FwCfgDmaAddress
= FwCfgDataAddress
+ 0x10;
158 // See explanation above.
160 ASSERT (FwCfgDmaAddress
<= MAX_UINTN
- FwCfgDmaSize
+ 1);
162 DEBUG ((EFI_D_INFO
, "Found FwCfg DMA @ 0x%Lx\n", FwCfgDmaAddress
));
167 if (QemuFwCfgIsAvailable ()) {
170 QemuFwCfgSelectItem (QemuFwCfgItemSignature
);
171 Signature
= QemuFwCfgRead32 ();
172 if (Signature
== SIGNATURE_32 ('Q', 'E', 'M', 'U')) {
174 // For DMA support, we require the DTB to advertise the register, and the
175 // feature bitmap (which we read without DMA) to confirm the feature.
177 if (FwCfgDmaAddress
!= 0) {
180 QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion
);
181 Features
= QemuFwCfgRead32 ();
182 if ((Features
& FW_CFG_F_DMA
) != 0) {
183 mFwCfgDmaAddress
= FwCfgDmaAddress
;
184 InternalQemuFwCfgReadBytes
= DmaReadBytes
;
185 InternalQemuFwCfgWriteBytes
= DmaWriteBytes
;
189 mFwCfgSelectorAddress
= 0;
190 mFwCfgDataAddress
= 0;
193 return RETURN_SUCCESS
;
198 Selects a firmware configuration item for reading.
200 Following this call, any data read from this item will start from the
201 beginning of the configuration item's data.
203 @param[in] QemuFwCfgItem Firmware Configuration item to read
208 QemuFwCfgSelectItem (
209 IN FIRMWARE_CONFIG_ITEM QemuFwCfgItem
212 if (QemuFwCfgIsAvailable ()) {
213 MmioWrite16 (mFwCfgSelectorAddress
, SwapBytes16 ((UINT16
)QemuFwCfgItem
));
219 Slow READ_BYTES_FUNCTION.
226 IN VOID
*Buffer OPTIONAL
233 #ifdef MDE_CPU_AARCH64
243 #ifdef MDE_CPU_AARCH64
245 *(UINT64
*)Ptr
= MmioRead64 (mFwCfgDataAddress
);
249 *(UINT32
*)Ptr
= MmioRead32 (mFwCfgDataAddress
);
254 *(UINT32
*)Ptr
= MmioRead32 (mFwCfgDataAddress
);
260 *(UINT16
*)Ptr
= MmioRead16 (mFwCfgDataAddress
);
264 *Ptr
= MmioRead8 (mFwCfgDataAddress
);
270 Transfer an array of bytes, or skip a number of bytes, using the DMA
273 @param[in] Size Size in bytes to transfer or skip.
275 @param[in,out] Buffer Buffer to read data into or write data from. Ignored,
276 and may be NULL, if Size is zero, or Control is
279 @param[in] Control One of the following:
280 FW_CFG_DMA_CTL_WRITE - write to fw_cfg from Buffer.
281 FW_CFG_DMA_CTL_READ - read from fw_cfg into Buffer.
282 FW_CFG_DMA_CTL_SKIP - skip bytes in fw_cfg.
288 IN OUT VOID
*Buffer OPTIONAL
,
292 volatile FW_CFG_DMA_ACCESS Access
;
295 ASSERT (Control
== FW_CFG_DMA_CTL_WRITE
|| Control
== FW_CFG_DMA_CTL_READ
||
296 Control
== FW_CFG_DMA_CTL_SKIP
);
302 ASSERT (Size
<= MAX_UINT32
);
304 Access
.Control
= SwapBytes32 (Control
);
305 Access
.Length
= SwapBytes32 ((UINT32
)Size
);
306 Access
.Address
= SwapBytes64 ((UINT64
)(UINTN
)Buffer
);
309 // We shouldn't start the transfer before setting up Access.
314 // This will fire off the transfer.
316 #ifdef MDE_CPU_AARCH64
317 MmioWrite64 (mFwCfgDmaAddress
, SwapBytes64 ((UINT64
)&Access
));
319 MmioWrite32 ((UINT32
)(mFwCfgDmaAddress
+ 4), SwapBytes32 ((UINT32
)&Access
));
323 // We shouldn't look at Access.Control before starting the transfer.
328 Status
= SwapBytes32 (Access
.Control
);
329 ASSERT ((Status
& FW_CFG_DMA_CTL_ERROR
) == 0);
330 } while (Status
!= 0);
333 // The caller will want to access the transferred data.
340 Fast READ_BYTES_FUNCTION.
347 IN VOID
*Buffer OPTIONAL
350 DmaTransferBytes (Size
, Buffer
, FW_CFG_DMA_CTL_READ
);
355 Reads firmware configuration bytes into a buffer
357 If called multiple times, then the data read will continue at the offset of
358 the firmware configuration item where the previous read ended.
360 @param[in] Size Size in bytes to read
361 @param[in] Buffer Buffer to store data into
371 if (QemuFwCfgIsAvailable ()) {
372 InternalQemuFwCfgReadBytes (Size
, Buffer
);
374 ZeroMem (Buffer
, Size
);
380 Slow WRITE_BYTES_FUNCTION.
387 IN VOID
*Buffer OPTIONAL
392 for (Idx
= 0; Idx
< Size
; ++Idx
) {
393 MmioWrite8 (mFwCfgDataAddress
, ((UINT8
*)Buffer
)[Idx
]);
399 Fast WRITE_BYTES_FUNCTION.
406 IN VOID
*Buffer OPTIONAL
409 DmaTransferBytes (Size
, Buffer
, FW_CFG_DMA_CTL_WRITE
);
414 Write firmware configuration bytes from a buffer
416 If called multiple times, then the data written will continue at the offset
417 of the firmware configuration item where the previous write ended.
419 @param[in] Size Size in bytes to write
420 @param[in] Buffer Buffer to read data from
425 QemuFwCfgWriteBytes (
430 if (QemuFwCfgIsAvailable ()) {
431 InternalQemuFwCfgWriteBytes (Size
, Buffer
);
437 Reads a UINT8 firmware configuration value
439 @return Value of Firmware Configuration item read
450 QemuFwCfgReadBytes (sizeof Result
, &Result
);
456 Reads a UINT16 firmware configuration value
458 @return Value of Firmware Configuration item read
469 QemuFwCfgReadBytes (sizeof Result
, &Result
);
475 Reads a UINT32 firmware configuration value
477 @return Value of Firmware Configuration item read
488 QemuFwCfgReadBytes (sizeof Result
, &Result
);
494 Reads a UINT64 firmware configuration value
496 @return Value of Firmware Configuration item read
507 QemuFwCfgReadBytes (sizeof Result
, &Result
);
513 Find the configuration item corresponding to the firmware configuration file.
515 @param[in] Name Name of file to look up.
516 @param[out] Item Configuration item corresponding to the file, to be passed
517 to QemuFwCfgSelectItem ().
518 @param[out] Size Number of bytes in the file.
520 @retval RETURN_SUCCESS If file is found.
521 @retval RETURN_NOT_FOUND If file is not found.
522 @retval RETURN_UNSUPPORTED If firmware configuration is unavailable.
528 IN CONST CHAR8
*Name
,
529 OUT FIRMWARE_CONFIG_ITEM
*Item
,
536 if (!QemuFwCfgIsAvailable ()) {
537 return RETURN_UNSUPPORTED
;
540 QemuFwCfgSelectItem (QemuFwCfgItemFileDir
);
541 Count
= SwapBytes32 (QemuFwCfgRead32 ());
543 for (Idx
= 0; Idx
< Count
; ++Idx
) {
546 CHAR8 FName
[QEMU_FW_CFG_FNAME_SIZE
];
548 FileSize
= QemuFwCfgRead32 ();
549 FileSelect
= QemuFwCfgRead16 ();
550 QemuFwCfgRead16 (); // skip the field called "reserved"
551 InternalQemuFwCfgReadBytes (sizeof (FName
), FName
);
553 if (AsciiStrCmp (Name
, FName
) == 0) {
554 *Item
= (FIRMWARE_CONFIG_ITEM
) SwapBytes16 (FileSelect
);
555 *Size
= SwapBytes32 (FileSize
);
556 return RETURN_SUCCESS
;
560 return RETURN_NOT_FOUND
;
565 Determine if S3 support is explicitly enabled.
567 @retval TRUE if S3 support is explicitly enabled.
568 FALSE otherwise. This includes unavailability of the firmware
569 configuration interface.