3 Stateful and implicitly initialized fw_cfg library implementation.
5 Copyright (C) 2013, Red Hat, Inc.
6 Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
7 Copyright (c) 2017, Advanced Micro Devices. All rights reserved.<BR>
9 This program and the accompanying materials are licensed and made available
10 under the terms and conditions of the BSD License which accompanies this
11 distribution. The full text of the license may be found at
12 http://opensource.org/licenses/bsd-license.php
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
15 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 #include <Protocol/IoMmu.h>
22 #include <Library/BaseLib.h>
23 #include <Library/BaseMemoryLib.h>
24 #include <Library/IoLib.h>
25 #include <Library/DebugLib.h>
26 #include <Library/QemuFwCfgLib.h>
27 #include <Library/UefiBootServicesTableLib.h>
28 #include <Library/MemEncryptSevLib.h>
30 #include "QemuFwCfgLibInternal.h"
32 STATIC BOOLEAN mQemuFwCfgSupported
= FALSE
;
33 STATIC BOOLEAN mQemuFwCfgDmaSupported
;
35 STATIC EDKII_IOMMU_PROTOCOL
*mIoMmuProtocol
;
38 Returns a boolean indicating if the firmware configuration interface
41 This function may change fw_cfg state.
43 @retval TRUE The interface is available
44 @retval FALSE The interface is not available
49 QemuFwCfgIsAvailable (
53 return InternalQemuFwCfgIsAvailable ();
67 // Enable the access routines while probing to see if it is supported.
68 // For probing we always use the IO Port (IoReadFifo8()) access method.
70 mQemuFwCfgSupported
= TRUE
;
71 mQemuFwCfgDmaSupported
= FALSE
;
73 QemuFwCfgSelectItem (QemuFwCfgItemSignature
);
74 Signature
= QemuFwCfgRead32 ();
75 DEBUG ((EFI_D_INFO
, "FW CFG Signature: 0x%x\n", Signature
));
76 QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion
);
77 Revision
= QemuFwCfgRead32 ();
78 DEBUG ((EFI_D_INFO
, "FW CFG Revision: 0x%x\n", Revision
));
79 if ((Signature
!= SIGNATURE_32 ('Q', 'E', 'M', 'U')) ||
82 DEBUG ((EFI_D_INFO
, "QemuFwCfg interface not supported.\n"));
83 mQemuFwCfgSupported
= FALSE
;
84 return RETURN_SUCCESS
;
87 if ((Revision
& FW_CFG_F_DMA
) == 0) {
88 DEBUG ((DEBUG_INFO
, "QemuFwCfg interface (IO Port) is supported.\n"));
90 mQemuFwCfgDmaSupported
= TRUE
;
91 DEBUG ((DEBUG_INFO
, "QemuFwCfg interface (DMA) is supported.\n"));
94 if (mQemuFwCfgDmaSupported
&& MemEncryptSevIsEnabled ()) {
98 // IoMmuDxe driver must have installed the IOMMU protocol. If we are not
99 // able to locate the protocol then something must have gone wrong.
101 Status
= gBS
->LocateProtocol (&gEdkiiIoMmuProtocolGuid
, NULL
,
102 (VOID
**)&mIoMmuProtocol
);
103 if (EFI_ERROR (Status
)) {
105 "QemuFwCfgSevDma %a:%a Failed to locate IOMMU protocol.\n",
106 gEfiCallerBaseName
, __FUNCTION__
));
112 return RETURN_SUCCESS
;
117 Returns a boolean indicating if the firmware configuration interface is
118 available for library-internal purposes.
120 This function never changes fw_cfg state.
122 @retval TRUE The interface is available internally.
123 @retval FALSE The interface is not available internally.
126 InternalQemuFwCfgIsAvailable (
130 return mQemuFwCfgSupported
;
134 Returns a boolean indicating whether QEMU provides the DMA-like access method
137 @retval TRUE The DMA-like access method is available.
138 @retval FALSE The DMA-like access method is unavailable.
141 InternalQemuFwCfgDmaIsAvailable (
145 return mQemuFwCfgDmaSupported
;
149 Function is used for allocating a bi-directional FW_CFG_DMA_ACCESS used
150 between Host and device to exchange the information. The buffer must be free'd
151 using FreeFwCfgDmaAccessBuffer ().
156 AllocFwCfgDmaAccessBuffer (
165 EFI_PHYSICAL_ADDRESS DmaAddress
;
168 Size
= sizeof (FW_CFG_DMA_ACCESS
);
169 NumPages
= EFI_SIZE_TO_PAGES (Size
);
172 // As per UEFI spec, in order to map a host address with
173 // BusMasterCommomBuffer64, the buffer must be allocated using the IOMMU
176 Status
= mIoMmuProtocol
->AllocateBuffer (
182 EDKII_IOMMU_ATTRIBUTE_DUAL_ADDRESS_CYCLE
184 if (EFI_ERROR (Status
)) {
186 "%a:%a failed to allocate FW_CFG_DMA_ACCESS\n", gEfiCallerBaseName
,
193 // Avoid exposing stale data even temporarily: zero the area before mapping
196 ZeroMem (HostAddress
, Size
);
199 // Map the host buffer with BusMasterCommonBuffer64
201 Status
= mIoMmuProtocol
->Map (
203 EdkiiIoMmuOperationBusMasterCommonBuffer64
,
209 if (EFI_ERROR (Status
)) {
210 mIoMmuProtocol
->FreeBuffer (mIoMmuProtocol
, NumPages
, HostAddress
);
212 "%a:%a failed to Map() FW_CFG_DMA_ACCESS\n", gEfiCallerBaseName
,
218 if (Size
< sizeof (FW_CFG_DMA_ACCESS
)) {
219 mIoMmuProtocol
->Unmap (mIoMmuProtocol
, Mapping
);
220 mIoMmuProtocol
->FreeBuffer (mIoMmuProtocol
, NumPages
, HostAddress
);
222 "%a:%a failed to Map() - requested 0x%Lx got 0x%Lx\n", gEfiCallerBaseName
,
223 __FUNCTION__
, (UINT64
)sizeof (FW_CFG_DMA_ACCESS
), (UINT64
)Size
));
228 *Access
= HostAddress
;
233 Function is to used for freeing the Access buffer allocated using
234 AllocFwCfgDmaAccessBuffer()
239 FreeFwCfgDmaAccessBuffer (
247 NumPages
= EFI_SIZE_TO_PAGES (sizeof (FW_CFG_DMA_ACCESS
));
249 Status
= mIoMmuProtocol
->Unmap (mIoMmuProtocol
, Mapping
);
250 if (EFI_ERROR (Status
)) {
252 "%a:%a failed to UnMap() Mapping 0x%Lx\n", gEfiCallerBaseName
,
253 __FUNCTION__
, (UINT64
)(UINTN
)Mapping
));
258 Status
= mIoMmuProtocol
->FreeBuffer (mIoMmuProtocol
, NumPages
, Access
);
259 if (EFI_ERROR (Status
)) {
261 "%a:%a failed to Free() 0x%Lx\n", gEfiCallerBaseName
, __FUNCTION__
,
262 (UINT64
)(UINTN
)Access
));
269 Function is used for mapping host address to device address. The buffer must
270 be unmapped with UnmapDmaDataBuffer ().
275 MapFwCfgDmaDataBuffer (
277 IN VOID
*HostAddress
,
279 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
286 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
288 NumberOfBytes
= Size
;
289 Status
= mIoMmuProtocol
->Map (
292 EdkiiIoMmuOperationBusMasterRead64
:
293 EdkiiIoMmuOperationBusMasterWrite64
),
299 if (EFI_ERROR (Status
)) {
301 "%a:%a failed to Map() Address 0x%Lx Size 0x%Lx\n", gEfiCallerBaseName
,
302 __FUNCTION__
, (UINT64
)(UINTN
)HostAddress
, (UINT64
)Size
));
307 if (NumberOfBytes
< Size
) {
308 mIoMmuProtocol
->Unmap (mIoMmuProtocol
, Mapping
);
310 "%a:%a failed to Map() - requested 0x%x got 0x%Lx\n", gEfiCallerBaseName
,
311 __FUNCTION__
, Size
, (UINT64
)NumberOfBytes
));
316 *DeviceAddress
= PhysicalAddress
;
322 UnmapFwCfgDmaDataBuffer (
328 Status
= mIoMmuProtocol
->Unmap (mIoMmuProtocol
, Mapping
);
329 if (EFI_ERROR (Status
)) {
331 "%a:%a failed to UnMap() Mapping 0x%Lx\n", gEfiCallerBaseName
,
332 __FUNCTION__
, (UINT64
)(UINTN
)Mapping
));
339 Transfer an array of bytes, or skip a number of bytes, using the DMA
342 @param[in] Size Size in bytes to transfer or skip.
344 @param[in,out] Buffer Buffer to read data into or write data from. Ignored,
345 and may be NULL, if Size is zero, or Control is
348 @param[in] Control One of the following:
349 FW_CFG_DMA_CTL_WRITE - write to fw_cfg from Buffer.
350 FW_CFG_DMA_CTL_READ - read from fw_cfg into Buffer.
351 FW_CFG_DMA_CTL_SKIP - skip bytes in fw_cfg.
354 InternalQemuFwCfgDmaBytes (
356 IN OUT VOID
*Buffer OPTIONAL
,
360 volatile FW_CFG_DMA_ACCESS LocalAccess
;
361 volatile FW_CFG_DMA_ACCESS
*Access
;
362 UINT32 AccessHigh
, AccessLow
;
364 VOID
*AccessMapping
, *DataMapping
;
367 ASSERT (Control
== FW_CFG_DMA_CTL_WRITE
|| Control
== FW_CFG_DMA_CTL_READ
||
368 Control
== FW_CFG_DMA_CTL_SKIP
);
374 Access
= &LocalAccess
;
375 AccessMapping
= NULL
;
380 // When SEV is enabled, map Buffer to DMA address before issuing the DMA
383 if (MemEncryptSevIsEnabled ()) {
385 EFI_PHYSICAL_ADDRESS DataBufferAddress
;
388 // Allocate DMA Access buffer
390 AllocFwCfgDmaAccessBuffer (&AccessBuffer
, &AccessMapping
);
392 Access
= AccessBuffer
;
395 // Map actual data buffer
397 if (Control
!= FW_CFG_DMA_CTL_SKIP
) {
398 MapFwCfgDmaDataBuffer (
399 Control
== FW_CFG_DMA_CTL_WRITE
,
406 DataBuffer
= (VOID
*) (UINTN
) DataBufferAddress
;
410 Access
->Control
= SwapBytes32 (Control
);
411 Access
->Length
= SwapBytes32 (Size
);
412 Access
->Address
= SwapBytes64 ((UINTN
)DataBuffer
);
415 // Delimit the transfer from (a) modifications to Access, (b) in case of a
416 // write, from writes to Buffer by the caller.
421 // Start the transfer.
423 AccessHigh
= (UINT32
)RShiftU64 ((UINTN
)Access
, 32);
424 AccessLow
= (UINT32
)(UINTN
)Access
;
425 IoWrite32 (FW_CFG_IO_DMA_ADDRESS
, SwapBytes32 (AccessHigh
));
426 IoWrite32 (FW_CFG_IO_DMA_ADDRESS
+ 4, SwapBytes32 (AccessLow
));
429 // Don't look at Access.Control before starting the transfer.
434 // Wait for the transfer to complete.
437 Status
= SwapBytes32 (Access
->Control
);
438 ASSERT ((Status
& FW_CFG_DMA_CTL_ERROR
) == 0);
439 } while (Status
!= 0);
442 // After a read, the caller will want to use Buffer.
447 // If Access buffer was dynamically allocated then free it.
449 if (AccessMapping
!= NULL
) {
450 FreeFwCfgDmaAccessBuffer ((VOID
*)Access
, AccessMapping
);
454 // If DataBuffer was mapped then unmap it.
456 if (DataMapping
!= NULL
) {
457 UnmapFwCfgDmaDataBuffer (DataMapping
);