audk/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c

208 lines
5.7 KiB
C
Raw Normal View History

/** @file
Stateful and implicitly initialized fw_cfg library implementation.
Copyright (C) 2013, Red Hat, Inc.
Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2017, Advanced Micro Devices. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Library/BaseLib.h>
OvmfPkg/QemuFwCfgLib: Use BusMasterCommonBuffer to map FW_CFG_DMA_ACCESS Commit 09719a01b11b (OvmfPkg/QemuFwCfgLib: Implement SEV internal function for Dxe phase) uses IOMMU protocol to allocate and free FW_CFG_DMA_ACCESS buffer when SEV is active. During initial commits we made assumption that IOMMU.AllocateBuffer() will provide PlainTextAddress (i.e C-bit cleared). This assumption was wrong, the AllocateBuffer() protocol member is not expected to produce a buffer that is immediatly usable, and client is required to call Map() uncondtionally with BusMasterCommonBuffer[64] to get a mapping which is accessable by both host and device. The patch refactors code a bit and add the support to Map() FW_CFG_DMA_ACCESS buffer using BusMasterCommonBuffer operation after allocation and Unamp() before free. The complete discussion about this and recommendation from Laszlo can be found here [1] [1] https://lists.01.org/pipermail/edk2-devel/2017-July/012652.html Suggested-by: Laszlo Ersek <lersek@redhat.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> [lersek@redhat.com: convert pointers to UINTN before converting to UINT64] [lersek@redhat.com: fix argument indentation in multi-line function call] [lersek@redhat.com: explicitly compare pointers to NULL] Reviewed-by: Laszlo Ersek <lersek@redhat.com> Regression-tested-by: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Laszlo Ersek <lersek@redhat.com>
2017-08-03 00:12:48 +02:00
#include <Library/IoLib.h>
#include <Library/DebugLib.h>
#include <Library/QemuFwCfgLib.h>
#include <Library/MemEncryptSevLib.h>
#include "QemuFwCfgLibInternal.h"
STATIC BOOLEAN mQemuFwCfgSupported = FALSE;
STATIC BOOLEAN mQemuFwCfgDmaSupported;
/**
Returns a boolean indicating if the firmware configuration interface
is available or not.
This function may change fw_cfg state.
@retval TRUE The interface is available
@retval FALSE The interface is not available
**/
BOOLEAN
EFIAPI
QemuFwCfgIsAvailable (
VOID
)
{
return InternalQemuFwCfgIsAvailable ();
}
RETURN_STATUS
EFIAPI
QemuFwCfgInitialize (
VOID
)
{
UINT32 Signature;
UINT32 Revision;
//
// Enable the access routines while probing to see if it is supported.
// For probing we always use the IO Port (IoReadFifo8()) access method.
//
mQemuFwCfgSupported = TRUE;
mQemuFwCfgDmaSupported = FALSE;
QemuFwCfgSelectItem (QemuFwCfgItemSignature);
Signature = QemuFwCfgRead32 ();
DEBUG ((EFI_D_INFO, "FW CFG Signature: 0x%x\n", Signature));
QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion);
Revision = QemuFwCfgRead32 ();
DEBUG ((EFI_D_INFO, "FW CFG Revision: 0x%x\n", Revision));
if ((Signature != SIGNATURE_32 ('Q', 'E', 'M', 'U')) ||
(Revision < 1)
) {
DEBUG ((EFI_D_INFO, "QemuFwCfg interface not supported.\n"));
mQemuFwCfgSupported = FALSE;
return RETURN_SUCCESS;
}
if ((Revision & FW_CFG_F_DMA) == 0) {
DEBUG ((DEBUG_INFO, "QemuFwCfg interface (IO Port) is supported.\n"));
} else {
//
// If SEV is enabled then we do not support DMA operations in PEI phase.
// This is mainly because DMA in SEV guest requires using bounce buffer
// (which need to allocate dynamic memory and allocating a PAGE size'd
// buffer can be challenge in PEI phase)
//
OvmfPkg/QemuFwCfgLib: Use BusMasterCommonBuffer to map FW_CFG_DMA_ACCESS Commit 09719a01b11b (OvmfPkg/QemuFwCfgLib: Implement SEV internal function for Dxe phase) uses IOMMU protocol to allocate and free FW_CFG_DMA_ACCESS buffer when SEV is active. During initial commits we made assumption that IOMMU.AllocateBuffer() will provide PlainTextAddress (i.e C-bit cleared). This assumption was wrong, the AllocateBuffer() protocol member is not expected to produce a buffer that is immediatly usable, and client is required to call Map() uncondtionally with BusMasterCommonBuffer[64] to get a mapping which is accessable by both host and device. The patch refactors code a bit and add the support to Map() FW_CFG_DMA_ACCESS buffer using BusMasterCommonBuffer operation after allocation and Unamp() before free. The complete discussion about this and recommendation from Laszlo can be found here [1] [1] https://lists.01.org/pipermail/edk2-devel/2017-July/012652.html Suggested-by: Laszlo Ersek <lersek@redhat.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> [lersek@redhat.com: convert pointers to UINTN before converting to UINT64] [lersek@redhat.com: fix argument indentation in multi-line function call] [lersek@redhat.com: explicitly compare pointers to NULL] Reviewed-by: Laszlo Ersek <lersek@redhat.com> Regression-tested-by: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Laszlo Ersek <lersek@redhat.com>
2017-08-03 00:12:48 +02:00
if (MemEncryptSevIsEnabled ()) {
DEBUG ((DEBUG_INFO, "SEV: QemuFwCfg fallback to IO Port interface.\n"));
} else {
mQemuFwCfgDmaSupported = TRUE;
DEBUG ((DEBUG_INFO, "QemuFwCfg interface (DMA) is supported.\n"));
}
}
return RETURN_SUCCESS;
}
/**
Returns a boolean indicating if the firmware configuration interface is
available for library-internal purposes.
This function never changes fw_cfg state.
@retval TRUE The interface is available internally.
@retval FALSE The interface is not available internally.
**/
BOOLEAN
InternalQemuFwCfgIsAvailable (
VOID
)
{
return mQemuFwCfgSupported;
}
/**
Returns a boolean indicating whether QEMU provides the DMA-like access method
for fw_cfg.
@retval TRUE The DMA-like access method is available.
@retval FALSE The DMA-like access method is unavailable.
**/
BOOLEAN
InternalQemuFwCfgDmaIsAvailable (
VOID
)
{
return mQemuFwCfgDmaSupported;
}
/**
OvmfPkg/QemuFwCfgLib: Use BusMasterCommonBuffer to map FW_CFG_DMA_ACCESS Commit 09719a01b11b (OvmfPkg/QemuFwCfgLib: Implement SEV internal function for Dxe phase) uses IOMMU protocol to allocate and free FW_CFG_DMA_ACCESS buffer when SEV is active. During initial commits we made assumption that IOMMU.AllocateBuffer() will provide PlainTextAddress (i.e C-bit cleared). This assumption was wrong, the AllocateBuffer() protocol member is not expected to produce a buffer that is immediatly usable, and client is required to call Map() uncondtionally with BusMasterCommonBuffer[64] to get a mapping which is accessable by both host and device. The patch refactors code a bit and add the support to Map() FW_CFG_DMA_ACCESS buffer using BusMasterCommonBuffer operation after allocation and Unamp() before free. The complete discussion about this and recommendation from Laszlo can be found here [1] [1] https://lists.01.org/pipermail/edk2-devel/2017-July/012652.html Suggested-by: Laszlo Ersek <lersek@redhat.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> [lersek@redhat.com: convert pointers to UINTN before converting to UINT64] [lersek@redhat.com: fix argument indentation in multi-line function call] [lersek@redhat.com: explicitly compare pointers to NULL] Reviewed-by: Laszlo Ersek <lersek@redhat.com> Regression-tested-by: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Laszlo Ersek <lersek@redhat.com>
2017-08-03 00:12:48 +02:00
Transfer an array of bytes, or skip a number of bytes, using the DMA
interface.
OvmfPkg/QemuFwCfgLib: Use BusMasterCommonBuffer to map FW_CFG_DMA_ACCESS Commit 09719a01b11b (OvmfPkg/QemuFwCfgLib: Implement SEV internal function for Dxe phase) uses IOMMU protocol to allocate and free FW_CFG_DMA_ACCESS buffer when SEV is active. During initial commits we made assumption that IOMMU.AllocateBuffer() will provide PlainTextAddress (i.e C-bit cleared). This assumption was wrong, the AllocateBuffer() protocol member is not expected to produce a buffer that is immediatly usable, and client is required to call Map() uncondtionally with BusMasterCommonBuffer[64] to get a mapping which is accessable by both host and device. The patch refactors code a bit and add the support to Map() FW_CFG_DMA_ACCESS buffer using BusMasterCommonBuffer operation after allocation and Unamp() before free. The complete discussion about this and recommendation from Laszlo can be found here [1] [1] https://lists.01.org/pipermail/edk2-devel/2017-July/012652.html Suggested-by: Laszlo Ersek <lersek@redhat.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> [lersek@redhat.com: convert pointers to UINTN before converting to UINT64] [lersek@redhat.com: fix argument indentation in multi-line function call] [lersek@redhat.com: explicitly compare pointers to NULL] Reviewed-by: Laszlo Ersek <lersek@redhat.com> Regression-tested-by: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Laszlo Ersek <lersek@redhat.com>
2017-08-03 00:12:48 +02:00
@param[in] Size Size in bytes to transfer or skip.
OvmfPkg/QemuFwCfgLib: Use BusMasterCommonBuffer to map FW_CFG_DMA_ACCESS Commit 09719a01b11b (OvmfPkg/QemuFwCfgLib: Implement SEV internal function for Dxe phase) uses IOMMU protocol to allocate and free FW_CFG_DMA_ACCESS buffer when SEV is active. During initial commits we made assumption that IOMMU.AllocateBuffer() will provide PlainTextAddress (i.e C-bit cleared). This assumption was wrong, the AllocateBuffer() protocol member is not expected to produce a buffer that is immediatly usable, and client is required to call Map() uncondtionally with BusMasterCommonBuffer[64] to get a mapping which is accessable by both host and device. The patch refactors code a bit and add the support to Map() FW_CFG_DMA_ACCESS buffer using BusMasterCommonBuffer operation after allocation and Unamp() before free. The complete discussion about this and recommendation from Laszlo can be found here [1] [1] https://lists.01.org/pipermail/edk2-devel/2017-July/012652.html Suggested-by: Laszlo Ersek <lersek@redhat.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> [lersek@redhat.com: convert pointers to UINTN before converting to UINT64] [lersek@redhat.com: fix argument indentation in multi-line function call] [lersek@redhat.com: explicitly compare pointers to NULL] Reviewed-by: Laszlo Ersek <lersek@redhat.com> Regression-tested-by: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Laszlo Ersek <lersek@redhat.com>
2017-08-03 00:12:48 +02:00
@param[in,out] Buffer Buffer to read data into or write data from. Ignored,
and may be NULL, if Size is zero, or Control is
FW_CFG_DMA_CTL_SKIP.
@param[in] Control One of the following:
FW_CFG_DMA_CTL_WRITE - write to fw_cfg from Buffer.
FW_CFG_DMA_CTL_READ - read from fw_cfg into Buffer.
FW_CFG_DMA_CTL_SKIP - skip bytes in fw_cfg.
**/
OvmfPkg/QemuFwCfgLib: Use BusMasterCommonBuffer to map FW_CFG_DMA_ACCESS Commit 09719a01b11b (OvmfPkg/QemuFwCfgLib: Implement SEV internal function for Dxe phase) uses IOMMU protocol to allocate and free FW_CFG_DMA_ACCESS buffer when SEV is active. During initial commits we made assumption that IOMMU.AllocateBuffer() will provide PlainTextAddress (i.e C-bit cleared). This assumption was wrong, the AllocateBuffer() protocol member is not expected to produce a buffer that is immediatly usable, and client is required to call Map() uncondtionally with BusMasterCommonBuffer[64] to get a mapping which is accessable by both host and device. The patch refactors code a bit and add the support to Map() FW_CFG_DMA_ACCESS buffer using BusMasterCommonBuffer operation after allocation and Unamp() before free. The complete discussion about this and recommendation from Laszlo can be found here [1] [1] https://lists.01.org/pipermail/edk2-devel/2017-July/012652.html Suggested-by: Laszlo Ersek <lersek@redhat.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> [lersek@redhat.com: convert pointers to UINTN before converting to UINT64] [lersek@redhat.com: fix argument indentation in multi-line function call] [lersek@redhat.com: explicitly compare pointers to NULL] Reviewed-by: Laszlo Ersek <lersek@redhat.com> Regression-tested-by: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Laszlo Ersek <lersek@redhat.com>
2017-08-03 00:12:48 +02:00
VOID
InternalQemuFwCfgDmaBytes (
IN UINT32 Size,
IN OUT VOID *Buffer OPTIONAL,
IN UINT32 Control
)
{
OvmfPkg/QemuFwCfgLib: Use BusMasterCommonBuffer to map FW_CFG_DMA_ACCESS Commit 09719a01b11b (OvmfPkg/QemuFwCfgLib: Implement SEV internal function for Dxe phase) uses IOMMU protocol to allocate and free FW_CFG_DMA_ACCESS buffer when SEV is active. During initial commits we made assumption that IOMMU.AllocateBuffer() will provide PlainTextAddress (i.e C-bit cleared). This assumption was wrong, the AllocateBuffer() protocol member is not expected to produce a buffer that is immediatly usable, and client is required to call Map() uncondtionally with BusMasterCommonBuffer[64] to get a mapping which is accessable by both host and device. The patch refactors code a bit and add the support to Map() FW_CFG_DMA_ACCESS buffer using BusMasterCommonBuffer operation after allocation and Unamp() before free. The complete discussion about this and recommendation from Laszlo can be found here [1] [1] https://lists.01.org/pipermail/edk2-devel/2017-July/012652.html Suggested-by: Laszlo Ersek <lersek@redhat.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> [lersek@redhat.com: convert pointers to UINTN before converting to UINT64] [lersek@redhat.com: fix argument indentation in multi-line function call] [lersek@redhat.com: explicitly compare pointers to NULL] Reviewed-by: Laszlo Ersek <lersek@redhat.com> Regression-tested-by: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Laszlo Ersek <lersek@redhat.com>
2017-08-03 00:12:48 +02:00
volatile FW_CFG_DMA_ACCESS Access;
UINT32 AccessHigh, AccessLow;
UINT32 Status;
OvmfPkg/QemuFwCfgLib: Use BusMasterCommonBuffer to map FW_CFG_DMA_ACCESS Commit 09719a01b11b (OvmfPkg/QemuFwCfgLib: Implement SEV internal function for Dxe phase) uses IOMMU protocol to allocate and free FW_CFG_DMA_ACCESS buffer when SEV is active. During initial commits we made assumption that IOMMU.AllocateBuffer() will provide PlainTextAddress (i.e C-bit cleared). This assumption was wrong, the AllocateBuffer() protocol member is not expected to produce a buffer that is immediatly usable, and client is required to call Map() uncondtionally with BusMasterCommonBuffer[64] to get a mapping which is accessable by both host and device. The patch refactors code a bit and add the support to Map() FW_CFG_DMA_ACCESS buffer using BusMasterCommonBuffer operation after allocation and Unamp() before free. The complete discussion about this and recommendation from Laszlo can be found here [1] [1] https://lists.01.org/pipermail/edk2-devel/2017-July/012652.html Suggested-by: Laszlo Ersek <lersek@redhat.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> [lersek@redhat.com: convert pointers to UINTN before converting to UINT64] [lersek@redhat.com: fix argument indentation in multi-line function call] [lersek@redhat.com: explicitly compare pointers to NULL] Reviewed-by: Laszlo Ersek <lersek@redhat.com> Regression-tested-by: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Laszlo Ersek <lersek@redhat.com>
2017-08-03 00:12:48 +02:00
ASSERT (Control == FW_CFG_DMA_CTL_WRITE || Control == FW_CFG_DMA_CTL_READ ||
Control == FW_CFG_DMA_CTL_SKIP);
OvmfPkg/QemuFwCfgLib: Use BusMasterCommonBuffer to map FW_CFG_DMA_ACCESS Commit 09719a01b11b (OvmfPkg/QemuFwCfgLib: Implement SEV internal function for Dxe phase) uses IOMMU protocol to allocate and free FW_CFG_DMA_ACCESS buffer when SEV is active. During initial commits we made assumption that IOMMU.AllocateBuffer() will provide PlainTextAddress (i.e C-bit cleared). This assumption was wrong, the AllocateBuffer() protocol member is not expected to produce a buffer that is immediatly usable, and client is required to call Map() uncondtionally with BusMasterCommonBuffer[64] to get a mapping which is accessable by both host and device. The patch refactors code a bit and add the support to Map() FW_CFG_DMA_ACCESS buffer using BusMasterCommonBuffer operation after allocation and Unamp() before free. The complete discussion about this and recommendation from Laszlo can be found here [1] [1] https://lists.01.org/pipermail/edk2-devel/2017-July/012652.html Suggested-by: Laszlo Ersek <lersek@redhat.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> [lersek@redhat.com: convert pointers to UINTN before converting to UINT64] [lersek@redhat.com: fix argument indentation in multi-line function call] [lersek@redhat.com: explicitly compare pointers to NULL] Reviewed-by: Laszlo Ersek <lersek@redhat.com> Regression-tested-by: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Laszlo Ersek <lersek@redhat.com>
2017-08-03 00:12:48 +02:00
if (Size == 0) {
return;
}
//
OvmfPkg/QemuFwCfgLib: Use BusMasterCommonBuffer to map FW_CFG_DMA_ACCESS Commit 09719a01b11b (OvmfPkg/QemuFwCfgLib: Implement SEV internal function for Dxe phase) uses IOMMU protocol to allocate and free FW_CFG_DMA_ACCESS buffer when SEV is active. During initial commits we made assumption that IOMMU.AllocateBuffer() will provide PlainTextAddress (i.e C-bit cleared). This assumption was wrong, the AllocateBuffer() protocol member is not expected to produce a buffer that is immediatly usable, and client is required to call Map() uncondtionally with BusMasterCommonBuffer[64] to get a mapping which is accessable by both host and device. The patch refactors code a bit and add the support to Map() FW_CFG_DMA_ACCESS buffer using BusMasterCommonBuffer operation after allocation and Unamp() before free. The complete discussion about this and recommendation from Laszlo can be found here [1] [1] https://lists.01.org/pipermail/edk2-devel/2017-July/012652.html Suggested-by: Laszlo Ersek <lersek@redhat.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> [lersek@redhat.com: convert pointers to UINTN before converting to UINT64] [lersek@redhat.com: fix argument indentation in multi-line function call] [lersek@redhat.com: explicitly compare pointers to NULL] Reviewed-by: Laszlo Ersek <lersek@redhat.com> Regression-tested-by: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Laszlo Ersek <lersek@redhat.com>
2017-08-03 00:12:48 +02:00
// SEV does not support DMA operations in PEI stage, we should
// not have reached here.
//
OvmfPkg/QemuFwCfgLib: Use BusMasterCommonBuffer to map FW_CFG_DMA_ACCESS Commit 09719a01b11b (OvmfPkg/QemuFwCfgLib: Implement SEV internal function for Dxe phase) uses IOMMU protocol to allocate and free FW_CFG_DMA_ACCESS buffer when SEV is active. During initial commits we made assumption that IOMMU.AllocateBuffer() will provide PlainTextAddress (i.e C-bit cleared). This assumption was wrong, the AllocateBuffer() protocol member is not expected to produce a buffer that is immediatly usable, and client is required to call Map() uncondtionally with BusMasterCommonBuffer[64] to get a mapping which is accessable by both host and device. The patch refactors code a bit and add the support to Map() FW_CFG_DMA_ACCESS buffer using BusMasterCommonBuffer operation after allocation and Unamp() before free. The complete discussion about this and recommendation from Laszlo can be found here [1] [1] https://lists.01.org/pipermail/edk2-devel/2017-July/012652.html Suggested-by: Laszlo Ersek <lersek@redhat.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> [lersek@redhat.com: convert pointers to UINTN before converting to UINT64] [lersek@redhat.com: fix argument indentation in multi-line function call] [lersek@redhat.com: explicitly compare pointers to NULL] Reviewed-by: Laszlo Ersek <lersek@redhat.com> Regression-tested-by: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Laszlo Ersek <lersek@redhat.com>
2017-08-03 00:12:48 +02:00
ASSERT (!MemEncryptSevIsEnabled ());
OvmfPkg/QemuFwCfgLib: Use BusMasterCommonBuffer to map FW_CFG_DMA_ACCESS Commit 09719a01b11b (OvmfPkg/QemuFwCfgLib: Implement SEV internal function for Dxe phase) uses IOMMU protocol to allocate and free FW_CFG_DMA_ACCESS buffer when SEV is active. During initial commits we made assumption that IOMMU.AllocateBuffer() will provide PlainTextAddress (i.e C-bit cleared). This assumption was wrong, the AllocateBuffer() protocol member is not expected to produce a buffer that is immediatly usable, and client is required to call Map() uncondtionally with BusMasterCommonBuffer[64] to get a mapping which is accessable by both host and device. The patch refactors code a bit and add the support to Map() FW_CFG_DMA_ACCESS buffer using BusMasterCommonBuffer operation after allocation and Unamp() before free. The complete discussion about this and recommendation from Laszlo can be found here [1] [1] https://lists.01.org/pipermail/edk2-devel/2017-July/012652.html Suggested-by: Laszlo Ersek <lersek@redhat.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> [lersek@redhat.com: convert pointers to UINTN before converting to UINT64] [lersek@redhat.com: fix argument indentation in multi-line function call] [lersek@redhat.com: explicitly compare pointers to NULL] Reviewed-by: Laszlo Ersek <lersek@redhat.com> Regression-tested-by: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Laszlo Ersek <lersek@redhat.com>
2017-08-03 00:12:48 +02:00
Access.Control = SwapBytes32 (Control);
Access.Length = SwapBytes32 (Size);
Access.Address = SwapBytes64 ((UINTN)Buffer);
OvmfPkg/QemuFwCfgLib: Use BusMasterCommonBuffer to map FW_CFG_DMA_ACCESS Commit 09719a01b11b (OvmfPkg/QemuFwCfgLib: Implement SEV internal function for Dxe phase) uses IOMMU protocol to allocate and free FW_CFG_DMA_ACCESS buffer when SEV is active. During initial commits we made assumption that IOMMU.AllocateBuffer() will provide PlainTextAddress (i.e C-bit cleared). This assumption was wrong, the AllocateBuffer() protocol member is not expected to produce a buffer that is immediatly usable, and client is required to call Map() uncondtionally with BusMasterCommonBuffer[64] to get a mapping which is accessable by both host and device. The patch refactors code a bit and add the support to Map() FW_CFG_DMA_ACCESS buffer using BusMasterCommonBuffer operation after allocation and Unamp() before free. The complete discussion about this and recommendation from Laszlo can be found here [1] [1] https://lists.01.org/pipermail/edk2-devel/2017-July/012652.html Suggested-by: Laszlo Ersek <lersek@redhat.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> [lersek@redhat.com: convert pointers to UINTN before converting to UINT64] [lersek@redhat.com: fix argument indentation in multi-line function call] [lersek@redhat.com: explicitly compare pointers to NULL] Reviewed-by: Laszlo Ersek <lersek@redhat.com> Regression-tested-by: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Laszlo Ersek <lersek@redhat.com>
2017-08-03 00:12:48 +02:00
//
// Delimit the transfer from (a) modifications to Access, (b) in case of a
// write, from writes to Buffer by the caller.
//
MemoryFence ();
//
// Start the transfer.
//
AccessHigh = (UINT32)RShiftU64 ((UINTN)&Access, 32);
AccessLow = (UINT32)(UINTN)&Access;
IoWrite32 (FW_CFG_IO_DMA_ADDRESS, SwapBytes32 (AccessHigh));
IoWrite32 (FW_CFG_IO_DMA_ADDRESS + 4, SwapBytes32 (AccessLow));
//
OvmfPkg/QemuFwCfgLib: Use BusMasterCommonBuffer to map FW_CFG_DMA_ACCESS Commit 09719a01b11b (OvmfPkg/QemuFwCfgLib: Implement SEV internal function for Dxe phase) uses IOMMU protocol to allocate and free FW_CFG_DMA_ACCESS buffer when SEV is active. During initial commits we made assumption that IOMMU.AllocateBuffer() will provide PlainTextAddress (i.e C-bit cleared). This assumption was wrong, the AllocateBuffer() protocol member is not expected to produce a buffer that is immediatly usable, and client is required to call Map() uncondtionally with BusMasterCommonBuffer[64] to get a mapping which is accessable by both host and device. The patch refactors code a bit and add the support to Map() FW_CFG_DMA_ACCESS buffer using BusMasterCommonBuffer operation after allocation and Unamp() before free. The complete discussion about this and recommendation from Laszlo can be found here [1] [1] https://lists.01.org/pipermail/edk2-devel/2017-July/012652.html Suggested-by: Laszlo Ersek <lersek@redhat.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> [lersek@redhat.com: convert pointers to UINTN before converting to UINT64] [lersek@redhat.com: fix argument indentation in multi-line function call] [lersek@redhat.com: explicitly compare pointers to NULL] Reviewed-by: Laszlo Ersek <lersek@redhat.com> Regression-tested-by: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Laszlo Ersek <lersek@redhat.com>
2017-08-03 00:12:48 +02:00
// Don't look at Access.Control before starting the transfer.
//
OvmfPkg/QemuFwCfgLib: Use BusMasterCommonBuffer to map FW_CFG_DMA_ACCESS Commit 09719a01b11b (OvmfPkg/QemuFwCfgLib: Implement SEV internal function for Dxe phase) uses IOMMU protocol to allocate and free FW_CFG_DMA_ACCESS buffer when SEV is active. During initial commits we made assumption that IOMMU.AllocateBuffer() will provide PlainTextAddress (i.e C-bit cleared). This assumption was wrong, the AllocateBuffer() protocol member is not expected to produce a buffer that is immediatly usable, and client is required to call Map() uncondtionally with BusMasterCommonBuffer[64] to get a mapping which is accessable by both host and device. The patch refactors code a bit and add the support to Map() FW_CFG_DMA_ACCESS buffer using BusMasterCommonBuffer operation after allocation and Unamp() before free. The complete discussion about this and recommendation from Laszlo can be found here [1] [1] https://lists.01.org/pipermail/edk2-devel/2017-July/012652.html Suggested-by: Laszlo Ersek <lersek@redhat.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> [lersek@redhat.com: convert pointers to UINTN before converting to UINT64] [lersek@redhat.com: fix argument indentation in multi-line function call] [lersek@redhat.com: explicitly compare pointers to NULL] Reviewed-by: Laszlo Ersek <lersek@redhat.com> Regression-tested-by: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Laszlo Ersek <lersek@redhat.com>
2017-08-03 00:12:48 +02:00
MemoryFence ();
//
// Wait for the transfer to complete.
//
do {
Status = SwapBytes32 (Access.Control);
ASSERT ((Status & FW_CFG_DMA_CTL_ERROR) == 0);
} while (Status != 0);
//
// After a read, the caller will want to use Buffer.
//
MemoryFence ();
}
OvmfPkg/QemuFwCfgLib: Use BusMasterCommonBuffer to map FW_CFG_DMA_ACCESS Commit 09719a01b11b (OvmfPkg/QemuFwCfgLib: Implement SEV internal function for Dxe phase) uses IOMMU protocol to allocate and free FW_CFG_DMA_ACCESS buffer when SEV is active. During initial commits we made assumption that IOMMU.AllocateBuffer() will provide PlainTextAddress (i.e C-bit cleared). This assumption was wrong, the AllocateBuffer() protocol member is not expected to produce a buffer that is immediatly usable, and client is required to call Map() uncondtionally with BusMasterCommonBuffer[64] to get a mapping which is accessable by both host and device. The patch refactors code a bit and add the support to Map() FW_CFG_DMA_ACCESS buffer using BusMasterCommonBuffer operation after allocation and Unamp() before free. The complete discussion about this and recommendation from Laszlo can be found here [1] [1] https://lists.01.org/pipermail/edk2-devel/2017-July/012652.html Suggested-by: Laszlo Ersek <lersek@redhat.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> [lersek@redhat.com: convert pointers to UINTN before converting to UINT64] [lersek@redhat.com: fix argument indentation in multi-line function call] [lersek@redhat.com: explicitly compare pointers to NULL] Reviewed-by: Laszlo Ersek <lersek@redhat.com> Regression-tested-by: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Laszlo Ersek <lersek@redhat.com>
2017-08-03 00:12:48 +02:00