OvmfPkg: Add the way of HOBs in QemuFwCfgLibMmio

Added the HOB methods to load and store the QEMU firmware configure
address, data address and DMA address, which are not enabled during the
DXE stage.

Build-tested only (with "ArmVirtQemu.dsc and RiscVVirtQemu.dsc").

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4755

Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Leif Lindholm <quic_llindhol@quicinc.com>
Cc: Sami Mujawar <sami.mujawar@arm.com>
Cc: Sunil V L <sunilvl@ventanamicro.com>
Cc: Andrei Warkentin <andrei.warkentin@intel.com>
Signed-off-by: Chao Li <lichao@loongson.cn>
This commit is contained in:
Chao Li 2024-04-30 15:48:09 +08:00 committed by mergify[bot]
parent 5e31c5666d
commit 748d57d40f
4 changed files with 216 additions and 27 deletions

View File

@ -3,15 +3,21 @@
Copyright (C) 2013 - 2014, Red Hat, Inc.
Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
(C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Base.h>
#include <Uefi.h>
#include <Pi/PiBootMode.h>
#include <Pi/PiHob.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/HobLib.h>
#include <Library/IoLib.h>
#include <Library/QemuFwCfgLib.h>
#include <Library/UefiBootServicesTableLib.h>
@ -27,6 +33,50 @@ READ_BYTES_FUNCTION *InternalQemuFwCfgReadBytes = MmioReadBytes;
WRITE_BYTES_FUNCTION *InternalQemuFwCfgWriteBytes = MmioWriteBytes;
SKIP_BYTES_FUNCTION *InternalQemuFwCfgSkipBytes = MmioSkipBytes;
/**
Build firmware configure resource HOB.
@param[in] FwCfgResource A pointer to firmware configure resource.
@retval VOID
**/
VOID
QemuBuildFwCfgResourceHob (
IN QEMU_FW_CFG_RESOURCE *FwCfgResource
)
{
BuildGuidDataHob (
&gQemuFirmwareResourceHobGuid,
(VOID *)FwCfgResource,
sizeof (QEMU_FW_CFG_RESOURCE)
);
}
/**
Get firmware configure resource in HOB.
@param VOID
@retval non-NULL The firmware configure resource in HOB.
NULL The firmware configure resource not found.
**/
QEMU_FW_CFG_RESOURCE *
QemuGetFwCfgResourceHob (
VOID
)
{
EFI_HOB_GUID_TYPE *GuidHob;
GuidHob = NULL;
GuidHob = GetFirstGuidHob (&gQemuFirmwareResourceHobGuid);
if (GuidHob == NULL) {
return NULL;
}
return (QEMU_FW_CFG_RESOURCE *)GET_GUID_HOB_DATA (GuidHob);
}
/**
Returns a boolean indicating if the firmware configuration interface
is available or not.
@ -43,7 +93,7 @@ QemuFwCfgIsAvailable (
VOID
)
{
return (BOOLEAN)(mFwCfgSelectorAddress != 0 && mFwCfgDataAddress != 0);
return (BOOLEAN)(QemuGetFwCfgSelectorAddress () != 0 && QemuGetFwCfgDataAddress () != 0);
}
/**
@ -62,7 +112,7 @@ QemuFwCfgSelectItem (
)
{
if (QemuFwCfgIsAvailable ()) {
MmioWrite16 (mFwCfgSelectorAddress, SwapBytes16 ((UINT16)QemuFwCfgItem));
MmioWrite16 (QemuGetFwCfgSelectorAddress (), SwapBytes16 ((UINT16)QemuFwCfgItem));
}
}
@ -92,30 +142,30 @@ MmioReadBytes (
#if defined (MDE_CPU_AARCH64) || defined (MDE_CPU_RISCV64) || defined (MDE_CPU_LOONGARCH64)
while (Ptr < End) {
*(UINT64 *)Ptr = MmioRead64 (mFwCfgDataAddress);
*(UINT64 *)Ptr = MmioRead64 (QemuGetFwCfgDataAddress ());
Ptr += 8;
}
if (Left & 4) {
*(UINT32 *)Ptr = MmioRead32 (mFwCfgDataAddress);
*(UINT32 *)Ptr = MmioRead32 (QemuGetFwCfgDataAddress ());
Ptr += 4;
}
#else
while (Ptr < End) {
*(UINT32 *)Ptr = MmioRead32 (mFwCfgDataAddress);
*(UINT32 *)Ptr = MmioRead32 (QemuGetFwCfgDataAddress ());
Ptr += 4;
}
#endif
if (Left & 2) {
*(UINT16 *)Ptr = MmioRead16 (mFwCfgDataAddress);
*(UINT16 *)Ptr = MmioRead16 (QemuGetFwCfgDataAddress ());
Ptr += 2;
}
if (Left & 1) {
*Ptr = MmioRead8 (mFwCfgDataAddress);
*Ptr = MmioRead8 (QemuGetFwCfgDataAddress ());
}
}
@ -168,9 +218,9 @@ DmaTransferBytes (
// This will fire off the transfer.
//
#if defined (MDE_CPU_AARCH64) || defined (MDE_CPU_RISCV64) || defined (MDE_CPU_LOONGARCH64)
MmioWrite64 (mFwCfgDmaAddress, SwapBytes64 ((UINT64)&Access));
MmioWrite64 (QemuGetFwCfgDmaAddress (), SwapBytes64 ((UINT64)&Access));
#else
MmioWrite32 ((UINT32)(mFwCfgDmaAddress + 4), SwapBytes32 ((UINT32)&Access));
MmioWrite32 ((UINT32)(QemuGetFwCfgDmaAddress () + 4), SwapBytes32 ((UINT32)&Access));
#endif
//
@ -239,7 +289,7 @@ MmioWriteBytes (
UINTN Idx;
for (Idx = 0; Idx < Size; ++Idx) {
MmioWrite8 (mFwCfgDataAddress, ((UINT8 *)Buffer)[Idx]);
MmioWrite8 (QemuGetFwCfgDataAddress (), ((UINT8 *)Buffer)[Idx]);
}
}

View File

@ -4,6 +4,7 @@
#
# Copyright (C) 2013 - 2014, Red Hat, Inc.
# Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@ -39,11 +40,15 @@
BaseLib
BaseMemoryLib
DebugLib
HobLib
IoLib
UefiBootServicesTableLib
[Protocols]
gFdtClientProtocolGuid ## CONSUMES
[Guids]
gQemuFirmwareResourceHobGuid
[Depex]
gFdtClientProtocolGuid

View File

@ -12,9 +12,11 @@
#ifndef QEMU_FW_CFG_LIB_MMIO_INTERNAL_H_
#define QEMU_FW_CFG_LIB_MMIO_INTERNAL_H_
extern UINTN mFwCfgSelectorAddress;
extern UINTN mFwCfgDataAddress;
extern UINTN mFwCfgDmaAddress;
typedef struct {
UINTN FwCfgSelectorAddress;
UINTN FwCfgDataAddress;
UINTN FwCfgDmaAddress;
} QEMU_FW_CFG_RESOURCE;
/**
Reads firmware configuration bytes into a buffer
@ -90,6 +92,69 @@ VOID (EFIAPI *InternalQemuFwCfgSkipBytes)(
IN UINTN Size
);
/**
Build firmware configure resource HOB.
@param[in] FwCfgResource A pointer to firmware configure resource.
@retval NULL
**/
VOID
QemuBuildFwCfgResourceHob (
IN QEMU_FW_CFG_RESOURCE *FwCfgResource
);
/**
Get firmware configure resource HOB.
@param VOID
@retval FwCfgResource The firmware configure resouce in HOB.
**/
QEMU_FW_CFG_RESOURCE *
QemuGetFwCfgResourceHob (
VOID
);
/**
To get firmware configure selector address.
@param VOID
@retval firmware configure selector address
**/
UINTN
EFIAPI
QemuGetFwCfgSelectorAddress (
VOID
);
/**
To get firmware configure Data address.
@param VOID
@retval firmware configure data address
**/
UINTN
EFIAPI
QemuGetFwCfgDataAddress (
VOID
);
/**
To get firmware DMA address.
@param VOID
@retval firmware DMA address
**/
UINTN
EFIAPI
QemuGetFwCfgDmaAddress (
VOID
);
/**
Slow READ_BYTES_FUNCTION.
**/

View File

@ -5,6 +5,7 @@
Copyright (C) 2013 - 2014, Red Hat, Inc.
Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
(C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@ -20,9 +21,57 @@
#include "QemuFwCfgLibMmioInternal.h"
UINTN mFwCfgSelectorAddress;
UINTN mFwCfgDataAddress;
UINTN mFwCfgDmaAddress;
STATIC UINTN mFwCfgSelectorAddress;
STATIC UINTN mFwCfgDataAddress;
STATIC UINTN mFwCfgDmaAddress;
/**
To get firmware configure selector address.
@param VOID
@retval firmware configure selector address
**/
UINTN
EFIAPI
QemuGetFwCfgSelectorAddress (
VOID
)
{
return mFwCfgSelectorAddress;
}
/**
To get firmware configure Data address.
@param VOID
@retval firmware configure data address
**/
UINTN
EFIAPI
QemuGetFwCfgDataAddress (
VOID
)
{
return mFwCfgDataAddress;
}
/**
To get firmware DMA address.
@param VOID
@retval firmware DMA address
**/
UINTN
EFIAPI
QemuGetFwCfgDmaAddress (
VOID
)
{
return mFwCfgDmaAddress;
}
RETURN_STATUS
EFIAPI
@ -30,17 +79,37 @@ QemuFwCfgInitialize (
VOID
)
{
EFI_STATUS Status;
FDT_CLIENT_PROTOCOL *FdtClient;
CONST UINT64 *Reg;
UINT32 RegSize;
UINTN AddressCells, SizeCells;
UINT64 FwCfgSelectorAddress;
UINT64 FwCfgSelectorSize;
UINT64 FwCfgDataAddress;
UINT64 FwCfgDataSize;
UINT64 FwCfgDmaAddress;
UINT64 FwCfgDmaSize;
EFI_STATUS Status;
FDT_CLIENT_PROTOCOL *FdtClient;
CONST UINT64 *Reg;
UINT32 RegSize;
UINTN AddressCells, SizeCells;
UINT64 FwCfgSelectorAddress;
UINT64 FwCfgSelectorSize;
UINT64 FwCfgDataAddress;
UINT64 FwCfgDataSize;
UINT64 FwCfgDmaAddress;
UINT64 FwCfgDmaSize;
QEMU_FW_CFG_RESOURCE *FwCfgResource;
//
// Check whether the Qemu firmware configure resources HOB has been created,
// if so use the resources in the HOB.
//
FwCfgResource = QemuGetFwCfgResourceHob ();
if (FwCfgResource != NULL) {
mFwCfgSelectorAddress = FwCfgResource->FwCfgSelectorAddress;
mFwCfgDataAddress = FwCfgResource->FwCfgDataAddress;
mFwCfgDmaAddress = FwCfgResource->FwCfgDmaAddress;
if (mFwCfgDmaAddress != 0) {
InternalQemuFwCfgReadBytes = DmaReadBytes;
InternalQemuFwCfgWriteBytes = DmaWriteBytes;
InternalQemuFwCfgSkipBytes = DmaSkipBytes;
}
return RETURN_SUCCESS;
}
Status = gBS->LocateProtocol (
&gFdtClientProtocolGuid,