diff --git a/MdePkg/MdePkg.ci.yaml b/MdePkg/MdePkg.ci.yaml index c3faf4913d..45f4fb537b 100644 --- a/MdePkg/MdePkg.ci.yaml +++ b/MdePkg/MdePkg.ci.yaml @@ -74,7 +74,10 @@ "Test/UnitTest/Library/BaseSafeIntLib/TestBaseSafeIntLib.c", "Library/BaseFdtLib", "Library/MipiSysTLib/mipi_syst.h", - "Include/Register/Amd/SmramSaveStateMap.h" + "Include/Register/Amd/SmramSaveStateMap.h", + "Test/UnitTest/Library/DevicePathLib/TestDevicePathLib.c", + "Test/UnitTest/Library/DevicePathLib/TestDevicePathLib.h", + "Test/UnitTest/Library/DevicePathLib/TestDevicePathStringConversions.c" ] }, ## options defined ci/Plugin/CompilerPlugin diff --git a/MdePkg/Test/MdePkgHostTest.dsc b/MdePkg/Test/MdePkgHostTest.dsc index 529ea69024..b92b564d43 100644 --- a/MdePkg/Test/MdePkgHostTest.dsc +++ b/MdePkg/Test/MdePkgHostTest.dsc @@ -21,6 +21,7 @@ [LibraryClasses] SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibBase.inf [Components] # @@ -29,6 +30,7 @@ MdePkg/Test/UnitTest/Library/BaseSafeIntLib/TestBaseSafeIntLibHost.inf MdePkg/Test/UnitTest/Library/BaseLib/BaseLibUnitTestsHost.inf MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/GoogleTestBaseSafeIntLib.inf + MdePkg/Test/UnitTest/Library/DevicePathLib/TestDevicePathLibHost.inf # # Build HOST_APPLICATION Libraries diff --git a/MdePkg/Test/UnitTest/Library/DevicePathLib/TestDevicePathLib.c b/MdePkg/Test/UnitTest/Library/DevicePathLib/TestDevicePathLib.c new file mode 100644 index 0000000000..687497278c --- /dev/null +++ b/MdePkg/Test/UnitTest/Library/DevicePathLib/TestDevicePathLib.c @@ -0,0 +1,638 @@ +/** @file + UEFI OS based application for unit testing the DevicePathLib. + + Copyright (c) 2023, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "TestDevicePathLib.h" + +#define UNIT_TEST_NAME "DevicePathLib Unit Test Application" +#define UNIT_TEST_VERSION "0.1" + +typedef struct { + ACPI_HID_DEVICE_PATH AcpiPath; + PCI_DEVICE_PATH PciPathRootPort; + PCI_DEVICE_PATH PciPathEndPoint; + USB_DEVICE_PATH UsbPath; + EFI_DEVICE_PATH_PROTOCOL End; +} TEST_COMPLEX_DEVICE_PATH; + +GLOBAL_REMOVE_IF_UNREFERENCED TEST_COMPLEX_DEVICE_PATH mComplexDevicePath = { + { // ACPI device path with root bridge EISA_PNP_ID + { + ACPI_DEVICE_PATH, + ACPI_DP, + { + (UINT8)(sizeof (ACPI_HID_DEVICE_PATH)), + (UINT8)((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) + } + }, + EISA_PNP_ID (0x0A03), + 0 + }, + { // PCI device path - root port (0x2:0x0) + { + HARDWARE_DEVICE_PATH, + HW_PCI_DP, + { + (UINT8)(sizeof (PCI_DEVICE_PATH)), + (UINT8)((sizeof (PCI_DEVICE_PATH)) >> 8) + } + }, + 0x2, + 0x0 + }, + { // PCI device path - endpoint (0x0:0x0) + { + HARDWARE_DEVICE_PATH, + HW_PCI_DP, + { + (UINT8)(sizeof (PCI_DEVICE_PATH)), + (UINT8)((sizeof (PCI_DEVICE_PATH)) >> 8) + } + }, + 0x0, + 0x0 + }, + { // USB interface + { + MESSAGING_DEVICE_PATH, + MSG_USB_DP, + { + (UINT8)(sizeof (USB_DEVICE_PATH)), + (UINT8)((sizeof (USB_CLASS_DEVICE_PATH)) >> 8) + } + }, + 0, + 2 + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8)(sizeof (EFI_DEVICE_PATH_PROTOCOL)), + (UINT8)((sizeof (EFI_DEVICE_PATH_PROTOCOL)) >> 8) + } + } +}; + +CONST GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mComplexDevicePathString = L"PciRoot(0x0)/Pci(0x0,0x2)/Pci(0x0,0x0)/USB(0x0,0x2)"; + +CONST GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mPciEndPointPathString = L"Pci(0x0, 0x0)"; + +typedef struct { + ACPI_HID_DEVICE_PATH AcpiPath; + EFI_DEVICE_PATH_PROTOCOL End; +} TEST_SIMPLE_DEVICE_PATH; + +GLOBAL_REMOVE_IF_UNREFERENCED TEST_SIMPLE_DEVICE_PATH mSimpleDevicePath = { + { // ACPI device path with root bridge EISA_PNP_ID + { + ACPI_DEVICE_PATH, + ACPI_DP, + { + (UINT8)(sizeof (ACPI_HID_DEVICE_PATH)), + (UINT8)((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) + } + }, + EISA_PNP_ID (0x0A03), + 0 + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8)(sizeof (EFI_DEVICE_PATH_PROTOCOL)), + (UINT8)((sizeof (EFI_DEVICE_PATH_PROTOCOL)) >> 8) + } + } +}; + +GLOBAL_REMOVE_IF_UNREFERENCED TEST_SIMPLE_DEVICE_PATH mInvalidSimpleDevicePath = { + { // ACPI device path with root bridge EISA_PNP_ID + { + ACPI_DEVICE_PATH, + ACPI_DP, + { + 0, + 0 + } + }, + EISA_PNP_ID (0x0A03), + 0 + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8)(sizeof (EFI_DEVICE_PATH_PROTOCOL)), + (UINT8)((sizeof (EFI_DEVICE_PATH_PROTOCOL)) >> 8) + } + } +}; + +typedef struct { + TEST_SIMPLE_DEVICE_PATH *SimpleDevicePath; + TEST_SIMPLE_DEVICE_PATH *InvalidDevicePath; + TEST_COMPLEX_DEVICE_PATH *ComplexDevicePath; +} SIMPLE_TEST_SUITE_CONTEXT; + +UNIT_TEST_STATUS +EFIAPI +TestIsDevicePathValid ( + IN UNIT_TEST_CONTEXT Context + ) +{ + BOOLEAN IsValid; + SIMPLE_TEST_SUITE_CONTEXT *TestContext; + + TestContext = (SIMPLE_TEST_SUITE_CONTEXT *)Context; + + IsValid = IsDevicePathValid ((EFI_DEVICE_PATH_PROTOCOL *)TestContext->SimpleDevicePath, sizeof (TEST_SIMPLE_DEVICE_PATH)); + UT_ASSERT_TRUE (IsValid); + + IsValid = IsDevicePathValid ((EFI_DEVICE_PATH_PROTOCOL *)TestContext->ComplexDevicePath, sizeof (TEST_COMPLEX_DEVICE_PATH)); + UT_ASSERT_TRUE (IsValid); + + IsValid = IsDevicePathValid ((EFI_DEVICE_PATH_PROTOCOL *)TestContext->ComplexDevicePath, 0); + UT_ASSERT_TRUE (IsValid); + + // Device path can't be NULL + IsValid = IsDevicePathValid (NULL, 0); + UT_ASSERT_FALSE (IsValid); + + // MaxSize can't be less then the size of the device path + IsValid = IsDevicePathValid ((EFI_DEVICE_PATH_PROTOCOL *)TestContext->SimpleDevicePath, sizeof (TEST_SIMPLE_DEVICE_PATH) - 1); + UT_ASSERT_FALSE (IsValid); + + // If MaxSize != 0 it must be bigger then EFI_DEVICE_PATH_PROTOCOL + IsValid = IsDevicePathValid ((EFI_DEVICE_PATH_PROTOCOL *)TestContext->SimpleDevicePath, sizeof (EFI_DEVICE_PATH_PROTOCOL) - 1); + UT_ASSERT_FALSE (IsValid); + + IsValid = IsDevicePathValid ((EFI_DEVICE_PATH_PROTOCOL *)TestContext->InvalidDevicePath, 0); + UT_ASSERT_FALSE (IsValid); + + return UNIT_TEST_PASSED; +} + +UNIT_TEST_STATUS +EFIAPI +TestDevicePathType ( + IN UNIT_TEST_CONTEXT Context + ) +{ + UINT8 Type; + SIMPLE_TEST_SUITE_CONTEXT *TestContext; + + TestContext = (SIMPLE_TEST_SUITE_CONTEXT *)Context; + + // Test 2 types just in case the implementation is returning constant value + // NOTE: passing NULL to this function causes NULL pointer dereference. + Type = DevicePathType (&TestContext->ComplexDevicePath->AcpiPath); + UT_ASSERT_EQUAL (Type, ACPI_DEVICE_PATH); + + Type = DevicePathType (&TestContext->ComplexDevicePath->PciPathRootPort); + UT_ASSERT_EQUAL (Type, HARDWARE_DEVICE_PATH); + + return UNIT_TEST_PASSED; +} + +UNIT_TEST_STATUS +EFIAPI +TestDevicePathSubType ( + IN UNIT_TEST_CONTEXT Context + ) +{ + UINT8 SubType; + SIMPLE_TEST_SUITE_CONTEXT *TestContext; + + TestContext = (SIMPLE_TEST_SUITE_CONTEXT *)Context; + + // Test 2 sub types just in case the implementation is returning constant value + // NOTE: passing NULL to this function causes NULL pointer dereference. + SubType = DevicePathSubType (&TestContext->ComplexDevicePath->AcpiPath); + UT_ASSERT_EQUAL (SubType, ACPI_DP); + + SubType = DevicePathSubType (&TestContext->ComplexDevicePath->PciPathRootPort); + UT_ASSERT_EQUAL (SubType, HW_PCI_DP); + + return UNIT_TEST_PASSED; +} + +UNIT_TEST_STATUS +EFIAPI +TestDevicePathNodeLength ( + IN UNIT_TEST_CONTEXT Context + ) +{ + UINTN Length; + SIMPLE_TEST_SUITE_CONTEXT *TestContext; + + TestContext = (SIMPLE_TEST_SUITE_CONTEXT *)Context; + + // Test 2 nodes just in case the implementation is returning constant value + // NOTE: passing NULL to this function causes NULL pointer dereference. + Length = DevicePathNodeLength (&TestContext->ComplexDevicePath->AcpiPath); + UT_ASSERT_EQUAL (Length, sizeof (ACPI_HID_DEVICE_PATH)); + + Length = DevicePathNodeLength (&TestContext->ComplexDevicePath->PciPathRootPort); + UT_ASSERT_EQUAL (Length, sizeof (PCI_DEVICE_PATH)); + + return UNIT_TEST_PASSED; +} + +UNIT_TEST_STATUS +EFIAPI +TestNextDevicePathNode ( + IN UNIT_TEST_CONTEXT Context + ) +{ + VOID *Node; + SIMPLE_TEST_SUITE_CONTEXT *TestContext; + + TestContext = (SIMPLE_TEST_SUITE_CONTEXT *)Context; + + Node = &mComplexDevicePath; + Node = NextDevicePathNode (Node); + UT_ASSERT_MEM_EQUAL (Node, &TestContext->ComplexDevicePath->PciPathRootPort, DevicePathNodeLength (Node)); + + Node = NextDevicePathNode (Node); + UT_ASSERT_MEM_EQUAL (Node, &TestContext->ComplexDevicePath->PciPathEndPoint, DevicePathNodeLength (Node)); + + return UNIT_TEST_PASSED; +} + +UNIT_TEST_STATUS +EFIAPI +TestIsDevicePathEndType ( + IN UNIT_TEST_CONTEXT Context + ) +{ + BOOLEAN IsEndType; + SIMPLE_TEST_SUITE_CONTEXT *TestContext; + + TestContext = (SIMPLE_TEST_SUITE_CONTEXT *)Context; + + IsEndType = IsDevicePathEndType (&TestContext->ComplexDevicePath->PciPathRootPort); + UT_ASSERT_FALSE (IsEndType); + + IsEndType = IsDevicePathEndType (&TestContext->ComplexDevicePath->End); + UT_ASSERT_TRUE (IsEndType); + + return UNIT_TEST_PASSED; +} + +UNIT_TEST_STATUS +EFIAPI +TestIsDevicePathEnd ( + IN UNIT_TEST_CONTEXT Context + ) +{ + BOOLEAN IsEnd; + SIMPLE_TEST_SUITE_CONTEXT *TestContext; + + TestContext = (SIMPLE_TEST_SUITE_CONTEXT *)Context; + + IsEnd = IsDevicePathEnd (&TestContext->ComplexDevicePath->PciPathRootPort); + UT_ASSERT_FALSE (IsEnd); + + IsEnd = IsDevicePathEnd (&TestContext->ComplexDevicePath->End); + UT_ASSERT_TRUE (IsEnd); + + return UNIT_TEST_PASSED; +} + +UNIT_TEST_STATUS +EFIAPI +TestSetDevicePathNodeLength ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_DEVICE_PATH_PROTOCOL DevPath; + + // NOTE: Node == NULL or NodeLength >= 0x10000 NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL) + // are all invalid parameters. However there are only ASSERTS added to catch them so there is no + // way to test it. + SetDevicePathNodeLength (&DevPath, sizeof (EFI_DEVICE_PATH_PROTOCOL)); + UT_ASSERT_EQUAL (DevicePathNodeLength (&DevPath), sizeof (EFI_DEVICE_PATH_PROTOCOL)); + + return UNIT_TEST_PASSED; +} + +UNIT_TEST_STATUS +EFIAPI +TestSetDevicePathEndNode ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_DEVICE_PATH_PROTOCOL EndNode; + + SetDevicePathEndNode (&EndNode); + UT_ASSERT_EQUAL (EndNode.Type, END_DEVICE_PATH_TYPE); + UT_ASSERT_EQUAL (EndNode.SubType, END_ENTIRE_DEVICE_PATH_SUBTYPE); + UT_ASSERT_EQUAL (DevicePathNodeLength (&EndNode), END_DEVICE_PATH_LENGTH); + + return UNIT_TEST_PASSED; +} + +UNIT_TEST_STATUS +EFIAPI +TestGetDevicePathSize ( + IN UNIT_TEST_CONTEXT Context + ) +{ + UINTN Size; + SIMPLE_TEST_SUITE_CONTEXT *TestContext; + + TestContext = (SIMPLE_TEST_SUITE_CONTEXT *)Context; + + Size = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)TestContext->SimpleDevicePath); + UT_ASSERT_EQUAL (Size, sizeof (TEST_SIMPLE_DEVICE_PATH)); + + Size = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)TestContext->ComplexDevicePath); + UT_ASSERT_EQUAL (Size, sizeof (TEST_COMPLEX_DEVICE_PATH)); + + return UNIT_TEST_PASSED; +} + +UNIT_TEST_STATUS +EFIAPI +TestDuplicateDevicePath ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Duplicate; + SIMPLE_TEST_SUITE_CONTEXT *TestContext; + + TestContext = (SIMPLE_TEST_SUITE_CONTEXT *)Context; + + Duplicate = DuplicateDevicePath ((EFI_DEVICE_PATH_PROTOCOL *)TestContext->ComplexDevicePath); + UT_ASSERT_EQUAL (GetDevicePathSize (Duplicate), GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)TestContext->ComplexDevicePath)); + UT_ASSERT_MEM_EQUAL (Duplicate, TestContext->ComplexDevicePath, GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)TestContext->ComplexDevicePath)); + FreePool (Duplicate); + + return UNIT_TEST_PASSED; +} + +UNIT_TEST_STATUS +EFIAPI +TestAppendDevicePath ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Appended; + EFI_DEVICE_PATH_PROTOCOL *NextNode; + + Appended = AppendDevicePath ((EFI_DEVICE_PATH_PROTOCOL *)&mSimpleDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&mComplexDevicePath); + NextNode = NextDevicePathNode (Appended); + UT_ASSERT_MEM_EQUAL (NextNode, &mSimpleDevicePath.AcpiPath, sizeof (ACPI_HID_DEVICE_PATH)); + FreePool (Appended); + + // If one of the paths is invalid result device path should be NULL + Appended = AppendDevicePath ((EFI_DEVICE_PATH_PROTOCOL *)&mSimpleDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&mInvalidSimpleDevicePath); + UT_ASSERT_EQUAL ((uintptr_t)Appended, (uintptr_t)NULL); + + Appended = AppendDevicePath (NULL, NULL); + UT_ASSERT_EQUAL (Appended->Type, END_DEVICE_PATH_TYPE); + UT_ASSERT_EQUAL (Appended->SubType, END_ENTIRE_DEVICE_PATH_SUBTYPE); + UT_ASSERT_EQUAL (DevicePathNodeLength (Appended), END_DEVICE_PATH_LENGTH); + FreePool (Appended); + + return UNIT_TEST_PASSED; +} + +UNIT_TEST_STATUS +EFIAPI +TestAppendDevicePathNode ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Appended; + EFI_DEVICE_PATH_PROTOCOL *NextNode; + BOOLEAN IsValid; + ACPI_HID_DEVICE_PATH AcpiPath = + { + { + ACPI_DEVICE_PATH, + ACPI_DP, + { + (UINT8)(sizeof (ACPI_HID_DEVICE_PATH)), + (UINT8)((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) + } + }, + EISA_PNP_ID (0x0AAB), + 0 + }; + + Appended = AppendDevicePathNode ((EFI_DEVICE_PATH_PROTOCOL *)&mSimpleDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&AcpiPath); + NextNode = NextDevicePathNode (Appended); + UT_ASSERT_MEM_EQUAL (NextNode, &AcpiPath, sizeof (ACPI_HID_DEVICE_PATH)); + FreePool (Appended); + + Appended = AppendDevicePathNode (NULL, (EFI_DEVICE_PATH_PROTOCOL *)&AcpiPath); + UT_ASSERT_MEM_EQUAL (Appended, &AcpiPath, sizeof (ACPI_HID_DEVICE_PATH)); + IsValid = IsDevicePathValid (Appended, 0); + UT_ASSERT_TRUE (IsValid); + FreePool (Appended); + + Appended = AppendDevicePathNode (NULL, NULL); + UT_ASSERT_EQUAL (Appended->Type, END_DEVICE_PATH_TYPE); + UT_ASSERT_EQUAL (Appended->SubType, END_ENTIRE_DEVICE_PATH_SUBTYPE); + UT_ASSERT_EQUAL (DevicePathNodeLength (Appended), END_DEVICE_PATH_LENGTH); + FreePool (Appended); + + return UNIT_TEST_PASSED; +} + +UNIT_TEST_STATUS +EFIAPI +TestAppendDevicePathInstance ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Appended; + EFI_DEVICE_PATH_PROTOCOL *NextInstance; + EFI_DEVICE_PATH_PROTOCOL *NextInstanceRet; + BOOLEAN IsMultiInstance; + UINTN Size; + + Appended = AppendDevicePathInstance ((EFI_DEVICE_PATH_PROTOCOL *)&mSimpleDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&mComplexDevicePath); + IsMultiInstance = IsDevicePathMultiInstance (Appended); + UT_ASSERT_TRUE (IsMultiInstance); + UT_ASSERT_MEM_EQUAL (Appended, &mSimpleDevicePath, sizeof (ACPI_DEVICE_PATH)); + NextInstance = Appended; + NextInstanceRet = GetNextDevicePathInstance (&NextInstance, &Size); + UT_ASSERT_MEM_EQUAL (NextInstance, &mComplexDevicePath, Size); + FreePool (Appended); + FreePool (NextInstanceRet); + + Appended = AppendDevicePathInstance (NULL, (EFI_DEVICE_PATH_PROTOCOL *)&mSimpleDevicePath); + UT_ASSERT_MEM_EQUAL (Appended, &mSimpleDevicePath, sizeof (TEST_SIMPLE_DEVICE_PATH)); + FreePool (Appended); + + Appended = AppendDevicePathInstance (NULL, NULL); + UT_ASSERT_EQUAL ((uintptr_t)Appended, (uintptr_t)NULL); + FreePool (Appended); + + Appended = AppendDevicePathInstance ((EFI_DEVICE_PATH_PROTOCOL *)&mSimpleDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&mInvalidSimpleDevicePath); + UT_ASSERT_EQUAL ((uintptr_t)Appended, (uintptr_t)NULL); + FreePool (Appended); + + return UNIT_TEST_PASSED; +} + +UNIT_TEST_STATUS +EFIAPI +TestDevicePathFromHandle ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_HANDLE Handle; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN FakeHandle; + + Handle = NULL; + DevicePath = DevicePathFromHandle (Handle); + UT_ASSERT_EQUAL ((uintptr_t)DevicePath, (uintptr_t)NULL); + + Handle = (EFI_HANDLE)&FakeHandle; + DevicePath = DevicePathFromHandle (Handle); + UT_ASSERT_EQUAL ((uintptr_t)DevicePath, (uintptr_t)NULL); + + return UNIT_TEST_PASSED; +} + +UNIT_TEST_STATUS +EFIAPI +TestCreateDeviceNode ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevNode; + + DevNode = CreateDeviceNode (HARDWARE_DEVICE_PATH, HW_PCI_DP, sizeof (PCI_DEVICE_PATH)); + UT_ASSERT_EQUAL (DevNode->Type, HARDWARE_DEVICE_PATH); + UT_ASSERT_EQUAL (DevNode->SubType, HW_PCI_DP); + UT_ASSERT_EQUAL (DevicePathNodeLength (DevNode), sizeof (PCI_DEVICE_PATH)); + + return UNIT_TEST_PASSED; +} + +UNIT_TEST_STATUS +EFIAPI +TestFileDevicePath ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_HANDLE Handle; + FILEPATH_DEVICE_PATH *DevicePath; + CONST CHAR16 *TestFilePath = L"FS0:/Boot/EFI/BootMgr.efi"; + + Handle = NULL; + DevicePath = (FILEPATH_DEVICE_PATH *)FileDevicePath (Handle, TestFilePath); + UT_ASSERT_NOT_NULL (DevicePath); + UT_ASSERT_EQUAL (DevicePath->Header.Type, MEDIA_DEVICE_PATH); + UT_ASSERT_EQUAL (DevicePath->Header.Type, MEDIA_FILEPATH_DP); + UT_ASSERT_MEM_EQUAL (DevicePath->PathName, TestFilePath, StrSize (TestFilePath)); + + return UNIT_TEST_PASSED; +} + +/** + + Main fuction sets up the unit test environment + +**/ +EFI_STATUS +EFIAPI +UefiTestMain ( + VOID + ) +{ + EFI_STATUS Status; + UNIT_TEST_FRAMEWORK_HANDLE Framework; + UNIT_TEST_SUITE_HANDLE DevicePathSimpleTestSuite; + UNIT_TEST_SUITE_HANDLE DevicePathAppendTestSuite; + UNIT_TEST_SUITE_HANDLE DevicePathFileTestSuite; + SIMPLE_TEST_SUITE_CONTEXT SimpleTestContext; + + DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_NAME, UNIT_TEST_VERSION)); + + Framework = NULL; + DevicePathSimpleTestSuite = NULL; + DevicePathAppendTestSuite = NULL; + DevicePathFileTestSuite = NULL; + + Status = InitUnitTestFramework (&Framework, UNIT_TEST_NAME, gEfiCallerBaseName, UNIT_TEST_VERSION); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status = %r\n", Status)); + goto EXIT; + } + + Status = CreateUnitTestSuite (&DevicePathSimpleTestSuite, Framework, "Simple device path operations test suite", "Common.DevicePath.SimpleOps", NULL, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed to create simple device path test suite\n")); + goto EXIT; + } + + SimpleTestContext.SimpleDevicePath = &mSimpleDevicePath; + SimpleTestContext.InvalidDevicePath = &mInvalidSimpleDevicePath; + SimpleTestContext.ComplexDevicePath = &mComplexDevicePath; + + AddTestCase (DevicePathSimpleTestSuite, "Test IsDevicePathValid", "TestIsDevicePathValid", TestIsDevicePathValid, NULL, NULL, &SimpleTestContext); + AddTestCase (DevicePathSimpleTestSuite, "Test DevicePathType", "TestDevicePathType", TestDevicePathType, NULL, NULL, &SimpleTestContext); + AddTestCase (DevicePathSimpleTestSuite, "Test DevicePathSubType", "TestDevicePathSubType", TestDevicePathSubType, NULL, NULL, &SimpleTestContext); + AddTestCase (DevicePathSimpleTestSuite, "Test DevicePathNodeLength", "TestDevicePathNodeLength", TestDevicePathNodeLength, NULL, NULL, &SimpleTestContext); + AddTestCase (DevicePathSimpleTestSuite, "Test NextDevicePathNode", "TestNextDevicePathNode", TestNextDevicePathNode, NULL, NULL, &SimpleTestContext); + AddTestCase (DevicePathSimpleTestSuite, "Test IsDevicePathEndType", "TestIsDevicePathEndType", TestIsDevicePathEndType, NULL, NULL, &SimpleTestContext); + AddTestCase (DevicePathSimpleTestSuite, "Test IsDevicePathEnd", "TestIsDevicePathEnd", TestIsDevicePathEnd, NULL, NULL, &SimpleTestContext); + AddTestCase (DevicePathSimpleTestSuite, "Test SetDevicePathNodeLength", "TestSetDevicePathNodeLength", TestSetDevicePathNodeLength, NULL, NULL, &SimpleTestContext); + AddTestCase (DevicePathSimpleTestSuite, "Test GetDevicePathSize", "TestGetDevicePathSize", TestGetDevicePathSize, NULL, NULL, &SimpleTestContext); + AddTestCase (DevicePathSimpleTestSuite, "Test CreateDeviceNode", "TestCreateDeviceNode", TestCreateDeviceNode, NULL, NULL, &SimpleTestContext); + AddTestCase (DevicePathSimpleTestSuite, "Test SetDevicePathEndNode", "TestSetDevicePathEndNode", TestSetDevicePathEndNode, NULL, NULL, &SimpleTestContext); + AddTestCase (DevicePathAppendTestSuite, "Test DuplicateDevicePath", "TestDuplicateDevicePath", TestDuplicateDevicePath, NULL, NULL, &SimpleTestContext); + + Status = CreateUnitTestSuite (&DevicePathAppendTestSuite, Framework, "Device path append operations test suite", "Common.DevicePath.Append", NULL, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed to create append device path test suite\n")); + goto EXIT; + } + + AddTestCase (DevicePathAppendTestSuite, "Test AppendDevicePath", "TestAppendDevicePath", TestAppendDevicePath, NULL, NULL, NULL); + AddTestCase (DevicePathAppendTestSuite, "Test AppendDevicePathNode", "TestAppendDevicePathNode", TestAppendDevicePathNode, NULL, NULL, NULL); + AddTestCase (DevicePathAppendTestSuite, "Test AppendDevicePathInstance", "TestAppendDevicePathInstance", TestAppendDevicePathInstance, NULL, NULL, NULL); + + Status = CreateDevicePathStringConversionsTestSuite (Framework); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed to create conversions test suite\n")); + goto EXIT; + } + + Status = CreateUnitTestSuite (&DevicePathFileTestSuite, Framework, "Device path file operations test suite", "Common.DevicePath.FileDevPath", NULL, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed to create device path file test suite\n")); + goto EXIT; + } + + AddTestCase (DevicePathFileTestSuite, "Test DevicePathFromHandle", "TestDevicePathFromHandle", TestDevicePathFromHandle, NULL, NULL, NULL); + AddTestCase (DevicePathFileTestSuite, "Test FileDevicePath", "TestFileDevicePath", TestFileDevicePath, NULL, NULL, NULL); + + Status = RunAllTestSuites (Framework); + +EXIT: + if (Framework != NULL) { + FreeUnitTestFramework (Framework); + } + + return Status; +} + +int +main ( + int argc, + char *argv[] + ) +{ + return UefiTestMain (); +} diff --git a/MdePkg/Test/UnitTest/Library/DevicePathLib/TestDevicePathLib.h b/MdePkg/Test/UnitTest/Library/DevicePathLib/TestDevicePathLib.h new file mode 100644 index 0000000000..4a0c3d4c43 --- /dev/null +++ b/MdePkg/Test/UnitTest/Library/DevicePathLib/TestDevicePathLib.h @@ -0,0 +1,26 @@ +/** @file + UEFI OS based application for unit testing the DevicePathLib. + + Copyright (c) 2023, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef __TEST_DEVICE_PATH_LIB_H__ +#define __TEST_DEVICE_PATH_LIB_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +EFI_STATUS +CreateDevicePathStringConversionsTestSuite ( + IN UNIT_TEST_FRAMEWORK_HANDLE Framework + ); + +#endif diff --git a/MdePkg/Test/UnitTest/Library/DevicePathLib/TestDevicePathLibHost.inf b/MdePkg/Test/UnitTest/Library/DevicePathLib/TestDevicePathLibHost.inf new file mode 100644 index 0000000000..9f9c36946a --- /dev/null +++ b/MdePkg/Test/UnitTest/Library/DevicePathLib/TestDevicePathLibHost.inf @@ -0,0 +1,33 @@ +## @file +# Host OS based Application that Unit Tests the UefiDevicePathLib +# +# Copyright (c) 2023, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TestDevicePathLibHost + MODULE_UNI_FILE = TestDevicePathLib.uni + FILE_GUID = F1505A0E-D71F-4431-99BE-736776842E38 + MODULE_TYPE = HOST_APPLICATION + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + TestDevicePathLib.c + TestDevicePathStringConversions.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + DebugLib + DevicePathLib + UnitTestLib diff --git a/MdePkg/Test/UnitTest/Library/DevicePathLib/TestDevicePathStringConversions.c b/MdePkg/Test/UnitTest/Library/DevicePathLib/TestDevicePathStringConversions.c new file mode 100644 index 0000000000..4ea25ec142 --- /dev/null +++ b/MdePkg/Test/UnitTest/Library/DevicePathLib/TestDevicePathStringConversions.c @@ -0,0 +1,370 @@ +/** @file + UEFI OS based application for unit testing the DevicePathLib. + + Copyright (c) 2023, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "TestDevicePathLib.h" + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL *DevPath; + CONST CHAR16 *DevPathString; +} DEVICE_PATH_CONVERSIONS_TEST_CONTEXT; + +GLOBAL_REMOVE_IF_UNREFERENCED PCI_DEVICE_PATH mPciDevicePathNode = +{ + // PCI device path - root port (0x2:0x0) + { + HARDWARE_DEVICE_PATH, + HW_PCI_DP, + { + (UINT8)(sizeof (PCI_DEVICE_PATH)), + (UINT8)((sizeof (PCI_DEVICE_PATH)) >> 8) + } + }, + 0x2, + 0x0 +}; + +GLOBAL_REMOVE_IF_UNREFERENCED ACPI_HID_DEVICE_PATH mAcpiPciRootHidDevicePathNode = +{ + // ACPI PCI root - PciRoot(0x0) + { + ACPI_DEVICE_PATH, + ACPI_DP, + { + (UINT8)(sizeof (ACPI_HID_DEVICE_PATH)), + (UINT8)((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) + } + }, + EISA_PNP_ID (0x0A03), + 0 +}; + +GLOBAL_REMOVE_IF_UNREFERENCED ACPI_HID_DEVICE_PATH mAcpiNonPciRootHidDevicePathNode = +{ + // Random ACPI device - ACPI(PNPB0C0, 1) + { + ACPI_DEVICE_PATH, + ACPI_DP, + { + (UINT8)(sizeof (ACPI_HID_DEVICE_PATH)), + (UINT8)((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) + } + }, + EISA_PNP_ID (0xB0C0), + 1 +}; + +#define HID_STR_SIZE 8 +#define CID_STR_SIZE 8 +#define UID_STR_SIZE 8 + +typedef struct { + ACPI_EXTENDED_HID_DEVICE_PATH AcpiEx; + CHAR8 HidStr[HID_STR_SIZE]; + CHAR8 CidStr[CID_STR_SIZE]; + CHAR8 UidStr[UID_STR_SIZE]; +} ACPI_EXTENDED_HID_DEVICE_PATH_FULL; + +GLOBAL_REMOVE_IF_UNREFERENCED ACPI_EXTENDED_HID_DEVICE_PATH_FULL mAcpiExtendedDevicePathFull = +{ + // ACPI Extended HID PciRoot device node + { + { + ACPI_DEVICE_PATH, + ACPI_EXTENDED_DP, + { + (UINT8)(sizeof (ACPI_EXTENDED_HID_DEVICE_PATH_FULL)), + (UINT8)((sizeof (ACPI_EXTENDED_HID_DEVICE_PATH_FULL)) >> 8) + } + }, + 0, + 0, + 0, + }, + { 'P', 'N', 'P', 'B', '0', 'C', '0', '\0' }, // HIDSTR + { 'P', 'N', 'P', '0', '0', '0', '1', '\0' }, // CIDSTR + { 'U', 'I', 'D', '0', '0', '0', '0', '\0' } // UIDSTR +}; + +typedef struct { + ACPI_EXTENDED_HID_DEVICE_PATH AcpiEx; + CHAR8 HidStr[HID_STR_SIZE]; +} ACPI_EXTENDED_HID_DEVICE_PATH_PARTIAL; + +GLOBAL_REMOVE_IF_UNREFERENCED ACPI_EXTENDED_HID_DEVICE_PATH_PARTIAL mAcpiExtendedDevicePathPartial = +{ + { + { + ACPI_DEVICE_PATH, + ACPI_EXTENDED_DP, + { + (UINT8)(sizeof (ACPI_EXTENDED_HID_DEVICE_PATH_PARTIAL)), + (UINT8)((sizeof (ACPI_EXTENDED_HID_DEVICE_PATH_PARTIAL)) >> 8) + } + }, + 0, + 2, + 0, + }, + { 'P', 'N', 'P', 'B', '0', '\0', '\0', '\0' }, // HIDSTR +}; + +typedef struct { + ACPI_EXTENDED_HID_DEVICE_PATH AcpiEx; + CHAR8 UidStr[UID_STR_SIZE]; +} ACPI_EXPANDED_DEVICE_PATH; + +GLOBAL_REMOVE_IF_UNREFERENCED ACPI_EXPANDED_DEVICE_PATH mAcpiExpandedDevicePathUidOnly = +{ + { + { + ACPI_DEVICE_PATH, + ACPI_EXTENDED_DP, + { + (UINT8)(sizeof (ACPI_EXPANDED_DEVICE_PATH)), + (UINT8)((sizeof (ACPI_EXPANDED_DEVICE_PATH)) >> 8) + } + }, + EISA_PNP_ID (0xAAAA), + 0, + 0, + }, + { '\0', 'U', 'I', 'D', '0', '0', '\0', '\0' } // UIDSTR +}; + +GLOBAL_REMOVE_IF_UNREFERENCED ACPI_EXPANDED_DEVICE_PATH mAcpiExpandedDevicePathUidOnlyWithCid = +{ + { + { + ACPI_DEVICE_PATH, + ACPI_EXTENDED_DP, + { + (UINT8)(sizeof (ACPI_EXPANDED_DEVICE_PATH)), + (UINT8)((sizeof (ACPI_EXPANDED_DEVICE_PATH)) >> 8) + } + }, + EISA_PNP_ID (0xAAAA), + 0, + EISA_PNP_ID (0xAADD), + }, + { '\0', 'U', 'I', 'D', '0', '0', '\0', '\0' } // UIDSTR +}; + +GLOBAL_REMOVE_IF_UNREFERENCED DEVICE_PATH_CONVERSIONS_TEST_CONTEXT mDevPathNodeToFromTextContext[] = { + { + (EFI_DEVICE_PATH_PROTOCOL *)&mPciDevicePathNode, + L"Pci(0x0,0x2)" + }, + { + (EFI_DEVICE_PATH_PROTOCOL *)&mAcpiPciRootHidDevicePathNode, + L"PciRoot(0x0)" + }, + { + (EFI_DEVICE_PATH_PROTOCOL *)&mAcpiNonPciRootHidDevicePathNode, + L"Acpi(PNPB0C0,0x1)" + }, + { + (EFI_DEVICE_PATH_PROTOCOL *)&mAcpiExtendedDevicePathFull, + L"AcpiEx(@@@0000,@@@0000,0x0,PNPB0C0,UID0000,PNP0001)" + }, + { + (EFI_DEVICE_PATH_PROTOCOL *)&mAcpiExtendedDevicePathPartial, + L"AcpiEx(@@@0000,@@@0000,0x2,PNPB0,,)" + }, + { + (EFI_DEVICE_PATH_PROTOCOL *)&mAcpiExpandedDevicePathUidOnly, + L"AcpiExp(PNPAAAA,0,UID00)" + }, + { + (EFI_DEVICE_PATH_PROTOCOL *)&mAcpiExpandedDevicePathUidOnlyWithCid, + L"AcpiExp(PNPAAAA,PNPAADD,UID00)" + } +}; + +typedef struct { + ACPI_HID_DEVICE_PATH AcpiPath; + PCI_DEVICE_PATH PciPathRootPort; + PCI_DEVICE_PATH PciPathEndPoint; + USB_DEVICE_PATH UsbPath; + EFI_DEVICE_PATH_PROTOCOL End; +} TEST_CONVERSIONS_DEVICE_PATH; + +GLOBAL_REMOVE_IF_UNREFERENCED TEST_CONVERSIONS_DEVICE_PATH mConversionsDevicePath = { + { // ACPI device path with root bridge EISA_PNP_ID + { + ACPI_DEVICE_PATH, + ACPI_DP, + { + (UINT8)(sizeof (ACPI_HID_DEVICE_PATH)), + (UINT8)((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) + } + }, + EISA_PNP_ID (0x0A03), + 0 + }, + { // PCI device path - root port (0x2:0x0) + { + HARDWARE_DEVICE_PATH, + HW_PCI_DP, + { + (UINT8)(sizeof (PCI_DEVICE_PATH)), + (UINT8)((sizeof (PCI_DEVICE_PATH)) >> 8) + } + }, + 0x2, + 0x0 + }, + { // PCI device path - endpoint (0x0:0x0) + { + HARDWARE_DEVICE_PATH, + HW_PCI_DP, + { + (UINT8)(sizeof (PCI_DEVICE_PATH)), + (UINT8)((sizeof (PCI_DEVICE_PATH)) >> 8) + } + }, + 0x0, + 0x0 + }, + { // USB interface + { + MESSAGING_DEVICE_PATH, + MSG_USB_DP, + { + (UINT8)(sizeof (USB_DEVICE_PATH)), + (UINT8)((sizeof (USB_CLASS_DEVICE_PATH)) >> 8) + } + }, + 0, + 2 + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8)(sizeof (EFI_DEVICE_PATH_PROTOCOL)), + (UINT8)((sizeof (EFI_DEVICE_PATH_PROTOCOL)) >> 8) + } + } +}; + +GLOBAL_REMOVE_IF_UNREFERENCED DEVICE_PATH_CONVERSIONS_TEST_CONTEXT mDevPathToFromTextContext[] = { + { + (EFI_DEVICE_PATH_PROTOCOL *)&mConversionsDevicePath, + L"PciRoot(0x0)/Pci(0x0,0x2)/Pci(0x0,0x0)/USB(0x0,0x2)" + } +}; + +UNIT_TEST_STATUS +EFIAPI +TestConvertDevicePathToText ( + IN UNIT_TEST_CONTEXT Context + ) +{ + CHAR16 *DevPathString; + DEVICE_PATH_CONVERSIONS_TEST_CONTEXT *TestContext; + + TestContext = (DEVICE_PATH_CONVERSIONS_TEST_CONTEXT *)Context; + + DevPathString = ConvertDevicePathToText (TestContext->DevPath, FALSE, FALSE); + UT_ASSERT_EQUAL (StrLen (DevPathString), StrLen (TestContext->DevPathString)); + UT_ASSERT_MEM_EQUAL (DevPathString, TestContext->DevPathString, StrLen (TestContext->DevPathString)); + FreePool (DevPathString); + + return UNIT_TEST_PASSED; +} + +UNIT_TEST_STATUS +EFIAPI +TestConvertTextToDevicePath ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_DEVICE_PATH_PROTOCOL *ConvertedDevPath; + DEVICE_PATH_CONVERSIONS_TEST_CONTEXT *TestContext; + + TestContext = (DEVICE_PATH_CONVERSIONS_TEST_CONTEXT *)Context; + + ConvertedDevPath = ConvertTextToDevicePath (TestContext->DevPathString); + UT_ASSERT_EQUAL (GetDevicePathSize (ConvertedDevPath), GetDevicePathSize (TestContext->DevPath)); + UT_ASSERT_MEM_EQUAL (ConvertedDevPath, TestContext->DevPath, GetDevicePathSize (TestContext->DevPath)); + FreePool (ConvertedDevPath); + + return UNIT_TEST_PASSED; +} + +UNIT_TEST_STATUS +EFIAPI +TestConvertDeviceNodeToText ( + IN UNIT_TEST_CONTEXT Context + ) +{ + CHAR16 *DevPathNodeString; + DEVICE_PATH_CONVERSIONS_TEST_CONTEXT *TestContext; + + TestContext = (DEVICE_PATH_CONVERSIONS_TEST_CONTEXT *)Context; + + DevPathNodeString = ConvertDeviceNodeToText (TestContext->DevPath, FALSE, FALSE); + UT_ASSERT_EQUAL (StrLen (DevPathNodeString), StrLen (TestContext->DevPathString)); + UT_ASSERT_MEM_EQUAL (DevPathNodeString, TestContext->DevPathString, StrLen (TestContext->DevPathString)); + FreePool (DevPathNodeString); + + return UNIT_TEST_PASSED; +} + +UNIT_TEST_STATUS +EFIAPI +TestConvertTextToDeviceNode ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevPath; + DEVICE_PATH_CONVERSIONS_TEST_CONTEXT *TestContext; + + TestContext = (DEVICE_PATH_CONVERSIONS_TEST_CONTEXT *)Context; + + DevPath = ConvertTextToDeviceNode (TestContext->DevPathString); + UT_ASSERT_EQUAL (DevicePathNodeLength (DevPath), DevicePathNodeLength (TestContext->DevPath)); + UT_ASSERT_MEM_EQUAL (DevPath, TestContext->DevPath, DevicePathNodeLength (TestContext->DevPath)); + FreePool (DevPath); + + return UNIT_TEST_PASSED; +} + +EFI_STATUS +CreateDevicePathStringConversionsTestSuite ( + IN UNIT_TEST_FRAMEWORK_HANDLE Framework + ) +{ + EFI_STATUS Status; + UNIT_TEST_SUITE_HANDLE DevicePathTextConversionSuite = NULL; + UINTN Index; + + Status = CreateUnitTestSuite (&DevicePathTextConversionSuite, Framework, "Device path text conversion operations test suite", "Common.DevicePath.TextConversions", NULL, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed to create device path text conversions test suite\n")); + return Status; + } + + for (Index = 0; Index < ARRAY_SIZE (mDevPathNodeToFromTextContext); Index++) { + AddTestCase (DevicePathTextConversionSuite, "Test ConvertDeviceNodeToText", "TestConvertDeviceNodeToText", TestConvertDeviceNodeToText, NULL, NULL, &mDevPathNodeToFromTextContext[Index]); + } + + for (Index = 0; Index < ARRAY_SIZE (mDevPathNodeToFromTextContext); Index++) { + AddTestCase (DevicePathTextConversionSuite, "Test ConvertTextToDeviceNode", "TestConvertTextToDeviceNode", TestConvertTextToDeviceNode, NULL, NULL, &mDevPathNodeToFromTextContext[Index]); + } + + for (Index = 0; Index < ARRAY_SIZE (mDevPathToFromTextContext); Index++) { + AddTestCase (DevicePathTextConversionSuite, "Test ConvertDevicePathToText", "TestConvertDevicePathToText", TestConvertDevicePathToText, NULL, NULL, &mDevPathToFromTextContext[Index]); + } + + for (Index = 0; Index < ARRAY_SIZE (mDevPathToFromTextContext); Index++) { + AddTestCase (DevicePathTextConversionSuite, "Test ConvertTextToDevicePath", "TestConvertTextToDevicePath", TestConvertTextToDevicePath, NULL, NULL, &mDevPathToFromTextContext[Index]); + } + + return EFI_SUCCESS; +}