From nobody Fri May 17 11:58:47 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+109125+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+109125+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1695829907; cv=none; d=zohomail.com; s=zohoarc; b=S4rqLa82Hphv7hBDhM14UcIuEjcXYLQ0d1+jg3TqwL7nHYPoQop3iN13lP45lc/x2TSuMQ4MOl2RQFCcgxpSFsTpkVhTpsVeRIkD2t0qRLGA68TeiavK+7xpLhOcYtbu3dIcV+DqLklknFCav6XCTPMLAkkN9U0QKPQDWcrB4Fk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1695829907; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=NSlNoQPgqMYrLJi9Mi81RmJz8TPVtcP8qDNUKDZw61w=; b=jCeLQ30bWmVPugJ8MMmbxgJXTXajpNjM0QNWVyRj+gfIsobCwzI/Uzht1e26/MCWd0zHGodBSPJNTHq3x7aQuq4a9oJb6UJQHKtEjVOCoiKj/AxDmn8gWbigd90iDFBSjD9XQhPmdpuC8Euf/FFYQMuHPjZK9sUEUGu0hb4bzFk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+109125+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 169582990746852.41571684776784; Wed, 27 Sep 2023 08:51:47 -0700 (PDT) Return-Path: DKIM-Signature: a=rsa-sha256; bh=k/MhiY8f+m4d1waqIXYBP04ntUJnqIZ5on+4lwtRV4E=; c=relaxed/simple; d=groups.io; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References:MIME-Version:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Type:Content-Transfer-Encoding; s=20140610; t=1695829907; v=1; b=Y50vUadTFRa2hbA2PT6Vum1PgI51zL+VbgrQzjqHg4qCFrxgZJdGnKPAT8chCzZ50weSM3Zo sh8KVQu1EOT7MVcWZdQ/LpYM6IE6vvXEiA2tCB2CVA+Ikfh/N42QlhsOCGQDuZ7niW6voivEWUY /qhqukxRX5p4jODFbtD7GpZI= X-Received: by 127.0.0.2 with SMTP id G1UsYY1788612xECllAqPeEs; Wed, 27 Sep 2023 08:51:47 -0700 X-Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.20]) by mx.groups.io with SMTP id smtpd.web11.21111.1695829902320589544 for ; Wed, 27 Sep 2023 08:51:46 -0700 X-IronPort-AV: E=McAfee;i="6600,9927,10846"; a="372206108" X-IronPort-AV: E=Sophos;i="6.03,181,1694761200"; d="scan'208";a="372206108" X-Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Sep 2023 08:51:46 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10846"; a="752641419" X-IronPort-AV: E=Sophos;i="6.03,181,1694761200"; d="scan'208";a="752641419" X-Received: from kjurczyk-mobl1.ger.corp.intel.com (HELO malbecki-mobl2.intel.com) ([10.213.9.18]) by fmsmga007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Sep 2023 08:51:44 -0700 From: "Albecki, Mateusz" To: devel@edk2.groups.io Cc: Mateusz Albecki , Michael D Kinney , Liming Gao , Zhiguang Liu Subject: [edk2-devel] [PATCHv2 1/2] MdePkg/UefiDevicePathLib: Fix AcpiEx print logic Date: Wed, 27 Sep 2023 17:51:22 +0200 Message-Id: <20230927155123.1465365-2-mateusz.albecki@intel.com> In-Reply-To: <20230927155123.1465365-1-mateusz.albecki@intel.com> References: <20230927155123.1465365-1-mateusz.albecki@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,mateusz.albecki@intel.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: Qbz2kqooY6hUo7SpknM5NpIox1787277AA= Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1695829909339100003 Content-Type: text/plain; charset="utf-8" BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4555 Add logic that checks if the code doesn't overflow ACPI_EXTENDED_HID_DEVICE_PATH node when searching for optional strings. If the string is not provided in the device path node default value of "\0" is used. Cc: Michael D Kinney Cc: Liming Gao Cc: Zhiguang Liu Signed-off-by: Mateusz Albecki Reviewed-by: Michael D Kinney --- .../UefiDevicePathLib/DevicePathToText.c | 69 +++++++++++-------- 1 file changed, 42 insertions(+), 27 deletions(-) diff --git a/MdePkg/Library/UefiDevicePathLib/DevicePathToText.c b/MdePkg/L= ibrary/UefiDevicePathLib/DevicePathToText.c index dd90dfa58e..bd8d1de201 100644 --- a/MdePkg/Library/UefiDevicePathLib/DevicePathToText.c +++ b/MdePkg/Library/UefiDevicePathLib/DevicePathToText.c @@ -418,23 +418,38 @@ DevPathToTextAcpiEx ( ) { ACPI_EXTENDED_HID_DEVICE_PATH *AcpiEx; - CHAR8 *HIDStr; - CHAR8 *UIDStr; - CHAR8 *CIDStr; CHAR16 HIDText[11]; CHAR16 CIDText[11]; - - AcpiEx =3D DevPath; - HIDStr =3D (CHAR8 *)(((UINT8 *)AcpiEx) + sizeof (ACPI_EXTENDED_HID_DEVIC= E_PATH)); - UIDStr =3D HIDStr + AsciiStrLen (HIDStr) + 1; - CIDStr =3D UIDStr + AsciiStrLen (UIDStr) + 1; + UINTN CurrentLength; + CHAR8 *CurrentPos; + UINTN NextStringOffset; + CHAR8 *Strings[3]; + CONST UINT8 HidStrIndex =3D 0; + CONST UINT8 UidStrIndex =3D 1; + CONST UINT8 CidStrIndex =3D 2; + UINT8 StrIndex; + + AcpiEx =3D DevPath; + Strings[HidStrIndex] =3D NULL; + Strings[UidStrIndex] =3D NULL; + Strings[CidStrIndex] =3D NULL; + CurrentLength =3D sizeof (ACPI_EXTENDED_HID_DEVICE_PATH); + CurrentPos =3D (CHAR8 *)(((UINT8 *)AcpiEx) + sizeof (ACPI_EXTE= NDED_HID_DEVICE_PATH)); + StrIndex =3D 0; + while (CurrentLength < AcpiEx->Header.Length[0] && StrIndex < ARRAY_SIZE= (Strings)) { + Strings[StrIndex] =3D CurrentPos; + NextStringOffset =3D AsciiStrLen (CurrentPos) + 1; + CurrentLength +=3D NextStringOffset; + CurrentPos +=3D NextStringOffset; + StrIndex++; + } =20 if (DisplayOnly) { if ((EISA_ID_TO_NUM (AcpiEx->HID) =3D=3D 0x0A03) || ((EISA_ID_TO_NUM (AcpiEx->CID) =3D=3D 0x0A03) && (EISA_ID_TO_NUM (= AcpiEx->HID) !=3D 0x0A08))) { - if (AcpiEx->UID =3D=3D 0) { - UefiDevicePathLibCatPrint (Str, L"PciRoot(%a)", UIDStr); + if (Strings[UidStrIndex] !=3D NULL) { + UefiDevicePathLibCatPrint (Str, L"PciRoot(%a)", Strings[UidStrInde= x]); } else { UefiDevicePathLibCatPrint (Str, L"PciRoot(0x%x)", AcpiEx->UID); } @@ -443,8 +458,8 @@ DevPathToTextAcpiEx ( } =20 if ((EISA_ID_TO_NUM (AcpiEx->HID) =3D=3D 0x0A08) || (EISA_ID_TO_NUM (A= cpiEx->CID) =3D=3D 0x0A08)) { - if (AcpiEx->UID =3D=3D 0) { - UefiDevicePathLibCatPrint (Str, L"PcieRoot(%a)", UIDStr); + if (Strings[UidStrIndex] !=3D NULL) { + UefiDevicePathLibCatPrint (Str, L"PcieRoot(%a)", Strings[UidStrInd= ex]); } else { UefiDevicePathLibCatPrint (Str, L"PcieRoot(0x%x)", AcpiEx->UID); } @@ -475,7 +490,10 @@ DevPathToTextAcpiEx ( (AcpiEx->CID >> 16) & 0xFFFF ); =20 - if ((*HIDStr =3D=3D '\0') && (*CIDStr =3D=3D '\0') && (*UIDStr !=3D '\0'= )) { + if (((Strings[HidStrIndex] !=3D NULL) && (*Strings[HidStrIndex] =3D=3D '= \0')) && + ((Strings[CidStrIndex] !=3D NULL) && (*Strings[CidStrIndex] =3D=3D '= \0')) && + ((Strings[UidStrIndex] !=3D NULL) && (*Strings[UidStrIndex] !=3D '\0= '))) + { // // use AcpiExp() // @@ -484,7 +502,7 @@ DevPathToTextAcpiEx ( Str, L"AcpiExp(%s,0,%a)", HIDText, - UIDStr + Strings[UidStrIndex] ); } else { UefiDevicePathLibCatPrint ( @@ -492,28 +510,25 @@ DevPathToTextAcpiEx ( L"AcpiExp(%s,%s,%a)", HIDText, CIDText, - UIDStr + Strings[UidStrIndex] ); } } else { if (DisplayOnly) { - // - // display only - // - if (AcpiEx->HID =3D=3D 0) { - UefiDevicePathLibCatPrint (Str, L"AcpiEx(%a,", HIDStr); + if (Strings[HidStrIndex] !=3D NULL) { + UefiDevicePathLibCatPrint (Str, L"AcpiEx(%a,", Strings[HidStrIndex= ]); } else { UefiDevicePathLibCatPrint (Str, L"AcpiEx(%s,", HIDText); } =20 - if (AcpiEx->CID =3D=3D 0) { - UefiDevicePathLibCatPrint (Str, L"%a,", CIDStr); + if (Strings[CidStrIndex] !=3D NULL) { + UefiDevicePathLibCatPrint (Str, L"%a,", Strings[CidStrIndex]); } else { UefiDevicePathLibCatPrint (Str, L"%s,", CIDText); } =20 - if (AcpiEx->UID =3D=3D 0) { - UefiDevicePathLibCatPrint (Str, L"%a)", UIDStr); + if (Strings[UidStrIndex] !=3D NULL) { + UefiDevicePathLibCatPrint (Str, L"%a)", Strings[UidStrIndex]); } else { UefiDevicePathLibCatPrint (Str, L"0x%x)", AcpiEx->UID); } @@ -524,9 +539,9 @@ DevPathToTextAcpiEx ( HIDText, CIDText, AcpiEx->UID, - HIDStr, - CIDStr, - UIDStr + Strings[HidStrIndex] !=3D NULL ? Strings[HidStrIndex] : '\0', + Strings[CidStrIndex] !=3D NULL ? Strings[CidStrIndex] : '\0', + Strings[UidStrIndex] !=3D NULL ? Strings[UidStrIndex] : '\0' ); } } --=20 2.39.2 --------------------------------------------------------------------- Intel Technology Poland sp. z o.o. ul. Slowackiego 173 | 80-298 Gdansk | Sad Rejonowy Gdansk Polnoc | VII Wydz= ial Gospodarczy Krajowego Rejestru Sadowego - KRS 101882 | NIP 957-07-52-31= 6 | Kapital zakladowy 200.000 PLN. Spolka oswiadcza, ze posiada status duzego przedsiebiorcy w rozumieniu usta= wy z dnia 8 marca 2013 r. o przeciwdzialaniu nadmiernym opoznieniom w trans= akcjach handlowych. Ta wiadomosc wraz z zalacznikami jest przeznaczona dla okreslonego adresata= i moze zawierac informacje poufne. W razie przypadkowego otrzymania tej wi= adomosci, prosimy o powiadomienie nadawcy oraz trwale jej usuniecie; jakiek= olwiek przegladanie lub rozpowszechnianie jest zabronione. This e-mail and any attachments may contain confidential material for the s= ole use of the intended recipient(s). If you are not the intended recipient= , please contact the sender and delete all copies; any review or distributi= on by others is strictly prohibited. -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#109125): https://edk2.groups.io/g/devel/message/109125 Mute This Topic: https://groups.io/mt/101619978/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Fri May 17 11:58:47 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+109126+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+109126+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1695829914; cv=none; d=zohomail.com; s=zohoarc; b=ZRFpEAh1M3FPdmp8OjZ6H6lG6MDSC1b83pZBft1O/SY2RZxL8BOt4jaWaXUK1p/O+B7xl5b33e5kXnAf1pdwUPAb7KpP5JM1OwCWEpsAswwO26KdVN0RJYmQL1e2ikHosoes64BCOn+FFjKyQM57DO6hvwqrpGsfChTd9bBMlnA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1695829914; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=2EaYxz6x+aTUe1r5TCvi16c+cq4GmBNFeV4pGoUNqx0=; b=ITmDC8W1baTH2iX/xlWbXzZdDlR0mVqxOJ4FKwylqDylYp5rnmEFRw9gIkBr4bgYOsGnc/jyrZt+Y4qeFCTROrV0xeK2Dj52OqZopr6CMUlLv7l6Jujjacrl9DldP2dL2hKoQgqUYGyVMdsgzR4HF9f/5s5OGPgjqQcKEmeYvzE= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+109126+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1695829914405907.3092923422053; Wed, 27 Sep 2023 08:51:54 -0700 (PDT) Return-Path: DKIM-Signature: a=rsa-sha256; bh=N1dnuU7+8KpbTWQPUtsrD2oLZdDs1cpuDrcbzzoDJgU=; c=relaxed/simple; d=groups.io; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References:MIME-Version:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Type:Content-Transfer-Encoding; s=20140610; t=1695829914; v=1; b=YGZvo06/LmZ5rsUcyhJjNB6Iw8FLRdEBTiYCAvzBhC/cYTcX+K3e7Y6t+7HTF5yclxYs+Gin JfCnm+r4w4g80X3IQEPuoO88jSMBqWNL6BY3lQ/g5CHI7kJB/1vZkhARNjhLSLqcOyALz2DAEPv 78fQUGJPyaklcvigeffYZ+oI= X-Received: by 127.0.0.2 with SMTP id M38FYY1788612xFsPyENtp3K; Wed, 27 Sep 2023 08:51:54 -0700 X-Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.20]) by mx.groups.io with SMTP id smtpd.web10.20755.1695829913165487046 for ; Wed, 27 Sep 2023 08:51:53 -0700 X-IronPort-AV: E=McAfee;i="6600,9927,10846"; a="372206134" X-IronPort-AV: E=Sophos;i="6.03,181,1694761200"; d="scan'208";a="372206134" X-Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Sep 2023 08:51:52 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10846"; a="752641430" X-IronPort-AV: E=Sophos;i="6.03,181,1694761200"; d="scan'208";a="752641430" X-Received: from kjurczyk-mobl1.ger.corp.intel.com (HELO malbecki-mobl2.intel.com) ([10.213.9.18]) by fmsmga007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Sep 2023 08:51:50 -0700 From: "Albecki, Mateusz" To: devel@edk2.groups.io Cc: Mateusz Albecki , Michael D Kinney , Liming Gao , Zhiguang Liu Subject: [edk2-devel] [PATCHv2 2/2] MdePkg/Test: Add DevicePathLib host test module Date: Wed, 27 Sep 2023 17:51:23 +0200 Message-Id: <20230927155123.1465365-3-mateusz.albecki@intel.com> In-Reply-To: <20230927155123.1465365-1-mateusz.albecki@intel.com> References: <20230927155123.1465365-1-mateusz.albecki@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,mateusz.albecki@intel.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: mvYeacTjdGGSVZGkBiyR0qLLx1787277AA= Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1695829916388100003 Content-Type: text/plain; charset="utf-8" This commit adds host-based unit tests for device path lib. Cc: Michael D Kinney Cc: Liming Gao Cc: Zhiguang Liu Signed-off-by: Mateusz Albecki Reviewed-by: Michael D Kinney --- MdePkg/MdePkg.ci.yaml | 5 +- MdePkg/Test/MdePkgHostTest.dsc | 2 + .../Library/DevicePathLib/TestDevicePathLib.c | 638 ++++++++++++++++++ .../Library/DevicePathLib/TestDevicePathLib.h | 26 + .../DevicePathLib/TestDevicePathLibHost.inf | 33 + .../TestDevicePathStringConversions.c | 370 ++++++++++ 6 files changed, 1073 insertions(+), 1 deletion(-) create mode 100644 MdePkg/Test/UnitTest/Library/DevicePathLib/TestDevicePa= thLib.c create mode 100644 MdePkg/Test/UnitTest/Library/DevicePathLib/TestDevicePa= thLib.h create mode 100644 MdePkg/Test/UnitTest/Library/DevicePathLib/TestDevicePa= thLibHost.inf create mode 100644 MdePkg/Test/UnitTest/Library/DevicePathLib/TestDevicePa= thStringConversions.c 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/TestDevicePathStringConve= rsions.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 @@ =20 [LibraryClasses] SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibBase.inf =20 [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.i= nf + MdePkg/Test/UnitTest/Library/DevicePathLib/TestDevicePathLibHost.inf =20 # # 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= =3D { + { // 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 =3D = L"PciRoot(0x0)/Pci(0x0,0x2)/Pci(0x0,0x0)/USB(0x0,0x2)"; + +CONST GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mPciEndPointPathString =3D 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 = =3D { + { // 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 mInvalidSimpleDevic= ePath =3D { + { // 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 =3D (SIMPLE_TEST_SUITE_CONTEXT *)Context; + + IsValid =3D IsDevicePathValid ((EFI_DEVICE_PATH_PROTOCOL *)TestContext->= SimpleDevicePath, sizeof (TEST_SIMPLE_DEVICE_PATH)); + UT_ASSERT_TRUE (IsValid); + + IsValid =3D IsDevicePathValid ((EFI_DEVICE_PATH_PROTOCOL *)TestContext->= ComplexDevicePath, sizeof (TEST_COMPLEX_DEVICE_PATH)); + UT_ASSERT_TRUE (IsValid); + + IsValid =3D IsDevicePathValid ((EFI_DEVICE_PATH_PROTOCOL *)TestContext->= ComplexDevicePath, 0); + UT_ASSERT_TRUE (IsValid); + + // Device path can't be NULL + IsValid =3D IsDevicePathValid (NULL, 0); + UT_ASSERT_FALSE (IsValid); + + // MaxSize can't be less then the size of the device path + IsValid =3D IsDevicePathValid ((EFI_DEVICE_PATH_PROTOCOL *)TestContext->= SimpleDevicePath, sizeof (TEST_SIMPLE_DEVICE_PATH) - 1); + UT_ASSERT_FALSE (IsValid); + + // If MaxSize !=3D 0 it must be bigger then EFI_DEVICE_PATH_PROTOCOL + IsValid =3D IsDevicePathValid ((EFI_DEVICE_PATH_PROTOCOL *)TestContext->= SimpleDevicePath, sizeof (EFI_DEVICE_PATH_PROTOCOL) - 1); + UT_ASSERT_FALSE (IsValid); + + IsValid =3D 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 =3D (SIMPLE_TEST_SUITE_CONTEXT *)Context; + + // Test 2 types just in case the implementation is returning constant va= lue + // NOTE: passing NULL to this function causes NULL pointer dereference. + Type =3D DevicePathType (&TestContext->ComplexDevicePath->AcpiPath); + UT_ASSERT_EQUAL (Type, ACPI_DEVICE_PATH); + + Type =3D DevicePathType (&TestContext->ComplexDevicePath->PciPathRootPor= t); + 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 =3D (SIMPLE_TEST_SUITE_CONTEXT *)Context; + + // Test 2 sub types just in case the implementation is returning constan= t value + // NOTE: passing NULL to this function causes NULL pointer dereference. + SubType =3D DevicePathSubType (&TestContext->ComplexDevicePath->AcpiPath= ); + UT_ASSERT_EQUAL (SubType, ACPI_DP); + + SubType =3D DevicePathSubType (&TestContext->ComplexDevicePath->PciPathR= ootPort); + 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 =3D (SIMPLE_TEST_SUITE_CONTEXT *)Context; + + // Test 2 nodes just in case the implementation is returning constant va= lue + // NOTE: passing NULL to this function causes NULL pointer dereference. + Length =3D DevicePathNodeLength (&TestContext->ComplexDevicePath->AcpiPa= th); + UT_ASSERT_EQUAL (Length, sizeof (ACPI_HID_DEVICE_PATH)); + + Length =3D DevicePathNodeLength (&TestContext->ComplexDevicePath->PciPat= hRootPort); + 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 =3D (SIMPLE_TEST_SUITE_CONTEXT *)Context; + + Node =3D &mComplexDevicePath; + Node =3D NextDevicePathNode (Node); + UT_ASSERT_MEM_EQUAL (Node, &TestContext->ComplexDevicePath->PciPathRootP= ort, DevicePathNodeLength (Node)); + + Node =3D NextDevicePathNode (Node); + UT_ASSERT_MEM_EQUAL (Node, &TestContext->ComplexDevicePath->PciPathEndPo= int, DevicePathNodeLength (Node)); + + return UNIT_TEST_PASSED; +} + +UNIT_TEST_STATUS +EFIAPI +TestIsDevicePathEndType ( + IN UNIT_TEST_CONTEXT Context + ) +{ + BOOLEAN IsEndType; + SIMPLE_TEST_SUITE_CONTEXT *TestContext; + + TestContext =3D (SIMPLE_TEST_SUITE_CONTEXT *)Context; + + IsEndType =3D IsDevicePathEndType (&TestContext->ComplexDevicePath->PciP= athRootPort); + UT_ASSERT_FALSE (IsEndType); + + IsEndType =3D 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 =3D (SIMPLE_TEST_SUITE_CONTEXT *)Context; + + IsEnd =3D IsDevicePathEnd (&TestContext->ComplexDevicePath->PciPathRootP= ort); + UT_ASSERT_FALSE (IsEnd); + + IsEnd =3D 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 =3D=3D NULL or NodeLength >=3D 0x10000 NodeLength < sizeof= (EFI_DEVICE_PATH_PROTOCOL) + // are all invalid parameters. However there are only ASSERTS added to c= atch them so there is no + // way to test it. + SetDevicePathNodeLength (&DevPath, sizeof (EFI_DEVICE_PATH_PROTOCOL)); + UT_ASSERT_EQUAL (DevicePathNodeLength (&DevPath), sizeof (EFI_DEVICE_PAT= H_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 =3D (SIMPLE_TEST_SUITE_CONTEXT *)Context; + + Size =3D GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)TestContext->Sim= pleDevicePath); + UT_ASSERT_EQUAL (Size, sizeof (TEST_SIMPLE_DEVICE_PATH)); + + Size =3D GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)TestContext->Com= plexDevicePath); + 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 =3D (SIMPLE_TEST_SUITE_CONTEXT *)Context; + + Duplicate =3D DuplicateDevicePath ((EFI_DEVICE_PATH_PROTOCOL *)TestConte= xt->ComplexDevicePath); + UT_ASSERT_EQUAL (GetDevicePathSize (Duplicate), GetDevicePathSize ((EFI_= DEVICE_PATH_PROTOCOL *)TestContext->ComplexDevicePath)); + UT_ASSERT_MEM_EQUAL (Duplicate, TestContext->ComplexDevicePath, GetDevic= ePathSize ((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 =3D AppendDevicePath ((EFI_DEVICE_PATH_PROTOCOL *)&mSimpleDevic= ePath, (EFI_DEVICE_PATH_PROTOCOL *)&mComplexDevicePath); + NextNode =3D 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 =3D AppendDevicePath ((EFI_DEVICE_PATH_PROTOCOL *)&mSimpleDevic= ePath, (EFI_DEVICE_PATH_PROTOCOL *)&mInvalidSimpleDevicePath); + UT_ASSERT_EQUAL ((uintptr_t)Appended, (uintptr_t)NULL); + + Appended =3D 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 =3D + { + { + ACPI_DEVICE_PATH, + ACPI_DP, + { + (UINT8)(sizeof (ACPI_HID_DEVICE_PATH)), + (UINT8)((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) + } + }, + EISA_PNP_ID (0x0AAB), + 0 + }; + + Appended =3D AppendDevicePathNode ((EFI_DEVICE_PATH_PROTOCOL *)&mSimpleD= evicePath, (EFI_DEVICE_PATH_PROTOCOL *)&AcpiPath); + NextNode =3D NextDevicePathNode (Appended); + UT_ASSERT_MEM_EQUAL (NextNode, &AcpiPath, sizeof (ACPI_HID_DEVICE_PATH)); + FreePool (Appended); + + Appended =3D AppendDevicePathNode (NULL, (EFI_DEVICE_PATH_PROTOCOL *)&Ac= piPath); + UT_ASSERT_MEM_EQUAL (Appended, &AcpiPath, sizeof (ACPI_HID_DEVICE_PATH)); + IsValid =3D IsDevicePathValid (Appended, 0); + UT_ASSERT_TRUE (IsValid); + FreePool (Appended); + + Appended =3D 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 =3D AppendDevicePathInstance ((EFI_DEVICE_PATH_PROTOCOL = *)&mSimpleDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&mComplexDevicePath); + IsMultiInstance =3D IsDevicePathMultiInstance (Appended); + UT_ASSERT_TRUE (IsMultiInstance); + UT_ASSERT_MEM_EQUAL (Appended, &mSimpleDevicePath, sizeof (ACPI_DEVICE_P= ATH)); + NextInstance =3D Appended; + NextInstanceRet =3D GetNextDevicePathInstance (&NextInstance, &Size); + UT_ASSERT_MEM_EQUAL (NextInstance, &mComplexDevicePath, Size); + FreePool (Appended); + FreePool (NextInstanceRet); + + Appended =3D AppendDevicePathInstance (NULL, (EFI_DEVICE_PATH_PROTOCOL *= )&mSimpleDevicePath); + UT_ASSERT_MEM_EQUAL (Appended, &mSimpleDevicePath, sizeof (TEST_SIMPLE_D= EVICE_PATH)); + FreePool (Appended); + + Appended =3D AppendDevicePathInstance (NULL, NULL); + UT_ASSERT_EQUAL ((uintptr_t)Appended, (uintptr_t)NULL); + FreePool (Appended); + + Appended =3D AppendDevicePathInstance ((EFI_DEVICE_PATH_PROTOCOL *)&mSim= pleDevicePath, (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 =3D NULL; + DevicePath =3D DevicePathFromHandle (Handle); + UT_ASSERT_EQUAL ((uintptr_t)DevicePath, (uintptr_t)NULL); + + Handle =3D (EFI_HANDLE)&FakeHandle; + DevicePath =3D 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 =3D CreateDeviceNode (HARDWARE_DEVICE_PATH, HW_PCI_DP, sizeof (P= CI_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 =3D L"FS0:/Boot/EFI/BootMgr.efi"; + + Handle =3D NULL; + DevicePath =3D (FILEPATH_DEVICE_PATH *)FileDevicePath (Handle, TestFileP= ath); + 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 (TestFi= lePath)); + + 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 =3D NULL; + DevicePathSimpleTestSuite =3D NULL; + DevicePathAppendTestSuite =3D NULL; + DevicePathFileTestSuite =3D NULL; + + Status =3D InitUnitTestFramework (&Framework, UNIT_TEST_NAME, gEfiCaller= BaseName, UNIT_TEST_VERSION); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status =3D %r\n= ", Status)); + goto EXIT; + } + + Status =3D CreateUnitTestSuite (&DevicePathSimpleTestSuite, Framework, "= Simple device path operations test suite", "Common.DevicePath.SimpleOps", N= ULL, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed to create simple device path test suite\n= ")); + goto EXIT; + } + + SimpleTestContext.SimpleDevicePath =3D &mSimpleDevicePath; + SimpleTestContext.InvalidDevicePath =3D &mInvalidSimpleDevicePath; + SimpleTestContext.ComplexDevicePath =3D &mComplexDevicePath; + + AddTestCase (DevicePathSimpleTestSuite, "Test IsDevicePathValid", "TestI= sDevicePathValid", TestIsDevicePathValid, NULL, NULL, &SimpleTestContext); + AddTestCase (DevicePathSimpleTestSuite, "Test DevicePathType", "TestDevi= cePathType", TestDevicePathType, NULL, NULL, &SimpleTestContext); + AddTestCase (DevicePathSimpleTestSuite, "Test DevicePathSubType", "TestD= evicePathSubType", TestDevicePathSubType, NULL, NULL, &SimpleTestContext); + AddTestCase (DevicePathSimpleTestSuite, "Test DevicePathNodeLength", "Te= stDevicePathNodeLength", TestDevicePathNodeLength, NULL, NULL, &SimpleTestC= ontext); + AddTestCase (DevicePathSimpleTestSuite, "Test NextDevicePathNode", "Test= NextDevicePathNode", TestNextDevicePathNode, NULL, NULL, &SimpleTestContext= ); + AddTestCase (DevicePathSimpleTestSuite, "Test IsDevicePathEndType", "Tes= tIsDevicePathEndType", TestIsDevicePathEndType, NULL, NULL, &SimpleTestCont= ext); + AddTestCase (DevicePathSimpleTestSuite, "Test IsDevicePathEnd", "TestIsD= evicePathEnd", TestIsDevicePathEnd, NULL, NULL, &SimpleTestContext); + AddTestCase (DevicePathSimpleTestSuite, "Test SetDevicePathNodeLength", = "TestSetDevicePathNodeLength", TestSetDevicePathNodeLength, NULL, NULL, &Si= mpleTestContext); + AddTestCase (DevicePathSimpleTestSuite, "Test GetDevicePathSize", "TestG= etDevicePathSize", TestGetDevicePathSize, NULL, NULL, &SimpleTestContext); + AddTestCase (DevicePathSimpleTestSuite, "Test CreateDeviceNode", "TestCr= eateDeviceNode", TestCreateDeviceNode, NULL, NULL, &SimpleTestContext); + AddTestCase (DevicePathSimpleTestSuite, "Test SetDevicePathEndNode", "Te= stSetDevicePathEndNode", TestSetDevicePathEndNode, NULL, NULL, &SimpleTestC= ontext); + AddTestCase (DevicePathAppendTestSuite, "Test DuplicateDevicePath", "Tes= tDuplicateDevicePath", TestDuplicateDevicePath, NULL, NULL, &SimpleTestCont= ext); + + Status =3D 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", "TestAp= pendDevicePath", TestAppendDevicePath, NULL, NULL, NULL); + AddTestCase (DevicePathAppendTestSuite, "Test AppendDevicePathNode", "Te= stAppendDevicePathNode", TestAppendDevicePathNode, NULL, NULL, NULL); + AddTestCase (DevicePathAppendTestSuite, "Test AppendDevicePathInstance",= "TestAppendDevicePathInstance", TestAppendDevicePathInstance, NULL, NULL, = NULL); + + Status =3D CreateDevicePathStringConversionsTestSuite (Framework); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed to create conversions test suite\n")); + goto EXIT; + } + + Status =3D CreateUnitTestSuite (&DevicePathFileTestSuite, Framework, "De= vice path file operations test suite", "Common.DevicePath.FileDevPath", NUL= L, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed to create device path file test suite\n")= ); + goto EXIT; + } + + AddTestCase (DevicePathFileTestSuite, "Test DevicePathFromHandle", "Test= DevicePathFromHandle", TestDevicePathFromHandle, NULL, NULL, NULL); + AddTestCase (DevicePathFileTestSuite, "Test FileDevicePath", "TestFileDe= vicePath", TestFileDevicePath, NULL, NULL, NULL); + + Status =3D RunAllTestSuites (Framework); + +EXIT: + if (Framework !=3D 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/TestDevicePathLibHo= st.inf b/MdePkg/Test/UnitTest/Library/DevicePathLib/TestDevicePathLibHost.i= nf 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 =3D 0x00010005 + BASE_NAME =3D TestDevicePathLibHost + MODULE_UNI_FILE =3D TestDevicePathLib.uni + FILE_GUID =3D F1505A0E-D71F-4431-99BE-736776842E38 + MODULE_TYPE =3D HOST_APPLICATION + VERSION_STRING =3D 1.0 + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 +# + +[Sources] + TestDevicePathLib.c + TestDevicePathStringConversions.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + DebugLib + DevicePathLib + UnitTestLib diff --git a/MdePkg/Test/UnitTest/Library/DevicePathLib/TestDevicePathStrin= gConversions.c b/MdePkg/Test/UnitTest/Library/DevicePathLib/TestDevicePathS= tringConversions.c new file mode 100644 index 0000000000..4ea25ec142 --- /dev/null +++ b/MdePkg/Test/UnitTest/Library/DevicePathLib/TestDevicePathStringConver= sions.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 =3D +{ + // 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 mAcpiPciRootHidDeviceP= athNode =3D +{ + // 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 mAcpiNonPciRootHidDevi= cePathNode =3D +{ + // 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 mAcpiExt= endedDevicePathFull =3D +{ + // 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 mAcpi= ExtendedDevicePathPartial =3D +{ + { + { + 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 mAcpiExpandedDevi= cePathUidOnly =3D +{ + { + { + 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 mAcpiExpandedDevi= cePathUidOnlyWithCid =3D +{ + { + { + 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 mDevPa= thNodeToFromTextContext[] =3D { + { + (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 mConversionsDe= vicePath =3D { + { // 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 mDevPa= thToFromTextContext[] =3D { + { + (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 =3D (DEVICE_PATH_CONVERSIONS_TEST_CONTEXT *)Context; + + DevPathString =3D ConvertDevicePathToText (TestContext->DevPath, FALSE, = FALSE); + UT_ASSERT_EQUAL (StrLen (DevPathString), StrLen (TestContext->DevPathStr= ing)); + 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 =3D (DEVICE_PATH_CONVERSIONS_TEST_CONTEXT *)Context; + + ConvertedDevPath =3D ConvertTextToDevicePath (TestContext->DevPathString= ); + UT_ASSERT_EQUAL (GetDevicePathSize (ConvertedDevPath), GetDevicePathSize= (TestContext->DevPath)); + UT_ASSERT_MEM_EQUAL (ConvertedDevPath, TestContext->DevPath, GetDevicePa= thSize (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 =3D (DEVICE_PATH_CONVERSIONS_TEST_CONTEXT *)Context; + + DevPathNodeString =3D ConvertDeviceNodeToText (TestContext->DevPath, FAL= SE, FALSE); + UT_ASSERT_EQUAL (StrLen (DevPathNodeString), StrLen (TestContext->DevPat= hString)); + UT_ASSERT_MEM_EQUAL (DevPathNodeString, TestContext->DevPathString, StrL= en (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 =3D (DEVICE_PATH_CONVERSIONS_TEST_CONTEXT *)Context; + + DevPath =3D ConvertTextToDeviceNode (TestContext->DevPathString); + UT_ASSERT_EQUAL (DevicePathNodeLength (DevPath), DevicePathNodeLength (T= estContext->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 =3D NULL; + UINTN Index; + + Status =3D CreateUnitTestSuite (&DevicePathTextConversionSuite, Framewor= k, "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 te= st suite\n")); + return Status; + } + + for (Index =3D 0; Index < ARRAY_SIZE (mDevPathNodeToFromTextContext); In= dex++) { + AddTestCase (DevicePathTextConversionSuite, "Test ConvertDeviceNodeToT= ext", "TestConvertDeviceNodeToText", TestConvertDeviceNodeToText, NULL, NUL= L, &mDevPathNodeToFromTextContext[Index]); + } + + for (Index =3D 0; Index < ARRAY_SIZE (mDevPathNodeToFromTextContext); In= dex++) { + AddTestCase (DevicePathTextConversionSuite, "Test ConvertTextToDeviceN= ode", "TestConvertTextToDeviceNode", TestConvertTextToDeviceNode, NULL, NUL= L, &mDevPathNodeToFromTextContext[Index]); + } + + for (Index =3D 0; Index < ARRAY_SIZE (mDevPathToFromTextContext); Index+= +) { + AddTestCase (DevicePathTextConversionSuite, "Test ConvertDevicePathToT= ext", "TestConvertDevicePathToText", TestConvertDevicePathToText, NULL, NUL= L, &mDevPathToFromTextContext[Index]); + } + + for (Index =3D 0; Index < ARRAY_SIZE (mDevPathToFromTextContext); Index+= +) { + AddTestCase (DevicePathTextConversionSuite, "Test ConvertTextToDeviceP= ath", "TestConvertTextToDevicePath", TestConvertTextToDevicePath, NULL, NUL= L, &mDevPathToFromTextContext[Index]); + } + + return EFI_SUCCESS; +} --=20 2.39.2 --------------------------------------------------------------------- Intel Technology Poland sp. z o.o. ul. Slowackiego 173 | 80-298 Gdansk | Sad Rejonowy Gdansk Polnoc | VII Wydz= ial Gospodarczy Krajowego Rejestru Sadowego - KRS 101882 | NIP 957-07-52-31= 6 | Kapital zakladowy 200.000 PLN. Spolka oswiadcza, ze posiada status duzego przedsiebiorcy w rozumieniu usta= wy z dnia 8 marca 2013 r. o przeciwdzialaniu nadmiernym opoznieniom w trans= akcjach handlowych. Ta wiadomosc wraz z zalacznikami jest przeznaczona dla okreslonego adresata= i moze zawierac informacje poufne. W razie przypadkowego otrzymania tej wi= adomosci, prosimy o powiadomienie nadawcy oraz trwale jej usuniecie; jakiek= olwiek przegladanie lub rozpowszechnianie jest zabronione. This e-mail and any attachments may contain confidential material for the s= ole use of the intended recipient(s). If you are not the intended recipient= , please contact the sender and delete all copies; any review or distributi= on by others is strictly prohibited. -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#109126): https://edk2.groups.io/g/devel/message/109126 Mute This Topic: https://groups.io/mt/101619981/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-