Skip to content

Commit

Permalink
OvmfPkg: Add the way of HOBs in QemuFwCfgLibMmio
Browse files Browse the repository at this point in the history
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 <[email protected]>
Cc: Jiewen Yao <[email protected]>
Cc: Gerd Hoffmann <[email protected]>
Cc: Leif Lindholm <[email protected]>
Cc: Sami Mujawar <[email protected]>
Cc: Sunil V L <[email protected]>
Cc: Andrei Warkentin <[email protected]>
Signed-off-by: Chao Li <[email protected]>
  • Loading branch information
kilaterlee authored and mergify[bot] committed Apr 30, 2024
1 parent 5e31c56 commit 748d57d
Show file tree
Hide file tree
Showing 4 changed files with 216 additions and 27 deletions.
70 changes: 60 additions & 10 deletions OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibMmio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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.
Expand All @@ -43,7 +93,7 @@ QemuFwCfgIsAvailable (
VOID
)
{
return (BOOLEAN)(mFwCfgSelectorAddress != 0 && mFwCfgDataAddress != 0);
return (BOOLEAN)(QemuGetFwCfgSelectorAddress () != 0 && QemuGetFwCfgDataAddress () != 0);
}

/**
Expand All @@ -62,7 +112,7 @@ QemuFwCfgSelectItem (
)
{
if (QemuFwCfgIsAvailable ()) {
MmioWrite16 (mFwCfgSelectorAddress, SwapBytes16 ((UINT16)QemuFwCfgItem));
MmioWrite16 (QemuGetFwCfgSelectorAddress (), SwapBytes16 ((UINT16)QemuFwCfgItem));
}
}

Expand Down Expand Up @@ -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 ());
}
}

Expand Down Expand Up @@ -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

//
Expand Down Expand Up @@ -239,7 +289,7 @@ MmioWriteBytes (
UINTN Idx;

for (Idx = 0; Idx < Size; ++Idx) {
MmioWrite8 (mFwCfgDataAddress, ((UINT8 *)Buffer)[Idx]);
MmioWrite8 (QemuGetFwCfgDataAddress (), ((UINT8 *)Buffer)[Idx]);
}
}

Expand Down
5 changes: 5 additions & 0 deletions OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibMmio.inf
Original file line number Diff line number Diff line change
Expand Up @@ -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
#
Expand Down Expand Up @@ -39,11 +40,15 @@
BaseLib
BaseMemoryLib
DebugLib
HobLib
IoLib
UefiBootServicesTableLib

[Protocols]
gFdtClientProtocolGuid ## CONSUMES

[Guids]
gQemuFirmwareResourceHobGuid

[Depex]
gFdtClientProtocolGuid
71 changes: 68 additions & 3 deletions OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibMmioInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
**/
Expand Down
97 changes: 83 additions & 14 deletions OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioDxe.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
**/
Expand All @@ -20,27 +21,95 @@

#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
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,
Expand Down

0 comments on commit 748d57d

Please sign in to comment.