From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by spool.mail.gandi.net (Postfix) with ESMTPS id 2186DD811A4 for ; Fri, 9 Feb 2024 16:37:56 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=nTJWpQlGVWAJVHj6W1YXWHgF4Mx3g1tOI8UAydSPgu4=; c=relaxed/simple; d=groups.io; h=ARC-Seal:ARC-Message-Signature:ARC-Authentication-Results:From:To:CC:Subject:Thread-Topic:Thread-Index:Date:Message-ID:References:In-Reply-To:Accept-Language:msip_labels:MIME-Version:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Language:Content-Type:Content-Transfer-Encoding; s=20140610; t=1707496675; v=1; b=omzwWz7ew73X7VTO0rRTlo4MOmq+tQ8N2hoWlvjg8HvH3FBIg9IlqoUsD7pwlz3PK4QVQGwR TBboPXpFLuVRZLSIY3VS2gZPvt0kSL5XUTflwNk8dupjDHhBnsGGAKBssfW2IO3PDwg3uadajcF 3xf7zjMLQKLxQ5+L7bug/1FU= X-Received: by 127.0.0.2 with SMTP id GAN7YY7687511xN6KYix8joB; Fri, 09 Feb 2024 08:37:55 -0800 X-Received: from NAM10-BN7-obe.outbound.protection.outlook.com (NAM10-BN7-obe.outbound.protection.outlook.com [40.107.92.60]) by mx.groups.io with SMTP id smtpd.web11.16425.1707496674469776430 for ; Fri, 09 Feb 2024 08:37:55 -0800 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=k1bELmfHU9epykCYwr4UIOqNycdyCNO818hFc1gTj5z7im2RYK4W3AGg9gVObjlNuwCZRARe36J+2S8qQDyHHKLb/n4XzxpRlA6c5HuvW+RTGUe6YNpkBanzoEbgtCQEw2DaQJItRDuYVxUL6cfspTmCix6MFjvZcrwcEQVdnO/9tV7U1CFRl5jNJKDCXS0hxDQalpzcYMoBgENPjh2x3plxw74/XaYoFylnH47JNTOdue9LUv5CTESw3lrDwzdc9Gt8SvWbT2civz8iAJEHOfFXhzBGQ9SK9es2WNftQosFixx4/hlXnnSLXef6C2pmZ0QOr9kRqXT3MFKRV6qmug== 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=K1yWIipW8/nE1IS+C8CKZ889l9cre744nMqvj1rwsXs=; b=Eq7g+W1ooLdiGb7/nhXdYgOAau9zX3+M4PDiyPui9NTKrop2rJMJWR2RPuFAtKJtg8Fcr10TdBtDhfpkrTeFtLI9R6WoxdGE0soMHDJv/TE7iQHX+WaGfibQjNN2+jSDFjMtXEUoTE4/awnZ3CgBy00+I7GQ5DATjHegN+auLZNXt7SscYzlPwEZDcIP1XlpbP7/Me1g6bCqRZ6ClebcMNY9B2K40d8Ah8pNo6d4Kn6TxLlfWUJ/mHNN55TFqFz5R0UFJOth1F+yR1dgfb7vLI/9dEouNCJp1MsA80bpkG6Njqn2WU4xop6ubuOI7dHzebRHFRpjn9UUu+378vM8yg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=amd.com; dmarc=pass action=none header.from=amd.com; dkim=pass header.d=amd.com; arc=none X-Received: from LV8PR12MB9452.namprd12.prod.outlook.com (2603:10b6:408:200::8) by PH8PR12MB8606.namprd12.prod.outlook.com (2603:10b6:510:1ce::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7292.12; Fri, 9 Feb 2024 16:37:48 +0000 X-Received: from LV8PR12MB9452.namprd12.prod.outlook.com ([fe80::1c1c:8b58:d84f:7052]) by LV8PR12MB9452.namprd12.prod.outlook.com ([fe80::1c1c:8b58:d84f:7052%5]) with mapi id 15.20.7270.016; Fri, 9 Feb 2024 16:37:48 +0000 From: "Chang, Abner via groups.io" To: Nickle Wang , Rebecca Cran , "devel@edk2.groups.io" CC: Isaac Oram , "Attar, AbdulLateef (Abdul Lateef)" , Tinh Nguyen Subject: Re: [edk2-devel] [edk2-platforms][PATCH] ManageabilityPkg: add support for the phosphor ipmi blob transfer protocol Thread-Topic: [edk2-devel] [edk2-platforms][PATCH] ManageabilityPkg: add support for the phosphor ipmi blob transfer protocol Thread-Index: AQHZbO1biTXS7tPYRkSQFekf8oIdY7EC+emAgADligCAADECwA== Date: Fri, 9 Feb 2024 16:37:48 +0000 Message-ID: References: <20230412031724.12690-1-nicklew@nvidia.com> In-Reply-To: Accept-Language: en-US, zh-CN X-MS-Has-Attach: X-MS-TNEF-Correlator: msip_labels: MSIP_Label_4342314e-0df4-4b58-84bf-38bed6170a0f_ActionId=7b569aa1-71d1-4cb6-bd5a-4b54af3d1322;MSIP_Label_4342314e-0df4-4b58-84bf-38bed6170a0f_ContentBits=0;MSIP_Label_4342314e-0df4-4b58-84bf-38bed6170a0f_Enabled=true;MSIP_Label_4342314e-0df4-4b58-84bf-38bed6170a0f_Method=Standard;MSIP_Label_4342314e-0df4-4b58-84bf-38bed6170a0f_Name=General;MSIP_Label_4342314e-0df4-4b58-84bf-38bed6170a0f_SetDate=2024-02-09T16:29:30Z;MSIP_Label_4342314e-0df4-4b58-84bf-38bed6170a0f_SiteId=3dd8961f-e488-4e60-8e11-a82d994e183d; x-ms-publictraffictype: Email x-ms-traffictypediagnostic: LV8PR12MB9452:EE_|PH8PR12MB8606:EE_ x-ms-office365-filtering-correlation-id: 8b5e295e-f686-4640-4b32-08dc298d738c x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam-message-info: VnG1QGWTFd64RjTmUz9Q9Nuyg561ycfBarSE6iqQXndXRvOFP5f9ShJg7rGWjHW8mY5kyjDAVmoTpYcyDL0+NlyEQFZB68vRwTVNbO9IqcjeXykDQ1ajmZhA2LCqnyHX5TYCD8hoG3hKk63wEp0qR93jF/CSxbADLkRrc5VGszSM1Ov4hicm8UVTIa7HAV2cTiVUjK9LQFPGHZ8DUt+M/PbckFvgLtfp8ZWBmnPcBXgGFjJy+8rhdF0lfVJK9i3hWY7dUFd3AomfxNvhdK9GId80/jZ9r+LWXchI1Tnb7BTfnFOEKc6GiBz5Zt2PvqwjxEGRLfcyy93jQYKB0WwGlZivMuAXeYe+cvDfD9CKeKK1QtZ7brYXKWc81inxQMN8cY+1FJAPGIqZBtYnx9zqt+y78+L11DMd6BFF5yv7lnj3EWgWkoFKCE2TjlDGac1O6gSifUGy0xWTVu3n4df5bcgRf8jFL34aoxPu3t/3wYlFg/qs5ApykTOCNiY9vLMfCd2PsllxMActDMnV9lezjb9uNwp6zgH5BMjtsvRmW7Ul6Ml0fHcpuqh1ZJnlbEaKbcAd+NrdKel7MTXAO2O60cK6sNCF1n3hZBYiAmUPSWk= x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?us-ascii?Q?qphhiE8nj/Skutlxi8ELtyJPUT+NUMpmsXypUabZNiIIfNtembDVC/vkvyhI?= =?us-ascii?Q?I/8pY4+dq87hvqJkcBkCgA0YliE9bCkuQ7DvQ+Wi2w79eNUMA0lMsE3Os/6C?= =?us-ascii?Q?lcItWsacEwd1USK27rtLWD4u07ZHcGkly0OBT/ccqKXGjbjAsYhz9UtnYp6N?= =?us-ascii?Q?sihUFQlP+3hYbbtEK0tXeC8DKnXa/VcAL7qhoRksft9pHF6JOYqjrGGfau9v?= =?us-ascii?Q?wzypJhfJdSKpAHG7L7dXz86eBXJvYRpPg2p98eAcqpTpxqd0Ut1JVbftWy4O?= =?us-ascii?Q?hX2VPYZ/u78Sls2HVULB9t/trbnivU4bRpj1+RxLRJzD4dCz1eTFvl5Xkipq?= =?us-ascii?Q?kv2ooEMFOHmNdeDaVtx2K/9HhMzNy8XUkPdsGdpuFnsmQTy08YZp/v89RbLc?= =?us-ascii?Q?SGwGeRdKu6wJVr9rQzR3z1CZbmxR5v/s78iCmwJOZMUMp3VgV567hEV8TKm2?= =?us-ascii?Q?Jym6NuHDL185OVmw3eDuqCyPzPu8IzT8rr4VJ1D09W+cSjCv4Vvv8VmcSGEE?= =?us-ascii?Q?vCM46JG4/FPxoYftfktxHo+L2Lfw418QEoWCfCjnDnrmJxKRNFABmIvUfSa8?= =?us-ascii?Q?YCqRPatenekSM0vUWeJrjfR0uB7UpTE4CwcZQek9W7ltGxUVH/1DUUoFZa9h?= =?us-ascii?Q?d9R73EUcqHhzA8kSWrgprNNl8VdVfyR3UFfQnHnEJrXO8iTfBBF0gSmAgb4u?= =?us-ascii?Q?jyTw9pyplvlVPOPAALS3a3JfZg8sq+ZO4afU6sHH1xro/5NJP0rIdLT9VIf9?= =?us-ascii?Q?pT7RcNRy/VCYb4IUjy5QSHGwGJDSP3ZqaOyr+GtrMDU/0HZv/UCfiwTuFDSC?= =?us-ascii?Q?/C+lsRwihccQZpWDwBM70u6gwftuqKI/YQU++kJCuQl2j4ed+0QRilAc2TBd?= =?us-ascii?Q?4kRmhOJwg0JerSVwOTVOmCjIai1rguvRYfT2r6muWkMnPA+pv7u9qxbAiwss?= =?us-ascii?Q?GSuoO2bHgTJigZG0Y+lFI/G+nX+pAZn6zpUMGN5KLT7j5lV7DZWBiCIy+Pog?= =?us-ascii?Q?YnCH4egMkHmtbse2TDddg7JGe8CUGtMnEM0gEts13CzfljpR4MPsGZ0822LA?= =?us-ascii?Q?3qiw5IZ4q4GxYBHViMrtJJ0nNXnBWm+VzFlTIBq1eUL82MlR5xpqo19nP8Nm?= =?us-ascii?Q?cZm+vOI+DRy+CPdmSlNM5XfT7RhFug1dbhoecfSFY7vkRm5+r8SvK/5Uhowe?= =?us-ascii?Q?BqFUMotVQ5ILoKbYqF2oFagEwaxzTink3O8Q+53k2TdJM6unVZjf9ujTM4+r?= =?us-ascii?Q?fkFzByMPI/kO4BBzKaMzm3LXar2lbVOEmrCaMWpcG167z2mEOROMmhwhWBhW?= =?us-ascii?Q?xQkTu1gxm4n+pi/nDrBB48uqv8jq3sDYBaSkqM7vvOvmGZWTwucjYt4ZaZDR?= =?us-ascii?Q?jiC4jC7pg/eItcEQd/bO5emPgCASF7vINDrRTpuvW/06rsLQ9rZT/SVoxTlR?= =?us-ascii?Q?jzkL9YxitPs+w1VmBYI10Li3uiA5F2rnjlLtn1CqyOil1mZP6C47oseroPeF?= =?us-ascii?Q?0jAA3KwfUciwgkk49/OGQLzxw2QV2bI7x6P8EtzeScI8cr2QK61S2HyxHmpF?= =?us-ascii?Q?tEMobUYUqyomAr0jF/c=3D?= MIME-Version: 1.0 X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: LV8PR12MB9452.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 8b5e295e-f686-4640-4b32-08dc298d738c X-MS-Exchange-CrossTenant-originalarrivaltime: 09 Feb 2024 16:37:48.5395 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: 41E9CNEebgxwB2bNkWdhf1/JnJ+c2WhR/bMYqYN97p6/Dk4wZ807KxbTgZ5Tb85Ws9EjfwTv5LeX1g7L+J6/Bg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH8PR12MB8606 Precedence: Bulk List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,abner.chang@amd.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: MNLe0TPMLgmLZFQo1BGkWQOtx7686176AA= Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable X-GND-Status: LEGIT Authentication-Results: spool.mail.gandi.net; dkim=pass header.d=groups.io header.s=20140610 header.b=omzwWz7e; spf=pass (spool.mail.gandi.net: domain of bounce@groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce@groups.io; dmarc=pass (policy=none) header.from=groups.io; arc=reject ("signature check failed: fail, {[1] = sig:microsoft.com:reject}") [AMD Official Use Only - General] Yeah, I forget this patch set and seems we don't have any follow up convers= ation after below feedbacks from community. https://edk2.groups.io/g/devel/message/103116 https://edk2.groups.io/g/devel/message/103087 So Nickle, does NV still has the plan to upstream IPMI blob edk2 implementa= tion? We should keep driving upstream the implementation as industry needs = it to incorporate with OpenBMC. Hi Rebessa, As we are on Chinese New Year holidays now, please expect the delay respons= e. Thanks Abner > -----Original Message----- > From: Nickle Wang > Sent: Friday, February 9, 2024 9:34 PM > To: Rebecca Cran ; devel@edk2.groups.io > Cc: Chang, Abner ; Isaac Oram > ; Attar, AbdulLateef (Abdul Lateef) > ; Tinh Nguyen > > Subject: RE: [edk2-devel] [edk2-platforms][PATCH] ManageabilityPkg: add > support for the phosphor ipmi blob transfer protocol > > Caution: This message originated from an External Source. Use proper caut= ion > when opening attachments, clicking links, or responding. > > > Hi Rebecca, > > There is change to this driver on NVIDIA GitHub here: > https://github.com/NVIDIA/edk2- > nvidia/tree/main/Silicon/NVIDIA/Drivers/IpmiBlobTransferDxe > > Regards, > Nickle > > > -----Original Message----- > > From: Rebecca Cran > > Sent: Friday, February 9, 2024 7:53 AM > > To: devel@edk2.groups.io; Nickle Wang > > Cc: Abner Chang ; Isaac Oram > > ; Abdul Lateef Attar > > ; Tinh Nguyen > > > > Subject: Re: [edk2-devel] [edk2-platforms][PATCH] ManageabilityPkg: add > > support for the phosphor ipmi blob transfer protocol > > > > External email: Use caution opening links or attachments > > > > > > Was this change abandoned? > > > > I've realized it would be useful to have in the firmware I'm working on= , > > and was wondering if there's a newer revision of this patch somewhere? > > > > > > -- > > Rebecca Cran > > > > > > On 4/11/23 21:17, Nickle Wang via groups.io wrote: > > > This change implements the blob transfer protocol used in OpenBmc > > > documented here: > > > https://nam11.safelinks.protection.outlook.com/?url=3Dhttps%3A%2F%2Fgith > ub. > > com%2Fopenbmc%2Fphosphor-ipmi- > > > blobs&data=3D05%7C02%7Cnicklew%40nvidia.com%7Cb327966e846243687 > 65 > > > 208dc29010a98%7C43083d15727340c1b7db39efd9ccc17a%7C0%7C0%7C > 63 > > > 8430331675542376%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAw > MD > > > AiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0%7C%7C%7C&s > da > > > ta=3DesHFGSAc5TGBvPUWAOKd22p7DRMZ9UbnBU1jNAh%2Fsb0%3D&reserv > ed > > =3D0 > > > > > > 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/IpmiBlobTransfer > D > > xe.inf > > > create mode 100644 > > > Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiBlo > b > > TransferTestUnitTestsHost.inf > > > create mode 100644 > > Features/ManageabilityPkg/Include/Protocol/IpmiBlobTransfer.h > > > create mode 100644 > > > Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/InternalIpmiBlob > Tr > > ansfer.h > > > create mode 100644 > > > Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransfer > D > > xe.c > > > create mode 100644 > > > Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiBlo > b > > TransferTestUnitTests.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 > reserved.
> > > +# Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights > > reserved. > > > # SPDX-License-Identifier: BSD-2-Clause-Patent > > > # > > > ## > > > @@ -48,3 +49,8 @@ > > > gManageabilityProtocolMctpGuid =3D { 0x76FED8F1, 0x0BE5, 0x426= 9, > > { 0xA3, 0x1A, 0x38, 0x0F, 0x54, 0xF1, 0xA1, 0x8A } } > > > # Manageability Protocol PLDM > > > gManageabilityProtocolPldmGuid =3D { 0x3958090D, 0x69DD, 0x486= 8, > > { 0x9C, 0x41, 0xC9, 0xAC, 0x31, 0xB5, 0x25, 0xC5 } } > > > + > > > +[Protocols] > > > + > > > + ## Include/Protocol/IpmiBlobTransfer.h > > > + gEdkiiIpmiBlobTransferProtocolGuid =3D { 0x05837c75, 0x1d65, 0x468= b, > > { 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 > reserved.
> > > +# Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights > > reserved. > > > # SPDX-License-Identifier: BSD-2-Clause-Patent > > > # > > > ## > > > [LibraryClasses] > > > > > > ManageabilityTransportHelperLib|ManageabilityPkg/Library/BaseManageabili > > tyTransportHelperLib/BaseManageabilityTransportHelper.inf > > > + > > > IpmiLib|MdeModulePkg/Library/DxeIpmiLibIpmiProtocol/DxeIpmiLibIpmiPro > t > > ocol.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/IpmiBlobTransf > e > > rDxe.inf > > > b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransf > e > > rDxe.inf > > > new file mode 100644 > > > index 0000000000..28e9d293c1 > > > --- /dev/null > > > +++ > > > b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransf > e > > rDxe.inf > > > @@ -0,0 +1,39 @@ > > > +## @file > > > +# IPMI Blob Transfer Protocol DXE Driver. > > > +# > > > +# Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All > rights > > reserved. > > > +# > > > +# SPDX-License-Identifier: BSD-2-Clause-Patent > > > +# > > > + > > > +[Defines] > > > + INF_VERSION =3D 0x00010005 > > > + BASE_NAME =3D IpmiBlobTransferDxe > > > + FILE_GUID =3D 6357c804-78bb-4b0c-abdf-c75df94= 2f319 > > > + MODULE_TYPE =3D DXE_DRIVER > > > + VERSION_STRING =3D 1.0 > > > + ENTRY_POINT =3D IpmiBlobTransferDxeDriverEntryP= oint > > > + > > > +[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/IpmiB > l > > obTransferTestUnitTestsHost.inf > > > b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiB > l > > obTransferTestUnitTestsHost.inf > > > new file mode 100644 > > > index 0000000000..1f071bbadc > > > --- /dev/null > > > +++ > > > b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiB > l > > obTransferTestUnitTestsHost.inf > > > @@ -0,0 +1,40 @@ > > > +## @file > > > +# Unit tests of the Ipmi blob transfer driver that are run from a ho= st > > 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 IpmiBlobTransferDxeUnitTestsHos= t > > > + FILE_GUID =3D 1f5d4095-ea52-432c-b078-86097fe= f6004 > > > + 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 righ= ts > > 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 > > > + > > > +#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/InternalIpmiBlo > > bTransfer.h > > > b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/InternalIpmiBl > o > > bTransfer.h > > > new file mode 100644 > > > index 0000000000..14f0dc02bc > > > --- /dev/null > > > +++ > > > b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/InternalIpmiBl > o > > bTransfer.h > > > @@ -0,0 +1,363 @@ > > > +/** @file > > > + > > > + Headers for IPMI Blob Transfer driver > > > + > > > + Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All righ= ts > > 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 = blob > > > +// 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 blo= b > > > +// 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 o= f active > > blobs. > > > + @retval Other An error occurred > > > +**/ > > > +EFI_STATUS > > > +IpmiBlobTransferGetCount ( > > > + OUT UINT32 *Count > > > + ); > > > + > > > +/** > > > + @param[in] BlobIndex The 0-based Index of the blob t= o > enumerate > > > + @param[out] BlobId The ID of the blob > > > + > > > + @retval EFI_SUCCESS Successfully enumerated the blo= b. > > > + @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 i= s 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 = call to > > BlobOpen > > > + @param[in] Offset The offset of the blob from whi= ch 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 = call to > > BlobOpen > > > + @param[in] Offset The offset of the blob from whi= ch 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= call to > > BlobOpen > > > + @param[in] CommitDataLength The length of data to commit t= o the > > blob > > > + @param[in] CommitData A pointer to the data to commi= t > > > + > > > + @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 = call 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 statistic= s 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 succes= sfully > > 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= 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 succes= sfully > > 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 = metadata for > > > + @param[in] Offset The offset of the metadata to w= rite to > > > + @param[in] Data The data to write to the metada= ta > > > + > > > + @retval EFI_SUCCESS The blob metadata was successfu= lly > 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/IpmiBlobTransf > e > > rDxe.c > > > b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransf > e > > rDxe.c > > > new file mode 100644 > > > index 0000000000..9e663289d5 > > > --- /dev/null > > > +++ > > > b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransf > e > > rDxe.c > > > @@ -0,0 +1,799 @@ > > > +/** @file > > > + > > > + IPMI Blob Transfer driver > > > + > > > + Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All righ= ts > > 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)*IpmiBlobTransferGetCoun > t, > > > + > > > (IPMI_BLOB_TRANSFER_PROTOCOL_ENUMERATE)*IpmiBlobTransferEnumera > t > > e, > > > + (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)*IpmiBlobTransferSession > S > > tat, > > > + > > > (IPMI_BLOB_TRANSFER_PROTOCOL_WRITE_META)*IpmiBlobTransferWriteM > e > > ta > > > +}; > > > + > > > +const UINT8 OpenBmcOen[] =3D { 0xCF, 0xC2, 0x00 }; // Open= BMC > OEN > > code in little endian format > > > + > > > +/** > > > + 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) * SendDataS= ize); > > > + } > > > + > > > + 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 t= he 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= error. > > > + // 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 b= ack > > > + } 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 success= fully > > 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 > > > + ) > > > +{ > > > + 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 t= o > enumerate > > > + @param[out] BlobId The ID of the blob > > > + > > > + @retval EFI_SUCCESS Successfully enumerated the blo= b. > > > + @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 i= s 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); > > > + 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); > > > + 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)) + sizeo= f > > (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 = call to > > BlobOpen > > > + @param[in] Offset The offset of the blob from whi= ch 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 = call to > > BlobOpen > > > + @param[in] Offset The offset of the blob from whi= ch 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) + WriteLengt= h; > > > + 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= call to > > BlobOpen > > > + @param[in] CommitDataLength The length of data to commit t= o the > > blob > > > + @param[in] CommitData A pointer to the data to commi= t > > > + > > > + @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 = call 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 statistic= s 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 succes= sfully > > 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 (IpmiBlobTransferSubcommandSta= t, > > 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= 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 succes= sfully > > 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) || (MetadataLeng= th =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_RESPO= NSE > > *)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 = metadata for > > > + @param[in] Offset The offset of the metadata to w= rite to > > > + @param[in] Data The data to write to the metada= ta > > > + > > > + @retval EFI_SUCCESS The blob metadata was successfu= lly > 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 po= int 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 th= e 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/IpmiB > l > > obTransferTestUnitTests.c > > > b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiB > l > > obTransferTestUnitTests.c > > > new file mode 100644 > > > index 0000000000..f326467922 > > > --- /dev/null > > > +++ > > > b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiB > l > > obTransferTestUnitTests.c > > > @@ -0,0 +1,1113 @@ > > > +/** @file > > > +* > > > +* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. > > > +* > > > +* 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 enabl= es: > > > + 1) test-case reuse with varied parameters a= nd > > > + 2) test-case re-entry for Target tests that= need a > > > + reboot. This parameter is a VOID* and it i= s the > > > + responsibility of the test author to ensure= that the > > > + contents are well understood by all test ca= ses that may > > > + consume it. > > > + @retval UNIT_TEST_PASSED The Unit test has completed = and 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 enabl= es: > > > + 1) test-case reuse with varied parameters a= nd > > > + 2) test-case re-entry for Target tests that= need a > > > + reboot. This parameter is a VOID* and it i= s the > > > + responsibility of the test author to ensure= that the > > > + contents are well understood by all test ca= ses that may > > > + consume it. > > > + @retval UNIT_TEST_PASSED The Unit test has completed = and 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 enabl= es: > > > + 1) test-case reuse with varied parameters a= nd > > > + 2) test-case re-entry for Target tests that= need a > > > + reboot. This parameter is a VOID* and it i= s the > > > + responsibility of the test author to ensure= that the > > > + contents are well understood by all test ca= ses that may > > > + consume it. > > > + @retval UNIT_TEST_PASSED The Unit test has completed = and 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 enabl= es: > > > + 1) test-case reuse with varied parameters a= nd > > > + 2) test-case re-entry for Target tests that= need a > > > + reboot. This parameter is a VOID* and it i= s the > > > + responsibility of the test author to ensure= that the > > > + contents are well understood by all test ca= ses that may > > > + consume it. > > > + @retval UNIT_TEST_PASSED The Unit test has completed = and 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 enabl= es: > > > + 1) test-case reuse with varied parameters a= nd > > > + 2) test-case re-entry for Target tests that= need a > > > + reboot. This parameter is a VOID* and it i= s the > > > + responsibility of the test author to ensure= that the > > > + contents are well understood by all test ca= ses that may > > > + consume it. > > > + @retval UNIT_TEST_PASSED The Unit test has completed = and 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 enabl= es: > > > + 1) test-case reuse with varied parameters a= nd > > > + 2) test-case re-entry for Target tests that= need a > > > + reboot. This parameter is a VOID* and it i= s the > > > + responsibility of the test author to ensure= that the > > > + contents are well understood by all test ca= ses that may > > > + consume it. > > > + @retval UNIT_TEST_PASSED The Unit test has completed = and 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 enabl= es: > > > + 1) test-case reuse with varied parameters a= nd > > > + 2) test-case re-entry for Target tests that= need a > > > + reboot. This parameter is a VOID* and it i= s the > > > + responsibility of the test author to ensure= that the > > > + contents are well understood by all test ca= ses that may > > > + consume it. > > > + @retval UNIT_TEST_PASSED The Unit test has completed = and 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 enabl= es: > > > + 1) test-case reuse with varied parameters a= nd > > > + 2) test-case re-entry for Target tests that= need a > > > + reboot. This parameter is a VOID* and it i= s the > > > + responsibility of the test author to ensure= that the > > > + contents are well understood by all test ca= ses that may > > > + consume it. > > > + @retval UNIT_TEST_PASSED The Unit test has completed = and 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 enabl= es: > > > + 1) test-case reuse with varied parameters a= nd > > > + 2) test-case re-entry for Target tests that= need a > > > + reboot. This parameter is a VOID* and it i= s the > > > + responsibility of the test author to ensure= that the > > > + contents are well understood by all test ca= ses that may > > > + consume it. > > > + @retval UNIT_TEST_PASSED The Unit test has completed = and 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 enabl= es: > > > + 1) test-case reuse with varied parameters a= nd > > > + 2) test-case re-entry for Target tests that= need a > > > + reboot. This parameter is a VOID* and it i= s the > > > + responsibility of the test author to ensure= that the > > > + contents are well understood by all test ca= ses that may > > > + consume it. > > > + @retval UNIT_TEST_PASSED The Unit test has completed = and 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 enabl= es: > > > + 1) test-case reuse with varied parameters a= nd > > > + 2) test-case re-entry for Target tests that= need a > > > + reboot. This parameter is a VOID* and it i= s the > > > + responsibility of the test author to ensure= that the > > > + contents are well understood by all test ca= ses that may > > > + consume it. > > > + @retval UNIT_TEST_PASSED The Unit test has completed = and 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 enabl= es: > > > + 1) test-case reuse with varied parameters a= nd > > > + 2) test-case re-entry for Target tests that= need a > > > + reboot. This parameter is a VOID* and it i= s the > > > + responsibility of the test author to ensure= that the > > > + contents are well understood by all test ca= ses that may > > > + consume it. > > > + @retval UNIT_TEST_PASSED The Unit test has completed = and 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 enabl= es: > > > + 1) test-case reuse with varied parameters a= nd > > > + 2) test-case re-entry for Target tests that= need a > > > + reboot. This parameter is a VOID* and it i= s the > > > + responsibility of the test author to ensure= that the > > > + contents are well understood by all test ca= ses that may > > > + consume it. > > > + @retval UNIT_TEST_PASSED The Unit test has completed = and 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 enabl= es: > > > + 1) test-case reuse with varied parameters a= nd > > > + 2) test-case re-entry for Target tests that= need a > > > + reboot. This parameter is a VOID* and it i= s the > > > + responsibility of the test author to ensure= that the > > > + contents are well understood by all test ca= ses that may > > > + consume it. > > > + @retval UNIT_TEST_PASSED The Unit test has completed = and 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 enabl= es: > > > + 1) test-case reuse with varied parameters a= nd > > > + 2) test-case re-entry for Target tests that= need a > > > + reboot. This parameter is a VOID* and it i= s the > > > + responsibility of the test author to ensure= that the > > > + contents are well understood by all test ca= ses that may > > > + consume it. > > > + @retval UNIT_TEST_PASSED The Unit test has completed = and 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 enabl= es: > > > + 1) test-case reuse with varied parameters a= nd > > > + 2) test-case re-entry for Target tests that= need a > > > + reboot. This parameter is a VOID* and it i= s the > > > + responsibility of the test author to ensure= that the > > > + contents are well understood by all test ca= ses that may > > > + consume it. > > > + @retval UNIT_TEST_PASSED The Unit test has completed = and 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 enabl= es: > > > + 1) test-case reuse with varied parameters a= nd > > > + 2) test-case re-entry for Target tests that= need a > > > + reboot. This parameter is a VOID* and it i= s the > > > + responsibility of the test author to ensure= that the > > > + contents are well understood by all test ca= ses that may > > > + consume it. > > > + @retval UNIT_TEST_PASSED The Unit test has completed = and 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 enabl= es: > > > + 1) test-case reuse with varied parameters a= nd > > > + 2) test-case re-entry for Target tests that= need a > > > + reboot. This parameter is a VOID* and it i= s the > > > + responsibility of the test author to ensure= that the > > > + contents are well understood by all test ca= ses that may > > > + consume it. > > > + @retval UNIT_TEST_PASSED The Unit test has completed = and 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, Metadata= Length, > > 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 enabl= es: > > > + 1) test-case reuse with varied parameters a= nd > > > + 2) test-case re-entry for Target tests that= need a > > > + reboot. This parameter is a VOID* and it i= s the > > > + responsibility of the test author to ensure= that the > > > + contents are well understood by all test ca= ses that may > > > + consume it. > > > + @retval UNIT_TEST_PASSED The Unit test has completed = and 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 enabl= es: > > > + 1) test-case reuse with varied parameters a= nd > > > + 2) test-case re-entry for Target tests that= need a > > > + reboot. This parameter is a VOID* and it i= s the > > > + responsibility of the test author to ensure= that the > > > + contents are well understood by all test ca= ses that may > > > + consume it. > > > + @retval UNIT_TEST_PASSED The Unit test has completed = and 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 enabl= es: > > > + 1) test-case reuse with varied parameters a= nd > > > + 2) test-case re-entry for Target tests that= need a > > > + reboot. This parameter is a VOID* and it i= s the > > > + responsibility of the test author to ensure= that the > > > + contents are well understood by all test ca= ses that may > > > + consume it. > > > + @retval UNIT_TEST_PASSED The Unit test has completed = and 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 enabl= es: > > > + 1) test-case reuse with varied parameters a= nd > > > + 2) test-case re-entry for Target tests that= need a > > > + reboot. This parameter is a VOID* and it i= s the > > > + responsibility of the test author to ensure= that the > > > + contents are well understood by all test ca= ses that may > > > + consume it. > > > + @retval UNIT_TEST_PASSED The Unit test has completed = and 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 wi= th > > status =3D %r\n", Status)); > > > + ASSERT (FALSE); > > > + return Status; > > > + } > > > + > > > + // > > > + // Populate the Unit Test Suite. > > > + // > > > + Status =3D CreateUnitTestSuite (&IpmiBlobTransfer, Framework, "IPM= I Blob > > Transfer Tests", "UnitTest.IpmiBlobTransferCB", NULL, NULL); > > > + if (EFI_ERROR (Status)) { > > > + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for IPMI Blo= b > > 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 Calculatio= n", > > "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 succe= ssfully > > with no data", "SendIpmiNoDataResponse", SendIpmiNoDataResponse, > NULL, > > NULL, NULL); > > > + Status =3D AddTestCase (IpmiBlobTransfer, "Send IPMI returns succe= ssfully > > with bad OEN", "SendIpmiBadOenResponse", SendIpmiBadOenResponse, > > NULL, NULL, NULL); > > > + Status =3D AddTestCase (IpmiBlobTransfer, "Send IPMI returns succe= ssfully > > with bad CRC", "SendIpmiBadCrcResponse", SendIpmiBadCrcResponse, > NULL, > > NULL, NULL); > > > + Status =3D AddTestCase (IpmiBlobTransfer, "Send IPMI returns with = valid > > GetCount data", "SendIpmiValidCountResponse", > > SendIpmiValidCountResponse, NULL, NULL, NULL); > > > + // IpmiBlobTransferGetCount > > > + Status =3D AddTestCase (IpmiBlobTransfer, "GetCount call with vali= d data", > > "GetCountValidCountResponse", GetCountValidCountResponse, NULL, > NULL, > > NULL); > > > + // IpmiBlobTransferEnumerate > > > + Status =3D AddTestCase (IpmiBlobTransfer, "Enumerate call with val= id > data", > > "EnumerateValidResponse", EnumerateValidResponse, NULL, NULL, NULL); > > > + Status =3D AddTestCase (IpmiBlobTransfer, "Enumerate call with inv= alid > > output buffer", "EnumerateInvalidBuffer", EnumerateInvalidBuffer, NULL, > > NULL, NULL); > > > + // IpmiBlobTransferOpen > > > + Status =3D AddTestCase (IpmiBlobTransfer, "Open call with valid da= ta", > > "OpenValidResponse", OpenValidResponse, NULL, NULL, NULL); > > > + // IpmiBlobTransferRead > > > + Status =3D AddTestCase (IpmiBlobTransfer, "Read call with valid da= ta", > > "ReadValidResponse", ReadValidResponse, NULL, NULL, NULL); > > > + Status =3D AddTestCase (IpmiBlobTransfer, "Read call with invalid = buffer", > > "ReadInvalidBuffer", ReadInvalidBuffer, NULL, NULL, NULL); > > > + // IpmiBlobTransferWrite > > > + Status =3D AddTestCase (IpmiBlobTransfer, "Write call with valid d= ata", > > "WriteValidResponse", WriteValidResponse, NULL, NULL, NULL); > > > + // IpmiBlobTransferCommit > > > + Status =3D AddTestCase (IpmiBlobTransfer, "Commit call with valid = data", > > "CommitValidResponse", CommitValidResponse, NULL, NULL, NULL); > > > + // IpmiBlobTransferClose > > > + Status =3D AddTestCase (IpmiBlobTransfer, "Close call with valid d= ata", > > "CloseValidResponse", CloseValidResponse, NULL, NULL, NULL); > > > + // IpmiBlobTransferDelete > > > + Status =3D AddTestCase (IpmiBlobTransfer, "Delete call with valid = data", > > "DeleteValidResponse", DeleteValidResponse, NULL, NULL, NULL); > > > + // IpmiBlobTransferStat > > > + Status =3D AddTestCase (IpmiBlobTransfer, "Blob Stat call with val= id data", > > "BlobStatValidResponse", BlobStatValidResponse, NULL, NULL, NULL); > > > + Status =3D AddTestCase (IpmiBlobTransfer, "Blob Stat call with inv= alid > buffer", > > "BlobStatInvalidBuffer", BlobStatInvalidBuffer, NULL, NULL, NULL); > > > + // IpmiBlobTransferSessionStat > > > + Status =3D AddTestCase (IpmiBlobTransfer, "Session Stat call with = valid > data", > > "SessionStatValidResponse", SessionStatValidResponse, NULL, NULL, NULL)= ; > > > + Status =3D AddTestCase (IpmiBlobTransfer, "Session Stat call with = invalid > > buffer", "SessionStatInvalidBuffer", SessionStatInvalidBuffer, NULL, NU= LL, > > NULL); > > > + // IpmiBlobTransferWriteMeta > > > + Status =3D AddTestCase (IpmiBlobTransfer, "WriteMeta call with val= id > 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 Transf= er > > Interface defined in OpenBMC > > > > > > +https://nam11.safelinks.protection.outlook.com/?url=3Dhttps%3A%2F%2Fgit > hu > > b.com%2Fopenbmc%2Fphosphor-ipmi- > > > blobs&data=3D05%7C02%7Cnicklew%40nvidia.com%7Cb327966e846243687 > 65 > > > 208dc29010a98%7C43083d15727340c1b7db39efd9ccc17a%7C0%7C0%7C > 63 > > > 8430331675551644%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAw > MD > > > AiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0%7C%7C%7C&s > da > > ta=3DWdwXQUKvHs3bv4KI9rbvvvQ3jJOFlWRhBczJAke9vL0%3D&reserved=3D0 > > > + > > > +## NVIDIA's OpenBMC implements this interface as a protocol, allowin= g > > UEFI and BMC to transfer blobs over IPMI. > > > + > > > +### Usage: > > > +Any DXE module that wishes to use this protocol should do the follow= ing: > > > +1) The module should have a dependency on > > gEdkiiIpmiBlobTransferProtocolGuid in its inf "Depex" section > > > +2) The module should list gEdkiiIpmiBlobTransferProtocolGuid in its = inf > > "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 successfu= l > unit > > tests. > > > + > > > +### Debugging > > > +To assist in debugging any issues, change BLOB_TRANSFER_DEBUG to 1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#115309): https://edk2.groups.io/g/devel/message/115309 Mute This Topic: https://groups.io/mt/98212643/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-