Reviewed-By: Olivier Martin <[email protected]> > -----Original Message----- > From: Laszlo Ersek [mailto:[email protected]] > Sent: 11 December 2014 02:46 > To: [email protected]; [email protected]; > [email protected]; [email protected] > Subject: [edk2] [PATCH v3 02/13] ArmVirtualizationPkg: introduce > QemuFwCfgLib instance for DXE drivers > > After reviewing OvmfPkg's use of its own QemuFwCfgLib instances, it is > clear that its only pre-DXE fw_cfg dependency concerns S3 support (the > QemuFwCfgS3Enabled() call in "PlatformPei/Platform.c"). > > For ARM guests, S3 is in the distant future, but we can see several > shorter term applications for fw_cfg that all reside in DXE: > - controlling boot order (to be implemented in PlatformBdsLib for Intel > BDS), > - supporting -kernel / -initrd / -append boot on QEMU (to be > implemented > in PlatformBdsLib for Intel BDS, similarly), > - loading and linking ACPI tables, > - installing SMBIOS tables. > > Therefore it makes sense to add a simple MMIO-based fw_cfg client > library > to ArmVirtualizationPkg that for the moment is only available to > DXE_DRIVER modules. > > Because MMIO accesses are costly on KVM/ARM, > InternalQemuFwCfgReadBytes() > accesses the fw_cfg data register in full words. This speeds up > transfers > almost linearly. > > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Laszlo Ersek <[email protected]> > --- > > Notes: > v3: > - full word access to fw_cfg data register > - mention '-kernel' booting in commit message > > > ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.i > nf | 52 ++++++++++ > > ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c > | 358 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc > | 1 + > 3 files changed, 411 insertions(+) > > diff --git > a/ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib > .inf > b/ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib > .inf > new file mode 100644 > index 0000000..21ab2bf > --- /dev/null > +++ > b/ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib > .inf > @@ -0,0 +1,52 @@ > +## @file > +# > +# Stateful, implicitly initialized fw_cfg library. > +# > +# Copyright (C) 2013 - 2014, Red Hat, Inc. > +# Copyright (c) 2008 - 2012, Intel Corporation. All rights > reserved.<BR> > +# > +# This program and the accompanying materials are licensed and made > available > +# under the terms and conditions of the BSD License which accompanies > this > +# distribution. The full text of the license may be found at > +# http://opensource.org/licenses/bsd-license.php > +# > +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" > BASIS, > +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS > OR > +# IMPLIED. > +# > +## > + > +[Defines] > + INF_VERSION = 0x00010005 > + BASE_NAME = QemuFwCfgLib > + FILE_GUID = B271F41F-B841-48A9-BA8D- > 545B4BC2E2BF > + MODULE_TYPE = BASE > + VERSION_STRING = 1.0 > + LIBRARY_CLASS = QemuFwCfgLib|DXE_DRIVER > + > + CONSTRUCTOR = QemuFwCfgInitialize > + > +# > +# The following information is for reference only and not required by > the build > +# tools. > +# > +# VALID_ARCHITECTURES = ARM AARCH64 > +# > + > +[Sources] > + QemuFwCfgLib.c > + > +[Packages] > + MdePkg/MdePkg.dec > + OvmfPkg/OvmfPkg.dec > + ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec > + > +[LibraryClasses] > + BaseLib > + BaseMemoryLib > + IoLib > + PcdLib > + > +[Pcd] > + gArmVirtualizationTokenSpaceGuid.PcdFwCfgSelectorAddress > + gArmVirtualizationTokenSpaceGuid.PcdFwCfgDataAddress > diff --git > a/ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib > .c > b/ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib > .c > new file mode 100644 > index 0000000..dc7506f > --- /dev/null > +++ > b/ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib > .c > @@ -0,0 +1,358 @@ > +/** @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.<BR> > + > + This program and the accompanying materials are licensed and made > available > + under the terms and conditions of the BSD License which accompanies > this > + distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" > BASIS, WITHOUT > + WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR > IMPLIED. > +**/ > + > +#include <Library/BaseLib.h> > +#include <Library/BaseMemoryLib.h> > +#include <Library/IoLib.h> > +#include <Library/PcdLib.h> > +#include <Library/QemuFwCfgLib.h> > + > +STATIC UINTN mFwCfgSelectorAddress; > +STATIC UINTN mFwCfgDataAddress; > + > + > +/** > + Returns a boolean indicating if the firmware configuration interface > is > + available for library-internal purposes. > + > + This function never changes fw_cfg state. > + > + @retval TRUE The interface is available internally. > + @retval FALSE The interface is not available internally. > +**/ > +BOOLEAN > +EFIAPI > +InternalQemuFwCfgIsAvailable ( > + VOID > + ) > +{ > + return (BOOLEAN)(mFwCfgSelectorAddress != 0 && mFwCfgDataAddress != > 0); > +} > + > + > +/** > + Returns a boolean indicating if the firmware configuration interface > + is available or not. > + > + This function may change fw_cfg state. > + > + @retval TRUE The interface is available > + @retval FALSE The interface is not available > + > +**/ > +BOOLEAN > +EFIAPI > +QemuFwCfgIsAvailable ( > + VOID > + ) > +{ > + return InternalQemuFwCfgIsAvailable (); > +} > + > + > +RETURN_STATUS > +EFIAPI > +QemuFwCfgInitialize ( > + VOID > + ) > +{ > + mFwCfgSelectorAddress = (UINTN)PcdGet64 (PcdFwCfgSelectorAddress); > + mFwCfgDataAddress = (UINTN)PcdGet64 (PcdFwCfgDataAddress); > + > + if (InternalQemuFwCfgIsAvailable ()) { > + UINT32 Signature; > + > + QemuFwCfgSelectItem (QemuFwCfgItemSignature); > + Signature = QemuFwCfgRead32 (); > + if (Signature != SIGNATURE_32 ('Q', 'E', 'M', 'U')) { > + mFwCfgSelectorAddress = 0; > + mFwCfgDataAddress = 0; > + } > + } > + return RETURN_SUCCESS; > +} > + > + > +/** > + Selects a firmware configuration item for reading. > + > + Following this call, any data read from this item will start from > the > + beginning of the configuration item's data. > + > + @param[in] QemuFwCfgItem Firmware Configuration item to read > + > +**/ > +VOID > +EFIAPI > +QemuFwCfgSelectItem ( > + IN FIRMWARE_CONFIG_ITEM QemuFwCfgItem > + ) > +{ > + if (InternalQemuFwCfgIsAvailable ()) { > + MmioWrite16 (mFwCfgSelectorAddress, (UINT16)QemuFwCfgItem); > + } > +} > + > + > +/** > + 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) > + > +**/ > +STATIC > +VOID > +EFIAPI > +InternalQemuFwCfgReadBytes ( > + IN UINTN Size, > + IN VOID *Buffer OPTIONAL > + ) > +{ > + UINTN Left; > + UINT8 *Ptr; > + UINT8 *End; > + > +#ifdef MDE_CPU_AARCH64 > + Left = Size & 7; > +#else > + Left = Size & 3; > +#endif > + > + Size -= Left; > + Ptr = Buffer; > + End = Ptr + Size; > + > +#ifdef MDE_CPU_AARCH64 > + while (Ptr < End) { > + *(UINT64 *)Ptr = MmioRead64 (mFwCfgDataAddress); > + Ptr += 8; > + } > + if (Left & 4) { > + *(UINT32 *)Ptr = MmioRead32 (mFwCfgDataAddress); > + Ptr += 4; > + } > +#else > + while (Ptr < End) { > + *(UINT32 *)Ptr = MmioRead32 (mFwCfgDataAddress); > + Ptr += 4; > + } > +#endif > + > + if (Left & 2) { > + *(UINT16 *)Ptr = MmioRead16 (mFwCfgDataAddress); > + Ptr += 2; > + } > + if (Left & 1) { > + *Ptr = MmioRead8 (mFwCfgDataAddress); > + } > +} > + > + > +/** > + Reads firmware configuration bytes into a buffer > + > + If called multiple times, then the data read will continue at the > offset of > + the firmware configuration item where the previous read ended. > + > + @param[in] Size Size in bytes to read > + @param[in] Buffer Buffer to store data into > + > +**/ > +VOID > +EFIAPI > +QemuFwCfgReadBytes ( > + IN UINTN Size, > + IN VOID *Buffer > + ) > +{ > + if (InternalQemuFwCfgIsAvailable ()) { > + InternalQemuFwCfgReadBytes (Size, Buffer); > + } else { > + ZeroMem (Buffer, Size); > + } > +} > + > +/** > + Write firmware configuration bytes from a buffer > + > + If called multiple times, then the data written will continue at the > offset > + of the firmware configuration item where the previous write ended. > + > + @param[in] Size Size in bytes to write > + @param[in] Buffer Buffer to read data from > + > +**/ > +VOID > +EFIAPI > +QemuFwCfgWriteBytes ( > + IN UINTN Size, > + IN VOID *Buffer > + ) > +{ > + if (InternalQemuFwCfgIsAvailable ()) { > + UINTN Idx; > + > + for (Idx = 0; Idx < Size; ++Idx) { > + MmioWrite8 (mFwCfgDataAddress, ((UINT8 *)Buffer)[Idx]); > + } > + } > +} > + > + > +/** > + Reads a UINT8 firmware configuration value > + > + @return Value of Firmware Configuration item read > + > +**/ > +UINT8 > +EFIAPI > +QemuFwCfgRead8 ( > + VOID > + ) > +{ > + UINT8 Result; > + > + QemuFwCfgReadBytes (sizeof Result, &Result); > + return Result; > +} > + > + > +/** > + Reads a UINT16 firmware configuration value > + > + @return Value of Firmware Configuration item read > + > +**/ > +UINT16 > +EFIAPI > +QemuFwCfgRead16 ( > + VOID > + ) > +{ > + UINT16 Result; > + > + QemuFwCfgReadBytes (sizeof Result, &Result); > + return Result; > +} > + > + > +/** > + Reads a UINT32 firmware configuration value > + > + @return Value of Firmware Configuration item read > + > +**/ > +UINT32 > +EFIAPI > +QemuFwCfgRead32 ( > + VOID > + ) > +{ > + UINT32 Result; > + > + QemuFwCfgReadBytes (sizeof Result, &Result); > + return Result; > +} > + > + > +/** > + Reads a UINT64 firmware configuration value > + > + @return Value of Firmware Configuration item read > + > +**/ > +UINT64 > +EFIAPI > +QemuFwCfgRead64 ( > + VOID > + ) > +{ > + UINT64 Result; > + > + QemuFwCfgReadBytes (sizeof Result, &Result); > + return Result; > +} > + > + > +/** > + Find the configuration item corresponding to the firmware > configuration file. > + > + @param[in] Name Name of file to look up. > + @param[out] Item Configuration item corresponding to the file, to > be passed > + to QemuFwCfgSelectItem (). > + @param[out] Size Number of bytes in the file. > + > + @retval RETURN_SUCCESS If file is found. > + @retval RETURN_NOT_FOUND If file is not found. > + @retval RETURN_UNSUPPORTED If firmware configuration is > unavailable. > + > +**/ > +RETURN_STATUS > +EFIAPI > +QemuFwCfgFindFile ( > + IN CONST CHAR8 *Name, > + OUT FIRMWARE_CONFIG_ITEM *Item, > + OUT UINTN *Size > + ) > +{ > + UINT32 Count; > + UINT32 Idx; > + > + if (!InternalQemuFwCfgIsAvailable ()) { > + return RETURN_UNSUPPORTED; > + } > + > + QemuFwCfgSelectItem (QemuFwCfgItemFileDir); > + Count = SwapBytes32 (QemuFwCfgRead32 ()); > + > + for (Idx = 0; Idx < Count; ++Idx) { > + UINT32 FileSize; > + UINT16 FileSelect; > + CHAR8 FName[QEMU_FW_CFG_FNAME_SIZE]; > + > + FileSize = QemuFwCfgRead32 (); > + FileSelect = QemuFwCfgRead16 (); > + QemuFwCfgRead16 (); // skip the field called "reserved" > + InternalQemuFwCfgReadBytes (sizeof (FName), FName); > + > + if (AsciiStrCmp (Name, FName) == 0) { > + *Item = SwapBytes16 (FileSelect); > + *Size = SwapBytes32 (FileSize); > + return RETURN_SUCCESS; > + } > + } > + > + return RETURN_NOT_FOUND; > +} > + > + > +/** > + Determine if S3 support is explicitly enabled. > + > + @retval TRUE if S3 support is explicitly enabled. > + FALSE otherwise. This includes unavailability of the > firmware > + configuration interface. > +**/ > +BOOLEAN > +EFIAPI > +QemuFwCfgS3Enabled ( > + VOID > + ) > +{ > + return FALSE; > +} > diff --git > a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc > b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc > index 1f3ddea..60f7d7f 100644 > --- a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc > +++ b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc > @@ -42,6 +42,7 @@ > # Virtio Support > VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf > > VirtioMmioDeviceLib|OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevic > eLib.inf > + > QemuFwCfgLib|ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/Q > emuFwCfgLib.inf > > > ArmPlatformLib|ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualiz > ationPlatformLib/ArmVirtualizationPlatformLib.inf > > ArmPlatformSysConfigLib|ArmPlatformPkg/Library/ArmPlatformSysConfigLibN > ull/ArmPlatformSysConfigLibNull.inf > -- > 1.8.3.1 > > > > ----------------------------------------------------------------------- > ------- > Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server > from Actuate! Instantly Supercharge Your Business Reports and > Dashboards > with Interactivity, Sharing, Native Excel Exports, App Integration & > more > Get technology previously reserved for billion-dollar corporations, > FREE > http://pubads.g.doubleclick.net/gampad/clk?id=164703151&iu=/4140/ostg.c > lktrk > _______________________________________________ > edk2-devel mailing list > [email protected] > https://lists.sourceforge.net/lists/listinfo/edk2-devel
------------------------------------------------------------------------------ Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server from Actuate! Instantly Supercharge Your Business Reports and Dashboards with Interactivity, Sharing, Native Excel Exports, App Integration & more Get technology previously reserved for billion-dollar corporations, FREE http://pubads.g.doubleclick.net/gampad/clk?id=164703151&iu=/4140/ostg.clktrk _______________________________________________ edk2-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/edk2-devel
