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 // Forward declaration of the two implementations we have.
48 STATIC READ_BYTES_FUNCTION MmioReadBytes
;
49 STATIC READ_BYTES_FUNCTION DmaReadBytes
;
52 // This points to the one we detect at runtime.
54 STATIC READ_BYTES_FUNCTION
*InternalQemuFwCfgReadBytes
= MmioReadBytes
;
57 // Communication structure for DmaReadBytes(). All fields are encoded in big
69 // Macros for the FW_CFG_DMA_ACCESS.Control bitmap (in native encoding).
71 #define FW_CFG_DMA_CTL_ERROR BIT0
72 #define FW_CFG_DMA_CTL_READ BIT1
73 #define FW_CFG_DMA_CTL_SKIP BIT2
74 #define FW_CFG_DMA_CTL_SELECT BIT3
78 Returns a boolean indicating if the firmware configuration interface is
79 available for library-internal purposes.
81 This function never changes fw_cfg state.
83 @retval TRUE The interface is available internally.
84 @retval FALSE The interface is not available internally.
88 InternalQemuFwCfgIsAvailable (
92 return (BOOLEAN
)(mFwCfgSelectorAddress
!= 0 && mFwCfgDataAddress
!= 0);
97 Returns a boolean indicating if the firmware configuration interface
100 This function may change fw_cfg state.
102 @retval TRUE The interface is available
103 @retval FALSE The interface is not available
108 QemuFwCfgIsAvailable (
112 return InternalQemuFwCfgIsAvailable ();
118 QemuFwCfgInitialize (
123 FDT_CLIENT_PROTOCOL
*FdtClient
;
125 UINT32 RegElemSize
, RegSize
;
126 UINT64 FwCfgSelectorAddress
;
127 UINT64 FwCfgSelectorSize
;
128 UINT64 FwCfgDataAddress
;
129 UINT64 FwCfgDataSize
;
130 UINT64 FwCfgDmaAddress
;
133 Status
= gBS
->LocateProtocol (&gFdtClientProtocolGuid
, NULL
,
134 (VOID
**)&FdtClient
);
135 ASSERT_EFI_ERROR (Status
);
137 Status
= FdtClient
->FindCompatibleNodeReg (FdtClient
, "qemu,fw-cfg-mmio",
138 (CONST VOID
**)&Reg
, &RegElemSize
, &RegSize
);
139 if (EFI_ERROR (Status
)) {
141 "%a: No 'qemu,fw-cfg-mmio' compatible DT node found (Status == %r)\n",
142 __FUNCTION__
, Status
));
146 ASSERT (RegElemSize
== sizeof (UINT64
));
147 ASSERT (RegSize
== 2 * sizeof (UINT64
));
149 FwCfgDataAddress
= SwapBytes64 (Reg
[0]);
151 FwCfgSelectorAddress
= FwCfgDataAddress
+ FwCfgDataSize
;
152 FwCfgSelectorSize
= 2;
155 // The following ASSERT()s express
157 // Address + Size - 1 <= MAX_UINTN
159 // for both registers, that is, that the last byte in each MMIO range is
160 // expressible as a MAX_UINTN. The form below is mathematically
161 // equivalent, and it also prevents any unsigned overflow before the
164 ASSERT (FwCfgSelectorAddress
<= MAX_UINTN
- FwCfgSelectorSize
+ 1);
165 ASSERT (FwCfgDataAddress
<= MAX_UINTN
- FwCfgDataSize
+ 1);
167 mFwCfgSelectorAddress
= FwCfgSelectorAddress
;
168 mFwCfgDataAddress
= FwCfgDataAddress
;
170 DEBUG ((EFI_D_INFO
, "Found FwCfg @ 0x%Lx/0x%Lx\n", FwCfgSelectorAddress
,
173 if (SwapBytes64 (Reg
[1]) >= 0x18) {
174 FwCfgDmaAddress
= FwCfgDataAddress
+ 0x10;
178 // See explanation above.
180 ASSERT (FwCfgDmaAddress
<= MAX_UINTN
- FwCfgDmaSize
+ 1);
182 DEBUG ((EFI_D_INFO
, "Found FwCfg DMA @ 0x%Lx\n", FwCfgDmaAddress
));
187 if (InternalQemuFwCfgIsAvailable ()) {
190 QemuFwCfgSelectItem (QemuFwCfgItemSignature
);
191 Signature
= QemuFwCfgRead32 ();
192 if (Signature
== SIGNATURE_32 ('Q', 'E', 'M', 'U')) {
194 // For DMA support, we require the DTB to advertise the register, and the
195 // feature bitmap (which we read without DMA) to confirm the feature.
197 if (FwCfgDmaAddress
!= 0) {
200 QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion
);
201 Features
= QemuFwCfgRead32 ();
202 if ((Features
& BIT1
) != 0) {
203 mFwCfgDmaAddress
= FwCfgDmaAddress
;
204 InternalQemuFwCfgReadBytes
= DmaReadBytes
;
208 mFwCfgSelectorAddress
= 0;
209 mFwCfgDataAddress
= 0;
212 return RETURN_SUCCESS
;
217 Selects a firmware configuration item for reading.
219 Following this call, any data read from this item will start from the
220 beginning of the configuration item's data.
222 @param[in] QemuFwCfgItem Firmware Configuration item to read
227 QemuFwCfgSelectItem (
228 IN FIRMWARE_CONFIG_ITEM QemuFwCfgItem
231 if (InternalQemuFwCfgIsAvailable ()) {
232 MmioWrite16 (mFwCfgSelectorAddress
, SwapBytes16 ((UINT16
)QemuFwCfgItem
));
238 Slow READ_BYTES_FUNCTION.
245 IN VOID
*Buffer OPTIONAL
252 #ifdef MDE_CPU_AARCH64
262 #ifdef MDE_CPU_AARCH64
264 *(UINT64
*)Ptr
= MmioRead64 (mFwCfgDataAddress
);
268 *(UINT32
*)Ptr
= MmioRead32 (mFwCfgDataAddress
);
273 *(UINT32
*)Ptr
= MmioRead32 (mFwCfgDataAddress
);
279 *(UINT16
*)Ptr
= MmioRead16 (mFwCfgDataAddress
);
283 *Ptr
= MmioRead8 (mFwCfgDataAddress
);
289 Fast READ_BYTES_FUNCTION.
296 IN VOID
*Buffer OPTIONAL
299 volatile FW_CFG_DMA_ACCESS Access
;
306 ASSERT (Size
<= MAX_UINT32
);
308 Access
.Control
= SwapBytes32 (FW_CFG_DMA_CTL_READ
);
309 Access
.Length
= SwapBytes32 ((UINT32
)Size
);
310 Access
.Address
= SwapBytes64 ((UINT64
)(UINTN
)Buffer
);
313 // We shouldn't start the transfer before setting up Access.
318 // This will fire off the transfer.
320 #ifdef MDE_CPU_AARCH64
321 MmioWrite64 (mFwCfgDmaAddress
, SwapBytes64 ((UINT64
)&Access
));
323 MmioWrite32 ((UINT32
)(mFwCfgDmaAddress
+ 4), SwapBytes32 ((UINT32
)&Access
));
327 // We shouldn't look at Access.Control before starting the transfer.
332 Status
= SwapBytes32 (Access
.Control
);
333 ASSERT ((Status
& FW_CFG_DMA_CTL_ERROR
) == 0);
334 } while (Status
!= 0);
337 // The caller will want to access the transferred data.
344 Reads firmware configuration bytes into a buffer
346 If called multiple times, then the data read will continue at the offset of
347 the firmware configuration item where the previous read ended.
349 @param[in] Size Size in bytes to read
350 @param[in] Buffer Buffer to store data into
360 if (InternalQemuFwCfgIsAvailable ()) {
361 InternalQemuFwCfgReadBytes (Size
, Buffer
);
363 ZeroMem (Buffer
, Size
);
368 Write firmware configuration bytes from a buffer
370 If called multiple times, then the data written will continue at the offset
371 of the firmware configuration item where the previous write ended.
373 @param[in] Size Size in bytes to write
374 @param[in] Buffer Buffer to read data from
379 QemuFwCfgWriteBytes (
384 if (InternalQemuFwCfgIsAvailable ()) {
387 for (Idx
= 0; Idx
< Size
; ++Idx
) {
388 MmioWrite8 (mFwCfgDataAddress
, ((UINT8
*)Buffer
)[Idx
]);
395 Reads a UINT8 firmware configuration value
397 @return Value of Firmware Configuration item read
408 QemuFwCfgReadBytes (sizeof Result
, &Result
);
414 Reads a UINT16 firmware configuration value
416 @return Value of Firmware Configuration item read
427 QemuFwCfgReadBytes (sizeof Result
, &Result
);
433 Reads a UINT32 firmware configuration value
435 @return Value of Firmware Configuration item read
446 QemuFwCfgReadBytes (sizeof Result
, &Result
);
452 Reads a UINT64 firmware configuration value
454 @return Value of Firmware Configuration item read
465 QemuFwCfgReadBytes (sizeof Result
, &Result
);
471 Find the configuration item corresponding to the firmware configuration file.
473 @param[in] Name Name of file to look up.
474 @param[out] Item Configuration item corresponding to the file, to be passed
475 to QemuFwCfgSelectItem ().
476 @param[out] Size Number of bytes in the file.
478 @retval RETURN_SUCCESS If file is found.
479 @retval RETURN_NOT_FOUND If file is not found.
480 @retval RETURN_UNSUPPORTED If firmware configuration is unavailable.
486 IN CONST CHAR8
*Name
,
487 OUT FIRMWARE_CONFIG_ITEM
*Item
,
494 if (!InternalQemuFwCfgIsAvailable ()) {
495 return RETURN_UNSUPPORTED
;
498 QemuFwCfgSelectItem (QemuFwCfgItemFileDir
);
499 Count
= SwapBytes32 (QemuFwCfgRead32 ());
501 for (Idx
= 0; Idx
< Count
; ++Idx
) {
504 CHAR8 FName
[QEMU_FW_CFG_FNAME_SIZE
];
506 FileSize
= QemuFwCfgRead32 ();
507 FileSelect
= QemuFwCfgRead16 ();
508 QemuFwCfgRead16 (); // skip the field called "reserved"
509 InternalQemuFwCfgReadBytes (sizeof (FName
), FName
);
511 if (AsciiStrCmp (Name
, FName
) == 0) {
512 *Item
= (FIRMWARE_CONFIG_ITEM
) SwapBytes16 (FileSelect
);
513 *Size
= SwapBytes32 (FileSize
);
514 return RETURN_SUCCESS
;
518 return RETURN_NOT_FOUND
;
523 Determine if S3 support is explicitly enabled.
525 @retval TRUE if S3 support is explicitly enabled.
526 FALSE otherwise. This includes unavailability of the firmware
527 configuration interface.