diff --git a/ArmVirtPkg/ArmVirtQemu.dsc b/ArmVirtPkg/ArmVirtQemu.dsc index aa0ce61630..9369a88858 100644 --- a/ArmVirtPkg/ArmVirtQemu.dsc +++ b/ArmVirtPkg/ArmVirtQemu.dsc @@ -81,6 +81,7 @@ PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf PciHostBridgeLib|OvmfPkg/Fdt/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf PciHostBridgeUtilityLib|OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.inf + PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf !if $(TPM2_ENABLE) == TRUE Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf diff --git a/OvmfPkg/AmdSev/AmdSevX64.dsc b/OvmfPkg/AmdSev/AmdSevX64.dsc index fa081e4fea..7497cace9c 100644 --- a/OvmfPkg/AmdSev/AmdSevX64.dsc +++ b/OvmfPkg/AmdSev/AmdSevX64.dsc @@ -168,6 +168,7 @@ FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf BlobVerifierLib|OvmfPkg/AmdSev/BlobVerifierLibSevHashes/BlobVerifierLibSevHashes.inf MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf + PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf !if $(SOURCE_DEBUG_ENABLE) == TRUE PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf diff --git a/OvmfPkg/Bhyve/BhyveX64.dsc b/OvmfPkg/Bhyve/BhyveX64.dsc index f0166e136c..ada904464e 100644 --- a/OvmfPkg/Bhyve/BhyveX64.dsc +++ b/OvmfPkg/Bhyve/BhyveX64.dsc @@ -170,6 +170,7 @@ MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf + PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf diff --git a/OvmfPkg/CloudHv/CloudHvX64.dsc b/OvmfPkg/CloudHv/CloudHvX64.dsc index c568662313..7fbc1021e2 100644 --- a/OvmfPkg/CloudHv/CloudHvX64.dsc +++ b/OvmfPkg/CloudHv/CloudHvX64.dsc @@ -180,6 +180,7 @@ VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf + PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf !if $(SMM_REQUIRE) == FALSE LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf !endif diff --git a/OvmfPkg/Include/Library/HardwareInfoLib.h b/OvmfPkg/Include/Library/HardwareInfoLib.h new file mode 100644 index 0000000000..66d964dab5 --- /dev/null +++ b/OvmfPkg/Include/Library/HardwareInfoLib.h @@ -0,0 +1,159 @@ +/*/@file + Hardware info parsing functions. + Binary data is expected as a consecutive series of header - object pairs. + Complete library providing static Qemu fw-cfg wrappers as well as list-like + interface to dynamically manipulate hardware info objects and parsing from + a generic blob. + + Copyright 2021 - 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __HARDWARE_INFO_LIB_H__ +#define __HARDWARE_INFO_LIB_H__ + +#include "../Library/HardwareInfoLib/HardwareInfoTypesLib.h" + +/** + Read, if available, the next Type element in the FwCfg file. + The FwCfg item must already be selected, this is a wrapper around + QemuFwCfgReadBytes and the Data pointer should be set to an existent + memory location with TypeSize bytes allocated for the date to be + properly written. If a Type element is found in the file which has a + size (in the header) greater than TypeSize, it is skipped. + + @param[in] Type Hardware Info Type to search for + @param[in] TypeSize Size (in bytes) of the structure intended to + be used to dereference the data + @param[in] TotalFileSize Total size (in bytes) of the FwCfg file from + which the data is read. + @param[out] Data Pointer to a memory allocated instance into + which the data is written to. + @param[out] DataSize Size in bytes of the actually filled + data available in the Data object after a + successful operation + @param[inout] ReadIndex Index of the next byte to be read. Incremented + accordingly after a read operation to reflect + up to date status + + @retval EFI_SUCCESS Next element found and read into Data + @retval EFI_INVALID_PARAMETER Operation failed + @retval EFI_END_OF_FILE End of the file reached, no more elements + to read. +**/ +EFI_STATUS +QemuFwCfgReadNextHardwareInfoByType ( + IN HARDWARE_INFO_TYPE Type, + IN UINTN TypeSize, + IN UINTN TotalFileSize, + OUT VOID *Data, + OUT UINTN *DataSize OPTIONAL, + IN OUT UINTN *ReadIndex + ); + +/** + Parse binary data containing resource information of multiple hardware + elements into a list of interpreted resources. + The translation is done on a copy-parse base so the blob can be freed + afterwards. + + @param[in] Blob Binary data to be parsed + @param[in] BlobSize Size (in bytes) of the binary data + @param[in] TypeFilter Optional type to filter entries. Set to + undefined to disable filtering and retrieve all + @param[out] ListHead Head of the list to populate hardware information + + @retval EFI_SUCCESS Succeed. + @retval EFI_INVALID_PARAMETER Provided Blob inforation is invalid + @retval EFI_OUT_OF_RESOURCES Out of memory, list populated as far as + possible +**/ +EFI_STATUS +CreateHardwareInfoList ( + IN UINT8 *Blob, + IN UINTN BlobSize, + IN HARDWARE_INFO_TYPE TypeFilter, + OUT LIST_ENTRY *ListHead + ); + +/** + Free the dynamically allocated list of HADWARE_INFO items populated + during parsing of Blob + + @param ListHead Head of the list to be destroyed +**/ +VOID +FreeHardwareInfoList ( + IN OUT LIST_ENTRY *ListHead + ); + +/** + Retrieve the number of hardware components of a specific type + in the list. + + @param[in] ListHead Head of the hardware info list + @param[in] Type Type of hardware elements to count + @param[in] TypeSize Size (in bytes) of the structure intended to + be used to dereference the data + @return Count of elements of Type found +**/ +UINTN +GetHardwareInfoCountByType ( + IN LIST_ENTRY *ListHead, + IN HARDWARE_INFO_TYPE Type, + IN UINTN TypeSize + ); + +/** + Get the First Hardware Info entry in the list of the specified type + + @param[in] ListHead Head of the hardware info list + @param[in] Type Hardware Info Type to search for + @param[in] TypeSize Size (in bytes) of the structure intended to + be used to dereference the data + @return Link of first entry of specified type or list head if not found +**/ +LIST_ENTRY * +GetFirstHardwareInfoByType ( + IN LIST_ENTRY *ListHead, + IN HARDWARE_INFO_TYPE Type, + IN UINTN TypeSize + ); + +/** + Get the Next Hardware Info entry in the list with the specified + type, which follows the provided Node. + + @param[in] ListHead Head of the hardware info list + @param[in] Node Current, already processed, node's link + @param[in] Type Hardware Info Type to search for + @param[in] TypeSize Size (in bytes) of the structure intended to + be used to dereference the data + @return Link of next entry, after Node, of the specified type. + List head otherwise +**/ +LIST_ENTRY * +GetNextHardwareInfoByType ( + IN LIST_ENTRY *ListHead, + IN LIST_ENTRY *Node, + IN HARDWARE_INFO_TYPE Type, + IN UINTN TypeSize + ); + +/** + Assess if Node stands at the end of the doubly linked list + + @param[in] ListHead Head of the hardware info list + @param[in] Node Current Node link + + @retval TRUE Node is at the end of the list + @retval FALSE Node is not at the end of the list +**/ +BOOLEAN +EndOfHardwareInfoList ( + IN LIST_ENTRY *ListHead, + IN LIST_ENTRY *Node + ); + +#endif // __HARDWARE_INFO_LIB_H__ diff --git a/OvmfPkg/Library/HardwareInfoLib/HardwareInfoPei.c b/OvmfPkg/Library/HardwareInfoLib/HardwareInfoPei.c new file mode 100644 index 0000000000..beb10ba896 --- /dev/null +++ b/OvmfPkg/Library/HardwareInfoLib/HardwareInfoPei.c @@ -0,0 +1,79 @@ +/*/@file + Hardware info parsing functions. + Binary data is expected as a consecutive series of header - object pairs. + Provides static Qemu fw-cfg wrappers as well as list-like interface to + dynamically manipulate hardware info objects and parsing from a generic + blob. + + Copyright 2021 - 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include + +EFI_STATUS +CreateHardwareInfoList ( + IN UINT8 *Blob, + IN UINTN BlobSize, + IN HARDWARE_INFO_TYPE TypeFilter, + OUT LIST_ENTRY *ListHead + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +VOID +FreeHardwareInfoList ( + IN OUT LIST_ENTRY *ListHead + ) +{ + ASSERT (FALSE); +} + +UINTN +GetHardwareInfoCountByType ( + IN LIST_ENTRY *ListHead, + IN HARDWARE_INFO_TYPE Type, + IN UINTN TypeSize + ) +{ + ASSERT (FALSE); + return 0; +} + +LIST_ENTRY * +GetFirstHardwareInfoByType ( + IN LIST_ENTRY *ListHead, + IN HARDWARE_INFO_TYPE Type, + IN UINTN TypeSize + ) +{ + ASSERT (FALSE); + return ListHead; +} + +LIST_ENTRY * +GetNextHardwareInfoByType ( + IN LIST_ENTRY *ListHead, + IN LIST_ENTRY *Node, + IN HARDWARE_INFO_TYPE Type, + IN UINTN TypeSize + ) +{ + ASSERT (FALSE); + return ListHead; +} + +BOOLEAN +EndOfHardwareInfoList ( + IN LIST_ENTRY *ListHead, + IN LIST_ENTRY *Node + ) +{ + ASSERT (FALSE); + return TRUE; +} diff --git a/OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf b/OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf new file mode 100644 index 0000000000..00b79bc8d6 --- /dev/null +++ b/OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf @@ -0,0 +1,39 @@ +## @file +# Hardware information library wrappers over Qemu fw-cfg functionality to parse, +# in a static manner, non-discoverable hardware information. +# +# Copyright 2021 - 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PeiHardwareInfoLib + FILE_GUID = 3D5011B3-9CBB-4C0B-88E8-1D758283C659 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PeiHardwareInfoLib + +# +# The following information is for reference only and not required by the build +# tools. +# +# VALID_ARCHITECTURES = X64 +# + +[Sources] + HardwareInfoPei.c + QemuFwCfgHardwareInfoLib.c + HardwareInfoPciHostBridgeLib.c + +[Packages] + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec + +[LibraryClasses] + DebugLib + QemuFwCfgLib diff --git a/OvmfPkg/Library/HardwareInfoLib/QemuFwCfgHardwareInfoLib.c b/OvmfPkg/Library/HardwareInfoLib/QemuFwCfgHardwareInfoLib.c new file mode 100644 index 0000000000..48d9dcd8ad --- /dev/null +++ b/OvmfPkg/Library/HardwareInfoLib/QemuFwCfgHardwareInfoLib.c @@ -0,0 +1,88 @@ +/*/@file + Qemu fw-cfg wrappers for hardware info parsing. + Provides an alternative to parse hardware information from a fw-cfg + file without relying on dynamic memory allocations. + + Copyright 2021 - 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +#include + +/** + Update an optional pointer value if possible + + @param[out] DataSize Pointer to variable to be updated + @param[in] Value Value to set the pointed variable to. +**/ +STATIC +VOID +UpdateDataSize ( + OUT UINTN *DataSize, + IN UINTN Value + ) +{ + if (DataSize == NULL) { + return; + } + + *DataSize = Value; +} + +EFI_STATUS +QemuFwCfgReadNextHardwareInfoByType ( + IN HARDWARE_INFO_TYPE Type, + IN UINTN TypeSize, + IN UINTN TotalFileSize, + OUT VOID *Data, + OUT UINTN *DataSize OPTIONAL, + IN OUT UINTN *ReadIndex + ) +{ + HARDWARE_INFO_HEADER Header; + + if ((Data == NULL) || + (ReadIndex == NULL) || + (TypeSize == 0) || + (Type == HardwareInfoTypeUndefined) || + (TotalFileSize == 0)) + { + return EFI_INVALID_PARAMETER; + } + + UpdateDataSize (DataSize, 0); + + while (*ReadIndex < TotalFileSize) { + QemuFwCfgReadBytes (sizeof (Header), &Header); + *ReadIndex += sizeof (Header); + + if ((Header.Size > MAX_UINTN) || (((UINT64)*ReadIndex + Header.Size) > TotalFileSize)) { + *ReadIndex = TotalFileSize; + return EFI_ABORTED; + } + + if ((Header.Type.Value == Type) && (Header.Size <= TypeSize)) { + QemuFwCfgReadBytes ((UINTN)Header.Size, Data); + + *ReadIndex += (UINTN)Header.Size; + UpdateDataSize (DataSize, (UINTN)Header.Size); + + return EFI_SUCCESS; + } + + // + // Skip the bytes corresponding to the next element as it is + // not of the expected type and/or size. The TotalFileSize + // and individual elements sizes should match so the size + // check is skipped. + // + QemuFwCfgSkipBytes ((UINTN)Header.Size); + *ReadIndex += (UINTN)Header.Size; + } + + return EFI_END_OF_FILE; +} diff --git a/OvmfPkg/Microvm/MicrovmX64.dsc b/OvmfPkg/Microvm/MicrovmX64.dsc index 5b150a959c..38dd708477 100644 --- a/OvmfPkg/Microvm/MicrovmX64.dsc +++ b/OvmfPkg/Microvm/MicrovmX64.dsc @@ -183,6 +183,7 @@ CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf + PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf !if $(SOURCE_DEBUG_ENABLE) == TRUE PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index 7b114a5e63..5af76a5405 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -125,6 +125,10 @@ # PeilessStartupLib|Include/Library/PeilessStartupLib.h + ## @libraryclass HardwareInfoLib + # + HardwareInfoLib|Include/Library/HardwareInfoLib.h + [Guids] gUefiOvmfPkgTokenSpaceGuid = {0x93bb96af, 0xb9f2, 0x4eb8, {0x94, 0x62, 0xe0, 0xba, 0x74, 0x56, 0x42, 0x36}} gEfiXenInfoGuid = {0xd3b46f3b, 0xd441, 0x1244, {0x9a, 0x12, 0x0, 0x12, 0x27, 0x3f, 0xc1, 0x4d}} diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc index c94b29205f..a3c8b358e5 100644 --- a/OvmfPkg/OvmfPkgIa32.dsc +++ b/OvmfPkg/OvmfPkgIa32.dsc @@ -178,6 +178,7 @@ LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLibNull.inf + PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf !if $(SMM_REQUIRE) == FALSE LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf !endif diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc index dc37c73074..f2ce2cfae2 100644 --- a/OvmfPkg/OvmfPkgIa32X64.dsc +++ b/OvmfPkg/OvmfPkgIa32X64.dsc @@ -182,6 +182,7 @@ LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLibNull.inf + PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf !if $(SMM_REQUIRE) == FALSE LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf !endif diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index c742fd9aa6..fa6b93563c 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -194,6 +194,7 @@ LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf + PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf !if $(SMM_REQUIRE) == FALSE LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf diff --git a/OvmfPkg/OvmfXen.dsc b/OvmfPkg/OvmfXen.dsc index 6ba4bd729a..03922b5c16 100644 --- a/OvmfPkg/OvmfXen.dsc +++ b/OvmfPkg/OvmfXen.dsc @@ -172,6 +172,7 @@ CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf + PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf !if $(SOURCE_DEBUG_ENABLE) == TRUE PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf