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.
17 #include <Library/BaseLib.h>
18 #include <Library/BaseMemoryLib.h>
19 #include <Library/DebugLib.h>
20 #include <Library/IoLib.h>
21 #include <Library/PcdLib.h>
22 #include <Library/QemuFwCfgLib.h>
24 STATIC UINTN mFwCfgSelectorAddress
;
25 STATIC UINTN mFwCfgDataAddress
;
26 STATIC UINTN mFwCfgDmaAddress
;
29 Reads firmware configuration bytes into a buffer
31 @param[in] Size Size in bytes to read
32 @param[in] Buffer Buffer to store data into (OPTIONAL if Size is 0)
36 VOID (EFIAPI READ_BYTES_FUNCTION
) (
38 IN VOID
*Buffer OPTIONAL
42 // Forward declaration of the two implementations we have.
44 STATIC READ_BYTES_FUNCTION MmioReadBytes
;
45 STATIC READ_BYTES_FUNCTION DmaReadBytes
;
48 // This points to the one we detect at runtime.
50 STATIC READ_BYTES_FUNCTION
*InternalQemuFwCfgReadBytes
= MmioReadBytes
;
53 // Communication structure for DmaReadBytes(). All fields are encoded in big
65 // Macros for the FW_CFG_DMA_ACCESS.Control bitmap (in native encoding).
67 #define FW_CFG_DMA_CTL_ERROR BIT0
68 #define FW_CFG_DMA_CTL_READ BIT1
69 #define FW_CFG_DMA_CTL_SKIP BIT2
70 #define FW_CFG_DMA_CTL_SELECT BIT3
74 Returns a boolean indicating if the firmware configuration interface is
75 available for library-internal purposes.
77 This function never changes fw_cfg state.
79 @retval TRUE The interface is available internally.
80 @retval FALSE The interface is not available internally.
84 InternalQemuFwCfgIsAvailable (
88 return (BOOLEAN
)(mFwCfgSelectorAddress
!= 0 && mFwCfgDataAddress
!= 0);
93 Returns a boolean indicating if the firmware configuration interface
96 This function may change fw_cfg state.
98 @retval TRUE The interface is available
99 @retval FALSE The interface is not available
104 QemuFwCfgIsAvailable (
108 return InternalQemuFwCfgIsAvailable ();
114 QemuFwCfgInitialize (
118 mFwCfgSelectorAddress
= (UINTN
)PcdGet64 (PcdFwCfgSelectorAddress
);
119 mFwCfgDataAddress
= (UINTN
)PcdGet64 (PcdFwCfgDataAddress
);
121 if (InternalQemuFwCfgIsAvailable ()) {
124 QemuFwCfgSelectItem (QemuFwCfgItemSignature
);
125 Signature
= QemuFwCfgRead32 ();
126 if (Signature
== SIGNATURE_32 ('Q', 'E', 'M', 'U')) {
128 // For DMA support, we require the DTB to advertise the register, and the
129 // feature bitmap (which we read without DMA) to confirm the feature.
131 if (PcdGet64 (PcdFwCfgDmaAddress
) != 0) {
134 QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion
);
135 Features
= QemuFwCfgRead32 ();
136 if ((Features
& BIT1
) != 0) {
137 mFwCfgDmaAddress
= PcdGet64 (PcdFwCfgDmaAddress
);
138 InternalQemuFwCfgReadBytes
= DmaReadBytes
;
142 mFwCfgSelectorAddress
= 0;
143 mFwCfgDataAddress
= 0;
146 return RETURN_SUCCESS
;
151 Selects a firmware configuration item for reading.
153 Following this call, any data read from this item will start from the
154 beginning of the configuration item's data.
156 @param[in] QemuFwCfgItem Firmware Configuration item to read
161 QemuFwCfgSelectItem (
162 IN FIRMWARE_CONFIG_ITEM QemuFwCfgItem
165 if (InternalQemuFwCfgIsAvailable ()) {
166 MmioWrite16 (mFwCfgSelectorAddress
, SwapBytes16 ((UINT16
)QemuFwCfgItem
));
172 Slow READ_BYTES_FUNCTION.
179 IN VOID
*Buffer OPTIONAL
186 #ifdef MDE_CPU_AARCH64
196 #ifdef MDE_CPU_AARCH64
198 *(UINT64
*)Ptr
= MmioRead64 (mFwCfgDataAddress
);
202 *(UINT32
*)Ptr
= MmioRead32 (mFwCfgDataAddress
);
207 *(UINT32
*)Ptr
= MmioRead32 (mFwCfgDataAddress
);
213 *(UINT16
*)Ptr
= MmioRead16 (mFwCfgDataAddress
);
217 *Ptr
= MmioRead8 (mFwCfgDataAddress
);
223 Fast READ_BYTES_FUNCTION.
230 IN VOID
*Buffer OPTIONAL
233 volatile FW_CFG_DMA_ACCESS Access
;
240 ASSERT (Size
<= MAX_UINT32
);
242 Access
.Control
= SwapBytes32 (FW_CFG_DMA_CTL_READ
);
243 Access
.Length
= SwapBytes32 ((UINT32
)Size
);
244 Access
.Address
= SwapBytes64 ((UINT64
)(UINTN
)Buffer
);
247 // We shouldn't start the transfer before setting up Access.
252 // This will fire off the transfer.
254 #ifdef MDE_CPU_AARCH64
255 MmioWrite64 (mFwCfgDmaAddress
, SwapBytes64 ((UINT64
)&Access
));
257 MmioWrite32 ((UINT32
)(mFwCfgDmaAddress
+ 4), SwapBytes32 ((UINT32
)&Access
));
261 // We shouldn't look at Access.Control before starting the transfer.
266 Status
= SwapBytes32 (Access
.Control
);
267 ASSERT ((Status
& FW_CFG_DMA_CTL_ERROR
) == 0);
268 } while (Status
!= 0);
271 // The caller will want to access the transferred data.
278 Reads firmware configuration bytes into a buffer
280 If called multiple times, then the data read will continue at the offset of
281 the firmware configuration item where the previous read ended.
283 @param[in] Size Size in bytes to read
284 @param[in] Buffer Buffer to store data into
294 if (InternalQemuFwCfgIsAvailable ()) {
295 InternalQemuFwCfgReadBytes (Size
, Buffer
);
297 ZeroMem (Buffer
, Size
);
302 Write firmware configuration bytes from a buffer
304 If called multiple times, then the data written will continue at the offset
305 of the firmware configuration item where the previous write ended.
307 @param[in] Size Size in bytes to write
308 @param[in] Buffer Buffer to read data from
313 QemuFwCfgWriteBytes (
318 if (InternalQemuFwCfgIsAvailable ()) {
321 for (Idx
= 0; Idx
< Size
; ++Idx
) {
322 MmioWrite8 (mFwCfgDataAddress
, ((UINT8
*)Buffer
)[Idx
]);
329 Reads a UINT8 firmware configuration value
331 @return Value of Firmware Configuration item read
342 QemuFwCfgReadBytes (sizeof Result
, &Result
);
348 Reads a UINT16 firmware configuration value
350 @return Value of Firmware Configuration item read
361 QemuFwCfgReadBytes (sizeof Result
, &Result
);
367 Reads a UINT32 firmware configuration value
369 @return Value of Firmware Configuration item read
380 QemuFwCfgReadBytes (sizeof Result
, &Result
);
386 Reads a UINT64 firmware configuration value
388 @return Value of Firmware Configuration item read
399 QemuFwCfgReadBytes (sizeof Result
, &Result
);
405 Find the configuration item corresponding to the firmware configuration file.
407 @param[in] Name Name of file to look up.
408 @param[out] Item Configuration item corresponding to the file, to be passed
409 to QemuFwCfgSelectItem ().
410 @param[out] Size Number of bytes in the file.
412 @retval RETURN_SUCCESS If file is found.
413 @retval RETURN_NOT_FOUND If file is not found.
414 @retval RETURN_UNSUPPORTED If firmware configuration is unavailable.
420 IN CONST CHAR8
*Name
,
421 OUT FIRMWARE_CONFIG_ITEM
*Item
,
428 if (!InternalQemuFwCfgIsAvailable ()) {
429 return RETURN_UNSUPPORTED
;
432 QemuFwCfgSelectItem (QemuFwCfgItemFileDir
);
433 Count
= SwapBytes32 (QemuFwCfgRead32 ());
435 for (Idx
= 0; Idx
< Count
; ++Idx
) {
438 CHAR8 FName
[QEMU_FW_CFG_FNAME_SIZE
];
440 FileSize
= QemuFwCfgRead32 ();
441 FileSelect
= QemuFwCfgRead16 ();
442 QemuFwCfgRead16 (); // skip the field called "reserved"
443 InternalQemuFwCfgReadBytes (sizeof (FName
), FName
);
445 if (AsciiStrCmp (Name
, FName
) == 0) {
446 *Item
= (FIRMWARE_CONFIG_ITEM
) SwapBytes16 (FileSelect
);
447 *Size
= SwapBytes32 (FileSize
);
448 return RETURN_SUCCESS
;
452 return RETURN_NOT_FOUND
;
457 Determine if S3 support is explicitly enabled.
459 @retval TRUE if S3 support is explicitly enabled.
460 FALSE otherwise. This includes unavailability of the firmware
461 configuration interface.