From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM10-MW2-obe.outbound.protection.outlook.com (NAM10-MW2-obe.outbound.protection.outlook.com [40.107.94.99]) by mx.groups.io with SMTP id smtpd.web11.44897.1681698303165033920 for ; Sun, 16 Apr 2023 19:25:03 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="no key for verify" header.i=@amperemail.onmicrosoft.com header.s=selector1-amperemail-onmicrosoft-com header.b=NL33sky4; spf=pass (domain: os.amperecomputing.com, ip: 40.107.94.99, mailfrom: tinhnguyen@os.amperecomputing.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=ATUaDsZP2Cf9RkA0Md3wOAVY0a1AC3Gn+foGMKw0rz1mojz22XpuklJHh6bvfLnyvZWCjESbMlNM4adVHWm/fpjZlRD1PuplyE3Qph1F0HM5n6bBZsy0bLKFNvoeqtUivrsgPfSZPoxgcY28ywCH6qn3tA5pbDqwnHQR4ZxQf+BX/1njxcKPge3Yz964NQFLpVIdK+ToaCJrhhtgwUiFUVuit0K92q3A0zmNSzltI6WtyUKV+J2xmKylLi5v/R1zxDqCB63iIwnCMRu6V1go0grUyH5D7JF4jxSYJiS/gmiTZAYByRywqGqNt0GAZyHMRoCony69W8uWkWfjXbveZg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=L4KrLMiJmmYH4nRFzZloepuovstomd7jFiNAFp5lcQE=; b=m14lBtLSh9xFbVlZauDANdRnAF3gAQuJIL66YnUscNmqr8l/5lhuyslT5cE/SrW1bKq5w7pHzJORLBJtun59tyJ40Ti/oU5ASFfFb71JEwR7W9arzpMdiQecSBH32rE8TUTc3cjuQ/V/E9GP550pOaahSblhccpoXO4oB6xR61mTKcacvs0S4jaDrH0UeouwpmGfhg5DQqFSrjiDSeCAInuVK5xAoDI2SKnSBWuZWflFw280s6tlBViNGLgnFfdVkDAtj/H6ZwNbME/BdCoKax+ySokDNEVKfQKt6WLjP5KIz0qKGsgshQjmspQvyanf6cTcnl0or43jHeCFlblRiQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=os.amperecomputing.com; dmarc=pass action=none header.from=amperemail.onmicrosoft.com; dkim=pass header.d=amperemail.onmicrosoft.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amperemail.onmicrosoft.com; s=selector1-amperemail-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=L4KrLMiJmmYH4nRFzZloepuovstomd7jFiNAFp5lcQE=; b=NL33sky4WmiGOWkcCGoh2IlWBsaXwg813hJYrX1pC4vQxp3iSi1kw+5tdLpikk+XYLGSG5oGH0/jsOOi9KhVPV5NYRr2Xrq2+hLEa3haWiWJPWNdFkVVeCEHMSFQvWIvZPbE1EjtiX4wNvBBbWbd325xcq3xfIae4g76XV7tXE0= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=amperemail.onmicrosoft.com; Received: from DM5PR0102MB3336.prod.exchangelabs.com (2603:10b6:4:9f::11) by PH0PR01MB6152.prod.exchangelabs.com (2603:10b6:510:13::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6319.8; Mon, 17 Apr 2023 02:24:56 +0000 Received: from DM5PR0102MB3336.prod.exchangelabs.com ([fe80::bb9e:46d1:ae4b:caf2]) by DM5PR0102MB3336.prod.exchangelabs.com ([fe80::bb9e:46d1:ae4b:caf2%6]) with mapi id 15.20.6319.019; Mon, 17 Apr 2023 02:24:56 +0000 Message-ID: <2e9e9899-ed63-ffd9-eff4-e8ef5af01950@amperemail.onmicrosoft.com> Date: Mon, 17 Apr 2023 09:24:48 +0700 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Thunderbird/102.10.0 From: "Tinh Nguyen" Subject: Re: [edk2-platforms][PATCH] ManageabilityPkg: add support for the phosphor ipmi blob transfer protocol To: "Chang, Abner" , Nickle Wang , "devel@edk2.groups.io" CC: Isaac Oram , "Attar, AbdulLateef (Abdul Lateef)" References: <20230412031724.12690-1-nicklew@nvidia.com> <0c49ba9d-25e8-2727-a1bd-c93d2d2d6bce@amperemail.onmicrosoft.com> In-Reply-To: X-ClientProxiedBy: SG2PR02CA0123.apcprd02.prod.outlook.com (2603:1096:4:188::22) To DM5PR0102MB3336.prod.exchangelabs.com (2603:10b6:4:9f::11) Return-Path: tinhnguyen@os.amperecomputing.com MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DM5PR0102MB3336:EE_|PH0PR01MB6152:EE_ X-MS-Office365-Filtering-Correlation-Id: f89bca39-b768-485c-c7b7-08db3eeaef24 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: XJ+EwjZkxWbJgF5uHQX9yOIRZplmrALcOSidKWgxp4jlPH9BynwYaGAagbk4CXwg+0UgnwNNOEkpViR7GYs3pj7E5CxXlsdo4zb28lc7goA9Vq7l2rnMIuPo99tOWbvLqe+Aun9WxiUeVZlgPHIKGgZAcnLI83dhvqq9xzO2CRnwYjv4PjlQnXFHi/euEyIHuzlJzGOOLa5AhRjhvRQ8uxdJyTTnvog9HPjsfwnc6KZYWLGp/P/VBMnV6KHjLgY6A6FIyQ/ANJR+GYIIjHp8f6CE3G5hJQNy/95RslpTNVXfnKtaG6knUA41meiXSebTnZLMZy/J0VViurr9dgqF20CmeNgHp8keSSH9cAbyfTIKL8w5h2mn/QUNcQQyW/FXvVLfxKLagO7B95wZ7C+XyfV6vQ2Z3kllnnqlve6yrsWh9L92wjVWBL0Ms+sCkU+IA28UKCGUEkqXXW4R3LSOUnGMSNMde2Gk6b1Ke3bUVmKZUz3SdfTyD9c7ezwKTFNyGZc5q2Ja9M3Dbqhh7EUEme7OycW/EP/8x7ZCtH/GyGYBbx1xYU+RGL08X85/pm4P+QPNtPZWKI3sT3MCv0DCkU1SPe7diB3FjHeCAflggfHJmMwsfV3nB9cdJGa0QCts X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:DM5PR0102MB3336.prod.exchangelabs.com;PTR:;CAT:NONE;SFS:(13230028)(4636009)(366004)(376002)(396003)(346002)(136003)(39850400004)(451199021)(42882007)(31686004)(31696002)(83380400001)(2616005)(478600001)(53546011)(6512007)(186003)(26005)(6506007)(6486002)(6666004)(966005)(54906003)(110136005)(19627235002)(83170400001)(4326008)(66946007)(66476007)(66556008)(316002)(30864003)(2906002)(41300700001)(38100700002)(5660300002)(8936002)(8676002)(43740500002)(579004)(559001)(44824005);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?UXlUWZrXPDOomcctkHue8YlZhfNW1HLNklrnzTzYzr+Y1KqAktWixe3PmSBh?= =?us-ascii?Q?n8l4bFcpOi1Ur5levasqagZy89vQJSJRV1KI9C1KE8StP6atceATaG7u/OiY?= =?us-ascii?Q?e3ra+htmrO9+DV5JV4C+QZkDPy/EJ6iR7P35naQeguPkajZUp/TBWW01ASmB?= =?us-ascii?Q?jZbBeJ+KJHp+//OEV/ciY8/u8GBcOYXGn8tV28QoQOHHbrnmDmK5nLc402IH?= =?us-ascii?Q?G3LpQ0Nyg7+X8SzAIQS5Id+I1lo6+3RL98ttFha4Pd9WOPaVOQfgjrCkmeUu?= =?us-ascii?Q?F9Mba7Y4eKWGLNXa7beN6LjCPsFGxVXEKz5abvti0/C2dz84V/tjNaKobZVo?= =?us-ascii?Q?+abed27sps+dfOVhTsXzVDgOZNXUmNwHUQ3aiuLDbwaxRUQReyASKh3RHXw4?= =?us-ascii?Q?Z5Za5XJtpX6r/LikqNgVaUOJDXw9uU03LI7sYUiZ9spdeBMFB3/1Gy//pWAd?= =?us-ascii?Q?oD0Rmyz0BdsD/qBpwC6K8c56IjrUg0n1plIdfnZe4VpmuVhIByT/Sfp/VdnU?= =?us-ascii?Q?kls2SHq8elTks+COlw/2rIRC2enTwJk1QJ9IO/MnuDGSba1BYiLSvusAhHyF?= =?us-ascii?Q?rtuX8+vCQWR3msOTfqZoCIC19lvKMC6/Pi3OxXd5Ez0fOQVPQh2vVJIqO6A3?= =?us-ascii?Q?Z8+R2+AAoTs+lKW91/D34gfr/BBWd7rFlzvzDWxRwW8O59H8Btjs4oRCv6lA?= =?us-ascii?Q?IbckREgLNfgbgXSj2WxxvgAoCA18jkbr6jAaQmJVm5KjvyEBqgqc/9VW50zS?= =?us-ascii?Q?uwHTDzPUtAkieelI3HDBc6kqkg3Oo0ZgGngkBkISYBwdtt0XtfwFEPEdCuIg?= =?us-ascii?Q?drSfhpHzdSY+dGxCpVOnlTmrQMqArD4XlDo0rY6g1Mz8kKmGX0tqi4sI41LK?= =?us-ascii?Q?GJ0eeB1LWExQRmmkEXPWdJbtYoPBAEehc4VQTaJuzvqKBrI3I0+K4hOKLip/?= =?us-ascii?Q?v4j5zObkPGkk1QxmHjJ5PDfOFb6iOVSe88eu+6rL/Z8TY4/A6G3Ynj0GYATJ?= =?us-ascii?Q?6t45zerIflwU+wyOkEups3+8yVSeCylxrOZZnVnI61DjSXFCX5CtKxXXDaxu?= =?us-ascii?Q?aYWYIDfBFqsxlcHSNfefeTPXRkpBwuTUzIWy6Tm2xT1L37nMqBErYMBqJ/dp?= =?us-ascii?Q?wWTNHDGMyoFKXmB2Oh7er8qob8KF+WRXSMys5skkwOy0HBsLOjxmxc2K8zwc?= =?us-ascii?Q?96bNoOI0nvAGrLgWRm9Zcq5SgThE5yTEYhMIopZ16E7ViXM8Jn1DO2tYZqn3?= =?us-ascii?Q?9m0Qz2d6yoWJKvEQGdLh8MLi4CWU16rKXf4HeuaJ4Yfoo2G70/iOcD5wEgUs?= =?us-ascii?Q?Jrgbkg8nYMWdt9dNOgL1+os5IgeBdbmZidUnbf9wo7ab//fmq6StfDHJiNKR?= =?us-ascii?Q?50qDn437cfKHHtNB5opPtLKeNu9YZp5JkytOT7y0GO7VTmuqpj+eCOGLOl8c?= =?us-ascii?Q?hpIwYFtKdSI8PMva6WznqScFLfU9cU7hRciVkll79flrtCos68WhnCFtdQ+q?= =?us-ascii?Q?yCPbdb+sf9O+gJu2/fDkeB0IW2w1LxjghYiigC/ZBD40TY20MkCSdknsOH3j?= =?us-ascii?Q?M0iE0BX9F3wTOwBSyySLp8x3nuNesIxXpDh0prjW194pKjGe92JJ8WpHX/8m?= =?us-ascii?Q?SYbYQbmwsVIheWQy8uJ6204=3D?= X-OriginatorOrg: amperemail.onmicrosoft.com X-MS-Exchange-CrossTenant-Network-Message-Id: f89bca39-b768-485c-c7b7-08db3eeaef24 X-MS-Exchange-CrossTenant-AuthSource: DM5PR0102MB3336.prod.exchangelabs.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 17 Apr 2023 02:24:56.4495 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 3bc2b170-fd94-476d-b0ce-4229bdc904a7 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: cpUzkYPdjJ7BxBA0NEQIf/SiwXhye3HQRxeltprKGGbfRU9GzMficGpJFaJ3G55RhP5FA7WdVY6X7oBwWfz4ogQCR2XZnGunCc8Lj0C/AjhLR9L6XsFpl3BFebxixx1S X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH0PR01MB6152 Content-Language: en-US Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: quoted-printable On 4/16/2023 5:50 PM, Chang, Abner wrote: > [EXTERNAL EMAIL NOTICE: This email originated from an external sender. Pl= ease be mindful of safe email handling and proprietary information protecti= on practices.] > > > [AMD Official Use Only - General] > > Tink and Nickle, > Two feedbacks in below, > >> -----Original Message----- >> From: Tinh Nguyen >> Sent: Sunday, April 16, 2023 6:29 PM >> To: Nickle Wang;devel@edk2.groups.io >> Cc: Chang, Abner; Isaac Oram >> ; Attar, AbdulLateef (Abdul Lateef) >> >> Subject: Re: [edk2-platforms][PATCH] ManageabilityPkg: add support for t= he >> phosphor ipmi blob transfer protocol >> >> Caution: This message originated from an External Source. Use proper >> caution when opening attachments, clicking links, or responding. >> >> >> Hi Nickle, >> >> Please find my inline comments below >> >> On 4/12/2023 10:17 AM, Nickle Wang wrote: >>> [EXTERNAL EMAIL NOTICE: This email originated from an external sender. >> Please be mindful of safe email handling and proprietary information >> protection practices.] >>> This change implements the blob transfer protocol used in OpenBmc >>> documented here:https://github.com/openbmc/phosphor-ipmi-blobs >>> >>> Signed-off-by: Nick Ramirez >>> Cc: Abner Chang >>> Cc: Isaac Oram >>> Cc: Abdul Lateef Attar >>> Cc: Nickle Wang >>> Cc: Tinh Nguyen >>> --- >>> .../ManageabilityPkg/ManageabilityPkg.dec | 6 + >>> .../Include/Dsc/Manageability.dsc | 4 +- >>> .../IpmiBlobTransferDxe.inf | 39 + >>> .../IpmiBlobTransferTestUnitTestsHost.inf | 40 + >>> .../Include/Protocol/IpmiBlobTransfer.h | 136 ++ >>> .../InternalIpmiBlobTransfer.h | 363 ++++++ >>> .../IpmiBlobTransferDxe/IpmiBlobTransferDxe.c | 799 ++++++++++++ >>> .../UnitTest/IpmiBlobTransferTestUnitTests.c | 1113 >> +++++++++++++++++ >>> .../Universal/IpmiBlobTransferDxe/Readme.md | 24 + >>> 9 files changed, 2523 insertions(+), 1 deletion(-) >>> create mode 100644 >> Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransf >> erDxe.inf >>> create mode 100644 >> Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiBl >> obTransferTestUnitTestsHost.inf >>> create mode 100644 >> Features/ManageabilityPkg/Include/Protocol/IpmiBlobTransfer.h >>> create mode 100644 >> Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/InternalIpmiBlo >> bTransfer.h >>> create mode 100644 >> Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransf >> erDxe.c >>> create mode 100644 >> Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiBl >> obTransferTestUnitTests.c >>> create mode 100644 >> Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/Readme.md >>> diff --git a/Features/ManageabilityPkg/ManageabilityPkg.dec >> b/Features/ManageabilityPkg/ManageabilityPkg.dec >>> index 9a930d3e4b..e2d6cccc50 100644 >>> --- a/Features/ManageabilityPkg/ManageabilityPkg.dec >>> +++ b/Features/ManageabilityPkg/ManageabilityPkg.dec >>> @@ -4,6 +4,7 @@ >>> # those are related to the platform management. >>> # >>> # Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserve= d.
>>> +# Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights >> reserved. >>> # SPDX-License-Identifier: BSD-2-Clause-Patent >>> # >>> ## >>> @@ -48,3 +49,8 @@ >>> gManageabilityProtocolMctpGuid =3D { 0x76FED8F1, 0x0BE5, 0x4269= , >> { 0xA3, 0x1A, 0x38, 0x0F, 0x54, 0xF1, 0xA1, 0x8A } } >>> # Manageability Protocol PLDM >>> gManageabilityProtocolPldmGuid =3D { 0x3958090D, 0x69DD, 0x4868= , >> { 0x9C, 0x41, 0xC9, 0xAC, 0x31, 0xB5, 0x25, 0xC5 } } >>> + >>> +[Protocols] >>> + >>> + ## Include/Protocol/IpmiBlobTransfer.h >>> + gEdkiiIpmiBlobTransferProtocolGuid =3D { 0x05837c75, 0x1d65, 0x468b, >> { 0xb1, 0xc2, 0x81, 0xaf, 0x9a, 0x31, 0x5b, 0x2c } } >>> diff --git a/Features/ManageabilityPkg/Include/Dsc/Manageability.dsc >> b/Features/ManageabilityPkg/Include/Dsc/Manageability.dsc >>> index 0d868fdf4a..111d6b91dc 100644 >>> --- a/Features/ManageabilityPkg/Include/Dsc/Manageability.dsc >>> +++ b/Features/ManageabilityPkg/Include/Dsc/Manageability.dsc >>> @@ -2,11 +2,13 @@ >>> # Common libraries for Manageabilty Package >>> # >>> # Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserve= d.
>>> +# Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights >> reserved. >>> # SPDX-License-Identifier: BSD-2-Clause-Patent >>> # >>> ## >>> [LibraryClasses] >>> >> ManageabilityTransportHelperLib|ManageabilityPkg/Library/BaseManageabi >> lityTransportHelperLib/BaseManageabilityTransportHelper.inf >>> + >> IpmiLib|MdeModulePkg/Library/DxeIpmiLibIpmiProtocol/DxeIpmiLibIpmiPr >> otocol.inf >>> [LibraryClasses.ARM, LibraryClasses.AARCH64] >>> # >>> @@ -22,4 +24,4 @@ >>> [Components.X64] >>> ManageabilityPkg/Universal/IpmiProtocol/Dxe/IpmiProtocolDxe.inf >>> ManageabilityPkg/Universal/IpmiProtocol/Smm/IpmiProtocolSmm.inf >>> - >>> + >> ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransferDxe.inf >>> diff --git >> a/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTran >> sferDxe.inf >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTran >> sferDxe.inf >>> new file mode 100644 >>> index 0000000000..28e9d293c1 >>> --- /dev/null >>> +++ >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTran >> sferDxe.inf >>> @@ -0,0 +1,39 @@ >>> +## @file >>> +# IPMI Blob Transfer Protocol DXE Driver. >>> +# >>> +# Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All right= s >> reserved. >>> +# >>> +# SPDX-License-Identifier: BSD-2-Clause-Patent >>> +# >>> + >>> +[Defines] >>> + INF_VERSION =3D 0x00010005 >>> + BASE_NAME =3D IpmiBlobTransferDxe >>> + FILE_GUID =3D 6357c804-78bb-4b0c-abdf-c75df942f= 319 >>> + MODULE_TYPE =3D DXE_DRIVER >>> + VERSION_STRING =3D 1.0 >>> + ENTRY_POINT =3D IpmiBlobTransferDxeDriverEntryPoi= nt >>> + >>> +[Sources.common] >>> + IpmiBlobTransferDxe.c >>> + >>> +[LibraryClasses] >>> + BaseLib >>> + BaseMemoryLib >>> + DebugLib >>> + IpmiLib >>> + MemoryAllocationLib >>> + PcdLib >>> + UefiBootServicesTableLib >>> + UefiDriverEntryPoint >>> + >>> +[Packages] >>> + MdePkg/MdePkg.dec >>> + MdeModulePkg/MdeModulePkg.dec >>> + ManageabilityPkg/ManageabilityPkg.dec >>> + >>> +[Protocols] >>> + gEdkiiIpmiBlobTransferProtocolGuid >>> + >>> +[Depex] >>> + TRUE >>> diff --git >> a/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/Ipmi >> BlobTransferTestUnitTestsHost.inf >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/Ipm >> iBlobTransferTestUnitTestsHost.inf >>> new file mode 100644 >>> index 0000000000..1f071bbadc >>> --- /dev/null >>> +++ >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/Ipm >> iBlobTransferTestUnitTestsHost.inf >>> @@ -0,0 +1,40 @@ >>> +## @file >>> +# Unit tests of the Ipmi blob transfer driver that are run from a host >> environment. >>> +# >>> +# Copyright (c) 2020-2023, NVIDIA CORPORATION & AFFILIATES. All rights >> reserved. >>> +# >>> +# SPDX-License-Identifier: BSD-2-Clause-Patent >>> +## >>> + >>> +[Defines] >>> + INF_VERSION =3D 0x00010006 >>> + BASE_NAME =3D IpmiBlobTransferDxeUnitTestsHost >>> + FILE_GUID =3D 1f5d4095-ea52-432c-b078-86097fef6= 004 >>> + 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 X64 >>> +# >>> + >>> +[Sources] >>> + IpmiBlobTransferTestUnitTests.c >>> + >>> +[Packages] >>> + MdePkg/MdePkg.dec >>> + MdeModulePkg/MdeModulePkg.dec >>> + ManageabilityPkg/ManageabilityPkg.dec >>> + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec >>> + >>> +[LibraryClasses] >>> + BaseLib >>> + BaseMemoryLib >>> + DebugLib >>> + UnitTestLib >>> + IpmiLib >>> + >>> +[Protocols] >>> + gEdkiiIpmiBlobTransferProtocolGuid >>> diff --git >> a/Features/ManageabilityPkg/Include/Protocol/IpmiBlobTransfer.h >> b/Features/ManageabilityPkg/Include/Protocol/IpmiBlobTransfer.h >>> new file mode 100644 >>> index 0000000000..8ea71d8816 >>> --- /dev/null >>> +++ b/Features/ManageabilityPkg/Include/Protocol/IpmiBlobTransfer.h >>> @@ -0,0 +1,136 @@ >>> +/** @file >>> + >>> + IPMI Blob Transfer driver >>> + >>> + Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights >> reserved. >>> + >>> + SPDX-License-Identifier: BSD-2-Clause-Patent >>> + >>> +**/ >>> +#include >>> +#include >>> +#include >>> + >>> +#define IPMI_NETFN_OEM 0x2E >>> +#define IPMI_OEM_BLOB_TRANSFER_CMD 0x80 >>> +#define IPMI_OEM_BLOB_MAX_DATA_PER_PACKET 64 >> It is better to avoid fixing the packet size here. >> >> - For ssif, get it from "get capabilities" command. If BMC supports only >> single-part read/write, this size exceeds BMC capability >> >> - For kcs, I don't see the limitation >> >> I think limiting the size here is unsuitable, applications that use this >> protocol should check the size themselves > IPMI blob uses IpmiLib to submit the command and IPMI protocol is the one= that talks to transport interface. That would be IPMI protocol's responsib= ility to know the exact maximum size of each transfer payload, according to= the transport interface. > From the ManageabilityPkg design, SSIF manageability transport library c= an returns MTU and the capability of single/multi part read/write to caller= (IPMI protocol for example). IPMI protocol should determine having a singl= e part transfer or splitting the packet into multi transfers. > I can help on SSIF manageability transport library as well if you have SS= IF sample code. =C2=A0yes I=E2=80=99m preparing the ssif driver, I=E2=80=99m sorry for bei= ng late. >>> + >>> +#define BLOB_TRANSFER_STAT_OPEN_R BIT0 >>> +#define BLOB_TRANSFER_STAT_OPEN_W BIT1 >>> +#define BLOB_TRANSFER_STAT_COMMITING BIT2 >>> +#define BLOB_TRANSFER_STAT_COMMITTED BIT3 >>> +#define BLOB_TRANSFER_STAT_COMMIT_ERROR BIT4 >>> +// Bits 5-7 are reserved >>> +// Bits 8-15 are blob-specific definitions >>> + >>> +// >>> +// Blob Transfer Function Prototypes >>> +// >>> +typedef >>> +EFI_STATUS >>> +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_GET_COUNT)( >>> + OUT UINT32 *Count >>> + ); >>> + >>> +typedef >>> +EFI_STATUS >>> +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_ENUMERATE)( >>> + IN UINT32 BlobIndex, >>> + OUT CHAR8 *BlobId >>> + ); >>> + >>> +typedef >>> +EFI_STATUS >>> +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_OPEN)( >>> + IN CHAR8 *BlobId, >>> + IN UINT16 Flags, >>> + OUT UINT16 *SessionId >>> + ); >>> + >>> +typedef >>> +EFI_STATUS >>> +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_READ)( >>> + IN UINT16 SessionId, >>> + IN UINT32 Offset, >>> + IN UINT32 RequestedSize, >>> + OUT UINT8 *Data >>> + ); >>> + >>> +typedef >>> +EFI_STATUS >>> +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_WRITE)( >>> + IN UINT16 SessionId, >>> + IN UINT32 Offset, >>> + IN UINT8 *Data, >>> + IN UINT32 WriteLength >>> + ); >>> + >>> +typedef >>> +EFI_STATUS >>> +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_COMMIT)( >>> + IN UINT16 SessionId, >>> + IN UINT8 CommitDataLength, >>> + IN UINT8 *CommitData >>> + ); >>> + >>> +typedef >>> +EFI_STATUS >>> +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_CLOSE)( >>> + IN UINT16 SessionId >>> + ); >>> + >>> +typedef >>> +EFI_STATUS >>> +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_DELETE)( >>> + IN CHAR8 *BlobId >>> + ); >>> + >>> +typedef >>> +EFI_STATUS >>> +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_STAT)( >>> + IN CHAR8 *BlobId, >>> + OUT UINT16 *BlobState, >>> + OUT UINT32 *Size, >>> + OUT UINT8 *MetadataLength, >>> + OUT UINT8 *Metadata >>> + ); >>> + >>> +typedef >>> +EFI_STATUS >>> +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_SESSION_STAT)( >>> + IN UINT16 SessionId, >>> + OUT UINT16 *BlobState, >>> + OUT UINT32 *Size, >>> + OUT UINT8 *MetadataLength, >>> + OUT UINT8 *Metadata >>> + ); >>> + >>> +typedef >>> +EFI_STATUS >>> +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_WRITE_META)( >>> + IN UINT16 SessionId, >>> + IN UINT32 Offset, >>> + IN UINT8 *Data, >>> + IN UINT32 WriteLength >>> + ); >>> + >>> +// >>> +// Structure of IPMI_BLOB_TRANSFER_PROTOCOL >>> +// >>> +struct _IPMI_BLOB_TRANSFER_PROTOCOL { >>> + IPMI_BLOB_TRANSFER_PROTOCOL_GET_COUNT BlobGetCount; >>> + IPMI_BLOB_TRANSFER_PROTOCOL_ENUMERATE BlobEnumerate; >>> + IPMI_BLOB_TRANSFER_PROTOCOL_OPEN BlobOpen; >>> + IPMI_BLOB_TRANSFER_PROTOCOL_READ BlobRead; >>> + IPMI_BLOB_TRANSFER_PROTOCOL_WRITE BlobWrite; >>> + IPMI_BLOB_TRANSFER_PROTOCOL_COMMIT BlobCommit; >>> + IPMI_BLOB_TRANSFER_PROTOCOL_CLOSE BlobClose; >>> + IPMI_BLOB_TRANSFER_PROTOCOL_DELETE BlobDelete; >>> + IPMI_BLOB_TRANSFER_PROTOCOL_STAT BlobStat; >>> + IPMI_BLOB_TRANSFER_PROTOCOL_SESSION_STAT BlobSessionStat; >>> + IPMI_BLOB_TRANSFER_PROTOCOL_WRITE_META BlobWriteMeta; >>> +}; >>> + >>> +typedef struct _IPMI_BLOB_TRANSFER_PROTOCOL >> IPMI_BLOB_TRANSFER_PROTOCOL; >>> + >>> +extern EFI_GUID gEdkiiIpmiBlobTransferProtocolGuid; >>> diff --git >> a/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/InternalIpmiB >> lobTransfer.h >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/InternalIpmiB >> lobTransfer.h >>> new file mode 100644 >>> index 0000000000..14f0dc02bc >>> --- /dev/null >>> +++ >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/InternalIpmiB >> lobTransfer.h >>> @@ -0,0 +1,363 @@ >>> +/** @file >>> + >>> + Headers for IPMI Blob Transfer driver >>> + >>> + Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights >> reserved. >>> + >>> + SPDX-License-Identifier: BSD-2-Clause-Patent >>> + >>> +**/ >>> + >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> + >>> +#define PROTOCOL_RESPONSE_OVERHEAD (4 * sizeof(UINT8)) // 1 >> byte completion code + 3 bytes OEN >>> + >>> +// Subcommands for this protocol >>> +typedef enum { >>> + IpmiBlobTransferSubcommandGetCount =3D 0, >>> + IpmiBlobTransferSubcommandEnumerate, >>> + IpmiBlobTransferSubcommandOpen, >>> + IpmiBlobTransferSubcommandRead, >>> + IpmiBlobTransferSubcommandWrite, >>> + IpmiBlobTransferSubcommandCommit, >>> + IpmiBlobTransferSubcommandClose, >>> + IpmiBlobTransferSubcommandDelete, >>> + IpmiBlobTransferSubcommandStat, >>> + IpmiBlobTransferSubcommandSessionStat, >>> + IpmiBlobTransferSubcommandWriteMeta, >>> +} IPMI_BLOB_TRANSFER_SUBCOMMANDS; >>> + >>> +#pragma pack(1) >>> + >>> +typedef struct { >>> + UINT8 OEN[3]; >>> + UINT8 SubCommand; >>> +} IPMI_BLOB_TRANSFER_HEADER; >>> + >>> +// >>> +// Command 0 - BmcBlobGetCount >>> +// The BmcBlobGetCount command expects to receive an empty body. >>> +// The BMC will return the number of enumerable blobs >>> +// >>> +typedef struct { >>> + UINT32 BlobCount; >>> +} IPMI_BLOB_TRANSFER_GET_COUNT_RESPONSE; >>> + >>> +// >>> +// Command 1 - BmcBlobEnumerate >>> +// The BmcBlobEnumerate command expects to receive a body of: >>> +// >>> +typedef struct { >>> + UINT32 BlobIndex; // 0-based index of blob to receive >>> +} IPMI_BLOB_TRANSFER_BLOB_ENUMERATE_SEND_DATA; >>> + >>> +typedef struct { >>> + CHAR8 BlobId[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET]; >>> +} IPMI_BLOB_TRANSFER_BLOB_ENUMERATE_RESPONSE; >>> + >>> +// >>> +// Command 2 - BmcBlobOpen >>> +// The BmcBlobOpen command expects to receive a body of: >>> +// >>> +typedef struct { >>> + UINT16 Flags; >>> + CHAR8 BlobId[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET]; >>> +} IPMI_BLOB_TRANSFER_BLOB_OPEN_SEND_DATA; >>> + >>> +#define BLOB_OPEN_FLAG_READ 0 >>> +#define BLOB_OPEN_FLAG_WRITE 1 >>> +// Bits 2-7 are reserved >>> +// Bits 8-15 are blob-specific definitions >>> + >>> +typedef struct { >>> + UINT16 SessionId; >>> +} IPMI_BLOB_TRANSFER_BLOB_OPEN_RESPONSE; >>> + >>> +// >>> +// Command 3 - BmcBlobRead >>> +// The BmcBlobRead command expects to receive a body of: >>> +// >>> +typedef struct { >>> + UINT16 SessionId; // Returned from BlobOpen >>> + UINT32 Offset; >>> + UINT32 RequestedSize; >>> +} IPMI_BLOB_TRANSFER_BLOB_READ_SEND_DATA; >>> + >>> +typedef struct { >>> + UINT8 Data[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET]; >>> +} IPMI_BLOB_TRANSFER_BLOB_READ_RESPONSE; >>> + >>> +// >>> +// Command 4 - BmcBlobWrite >>> +// The BmcBlobWrite command expects to receive a body of: >>> +// >>> +typedef struct { >>> + UINT16 SessionId; // Returned from BlobOpen >>> + UINT32 Offset; >>> + UINT8 Data[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET]; >>> +} IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA; >>> + >>> +// >>> +// Command 5 - BmcBlobCommit >>> +// The BmcBlobCommit command expects to receive a body of: >>> +// >>> +typedef struct { >>> + UINT16 SessionId; // Returned from BlobOpen >>> + UINT8 CommitDataLength; >>> + UINT8 CommitData[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET]; >>> +} IPMI_BLOB_TRANSFER_BLOB_COMMIT_SEND_DATA; >>> + >>> +// >>> +// Command 6 - BmcBlobClose >>> +// The BmcBlobClose command expects to receive a body of: >>> +// >>> +typedef struct { >>> + UINT16 SessionId; // Returned from BlobOpen >>> +} IPMI_BLOB_TRANSFER_BLOB_CLOSE_SEND_DATA; >>> + >>> +// >>> +// Command 7 - BmcBlobDelete >>> +// NOTE: This command will fail if there are open sessions for this bl= ob >>> +// The BmcBlobDelete command expects to receive a body of: >>> +// >>> +typedef struct { >>> + CHAR8 BlobId[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET]; >>> +} IPMI_BLOB_TRANSFER_BLOB_DELETE_SEND_DATA; >>> + >>> +// >>> +// Command 8 - BmcBlobStat >>> +// This command returns statistics about a blob. >>> +// This command expects to receive a body of: >>> +// >>> +typedef struct { >>> + CHAR8 BlobId[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET]; >>> +} IPMI_BLOB_TRANSFER_BLOB_STAT_SEND_DATA; >>> + >>> +typedef struct { >>> + UINT16 BlobState; >>> + UINT32 Size; // Size in bytes of the blob >>> + UINT8 MetaDataLen; >>> + UINT8 MetaData[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET]; >>> +} IPMI_BLOB_TRANSFER_BLOB_STAT_RESPONSE; >>> + >>> +// >>> +// Command 9 - BmcBlobSessionStat >>> +// Returns same data as BmcBlobState expect for a session, not a blob >>> +// This command expects to receive a body of: >>> +// >>> +typedef struct { >>> + UINT16 SessionId; >>> +} IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_SEND_DATA; >>> + >>> +typedef struct { >>> + UINT16 BlobState; >>> + UINT32 Size; // Size in bytes of the blob >>> + UINT8 MetaDataLen; >>> + UINT8 MetaData[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET]; >>> +} IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_RESPONSE; >>> + >>> +// >>> +// Command 10 - BmcBlobWriteMeta >>> +// The BmcBlobWriteMeta command expects to receive a body of: >>> +// >>> +typedef struct { >>> + UINT16 SessionId; >>> + UINT32 Offset; >>> + UINT8 Data[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET]; >>> +} IPMI_BLOB_TRANSFER_BLOB_WRITE_META_SEND_DATA; >>> + >>> +#define IPMI_BLOB_TRANSFER_BLOB_WRITE_META_RESPONSE NULL >>> + >>> +#pragma pack() >>> + >>> +/** >>> + Calculate CRC-16-CCITT with poly of 0x1021 >>> + >>> + @param[in] Data The target data. >>> + @param[in] DataSize The target data size. >>> + >>> + @return UINT16 The CRC16 value. >>> + >>> +**/ >>> +UINT16 >>> +CalculateCrc16 ( >>> + IN UINT8 *Data, >>> + IN UINTN DataSize >>> + ); >>> + >>> +EFI_STATUS >>> +IpmiBlobTransferSendIpmi ( >>> + IN UINT8 SubCommand, >>> + IN UINT8 *SendData, >>> + IN UINT32 SendDataSize, >>> + OUT UINT8 *ResponseData, >>> + OUT UINT32 *ResponseDataSize >>> + ); >>> + >>> +/** >>> + @param[out] Count The number of active blobs >>> + >>> + @retval EFI_SUCCESS Successfully retrieved the number of = active >> blobs. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferGetCount ( >>> + OUT UINT32 *Count >>> + ); >>> + >>> +/** >>> + @param[in] BlobIndex The 0-based Index of the blob to >> enumerate >>> + @param[out] BlobId The ID of the blob >>> + >>> + @retval EFI_SUCCESS Successfully enumerated the blob. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferEnumerate ( >>> + IN UINT32 BlobIndex, >>> + OUT CHAR8 *BlobId >>> + ); >>> + >>> +/** >>> + @param[in] BlobId The ID of the blob to open >>> + @param[in] Flags Flags to control how the blob is = opened >>> + @param[out] SessionId A unique session identifier >>> + >>> + @retval EFI_SUCCESS Successfully opened the blob. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferOpen ( >>> + IN CHAR8 *BlobId, >>> + IN UINT16 Flags, >>> + OUT UINT16 *SessionId >>> + ); >>> + >>> +/** >>> + @param[in] SessionId The session ID returned from a ca= ll to >> BlobOpen >>> + @param[in] Offset The offset of the blob from which= to start >> reading >>> + @param[in] RequestedSize The length of data to read >>> + @param[out] Data Data read from the blob >>> + >>> + @retval EFI_SUCCESS Successfully read from the blob. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferRead ( >>> + IN UINT16 SessionId, >>> + IN UINT32 Offset, >>> + IN UINT32 RequestedSize, >>> + OUT UINT8 *Data >>> + ); >>> + >>> +/** >>> + @param[in] SessionId The session ID returned from a ca= ll to >> BlobOpen >>> + @param[in] Offset The offset of the blob from which= to start >> writing >>> + @param[in] Data A pointer to the data to write >>> + >>> + @retval EFI_SUCCESS Successfully wrote to the blob. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferWrite ( >>> + IN UINT16 SessionId, >>> + IN UINT32 Offset, >>> + IN UINT8 *Data, >>> + IN UINT32 WriteLength >>> + ); >>> + >>> +/** >>> + @param[in] SessionId The session ID returned from a c= all to >> BlobOpen >>> + @param[in] CommitDataLength The length of data to commit to = the >> blob >>> + @param[in] CommitData A pointer to the data to commit >>> + >>> + @retval EFI_SUCCESS Successful commit to the blob. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferCommit ( >>> + IN UINT16 SessionId, >>> + IN UINT8 CommitDataLength, >>> + IN UINT8 *CommitData >>> + ); >>> + >>> +/** >>> + @param[in] SessionId The session ID returned from a ca= ll to >> BlobOpen >>> + >>> + @retval EFI_SUCCESS The blob was closed. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferClose ( >>> + IN UINT16 SessionId >>> + ); >>> + >>> +/** >>> + @param[in] BlobId The BlobId to be deleted >>> + >>> + @retval EFI_SUCCESS The blob was deleted. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferDelete ( >>> + IN CHAR8 *BlobId >>> + ); >>> + >>> +/** >>> + @param[in] BlobId The Blob ID to gather statistics = for >>> + @param[out] BlobState The current state of the blob >>> + @param[out] Size Size in bytes of the blob >>> + @param[out] MetadataLength Length of the optional metadata >>> + @param[out] Metadata Optional blob-specific metadata >>> + >>> + @retval EFI_SUCCESS The blob statistics were successf= ully >> gathered. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferStat ( >>> + IN CHAR8 *BlobId, >>> + OUT UINT16 *BlobState, >>> + OUT UINT32 *Size, >>> + OUT UINT8 *MetadataLength, >>> + OUT UINT8 *Metadata >>> + ); >>> + >>> +/** >>> + @param[in] SessionId The ID of the session to gather s= tatistics for >>> + @param[out] BlobState The current state of the blob >>> + @param[out] Size Size in bytes of the blob >>> + @param[out] MetadataLength Length of the optional metadata >>> + @param[out] Metadata Optional blob-specific metadata >>> + >>> + @retval EFI_SUCCESS The blob statistics were successf= ully >> gathered. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferSessionStat ( >>> + IN UINT16 SessionId, >>> + OUT UINT16 *BlobState, >>> + OUT UINT32 *Size, >>> + OUT UINT8 *MetadataLength, >>> + OUT UINT8 *Metadata >>> + ); >>> + >>> +/** >>> + @param[in] SessionId The ID of the session to write me= tadata for >>> + @param[in] Offset The offset of the metadata to wri= te to >>> + @param[in] Data The data to write to the metadata >>> + >>> + @retval EFI_SUCCESS The blob metadata was successfull= y written. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferWriteMeta ( >>> + IN UINT16 SessionId, >>> + IN UINT32 Offset, >>> + IN UINT8 *Data, >>> + IN UINT32 WriteLength >>> + ); >>> diff --git >> a/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTran >> sferDxe.c >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTran >> sferDxe.c >>> new file mode 100644 >>> index 0000000000..9e663289d5 >>> --- /dev/null >>> +++ >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTran >> sferDxe.c >>> @@ -0,0 +1,799 @@ >>> +/** @file >>> + >>> + IPMI Blob Transfer driver >>> + >>> + Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights >> reserved. >>> + >>> + SPDX-License-Identifier: BSD-2-Clause-Patent >>> + >>> +**/ >>> +#include >>> + >>> +#include "InternalIpmiBlobTransfer.h" >>> + >>> +#define BLOB_TRANSFER_DEBUG 0 >>> + >>> +STATIC CONST IPMI_BLOB_TRANSFER_PROTOCOL mIpmiBlobTransfer =3D { >>> + >> (IPMI_BLOB_TRANSFER_PROTOCOL_GET_COUNT)*IpmiBlobTransferGetCou >> nt, >>> + >> (IPMI_BLOB_TRANSFER_PROTOCOL_ENUMERATE)*IpmiBlobTransferEnume >> rate, >>> + (IPMI_BLOB_TRANSFER_PROTOCOL_OPEN)*IpmiBlobTransferOpen, >>> + (IPMI_BLOB_TRANSFER_PROTOCOL_READ)*IpmiBlobTransferRead, >>> + (IPMI_BLOB_TRANSFER_PROTOCOL_WRITE)*IpmiBlobTransferWrite, >>> + >> (IPMI_BLOB_TRANSFER_PROTOCOL_COMMIT)*IpmiBlobTransferCommit, >>> + (IPMI_BLOB_TRANSFER_PROTOCOL_CLOSE)*IpmiBlobTransferClose, >>> + (IPMI_BLOB_TRANSFER_PROTOCOL_DELETE)*IpmiBlobTransferDelete, >>> + (IPMI_BLOB_TRANSFER_PROTOCOL_STAT)*IpmiBlobTransferStat, >>> + >> (IPMI_BLOB_TRANSFER_PROTOCOL_SESSION_STAT)*IpmiBlobTransferSessi >> onStat, >>> + >> (IPMI_BLOB_TRANSFER_PROTOCOL_WRITE_META)*IpmiBlobTransferWrite >> Meta >>> +}; >>> + >>> +const UINT8 OpenBmcOen[] =3D { 0xCF, 0xC2, 0x00 }; // OpenBM= C OEN >> code in little endian format >> >> I don=E2=80=99t know what =E2=80=9COen=E2=80=9D means. Should it be =E2= =80=9COem=E2=80=9D or =E2=80=9CIANA=E2=80=9D number? > This is the OEM number defined by openbmc phosphor blob transfer interfac= e for openbmc. > https://github.com/openbmc/phosphor-ipmi-blobs#phosphor-blob-transfer-int= erface so it is a short form of "OEM number", that is my mistake for not=20 reading the document carefully, thank you >> And this number can be configured, other OEMs will have their own number= . > Openbmc is already the OEM that uses this OEN number (49871). I consider = this is a industry standard for openbmc IPMI BLOB transfer and it is unnece= ssary to be override by others, right? Any use case you can think of to mak= e this value configurable? The first thing that comes to my mind is that it is a part of a message.=20 It will have some meaning that helps BMC to know what exactly it needs=20 to do. If OEN is always fixed, why do we need it as a part of the message? Hmm as you suggested, it is good to use it as an industry standard for=20 OpenBMC. Let's use fixed number (49871) If they support more OEN numbers, we will support later > Thanks > Abner > >> This number should be provided by drivers that consume this protocol >> >>> + >>> +/** >>> + Calculate CRC-16-CCITT with poly of 0x1021 >>> + >>> + @param[in] Data The target data. >>> + @param[in] DataSize The target data size. >>> + >>> + @return UINT16 The CRC16 value. >>> + >>> +**/ >>> +UINT16 >>> +CalculateCrc16 ( >>> + IN UINT8 *Data, >>> + IN UINTN DataSize >>> + ) >>> +{ >>> + UINTN Index; >>> + UINTN BitIndex; >>> + UINT16 Crc =3D 0xFFFF; >>> + UINT16 Poly =3D 0x1021; >>> + BOOLEAN XorFlag =3D FALSE; >>> + >>> + for (Index =3D 0; Index < (DataSize + 2); ++Index) { >>> + for (BitIndex =3D 0; BitIndex < 8; ++BitIndex) { >>> + XorFlag =3D (Crc & 0x8000) ? TRUE : FALSE; >>> + Crc <<=3D 1; >>> + if ((Index < DataSize) && (Data[Index] & (1 << (7 - BitIndex))))= { >>> + Crc++; >>> + } >>> + >>> + if (XorFlag =3D=3D TRUE) { >>> + Crc ^=3D Poly; >>> + } >>> + } >>> + } >>> + >>> + #if BLOB_TRANSFER_DEBUG >>> + DEBUG ((DEBUG_INFO, "%a: CRC-16-CCITT %x\n", __FUNCTION__, Crc)); >>> + #endif >>> + >>> + return Crc; >>> +} >>> + >>> +EFI_STATUS >>> +IpmiBlobTransferSendIpmi ( >>> + IN UINT8 SubCommand, >>> + IN UINT8 *SendData, >>> + IN UINT32 SendDataSize, >>> + OUT UINT8 *ResponseData, >>> + OUT UINT32 *ResponseDataSize >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT8 CompletionCode; >>> + UINT16 Crc; >>> + UINT8 Oen[3]; >>> + UINT8 *IpmiSendData; >>> + UINT32 IpmiSendDataSize; >>> + UINT8 *IpmiResponseData; >>> + UINT8 *ModifiedResponseData; >>> + UINT32 IpmiResponseDataSize; >>> + IPMI_BLOB_TRANSFER_HEADER Header; >>> + >>> + Crc =3D 0; >>> + >>> + // >>> + // Prepend the proper header to the SendData >>> + // >>> + IpmiSendDataSize =3D (sizeof (IPMI_BLOB_TRANSFER_HEADER)); >>> + if (SendDataSize) { >>> + IpmiSendDataSize +=3D sizeof (Crc) + (sizeof (UINT8) * SendDataSiz= e); >>> + } >>> + >>> + IpmiSendData =3D AllocateZeroPool (IpmiSendDataSize); >>> + if (IpmiSendData =3D=3D NULL) { >>> + return EFI_OUT_OF_RESOURCES; >>> + } >>> + >>> + Header.OEN[0] =3D OpenBmcOen[0]; >>> + Header.OEN[1] =3D OpenBmcOen[1]; >>> + Header.OEN[2] =3D OpenBmcOen[2]; >>> + Header.SubCommand =3D SubCommand; >>> + CopyMem (IpmiSendData, &Header, sizeof >> (IPMI_BLOB_TRANSFER_HEADER)); >>> + if (SendDataSize) { >>> + // >>> + // Calculate the Crc of the send data >>> + // >>> + Crc =3D CalculateCrc16 (SendData, SendDataSize); >>> + CopyMem (IpmiSendData + sizeof (IPMI_BLOB_TRANSFER_HEADER), >> &Crc, sizeof (UINT16)); >>> + CopyMem (IpmiSendData + sizeof (IPMI_BLOB_TRANSFER_HEADER) + >> sizeof (UINT16), SendData, SendDataSize); >>> + } >>> + >>> + #if BLOB_TRANSFER_DEBUG >>> + DEBUG ((DEBUG_INFO, "%a: Inputs:\n", __FUNCTION__)); >>> + DEBUG ((DEBUG_INFO, "%a: SendDataSize: %02x\nData: ", >> __FUNCTION__, SendDataSize)); >>> + UINT8 i; >>> + for (i =3D 0; i < SendDataSize; i++) { >>> + DEBUG ((DEBUG_INFO, "%02x", *((UINT8 *)SendData + i))); >>> + } >>> + >>> + DEBUG ((DEBUG_INFO, "\n")); >>> + DEBUG ((DEBUG_INFO, "%a: IpmiSendDataSize: %02x\nData: ", >> __FUNCTION__, IpmiSendDataSize)); >>> + for (i =3D 0; i < IpmiSendDataSize; i++) { >>> + DEBUG ((DEBUG_INFO, "%02x", *((UINT8 *)IpmiSendData + i))); >>> + } >>> + >>> + DEBUG ((DEBUG_INFO, "\n")); >>> + #endif >>> + >>> + IpmiResponseDataSize =3D (*ResponseDataSize + >> PROTOCOL_RESPONSE_OVERHEAD); >>> + // >>> + // If expecting data to be returned, we have to also account for the= 16 bit >> CRC >>> + // >>> + if (*ResponseDataSize) { >>> + IpmiResponseDataSize +=3D sizeof (Crc); >>> + } >>> + >>> + IpmiResponseData =3D AllocateZeroPool (IpmiResponseDataSize); >>> + if (IpmiResponseData =3D=3D NULL) { >>> + return EFI_OUT_OF_RESOURCES; >>> + } >>> + >>> + Status =3D IpmiSubmitCommand ( >>> + IPMI_NETFN_OEM, >>> + IPMI_OEM_BLOB_TRANSFER_CMD, >>> + (VOID *)IpmiSendData, >>> + IpmiSendDataSize, >>> + (VOID *)IpmiResponseData, >>> + &IpmiResponseDataSize >>> + ); >>> + >>> + FreePool (IpmiSendData); >>> + ModifiedResponseData =3D IpmiResponseData; >>> + >>> + #if BLOB_TRANSFER_DEBUG >>> + DEBUG ((DEBUG_INFO, "%a: IPMI Response:\n", __FUNCTION__)); >>> + DEBUG ((DEBUG_INFO, "%a: ResponseDataSize: %02x\nData: ", >> __FUNCTION__, IpmiResponseDataSize)); >>> + for (i =3D 0; i < IpmiResponseDataSize; i++) { >>> + DEBUG ((DEBUG_INFO, "%02x", *(ModifiedResponseData + i))); >>> + } >>> + >>> + DEBUG ((DEBUG_INFO, "\n")); >>> + #endif >>> + >>> + if (EFI_ERROR (Status)) { >>> + return Status; >>> + } >>> + >>> + CompletionCode =3D *ModifiedResponseData; >>> + if (CompletionCode !=3D IPMI_COMP_CODE_NORMAL) { >>> + DEBUG ((DEBUG_ERROR, "%a: Returning because CompletionCode =3D >> 0x%x\n", __FUNCTION__, CompletionCode)); >>> + FreePool (IpmiResponseData); >>> + return EFI_PROTOCOL_ERROR; >>> + } >>> + >>> + // Strip completion code, we are done with it >>> + ModifiedResponseData =3D ModifiedResponseData + sizeof >> (CompletionCode); >>> + IpmiResponseDataSize -=3D sizeof (CompletionCode); >>> + >>> + // Check OEN code and verify it matches the OpenBMC OEN >>> + CopyMem (Oen, ModifiedResponseData, sizeof (OpenBmcOen)); >>> + if (CompareMem (Oen, OpenBmcOen, sizeof (OpenBmcOen)) !=3D 0) { >>> + FreePool (IpmiResponseData); >>> + return EFI_PROTOCOL_ERROR; >>> + } >>> + >>> + if (IpmiResponseDataSize =3D=3D sizeof (OpenBmcOen)) { >>> + // >>> + // In this case, there was no response data sent. This is not an e= rror. >>> + // Some messages do not require a response. >>> + // >>> + *ResponseDataSize =3D 0; >>> + FreePool (IpmiResponseData); >>> + return Status; >>> + // Now we need to validate the CRC then send the Response body bac= k >>> + } else { >>> + // Strip the OEN, we are done with it now >>> + ModifiedResponseData =3D ModifiedResponseData + sizeof (Oen); >>> + IpmiResponseDataSize -=3D sizeof (Oen); >>> + // Then validate the Crc >>> + CopyMem (&Crc, ModifiedResponseData, sizeof (Crc)); >>> + ModifiedResponseData =3D ModifiedResponseData + sizeof (Crc); >>> + IpmiResponseDataSize -=3D sizeof (Crc); >>> + >>> + if (Crc =3D=3D CalculateCrc16 (ModifiedResponseData, >> IpmiResponseDataSize)) { >>> + CopyMem (ResponseData, ModifiedResponseData, >> IpmiResponseDataSize); >>> + CopyMem (ResponseDataSize, &IpmiResponseDataSize, sizeof >> (IpmiResponseDataSize)); >>> + FreePool (IpmiResponseData); >>> + return EFI_SUCCESS; >>> + } else { >>> + FreePool (IpmiResponseData); >>> + return EFI_CRC_ERROR; >>> + } >>> + } >>> +} >>> + >>> +/** >>> + @param[out] Count The number of active blobs >>> + >>> + @retval EFI_SUCCESS The command byte stream was successfu= lly >> submit to the device and a response was successfully received. >>> + @retval EFI_PROTOCOL_ERROR The Ipmi command failed >>> + @retval EFI_CRC_ERROR The Ipmi command returned a bad >> checksum >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferGetCount ( >>> + OUT UINT32 *Count >>> + ) >>> +{ >> Please add the argument validation for functions which expose for other >> drivers >> >> >>> + EFI_STATUS Status; >>> + UINT8 *ResponseData; >>> + UINT32 ResponseDataSize; >>> + >>> + ResponseDataSize =3D sizeof >> (IPMI_BLOB_TRANSFER_GET_COUNT_RESPONSE); >>> + ResponseData =3D AllocateZeroPool (ResponseDataSize); >>> + if (ResponseData =3D=3D NULL) { >>> + return EFI_OUT_OF_RESOURCES; >>> + } >>> + >>> + Status =3D IpmiBlobTransferSendIpmi >> (IpmiBlobTransferSubcommandGetCount, NULL, 0, (UINT8 *)ResponseData, >> &ResponseDataSize); >>> + if (!EFI_ERROR (Status)) { >>> + *Count =3D ((IPMI_BLOB_TRANSFER_GET_COUNT_RESPONSE >> *)ResponseData)->BlobCount; >>> + } >>> + >>> + FreePool (ResponseData); >>> + return Status; >>> +} >>> + >>> +/** >>> + @param[in] BlobIndex The 0-based Index of the blob to >> enumerate >>> + @param[out] BlobId The ID of the blob >>> + >>> + @retval EFI_SUCCESS Successfully enumerated the blob. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferEnumerate ( >>> + IN UINT32 BlobIndex, >>> + OUT CHAR8 *BlobId >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + >>> + UINT8 *SendData; >>> + UINT8 *ResponseData; >>> + UINT32 SendDataSize; >>> + UINT32 ResponseDataSize; >>> + >>> + if (BlobId =3D=3D NULL) { >>> + ASSERT (FALSE); >>> + return EFI_ABORTED; >>> + } >>> + >>> + ResponseDataSize =3D sizeof >> (IPMI_BLOB_TRANSFER_BLOB_ENUMERATE_RESPONSE); >>> + ResponseData =3D AllocateZeroPool (ResponseDataSize); >>> + if (ResponseData =3D=3D NULL) { >>> + return EFI_OUT_OF_RESOURCES; >>> + } >>> + >>> + // >>> + // Format send data >>> + // >>> + SendDataSize =3D sizeof >> (IPMI_BLOB_TRANSFER_BLOB_ENUMERATE_SEND_DATA); >>> + SendData =3D AllocateZeroPool (SendDataSize); >>> + if (SendData =3D=3D NULL) { >>> + return EFI_OUT_OF_RESOURCES; >>> + } >>> + >>> + ((IPMI_BLOB_TRANSFER_BLOB_ENUMERATE_SEND_DATA *)SendData)- >>> BlobIndex =3D BlobIndex; >>> + >>> + Status =3D IpmiBlobTransferSendIpmi >> (IpmiBlobTransferSubcommandEnumerate, SendData, SendDataSize, (UINT8 >> *)ResponseData, &ResponseDataSize); >>> + if (!EFI_ERROR (Status)) { >>> + AsciiStrCpyS (BlobId, ResponseDataSize, (CHAR8 *)ResponseData); >>> + } >>> + >>> + FreePool (ResponseData); >>> + return Status; >>> +} >>> + >>> +/** >>> + @param[in] BlobId The ID of the blob to open >>> + @param[in] Flags Flags to control how the blob is = opened >>> + @param[out] SessionId A unique session identifier >>> + >>> + @retval EFI_SUCCESS Successfully opened the blob. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferOpen ( >>> + IN CHAR8 *BlobId, >>> + IN UINT16 Flags, >>> + OUT UINT16 *SessionId >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT8 *SendData; >>> + UINT8 *ResponseData; >>> + UINT32 SendDataSize; >>> + UINT32 ResponseDataSize; >>> + CHAR8 *BlobSearch; >>> + UINT32 NumBlobs; >>> + UINT16 Index; >>> + BOOLEAN BlobFound; >>> + >>> + // >>> + // Before opening a blob, need to check if it exists >>> + // >>> + Status =3D IpmiBlobTransferGetCount (&NumBlobs); >> I think it should be removed as that will duplicate work >> >> The drivers using IPMI blob protocol will "get count" themselves. >> >>> + if (EFI_ERROR (Status) || (NumBlobs =3D=3D 0)) { >>> + if (Status =3D=3D EFI_UNSUPPORTED) { >>> + return Status; >>> + } >>> + >>> + DEBUG ((DEBUG_ERROR, "%a: Could not find any blobs: %r\n", >> __FUNCTION__, Status)); >>> + return EFI_NOT_FOUND; >>> + } >>> + >>> + BlobSearch =3D AllocateZeroPool (sizeof (CHAR8) * >> IPMI_OEM_BLOB_MAX_DATA_PER_PACKET); >>> + if (BlobSearch =3D=3D NULL) { >>> + return EFI_OUT_OF_RESOURCES; >>> + } >>> + >>> + BlobFound =3D FALSE; >>> + for (Index =3D 0; Index < NumBlobs; Index++) { >>> + Status =3D IpmiBlobTransferEnumerate (Index, BlobSearch); >> the same here >>> + if ((!EFI_ERROR (Status)) && (AsciiStrCmp (BlobSearch, BlobId) =3D= =3D 0)) { >>> + BlobFound =3D TRUE; >>> + break; >>> + } else { >>> + continue; >>> + } >>> + } >>> + >>> + if (!BlobFound) { >>> + DEBUG ((DEBUG_ERROR, "%a: Could not find a blob that matches %s\n"= , >> __FUNCTION__, BlobId)); >>> + FreePool (BlobSearch); >>> + return EFI_NOT_FOUND; >>> + } >>> + >>> + ResponseDataSize =3D sizeof >> (IPMI_BLOB_TRANSFER_BLOB_OPEN_RESPONSE); >>> + ResponseData =3D AllocateZeroPool (ResponseDataSize); >>> + if (ResponseData =3D=3D NULL) { >>> + return EFI_OUT_OF_RESOURCES; >>> + } >>> + >>> + // >>> + // Format send data >>> + // >>> + SendDataSize =3D sizeof >> (((IPMI_BLOB_TRANSFER_BLOB_OPEN_SEND_DATA *)SendData)->Flags) + >> ((AsciiStrLen (BlobId)) * sizeof (CHAR8)) + sizeof (CHAR8); >>> + SendData =3D AllocateZeroPool (SendDataSize); >>> + if (SendData =3D=3D NULL) { >>> + return EFI_OUT_OF_RESOURCES; >>> + } >>> + >>> + AsciiStrCpyS (((IPMI_BLOB_TRANSFER_BLOB_OPEN_SEND_DATA >> *)SendData)->BlobId, AsciiStrSize (BlobId) / sizeof (CHAR8), BlobId); >>> + ((IPMI_BLOB_TRANSFER_BLOB_OPEN_SEND_DATA *)SendData)->Flags >> =3D Flags; >>> + // append null char to SendData >>> + SendData[SendDataSize-1] =3D 0; >>> + >>> + Status =3D IpmiBlobTransferSendIpmi >> (IpmiBlobTransferSubcommandOpen, SendData, SendDataSize, (UINT8 >> *)ResponseData, &ResponseDataSize); >>> + if (!EFI_ERROR (Status)) { >>> + *SessionId =3D ((IPMI_BLOB_TRANSFER_BLOB_OPEN_RESPONSE >> *)ResponseData)->SessionId; >>> + } >>> + >>> + FreePool (ResponseData); >>> + FreePool (SendData); >>> + FreePool (BlobSearch); >>> + return Status; >>> +} >>> + >>> +/** >>> + @param[in] SessionId The session ID returned from a ca= ll to >> BlobOpen >>> + @param[in] Offset The offset of the blob from which= to start >> reading >>> + @param[in] RequestedSize The length of data to read >>> + @param[out] Data Data read from the blob >>> + >>> + @retval EFI_SUCCESS Successfully read from the blob. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferRead ( >>> + IN UINT16 SessionId, >>> + IN UINT32 Offset, >>> + IN UINT32 RequestedSize, >>> + OUT UINT8 *Data >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT8 *SendData; >>> + UINT8 *ResponseData; >>> + UINT32 SendDataSize; >>> + UINT32 ResponseDataSize; >>> + >>> + if (Data =3D=3D NULL) { >>> + ASSERT (FALSE); >>> + return EFI_ABORTED; >>> + } >>> + >>> + ResponseDataSize =3D RequestedSize * sizeof (UINT8); >>> + ResponseData =3D AllocateZeroPool (ResponseDataSize); >>> + if (ResponseData =3D=3D NULL) { >>> + return EFI_OUT_OF_RESOURCES; >>> + } >>> + >>> + // >>> + // Format send data >>> + // >>> + SendDataSize =3D sizeof >> (IPMI_BLOB_TRANSFER_BLOB_READ_SEND_DATA); >>> + SendData =3D AllocateZeroPool (SendDataSize); >>> + if (SendData =3D=3D NULL) { >>> + return EFI_OUT_OF_RESOURCES; >>> + } >>> + >>> + ((IPMI_BLOB_TRANSFER_BLOB_READ_SEND_DATA *)SendData)- >>> SessionId =3D SessionId; >>> + ((IPMI_BLOB_TRANSFER_BLOB_READ_SEND_DATA *)SendData)- >>> Offset =3D Offset; >>> + ((IPMI_BLOB_TRANSFER_BLOB_READ_SEND_DATA *)SendData)- >>> RequestedSize =3D RequestedSize; >>> + >>> + Status =3D IpmiBlobTransferSendIpmi (IpmiBlobTransferSubcommandRead, >> SendData, SendDataSize, (UINT8 *)ResponseData, &ResponseDataSize); >>> + if (!EFI_ERROR (Status)) { >>> + CopyMem (Data, ((IPMI_BLOB_TRANSFER_BLOB_READ_RESPONSE >> *)ResponseData)->Data, ResponseDataSize * sizeof (UINT8)); >>> + } >>> + >>> + FreePool (ResponseData); >>> + FreePool (SendData); >>> + return Status; >>> +} >>> + >>> +/** >>> + @param[in] SessionId The session ID returned from a ca= ll to >> BlobOpen >>> + @param[in] Offset The offset of the blob from which= to start >> writing >>> + @param[in] Data A pointer to the data to write >>> + >>> + @retval EFI_SUCCESS Successfully wrote to the blob. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferWrite ( >>> + IN UINT16 SessionId, >>> + IN UINT32 Offset, >>> + IN UINT8 *Data, >>> + IN UINT32 WriteLength >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT8 *SendData; >>> + UINT32 SendDataSize; >>> + UINT32 ResponseDataSize; >>> + >>> + // >>> + // Format send data >>> + // >>> + SendDataSize =3D sizeof (SessionId) + sizeof (Offset) + WriteLength; >>> + SendData =3D AllocateZeroPool (SendDataSize); >>> + if (SendData =3D=3D NULL) { >>> + return EFI_OUT_OF_RESOURCES; >>> + } >>> + >>> + ((IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA *)SendData)- >>> SessionId =3D SessionId; >>> + ((IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA *)SendData)- >>> Offset =3D Offset; >>> + CopyMem (((IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA >> *)SendData)->Data, Data, sizeof (UINT8) * WriteLength); >>> + >>> + ResponseDataSize =3D 0; >>> + Status =3D IpmiBlobTransferSendIpmi >> (IpmiBlobTransferSubcommandWrite, SendData, SendDataSize, NULL, >> &ResponseDataSize); >>> + >>> + FreePool (SendData); >>> + return Status; >>> +} >>> + >>> +/** >>> + @param[in] SessionId The session ID returned from a c= all to >> BlobOpen >>> + @param[in] CommitDataLength The length of data to commit to = the >> blob >>> + @param[in] CommitData A pointer to the data to commit >>> + >>> + @retval EFI_SUCCESS Successful commit to the blob. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferCommit ( >>> + IN UINT16 SessionId, >>> + IN UINT8 CommitDataLength, >>> + IN UINT8 *CommitData >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT8 *SendData; >>> + UINT32 SendDataSize; >>> + UINT32 ResponseDataSize; >>> + >>> + // >>> + // Format send data >>> + // >>> + SendDataSize =3D sizeof (SessionId) + sizeof (CommitDataLength) + >> CommitDataLength; >>> + SendData =3D AllocateZeroPool (SendDataSize); >>> + if (SendData =3D=3D NULL) { >>> + return EFI_OUT_OF_RESOURCES; >>> + } >>> + >>> + ((IPMI_BLOB_TRANSFER_BLOB_COMMIT_SEND_DATA *)SendData)- >>> SessionId =3D SessionId; >>> + ((IPMI_BLOB_TRANSFER_BLOB_COMMIT_SEND_DATA *)SendData)- >>> CommitDataLength =3D CommitDataLength; >>> + CopyMem (((IPMI_BLOB_TRANSFER_BLOB_COMMIT_SEND_DATA >> *)SendData)->CommitData, CommitData, sizeof (UINT8) * >> CommitDataLength); >>> + >>> + ResponseDataSize =3D 0; >>> + >>> + Status =3D IpmiBlobTransferSendIpmi >> (IpmiBlobTransferSubcommandCommit, SendData, SendDataSize, NULL, >> &ResponseDataSize); >>> + >>> + FreePool (SendData); >>> + return Status; >>> +} >>> + >>> +/** >>> + @param[in] SessionId The session ID returned from a ca= ll to >> BlobOpen >>> + >>> + @retval EFI_SUCCESS The blob was closed. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferClose ( >>> + IN UINT16 SessionId >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT8 *SendData; >>> + UINT32 SendDataSize; >>> + UINT32 ResponseDataSize; >>> + >>> + // >>> + // Format send data >>> + // >>> + SendDataSize =3D sizeof >> (IPMI_BLOB_TRANSFER_BLOB_CLOSE_SEND_DATA); >>> + SendData =3D AllocateZeroPool (SendDataSize); >>> + if (SendData =3D=3D NULL) { >>> + return EFI_OUT_OF_RESOURCES; >>> + } >>> + >>> + ((IPMI_BLOB_TRANSFER_BLOB_CLOSE_SEND_DATA *)SendData)- >>> SessionId =3D SessionId; >>> + >>> + ResponseDataSize =3D 0; >>> + >>> + Status =3D IpmiBlobTransferSendIpmi (IpmiBlobTransferSubcommandClose= , >> SendData, SendDataSize, NULL, &ResponseDataSize); >>> + >>> + FreePool (SendData); >>> + return Status; >>> +} >>> + >>> +/** >>> + @param[in] BlobId The BlobId to be deleted >>> + >>> + @retval EFI_SUCCESS The blob was deleted. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferDelete ( >>> + IN CHAR8 *BlobId >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT8 *SendData; >>> + UINT32 SendDataSize; >>> + UINT32 ResponseDataSize; >>> + >>> + // >>> + // Format send data >>> + // >>> + SendDataSize =3D sizeof >> (IPMI_BLOB_TRANSFER_BLOB_DELETE_SEND_DATA); >>> + SendData =3D AllocateZeroPool (SendDataSize); >>> + if (SendData =3D=3D NULL) { >>> + return EFI_OUT_OF_RESOURCES; >>> + } >>> + >>> + AsciiStrCpyS (((IPMI_BLOB_TRANSFER_BLOB_DELETE_SEND_DATA >> *)SendData)->BlobId, AsciiStrLen (BlobId), BlobId); >>> + >>> + ResponseDataSize =3D 0; >>> + >>> + Status =3D IpmiBlobTransferSendIpmi >> (IpmiBlobTransferSubcommandDelete, SendData, SendDataSize, NULL, >> &ResponseDataSize); >>> + >>> + FreePool (SendData); >>> + return Status; >>> +} >>> + >>> +/** >>> + @param[in] BlobId The Blob ID to gather statistics = for >>> + @param[out] BlobState The current state of the blob >>> + @param[out] Size Size in bytes of the blob >>> + @param[out] MetadataLength Length of the optional metadata >>> + @param[out] Metadata Optional blob-specific metadata >>> + >>> + @retval EFI_SUCCESS The blob statistics were successf= ully >> gathered. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferStat ( >>> + IN CHAR8 *BlobId, >>> + OUT UINT16 *BlobState, >>> + OUT UINT32 *Size, >>> + OUT UINT8 *MetadataLength, >>> + OUT UINT8 *Metadata >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT8 *SendData; >>> + UINT8 *ResponseData; >>> + UINT32 SendDataSize; >>> + UINT32 ResponseDataSize; >>> + >>> + if (Metadata =3D=3D NULL) { >>> + ASSERT (FALSE); >>> + return EFI_ABORTED; >>> + } >>> + >>> + ResponseDataSize =3D sizeof >> (IPMI_BLOB_TRANSFER_BLOB_STAT_RESPONSE); >>> + ResponseData =3D AllocateZeroPool (ResponseDataSize); >>> + if (ResponseData =3D=3D NULL) { >>> + return EFI_OUT_OF_RESOURCES; >>> + } >>> + >>> + // >>> + // Format send data >>> + // >>> + SendDataSize =3D sizeof >> (IPMI_BLOB_TRANSFER_BLOB_STAT_SEND_DATA); >>> + SendData =3D AllocateZeroPool (SendDataSize); >>> + if (SendData =3D=3D NULL) { >>> + return EFI_OUT_OF_RESOURCES; >>> + } >>> + >>> + AsciiStrCpyS (((IPMI_BLOB_TRANSFER_BLOB_STAT_SEND_DATA >> *)SendData)->BlobId, IPMI_OEM_BLOB_MAX_DATA_PER_PACKET, BlobId); >>> + >>> + Status =3D IpmiBlobTransferSendIpmi (IpmiBlobTransferSubcommandStat, >> SendData, SendDataSize, (UINT8 *)ResponseData, &ResponseDataSize); >>> + if (!EFI_ERROR (Status)) { >>> + *BlobState =3D ((IPMI_BLOB_TRANSFER_BLOB_STAT_RESPONSE >> *)ResponseData)->BlobState; >>> + *Size =3D ((IPMI_BLOB_TRANSFER_BLOB_STAT_RESPONSE >> *)ResponseData)->Size; >>> + *MetadataLength =3D ((IPMI_BLOB_TRANSFER_BLOB_STAT_RESPONSE >> *)ResponseData)->MetaDataLen; >>> + >>> + CopyMem (&Metadata, >> &((IPMI_BLOB_TRANSFER_BLOB_STAT_RESPONSE *)ResponseData)- >>> MetaData, sizeof (((IPMI_BLOB_TRANSFER_BLOB_STAT_RESPONSE >> *)ResponseData)->MetaData)); >>> + } >>> + >>> + FreePool (ResponseData); >>> + FreePool (SendData); >>> + return Status; >>> +} >>> + >>> +/** >>> + @param[in] SessionId The ID of the session to gather s= tatistics for >>> + @param[out] BlobState The current state of the blob >>> + @param[out] Size Size in bytes of the blob >>> + @param[out] MetadataLength Length of the optional metadata >>> + @param[out] Metadata Optional blob-specific metadata >>> + >>> + @retval EFI_SUCCESS The blob statistics were successf= ully >> gathered. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferSessionStat ( >>> + IN UINT16 SessionId, >>> + OUT UINT16 *BlobState, >>> + OUT UINT32 *Size, >>> + OUT UINT8 *MetadataLength, >>> + OUT UINT8 *Metadata >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT8 *SendData; >>> + UINT8 *ResponseData; >>> + UINT32 SendDataSize; >>> + UINT32 ResponseDataSize; >>> + >>> + if ((BlobState =3D=3D NULL) || (Size =3D=3D NULL) || (MetadataLength= =3D=3D NULL) >> || (Metadata =3D=3D NULL)) { >>> + ASSERT (FALSE); >>> + return EFI_ABORTED; >>> + } >>> + >>> + ResponseDataSize =3D sizeof >> (IPMI_BLOB_TRANSFER_BLOB_STAT_RESPONSE); >>> + ResponseData =3D AllocateZeroPool (ResponseDataSize); >>> + if (ResponseData =3D=3D NULL) { >>> + return EFI_OUT_OF_RESOURCES; >>> + } >>> + >>> + // >>> + // Format send data >>> + // >>> + SendDataSize =3D sizeof >> (IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_SEND_DATA); >>> + SendData =3D AllocateZeroPool (SendDataSize); >>> + if (SendData =3D=3D NULL) { >>> + return EFI_OUT_OF_RESOURCES; >>> + } >>> + >>> + ((IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_SEND_DATA >> *)SendData)->SessionId =3D SessionId; >>> + >>> + Status =3D IpmiBlobTransferSendIpmi >> (IpmiBlobTransferSubcommandSessionStat, SendData, SendDataSize, (UINT8 >> *)ResponseData, &ResponseDataSize); >>> + >>> + if (!EFI_ERROR (Status)) { >>> + *BlobState =3D >> ((IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_RESPONSE >> *)ResponseData)->BlobState; >>> + *Size =3D ((IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_RESPONS= E >> *)ResponseData)->Size; >>> + *MetadataLength =3D >> ((IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_RESPONSE >> *)ResponseData)->MetaDataLen; >>> + >>> + CopyMem (&Metadata, >> &((IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_RESPONSE >> *)ResponseData)->MetaData, sizeof >> (((IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_RESPONSE >> *)ResponseData)->MetaData)); >>> + } >>> + >>> + FreePool (ResponseData); >>> + FreePool (SendData); >>> + return Status; >>> +} >>> + >>> +/** >>> + @param[in] SessionId The ID of the session to write me= tadata for >>> + @param[in] Offset The offset of the metadata to wri= te to >>> + @param[in] Data The data to write to the metadata >>> + >>> + @retval EFI_SUCCESS The blob metadata was successfull= y written. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferWriteMeta ( >>> + IN UINT16 SessionId, >>> + IN UINT32 Offset, >>> + IN UINT8 *Data, >>> + IN UINT32 WriteLength >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT8 *SendData; >>> + UINT32 SendDataSize; >>> + UINT32 ResponseDataSize; >>> + >>> + // >>> + // Format send data >>> + // >>> + SendDataSize =3D sizeof >> (IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA); >>> + SendData =3D AllocateZeroPool (SendDataSize); >>> + if (SendData =3D=3D NULL) { >>> + return EFI_OUT_OF_RESOURCES; >>> + } >>> + >>> + ((IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA *)SendData)- >>> SessionId =3D SessionId; >>> + ((IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA *)SendData)- >>> Offset =3D Offset; >>> + CopyMem (((IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA >> *)SendData)->Data, Data, sizeof (UINT8) * WriteLength); >>> + >>> + ResponseDataSize =3D 0; >>> + >>> + Status =3D IpmiBlobTransferSendIpmi >> (IpmiBlobTransferSubcommandWriteMeta, SendData, SendDataSize, NULL, >> &ResponseDataSize); >>> + >>> + FreePool (SendData); >>> + return Status; >>> +} >>> + >>> +/** >>> + This is the declaration of an EFI image entry point. This entry poin= t is >>> + the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers >> including >>> + both device drivers and bus drivers. >>> + >>> + @param[in] ImageHandle The firmware allocated handle for the = UEFI >> image. >>> + @param[in] SystemTable A pointer to the EFI System Table. >>> + >>> + @retval EFI_SUCCESS The operation completed successfully. >>> + @retval Others An unexpected error occurred. >>> + >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +IpmiBlobTransferDxeDriverEntryPoint ( >>> + IN EFI_HANDLE ImageHandle, >>> + IN EFI_SYSTEM_TABLE *SystemTable >>> + ) >>> +{ >>> + return gBS->InstallMultipleProtocolInterfaces ( >>> + &ImageHandle, >>> + &gEdkiiIpmiBlobTransferProtocolGuid, >>> + (VOID *)&mIpmiBlobTransfer, >>> + NULL >>> + ); >>> +} >>> diff --git >> a/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/Ipmi >> BlobTransferTestUnitTests.c >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/Ipm >> iBlobTransferTestUnitTests.c >>> new file mode 100644 >>> index 0000000000..f326467922 >>> --- /dev/null >>> +++ >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/Ipm >> iBlobTransferTestUnitTests.c >>> @@ -0,0 +1,1113 @@ >>> +/** @file >>> +* >>> +* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. >> 2023 >>> +* >>> +* SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & >> AFFILIATES >>> +* SPDX-License-Identifier: BSD-2-Clause-Patent >>> +* >>> +**/ >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> + >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> + >>> +#include >>> +#include >>> +#include "../InternalIpmiBlobTransfer.h" >>> + >>> +#define UNIT_TEST_NAME "IPMI Blob Transfer Unit Tests" >>> +#define UNIT_TEST_VERSION "1.0" >>> + >>> +UINT8 InvalidCompletion[] =3D { >>> + 0xC0, // CompletionCode >>> + 0xCF, 0xC2, 0x00, // OpenBMC OEN >>> +}; >>> +#define INVALID_COMPLETION_SIZE 4 * sizeof(UINT8) >>> + >>> +UINT8 NoDataResponse[] =3D { >>> + 0x00, // CompletionCode >>> + 0xCF, 0xC2, 0x00, // OpenBMC OEN >>> +}; >>> +#define NO_DATA_RESPONSE_SIZE 4 * sizeof(UINT8) >>> + >>> +UINT8 BadOenResponse[] =3D { >>> + 0x00, // CompletionCode >>> + 0xFF, 0xC2, 0x00, // Wrong OEN >>> +}; >>> +#define BAD_OEN_RESPONSE_SIZE 4 * sizeof(UINT8) >>> + >>> +UINT8 BadCrcResponse[] =3D { >>> + 0x00, // CompletionCode >>> + 0xCF, 0xC2, 0x00, // OpenBMC OEN >>> + 0x00, 0x00, // CRC >>> + 0x01, 0x00, 0x00, 0x00, // Data >>> +}; >>> +#define BAD_CRC_RESPONSE_SIZE 10 * sizeof(UINT8) >>> + >>> +UINT8 ValidNoDataResponse[] =3D { >>> + 0x00, // CompletionCode >>> + 0xCF, 0xC2, 0x00, // OpenBMC OEN >>> +}; >>> + >>> +#define VALID_NODATA_RESPONSE_SIZE 4 * sizeof(UINT8) >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >> failed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +GoodCrc ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + UINT8 Data[5] =3D { 0x12, 0x34, 0x56, 0x78, 0x90 }; >>> + UINTN DataSize; >>> + UINT16 Crc; >>> + >>> + DataSize =3D sizeof (Data); >>> + >>> + Crc =3D CalculateCrc16 (Data, DataSize); >>> + >>> + UT_ASSERT_EQUAL (Crc, 0xB928); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >> failed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +BadCrc ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + UINT8 Data[5] =3D { 0x12, 0x34, 0x56, 0x78, 0x90 }; >>> + UINTN DataSize; >>> + UINT16 Crc; >>> + >>> + DataSize =3D sizeof (Data); >>> + >>> + Crc =3D CalculateCrc16 (Data, DataSize); >>> + >>> + UT_ASSERT_NOT_EQUAL (Crc, 0x3409); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >> failed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +SendIpmiBadCompletion ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + VOID *ResponseData; >>> + UINT32 *ResponseDataSize; >>> + EFI_STATUS Status; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool >> (INVALID_COMPLETION_SIZE); >>> + ResponseDataSize =3D (UINT32 *)AllocateZeroPool (sizeof (UINT32))= ; >>> + CopyMem (MockResponseResults, &InvalidCompletion, >> INVALID_COMPLETION_SIZE); >>> + >>> + MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> INVALID_COMPLETION_SIZE, EFI_SUCCESS); >>> + >>> + ResponseData =3D (UINT8 *)AllocateZeroPool (*ResponseDataSize); >>> + Status =3D IpmiBlobTransferSendIpmi >> (IpmiBlobTransferSubcommandGetCount, NULL, 0, ResponseData, >> ResponseDataSize); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_PROTOCOL_ERROR); >>> + FreePool (MockResponseResults); >>> + FreePool (ResponseDataSize); >>> + FreePool (ResponseData); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >> failed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +SendIpmiNoDataResponse ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + VOID *ResponseData; >>> + UINT32 *ResponseDataSize; >>> + EFI_STATUS Status; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool >> (NO_DATA_RESPONSE_SIZE); >>> + ResponseDataSize =3D (UINT32 *)AllocateZeroPool (sizeof (UINT32))= ; >>> + CopyMem (MockResponseResults, &NoDataResponse, >> NO_DATA_RESPONSE_SIZE); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> NO_DATA_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + ResponseData =3D (UINT8 *)AllocateZeroPool (sizeof (NoDataResponse))= ; >>> + Status =3D IpmiBlobTransferSendIpmi >> (IpmiBlobTransferSubcommandGetCount, NULL, 0, ResponseData, >> ResponseDataSize); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>> + UT_ASSERT_EQUAL (*ResponseDataSize, 0); >>> + FreePool (MockResponseResults); >>> + FreePool (ResponseDataSize); >>> + FreePool (ResponseData); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >> failed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +SendIpmiBadOenResponse ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + VOID *ResponseData; >>> + UINT32 *ResponseDataSize; >>> + EFI_STATUS Status; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool >> (BAD_OEN_RESPONSE_SIZE); >>> + ResponseDataSize =3D (UINT32 *)AllocateZeroPool (sizeof (UINT32))= ; >>> + CopyMem (MockResponseResults, &BadOenResponse, >> BAD_OEN_RESPONSE_SIZE); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> BAD_OEN_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + ResponseData =3D (UINT8 *)AllocateZeroPool (sizeof (BadOenResponse))= ; >>> + Status =3D IpmiBlobTransferSendIpmi >> (IpmiBlobTransferSubcommandGetCount, NULL, 0, ResponseData, >> ResponseDataSize); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_PROTOCOL_ERROR); >>> + FreePool (MockResponseResults); >>> + FreePool (ResponseDataSize); >>> + FreePool (ResponseData); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >> failed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +SendIpmiBadCrcResponse ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + VOID *ResponseData; >>> + UINT32 *ResponseDataSize; >>> + EFI_STATUS Status; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (BAD_CRC_RESPONSE_SIZE)); >>> + ResponseDataSize =3D (UINT32 *)AllocateZeroPool (sizeof (UINT32))= ; >>> + CopyMem (MockResponseResults, &BadCrcResponse, >> BAD_CRC_RESPONSE_SIZE); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> BAD_CRC_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + ResponseData =3D (UINT8 *)AllocateZeroPool (sizeof (BadCrcResponse))= ; >>> + Status =3D IpmiBlobTransferSendIpmi >> (IpmiBlobTransferSubcommandGetCount, NULL, 0, ResponseData, >> ResponseDataSize); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_CRC_ERROR); >>> + FreePool (MockResponseResults); >>> + FreePool (ResponseDataSize); >>> + FreePool (ResponseData); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +UINT8 ValidGetCountResponse[] =3D { >>> + 0x00, // CompletionCode >>> + 0xCF, 0xC2, 0x00, // OpenBMC OEN >>> + 0xA4, 0x78, // CRC >>> + 0x01, 0x00, 0x00, 0x00, // Data >>> +}; >>> +#define VALID_GET_COUNT_RESPONSE_SIZE 10 * sizeof(UINT8) >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >> failed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +SendIpmiValidCountResponse ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + UINT8 *ResponseData; >>> + UINT32 *ResponseDataSize; >>> + EFI_STATUS Status; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_GET_COUNT_RESPONSE_SIZE)); >>> + ResponseDataSize =3D (UINT32 *)AllocateZeroPool (sizeof (UINT32))= ; >>> + CopyMem (MockResponseResults, &ValidGetCountResponse, >> VALID_GET_COUNT_RESPONSE_SIZE); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> VALID_GET_COUNT_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + ResponseData =3D AllocateZeroPool (sizeof (ValidGetCountResponse)); >>> + Status =3D IpmiBlobTransferSendIpmi >> (IpmiBlobTransferSubcommandGetCount, NULL, 0, ResponseData, >> ResponseDataSize); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>> + FreePool (MockResponseResults); >>> + FreePool (ResponseDataSize); >>> + FreePool (ResponseData); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >> failed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +GetCountValidCountResponse ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT32 Count; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + Count =3D 0; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_GET_COUNT_RESPONSE_SIZE)); >>> + CopyMem (MockResponseResults, &ValidGetCountResponse, >> VALID_GET_COUNT_RESPONSE_SIZE); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> VALID_GET_COUNT_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + Status =3D IpmiBlobTransferGetCount (&Count); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>> + UT_ASSERT_EQUAL (Count, 1); >>> + FreePool (MockResponseResults); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +UINT8 ValidEnumerateResponse[] =3D { >>> + 0x00, // CompletionCode >>> + 0xCF, 0xC2, 0x00, // OpenBMC OEN >>> + 0x81, 0x13, // CRC >>> + 0x2F, 0x73, 0x6D, 0x62, // Data =3D "/smbios" >>> + 0x69, 0x6F, 0x73, 0x00, >>> +}; >>> +#define VALID_ENUMERATE_RESPONSE_SIZE 14 * sizeof(UINT8) >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >> failed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +EnumerateValidResponse ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + CHAR8 *BlobId; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_ENUMERATE_RESPONSE_SIZE)); >>> + CopyMem (MockResponseResults, &ValidEnumerateResponse, >> VALID_ENUMERATE_RESPONSE_SIZE); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> VALID_ENUMERATE_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + BlobId =3D AllocateZeroPool (sizeof (CHAR8) * >> IPMI_OEM_BLOB_MAX_DATA_PER_PACKET); >>> + >>> + Status =3D IpmiBlobTransferEnumerate (0, BlobId); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>> + UT_ASSERT_MEM_EQUAL (BlobId, "/smbios", 7); >>> + FreePool (MockResponseResults); >>> + FreePool (BlobId); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >> failed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +EnumerateInvalidBuffer ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + CHAR8 *BlobId; >>> + EFI_STATUS Status; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_ENUMERATE_RESPONSE_SIZE)); >>> + CopyMem (MockResponseResults, &ValidEnumerateResponse, >> VALID_ENUMERATE_RESPONSE_SIZE); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> VALID_ENUMERATE_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + BlobId =3D NULL; >>> + >>> + UT_EXPECT_ASSERT_FAILURE (IpmiBlobTransferEnumerate (0, BlobId), >> NULL); >>> + >>> + FreePool (MockResponseResults); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +UINT8 ValidOpenResponse[] =3D { >>> + 0x00, // CompletionCode >>> + 0xCF, 0xC2, 0x00, // OpenBMC OEN >>> + 0x93, 0xD1, // CRC >>> + 0x03, 0x00, // SessionId =3D 3 >>> +}; >>> +#define VALID_OPEN_RESPONSE_SIZE 8 * sizeof(UINT8) >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >> failed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +OpenValidResponse ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + CHAR8 *BlobId; >>> + UINT16 Flags; >>> + UINT16 SessionId; >>> + VOID *MockResponseResults =3D NULL; >>> + VOID *MockResponseResults2 =3D NULL; >>> + VOID *MockResponseResults3 =3D NULL; >>> + >>> + Flags =3D BLOB_TRANSFER_STAT_OPEN_W; >>> + >>> + // >>> + // An open call effectively leads to three IPMI commands >>> + // 1. GetCount of blobs >>> + // 2. Enumerate the requested blob >>> + // 3. Open the requested blob >>> + // >>> + // So we'll push three Ipmi responses in this case >>> + // >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_OPEN_RESPONSE_SIZE)); >>> + >>> + CopyMem (MockResponseResults, &ValidOpenResponse, >> VALID_OPEN_RESPONSE_SIZE); >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> VALID_OPEN_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + MockResponseResults2 =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_ENUMERATE_RESPONSE_SIZE)); >>> + CopyMem (MockResponseResults2, &ValidEnumerateResponse, >> VALID_ENUMERATE_RESPONSE_SIZE); >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults2, >> VALID_ENUMERATE_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + MockResponseResults3 =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_GET_COUNT_RESPONSE_SIZE)); >>> + CopyMem (MockResponseResults3, &ValidGetCountResponse, >> VALID_GET_COUNT_RESPONSE_SIZE); >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults3, >> VALID_GET_COUNT_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + BlobId =3D "/smbios"; >>> + >>> + Status =3D IpmiBlobTransferOpen (BlobId, Flags, &SessionId); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>> + UT_ASSERT_EQUAL (SessionId, 3); >>> + FreePool (MockResponseResults); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +UINT8 ValidReadResponse[] =3D { >>> + 0x00, // CompletionCode >>> + 0xCF, 0xC2, 0x00, // OpenBMC OEN >>> + 0x21, 0x6F, // CRC >>> + 0x00, 0x01, 0x02, 0x03, // Data to read >>> +}; >>> + >>> +#define VALID_READ_RESPONSE_SIZE 10 * sizeof(UINT8) >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >> failed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +ReadValidResponse ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT8 *ResponseData; >>> + UINT8 ExpectedDataResponse[4] =3D { 0x00, 0x01, 0x02, 0x03 }; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_READ_RESPONSE_SIZE)); >>> + CopyMem (MockResponseResults, &ValidReadResponse, >> VALID_READ_RESPONSE_SIZE); >>> + ResponseData =3D AllocateZeroPool (sizeof (ValidReadResponse)); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> VALID_READ_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + Status =3D IpmiBlobTransferRead (0, 0, 4, ResponseData); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>> + UT_ASSERT_MEM_EQUAL (ResponseData, ExpectedDataResponse, 4); >>> + FreePool (MockResponseResults); >>> + FreePool (ResponseData); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >> failed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +ReadInvalidBuffer ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + UINT8 *ResponseData; >>> + EFI_STATUS Status; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_READ_RESPONSE_SIZE)); >>> + CopyMem (MockResponseResults, &ValidReadResponse, >> VALID_READ_RESPONSE_SIZE); >>> + ResponseData =3D NULL; >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> VALID_READ_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + UT_EXPECT_ASSERT_FAILURE (IpmiBlobTransferRead (0, 0, 4, >> ResponseData), NULL); >>> + >>> + FreePool (MockResponseResults); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >> failed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +WriteValidResponse ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT8 SendData[4] =3D { 0x00, 0x01, 0x02, 0x03 }; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_NODATA_RESPONSE_SIZE)); >>> + CopyMem (MockResponseResults, &ValidNoDataResponse, >> VALID_NODATA_RESPONSE_SIZE); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> VALID_NODATA_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + Status =3D IpmiBlobTransferWrite (0, 0, SendData, 4); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>> + FreePool (MockResponseResults); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >> failed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +CommitValidResponse ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT8 SendData[4] =3D { 0x00, 0x01, 0x02, 0x03 }; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_NODATA_RESPONSE_SIZE)); >>> + CopyMem (MockResponseResults, &ValidNoDataResponse, >> VALID_NODATA_RESPONSE_SIZE); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> VALID_NODATA_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + Status =3D IpmiBlobTransferCommit (0, 4, SendData); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>> + FreePool (MockResponseResults); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >> failed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +CloseValidResponse ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_NODATA_RESPONSE_SIZE)); >>> + CopyMem (MockResponseResults, &ValidNoDataResponse, >> VALID_NODATA_RESPONSE_SIZE); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> VALID_NODATA_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + Status =3D IpmiBlobTransferClose (1); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>> + FreePool (MockResponseResults); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >> failed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +DeleteValidResponse ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_NODATA_RESPONSE_SIZE)); >>> + CopyMem (MockResponseResults, &ValidNoDataResponse, >> VALID_NODATA_RESPONSE_SIZE); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> VALID_NODATA_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + Status =3D IpmiBlobTransferDelete ("/smbios"); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>> + FreePool (MockResponseResults); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +UINT8 ValidBlobStatResponse[] =3D { >>> + 0x00, // CompletionCode >>> + 0xCF, 0xC2, 0x00, // OpenBMC OEN >>> + 0x1F, 0x4F, // Crc >>> + 0x01, 0x00, // BlobState >>> + 0x02, 0x03, 0x04, 0x05, // BlobSize >>> + 0x04, // MetaDataLen >>> + 0x06, 0x07, 0x08, 0x09, // MetaData >>> +}; >>> + >>> +#define VALID_BLOB_STAT_RESPONSE_SIZE 17 * sizeof(UINT8) >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >> failed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +BlobStatValidResponse ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT16 *BlobState; >>> + UINT32 *Size; >>> + UINT8 *MetadataLength; >>> + UINT8 *Metadata; >>> + UINT8 *ExpectedMetadata; >>> + CHAR8 *BlobId; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + BlobState =3D AllocateZeroPool (sizeof (UINT16)); >>> + Size =3D AllocateZeroPool (sizeof (UINT32)); >>> + BlobId =3D "BlobId"; >>> + MetadataLength =3D AllocateZeroPool (sizeof (UINT8)); >>> + Metadata =3D AllocateZeroPool (4 * sizeof (UINT8)); >>> + ExpectedMetadata =3D AllocateZeroPool (4 * sizeof (UINT8)); >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_BLOB_STAT_RESPONSE_SIZE)); >>> + CopyMem (MockResponseResults, &ValidBlobStatResponse, >> VALID_BLOB_STAT_RESPONSE_SIZE); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> VALID_BLOB_STAT_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + Status =3D IpmiBlobTransferStat (BlobId, BlobState, Size, MetadataLe= ngth, >> Metadata); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>> + UT_ASSERT_EQUAL (*BlobState, 1); >>> + UT_ASSERT_EQUAL (*Size, 0x05040302); >>> + UT_ASSERT_EQUAL (*MetadataLength, 4); >>> + UT_ASSERT_MEM_EQUAL (Metadata, ExpectedMetadata, 4); >>> + FreePool (MockResponseResults); >>> + FreePool (BlobState); >>> + FreePool (Size); >>> + FreePool (MetadataLength); >>> + FreePool (Metadata); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >> failed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +BlobStatInvalidBuffer ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + UINT8 *Metadata; >>> + EFI_STATUS Status; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + Metadata =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_BLOB_STAT_RESPONSE_SIZE)); >>> + CopyMem (MockResponseResults, &ValidBlobStatResponse, >> VALID_BLOB_STAT_RESPONSE_SIZE); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> VALID_BLOB_STAT_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + UT_EXPECT_ASSERT_FAILURE (IpmiBlobTransferStat (NULL, 0, 0, 0, >> Metadata), NULL); >>> + >>> + FreePool (MockResponseResults); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >> failed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +SessionStatValidResponse ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT16 *BlobState; >>> + UINT32 *Size; >>> + UINT8 *MetadataLength; >>> + UINT8 *Metadata; >>> + UINT8 *ExpectedMetadata; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + BlobState =3D AllocateZeroPool (sizeof (UINT16)); >>> + Size =3D AllocateZeroPool (sizeof (UINT32)); >>> + MetadataLength =3D AllocateZeroPool (sizeof (UINT8)); >>> + Metadata =3D AllocateZeroPool (4 * sizeof (UINT8)); >>> + ExpectedMetadata =3D AllocateZeroPool (4 * sizeof (UINT8)); >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_BLOB_STAT_RESPONSE_SIZE)); >>> + CopyMem (MockResponseResults, &ValidBlobStatResponse, >> VALID_BLOB_STAT_RESPONSE_SIZE); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> VALID_BLOB_STAT_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + Status =3D IpmiBlobTransferSessionStat (0, BlobState, Size, >> MetadataLength, Metadata); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>> + UT_ASSERT_EQUAL (*BlobState, 1); >>> + UT_ASSERT_EQUAL (*Size, 0x05040302); >>> + UT_ASSERT_EQUAL (*MetadataLength, 4); >>> + UT_ASSERT_MEM_EQUAL (Metadata, ExpectedMetadata, 4); >>> + FreePool (MockResponseResults); >>> + FreePool (BlobState); >>> + FreePool (Size); >>> + FreePool (MetadataLength); >>> + FreePool (Metadata); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >> failed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +SessionStatInvalidBuffer ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + UINT8 *Metadata; >>> + EFI_STATUS Status; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + Metadata =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_BLOB_STAT_RESPONSE_SIZE)); >>> + CopyMem (MockResponseResults, &ValidBlobStatResponse, >> VALID_BLOB_STAT_RESPONSE_SIZE); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> VALID_BLOB_STAT_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + UT_EXPECT_ASSERT_FAILURE (IpmiBlobTransferSessionStat (0, 0, 0, 0, >> Metadata), NULL); >>> + >>> + FreePool (MockResponseResults); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >> failed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +WriteMetaValidResponse ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_NODATA_RESPONSE_SIZE)); >>> + CopyMem (MockResponseResults, &ValidNoDataResponse, >> VALID_NODATA_RESPONSE_SIZE); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> VALID_NODATA_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + Status =3D IpmiBlobTransferWriteMeta (0, 0, NULL, 0); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>> + FreePool (MockResponseResults); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + Initialize the unit test framework, suite, and unit tests for the >>> + sample unit tests and run the unit tests. >>> + @retval EFI_SUCCESS All test cases were dispatched. >>> + @retval EFI_OUT_OF_RESOURCES There are not enough resources >> available to >>> + initialize the unit tests. >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +SetupAndRunUnitTests ( >>> + VOID >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UNIT_TEST_FRAMEWORK_HANDLE Framework; >>> + UNIT_TEST_SUITE_HANDLE IpmiBlobTransfer; >>> + >>> + Framework =3D NULL; >>> + DEBUG ((DEBUG_INFO, "%a: v%a\n", UNIT_TEST_NAME, >> UNIT_TEST_VERSION)); >>> + >>> + Status =3D InitUnitTestFramework (&Framework, UNIT_TEST_NAME, >> gEfiCallerBaseName, UNIT_TEST_VERSION); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG ((DEBUG_ERROR, "Failed to setup Test Framework. Exiting with >> status =3D %r\n", Status)); >>> + ASSERT (FALSE); >>> + return Status; >>> + } >>> + >>> + // >>> + // Populate the Unit Test Suite. >>> + // >>> + Status =3D CreateUnitTestSuite (&IpmiBlobTransfer, Framework, "IPMI >> Blob Transfer Tests", "UnitTest.IpmiBlobTransferCB", NULL, NULL); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for IPMI Blob >> Transfer Tests\n")); >>> + Status =3D EFI_OUT_OF_RESOURCES; >>> + return Status; >>> + } >>> + >>> + // CalculateCrc16 >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Test CRC Calculation", >> "GoodCrc", GoodCrc, NULL, NULL, NULL); >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Test Bad CRC Calculation"= , >> "BadCrc", BadCrc, NULL, NULL, NULL); >>> + // IpmiBlobTransferSendIpmi >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Send IPMI returns bad >> completion", "SendIpmiBadCompletion", SendIpmiBadCompletion, NULL, >> NULL, NULL); >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Send IPMI returns success= fully >> with no data", "SendIpmiNoDataResponse", SendIpmiNoDataResponse, >> NULL, NULL, NULL); >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Send IPMI returns success= fully >> with bad OEN", "SendIpmiBadOenResponse", SendIpmiBadOenResponse, >> NULL, NULL, NULL); >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Send IPMI returns success= fully >> with bad CRC", "SendIpmiBadCrcResponse", SendIpmiBadCrcResponse, >> NULL, NULL, NULL); >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Send IPMI returns with va= lid >> GetCount data", "SendIpmiValidCountResponse", >> SendIpmiValidCountResponse, NULL, NULL, NULL); >>> + // IpmiBlobTransferGetCount >>> + Status =3D AddTestCase (IpmiBlobTransfer, "GetCount call with valid = data", >> "GetCountValidCountResponse", GetCountValidCountResponse, NULL, >> NULL, NULL); >>> + // IpmiBlobTransferEnumerate >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Enumerate call with valid= data", >> "EnumerateValidResponse", EnumerateValidResponse, NULL, NULL, NULL); >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Enumerate call with inval= id >> output buffer", "EnumerateInvalidBuffer", EnumerateInvalidBuffer, NULL, >> NULL, NULL); >>> + // IpmiBlobTransferOpen >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Open call with valid data= ", >> "OpenValidResponse", OpenValidResponse, NULL, NULL, NULL); >>> + // IpmiBlobTransferRead >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Read call with valid data= ", >> "ReadValidResponse", ReadValidResponse, NULL, NULL, NULL); >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Read call with invalid bu= ffer", >> "ReadInvalidBuffer", ReadInvalidBuffer, NULL, NULL, NULL); >>> + // IpmiBlobTransferWrite >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Write call with valid dat= a", >> "WriteValidResponse", WriteValidResponse, NULL, NULL, NULL); >>> + // IpmiBlobTransferCommit >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Commit call with valid da= ta", >> "CommitValidResponse", CommitValidResponse, NULL, NULL, NULL); >>> + // IpmiBlobTransferClose >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Close call with valid dat= a", >> "CloseValidResponse", CloseValidResponse, NULL, NULL, NULL); >>> + // IpmiBlobTransferDelete >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Delete call with valid da= ta", >> "DeleteValidResponse", DeleteValidResponse, NULL, NULL, NULL); >>> + // IpmiBlobTransferStat >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Blob Stat call with valid= data", >> "BlobStatValidResponse", BlobStatValidResponse, NULL, NULL, NULL); >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Blob Stat call with inval= id >> buffer", "BlobStatInvalidBuffer", BlobStatInvalidBuffer, NULL, NULL, NUL= L); >>> + // IpmiBlobTransferSessionStat >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Session Stat call with va= lid >> data", "SessionStatValidResponse", SessionStatValidResponse, NULL, NULL, >> NULL); >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Session Stat call with in= valid >> buffer", "SessionStatInvalidBuffer", SessionStatInvalidBuffer, NULL, NUL= L, >> NULL); >>> + // IpmiBlobTransferWriteMeta >>> + Status =3D AddTestCase (IpmiBlobTransfer, "WriteMeta call with valid= data", >> "WriteMetaValidResponse", WriteMetaValidResponse, NULL, NULL, NULL); >>> + >>> + // Execute the tests. >>> + Status =3D RunAllTestSuites (Framework); >>> + return Status; >>> +} >>> + >>> +/** >>> + Standard UEFI entry point for target based >>> + unit test execution from UEFI Shell. >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +BaseLibUnitTestAppEntry ( >>> + IN EFI_HANDLE ImageHandle, >>> + IN EFI_SYSTEM_TABLE *SystemTable >>> + ) >>> +{ >>> + return SetupAndRunUnitTests (); >>> +} >>> + >>> +/** >>> + Standard POSIX C entry point for host based unit test execution. >>> +**/ >>> +int >>> +main ( >>> + int argc, >>> + char *argv[] >>> + ) >>> +{ >>> + return SetupAndRunUnitTests (); >>> +} >>> diff --git >> a/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/Readme.md >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/Readme.md >>> new file mode 100644 >>> index 0000000000..47800f5801 >>> --- /dev/null >>> +++ >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/Readme.md >>> @@ -0,0 +1,24 @@ >>> +# IPMI Blob Transfer Interface Driver >>> + >>> +This DXE module is a UEFI implementation of the Phorphor Blob Transfer >> Interface defined in OpenBMC >>> +https://github.com/openbmc/phosphor-ipmi-blobs >>> + >>> +## NVIDIA's OpenBMC implements this interface as a protocol, allowing >> UEFI and BMC to transfer blobs over IPMI. >>> + >>> +### Usage: >>> +Any DXE module that wishes to use this protocol should do the followin= g: >>> +1) The module should have a dependency on >> gEdkiiIpmiBlobTransferProtocolGuid in its inf "Depex" section >>> +2) The module should list gEdkiiIpmiBlobTransferProtocolGuid in its in= f >> "Protocol" section >>> +3) The module's entry point should do a LocateProtocol on >> gEdkiiIpmiBlobTransferProtocolGuid >>> + >>> +### A sample flow of protocol usage is as follows: >>> +1) A call to IpmiBlobTransferOpen () >>> +2) Iterative calls to IpmiBlobTransferWrite >>> +3) A call to IpmiBlobTransferClose () >>> + >>> +### Unit Tests: >>> +IpmiBlobTransferDxe/UnitTest/ contains host based unit tests of this >> implementation. >>> +Any changes to IpmiBlobTransferDxe should include proof of successful >> unit tests. >>> + >>> +### Debugging >>> +To assist in debugging any issues, change BLOB_TRANSFER_DEBUG to 1 >>> -- >>> 2.17.1 >>>