diff options
12 files changed, 1757 insertions, 30 deletions
diff --git a/ArmPkg/Drivers/ArmScmiDxe/ScmiClockProtocol.c b/ArmPkg/Drivers/ArmScmiDxe/ScmiClockProtocol.c index 1b11d72a24..7cb4734bab 100644 --- a/ArmPkg/Drivers/ArmScmiDxe/ScmiClockProtocol.c +++ b/ArmPkg/Drivers/ArmScmiDxe/ScmiClockProtocol.c @@ -186,8 +186,7 @@ ClockDescribeRates ( UINT32 PayloadLength;
SCMI_COMMAND Cmd;
- UINT32 *MessageParams1;
- UINT32 *MessageParams2;
+ UINT32 *MessageParams;
CLOCK_DESCRIBE_RATES *DescribeRates;
CLOCK_RATE_DWORD *Rate;
@@ -200,7 +199,7 @@ ClockDescribeRates ( RequiredArraySize = 0;
RateIndex = 0;
- Status = ScmiCommandGetPayload (&MessageParams1);
+ Status = ScmiCommandGetPayload (&MessageParams);
if (EFI_ERROR (Status)) {
return Status;
}
@@ -208,11 +207,9 @@ ClockDescribeRates ( Cmd.ProtocolId = ScmiProtocolIdClock;
Cmd.MessageId = ScmiMessageIdClockDescribeRates;
- MessageParams2 = MessageParams1 + 1;
-
do {
- *MessageParams1 = ClockId;
- *MessageParams2 = RateIndex;
+ MessageParams[0] = ClockId;
+ MessageParams[1] = RateIndex;
// Set Payload length, note PayloadLength is a IN/OUT parameter.
PayloadLength = sizeof (ClockId) + sizeof (RateIndex);
diff --git a/DynamicTablesPkg/DynamicTablesPkg.ci.yaml b/DynamicTablesPkg/DynamicTablesPkg.ci.yaml index cc9771aec5..411784ec7a 100644 --- a/DynamicTablesPkg/DynamicTablesPkg.ci.yaml +++ b/DynamicTablesPkg/DynamicTablesPkg.ci.yaml @@ -38,7 +38,7 @@ ## options defined .pytool/Plugin/HostUnitTestCompilerPlugin
"HostUnitTestCompilerPlugin": {
- "DscPath": "" # Don't support this test
+ "DscPath": "Test/DynamicTablesPkgHostTest.dsc"
},
## options defined .pytool/Plugin/CharEncodingCheck
diff --git a/DynamicTablesPkg/DynamicTablesPkg.dec b/DynamicTablesPkg/DynamicTablesPkg.dec index 2b3ad16319..68624f20e7 100644 --- a/DynamicTablesPkg/DynamicTablesPkg.dec +++ b/DynamicTablesPkg/DynamicTablesPkg.dec @@ -15,6 +15,7 @@ [Includes]
Include
+ Test/Mock/Include
[LibraryClasses]
## @libraryclass Defines a set of Acpi helper methods
diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiDbg2Lib/GoogleTest/Dbg2GeneratorGoogleTest.cpp b/DynamicTablesPkg/Library/Acpi/Common/AcpiDbg2Lib/GoogleTest/Dbg2GeneratorGoogleTest.cpp new file mode 100644 index 0000000000..1d7b9c2cd0 --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiDbg2Lib/GoogleTest/Dbg2GeneratorGoogleTest.cpp @@ -0,0 +1,1454 @@ +/** @file
+ Unit tests for DBG2 Generator
+
+ Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved. <BR>
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+#include <Library/GoogleTestLib.h>
+
+extern "C" {
+ #include <Uefi.h>
+ #include <Protocol/ConfigurationManagerProtocol.h>
+ #include <Library/FunctionMockLib.h>
+ #include <Library/BaseMemoryLib.h>
+ #include <Library/DebugLib.h>
+ #include <Library/MemoryAllocationLib.h>
+ #include <Library/TableHelperLib.h>
+ #include <Library/SsdtSerialPortFixupLib.h>
+ #include <AcpiTableGenerator.h>
+ #include <ConfigurationManagerObject.h>
+ #include <ConfigurationManagerHelper.h>
+ #include <StandardNameSpaceObjects.h>
+ #include <IndustryStandard/DebugPort2Table.h>
+ #include <Protocol/SerialIo.h>
+ #include "GoogleTest/Protocol/MockConfigurationManagerProtocol.h"
+ #include "../Dbg2Generator.h"
+
+ #define SERIAL_PORT_BASE_ADDRESS(i) (0x1000ULL * (i + 1))
+ #define SERIAL_PORT_BASE_ADDRESS_LENGTH (0x1000ULL)
+ #define SERIAL_PORT_BAUD_RATE (115200)
+
+ #define DBG2_BASE_ADDRESS(i) (0x1000ULL * (i + 1))
+ #define DBG2_BASE_ADDRESS_LENGTH (0x1000ULL)
+
+ EFI_STATUS
+ EFIAPI
+ AcpiDbg2LibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+ EFI_STATUS
+ EFIAPI
+ AcpiDbg2LibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+ // Global generator instance
+ static ACPI_TABLE_GENERATOR *gDbg2Generator = NULL;
+
+ // C++ wrapper functions for C linkage functions
+ EFI_STATUS
+ RegisterAcpiTableGenerator (
+ IN CONST ACPI_TABLE_GENERATOR *CONST TableGenerator
+ )
+ {
+ if (TableGenerator == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Store the generator for use in tests
+ gDbg2Generator = const_cast<ACPI_TABLE_GENERATOR *>(TableGenerator);
+ return EFI_SUCCESS;
+ }
+
+ EFI_STATUS
+ DeregisterAcpiTableGenerator (
+ IN CONST ACPI_TABLE_GENERATOR *CONST TableGenerator
+ )
+ {
+ if (TableGenerator == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Clear the stored generator
+ gDbg2Generator = NULL;
+ return EFI_SUCCESS;
+ }
+}
+
+using namespace testing;
+using ::testing::_;
+using ::testing::NiceMock;
+using ::testing::Return;
+using ::testing::DoAll;
+using ::testing::SetArgPointee;
+using ::testing::AtLeast;
+
+// Add base class before the test classes
+class Dbg2GeneratorTestBase {
+protected:
+ void
+ ValidateDbg2TableHeader (
+ IN EFI_ACPI_DEBUG_PORT_2_DESCRIPTION_TABLE *Dbg2Table
+ )
+ {
+ EXPECT_NE (Dbg2Table, nullptr);
+ EXPECT_EQ (Dbg2Table->Header.Signature, (UINT32)EFI_ACPI_6_3_DEBUG_PORT_2_TABLE_SIGNATURE);
+ EXPECT_EQ (Dbg2Table->Header.Revision, EFI_ACPI_DEBUG_PORT_2_TABLE_REVISION);
+ EXPECT_EQ (Dbg2Table->Header.OemId[0], (UINT8)'T');
+ EXPECT_EQ (Dbg2Table->Header.OemId[1], (UINT8)'E');
+ EXPECT_EQ (Dbg2Table->Header.OemId[2], (UINT8)'S');
+ EXPECT_EQ (Dbg2Table->Header.OemId[3], (UINT8)'T');
+ EXPECT_EQ (Dbg2Table->Header.OemId[4], (UINT8)'I');
+ EXPECT_EQ (Dbg2Table->Header.OemId[5], (UINT8)'D');
+ }
+
+ void
+ ValidateSerialDeviceInfo (
+ IN EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT *DeviceInfo,
+ IN UINT64 ExpectedBaseAddress,
+ IN UINT32 ExpectedAddressSize
+ )
+ {
+ EXPECT_EQ (DeviceInfo->Revision, EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION);
+ EXPECT_EQ (DeviceInfo->PortType, EFI_ACPI_DBG2_PORT_TYPE_SERIAL);
+ EXPECT_EQ (DeviceInfo->PortSubtype, EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_FULL_16550);
+ EXPECT_EQ (DeviceInfo->NumberofGenericAddressRegisters, 1U);
+
+ // Validate base address register
+ EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE *Gas = (EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE *)((UINT8 *)DeviceInfo + DeviceInfo->BaseAddressRegisterOffset);
+
+ EXPECT_EQ (Gas->AddressSpaceId, (UINT8)EFI_ACPI_6_3_SYSTEM_MEMORY);
+ EXPECT_EQ (Gas->RegisterBitWidth, 32U);
+ EXPECT_EQ (Gas->RegisterBitOffset, 0U);
+ EXPECT_EQ (Gas->AccessSize, (UINT8)EFI_ACPI_6_3_DWORD);
+ EXPECT_EQ (Gas->Address, ExpectedBaseAddress);
+
+ // Validate address size
+ UINT32 *AddressSize = (UINT32 *)((UINT8 *)DeviceInfo + DeviceInfo->AddressSizeOffset);
+
+ EXPECT_EQ (*AddressSize, ExpectedAddressSize);
+ }
+
+ void
+ ValidateNonSerialDeviceInfo (
+ IN EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT *DeviceInfo,
+ IN const std::vector<CM_ARCH_COMMON_MEMORY_RANGE_DESCRIPTOR> &MemoryRanges
+ )
+ {
+ EXPECT_EQ (DeviceInfo->Revision, (UINT8)EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION);
+ // Cast both sides to UINT16 to ensure proper comparison
+ EXPECT_EQ ((UINT16)DeviceInfo->PortType, (UINT16)EFI_ACPI_DBG2_PORT_TYPE_NET);
+ EXPECT_EQ (DeviceInfo->PortSubtype, (UINT16)0x0000);
+ EXPECT_EQ ((UINT32)DeviceInfo->NumberofGenericAddressRegisters, (UINT32)MemoryRanges.size ());
+
+ // Validate base address registers
+ EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE *Gas = (EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE *)((UINT8 *)DeviceInfo + DeviceInfo->BaseAddressRegisterOffset);
+
+ // Validate each memory range
+ for (size_t j = 0; j < MemoryRanges.size (); j++) {
+ EXPECT_EQ (Gas->AddressSpaceId, (UINT8)EFI_ACPI_6_3_SYSTEM_MEMORY);
+ EXPECT_EQ (Gas->RegisterBitWidth, (UINT8)32);
+ EXPECT_EQ (Gas->RegisterBitOffset, (UINT8)0);
+ EXPECT_EQ (Gas->AccessSize, (UINT8)EFI_ACPI_6_3_DWORD);
+ EXPECT_EQ (Gas->Address, MemoryRanges[j].BaseAddress);
+
+ // Move to next GAS structure
+ Gas = (EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE *)((UINT8 *)Gas + sizeof (EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE));
+ }
+
+ // Validate address sizes
+ UINT32 *AddressSize = (UINT32 *)((UINT8 *)DeviceInfo + DeviceInfo->AddressSizeOffset);
+
+ for (size_t j = 0; j < MemoryRanges.size (); j++) {
+ EXPECT_EQ (AddressSize[j], MemoryRanges[j].Length);
+ }
+ }
+
+ void
+ ValidateSsdtTableHeader (
+ IN EFI_ACPI_DESCRIPTION_HEADER *SsdtTable
+ )
+ {
+ EXPECT_NE (SsdtTable, nullptr);
+ EXPECT_EQ (SsdtTable->Signature, (UINT32)EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE);
+ EXPECT_EQ (SsdtTable->Revision, EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_REVISION);
+ EXPECT_EQ (SsdtTable->OemId[0], (UINT8)'A');
+ EXPECT_EQ (SsdtTable->OemId[1], (UINT8)'R');
+ EXPECT_EQ (SsdtTable->OemId[2], (UINT8)'M');
+ EXPECT_EQ (SsdtTable->OemId[3], (UINT8)'L');
+ EXPECT_EQ (SsdtTable->OemId[4], (UINT8)'T');
+ EXPECT_EQ (SsdtTable->OemId[5], (UINT8)'D');
+ }
+};
+
+// Update test class declarations to inherit from base class
+class Dbg2GeneratorTest : public ::testing::Test, public Dbg2GeneratorTestBase {
+protected:
+ MockConfigurationManagerProtocol MockConfigMgrProtocol;
+ CM_STD_OBJ_CONFIGURATION_MANAGER_INFO CfgMgrInfo = { 0 };
+
+ void
+ SetUp (
+ ) override
+ {
+ // Set up default behavior for GetObject
+ ON_CALL (MockConfigMgrProtocol, GetObject (_, _, _, _))
+ .WillByDefault (Return (EFI_NOT_FOUND));
+
+ // Set up configuration manager info
+
+ CfgMgrInfo.Revision = CREATE_REVISION (1, 0);
+ CfgMgrInfo.OemId[0] = 'T';
+ CfgMgrInfo.OemId[1] = 'E';
+ CfgMgrInfo.OemId[2] = 'S';
+ CfgMgrInfo.OemId[3] = 'T';
+ CfgMgrInfo.OemId[4] = 'I';
+ CfgMgrInfo.OemId[5] = 'D';
+
+ EXPECT_CALL (MockConfigMgrProtocol, GetObject (_, CREATE_CM_STD_OBJECT_ID (EStdObjCfgMgrInfo), CM_NULL_TOKEN, _))
+ .WillRepeatedly (
+ DoAll (
+ SetArgPointee<3>(
+ CM_OBJ_DESCRIPTOR {
+ CREATE_CM_STD_OBJECT_ID (EStdObjCfgMgrInfo),
+ sizeof (CM_STD_OBJ_CONFIGURATION_MANAGER_INFO),
+ &CfgMgrInfo,
+ 1
+ }
+ ),
+ Return (EFI_SUCCESS)
+ )
+ );
+
+ // Initialize the DBG2 library with our mock protocol
+ EXPECT_EQ (AcpiDbg2LibConstructor (NULL, NULL), EFI_SUCCESS);
+
+ // Setup common test data with proper initialization
+ mAcpiTableInfo.TableGeneratorId = CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdDbg2);
+ mAcpiTableInfo.AcpiTableSignature = EFI_ACPI_6_3_DEBUG_PORT_2_TABLE_SIGNATURE;
+ mAcpiTableInfo.AcpiTableRevision = EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION;
+ }
+
+ void
+ TearDown (
+ ) override
+ {
+ // Clean up the DBG2 library
+ AcpiDbg2LibDestructor (NULL, NULL);
+ }
+
+ void
+ SetupSerialPortInfo (
+ UINT32 Count
+ )
+ {
+ mSerialPortInfo.resize (Count);
+ for (UINT32 i = 0; i < Count; i++) {
+ CM_ARCH_COMMON_SERIAL_PORT_INFO info = { 0 };
+ info.BaseAddress = SERIAL_PORT_BASE_ADDRESS (i);
+ info.BaseAddressLength = SERIAL_PORT_BASE_ADDRESS_LENGTH;
+ info.AccessSize = EFI_ACPI_6_3_DWORD;
+ info.BaudRate = SERIAL_PORT_BAUD_RATE;
+ info.PortSubtype = EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_FULL_16550;
+ mSerialPortInfo[i] = info;
+ }
+
+ EXPECT_CALL (MockConfigMgrProtocol, GetObject (_, CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjSerialDebugPortInfo), CM_NULL_TOKEN, _))
+ .WillOnce (
+ DoAll (
+ SetArgPointee<3>(
+ CM_OBJ_DESCRIPTOR {
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjSerialDebugPortInfo),
+ (UINT32)sizeof (CM_ARCH_COMMON_SERIAL_PORT_INFO) * Count,
+ &mSerialPortInfo[0],
+ Count
+ }
+ ),
+ Return (EFI_SUCCESS)
+ )
+ );
+
+ // Set up expectation for DBG2 device info
+ EXPECT_CALL (MockConfigMgrProtocol, GetObject (_, CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjGenericDbg2DeviceInfo), CM_NULL_TOKEN, _))
+ .WillOnce (Return (EFI_NOT_FOUND));
+ }
+
+ void
+ SetupNonSerialDbg2DeviceInfo (
+ VOID
+ )
+ {
+ // Set up memory range descriptors
+ mMemoryRangeDescriptors.clear ();
+ for (UINT32 i = 0; i < 2; i++) {
+ CM_ARCH_COMMON_MEMORY_RANGE_DESCRIPTOR desc = { 0 };
+ desc.BaseAddress = DBG2_BASE_ADDRESS (i);
+ desc.Length = DBG2_BASE_ADDRESS_LENGTH;
+ mMemoryRangeDescriptors.push_back (desc);
+ }
+
+ // Set up DBG2 device info
+ mDbg2DeviceInfo.clear ();
+ CM_ARCH_COMMON_DBG2_DEVICE_INFO info = { 0 };
+
+ info.AddressResourceToken = 1; // Unique token for each device
+ info.PortType = EFI_ACPI_DBG2_PORT_TYPE_NET;
+ info.PortSubtype = 0;
+ info.AccessSize = EFI_ACPI_6_3_DWORD;
+ CopyMem (info.ObjectName, "DBG2", sizeof ("DBG2"));
+ mDbg2DeviceInfo.push_back (info);
+
+ // Set up mock expectations
+ EXPECT_CALL (MockConfigMgrProtocol, GetObject (_, CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjGenericDbg2DeviceInfo), CM_NULL_TOKEN, _))
+ .WillOnce (
+ DoAll (
+ SetArgPointee<3>(
+ CM_OBJ_DESCRIPTOR {
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjGenericDbg2DeviceInfo),
+ sizeof (CM_ARCH_COMMON_DBG2_DEVICE_INFO),
+ &mDbg2DeviceInfo[0],
+ 1
+ }
+ ),
+ Return (EFI_SUCCESS)
+ )
+ );
+
+ // Set up mock expectations
+ EXPECT_CALL (
+ MockConfigMgrProtocol,
+ GetObject (
+ _,
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjMemoryRangeDescriptor),
+ 1,
+ _
+ )
+ ).WillOnce (
+ DoAll (
+ SetArgPointee<3> (
+ CM_OBJ_DESCRIPTOR {
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjMemoryRangeDescriptor),
+ sizeof (CM_ARCH_COMMON_MEMORY_RANGE_DESCRIPTOR) * 2,
+ &mMemoryRangeDescriptors[0],
+ 2
+ }
+ ),
+ Return (EFI_SUCCESS)
+ )
+ );
+ }
+
+ CM_STD_OBJ_ACPI_TABLE_INFO mAcpiTableInfo;
+ std::vector<CM_ARCH_COMMON_SERIAL_PORT_INFO> mSerialPortInfo;
+ std::vector<CM_ARCH_COMMON_DBG2_DEVICE_INFO> mDbg2DeviceInfo;
+ std::vector<CM_ARCH_COMMON_MEMORY_RANGE_DESCRIPTOR> mMemoryRangeDescriptors;
+};
+
+TEST_F (Dbg2GeneratorTest, BuildDbg2TableEx_SingleSerialPort) {
+ SetupSerialPortInfo (1U);
+
+ EFI_ACPI_DESCRIPTION_HEADER **Table = nullptr;
+ UINTN TableCount = 0;
+
+ EXPECT_EQ (
+ gDbg2Generator->BuildAcpiTableEx (
+ gDbg2Generator,
+ &mAcpiTableInfo,
+ gConfigurationManagerProtocol,
+ &Table,
+ &TableCount
+ ),
+ EFI_SUCCESS
+ );
+
+ EXPECT_NE (Table, nullptr);
+ EXPECT_EQ (TableCount, 2U);
+
+ // Find the DBG2 table
+ EFI_ACPI_DEBUG_PORT_2_DESCRIPTION_TABLE *Dbg2Table = nullptr;
+ EFI_ACPI_DESCRIPTION_HEADER *SsdtTable = nullptr;
+
+ for (UINTN i = 0; i < TableCount; i++) {
+ if (Table[i]->Signature == EFI_ACPI_6_3_DEBUG_PORT_2_TABLE_SIGNATURE) {
+ Dbg2Table = (EFI_ACPI_DEBUG_PORT_2_DESCRIPTION_TABLE *)Table[i];
+ } else if (Table[i]->Signature == EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
+ SsdtTable = Table[i];
+ }
+ }
+
+ ValidateDbg2TableHeader (Dbg2Table);
+ ValidateSsdtTableHeader (SsdtTable);
+
+ // Validate DBG2 table structure
+ EXPECT_EQ (Dbg2Table->NumberDbgDeviceInfo, 1U);
+ EXPECT_NE (Dbg2Table->OffsetDbgDeviceInfo, 0U);
+
+ // Get pointer to device information structure
+ EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT *DeviceInfo = (EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT *)((UINT8 *)Dbg2Table + Dbg2Table->OffsetDbgDeviceInfo);
+
+ ValidateSerialDeviceInfo (DeviceInfo, SERIAL_PORT_BASE_ADDRESS (0), SERIAL_PORT_BASE_ADDRESS_LENGTH);
+
+ gDbg2Generator->FreeTableResourcesEx (
+ gDbg2Generator,
+ &mAcpiTableInfo,
+ gConfigurationManagerProtocol,
+ &Table,
+ TableCount
+ );
+}
+
+TEST_F (Dbg2GeneratorTest, BuildDbg2TableEx_NoDevices) {
+ // Setup expectation for no devices
+ EXPECT_CALL (MockConfigMgrProtocol, GetObject (_, CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjSerialDebugPortInfo), CM_NULL_TOKEN, _))
+ .WillOnce (Return (EFI_NOT_FOUND));
+
+ EXPECT_CALL (MockConfigMgrProtocol, GetObject (_, CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjGenericDbg2DeviceInfo), CM_NULL_TOKEN, _))
+ .WillOnce (Return (EFI_NOT_FOUND));
+
+ EFI_ACPI_DESCRIPTION_HEADER **Table = nullptr;
+ UINTN TableCount = 0;
+
+ EXPECT_EQ (
+ gDbg2Generator->BuildAcpiTableEx (
+ gDbg2Generator,
+ &mAcpiTableInfo,
+ gConfigurationManagerProtocol,
+ &Table,
+ &TableCount
+ ),
+ EFI_NOT_FOUND
+ );
+
+ EXPECT_EQ (Table, nullptr);
+ EXPECT_EQ (TableCount, 0U);
+}
+
+TEST_F (Dbg2GeneratorTest, BuildDbg2TableEx_NonSerialDbg2Device) {
+ EXPECT_CALL (MockConfigMgrProtocol, GetObject (_, CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjSerialDebugPortInfo), CM_NULL_TOKEN, _))
+ .WillOnce (Return (EFI_NOT_FOUND));
+
+ SetupNonSerialDbg2DeviceInfo ();
+
+ EFI_ACPI_DESCRIPTION_HEADER **Table = nullptr;
+ UINTN TableCount = 0;
+
+ EXPECT_EQ (
+ gDbg2Generator->BuildAcpiTableEx (
+ gDbg2Generator,
+ &mAcpiTableInfo,
+ gConfigurationManagerProtocol,
+ &Table,
+ &TableCount
+ ),
+ EFI_SUCCESS
+ );
+
+ EXPECT_NE (Table, nullptr);
+ EXPECT_EQ (TableCount, 1U);
+
+ // Find the DBG2 table
+ EFI_ACPI_DEBUG_PORT_2_DESCRIPTION_TABLE *Dbg2Table = nullptr;
+
+ for (UINTN i = 0; i < TableCount; i++) {
+ if (Table[i]->Signature == EFI_ACPI_6_3_DEBUG_PORT_2_TABLE_SIGNATURE) {
+ Dbg2Table = (EFI_ACPI_DEBUG_PORT_2_DESCRIPTION_TABLE *)Table[i];
+ break;
+ }
+ }
+
+ ValidateDbg2TableHeader (Dbg2Table);
+
+ // Validate DBG2 table structure
+ EXPECT_EQ (Dbg2Table->NumberDbgDeviceInfo, 1U);
+ EXPECT_NE (Dbg2Table->OffsetDbgDeviceInfo, 0U);
+
+ // Get pointer to device information structure
+ EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT *DeviceInfo = (EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT *)((UINT8 *)Dbg2Table + Dbg2Table->OffsetDbgDeviceInfo);
+
+ ValidateNonSerialDeviceInfo (DeviceInfo, mMemoryRangeDescriptors);
+
+ gDbg2Generator->FreeTableResourcesEx (
+ gDbg2Generator,
+ &mAcpiTableInfo,
+ gConfigurationManagerProtocol,
+ &Table,
+ TableCount
+ );
+}
+
+// Replace tuple-based test structure with a simpler struct
+struct DeviceTestConfig {
+ UINT32 DeviceCount;
+ UINT32 RangesPerDevice;
+ BOOLEAN HasSerialPort; // Changed from SerialPortCount to HasSerialPort since only one port is supported
+};
+
+// Update test class declarations to inherit from base class
+class Dbg2GeneratorParameterizedTest : public ::testing::TestWithParam<DeviceTestConfig>, public Dbg2GeneratorTestBase {
+protected:
+ MockConfigurationManagerProtocol MockConfigMgrProtocol;
+ CM_STD_OBJ_CONFIGURATION_MANAGER_INFO CfgMgrInfo = { 0 };
+ CM_STD_OBJ_ACPI_TABLE_INFO mAcpiTableInfo;
+ std::vector<CM_ARCH_COMMON_DBG2_DEVICE_INFO> mDevices;
+ std::vector<CM_ARCH_COMMON_MEMORY_RANGE_DESCRIPTOR> mMemoryRanges;
+ std::vector<std::vector<CM_ARCH_COMMON_MEMORY_RANGE_DESCRIPTOR> > mDeviceSpecificRanges;
+ std::vector<CM_ARCH_COMMON_SERIAL_PORT_INFO> mSerialPortInfo;
+
+ void
+ SetUp (
+ ) override
+ {
+ // Set up default behavior for GetObject
+ ON_CALL (MockConfigMgrProtocol, GetObject (_, _, _, _))
+ .WillByDefault (Return (EFI_NOT_FOUND));
+
+ // Set up configuration manager info
+ CfgMgrInfo.Revision = CREATE_REVISION (1, 0);
+ CfgMgrInfo.OemId[0] = 'T';
+ CfgMgrInfo.OemId[1] = 'E';
+ CfgMgrInfo.OemId[2] = 'S';
+ CfgMgrInfo.OemId[3] = 'T';
+ CfgMgrInfo.OemId[4] = 'I';
+ CfgMgrInfo.OemId[5] = 'D';
+
+ EXPECT_CALL (MockConfigMgrProtocol, GetObject (_, CREATE_CM_STD_OBJECT_ID (EStdObjCfgMgrInfo), CM_NULL_TOKEN, _))
+ .WillRepeatedly (
+ DoAll (
+ SetArgPointee<3>(
+ CM_OBJ_DESCRIPTOR {
+ CREATE_CM_STD_OBJECT_ID (EStdObjCfgMgrInfo),
+ sizeof (CM_STD_OBJ_CONFIGURATION_MANAGER_INFO),
+ &CfgMgrInfo,
+ 1
+ }
+ ),
+ Return (EFI_SUCCESS)
+ )
+ );
+
+ // Initialize the DBG2 library with our mock protocol
+ EXPECT_EQ (AcpiDbg2LibConstructor (NULL, NULL), EFI_SUCCESS);
+
+ // Setup common test data
+ mAcpiTableInfo.TableGeneratorId = CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdDbg2);
+ mAcpiTableInfo.AcpiTableSignature = EFI_ACPI_6_3_DEBUG_PORT_2_TABLE_SIGNATURE;
+ mAcpiTableInfo.AcpiTableRevision = EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION;
+
+ // Set up devices and memory ranges based on test parameters
+ mDevices.clear ();
+ mMemoryRanges.clear ();
+ mDeviceSpecificRanges.clear ();
+ mSerialPortInfo.clear ();
+
+ UINT32 totalRanges = 0;
+ const DeviceTestConfig &config = GetParam ();
+
+ // Set up serial port info if configured
+ if (config.HasSerialPort) {
+ mSerialPortInfo.resize (1); // Always create just one serial port
+ CM_ARCH_COMMON_SERIAL_PORT_INFO info = { 0 };
+ info.BaseAddress = SERIAL_PORT_BASE_ADDRESS (0);
+ info.BaseAddressLength = SERIAL_PORT_BASE_ADDRESS_LENGTH;
+ info.AccessSize = EFI_ACPI_6_3_DWORD;
+ info.BaudRate = SERIAL_PORT_BAUD_RATE;
+ info.PortSubtype = EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_FULL_16550;
+ mSerialPortInfo[0] = info;
+
+ EXPECT_CALL (MockConfigMgrProtocol, GetObject (_, CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjSerialDebugPortInfo), CM_NULL_TOKEN, _))
+ .WillOnce (
+ DoAll (
+ SetArgPointee<3>(
+ CM_OBJ_DESCRIPTOR {
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjSerialDebugPortInfo),
+ sizeof (CM_ARCH_COMMON_SERIAL_PORT_INFO),
+ &mSerialPortInfo[0],
+ 1
+ }
+ ),
+ Return (EFI_SUCCESS)
+ )
+ );
+ } else {
+ EXPECT_CALL (MockConfigMgrProtocol, GetObject (_, CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjSerialDebugPortInfo), CM_NULL_TOKEN, _))
+ .WillOnce (Return (EFI_NOT_FOUND));
+ }
+
+ // Create devices
+ for (UINT32 i = 0; i < config.DeviceCount; i++) {
+ CM_ARCH_COMMON_DBG2_DEVICE_INFO device = { 0 };
+ device.AddressResourceToken = mDevices.size () + 1;
+ device.PortType = EFI_ACPI_DBG2_PORT_TYPE_NET;
+ device.PortSubtype = 0;
+ device.AccessSize = EFI_ACPI_6_3_DWORD;
+ CopyMem (device.ObjectName, "DBG2", sizeof (device.ObjectName) - 1);
+ device.ObjectName[sizeof (device.ObjectName) - 1] = '\0';
+ mDevices.push_back (device);
+
+ // Create memory ranges for this device
+ std::vector<CM_ARCH_COMMON_MEMORY_RANGE_DESCRIPTOR> deviceRanges;
+ for (UINT32 j = 0; j < config.RangesPerDevice; j++) {
+ CM_ARCH_COMMON_MEMORY_RANGE_DESCRIPTOR range = { 0 };
+ range.BaseAddress = DBG2_BASE_ADDRESS (totalRanges + j);
+ range.Length = DBG2_BASE_ADDRESS_LENGTH;
+ deviceRanges.push_back (range);
+ mMemoryRanges.push_back (range);
+ }
+
+ mDeviceSpecificRanges.push_back (deviceRanges);
+ totalRanges += config.RangesPerDevice;
+ }
+
+ // Set up mock expectations for DBG2 device info
+ EXPECT_CALL (MockConfigMgrProtocol, GetObject (_, CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjGenericDbg2DeviceInfo), CM_NULL_TOKEN, _))
+ .WillOnce (
+ DoAll (
+ SetArgPointee<3>(
+ CM_OBJ_DESCRIPTOR {
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjGenericDbg2DeviceInfo),
+ (UINT32)(sizeof (CM_ARCH_COMMON_DBG2_DEVICE_INFO) * mDevices.size ()),
+ &mDevices[0],
+ (UINT32)mDevices.size ()
+ }
+ ),
+ Return (EFI_SUCCESS)
+ )
+ );
+
+ // Set up mock expectations for memory range descriptors
+ for (size_t i = 0; i < mDevices.size (); i++) {
+ EXPECT_CALL (
+ MockConfigMgrProtocol,
+ GetObject (
+ _,
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjMemoryRangeDescriptor),
+ mDevices[i].AddressResourceToken,
+ _
+ )
+ ).WillOnce (
+ DoAll (
+ SetArgPointee<3> (
+ CM_OBJ_DESCRIPTOR {
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjMemoryRangeDescriptor),
+ (UINT32)(sizeof (CM_ARCH_COMMON_MEMORY_RANGE_DESCRIPTOR) * mDeviceSpecificRanges[i].size ()),
+ &mDeviceSpecificRanges[i][0],
+ (UINT32)mDeviceSpecificRanges[i].size ()
+ }
+ ),
+ Return (EFI_SUCCESS)
+ )
+ );
+ }
+ }
+
+ void
+ TearDown (
+ ) override
+ {
+ // Clean up the DBG2 library
+ AcpiDbg2LibDestructor (NULL, NULL);
+ }
+};
+
+TEST_P (Dbg2GeneratorParameterizedTest, BuildDbg2TableEx_MultipleNonSerialDevices) {
+ EFI_ACPI_DESCRIPTION_HEADER **Table = nullptr;
+ UINTN TableCount = 0;
+
+ EXPECT_EQ (
+ gDbg2Generator->BuildAcpiTableEx (
+ gDbg2Generator,
+ &mAcpiTableInfo,
+ gConfigurationManagerProtocol,
+ &Table,
+ &TableCount
+ ),
+ EFI_SUCCESS
+ );
+
+ EXPECT_NE (Table, nullptr);
+ EXPECT_EQ (TableCount, GetParam ().HasSerialPort ? 2U : 1U);
+
+ // Find the DBG2 table
+ EFI_ACPI_DEBUG_PORT_2_DESCRIPTION_TABLE *Dbg2Table = nullptr;
+ EFI_ACPI_DESCRIPTION_HEADER *SsdtTable = nullptr;
+
+ for (UINTN i = 0; i < TableCount; i++) {
+ if (Table[i]->Signature == EFI_ACPI_6_3_DEBUG_PORT_2_TABLE_SIGNATURE) {
+ Dbg2Table = (EFI_ACPI_DEBUG_PORT_2_DESCRIPTION_TABLE *)Table[i];
+ } else if (Table[i]->Signature == EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
+ SsdtTable = Table[i];
+ }
+ }
+
+ ValidateDbg2TableHeader (Dbg2Table);
+
+ // Validate DBG2 table structure
+ UINT32 expectedDeviceCount = (UINT32)(mDevices.size () + (GetParam ().HasSerialPort ? 1 : 0));
+
+ EXPECT_EQ (Dbg2Table->NumberDbgDeviceInfo, expectedDeviceCount);
+ EXPECT_NE (Dbg2Table->OffsetDbgDeviceInfo, 0U);
+
+ // Get pointer to first device information structure
+ EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT *DeviceInfo = (EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT *)((UINT8 *)Dbg2Table + Dbg2Table->OffsetDbgDeviceInfo);
+
+ // Validate each device
+ for (size_t i = 0; i < mDevices.size (); i++) {
+ ValidateNonSerialDeviceInfo (DeviceInfo, mDeviceSpecificRanges[i]);
+ DeviceInfo = (EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT *)((UINT8 *)DeviceInfo + DeviceInfo->Length);
+ }
+
+ // Validate SSDT table if present
+ if (GetParam ().HasSerialPort) {
+ ValidateSsdtTableHeader (SsdtTable);
+ }
+
+ gDbg2Generator->FreeTableResourcesEx (
+ gDbg2Generator,
+ &mAcpiTableInfo,
+ gConfigurationManagerProtocol,
+ &Table,
+ TableCount
+ );
+}
+
+INSTANTIATE_TEST_SUITE_P (
+ Dbg2GeneratorTests,
+ Dbg2GeneratorParameterizedTest,
+ ::testing::Values (
+ DeviceTestConfig { 1, 2, false }, // 1 device, 2 ranges per device, no serial port
+ DeviceTestConfig { 2, 3, false }, // 2 devices, 3 ranges per device, no serial port
+ DeviceTestConfig { 2, 2, true } // 2 devices, 2 ranges per device, with serial port
+ )
+ );
+
+// Test class for adversarial test cases
+class Dbg2GeneratorAdversarialTest : public ::testing::Test, public Dbg2GeneratorTestBase {
+protected:
+ MockConfigurationManagerProtocol MockConfigMgrProtocol;
+ CM_STD_OBJ_CONFIGURATION_MANAGER_INFO CfgMgrInfo = { 0 };
+ CM_STD_OBJ_ACPI_TABLE_INFO mAcpiTableInfo;
+
+ void
+ SetUp (
+ ) override
+ {
+ // Set up default behavior for GetObject
+ ON_CALL (MockConfigMgrProtocol, GetObject (_, _, _, _))
+ .WillByDefault (Return (EFI_NOT_FOUND));
+
+ // Set up configuration manager info
+ CfgMgrInfo.Revision = CREATE_REVISION (1, 0);
+ CfgMgrInfo.OemId[0] = 'T';
+ CfgMgrInfo.OemId[1] = 'E';
+ CfgMgrInfo.OemId[2] = 'S';
+ CfgMgrInfo.OemId[3] = 'T';
+ CfgMgrInfo.OemId[4] = 'I';
+ CfgMgrInfo.OemId[5] = 'D';
+
+ EXPECT_CALL (MockConfigMgrProtocol, GetObject (_, CREATE_CM_STD_OBJECT_ID (EStdObjCfgMgrInfo), CM_NULL_TOKEN, _))
+ .WillRepeatedly (
+ DoAll (
+ SetArgPointee<3>(
+ CM_OBJ_DESCRIPTOR {
+ CREATE_CM_STD_OBJECT_ID (EStdObjCfgMgrInfo),
+ sizeof (CM_STD_OBJ_CONFIGURATION_MANAGER_INFO),
+ &CfgMgrInfo,
+ 1
+ }
+ ),
+ Return (EFI_SUCCESS)
+ )
+ );
+
+ // Initialize the DBG2 library with our mock protocol
+ EXPECT_EQ (AcpiDbg2LibConstructor (NULL, NULL), EFI_SUCCESS);
+
+ // Setup common test data
+ mAcpiTableInfo.TableGeneratorId = CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdDbg2);
+ mAcpiTableInfo.AcpiTableSignature = EFI_ACPI_6_3_DEBUG_PORT_2_TABLE_SIGNATURE;
+ mAcpiTableInfo.AcpiTableRevision = EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION;
+ }
+
+ void
+ TearDown (
+ ) override
+ {
+ // Clean up the DBG2 library
+ AcpiDbg2LibDestructor (NULL, NULL);
+ }
+};
+
+// Test invalid memory range base address (0)
+TEST_F (Dbg2GeneratorAdversarialTest, InvalidMemoryRangeBaseAddress) {
+ // Set up DBG2 device info
+ CM_ARCH_COMMON_DBG2_DEVICE_INFO device = { 0 };
+
+ device.AddressResourceToken = 1;
+ device.PortType = EFI_ACPI_DBG2_PORT_TYPE_NET;
+ device.PortSubtype = 0;
+ device.AccessSize = EFI_ACPI_6_3_DWORD;
+
+ // Set up memory range with invalid base address
+ CM_ARCH_COMMON_MEMORY_RANGE_DESCRIPTOR range = { 0 };
+
+ range.BaseAddress = 0; // Invalid - must be non-zero
+ range.Length = DBG2_BASE_ADDRESS_LENGTH;
+
+ // Mock serial port info query to return not found
+ EXPECT_CALL (
+ MockConfigMgrProtocol,
+ GetObject (
+ _,
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjSerialDebugPortInfo),
+ CM_NULL_TOKEN,
+ _
+ )
+ )
+ .WillOnce (Return (EFI_NOT_FOUND));
+
+ // Mock DBG2 device info query
+ EXPECT_CALL (
+ MockConfigMgrProtocol,
+ GetObject (
+ _,
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjGenericDbg2DeviceInfo),
+ CM_NULL_TOKEN,
+ _
+ )
+ )
+ .WillOnce (
+ DoAll (
+ SetArgPointee<3>(
+ CM_OBJ_DESCRIPTOR {
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjGenericDbg2DeviceInfo),
+ sizeof (CM_ARCH_COMMON_DBG2_DEVICE_INFO),
+ &device,
+ 1
+ }
+ ),
+ Return (EFI_SUCCESS)
+ )
+ );
+
+ // Mock memory range descriptor query
+ EXPECT_CALL (
+ MockConfigMgrProtocol,
+ GetObject (
+ _,
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjMemoryRangeDescriptor),
+ 1,
+ _
+ )
+ )
+ .WillOnce (
+ DoAll (
+ SetArgPointee<3>(
+ CM_OBJ_DESCRIPTOR {
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjMemoryRangeDescriptor),
+ sizeof (CM_ARCH_COMMON_MEMORY_RANGE_DESCRIPTOR),
+ &range,
+ 1
+ }
+ ),
+ Return (EFI_SUCCESS)
+ )
+ );
+
+ EFI_ACPI_DESCRIPTION_HEADER **Table = nullptr;
+ UINTN TableCount = 0;
+
+ EXPECT_EQ (
+ gDbg2Generator->BuildAcpiTableEx (
+ gDbg2Generator,
+ &mAcpiTableInfo,
+ gConfigurationManagerProtocol,
+ &Table,
+ &TableCount
+ ),
+ EFI_INVALID_PARAMETER
+ );
+}
+
+// Test memory range length too large
+TEST_F (Dbg2GeneratorAdversarialTest, MemoryRangeTooLarge) {
+ // Set up DBG2 device info
+ CM_ARCH_COMMON_DBG2_DEVICE_INFO device = { 0 };
+
+ device.AddressResourceToken = 1;
+ device.PortType = EFI_ACPI_DBG2_PORT_TYPE_NET;
+ device.PortSubtype = 0;
+ device.AccessSize = EFI_ACPI_6_3_DWORD;
+
+ // Set up memory range with length > MAX_UINT32
+ CM_ARCH_COMMON_MEMORY_RANGE_DESCRIPTOR range = { 0 };
+
+ range.BaseAddress = DBG2_BASE_ADDRESS (0);
+ range.Length = ((UINT64)MAX_UINT32) + 1; // Too large for DBG2 table
+
+ // Mock serial port info query to return not found
+ EXPECT_CALL (
+ MockConfigMgrProtocol,
+ GetObject (
+ _,
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjSerialDebugPortInfo),
+ CM_NULL_TOKEN,
+ _
+ )
+ )
+ .WillOnce (Return (EFI_NOT_FOUND));
+
+ // Mock DBG2 device info query
+ EXPECT_CALL (
+ MockConfigMgrProtocol,
+ GetObject (
+ _,
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjGenericDbg2DeviceInfo),
+ CM_NULL_TOKEN,
+ _
+ )
+ )
+ .WillOnce (
+ DoAll (
+ SetArgPointee<3>(
+ CM_OBJ_DESCRIPTOR {
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjGenericDbg2DeviceInfo),
+ sizeof (CM_ARCH_COMMON_DBG2_DEVICE_INFO),
+ &device,
+ 1
+ }
+ ),
+ Return (EFI_SUCCESS)
+ )
+ );
+
+ // Mock memory range descriptor query
+ EXPECT_CALL (
+ MockConfigMgrProtocol,
+ GetObject (
+ _,
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjMemoryRangeDescriptor),
+ 1,
+ _
+ )
+ )
+ .WillOnce (
+ DoAll (
+ SetArgPointee<3>(
+ CM_OBJ_DESCRIPTOR {
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjMemoryRangeDescriptor),
+ sizeof (CM_ARCH_COMMON_MEMORY_RANGE_DESCRIPTOR),
+ &range,
+ 1
+ }
+ ),
+ Return (EFI_SUCCESS)
+ )
+ );
+
+ EFI_ACPI_DESCRIPTION_HEADER **Table = nullptr;
+ UINTN TableCount = 0;
+
+ EXPECT_EQ (
+ gDbg2Generator->BuildAcpiTableEx (
+ gDbg2Generator,
+ &mAcpiTableInfo,
+ gConfigurationManagerProtocol,
+ &Table,
+ &TableCount
+ ),
+ EFI_INVALID_PARAMETER
+ );
+}
+
+// Test too many memory ranges
+TEST_F (Dbg2GeneratorAdversarialTest, TooManyMemoryRanges) {
+ // Set up DBG2 device info
+ CM_ARCH_COMMON_DBG2_DEVICE_INFO device = { 0 };
+
+ device.AddressResourceToken = 1;
+ device.PortType = EFI_ACPI_DBG2_PORT_TYPE_NET;
+ device.PortSubtype = 0;
+ device.AccessSize = EFI_ACPI_6_3_DWORD;
+
+ // Create array of memory ranges with count > MAX_UINT8
+ std::vector<CM_ARCH_COMMON_MEMORY_RANGE_DESCRIPTOR> ranges;
+
+ for (UINT32 i = 0; i <= MAX_UINT8 + 1; i++) {
+ CM_ARCH_COMMON_MEMORY_RANGE_DESCRIPTOR range = { 0 };
+ range.BaseAddress = DBG2_BASE_ADDRESS (i);
+ range.Length = DBG2_BASE_ADDRESS_LENGTH;
+ ranges.push_back (range);
+ }
+
+ // Mock serial port info query to return not found
+ EXPECT_CALL (
+ MockConfigMgrProtocol,
+ GetObject (
+ _,
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjSerialDebugPortInfo),
+ CM_NULL_TOKEN,
+ _
+ )
+ )
+ .WillOnce (Return (EFI_NOT_FOUND));
+
+ // Mock DBG2 device info query
+ EXPECT_CALL (
+ MockConfigMgrProtocol,
+ GetObject (
+ _,
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjGenericDbg2DeviceInfo),
+ CM_NULL_TOKEN,
+ _
+ )
+ )
+ .WillOnce (
+ DoAll (
+ SetArgPointee<3>(
+ CM_OBJ_DESCRIPTOR {
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjGenericDbg2DeviceInfo),
+ sizeof (CM_ARCH_COMMON_DBG2_DEVICE_INFO),
+ &device,
+ 1
+ }
+ ),
+ Return (EFI_SUCCESS)
+ )
+ );
+
+ // Mock memory range descriptor query
+ EXPECT_CALL (
+ MockConfigMgrProtocol,
+ GetObject (
+ _,
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjMemoryRangeDescriptor),
+ 1,
+ _
+ )
+ )
+ .WillOnce (
+ DoAll (
+ SetArgPointee<3>(
+ CM_OBJ_DESCRIPTOR {
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjMemoryRangeDescriptor),
+ (UINT32)(sizeof (CM_ARCH_COMMON_MEMORY_RANGE_DESCRIPTOR) * ranges.size ()),
+ ranges.data (),
+ (UINT32)ranges.size ()
+ }
+ ),
+ Return (EFI_SUCCESS)
+ )
+ );
+
+ EFI_ACPI_DESCRIPTION_HEADER **Table = nullptr;
+ UINTN TableCount = 0;
+
+ EXPECT_EQ (
+ gDbg2Generator->BuildAcpiTableEx (
+ gDbg2Generator,
+ &mAcpiTableInfo,
+ gConfigurationManagerProtocol,
+ &Table,
+ &TableCount
+ ),
+ EFI_INVALID_PARAMETER
+ );
+}
+
+// Test invalid resource token
+TEST_F (Dbg2GeneratorAdversarialTest, InvalidResourceToken) {
+ // Set up DBG2 device info with CM_NULL_TOKEN for AddressResourceToken
+ CM_ARCH_COMMON_DBG2_DEVICE_INFO device = { 0 };
+
+ device.AddressResourceToken = CM_NULL_TOKEN; // Invalid - must be non-zero
+ device.PortType = EFI_ACPI_DBG2_PORT_TYPE_NET;
+ device.PortSubtype = 0;
+ device.AccessSize = EFI_ACPI_6_3_DWORD;
+
+ // Mock serial port info query to return not found
+ EXPECT_CALL (
+ MockConfigMgrProtocol,
+ GetObject (
+ _,
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjSerialDebugPortInfo),
+ CM_NULL_TOKEN,
+ _
+ )
+ )
+ .WillOnce (Return (EFI_NOT_FOUND));
+
+ // Mock DBG2 device info query
+ EXPECT_CALL (
+ MockConfigMgrProtocol,
+ GetObject (
+ _,
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjGenericDbg2DeviceInfo),
+ CM_NULL_TOKEN,
+ _
+ )
+ )
+ .WillOnce (
+ DoAll (
+ SetArgPointee<3>(
+ CM_OBJ_DESCRIPTOR {
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjGenericDbg2DeviceInfo),
+ sizeof (CM_ARCH_COMMON_DBG2_DEVICE_INFO),
+ &device,
+ 1
+ }
+ ),
+ Return (EFI_SUCCESS)
+ )
+ );
+
+ EFI_ACPI_DESCRIPTION_HEADER **Table = nullptr;
+ UINTN TableCount = 0;
+
+ EXPECT_EQ (
+ gDbg2Generator->BuildAcpiTableEx (
+ gDbg2Generator,
+ &mAcpiTableInfo,
+ gConfigurationManagerProtocol,
+ &Table,
+ &TableCount
+ ),
+ EFI_INVALID_PARAMETER
+ );
+}
+
+// Test invalid serial port access size
+TEST_F (Dbg2GeneratorAdversarialTest, InvalidSerialPortAccessSize) {
+ CM_ARCH_COMMON_SERIAL_PORT_INFO serialPort = { 0 };
+
+ serialPort.BaseAddress = SERIAL_PORT_BASE_ADDRESS (0);
+ serialPort.BaseAddressLength = SERIAL_PORT_BASE_ADDRESS_LENGTH;
+ serialPort.AccessSize = EFI_ACPI_6_3_QWORD; // Invalid - must be <= DWORD
+ serialPort.BaudRate = SERIAL_PORT_BAUD_RATE;
+ serialPort.PortSubtype = EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_FULL_16550;
+
+ // Mock serial port info query
+ EXPECT_CALL (
+ MockConfigMgrProtocol,
+ GetObject (
+ _,
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjSerialDebugPortInfo),
+ CM_NULL_TOKEN,
+ _
+ )
+ )
+ .WillOnce (
+ DoAll (
+ SetArgPointee<3>(
+ CM_OBJ_DESCRIPTOR {
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjSerialDebugPortInfo),
+ sizeof (CM_ARCH_COMMON_SERIAL_PORT_INFO),
+ &serialPort,
+ 1
+ }
+ ),
+ Return (EFI_SUCCESS)
+ )
+ );
+
+ // Mock DBG2 device info query to return not found
+ EXPECT_CALL (
+ MockConfigMgrProtocol,
+ GetObject (
+ _,
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjGenericDbg2DeviceInfo),
+ CM_NULL_TOKEN,
+ _
+ )
+ )
+ .WillOnce (Return (EFI_NOT_FOUND));
+
+ EFI_ACPI_DESCRIPTION_HEADER **Table = nullptr;
+ UINTN TableCount = 0;
+
+ EXPECT_EQ (
+ gDbg2Generator->BuildAcpiTableEx (
+ gDbg2Generator,
+ &mAcpiTableInfo,
+ gConfigurationManagerProtocol,
+ &Table,
+ &TableCount
+ ),
+ EFI_INVALID_PARAMETER
+ );
+}
+
+// Test non-serial DBG2 device with missing object name (should default to ".")
+TEST_F (Dbg2GeneratorAdversarialTest, MissingObjectName) {
+ // Set up DBG2 device info with empty object name
+ CM_ARCH_COMMON_DBG2_DEVICE_INFO device = { 0 };
+
+ device.AddressResourceToken = 1;
+ device.PortType = EFI_ACPI_DBG2_PORT_TYPE_NET;
+ device.PortSubtype = 0;
+ device.AccessSize = EFI_ACPI_6_3_DWORD;
+ // Intentionally leave ObjectName empty
+
+ // Set up memory range
+ CM_ARCH_COMMON_MEMORY_RANGE_DESCRIPTOR range = { 0 };
+
+ range.BaseAddress = DBG2_BASE_ADDRESS (0);
+ range.Length = DBG2_BASE_ADDRESS_LENGTH;
+
+ // Mock serial port info query to return not found
+ EXPECT_CALL (
+ MockConfigMgrProtocol,
+ GetObject (
+ _,
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjSerialDebugPortInfo),
+ CM_NULL_TOKEN,
+ _
+ )
+ )
+ .WillOnce (Return (EFI_NOT_FOUND));
+
+ // Mock DBG2 device info query
+ EXPECT_CALL (
+ MockConfigMgrProtocol,
+ GetObject (
+ _,
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjGenericDbg2DeviceInfo),
+ CM_NULL_TOKEN,
+ _
+ )
+ )
+ .WillOnce (
+ DoAll (
+ SetArgPointee<3>(
+ CM_OBJ_DESCRIPTOR {
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjGenericDbg2DeviceInfo),
+ sizeof (CM_ARCH_COMMON_DBG2_DEVICE_INFO),
+ &device,
+ 1
+ }
+ ),
+ Return (EFI_SUCCESS)
+ )
+ );
+
+ // Mock memory range descriptor query
+ EXPECT_CALL (
+ MockConfigMgrProtocol,
+ GetObject (
+ _,
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjMemoryRangeDescriptor),
+ 1,
+ _
+ )
+ )
+ .WillOnce (
+ DoAll (
+ SetArgPointee<3>(
+ CM_OBJ_DESCRIPTOR {
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjMemoryRangeDescriptor),
+ sizeof (CM_ARCH_COMMON_MEMORY_RANGE_DESCRIPTOR),
+ &range,
+ 1
+ }
+ ),
+ Return (EFI_SUCCESS)
+ )
+ );
+
+ EFI_ACPI_DESCRIPTION_HEADER **Table = nullptr;
+ UINTN TableCount = 0;
+
+ EXPECT_EQ (
+ gDbg2Generator->BuildAcpiTableEx (
+ gDbg2Generator,
+ &mAcpiTableInfo,
+ gConfigurationManagerProtocol,
+ &Table,
+ &TableCount
+ ),
+ EFI_SUCCESS
+ );
+
+ EXPECT_NE (Table, nullptr);
+ EXPECT_EQ (TableCount, 1U);
+
+ // Find the DBG2 table
+ EFI_ACPI_DEBUG_PORT_2_DESCRIPTION_TABLE *Dbg2Table = nullptr;
+
+ for (UINTN i = 0; i < TableCount; i++) {
+ if (Table[i]->Signature == EFI_ACPI_6_3_DEBUG_PORT_2_TABLE_SIGNATURE) {
+ Dbg2Table = (EFI_ACPI_DEBUG_PORT_2_DESCRIPTION_TABLE *)Table[i];
+ break;
+ }
+ }
+
+ ValidateDbg2TableHeader (Dbg2Table);
+
+ // Validate DBG2 table structure
+ EXPECT_EQ (Dbg2Table->NumberDbgDeviceInfo, 1U);
+ EXPECT_NE (Dbg2Table->OffsetDbgDeviceInfo, 0U);
+
+ // Get pointer to device information structure
+ EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT *DeviceInfo = (EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT *)((UINT8 *)Dbg2Table + Dbg2Table->OffsetDbgDeviceInfo);
+
+ // Validate device info
+ EXPECT_EQ (DeviceInfo->Revision, EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION);
+ EXPECT_EQ ((UINT16)DeviceInfo->PortType, (UINT16)EFI_ACPI_DBG2_PORT_TYPE_NET);
+ EXPECT_EQ (DeviceInfo->PortSubtype, (UINT16)0x0000);
+ EXPECT_EQ (DeviceInfo->NumberofGenericAddressRegisters, 1U);
+
+ // Validate that the name string is "."
+ CHAR8 *NameString = (CHAR8 *)((UINT8 *)DeviceInfo + DeviceInfo->NameSpaceStringOffset);
+
+ EXPECT_EQ (NameString[0], '.');
+ EXPECT_EQ (NameString[1], '\0');
+
+ // Validate memory range
+ EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE *Gas = (EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE *)((UINT8 *)DeviceInfo + DeviceInfo->BaseAddressRegisterOffset);
+
+ EXPECT_EQ (Gas->AddressSpaceId, (UINT8)EFI_ACPI_6_3_SYSTEM_MEMORY);
+ EXPECT_EQ (Gas->RegisterBitWidth, (UINT8)32);
+ EXPECT_EQ (Gas->RegisterBitOffset, (UINT8)0);
+ EXPECT_EQ (Gas->AccessSize, (UINT8)EFI_ACPI_6_3_DWORD);
+ EXPECT_EQ (Gas->Address, range.BaseAddress);
+
+ // Validate address size
+ UINT32 *AddressSize = (UINT32 *)((UINT8 *)DeviceInfo + DeviceInfo->AddressSizeOffset);
+
+ EXPECT_EQ (*AddressSize, range.Length);
+
+ gDbg2Generator->FreeTableResourcesEx (
+ gDbg2Generator,
+ &mAcpiTableInfo,
+ gConfigurationManagerProtocol,
+ &Table,
+ TableCount
+ );
+}
+
+// Test multiple serial ports where only first one is used
+TEST_F (Dbg2GeneratorTest, MultipleSerialPorts) {
+ // Create two serial ports
+ std::vector<CM_ARCH_COMMON_SERIAL_PORT_INFO> serialPorts;
+
+ // First serial port
+ CM_ARCH_COMMON_SERIAL_PORT_INFO port1 = { 0 };
+
+ port1.BaseAddress = SERIAL_PORT_BASE_ADDRESS (0);
+ port1.BaseAddressLength = SERIAL_PORT_BASE_ADDRESS_LENGTH;
+ port1.AccessSize = EFI_ACPI_6_3_DWORD;
+ port1.BaudRate = SERIAL_PORT_BAUD_RATE;
+ port1.PortSubtype = EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_FULL_16550;
+ serialPorts.push_back (port1);
+
+ // Second serial port
+ CM_ARCH_COMMON_SERIAL_PORT_INFO port2 = { 0 };
+
+ port2.BaseAddress = SERIAL_PORT_BASE_ADDRESS (1);
+ port2.BaseAddressLength = SERIAL_PORT_BASE_ADDRESS_LENGTH;
+ port2.AccessSize = EFI_ACPI_6_3_DWORD;
+ port2.BaudRate = SERIAL_PORT_BAUD_RATE;
+ port2.PortSubtype = EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_FULL_16550;
+ serialPorts.push_back (port2);
+
+ // Mock serial port info query to return both ports
+ EXPECT_CALL (
+ MockConfigMgrProtocol,
+ GetObject (
+ _,
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjSerialDebugPortInfo),
+ CM_NULL_TOKEN,
+ _
+ )
+ )
+ .WillOnce (
+ DoAll (
+ SetArgPointee<3>(
+ CM_OBJ_DESCRIPTOR {
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjSerialDebugPortInfo),
+ (UINT32)(sizeof (CM_ARCH_COMMON_SERIAL_PORT_INFO) * serialPorts.size ()),
+ serialPorts.data (),
+ (UINT32)serialPorts.size ()
+ }
+ ),
+ Return (EFI_SUCCESS)
+ )
+ );
+
+ // Mock DBG2 device info query to return not found
+ EXPECT_CALL (
+ MockConfigMgrProtocol,
+ GetObject (
+ _,
+ CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjGenericDbg2DeviceInfo),
+ CM_NULL_TOKEN,
+ _
+ )
+ )
+ .WillOnce (Return (EFI_NOT_FOUND));
+
+ EFI_ACPI_DESCRIPTION_HEADER **Table = nullptr;
+ UINTN TableCount = 0;
+
+ EXPECT_EQ (
+ gDbg2Generator->BuildAcpiTableEx (
+ gDbg2Generator,
+ &mAcpiTableInfo,
+ gConfigurationManagerProtocol,
+ &Table,
+ &TableCount
+ ),
+ EFI_SUCCESS
+ );
+
+ EXPECT_NE (Table, nullptr);
+ EXPECT_EQ (TableCount, 2U); // DBG2 table and SSDT table
+
+ // Find the DBG2 table
+ EFI_ACPI_DEBUG_PORT_2_DESCRIPTION_TABLE *Dbg2Table = nullptr;
+ EFI_ACPI_DESCRIPTION_HEADER *SsdtTable = nullptr;
+
+ for (UINTN i = 0; i < TableCount; i++) {
+ if (Table[i]->Signature == EFI_ACPI_6_3_DEBUG_PORT_2_TABLE_SIGNATURE) {
+ Dbg2Table = (EFI_ACPI_DEBUG_PORT_2_DESCRIPTION_TABLE *)Table[i];
+ } else if (Table[i]->Signature == EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
+ SsdtTable = Table[i];
+ }
+ }
+
+ ValidateDbg2TableHeader (Dbg2Table);
+ ValidateSsdtTableHeader (SsdtTable);
+
+ // Validate DBG2 table structure - should only have one device
+ EXPECT_EQ (Dbg2Table->NumberDbgDeviceInfo, 1U);
+ EXPECT_NE (Dbg2Table->OffsetDbgDeviceInfo, 0U);
+
+ // Get pointer to device information structure
+ EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT *DeviceInfo = (EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT *)((UINT8 *)Dbg2Table + Dbg2Table->OffsetDbgDeviceInfo);
+
+ // Validate that only the first serial port is included
+ ValidateSerialDeviceInfo (DeviceInfo, port1.BaseAddress, (UINT32)port1.BaseAddressLength);
+
+ gDbg2Generator->FreeTableResourcesEx (
+ gDbg2Generator,
+ &mAcpiTableInfo,
+ gConfigurationManagerProtocol,
+ &Table,
+ TableCount
+ );
+}
+
+int
+main (
+ int argc,
+ char *argv[]
+ )
+{
+ testing::InitGoogleTest (&argc, argv);
+ return RUN_ALL_TESTS ();
+}
diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiDbg2Lib/GoogleTest/Dbg2GeneratorGoogleTest.inf b/DynamicTablesPkg/Library/Acpi/Common/AcpiDbg2Lib/GoogleTest/Dbg2GeneratorGoogleTest.inf new file mode 100644 index 0000000000..0c3f12f14d --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiDbg2Lib/GoogleTest/Dbg2GeneratorGoogleTest.inf @@ -0,0 +1,36 @@ +## @file
+# Google Test application for DBG2 Generator.
+#
+# Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved. <BR>
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 1.29
+ BASE_NAME = Dbg2GeneratorGoogleTest
+ FILE_GUID = 65dd5a9e-fe40-439c-9ce3-01202d8436c9
+ MODULE_TYPE = HOST_APPLICATION
+ VERSION_STRING = 1.0
+ ENTRY_POINT = GoogleTestCppMain
+
+[Sources]
+ Dbg2GeneratorGoogleTest.cpp
+ ../../../../../Test/Mock/Library/GoogleTest/Protocol/MockConfigurationManagerProtocol.cpp
+
+[Packages]
+ EmbeddedPkg/EmbeddedPkg.dec
+ MdePkg/MdePkg.dec
+ UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
+ DynamicTablesPkg/DynamicTablesPkg.dec
+
+[LibraryClasses]
+ GoogleTestLib
+ BaseLib
+ TableHelperLib
+
+[Protocols]
+ gEdkiiConfigurationManagerProtocolGuid ## CONSUMES
+
+[BuildOptions]
+ MSFT:*_*_*_CC_FLAGS = /EHsc
diff --git a/DynamicTablesPkg/Test/DynamicTablesPkgHostTest.dsc b/DynamicTablesPkg/Test/DynamicTablesPkgHostTest.dsc new file mode 100644 index 0000000000..5dc2094ac6 --- /dev/null +++ b/DynamicTablesPkg/Test/DynamicTablesPkgHostTest.dsc @@ -0,0 +1,34 @@ +## @file
+# DynamicTablesPkg DSC file used to build host-based unit tests.
+#
+# Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved. <BR>
+# Copyright (c) 2019 - 2020, Intel Corporation. All rights reserved.<BR>
+# Copyright (C) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ PLATFORM_NAME = DynamicTablesPkgHostTest
+ PLATFORM_GUID = 47c66bc0-e9ad-4d83-ae31-945eb128beee
+ PLATFORM_VERSION = 0.1
+ DSC_SPECIFICATION = 0x00010005
+ OUTPUT_DIRECTORY = Build/DynamicTablesPkg/HostTest
+ SUPPORTED_ARCHITECTURES = IA32|X64
+ BUILD_TARGETS = NOOPT
+ SKUID_IDENTIFIER = DEFAULT
+
+!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
+
+[LibraryClasses]
+ AcpiHelperLib|DynamicTablesPkg/Library/Common/AcpiHelperLib/AcpiHelperLib.inf
+ AcpiLib|EmbeddedPkg/Library/AcpiLib/AcpiLib.inf
+ AmlLib|DynamicTablesPkg/Library/Common/AmlLib/AmlLib.inf
+ SsdtSerialPortFixupLib|DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPortFixupLib.inf
+ TableHelperLib|DynamicTablesPkg/Library/Common/TableHelperLib/TableHelperLib.inf
+
+[Components]
+ DynamicTablesPkg/Library/Acpi/Common/AcpiDbg2Lib/GoogleTest/Dbg2GeneratorGoogleTest.inf {
+ <LibraryClasses>
+ NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiDbg2Lib/AcpiDbg2Lib.inf
+ }
diff --git a/DynamicTablesPkg/Test/Mock/Include/GoogleTest/Protocol/MockConfigurationManagerProtocol.h b/DynamicTablesPkg/Test/Mock/Include/GoogleTest/Protocol/MockConfigurationManagerProtocol.h new file mode 100644 index 0000000000..447bb0f0af --- /dev/null +++ b/DynamicTablesPkg/Test/Mock/Include/GoogleTest/Protocol/MockConfigurationManagerProtocol.h @@ -0,0 +1,36 @@ +/** @file
+ This file declares a mock of Configuration Manager Protocol.
+
+ Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef MOCK_CONFIGURATION_MANAGER_PROTOCOL_H_
+#define MOCK_CONFIGURATION_MANAGER_PROTOCOL_H_
+
+#include <Library/GoogleTestLib.h>
+#include <Library/FunctionMockLib.h>
+
+extern "C" {
+ #include <Uefi.h>
+ #include <Protocol/ConfigurationManagerProtocol.h>
+}
+
+struct MockConfigurationManagerProtocol {
+ MOCK_INTERFACE_DECLARATION (MockConfigurationManagerProtocol);
+
+ MOCK_FUNCTION_DECLARATION (
+ EFI_STATUS,
+ GetObject,
+ (IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *This,
+ IN CONST CM_OBJECT_ID CmObjectId,
+ IN CONST CM_OBJECT_TOKEN Token,
+ IN OUT CM_OBJ_DESCRIPTOR *CmObject)
+ );
+};
+
+extern "C" {
+ extern EDKII_CONFIGURATION_MANAGER_PROTOCOL *gConfigurationManagerProtocol;
+}
+
+#endif // MOCK_CONFIGURATION_MANAGER_PROTOCOL_H_
diff --git a/DynamicTablesPkg/Test/Mock/Library/GoogleTest/Protocol/MockConfigurationManagerProtocol.cpp b/DynamicTablesPkg/Test/Mock/Library/GoogleTest/Protocol/MockConfigurationManagerProtocol.cpp new file mode 100644 index 0000000000..c157ce8ecf --- /dev/null +++ b/DynamicTablesPkg/Test/Mock/Library/GoogleTest/Protocol/MockConfigurationManagerProtocol.cpp @@ -0,0 +1,22 @@ +/** @file
+ Google Test mock for Configuration Manager Protocol
+
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <GoogleTest/Protocol/MockConfigurationManagerProtocol.h>
+
+MOCK_INTERFACE_DEFINITION (MockConfigurationManagerProtocol);
+MOCK_FUNCTION_DEFINITION (MockConfigurationManagerProtocol, GetObject, 4, EFIAPI);
+
+EDKII_CONFIGURATION_MANAGER_PROTOCOL CONFIG_MGR_PROTOCOL_INSTANCE = {
+ CREATE_REVISION (1, 0), // Revision
+ GetObject, // GetObject
+ NULL, // SetObject
+ NULL // PlatRepoInfo
+};
+
+extern "C" {
+ EDKII_CONFIGURATION_MANAGER_PROTOCOL *gConfigurationManagerProtocol = &CONFIG_MGR_PROTOCOL_INSTANCE;
+}
diff --git a/MdeModulePkg/Library/DeviceManagerUiLib/DeviceManager.c b/MdeModulePkg/Library/DeviceManagerUiLib/DeviceManager.c index c8ca25e87f..3950bbb169 100644 --- a/MdeModulePkg/Library/DeviceManagerUiLib/DeviceManager.c +++ b/MdeModulePkg/Library/DeviceManagerUiLib/DeviceManager.c @@ -848,7 +848,17 @@ DeviceManagerCallback ( {
UINTN CurIndex;
- if (Action != EFI_BROWSER_ACTION_CHANGING) {
+ if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {
+ //
+ // Means enter the device manager form.
+ // Update device manager page when form opens, because options may add or remove.
+ //
+ if (QuestionId == 0x1212) {
+ CreateDeviceManagerForm (DEVICE_MANAGER_FORM_ID);
+ }
+
+ return EFI_SUCCESS;
+ } else if (Action != EFI_BROWSER_ACTION_CHANGING) {
//
// Do nothing for other UEFI Action. Only do call back when data is changed.
//
@@ -926,11 +936,6 @@ DeviceManagerUiLibConstructor ( //
EfiBootManagerConnectAll ();
- //
- // Update boot manager page
- //
- CreateDeviceManagerForm (DEVICE_MANAGER_FORM_ID);
-
return EFI_SUCCESS;
}
diff --git a/MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerVfr.Vfr b/MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerVfr.Vfr index d81c580fe7..911ea036b8 100644 --- a/MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerVfr.Vfr +++ b/MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerVfr.Vfr @@ -28,6 +28,17 @@ formset title = STRING_TOKEN(STR_EDKII_MENU_TITLE);
subtitle text = STRING_TOKEN(STR_DEVICES_LIST);
+ //
+ // Add this invisable text in order to indicate enter Device Manager form.
+ //
+ suppressif TRUE;
+ text
+ help = STRING_TOKEN(STR_EMPTY_STRING),
+ text = STRING_TOKEN(STR_EMPTY_STRING),
+ flags = INTERACTIVE,
+ key = 0x1212;
+ endif;
+
label LABEL_DEVICES_LIST;
label LABEL_END;
diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmDriverHealth.c b/MdeModulePkg/Library/UefiBootManagerLib/BmDriverHealth.c index 46a8b780e3..1f6786f353 100644 --- a/MdeModulePkg/Library/UefiBootManagerLib/BmDriverHealth.c +++ b/MdeModulePkg/Library/UefiBootManagerLib/BmDriverHealth.c @@ -105,6 +105,79 @@ BmGetControllerName ( }
/**
+ Return the driver name.
+
+ @param DriverHealthHandle The handle on which the Driver Health protocol instance is retrieved.
+
+ @return A pointer to the Unicode string to return. This Unicode string is the name of the controller
+ specified by DriverHealthHandle.
+**/
+CHAR16 *
+BmGetDriverName (
+ IN EFI_HANDLE DriverHealthHandle
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *DriverName;
+ CHAR8 *LanguageVariable;
+ CHAR8 *BestLanguage;
+ BOOLEAN Iso639Language;
+ EFI_COMPONENT_NAME_PROTOCOL *ComponentName;
+
+ DriverName = NULL;
+
+ //
+ // Locate Component Name (2) protocol on the driver binging handle.
+ //
+ Iso639Language = FALSE;
+ Status = gBS->HandleProtocol (
+ DriverHealthHandle,
+ &gEfiComponentName2ProtocolGuid,
+ (VOID **)&ComponentName
+ );
+ if (EFI_ERROR (Status)) {
+ Status = gBS->HandleProtocol (
+ DriverHealthHandle,
+ &gEfiComponentNameProtocolGuid,
+ (VOID **)&ComponentName
+ );
+ if (!EFI_ERROR (Status)) {
+ Iso639Language = TRUE;
+ }
+ }
+
+ if (!EFI_ERROR (Status)) {
+ GetEfiGlobalVariable2 (Iso639Language ? L"Lang" : L"PlatformLang", (VOID **)&LanguageVariable, NULL);
+ BestLanguage = GetBestLanguage (
+ ComponentName->SupportedLanguages,
+ Iso639Language,
+ (LanguageVariable != NULL) ? LanguageVariable : "",
+ Iso639Language ? "eng" : "en-US",
+ NULL
+ );
+ if (LanguageVariable != NULL) {
+ FreePool (LanguageVariable);
+ }
+
+ Status = ComponentName->GetDriverName (
+ ComponentName,
+ BestLanguage,
+ &DriverName
+ );
+ }
+
+ if (!EFI_ERROR (Status)) {
+ return AllocateCopyPool (StrSize (DriverName), DriverName);
+ } else {
+ return ConvertDevicePathToText (
+ DevicePathFromHandle (DriverHealthHandle),
+ FALSE,
+ FALSE
+ );
+ }
+}
+
+/**
Display a set of messages returned by the GetHealthStatus () service of the EFI Driver Health Protocol
@param DriverHealthInfo Pointer to the Driver Health information entry.
@@ -116,7 +189,8 @@ BmDisplayMessages ( {
UINTN Index;
EFI_STRING String;
- CHAR16 *ControllerName;
+ CHAR16 *ControllerName = NULL;
+ CHAR16 *DriverName = NULL;
if ((DriverHealthInfo->MessageList == NULL) ||
(DriverHealthInfo->MessageList[0].HiiHandle == NULL))
@@ -124,14 +198,30 @@ BmDisplayMessages ( return;
}
- ControllerName = BmGetControllerName (
- DriverHealthInfo->DriverHealthHandle,
- DriverHealthInfo->ControllerHandle,
- DriverHealthInfo->ChildHandle
- );
+ if (DriverHealthInfo->DriverHealthHandle != NULL) {
+ DriverName = BmGetDriverName (DriverHealthInfo->DriverHealthHandle);
+ if (DriverName != NULL) {
+ DEBUG ((DEBUG_INFO, "Driver: %s\n", DriverName));
+ Print (L"Driver: %s\n", DriverName);
+ }
+ }
+
+ if (DriverHealthInfo->ControllerHandle != NULL) {
+ ControllerName = BmGetControllerName (
+ DriverHealthInfo->DriverHealthHandle,
+ DriverHealthInfo->ControllerHandle,
+ DriverHealthInfo->ChildHandle
+ );
+ if (ControllerName != NULL) {
+ DEBUG ((DEBUG_INFO, "Controller: %s\n", ControllerName));
+ Print (L"Controller: %s\n", ControllerName);
+ }
+ }
+
+ if ((DriverName == NULL) && (ControllerName == NULL)) {
+ return;
+ }
- DEBUG ((DEBUG_INFO, "Controller: %s\n", ControllerName));
- Print (L"Controller: %s\n", ControllerName);
for (Index = 0; DriverHealthInfo->MessageList[Index].HiiHandle != NULL; Index++) {
String = HiiGetString (
DriverHealthInfo->MessageList[Index].HiiHandle,
@@ -147,6 +237,12 @@ BmDisplayMessages ( if (ControllerName != NULL) {
FreePool (ControllerName);
+ ControllerName = NULL;
+ }
+
+ if (DriverName != NULL) {
+ FreePool (DriverName);
+ DriverName = NULL;
}
}
@@ -550,24 +646,58 @@ BmRepairAllControllers ( EfiBootManagerFreeDriverHealthInfo (DriverHealthInfo, Count);
DEBUG_CODE_BEGIN ();
- CHAR16 *ControllerName;
+ CHAR16 *ControllerName = NULL;
+ CHAR16 *DriverName = NULL;
+ CHAR16 String[512];
DriverHealthInfo = EfiBootManagerGetDriverHealthInfo (&Count);
for (Index = 0; Index < Count; Index++) {
- ControllerName = BmGetControllerName (
- DriverHealthInfo[Index].DriverHealthHandle,
- DriverHealthInfo[Index].ControllerHandle,
- DriverHealthInfo[Index].ChildHandle
- );
+ if (DriverHealthInfo == NULL) {
+ continue;
+ }
+
+ ZeroMem (String, sizeof (String));
+ if (DriverHealthInfo[Index].DriverHealthHandle != NULL) {
+ DriverName = BmGetDriverName (DriverHealthInfo[Index].DriverHealthHandle);
+ }
+
+ if (DriverHealthInfo[Index].ControllerHandle != NULL) {
+ ControllerName = BmGetControllerName (
+ DriverHealthInfo[Index].DriverHealthHandle,
+ DriverHealthInfo[Index].ControllerHandle,
+ DriverHealthInfo[Index].ChildHandle
+ );
+ }
+
+ if ((DriverName == NULL) && (ControllerName == NULL)) {
+ continue;
+ }
+
+ UnicodeSPrint (
+ String,
+ sizeof (String),
+ L"%s%s%s",
+ DriverName != NULL ? DriverName : L"",
+ (DriverName != NULL && ControllerName != NULL) ? L" " : L"",
+ ControllerName != NULL ? ControllerName : L""
+ );
+
DEBUG ((
DEBUG_INFO,
"%02d: %s - %s\n",
Index,
- ControllerName,
+ String,
mBmHealthStatusText[DriverHealthInfo[Index].HealthStatus]
));
+
if (ControllerName != NULL) {
FreePool (ControllerName);
+ ControllerName = NULL;
+ }
+
+ if (DriverName != NULL) {
+ FreePool (DriverName);
+ DriverName = NULL;
}
}
diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c index 056a4cb4e9..a1914f169a 100644 --- a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c +++ b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c @@ -2164,12 +2164,13 @@ DisplayMenuString ( // First print the highlight string.
//
SetDisplayAttribute (MenuOption, TRUE);
- Length = PrintStringAt (Col, Row, String);
+ PrintStringAt (Col, Row, String);
//
// Second, clean the empty after the string.
//
SetDisplayAttribute (MenuOption, FALSE);
+ Length = GetStringWidth (String) / 2 - 1;
PrintStringAtWithWidth (Col + Length, Row, L"", Width - Length);
}
|