On 09/24/15 23:10, Ard Biesheuvel wrote:
> On 24 September 2015 at 04:26, Laszlo Ersek <[email protected]> wrote:
>> The protocol is documented in "docs/specs/fw_cfg.txt" in the QEMU tree.
>>
>> Cc: Ard Biesheuvel <[email protected]>
>> Contributed-under: TianoCore Contribution Agreement 1.0
>> Signed-off-by: Laszlo Ersek <[email protected]>
> 
> Nice feature!

Thank you, especially on behalf of the QEMU side designers &
implementors of the feature. :)

> 
> Reviewed-by: Ard Biesheuvel <[email protected]>

Thank you very much for the quick review. I committed the series to SVN
(r18544, r18545).

Cheers
Laszlo

> 
>> ---
>>  ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf |   2 +
>>  ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c   | 126 ++++++++++++++++++--
>>  2 files changed, 121 insertions(+), 7 deletions(-)
>>
>> diff --git a/ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf 
>> b/ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
>> index 42f21f2..298aa6e 100644
>> --- a/ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
>> +++ b/ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
>> @@ -44,9 +44,11 @@ [Packages]
>>  [LibraryClasses]
>>    BaseLib
>>    BaseMemoryLib
>> +  DebugLib
>>    IoLib
>>    PcdLib
>>
>>  [Pcd]
>>    gArmVirtTokenSpaceGuid.PcdFwCfgSelectorAddress
>>    gArmVirtTokenSpaceGuid.PcdFwCfgDataAddress
>> +  gArmVirtTokenSpaceGuid.PcdFwCfgDmaAddress
>> diff --git a/ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c 
>> b/ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c
>> index c62eee3..303dc52 100644
>> --- a/ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c
>> +++ b/ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c
>> @@ -16,12 +16,58 @@
>>
>>  #include <Library/BaseLib.h>
>>  #include <Library/BaseMemoryLib.h>
>> +#include <Library/DebugLib.h>
>>  #include <Library/IoLib.h>
>>  #include <Library/PcdLib.h>
>>  #include <Library/QemuFwCfgLib.h>
>>
>>  STATIC UINTN mFwCfgSelectorAddress;
>>  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);
>>      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;
>>        mFwCfgDataAddress     = 0;
>>      }
>> @@ -108,16 +169,12 @@ QemuFwCfgSelectItem (
>>
>>
>>  /**
>> -  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)
>> -
>> +  Slow READ_BYTES_FUNCTION.
>>  **/
>>  STATIC
>>  VOID
>>  EFIAPI
>> -InternalQemuFwCfgReadBytes (
>> +MmioReadBytes (
>>    IN UINTN Size,
>>    IN VOID  *Buffer OPTIONAL
>>    )
>> @@ -163,6 +220,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
>>
>>    If called multiple times, then the data read will continue at the offset 
>> of
>> --
>> 1.8.3.1
>>
> _______________________________________________
> edk2-devel mailing list
> [email protected]
> https://lists.01.org/mailman/listinfo/edk2-devel
> 

_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to