From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM02-DM3-obe.outbound.protection.outlook.com (NAM02-DM3-obe.outbound.protection.outlook.com [40.107.95.63]) by mx.groups.io with SMTP id smtpd.web11.4904.1681360154996422007 for ; Wed, 12 Apr 2023 21:29:15 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@amd.com header.s=selector1 header.b=j8ONPgg1; spf=permerror, err=parse error for token &{10 18 %{i}._ip.%{h}._ehlo.%{d}._spf.vali.email}: invalid domain name (domain: amd.com, ip: 40.107.95.63, mailfrom: abner.chang@amd.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=blcOj5uAXjsXQcjKSvqSeKxv9u3J5G+tZG4ZyA9C1mx2LcGduWayoewu3Dq4GIoZV+PShXTS4RMEODZ5Rq9QZPesicKa0atS9ZVlPrXII96zfA1ZfxTOsFwpx9cg8Xx9S0zE2dHjJPdE8rXNR0tInDt1Bh4nxICjilKazdpTDaRxux8sTsNdzL0xZZLyWLzC78hXqmaEByvZ42WyLxPtFoUidtaqapXQ1JS//0YkHgImpolzLTWCdxwSliWoo3YYi0ogyygj+vfe3BSaJ9J+zuskOtDkLJnTF6T2Pzm2k3m/fMPEkfh8bZFr65tGsICQcNeRT3v8LWyaoOLjlZgc8Q== 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=5Jt0Mi8q9U1IReEtGzUPFhZMGkOHEL5E0eeqoMrsYxo=; b=KdcRcmPKlbkNCdAbQy7Xcn+pL6lM8Lp0LNyAlCv1uLeyv+CsTpk2p9uYoaRrlPDW1Vvd0kAdoLqGTM3gSk6nZEVXZ19OtNYv/ERbm+i3RIyRdMriq5QyM5QcOIBsK5vVK0nI0PCIrCfWsILM1+bm68GSn9Eu3DGfU0FMmHfzWrNaePhMb/MeeYN5lyrANeBSaVj4K8S/6PUpCdWQHRGnUHnmJRSRZ0Fn6Bg1taJjs6GbpGxPs1fbjHSbNvLVIE6FUO+4e+FnIRLR7DPx/c80ZFRlsbp0RgrwEqijxudCaOlergcnWNeNC991Ge5H0A2ZXVz8Lh8J81aIv0hDKTtPLw== 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 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=5Jt0Mi8q9U1IReEtGzUPFhZMGkOHEL5E0eeqoMrsYxo=; b=j8ONPgg1TB8NKHLXg6WJhMaOvN9vqaUOARbDFldhbYFb5xwPE38R2kWyhDp1T8aTl9oG63Fwy2N7RtkeTK0cyfaOVj7OeA71kfGD6WmWtaZPtZbC1YVNbUfzkLXwXV1fdYTp0sgKsVl79zluiYm1gKRIufdHy1PXo2jmvsiNeUY= Received: from MN2PR12MB3966.namprd12.prod.outlook.com (2603:10b6:208:165::18) by PH7PR12MB7354.namprd12.prod.outlook.com (2603:10b6:510:20d::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6277.38; Thu, 13 Apr 2023 04:29:08 +0000 Received: from MN2PR12MB3966.namprd12.prod.outlook.com ([fe80::30f:bd83:40dd:8f1]) by MN2PR12MB3966.namprd12.prod.outlook.com ([fe80::30f:bd83:40dd:8f1%3]) with mapi id 15.20.6298.030; Thu, 13 Apr 2023 04:29:08 +0000 From: "Chang, Abner" To: Nickle Wang , "devel@edk2.groups.io" CC: Isaac Oram , "Attar, AbdulLateef (Abdul Lateef)" , Tinh Nguyen Subject: Re: [edk2-platforms][PATCH] ManageabilityPkg: add support for the phosphor ipmi blob transfer protocol Thread-Topic: [edk2-platforms][PATCH] ManageabilityPkg: add support for the phosphor ipmi blob transfer protocol Thread-Index: AQHZbO1biTXS7tPYRkSQFekf8oIdY68ojHYg Date: Thu, 13 Apr 2023 04:29:08 +0000 Message-ID: References: <20230412031724.12690-1-nicklew@nvidia.com> In-Reply-To: <20230412031724.12690-1-nicklew@nvidia.com> Accept-Language: zh-CN, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: msip_labels: MSIP_Label_4342314e-0df4-4b58-84bf-38bed6170a0f_Enabled=true; MSIP_Label_4342314e-0df4-4b58-84bf-38bed6170a0f_SetDate=2023-04-13T04:29:06Z; 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_SiteId=3dd8961f-e488-4e60-8e11-a82d994e183d; MSIP_Label_4342314e-0df4-4b58-84bf-38bed6170a0f_ActionId=fd843edb-663f-400b-abfc-f8957a20480e; MSIP_Label_4342314e-0df4-4b58-84bf-38bed6170a0f_ContentBits=1 authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=amd.com; x-ms-publictraffictype: Email x-ms-traffictypediagnostic: MN2PR12MB3966:EE_|PH7PR12MB7354:EE_ x-ms-office365-filtering-correlation-id: cff189bc-7042-47ab-f9e7-08db3bd79fa0 x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: U+r2amLrY6Asv22t27l48qbx8PUC1POtmsve0o6s0siUo90joAIXBIZNGf63jkE3LR9ohx/Oc0ejBKibe0TOAw62zg/lHK4EU+qzH2DskYxjqtnyOVi4WdmDSiez9TuIjzABS4eWNFBU/UhNkgc9Ty8/DGFPzo6FmvubTlMhMzgTfs1YKufk0zl3PVphM6taDqaMCMdmtZKbrTo49pLf0Fo0lXCihF8++aY5o7tQaDxAE4Fc4mRmS9UAwsz39oDbOo+r9xLfAJ1BTy+nkPGW7mJVRgMLxoZ5Abs+nAE8d12U/0tXprKYhgeDed6EvSaKf0WmZ4HY3Ya5JsyXkCQ61BgAXiGr02RnpLE6TJ7vwavZw/3sXg+5uxxiR9pqh0Z0L0lF3asVaDkibsd44Hrhh+xfDFSYBNuTfy7bxhQkW+Tu9AlZ2LKxKAqJ1uN0fhQUrNFv2J5PXOmG+IdE24Q4tqFvf0CrkscNYHkQ9XQ1XpklLvWQAvYl7/rEIEHoGdEAJ5BfeBk+UK3+6/RELyZ9A/Z8PdL4VAkpLDKUmUKcaYOPy94EXkmOBnvnXF0UjYdXfqQMDK7nNmaa+2tU+gHKn99AulLGjIXCLbLo8iNJ2unJCPoICbfyRbwyoNRzXxFsSlFKUbMWooxlMNLTzqO1H1RmtkAptqSufmWmPsAb0zk= x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:MN2PR12MB3966.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230028)(4636009)(366004)(396003)(39860400002)(136003)(376002)(346002)(451199021)(8676002)(5660300002)(52536014)(55016003)(186003)(8936002)(41300700001)(38100700002)(38070700005)(33656002)(2906002)(30864003)(83380400001)(122000001)(53546011)(26005)(6506007)(478600001)(9686003)(110136005)(71200400001)(7696005)(86362001)(316002)(54906003)(19627235002)(966005)(4326008)(66556008)(66476007)(66446008)(66946007)(76116006)(64756008)(559001)(579004)(44824005);DIR:OUT;SFP:1101; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?us-ascii?Q?jBqEdWHzilJEt7teb+QGDle7kIGeGA1RpZIxfI4DYNHmTY529gW7fPcrKnNc?= =?us-ascii?Q?+Nk2VEsise+w1450sNXu1NR95FSB5tO5oAXXPYPoeomGBhekmBkJzedG8QUC?= =?us-ascii?Q?ISY4jhae6bMMD/R77p5mXwxIpbixnjBslr358vuDRmtjZ9TV2szGUmMkNJ4C?= =?us-ascii?Q?sejuV12dTQw0vWIZ0PDQKcSJMCvprfH4sXE6/lEDjNC+cSTvZqlOmHUNRSBZ?= =?us-ascii?Q?X7m9iLidP8bf5oXhCCFPDChRELcRgJGNIgK4+pPrzD6GJNaoM8hoRsBVcm0H?= =?us-ascii?Q?Jtykt/P1H88UFAXUv9z9M4OV8EKRU9DlrWo3W8mRi5DvwbGuGETVtewdaTHJ?= =?us-ascii?Q?7J8WBYAm6ro8mS80zVZW7zoAwX/Y02TIJe7IbE13GwpWZUWGoJHV+1gEorRz?= =?us-ascii?Q?WIZKk9oqZgHsJ4MOMARtVVtqny2jAhVEk3gXQcJt5V7BzP+ZpgLjN7K6QfHA?= =?us-ascii?Q?Wixf4lEL5gKtaLiHkVyhGe83YtOm6sXX6bbjGxqWwPJPvHKtVOiosaLxa76l?= =?us-ascii?Q?Dd99HZziTp3BB85gQJyuP5Jx/saZUDRg/xy4n+lW7wM8yUT0zE7/mTIxsf1z?= =?us-ascii?Q?guQQFaoPp2s6Wlc89AOUnD6EMxt8lUNPjGqnLR+Gn7LsAB/1bRFMry6iN4wQ?= =?us-ascii?Q?MN6a3WNiSY1fonOb6aTOmFFrNfgz83tihy9cwwkDM7Hw6hwVTEAJLB/qc5q5?= =?us-ascii?Q?FahE79rveX57OoGJ+KUsfeGbAXuKppIXxpWhjwWuL90zgJCIRjblFF/WUe/a?= =?us-ascii?Q?zbW/w8v+KxR4/zMgNKNTGNTjIYEscwgwlHQWCuq9XBr+dPbWuy/syN00/5ou?= =?us-ascii?Q?DesUmaf38L9b18ffVF6E/edKirbU8H7wUbJ5OFkD6JvQKGgYLyXdclzMx2Tp?= =?us-ascii?Q?cDUf0EtHwXdZeHWHcNoZ7TP1WOkVb2UoNf4fyFVZMG8m7nF5eKwlVLGaWLmG?= =?us-ascii?Q?7QS/kzVDJ1ObB2fQI7ow2QzP5W1v5dKqNuolCiYpDf3lNMdM6rIqw9dpbwcI?= =?us-ascii?Q?cEN6KgtiVsq8fF7OnDiKiVYtATHYw2glZpmOYThz/CBUgrjGEoOa3UUMoLln?= =?us-ascii?Q?b45Z2kIiPUo0Qdymp76fXJFbuWJdb0nvp2Atcih0Wq+FrFw/JreRTdzl99+j?= =?us-ascii?Q?D5ktxo9CGYScthyYdpsqdHTxkBrM8Iq4b8Kq49Kyb1Rd8rObvkwSw7YSAXFs?= =?us-ascii?Q?B7fZUndxpuOL+bahc4I8TIBl8F8slEMwEueEcIrrXzrRZhkXjvwFCCQxiFNr?= =?us-ascii?Q?W8dzbPKy6TbJrOu72/k3CCxsOKk4NH6rLiGzktrMbHIAKqBaqIbzR0rWIccR?= =?us-ascii?Q?hw/NPr6AmqypYPki6WV9pinxhN8hHMSACgQNg7vzX29R8YnwPEnOeNjMCN84?= =?us-ascii?Q?BX2a5m0F2tN4+ngmOOPxX4NOuUsLQvPGuCWg32AvmTADD3QbKeked7/j7w+m?= =?us-ascii?Q?duCZBfdMqGXo6I48qdirvEQnQXjfu4JeWj7Jj6v+k4Mw5BQtNM6FJ0KKVpLv?= =?us-ascii?Q?p7LydtbiUvrgVsPETo1LiQar3IXW7knCzE1/uZvrnqb/O3VSms/E0kG6ZWSb?= =?us-ascii?Q?bYKRESSmewhXtp+DJDw=3D?= MIME-Version: 1.0 X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: MN2PR12MB3966.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: cff189bc-7042-47ab-f9e7-08db3bd79fa0 X-MS-Exchange-CrossTenant-originalarrivaltime: 13 Apr 2023 04:29:08.4919 (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: 38YrCxRQSE2SzdixEm5g4LvelsnE0GbNAbK4yhMkz0zy3m3L3KC/tPw7FG/Hu/ivJ41SGH8PYC8JBRmMHrT1hA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH7PR12MB7354 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable [AMD Official Use Only - General] Hi Nickle, Could you please create a BZ ticket for this? Pease also run Uncristify on = these files. Feedback inline,=20 > -----Original Message----- > From: Nickle Wang > Sent: Wednesday, April 12, 2023 11:17 AM > To: devel@edk2.groups.io > Cc: Chang, Abner ; Isaac Oram > ; Attar, AbdulLateef (Abdul Lateef) > ; Tinh Nguyen > > Subject: [edk2-platforms][PATCH] ManageabilityPkg: add support for the > phosphor ipmi blob transfer protocol >=20 > Caution: This message originated from an External Source. Use proper > caution when opening attachments, clicking links, or responding. >=20 >=20 > This change implements the blob transfer protocol used in OpenBmc > documented here: https://github.com/openbmc/phosphor-ipmi-blobs >=20 > Signed-off-by: Nick Ramirez > Cc: Abner Chang > Cc: Isaac Oram > Cc: Abdul Lateef Attar > Cc: Nickle Wang > Cc: Tinh Nguyen > --- > .../ManageabilityPkg/ManageabilityPkg.dec | 6 + > .../Include/Dsc/Manageability.dsc | 4 +- > .../IpmiBlobTransferDxe.inf | 39 + > .../IpmiBlobTransferTestUnitTestsHost.inf | 40 + > .../Include/Protocol/IpmiBlobTransfer.h | 136 ++ > .../InternalIpmiBlobTransfer.h | 363 ++++++ > .../IpmiBlobTransferDxe/IpmiBlobTransferDxe.c | 799 ++++++++++++ > .../UnitTest/IpmiBlobTransferTestUnitTests.c | 1113 +++++++++++++++++ > .../Universal/IpmiBlobTransferDxe/Readme.md | 24 + > 9 files changed, 2523 insertions(+), 1 deletion(-) > create mode 100644 > Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransf > erDxe.inf > create mode 100644 > Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiBl > obTransferTestUnitTestsHost.inf > create mode 100644 > Features/ManageabilityPkg/Include/Protocol/IpmiBlobTransfer.h > create mode 100644 > Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/InternalIpmiBlo > bTransfer.h > create mode 100644 > Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransf > erDxe.c > create mode 100644 > Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiBl > obTransferTestUnitTests.c > create mode 100644 > Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/Readme.md >=20 > 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, 0x4269, { = 0xA3, > 0x1A, 0x38, 0x0F, 0x54, 0xF1, 0xA1, 0x8A } } > # Manageability Protocol PLDM > gManageabilityProtocolPldmGuid =3D { 0x3958090D, 0x69DD, 0x4868, { = 0x9C, > 0x41, 0xC9, 0xAC, 0x31, 0xB5, 0x25, 0xC5 } } > + > +[Protocols] > + > + ## Include/Protocol/IpmiBlobTransfer.h > + gEdkiiIpmiBlobTransferProtocolGuid =3D { 0x05837c75, 0x1d65, 0x468b, {= 0xb1, > 0xc2, 0x81, 0xaf, 0x9a, 0x31, 0x5b, 0x2c } } > diff --git a/Features/ManageabilityPkg/Include/Dsc/Manageability.dsc > b/Features/ManageabilityPkg/Include/Dsc/Manageability.dsc > index 0d868fdf4a..111d6b91dc 100644 > --- a/Features/ManageabilityPkg/Include/Dsc/Manageability.dsc > +++ b/Features/ManageabilityPkg/Include/Dsc/Manageability.dsc > @@ -2,11 +2,13 @@ > # Common libraries for Manageabilty Package > # > # Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved. > +# Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights > reserved. > # SPDX-License-Identifier: BSD-2-Clause-Patent > # > ## > [LibraryClasses] >=20 > ManageabilityTransportHelperLib|ManageabilityPkg/Library/BaseManageabi > lityTransportHelperLib/BaseManageabilityTransportHelper.inf > + > IpmiLib|MdeModulePkg/Library/DxeIpmiLibIpmiProtocol/DxeIpmiLibIpmiPr > otocol.inf >=20 > [LibraryClasses.ARM, LibraryClasses.AARCH64] > # > @@ -22,4 +24,4 @@ > [Components.X64] > ManageabilityPkg/Universal/IpmiProtocol/Dxe/IpmiProtocolDxe.inf > ManageabilityPkg/Universal/IpmiProtocol/Smm/IpmiProtocolSmm.inf > - > + > ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransferDxe.inf > diff --git > a/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTran > sferDxe.inf > b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTran > sferDxe.inf > new file mode 100644 > index 0000000000..28e9d293c1 > --- /dev/null > +++ > b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTran > sferDxe.inf > @@ -0,0 +1,39 @@ > +## @file > +# IPMI Blob Transfer Protocol DXE Driver. > +# > +# Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights Is 2022-2023 correct? This file will be added in 2023. > reserved. > +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > + > +[Defines] > + INF_VERSION =3D 0x00010005 > + BASE_NAME =3D IpmiBlobTransferDxe > + FILE_GUID =3D 6357c804-78bb-4b0c-abdf-c75df942f31= 9 > + MODULE_TYPE =3D DXE_DRIVER > + VERSION_STRING =3D 1.0 > + ENTRY_POINT =3D IpmiBlobTransferDxeDriverEntryPoint > + > +[Sources.common] > + IpmiBlobTransferDxe.c > + > +[LibraryClasses] > + BaseLib > + BaseMemoryLib > + DebugLib > + IpmiLib > + MemoryAllocationLib > + PcdLib > + UefiBootServicesTableLib > + UefiDriverEntryPoint > + > +[Packages] > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + ManageabilityPkg/ManageabilityPkg.dec > + > +[Protocols] > + gEdkiiIpmiBlobTransferProtocolGuid > + > +[Depex] > + TRUE > diff --git > a/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/Ipmi > BlobTransferTestUnitTestsHost.inf > b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/Ipm > iBlobTransferTestUnitTestsHost.inf > new file mode 100644 > index 0000000000..1f071bbadc > --- /dev/null > +++ > b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/Ipm > iBlobTransferTestUnitTestsHost.inf > @@ -0,0 +1,40 @@ > +## @file > +# Unit tests of the Ipmi blob transfer driver that are run from a host > environment. > +# > +# Copyright (c) 2020-2023, NVIDIA CORPORATION & AFFILIATES. All rights > reserved. > +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +## > + > +[Defines] > + INF_VERSION =3D 0x00010006 > + BASE_NAME =3D IpmiBlobTransferDxeUnitTestsHost > + FILE_GUID =3D 1f5d4095-ea52-432c-b078-86097fef600= 4 > + MODULE_TYPE =3D HOST_APPLICATION > + VERSION_STRING =3D 1.0 > + > +# > +# The following information is for reference only > +# and not required by the build tools. > +# > +# VALID_ARCHITECTURES =3D X64 > +# > + > +[Sources] > + IpmiBlobTransferTestUnitTests.c > + > +[Packages] > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + ManageabilityPkg/ManageabilityPkg.dec > + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec > + > +[LibraryClasses] > + BaseLib > + BaseMemoryLib > + DebugLib > + UnitTestLib > + IpmiLib > + > +[Protocols] > + gEdkiiIpmiBlobTransferProtocolGuid > diff --git a/Features/ManageabilityPkg/Include/Protocol/IpmiBlobTransfer.= h > b/Features/ManageabilityPkg/Include/Protocol/IpmiBlobTransfer.h > new file mode 100644 > index 0000000000..8ea71d8816 > --- /dev/null > +++ b/Features/ManageabilityPkg/Include/Protocol/IpmiBlobTransfer.h > @@ -0,0 +1,136 @@ > +/** @file > + > + IPMI Blob Transfer driver > + > + Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights > reserved. > + > + SPDX-License-Identifier: BSD-2-Clause-Patent Please add @Par to https://github.com/openbmc/phosphor-ipmi-blobs/blob/mast= er/README.md, as the reference of specification. > + > +**/ > +#include > +#include > +#include > + > +#define IPMI_NETFN_OEM 0x2E Let's move this definition to under MdePkg/Incldue/IndustryStandard/IpmiNet= FnOem.h, please refer to IpmiNetFnGroupExtension.h. This keeps the consiste= nt implementation with the current IPMI header files under MdePkg, although= there is only one line definition. > +#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 We can create a C header file "IpmiOpenBmc.h" under ManageabilityPkg/Includ= e/IndustryStandard. Also relocate OpenBmcOen from IpmiBloblTransfer.c to = this header file. We can have this header file that accommodates the IPMI s= pecs defined by OpenBMC. Please also use OpenBmc instead of "Oem". > + > +// > +// 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 > + ); > + You missed the function header for all function prototype here and above. > +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; > +}; Do you think EDKII_IPMI_BLOB_TRANSFER_PROTOCOL for protocol name is better?= Although IPMI_PROTOCOL wasn't named as this way. That's fine to keep the n= aming of function member as it. > + > +typedef struct _IPMI_BLOB_TRANSFER_PROTOCOL > IPMI_BLOB_TRANSFER_PROTOCOL; > + > +extern EFI_GUID gEdkiiIpmiBlobTransferProtocolGuid; > diff --git > a/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/InternalIpmiB > lobTransfer.h > b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/InternalIpmiB > lobTransfer.h > new file mode 100644 > index 0000000000..14f0dc02bc > --- /dev/null > +++ > b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/InternalIpmiB > lobTransfer.h > @@ -0,0 +1,363 @@ > +/** @file > + > + Headers for IPMI Blob Transfer driver > + > + Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights > reserved. > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +#define PROTOCOL_RESPONSE_OVERHEAD (4 * sizeof(UINT8)) // 1 byte > completion code + 3 bytes OEN > + > +// Subcommands for this protocol > +typedef enum { > + IpmiBlobTransferSubcommandGetCount =3D 0, > + IpmiBlobTransferSubcommandEnumerate, > + IpmiBlobTransferSubcommandOpen, > + IpmiBlobTransferSubcommandRead, > + IpmiBlobTransferSubcommandWrite, > + IpmiBlobTransferSubcommandCommit, > + IpmiBlobTransferSubcommandClose, > + IpmiBlobTransferSubcommandDelete, > + IpmiBlobTransferSubcommandStat, > + IpmiBlobTransferSubcommandSessionStat, > + IpmiBlobTransferSubcommandWriteMeta, > +} IPMI_BLOB_TRANSFER_SUBCOMMANDS; > + > +#pragma pack(1) > + > +typedef struct { > + UINT8 OEN[3]; > + UINT8 SubCommand; > +} IPMI_BLOB_TRANSFER_HEADER; > + > +// > +// Command 0 - BmcBlobGetCount > +// The BmcBlobGetCount command expects to receive an empty body. > +// The BMC will return the number of enumerable blobs > +// > +typedef struct { > + UINT32 BlobCount; > +} IPMI_BLOB_TRANSFER_GET_COUNT_RESPONSE; > + > +// > +// Command 1 - BmcBlobEnumerate > +// The BmcBlobEnumerate command expects to receive a body of: > +// > +typedef struct { > + UINT32 BlobIndex; // 0-based index of blob to receive > +} IPMI_BLOB_TRANSFER_BLOB_ENUMERATE_SEND_DATA; > + > +typedef struct { > + CHAR8 BlobId[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET]; > +} IPMI_BLOB_TRANSFER_BLOB_ENUMERATE_RESPONSE; > + > +// > +// Command 2 - BmcBlobOpen > +// The BmcBlobOpen command expects to receive a body of: > +// > +typedef struct { > + UINT16 Flags; > + CHAR8 BlobId[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET]; > +} IPMI_BLOB_TRANSFER_BLOB_OPEN_SEND_DATA; > + > +#define BLOB_OPEN_FLAG_READ 0 > +#define BLOB_OPEN_FLAG_WRITE 1 > +// Bits 2-7 are reserved > +// Bits 8-15 are blob-specific definitions > + > +typedef struct { > + UINT16 SessionId; > +} IPMI_BLOB_TRANSFER_BLOB_OPEN_RESPONSE; > + > +// > +// Command 3 - BmcBlobRead > +// The BmcBlobRead command expects to receive a body of: > +// > +typedef struct { > + UINT16 SessionId; // Returned from BlobOpen > + UINT32 Offset; > + UINT32 RequestedSize; > +} IPMI_BLOB_TRANSFER_BLOB_READ_SEND_DATA; > + > +typedef struct { > + UINT8 Data[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET]; > +} IPMI_BLOB_TRANSFER_BLOB_READ_RESPONSE; > + > +// > +// Command 4 - BmcBlobWrite > +// The BmcBlobWrite command expects to receive a body of: > +// > +typedef struct { > + UINT16 SessionId; // Returned from BlobOpen > + UINT32 Offset; > + UINT8 Data[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET]; > +} IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA; > + > +// > +// Command 5 - BmcBlobCommit > +// The BmcBlobCommit command expects to receive a body of: > +// > +typedef struct { > + UINT16 SessionId; // Returned from BlobOpen > + UINT8 CommitDataLength; > + UINT8 CommitData[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET]; > +} IPMI_BLOB_TRANSFER_BLOB_COMMIT_SEND_DATA; > + > +// > +// Command 6 - BmcBlobClose > +// The BmcBlobClose command expects to receive a body of: > +// > +typedef struct { > + UINT16 SessionId; // Returned from BlobOpen > +} IPMI_BLOB_TRANSFER_BLOB_CLOSE_SEND_DATA; > + > +// > +// Command 7 - BmcBlobDelete > +// NOTE: This command will fail if there are open sessions for this 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 blob > +// This command expects to receive a body of: > +// > +typedef struct { > + UINT16 SessionId; > +} IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_SEND_DATA; > + > +typedef struct { > + UINT16 BlobState; > + UINT32 Size; // Size in bytes of the blob > + UINT8 MetaDataLen; > + UINT8 MetaData[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET]; > +} IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_RESPONSE; > + > +// > +// Command 10 - BmcBlobWriteMeta > +// The BmcBlobWriteMeta command expects to receive a body of: > +// > +typedef struct { > + UINT16 SessionId; > + UINT32 Offset; > + UINT8 Data[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET]; > +} IPMI_BLOB_TRANSFER_BLOB_WRITE_META_SEND_DATA; > + > +#define IPMI_BLOB_TRANSFER_BLOB_WRITE_META_RESPONSE NULL > + > +#pragma pack() Above is defined in openbmc, we can remove it to the new C header file. > + > +/** > + 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 > + ); No function header. > + > +/** > + @param[out] Count The number of active blobs > + > + @retval EFI_SUCCESS Successfully retrieved the number of ac= tive > blobs. > + @retval Other An error occurred > +**/ > +EFI_STATUS > +IpmiBlobTransferGetCount ( > + OUT UINT32 *Count > + ); > + > +/** > + @param[in] BlobIndex The 0-based Index of the blob to en= umerate > + @param[out] BlobId The ID of the blob > + > + @retval EFI_SUCCESS Successfully enumerated the blob. > + @retval Other An error occurred > +**/ > +EFI_STATUS > +IpmiBlobTransferEnumerate ( > + IN UINT32 BlobIndex, > + OUT CHAR8 *BlobId > + ); > + > +/** > + @param[in] BlobId The ID of the blob to open > + @param[in] Flags Flags to control how the blob is op= ened > + @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 which t= o 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 which t= o 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 cal= l to > BlobOpen > + @param[in] CommitDataLength The length of data to commit to th= e > blob > + @param[in] CommitData A pointer to the data to commit > + > + @retval EFI_SUCCESS Successful commit to the blob. > + @retval Other An error occurred > +**/ > +EFI_STATUS > +IpmiBlobTransferCommit ( > + IN UINT16 SessionId, > + IN UINT8 CommitDataLength, > + IN UINT8 *CommitData > + ); > + > +/** > + @param[in] SessionId The session ID returned from a 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 statistics fo= r > + @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 successful= ly 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 sta= tistics 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 successful= ly 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 meta= data for > + @param[in] Offset The offset of the metadata to write= to > + @param[in] Data The data to write to the metadata > + > + @retval EFI_SUCCESS The blob metadata was successfully = written. > + @retval Other An error occurred > +**/ > +EFI_STATUS > +IpmiBlobTransferWriteMeta ( > + IN UINT16 SessionId, > + IN UINT32 Offset, > + IN UINT8 *Data, > + IN UINT32 WriteLength > + ); > diff --git > a/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTran > sferDxe.c > b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTran > sferDxe.c > new file mode 100644 > index 0000000000..9e663289d5 > --- /dev/null > +++ > b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTran > sferDxe.c > @@ -0,0 +1,799 @@ > +/** @file > + > + IPMI Blob Transfer driver > + > + Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights > reserved. > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > +#include > + > +#include "InternalIpmiBlobTransfer.h" > + > +#define BLOB_TRANSFER_DEBUG 0 > + > +STATIC CONST IPMI_BLOB_TRANSFER_PROTOCOL mIpmiBlobTransfer =3D { > + > (IPMI_BLOB_TRANSFER_PROTOCOL_GET_COUNT)*IpmiBlobTransferGetCou > nt, > + > (IPMI_BLOB_TRANSFER_PROTOCOL_ENUMERATE)*IpmiBlobTransferEnume > rate, > + (IPMI_BLOB_TRANSFER_PROTOCOL_OPEN)*IpmiBlobTransferOpen, > + (IPMI_BLOB_TRANSFER_PROTOCOL_READ)*IpmiBlobTransferRead, > + (IPMI_BLOB_TRANSFER_PROTOCOL_WRITE)*IpmiBlobTransferWrite, > + (IPMI_BLOB_TRANSFER_PROTOCOL_COMMIT)*IpmiBlobTransferCommit, > + (IPMI_BLOB_TRANSFER_PROTOCOL_CLOSE)*IpmiBlobTransferClose, > + (IPMI_BLOB_TRANSFER_PROTOCOL_DELETE)*IpmiBlobTransferDelete, > + (IPMI_BLOB_TRANSFER_PROTOCOL_STAT)*IpmiBlobTransferStat, > + > (IPMI_BLOB_TRANSFER_PROTOCOL_SESSION_STAT)*IpmiBlobTransferSessi > onStat, > + > (IPMI_BLOB_TRANSFER_PROTOCOL_WRITE_META)*IpmiBlobTransferWrite > Meta > +}; > + > +const UINT8 OpenBmcOen[] =3D { 0xCF, 0xC2, 0x00 }; // OpenBMC = 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; I remember we don't do local variable initialization here. We give it a in= itial value in a separate line. > + > + 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 Do you mind if we remove the macros those are used through entire file, th= e definition of BLOB_TRANSFER_DEBUG as well. We can just output the message= with DEBUG_INFO for now. We can use DEBUG_MANAGEABILITY_INFO once Manageab= ilty Part II patch set is reviewed and merged. Also, I am proposing to have new debug print error level. > + > + return Crc; > +} > + Missed function header.=20 > +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) * SendDataSize)= ; > + } > + > + IpmiSendData =3D AllocateZeroPool (IpmiSendDataSize); > + if (IpmiSendData =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + Header.OEN[0] =3D OpenBmcOen[0]; > + Header.OEN[1] =3D OpenBmcOen[1]; > + Header.OEN[2] =3D OpenBmcOen[2]; > + Header.SubCommand =3D SubCommand; > + CopyMem (IpmiSendData, &Header, sizeof > (IPMI_BLOB_TRANSFER_HEADER)); > + if (SendDataSize) { > + // > + // Calculate the Crc of the send data > + // > + Crc =3D CalculateCrc16 (SendData, SendDataSize); > + CopyMem (IpmiSendData + sizeof (IPMI_BLOB_TRANSFER_HEADER), > &Crc, sizeof (UINT16)); > + CopyMem (IpmiSendData + sizeof (IPMI_BLOB_TRANSFER_HEADER) + > sizeof (UINT16), SendData, SendDataSize); > + } > + > + #if BLOB_TRANSFER_DEBUG > + DEBUG ((DEBUG_INFO, "%a: Inputs:\n", __FUNCTION__)); > + DEBUG ((DEBUG_INFO, "%a: SendDataSize: %02x\nData: ", > __FUNCTION__, SendDataSize)); > + UINT8 i; > + for (i =3D 0; i < SendDataSize; i++) { > + DEBUG ((DEBUG_INFO, "%02x", *((UINT8 *)SendData + i))); > + } > + > + DEBUG ((DEBUG_INFO, "\n")); > + DEBUG ((DEBUG_INFO, "%a: IpmiSendDataSize: %02x\nData: ", > __FUNCTION__, IpmiSendDataSize)); > + for (i =3D 0; i < IpmiSendDataSize; i++) { > + DEBUG ((DEBUG_INFO, "%02x", *((UINT8 *)IpmiSendData + i))); > + } > + > + DEBUG ((DEBUG_INFO, "\n")); > + #endif > + > + IpmiResponseDataSize =3D (*ResponseDataSize + > PROTOCOL_RESPONSE_OVERHEAD); > + // > + // If expecting data to be returned, we have to also account for the 1= 6 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 err= or. > + // 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 back > + } 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, IpmiResponseDat= aSize)) > { > + CopyMem (ResponseData, ModifiedResponseData, > IpmiResponseDataSize); > + CopyMem (ResponseDataSize, &IpmiResponseDataSize, sizeof > (IpmiResponseDataSize)); > + FreePool (IpmiResponseData); > + return EFI_SUCCESS; > + } else { > + FreePool (IpmiResponseData); > + return EFI_CRC_ERROR; > + } > + } > +} > + > +/** Could we have short description for function in this files? We can copy it = from openbmc spec. > + @param[out] Count The number of active blobs > + > + @retval EFI_SUCCESS The command byte stream was successfull= y > 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 checksu= m > +**/ > +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 to en= umerate > + @param[out] BlobId The ID of the blob > + > + @retval EFI_SUCCESS Successfully enumerated the blob. > + @retval Other An error occurred > +**/ > +EFI_STATUS > +IpmiBlobTransferEnumerate ( > + IN UINT32 BlobIndex, > + OUT CHAR8 *BlobId > + ) > +{ > + EFI_STATUS Status; > + > + UINT8 *SendData; > + UINT8 *ResponseData; > + UINT32 SendDataSize; > + UINT32 ResponseDataSize; > + > + if (BlobId =3D=3D NULL) { > + ASSERT (FALSE); > + return EFI_ABORTED; > + } > + > + ResponseDataSize =3D sizeof > (IPMI_BLOB_TRANSFER_BLOB_ENUMERATE_RESPONSE); > + ResponseData =3D AllocateZeroPool (ResponseDataSize); > + if (ResponseData =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + // > + // Format send data > + // > + SendDataSize =3D sizeof > (IPMI_BLOB_TRANSFER_BLOB_ENUMERATE_SEND_DATA); > + SendData =3D AllocateZeroPool (SendDataSize); > + if (SendData =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + ((IPMI_BLOB_TRANSFER_BLOB_ENUMERATE_SEND_DATA *)SendData)- > >BlobIndex =3D BlobIndex; > + > + Status =3D IpmiBlobTransferSendIpmi > (IpmiBlobTransferSubcommandEnumerate, SendData, SendDataSize, (UINT8 > *)ResponseData, &ResponseDataSize); > + if (!EFI_ERROR (Status)) { > + AsciiStrCpyS (BlobId, ResponseDataSize, (CHAR8 *)ResponseData); > + } > + > + FreePool (ResponseData); > + return Status; > +} > + > +/** > + @param[in] BlobId The ID of the blob to open > + @param[in] Flags Flags to control how the blob is op= ened > + @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)) + sizeof (CHAR8); > + SendData =3D AllocateZeroPool (SendDataSize); > + if (SendData =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + AsciiStrCpyS (((IPMI_BLOB_TRANSFER_BLOB_OPEN_SEND_DATA > *)SendData)->BlobId, AsciiStrSize (BlobId) / sizeof (CHAR8), BlobId); > + ((IPMI_BLOB_TRANSFER_BLOB_OPEN_SEND_DATA *)SendData)->Flags =3D > Flags; > + // append null char to SendData > + SendData[SendDataSize-1] =3D 0; > + > + Status =3D IpmiBlobTransferSendIpmi (IpmiBlobTransferSubcommandOpen, > SendData, SendDataSize, (UINT8 *)ResponseData, &ResponseDataSize); > + if (!EFI_ERROR (Status)) { > + *SessionId =3D ((IPMI_BLOB_TRANSFER_BLOB_OPEN_RESPONSE > *)ResponseData)->SessionId; > + } > + > + FreePool (ResponseData); > + FreePool (SendData); > + FreePool (BlobSearch); > + return Status; > +} > + > +/** > + @param[in] SessionId The session ID returned from a call= to > BlobOpen > + @param[in] Offset The offset of the blob from which t= o 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 which t= o start > writing > + @param[in] Data A pointer to the data to write > + > + @retval EFI_SUCCESS Successfully wrote to the blob. > + @retval Other An error occurred > +**/ > +EFI_STATUS > +IpmiBlobTransferWrite ( > + IN UINT16 SessionId, > + IN UINT32 Offset, > + IN UINT8 *Data, > + IN UINT32 WriteLength > + ) > +{ > + EFI_STATUS Status; > + UINT8 *SendData; > + UINT32 SendDataSize; > + UINT32 ResponseDataSize; > + > + // > + // Format send data > + // > + SendDataSize =3D sizeof (SessionId) + sizeof (Offset) + WriteLength; > + SendData =3D AllocateZeroPool (SendDataSize); > + if (SendData =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + ((IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA *)SendData)- > >SessionId =3D SessionId; > + ((IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA *)SendData)->Offset > =3D Offset; > + CopyMem (((IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA > *)SendData)->Data, Data, sizeof (UINT8) * WriteLength); > + > + ResponseDataSize =3D 0; > + Status =3D IpmiBlobTransferSendIpmi > (IpmiBlobTransferSubcommandWrite, SendData, SendDataSize, NULL, > &ResponseDataSize); > + > + FreePool (SendData); > + return Status; > +} > + > +/** > + @param[in] SessionId The session ID returned from a cal= l to > BlobOpen > + @param[in] CommitDataLength The length of data to commit to th= e > blob > + @param[in] CommitData A pointer to the data to commit > + > + @retval EFI_SUCCESS Successful commit to the blob. > + @retval Other An error occurred > +**/ > +EFI_STATUS > +IpmiBlobTransferCommit ( > + IN UINT16 SessionId, > + IN UINT8 CommitDataLength, > + IN UINT8 *CommitData > + ) > +{ > + EFI_STATUS Status; > + UINT8 *SendData; > + UINT32 SendDataSize; > + UINT32 ResponseDataSize; > + > + // > + // Format send data > + // > + SendDataSize =3D sizeof (SessionId) + sizeof (CommitDataLength) + > CommitDataLength; > + SendData =3D AllocateZeroPool (SendDataSize); > + if (SendData =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + ((IPMI_BLOB_TRANSFER_BLOB_COMMIT_SEND_DATA *)SendData)- > >SessionId =3D SessionId; > + ((IPMI_BLOB_TRANSFER_BLOB_COMMIT_SEND_DATA *)SendData)- > >CommitDataLength =3D CommitDataLength; > + CopyMem (((IPMI_BLOB_TRANSFER_BLOB_COMMIT_SEND_DATA > *)SendData)->CommitData, CommitData, sizeof (UINT8) * > CommitDataLength); > + > + ResponseDataSize =3D 0; > + > + Status =3D IpmiBlobTransferSendIpmi > (IpmiBlobTransferSubcommandCommit, SendData, SendDataSize, NULL, > &ResponseDataSize); > + > + FreePool (SendData); > + return Status; > +} > + > +/** > + @param[in] SessionId The session ID returned from a 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 statistics fo= r > + @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 successful= ly gathered. > + @retval Other An error occurred > +**/ > +EFI_STATUS > +IpmiBlobTransferStat ( > + IN CHAR8 *BlobId, > + OUT UINT16 *BlobState, > + OUT UINT32 *Size, > + OUT UINT8 *MetadataLength, > + OUT UINT8 *Metadata > + ) > +{ > + EFI_STATUS Status; > + UINT8 *SendData; > + UINT8 *ResponseData; > + UINT32 SendDataSize; > + UINT32 ResponseDataSize; > + > + if (Metadata =3D=3D NULL) { > + ASSERT (FALSE); > + return EFI_ABORTED; > + } > + > + ResponseDataSize =3D sizeof > (IPMI_BLOB_TRANSFER_BLOB_STAT_RESPONSE); > + ResponseData =3D AllocateZeroPool (ResponseDataSize); > + if (ResponseData =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + // > + // Format send data > + // > + SendDataSize =3D sizeof (IPMI_BLOB_TRANSFER_BLOB_STAT_SEND_DATA); > + SendData =3D AllocateZeroPool (SendDataSize); > + if (SendData =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + AsciiStrCpyS (((IPMI_BLOB_TRANSFER_BLOB_STAT_SEND_DATA > *)SendData)->BlobId, IPMI_OEM_BLOB_MAX_DATA_PER_PACKET, BlobId); > + > + Status =3D IpmiBlobTransferSendIpmi (IpmiBlobTransferSubcommandStat, > SendData, SendDataSize, (UINT8 *)ResponseData, &ResponseDataSize); > + if (!EFI_ERROR (Status)) { > + *BlobState =3D ((IPMI_BLOB_TRANSFER_BLOB_STAT_RESPONSE > *)ResponseData)->BlobState; > + *Size =3D ((IPMI_BLOB_TRANSFER_BLOB_STAT_RESPONSE > *)ResponseData)->Size; > + *MetadataLength =3D ((IPMI_BLOB_TRANSFER_BLOB_STAT_RESPONSE > *)ResponseData)->MetaDataLen; > + > + CopyMem (&Metadata, > &((IPMI_BLOB_TRANSFER_BLOB_STAT_RESPONSE *)ResponseData)- > >MetaData, sizeof (((IPMI_BLOB_TRANSFER_BLOB_STAT_RESPONSE > *)ResponseData)->MetaData)); > + } > + > + FreePool (ResponseData); > + FreePool (SendData); > + return Status; > +} > + > +/** > + @param[in] SessionId The ID of the session to gather sta= tistics 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 successful= ly gathered. > + @retval Other An error occurred > +**/ > +EFI_STATUS > +IpmiBlobTransferSessionStat ( > + IN UINT16 SessionId, > + OUT UINT16 *BlobState, > + OUT UINT32 *Size, > + OUT UINT8 *MetadataLength, > + OUT UINT8 *Metadata > + ) > +{ > + EFI_STATUS Status; > + UINT8 *SendData; > + UINT8 *ResponseData; > + UINT32 SendDataSize; > + UINT32 ResponseDataSize; > + > + if ((BlobState =3D=3D NULL) || (Size =3D=3D NULL) || (MetadataLength = =3D=3D NULL) || > (Metadata =3D=3D NULL)) { > + ASSERT (FALSE); > + return EFI_ABORTED; > + } > + > + ResponseDataSize =3D sizeof > (IPMI_BLOB_TRANSFER_BLOB_STAT_RESPONSE); > + ResponseData =3D AllocateZeroPool (ResponseDataSize); > + if (ResponseData =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + // > + // Format send data > + // > + SendDataSize =3D sizeof > (IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_SEND_DATA); > + SendData =3D AllocateZeroPool (SendDataSize); > + if (SendData =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + ((IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_SEND_DATA *)SendData)- > >SessionId =3D SessionId; > + > + Status =3D IpmiBlobTransferSendIpmi > (IpmiBlobTransferSubcommandSessionStat, SendData, SendDataSize, (UINT8 > *)ResponseData, &ResponseDataSize); > + > + if (!EFI_ERROR (Status)) { > + *BlobState =3D > ((IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_RESPONSE > *)ResponseData)->BlobState; > + *Size =3D ((IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_RESPONSE > *)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 meta= data for > + @param[in] Offset The offset of the metadata to write= to > + @param[in] Data The data to write to the metadata > + > + @retval EFI_SUCCESS The blob metadata was successfully = 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 point = is > + the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers incl= uding > + both device drivers and bus drivers. > + > + @param[in] ImageHandle The firmware allocated handle for the UE= FI > image. > + @param[in] SystemTable A pointer to the EFI System Table. > + > + @retval EFI_SUCCESS The operation completed successfully. > + @retval Others An unexpected error occurred. > + > +**/ > +EFI_STATUS > +EFIAPI > +IpmiBlobTransferDxeDriverEntryPoint ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + return gBS->InstallMultipleProtocolInterfaces ( > + &ImageHandle, > + &gEdkiiIpmiBlobTransferProtocolGuid, > + (VOID *)&mIpmiBlobTransfer, > + NULL > + ); > +} > diff --git > a/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/Ipmi > BlobTransferTestUnitTests.c > b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/Ipm > iBlobTransferTestUnitTests.c > new file mode 100644 > index 0000000000..f326467922 > --- /dev/null > +++ > b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/Ipm > iBlobTransferTestUnitTests.c > @@ -0,0 +1,1113 @@ > +/** @file > +* > +* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. > +* > +* SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & > AFFILIATES > +* SPDX-License-Identifier: BSD-2-Clause-Patent > +* > +**/ > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include "../InternalIpmiBlobTransfer.h" > + > +#define UNIT_TEST_NAME "IPMI Blob Transfer Unit Tests" > +#define UNIT_TEST_VERSION "1.0" > + > +UINT8 InvalidCompletion[] =3D { > + 0xC0, // CompletionCode > + 0xCF, 0xC2, 0x00, // OpenBMC OEN > +}; > +#define INVALID_COMPLETION_SIZE 4 * sizeof(UINT8) > + > +UINT8 NoDataResponse[] =3D { > + 0x00, // CompletionCode > + 0xCF, 0xC2, 0x00, // OpenBMC OEN > +}; > +#define NO_DATA_RESPONSE_SIZE 4 * sizeof(UINT8) > + > +UINT8 BadOenResponse[] =3D { > + 0x00, // CompletionCode > + 0xFF, 0xC2, 0x00, // Wrong OEN > +}; > +#define BAD_OEN_RESPONSE_SIZE 4 * sizeof(UINT8) > + > +UINT8 BadCrcResponse[] =3D { > + 0x00, // CompletionCode > + 0xCF, 0xC2, 0x00, // OpenBMC OEN > + 0x00, 0x00, // CRC > + 0x01, 0x00, 0x00, 0x00, // Data > +}; > +#define BAD_CRC_RESPONSE_SIZE 10 * sizeof(UINT8) > + > +UINT8 ValidNoDataResponse[] =3D { > + 0x00, // CompletionCode > + 0xCF, 0xC2, 0x00, // OpenBMC OEN > +}; > + > +#define VALID_NODATA_RESPONSE_SIZE 4 * sizeof(UINT8) > + > +/** > + @param[in] Context [Optional] An optional parameter that enables: > + 1) test-case reuse with varied parameters and > + 2) test-case re-entry for Target tests that nee= d a > + reboot. This parameter is a VOID* and it is th= e > + responsibility of the test author to ensure tha= t the > + contents are well understood by all test cases = 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 enables: > + 1) test-case reuse with varied parameters and > + 2) test-case re-entry for Target tests that nee= d a > + reboot. This parameter is a VOID* and it is th= e > + responsibility of the test author to ensure tha= t the > + contents are well understood by all test cases = 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 enables: > + 1) test-case reuse with varied parameters and > + 2) test-case re-entry for Target tests that nee= d a > + reboot. This parameter is a VOID* and it is th= e > + responsibility of the test author to ensure tha= t the > + contents are well understood by all test cases = 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 enables: > + 1) test-case reuse with varied parameters and > + 2) test-case re-entry for Target tests that nee= d a > + reboot. This parameter is a VOID* and it is th= e > + responsibility of the test author to ensure tha= t the > + contents are well understood by all test cases = 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 enables: > + 1) test-case reuse with varied parameters and > + 2) test-case re-entry for Target tests that nee= d a > + reboot. This parameter is a VOID* and it is th= e > + responsibility of the test author to ensure tha= t the > + contents are well understood by all test cases = 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 enables: > + 1) test-case reuse with varied parameters and > + 2) test-case re-entry for Target tests that nee= d a > + reboot. This parameter is a VOID* and it is th= e > + responsibility of the test author to ensure tha= t the > + contents are well understood by all test cases = 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 enables: > + 1) test-case reuse with varied parameters and > + 2) test-case re-entry for Target tests that nee= d a > + reboot. This parameter is a VOID* and it is th= e > + responsibility of the test author to ensure tha= t the > + contents are well understood by all test cases = 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 enables: > + 1) test-case reuse with varied parameters and > + 2) test-case re-entry for Target tests that nee= d a > + reboot. This parameter is a VOID* and it is th= e > + responsibility of the test author to ensure tha= t the > + contents are well understood by all test cases = 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 enables: > + 1) test-case reuse with varied parameters and > + 2) test-case re-entry for Target tests that nee= d a > + reboot. This parameter is a VOID* and it is th= e > + responsibility of the test author to ensure tha= t the > + contents are well understood by all test cases = 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 enables: > + 1) test-case reuse with varied parameters and > + 2) test-case re-entry for Target tests that nee= d a > + reboot. This parameter is a VOID* and it is th= e > + responsibility of the test author to ensure tha= t the > + contents are well understood by all test cases = 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 enables: > + 1) test-case reuse with varied parameters and > + 2) test-case re-entry for Target tests that nee= d a > + reboot. This parameter is a VOID* and it is th= e > + responsibility of the test author to ensure tha= t the > + contents are well understood by all test cases = 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 enables: > + 1) test-case reuse with varied parameters and > + 2) test-case re-entry for Target tests that nee= d a > + reboot. This parameter is a VOID* and it is th= e > + responsibility of the test author to ensure tha= t the > + contents are well understood by all test cases = 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 enables: > + 1) test-case reuse with varied parameters and > + 2) test-case re-entry for Target tests that nee= d a > + reboot. This parameter is a VOID* and it is th= e > + responsibility of the test author to ensure tha= t the > + contents are well understood by all test cases = 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 enables: > + 1) test-case reuse with varied parameters and > + 2) test-case re-entry for Target tests that nee= d a > + reboot. This parameter is a VOID* and it is th= e > + responsibility of the test author to ensure tha= t the > + contents are well understood by all test cases = 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 enables: > + 1) test-case reuse with varied parameters and > + 2) test-case re-entry for Target tests that nee= d a > + reboot. This parameter is a VOID* and it is th= e > + responsibility of the test author to ensure tha= t the > + contents are well understood by all test cases = 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 enables: > + 1) test-case reuse with varied parameters and > + 2) test-case re-entry for Target tests that nee= d a > + reboot. This parameter is a VOID* and it is th= e > + responsibility of the test author to ensure tha= t the > + contents are well understood by all test cases = 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 enables: > + 1) test-case reuse with varied parameters and > + 2) test-case re-entry for Target tests that nee= d a > + reboot. This parameter is a VOID* and it is th= e > + responsibility of the test author to ensure tha= t the > + contents are well understood by all test cases = 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 enables: > + 1) test-case reuse with varied parameters and > + 2) test-case re-entry for Target tests that nee= d a > + reboot. This parameter is a VOID* and it is th= e > + responsibility of the test author to ensure tha= t the > + contents are well understood by all test cases = 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, MetadataLeng= th, > Metadata); > + > + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); > + UT_ASSERT_EQUAL (*BlobState, 1); > + UT_ASSERT_EQUAL (*Size, 0x05040302); > + UT_ASSERT_EQUAL (*MetadataLength, 4); > + UT_ASSERT_MEM_EQUAL (Metadata, ExpectedMetadata, 4); > + FreePool (MockResponseResults); > + FreePool (BlobState); > + FreePool (Size); > + FreePool (MetadataLength); > + FreePool (Metadata); > + return UNIT_TEST_PASSED; > +} > + > +/** > + @param[in] Context [Optional] An optional parameter that enables: > + 1) test-case reuse with varied parameters and > + 2) test-case re-entry for Target tests that nee= d a > + reboot. This parameter is a VOID* and it is th= e > + responsibility of the test author to ensure tha= t the > + contents are well understood by all test cases = 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 enables: > + 1) test-case reuse with varied parameters and > + 2) test-case re-entry for Target tests that nee= d a > + reboot. This parameter is a VOID* and it is th= e > + responsibility of the test author to ensure tha= t the > + contents are well understood by all test cases = 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, MetadataLe= ngth, > Metadata); > + > + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); > + UT_ASSERT_EQUAL (*BlobState, 1); > + UT_ASSERT_EQUAL (*Size, 0x05040302); > + UT_ASSERT_EQUAL (*MetadataLength, 4); > + UT_ASSERT_MEM_EQUAL (Metadata, ExpectedMetadata, 4); > + FreePool (MockResponseResults); > + FreePool (BlobState); > + FreePool (Size); > + FreePool (MetadataLength); > + FreePool (Metadata); > + return UNIT_TEST_PASSED; > +} > + > +/** > + @param[in] Context [Optional] An optional parameter that enables: > + 1) test-case reuse with varied parameters and > + 2) test-case re-entry for Target tests that nee= d a > + reboot. This parameter is a VOID* and it is th= e > + responsibility of the test author to ensure tha= t the > + contents are well understood by all test cases = 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 enables: > + 1) test-case reuse with varied parameters and > + 2) test-case re-entry for Target tests that nee= d a > + reboot. This parameter is a VOID* and it is th= e > + responsibility of the test author to ensure tha= t the > + contents are well understood by all test cases = 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 with > status =3D %r\n", Status)); > + ASSERT (FALSE); > + return Status; > + } > + > + // > + // Populate the Unit Test Suite. > + // > + Status =3D CreateUnitTestSuite (&IpmiBlobTransfer, Framework, "IPMI Bl= ob > Transfer Tests", "UnitTest.IpmiBlobTransferCB", NULL, NULL); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for IPMI Blob > Transfer Tests\n")); > + Status =3D EFI_OUT_OF_RESOURCES; > + return Status; > + } > + > + // CalculateCrc16 > + Status =3D AddTestCase (IpmiBlobTransfer, "Test CRC Calculation", > "GoodCrc", GoodCrc, NULL, NULL, NULL); > + Status =3D AddTestCase (IpmiBlobTransfer, "Test Bad CRC Calculation", > "BadCrc", BadCrc, NULL, NULL, NULL); > + // IpmiBlobTransferSendIpmi > + Status =3D AddTestCase (IpmiBlobTransfer, "Send IPMI returns bad > completion", "SendIpmiBadCompletion", SendIpmiBadCompletion, NULL, > NULL, NULL); > + Status =3D AddTestCase (IpmiBlobTransfer, "Send IPMI returns successfu= lly > with no data", "SendIpmiNoDataResponse", SendIpmiNoDataResponse, > NULL, NULL, NULL); > + Status =3D AddTestCase (IpmiBlobTransfer, "Send IPMI returns successfu= lly > with bad OEN", "SendIpmiBadOenResponse", SendIpmiBadOenResponse, > NULL, NULL, NULL); > + Status =3D AddTestCase (IpmiBlobTransfer, "Send IPMI returns successfu= lly > with bad CRC", "SendIpmiBadCrcResponse", SendIpmiBadCrcResponse, > NULL, NULL, NULL); > + Status =3D AddTestCase (IpmiBlobTransfer, "Send IPMI returns with vali= d > GetCount data", "SendIpmiValidCountResponse", > SendIpmiValidCountResponse, NULL, NULL, NULL); > + // IpmiBlobTransferGetCount > + Status =3D AddTestCase (IpmiBlobTransfer, "GetCount call with valid da= ta", > "GetCountValidCountResponse", GetCountValidCountResponse, NULL, > NULL, NULL); > + // IpmiBlobTransferEnumerate > + Status =3D AddTestCase (IpmiBlobTransfer, "Enumerate call with valid d= ata", > "EnumerateValidResponse", EnumerateValidResponse, NULL, NULL, NULL); > + Status =3D AddTestCase (IpmiBlobTransfer, "Enumerate call with invalid > output buffer", "EnumerateInvalidBuffer", EnumerateInvalidBuffer, NULL, > NULL, NULL); > + // IpmiBlobTransferOpen > + Status =3D AddTestCase (IpmiBlobTransfer, "Open call with valid data", > "OpenValidResponse", OpenValidResponse, NULL, NULL, NULL); > + // IpmiBlobTransferRead > + Status =3D AddTestCase (IpmiBlobTransfer, "Read call with valid data", > "ReadValidResponse", ReadValidResponse, NULL, NULL, NULL); > + Status =3D AddTestCase (IpmiBlobTransfer, "Read call with invalid buff= er", > "ReadInvalidBuffer", ReadInvalidBuffer, NULL, NULL, NULL); > + // IpmiBlobTransferWrite > + Status =3D AddTestCase (IpmiBlobTransfer, "Write call with valid data"= , > "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 data"= , > "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 valid d= ata", > "BlobStatValidResponse", BlobStatValidResponse, NULL, NULL, NULL); > + Status =3D AddTestCase (IpmiBlobTransfer, "Blob Stat call with invalid= buffer", > "BlobStatInvalidBuffer", BlobStatInvalidBuffer, NULL, NULL, NULL); > + // IpmiBlobTransferSessionStat > + Status =3D AddTestCase (IpmiBlobTransfer, "Session Stat call with vali= d data", > "SessionStatValidResponse", SessionStatValidResponse, NULL, NULL, NULL); > + Status =3D AddTestCase (IpmiBlobTransfer, "Session Stat call with inva= lid > buffer", "SessionStatInvalidBuffer", SessionStatInvalidBuffer, NULL, NULL= , > NULL); > + // IpmiBlobTransferWriteMeta > + Status =3D AddTestCase (IpmiBlobTransfer, "WriteMeta call with valid d= ata", > "WriteMetaValidResponse", WriteMetaValidResponse, NULL, NULL, NULL); > + > + // Execute the tests. > + Status =3D RunAllTestSuites (Framework); > + return Status; > +} > + > +/** > + Standard UEFI entry point for target based > + unit test execution from UEFI Shell. > +**/ > +EFI_STATUS > +EFIAPI > +BaseLibUnitTestAppEntry ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + return SetupAndRunUnitTests (); > +} > + > +/** > + Standard POSIX C entry point for host based unit test execution. > +**/ > +int > +main ( > + int argc, > + char *argv[] > + ) > +{ > + return SetupAndRunUnitTests (); > +} > diff --git > a/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/Readme.md > b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/Readme.md > new file mode 100644 > index 0000000000..47800f5801 > --- /dev/null > +++ > b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/Readme.md > @@ -0,0 +1,24 @@ > +# IPMI Blob Transfer Interface Driver > + > +This DXE module is a UEFI implementation of the Phorphor Blob Transfer > Interface defined in OpenBMC > +https://github.com/openbmc/phosphor-ipmi-blobs > + > +## NVIDIA's OpenBMC implements this interface as a protocol, allowing > UEFI and BMC to transfer blobs over IPMI. We should remove NVIDIA and use edk2 instead.=20 Thanks Abner > + > +### Usage: > +Any DXE module that wishes to use this protocol should do the following: > +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 successful un= it > tests. > + > +### Debugging > +To assist in debugging any issues, change BLOB_TRANSFER_DEBUG to 1 > -- > 2.17.1