mirror of https://github.com/acidanthera/audk.git
ArmVirtPkg: QemuFwCfgLib: read bytes from fw-cfg with DMA when available
The protocol is documented in "docs/specs/fw_cfg.txt" in the QEMU tree. Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18545 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
50b91449a3
commit
953bcbcce4
|
@ -16,12 +16,58 @@
|
||||||
|
|
||||||
#include <Library/BaseLib.h>
|
#include <Library/BaseLib.h>
|
||||||
#include <Library/BaseMemoryLib.h>
|
#include <Library/BaseMemoryLib.h>
|
||||||
|
#include <Library/DebugLib.h>
|
||||||
#include <Library/IoLib.h>
|
#include <Library/IoLib.h>
|
||||||
#include <Library/PcdLib.h>
|
#include <Library/PcdLib.h>
|
||||||
#include <Library/QemuFwCfgLib.h>
|
#include <Library/QemuFwCfgLib.h>
|
||||||
|
|
||||||
STATIC UINTN mFwCfgSelectorAddress;
|
STATIC UINTN mFwCfgSelectorAddress;
|
||||||
STATIC UINTN mFwCfgDataAddress;
|
STATIC UINTN mFwCfgDataAddress;
|
||||||
|
STATIC UINTN mFwCfgDmaAddress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reads firmware configuration bytes into a buffer
|
||||||
|
|
||||||
|
@param[in] Size Size in bytes to read
|
||||||
|
@param[in] Buffer Buffer to store data into (OPTIONAL if Size is 0)
|
||||||
|
|
||||||
|
**/
|
||||||
|
typedef
|
||||||
|
VOID (EFIAPI READ_BYTES_FUNCTION) (
|
||||||
|
IN UINTN Size,
|
||||||
|
IN VOID *Buffer OPTIONAL
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Forward declaration of the two implementations we have.
|
||||||
|
//
|
||||||
|
STATIC READ_BYTES_FUNCTION MmioReadBytes;
|
||||||
|
STATIC READ_BYTES_FUNCTION DmaReadBytes;
|
||||||
|
|
||||||
|
//
|
||||||
|
// This points to the one we detect at runtime.
|
||||||
|
//
|
||||||
|
STATIC READ_BYTES_FUNCTION *InternalQemuFwCfgReadBytes = MmioReadBytes;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Communication structure for DmaReadBytes(). All fields are encoded in big
|
||||||
|
// endian.
|
||||||
|
//
|
||||||
|
#pragma pack (1)
|
||||||
|
typedef struct {
|
||||||
|
UINT32 Control;
|
||||||
|
UINT32 Length;
|
||||||
|
UINT64 Address;
|
||||||
|
} FW_CFG_DMA_ACCESS;
|
||||||
|
#pragma pack ()
|
||||||
|
|
||||||
|
//
|
||||||
|
// Macros for the FW_CFG_DMA_ACCESS.Control bitmap (in native encoding).
|
||||||
|
//
|
||||||
|
#define FW_CFG_DMA_CTL_ERROR BIT0
|
||||||
|
#define FW_CFG_DMA_CTL_READ BIT1
|
||||||
|
#define FW_CFG_DMA_CTL_SKIP BIT2
|
||||||
|
#define FW_CFG_DMA_CTL_SELECT BIT3
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -77,7 +123,22 @@ QemuFwCfgInitialize (
|
||||||
|
|
||||||
QemuFwCfgSelectItem (QemuFwCfgItemSignature);
|
QemuFwCfgSelectItem (QemuFwCfgItemSignature);
|
||||||
Signature = QemuFwCfgRead32 ();
|
Signature = QemuFwCfgRead32 ();
|
||||||
if (Signature != SIGNATURE_32 ('Q', 'E', 'M', 'U')) {
|
if (Signature == SIGNATURE_32 ('Q', 'E', 'M', 'U')) {
|
||||||
|
//
|
||||||
|
// For DMA support, we require the DTB to advertise the register, and the
|
||||||
|
// feature bitmap (which we read without DMA) to confirm the feature.
|
||||||
|
//
|
||||||
|
if (PcdGet64 (PcdFwCfgDmaAddress) != 0) {
|
||||||
|
UINT32 Features;
|
||||||
|
|
||||||
|
QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion);
|
||||||
|
Features = QemuFwCfgRead32 ();
|
||||||
|
if ((Features & BIT1) != 0) {
|
||||||
|
mFwCfgDmaAddress = PcdGet64 (PcdFwCfgDmaAddress);
|
||||||
|
InternalQemuFwCfgReadBytes = DmaReadBytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
mFwCfgSelectorAddress = 0;
|
mFwCfgSelectorAddress = 0;
|
||||||
mFwCfgDataAddress = 0;
|
mFwCfgDataAddress = 0;
|
||||||
}
|
}
|
||||||
|
@ -108,16 +169,12 @@ QemuFwCfgSelectItem (
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Reads firmware configuration bytes into a buffer
|
Slow READ_BYTES_FUNCTION.
|
||||||
|
|
||||||
@param[in] Size Size in bytes to read
|
|
||||||
@param[in] Buffer Buffer to store data into (OPTIONAL if Size is 0)
|
|
||||||
|
|
||||||
**/
|
**/
|
||||||
STATIC
|
STATIC
|
||||||
VOID
|
VOID
|
||||||
EFIAPI
|
EFIAPI
|
||||||
InternalQemuFwCfgReadBytes (
|
MmioReadBytes (
|
||||||
IN UINTN Size,
|
IN UINTN Size,
|
||||||
IN VOID *Buffer OPTIONAL
|
IN VOID *Buffer OPTIONAL
|
||||||
)
|
)
|
||||||
|
@ -162,6 +219,61 @@ InternalQemuFwCfgReadBytes (
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fast READ_BYTES_FUNCTION.
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
DmaReadBytes (
|
||||||
|
IN UINTN Size,
|
||||||
|
IN VOID *Buffer OPTIONAL
|
||||||
|
)
|
||||||
|
{
|
||||||
|
volatile FW_CFG_DMA_ACCESS Access;
|
||||||
|
UINT32 Status;
|
||||||
|
|
||||||
|
if (Size == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT (Size <= MAX_UINT32);
|
||||||
|
|
||||||
|
Access.Control = SwapBytes32 (FW_CFG_DMA_CTL_READ);
|
||||||
|
Access.Length = SwapBytes32 ((UINT32)Size);
|
||||||
|
Access.Address = SwapBytes64 ((UINT64)(UINTN)Buffer);
|
||||||
|
|
||||||
|
//
|
||||||
|
// We shouldn't start the transfer before setting up Access.
|
||||||
|
//
|
||||||
|
MemoryFence ();
|
||||||
|
|
||||||
|
//
|
||||||
|
// This will fire off the transfer.
|
||||||
|
//
|
||||||
|
#ifdef MDE_CPU_AARCH64
|
||||||
|
MmioWrite64 (mFwCfgDmaAddress, SwapBytes64 ((UINT64)&Access));
|
||||||
|
#else
|
||||||
|
MmioWrite32 ((UINT32)(mFwCfgDmaAddress + 4), SwapBytes32 ((UINT32)&Access));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// We shouldn't look at Access.Control before starting the transfer.
|
||||||
|
//
|
||||||
|
MemoryFence ();
|
||||||
|
|
||||||
|
do {
|
||||||
|
Status = SwapBytes32 (Access.Control);
|
||||||
|
ASSERT ((Status & FW_CFG_DMA_CTL_ERROR) == 0);
|
||||||
|
} while (Status != 0);
|
||||||
|
|
||||||
|
//
|
||||||
|
// The caller will want to access the transferred data.
|
||||||
|
//
|
||||||
|
MemoryFence ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Reads firmware configuration bytes into a buffer
|
Reads firmware configuration bytes into a buffer
|
||||||
|
|
||||||
|
|
|
@ -44,9 +44,11 @@
|
||||||
[LibraryClasses]
|
[LibraryClasses]
|
||||||
BaseLib
|
BaseLib
|
||||||
BaseMemoryLib
|
BaseMemoryLib
|
||||||
|
DebugLib
|
||||||
IoLib
|
IoLib
|
||||||
PcdLib
|
PcdLib
|
||||||
|
|
||||||
[Pcd]
|
[Pcd]
|
||||||
gArmVirtTokenSpaceGuid.PcdFwCfgSelectorAddress
|
gArmVirtTokenSpaceGuid.PcdFwCfgSelectorAddress
|
||||||
gArmVirtTokenSpaceGuid.PcdFwCfgDataAddress
|
gArmVirtTokenSpaceGuid.PcdFwCfgDataAddress
|
||||||
|
gArmVirtTokenSpaceGuid.PcdFwCfgDmaAddress
|
||||||
|
|
Loading…
Reference in New Issue