Re: [edk2-devel] [PATCH v4 4/8] OvmfPkg: Add the QemuFwCfgMmioLib PEI stage version
Hi Ard, Thanks, Chao On 2024/4/30 09:19, Chao Li wrote: Hi Ard, OK, I will submit the V5 today and make the adjustments according to your suggestions. On 2024/4/29 21:11, Ard Biesheuvel wrote: On Fri, 26 Apr 2024 at 10:29, Chao Li wrote: Added the PEI stage library for QemuFwCfgMmioLib, which uses the FDT to find the fw_cfg and parse it. BZ:https://bugzilla.tianocore.org/show_bug.cgi?id=4755 Cc: Ard Biesheuvel Cc: Jiewen Yao Cc: Gerd Hoffmann Co-authored-by: Xianglai Li Signed-off-by: Chao Li --- .../Library/QemuFwCfgLib/QemuFwCfgMmioPei.c | 235 ++ .../QemuFwCfgLib/QemuFwCfgMmioPeiLib.inf | 52 2 files changed, 287 insertions(+) create mode 100644 OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioPei.c create mode 100644 OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioPeiLib.inf diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioPei.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioPei.c new file mode 100644 index 00..055148de8e --- /dev/null +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioPei.c @@ -0,0 +1,235 @@ +/** @file + + Stateful and implicitly initialized fw_cfg library implementation. + + Copyright (C) 2013 - 2014, Red Hat, Inc. + Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved. + (C) Copyright 2021 Hewlett Packard Enterprise Development LP + Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include + +#include +#include +#include +#include +#include + +#include + +#include "QemuFwCfgLibMmioInternal.h" + +/** + To get firmware configure selector address. + + @param VOID + + @retval firmware configure selector address +**/ +UINTN +EFIAPI +QemuGetFwCfgSelectorAddress ( + VOID + ) +{ + QEMU_FW_CFG_RESOURCE *FwCfgResource; + + FwCfgResource = QemuGetFwCfgResourceHob (); + ASSERT (FwCfgResource != NULL); + + return FwCfgResource->FwCfgSelectorAddress; +} + +/** + To get firmware configure Data address. + + @param VOID + + @retval firmware configure data address +**/ +UINTN +EFIAPI +QemuGetFwCfgDataAddress ( + VOID + ) +{ + QEMU_FW_CFG_RESOURCE *FwCfgResource; + + FwCfgResource = QemuGetFwCfgResourceHob (); + ASSERT (FwCfgResource != NULL); + + return FwCfgResource->FwCfgDataAddress; +} + +/** + To get firmware DMA address. + + @param VOID + + @retval firmware DMA address +**/ +UINTN +EFIAPI +QemuGetFwCfgDmaAddress ( + VOID + ) +{ + QEMU_FW_CFG_RESOURCE *FwCfgResource; + + FwCfgResource = QemuGetFwCfgResourceHob (); + ASSERT (FwCfgResource != NULL); + + return FwCfgResource->FwCfgDmaAddress; +} + +RETURN_STATUS +EFIAPI +QemuFwCfgInitialize ( + VOID + ) +{ + VOID *DeviceTreeBase; + INT32 Node; + INT32 Prev; + CONST CHAR8 *Type; + INT32 Len; + CONST UINT64 *Reg; + UINT64FwCfgSelectorAddress; + UINT64FwCfgSelectorSize; + UINT64FwCfgDataAddress; + UINT64FwCfgDataSize; + UINT64FwCfgDmaAddress; + UINT64FwCfgDmaSize; + QEMU_FW_CFG_RESOURCE *FwCfgResource; + VOID *Buffer; + + // + // Check whether the Qemu firmware configure resources HOB has been created, + // if so use the resources in the HOB. + // + FwCfgResource = QemuGetFwCfgResourceHob (); + if (FwCfgResource != NULL) { +return RETURN_SUCCESS; + } + + DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress); + ASSERT (DeviceTreeBase != NULL); + // + // Make sure we have a valid device tree blob + // + ASSERT (fdt_check_header (DeviceTreeBase) == 0); + + // + // Create resouce memory + // + Buffer = AllocatePages(EFI_SIZE_TO_PAGES (sizeof (QEMU_FW_CFG_RESOURCE))); + ASSERT (Buffer != NULL); + ZeroMem (Buffer, sizeof (QEMU_FW_CFG_RESOURCE)); + + FwCfgResource = (QEMU_FW_CFG_RESOURCE *)Buffer; + You will need to respin after all, so please incorporate the fixes I proposed on v4 + for (Prev = 0; ; Prev = Node) { +Node = fdt_next_node (DeviceTreeBase, Prev, NULL); +if (Node < 0) { + break; +} + +// +// Check for memory node +// +Type = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len); +if ((Type) && and here +(AsciiStrnCmp (Type, "qemu,fw-cfg-mmio", Len) == 0)) +{ + // + // Get the 'reg' property of this node. For now, we will assume + // two 8 byte quantities for base and size, respectively. + // + Reg = fdt_getprop (DeviceTreeBase, Node, "reg", &Len); + if ((Reg != 0) && (Len == (2 * sizeof (UINT64 { +FwCfgDataAddress = SwapBytes64 (Reg[0]); +FwCfgDataSize= 8; +FwCfgSelectorAddress = FwCfgDataAddress + FwCfgDataSize; +FwCfgSelectorSize= 2; + +// +// The following ASSERT()s express +// +// Address + Size - 1 <= MAX_UINTN +// +
Re: [edk2-devel] [PATCH v4 4/8] OvmfPkg: Add the QemuFwCfgMmioLib PEI stage version
Hi Ard, OK, I will submit the V5 today and make the adjustments according to your suggestions. Thanks, Chao On 2024/4/29 21:11, Ard Biesheuvel wrote: On Fri, 26 Apr 2024 at 10:29, Chao Li wrote: Added the PEI stage library for QemuFwCfgMmioLib, which uses the FDT to find the fw_cfg and parse it. BZ:https://bugzilla.tianocore.org/show_bug.cgi?id=4755 Cc: Ard Biesheuvel Cc: Jiewen Yao Cc: Gerd Hoffmann Co-authored-by: Xianglai Li Signed-off-by: Chao Li --- .../Library/QemuFwCfgLib/QemuFwCfgMmioPei.c | 235 ++ .../QemuFwCfgLib/QemuFwCfgMmioPeiLib.inf | 52 2 files changed, 287 insertions(+) create mode 100644 OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioPei.c create mode 100644 OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioPeiLib.inf diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioPei.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioPei.c new file mode 100644 index 00..055148de8e --- /dev/null +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioPei.c @@ -0,0 +1,235 @@ +/** @file + + Stateful and implicitly initialized fw_cfg library implementation. + + Copyright (C) 2013 - 2014, Red Hat, Inc. + Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved. + (C) Copyright 2021 Hewlett Packard Enterprise Development LP + Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include + +#include +#include +#include +#include +#include + +#include + +#include "QemuFwCfgLibMmioInternal.h" + +/** + To get firmware configure selector address. + + @param VOID + + @retval firmware configure selector address +**/ +UINTN +EFIAPI +QemuGetFwCfgSelectorAddress ( + VOID + ) +{ + QEMU_FW_CFG_RESOURCE *FwCfgResource; + + FwCfgResource = QemuGetFwCfgResourceHob (); + ASSERT (FwCfgResource != NULL); + + return FwCfgResource->FwCfgSelectorAddress; +} + +/** + To get firmware configure Data address. + + @param VOID + + @retval firmware configure data address +**/ +UINTN +EFIAPI +QemuGetFwCfgDataAddress ( + VOID + ) +{ + QEMU_FW_CFG_RESOURCE *FwCfgResource; + + FwCfgResource = QemuGetFwCfgResourceHob (); + ASSERT (FwCfgResource != NULL); + + return FwCfgResource->FwCfgDataAddress; +} + +/** + To get firmware DMA address. + + @param VOID + + @retval firmware DMA address +**/ +UINTN +EFIAPI +QemuGetFwCfgDmaAddress ( + VOID + ) +{ + QEMU_FW_CFG_RESOURCE *FwCfgResource; + + FwCfgResource = QemuGetFwCfgResourceHob (); + ASSERT (FwCfgResource != NULL); + + return FwCfgResource->FwCfgDmaAddress; +} + +RETURN_STATUS +EFIAPI +QemuFwCfgInitialize ( + VOID + ) +{ + VOID *DeviceTreeBase; + INT32 Node; + INT32 Prev; + CONST CHAR8 *Type; + INT32 Len; + CONST UINT64 *Reg; + UINT64FwCfgSelectorAddress; + UINT64FwCfgSelectorSize; + UINT64FwCfgDataAddress; + UINT64FwCfgDataSize; + UINT64FwCfgDmaAddress; + UINT64FwCfgDmaSize; + QEMU_FW_CFG_RESOURCE *FwCfgResource; + VOID *Buffer; + + // + // Check whether the Qemu firmware configure resources HOB has been created, + // if so use the resources in the HOB. + // + FwCfgResource = QemuGetFwCfgResourceHob (); + if (FwCfgResource != NULL) { +return RETURN_SUCCESS; + } + + DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress); + ASSERT (DeviceTreeBase != NULL); + // + // Make sure we have a valid device tree blob + // + ASSERT (fdt_check_header (DeviceTreeBase) == 0); + + // + // Create resouce memory + // + Buffer = AllocatePages(EFI_SIZE_TO_PAGES (sizeof (QEMU_FW_CFG_RESOURCE))); + ASSERT (Buffer != NULL); + ZeroMem (Buffer, sizeof (QEMU_FW_CFG_RESOURCE)); + + FwCfgResource = (QEMU_FW_CFG_RESOURCE *)Buffer; + You will need to respin after all, so please incorporate the fixes I proposed on v4 + for (Prev = 0; ; Prev = Node) { +Node = fdt_next_node (DeviceTreeBase, Prev, NULL); +if (Node < 0) { + break; +} + +// +// Check for memory node +// +Type = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len); +if ((Type) && and here +(AsciiStrnCmp (Type, "qemu,fw-cfg-mmio", Len) == 0)) +{ + // + // Get the 'reg' property of this node. For now, we will assume + // two 8 byte quantities for base and size, respectively. + // + Reg = fdt_getprop (DeviceTreeBase, Node, "reg", &Len); + if ((Reg != 0) && (Len == (2 * sizeof (UINT64 { +FwCfgDataAddress = SwapBytes64 (Reg[0]); +FwCfgDataSize= 8; +FwCfgSelectorAddress = FwCfgDataAddress + FwCfgDataSize; +FwCfgSelectorSize= 2; + +// +// The following ASSERT()s express +// +// Address + Size - 1 <= MAX_UINTN +// +// for both registers, that is, that t
Re: [edk2-devel] [PATCH v4 4/8] OvmfPkg: Add the QemuFwCfgMmioLib PEI stage version
On Fri, 26 Apr 2024 at 10:29, Chao Li wrote: > > Added the PEI stage library for QemuFwCfgMmioLib, which uses the FDT to > find the fw_cfg and parse it. > > BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4755 > > Cc: Ard Biesheuvel > Cc: Jiewen Yao > Cc: Gerd Hoffmann > Co-authored-by: Xianglai Li > Signed-off-by: Chao Li > --- > .../Library/QemuFwCfgLib/QemuFwCfgMmioPei.c | 235 ++ > .../QemuFwCfgLib/QemuFwCfgMmioPeiLib.inf | 52 > 2 files changed, 287 insertions(+) > create mode 100644 OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioPei.c > create mode 100644 OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioPeiLib.inf > > diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioPei.c > b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioPei.c > new file mode 100644 > index 00..055148de8e > --- /dev/null > +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioPei.c > @@ -0,0 +1,235 @@ > +/** @file > + > + Stateful and implicitly initialized fw_cfg library implementation. > + > + Copyright (C) 2013 - 2014, Red Hat, Inc. > + Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved. > + (C) Copyright 2021 Hewlett Packard Enterprise Development LP > + Copyright (c) 2024 Loongson Technology Corporation Limited. All rights > reserved. > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > +**/ > + > +#include > + > +#include > +#include > +#include > +#include > +#include > + > +#include > + > +#include "QemuFwCfgLibMmioInternal.h" > + > +/** > + To get firmware configure selector address. > + > + @param VOID > + > + @retval firmware configure selector address > +**/ > +UINTN > +EFIAPI > +QemuGetFwCfgSelectorAddress ( > + VOID > + ) > +{ > + QEMU_FW_CFG_RESOURCE *FwCfgResource; > + > + FwCfgResource = QemuGetFwCfgResourceHob (); > + ASSERT (FwCfgResource != NULL); > + > + return FwCfgResource->FwCfgSelectorAddress; > +} > + > +/** > + To get firmware configure Data address. > + > + @param VOID > + > + @retval firmware configure data address > +**/ > +UINTN > +EFIAPI > +QemuGetFwCfgDataAddress ( > + VOID > + ) > +{ > + QEMU_FW_CFG_RESOURCE *FwCfgResource; > + > + FwCfgResource = QemuGetFwCfgResourceHob (); > + ASSERT (FwCfgResource != NULL); > + > + return FwCfgResource->FwCfgDataAddress; > +} > + > +/** > + To get firmware DMA address. > + > + @param VOID > + > + @retval firmware DMA address > +**/ > +UINTN > +EFIAPI > +QemuGetFwCfgDmaAddress ( > + VOID > + ) > +{ > + QEMU_FW_CFG_RESOURCE *FwCfgResource; > + > + FwCfgResource = QemuGetFwCfgResourceHob (); > + ASSERT (FwCfgResource != NULL); > + > + return FwCfgResource->FwCfgDmaAddress; > +} > + > +RETURN_STATUS > +EFIAPI > +QemuFwCfgInitialize ( > + VOID > + ) > +{ > + VOID *DeviceTreeBase; > + INT32 Node; > + INT32 Prev; > + CONST CHAR8 *Type; > + INT32 Len; > + CONST UINT64 *Reg; > + UINT64FwCfgSelectorAddress; > + UINT64FwCfgSelectorSize; > + UINT64FwCfgDataAddress; > + UINT64FwCfgDataSize; > + UINT64FwCfgDmaAddress; > + UINT64FwCfgDmaSize; > + QEMU_FW_CFG_RESOURCE *FwCfgResource; > + VOID *Buffer; > + > + // > + // Check whether the Qemu firmware configure resources HOB has been > created, > + // if so use the resources in the HOB. > + // > + FwCfgResource = QemuGetFwCfgResourceHob (); > + if (FwCfgResource != NULL) { > +return RETURN_SUCCESS; > + } > + > + DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress); > + ASSERT (DeviceTreeBase != NULL); > + // > + // Make sure we have a valid device tree blob > + // > + ASSERT (fdt_check_header (DeviceTreeBase) == 0); > + > + // > + // Create resouce memory > + // > + Buffer = AllocatePages(EFI_SIZE_TO_PAGES (sizeof (QEMU_FW_CFG_RESOURCE))); > + ASSERT (Buffer != NULL); > + ZeroMem (Buffer, sizeof (QEMU_FW_CFG_RESOURCE)); > + > + FwCfgResource = (QEMU_FW_CFG_RESOURCE *)Buffer; > + You will need to respin after all, so please incorporate the fixes I proposed on v4 > + for (Prev = 0; ; Prev = Node) { > +Node = fdt_next_node (DeviceTreeBase, Prev, NULL); > +if (Node < 0) { > + break; > +} > + > +// > +// Check for memory node > +// > +Type = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len); > +if ((Type) && and here > +(AsciiStrnCmp (Type, "qemu,fw-cfg-mmio", Len) == 0)) > +{ > + // > + // Get the 'reg' property of this node. For now, we will assume > + // two 8 byte quantities for base and size, respectively. > + // > + Reg = fdt_getprop (DeviceTreeBase, Node, "reg", &Len); > + if ((Reg != 0) && (Len == (2 * sizeof (UINT64 { > +FwCfgDataAddress = SwapBytes64 (Reg[0]); > +FwCfgDataSize= 8; > +FwCfgSelectorAddress = FwCfgDataAddress + FwCfgDataSize; > +
[edk2-devel] [PATCH v4 4/8] OvmfPkg: Add the QemuFwCfgMmioLib PEI stage version
Added the PEI stage library for QemuFwCfgMmioLib, which uses the FDT to find the fw_cfg and parse it. BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4755 Cc: Ard Biesheuvel Cc: Jiewen Yao Cc: Gerd Hoffmann Co-authored-by: Xianglai Li Signed-off-by: Chao Li --- .../Library/QemuFwCfgLib/QemuFwCfgMmioPei.c | 235 ++ .../QemuFwCfgLib/QemuFwCfgMmioPeiLib.inf | 52 2 files changed, 287 insertions(+) create mode 100644 OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioPei.c create mode 100644 OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioPeiLib.inf diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioPei.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioPei.c new file mode 100644 index 00..055148de8e --- /dev/null +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioPei.c @@ -0,0 +1,235 @@ +/** @file + + Stateful and implicitly initialized fw_cfg library implementation. + + Copyright (C) 2013 - 2014, Red Hat, Inc. + Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved. + (C) Copyright 2021 Hewlett Packard Enterprise Development LP + Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include + +#include +#include +#include +#include +#include + +#include + +#include "QemuFwCfgLibMmioInternal.h" + +/** + To get firmware configure selector address. + + @param VOID + + @retval firmware configure selector address +**/ +UINTN +EFIAPI +QemuGetFwCfgSelectorAddress ( + VOID + ) +{ + QEMU_FW_CFG_RESOURCE *FwCfgResource; + + FwCfgResource = QemuGetFwCfgResourceHob (); + ASSERT (FwCfgResource != NULL); + + return FwCfgResource->FwCfgSelectorAddress; +} + +/** + To get firmware configure Data address. + + @param VOID + + @retval firmware configure data address +**/ +UINTN +EFIAPI +QemuGetFwCfgDataAddress ( + VOID + ) +{ + QEMU_FW_CFG_RESOURCE *FwCfgResource; + + FwCfgResource = QemuGetFwCfgResourceHob (); + ASSERT (FwCfgResource != NULL); + + return FwCfgResource->FwCfgDataAddress; +} + +/** + To get firmware DMA address. + + @param VOID + + @retval firmware DMA address +**/ +UINTN +EFIAPI +QemuGetFwCfgDmaAddress ( + VOID + ) +{ + QEMU_FW_CFG_RESOURCE *FwCfgResource; + + FwCfgResource = QemuGetFwCfgResourceHob (); + ASSERT (FwCfgResource != NULL); + + return FwCfgResource->FwCfgDmaAddress; +} + +RETURN_STATUS +EFIAPI +QemuFwCfgInitialize ( + VOID + ) +{ + VOID *DeviceTreeBase; + INT32 Node; + INT32 Prev; + CONST CHAR8 *Type; + INT32 Len; + CONST UINT64 *Reg; + UINT64FwCfgSelectorAddress; + UINT64FwCfgSelectorSize; + UINT64FwCfgDataAddress; + UINT64FwCfgDataSize; + UINT64FwCfgDmaAddress; + UINT64FwCfgDmaSize; + QEMU_FW_CFG_RESOURCE *FwCfgResource; + VOID *Buffer; + + // + // Check whether the Qemu firmware configure resources HOB has been created, + // if so use the resources in the HOB. + // + FwCfgResource = QemuGetFwCfgResourceHob (); + if (FwCfgResource != NULL) { +return RETURN_SUCCESS; + } + + DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress); + ASSERT (DeviceTreeBase != NULL); + // + // Make sure we have a valid device tree blob + // + ASSERT (fdt_check_header (DeviceTreeBase) == 0); + + // + // Create resouce memory + // + Buffer = AllocatePages(EFI_SIZE_TO_PAGES (sizeof (QEMU_FW_CFG_RESOURCE))); + ASSERT (Buffer != NULL); + ZeroMem (Buffer, sizeof (QEMU_FW_CFG_RESOURCE)); + + FwCfgResource = (QEMU_FW_CFG_RESOURCE *)Buffer; + + for (Prev = 0; ; Prev = Node) { +Node = fdt_next_node (DeviceTreeBase, Prev, NULL); +if (Node < 0) { + break; +} + +// +// Check for memory node +// +Type = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len); +if ((Type) && +(AsciiStrnCmp (Type, "qemu,fw-cfg-mmio", Len) == 0)) +{ + // + // Get the 'reg' property of this node. For now, we will assume + // two 8 byte quantities for base and size, respectively. + // + Reg = fdt_getprop (DeviceTreeBase, Node, "reg", &Len); + if ((Reg != 0) && (Len == (2 * sizeof (UINT64 { +FwCfgDataAddress = SwapBytes64 (Reg[0]); +FwCfgDataSize= 8; +FwCfgSelectorAddress = FwCfgDataAddress + FwCfgDataSize; +FwCfgSelectorSize= 2; + +// +// The following ASSERT()s express +// +// Address + Size - 1 <= MAX_UINTN +// +// for both registers, that is, that the last byte in each MMIO range is +// expressible as a MAX_UINTN. The form below is mathematically +// equivalent, and it also prevents any unsigned overflow before the +// comparison. +// +ASSERT (FwCfgSelectorAddress <= MAX_UINTN - FwCfgSelectorSize + 1); +