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/DebugLib.h>
24 #include <Library/QemuFwCfgLib.h>
25 #include <Library/UefiBootServicesTableLib.h>
26 #include <Library/MemEncryptSevLib.h>
28 #include "QemuFwCfgLibInternal.h"
30 STATIC BOOLEAN mQemuFwCfgSupported
= FALSE
;
31 STATIC BOOLEAN mQemuFwCfgDmaSupported
;
33 STATIC EDKII_IOMMU_PROTOCOL
*mIoMmuProtocol
;
36 Returns a boolean indicating whether SEV is enabled
38 @retval TRUE SEV is enabled
39 @retval FALSE SEV is disabled
42 InternalQemuFwCfgSevIsEnabled (
46 return MemEncryptSevIsEnabled ();
50 Returns a boolean indicating if the firmware configuration interface
53 This function may change fw_cfg state.
55 @retval TRUE The interface is available
56 @retval FALSE The interface is not available
61 QemuFwCfgIsAvailable (
65 return InternalQemuFwCfgIsAvailable ();
79 // Enable the access routines while probing to see if it is supported.
80 // For probing we always use the IO Port (IoReadFifo8()) access method.
82 mQemuFwCfgSupported
= TRUE
;
83 mQemuFwCfgDmaSupported
= FALSE
;
85 QemuFwCfgSelectItem (QemuFwCfgItemSignature
);
86 Signature
= QemuFwCfgRead32 ();
87 DEBUG ((EFI_D_INFO
, "FW CFG Signature: 0x%x\n", Signature
));
88 QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion
);
89 Revision
= QemuFwCfgRead32 ();
90 DEBUG ((EFI_D_INFO
, "FW CFG Revision: 0x%x\n", Revision
));
91 if ((Signature
!= SIGNATURE_32 ('Q', 'E', 'M', 'U')) ||
94 DEBUG ((EFI_D_INFO
, "QemuFwCfg interface not supported.\n"));
95 mQemuFwCfgSupported
= FALSE
;
96 return RETURN_SUCCESS
;
99 if ((Revision
& FW_CFG_F_DMA
) == 0) {
100 DEBUG ((DEBUG_INFO
, "QemuFwCfg interface (IO Port) is supported.\n"));
102 mQemuFwCfgDmaSupported
= TRUE
;
103 DEBUG ((DEBUG_INFO
, "QemuFwCfg interface (DMA) is supported.\n"));
106 if (mQemuFwCfgDmaSupported
&& MemEncryptSevIsEnabled ()) {
110 // IoMmuDxe driver must have installed the IOMMU protocol. If we are not
111 // able to locate the protocol then something must have gone wrong.
113 Status
= gBS
->LocateProtocol (&gEdkiiIoMmuProtocolGuid
, NULL
, (VOID
**)&mIoMmuProtocol
);
114 if (EFI_ERROR (Status
)) {
116 "QemuFwCfgSevDma %a:%a Failed to locate IOMMU protocol.\n",
117 gEfiCallerBaseName
, __FUNCTION__
));
123 return RETURN_SUCCESS
;
128 Returns a boolean indicating if the firmware configuration interface is
129 available for library-internal purposes.
131 This function never changes fw_cfg state.
133 @retval TRUE The interface is available internally.
134 @retval FALSE The interface is not available internally.
137 InternalQemuFwCfgIsAvailable (
141 return mQemuFwCfgSupported
;
145 Returns a boolean indicating whether QEMU provides the DMA-like access method
148 @retval TRUE The DMA-like access method is available.
149 @retval FALSE The DMA-like access method is unavailable.
152 InternalQemuFwCfgDmaIsAvailable (
156 return mQemuFwCfgDmaSupported
;
160 Allocate a bounce buffer for SEV DMA.
162 @param[in] NumPage Number of pages.
163 @param[out] Buffer Allocated DMA Buffer pointer
167 InternalQemuFwCfgSevDmaAllocateBuffer (
174 ASSERT (mIoMmuProtocol
!= NULL
);
176 Status
= mIoMmuProtocol
->AllocateBuffer (
182 EDKII_IOMMU_ATTRIBUTE_MEMORY_CACHED
184 if (EFI_ERROR (Status
)) {
186 "%a:%a failed to allocate %u pages\n", gEfiCallerBaseName
, __FUNCTION__
,
192 DEBUG ((DEBUG_VERBOSE
,
193 "%a:%a buffer 0x%Lx Pages %u\n", gEfiCallerBaseName
, __FUNCTION__
,
194 (UINT64
)(UINTN
)Buffer
, NumPages
));
198 Free the DMA buffer allocated using InternalQemuFwCfgSevDmaAllocateBuffer
200 @param[in] NumPage Number of pages.
201 @param[in] Buffer DMA Buffer pointer
205 InternalQemuFwCfgSevDmaFreeBuffer (
212 ASSERT (mIoMmuProtocol
!= NULL
);
214 Status
= mIoMmuProtocol
->FreeBuffer (
219 if (EFI_ERROR (Status
)) {
221 "%a:%a failed to free buffer 0x%Lx pages %u\n", gEfiCallerBaseName
,
222 __FUNCTION__
, (UINT64
)(UINTN
)Buffer
, NumPages
));
227 DEBUG ((DEBUG_VERBOSE
,
228 "%a:%a buffer 0x%Lx Pages %u\n", gEfiCallerBaseName
,__FUNCTION__
,
229 (UINT64
)(UINTN
)Buffer
, NumPages
));