From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM04-DM6-obe.outbound.protection.outlook.com (NAM04-DM6-obe.outbound.protection.outlook.com [40.107.102.97]) by mx.groups.io with SMTP id smtpd.web11.45449.1681700923883428165 for ; Sun, 16 Apr 2023 20:08:44 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="no key for verify" header.i=@amperemail.onmicrosoft.com header.s=selector1-amperemail-onmicrosoft-com header.b=7U15lVvk; spf=pass (domain: os.amperecomputing.com, ip: 40.107.102.97, mailfrom: tinhnguyen@os.amperecomputing.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=EOpYlgBXiWQf0OOoAI569sFJiXNwDY1yZ+ex2qECB3lwVzagObNTEAh5xQ7AVOromBRav9qSewVrXSS/lb1wGV9DZ2W6Bf/uIWQ1RsFP4AYQFLu2yO/tCG6lKlL9cCeIuemH4dfBFTc0+TXijYHK605FdorYEPB3VHuuVXPvNWRgeWGPk1G599NEbcuh8alTLKELT58HQRsEEe5nhmmUgRDPLJ2erWeSn536AQ510TUDnDQBlgohTD2DqWq2i23GIK9MValR3Sp5LJVTxiM8r4SUPDoLJr9VIzyJ/xoKj7+5ZT1yeRfGUHdbonhpG04uE93YXDGukZ3kmcIIhirfuw== 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=RxjcR9H5ShvYIzzOkA1SMLTEIbU4Nyx8jVAMcrQJHQw=; b=cdUI93J1ZVd8y+4hiP7GZnmgK1vvhGQFkwma/lKcpt5Wfzbw+gL3AEcj/lP2vBHynvBP8twC0pjgzv/xxlWDReOGzcxI3ZSpGAIsJY791GLDptekviz6INNXlyxIqCv1RyxDIoHASzQLN16nKX2smh+DS3jt1p+Z7QfBZJEbN+zyScoA234qyIrPP7734vrJ15PYC9d5oeFaeUwiItu/R6oFc4U9bQ9TN5UulmuwZxZ+dzTlOjDAr25FDROlXu6wI7vpFwECLZVMlWg17RKr+JI5DdIa3N2YgqW8tIc/kk4MbtG6iD7jrVIVFvUXLbffRVwmLe/DyaOHOI90Jna6aw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=os.amperecomputing.com; dmarc=pass action=none header.from=amperemail.onmicrosoft.com; dkim=pass header.d=amperemail.onmicrosoft.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amperemail.onmicrosoft.com; s=selector1-amperemail-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=RxjcR9H5ShvYIzzOkA1SMLTEIbU4Nyx8jVAMcrQJHQw=; b=7U15lVvkU5O+tN1tmo79t7L9OPPJk/zoSmPxhkwGnSQSy+ywWWZucfgiE5xr2wqjW/5gQi8UXqrhvGqoBnrd1CFvgumoBwchOYD6JXzk+9c4IENbxbG+BJJnOFcR3TuzfGdRACO7+3sbcbwlQlUH+Dy0B79jT2IqEDyPaQtA0zo= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=amperemail.onmicrosoft.com; Received: from DM5PR0102MB3336.prod.exchangelabs.com (2603:10b6:4:9f::11) by PH0PR01MB6585.prod.exchangelabs.com (2603:10b6:510:79::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6319.19; Mon, 17 Apr 2023 03:08:37 +0000 Received: from DM5PR0102MB3336.prod.exchangelabs.com ([fe80::bb9e:46d1:ae4b:caf2]) by DM5PR0102MB3336.prod.exchangelabs.com ([fe80::bb9e:46d1:ae4b:caf2%6]) with mapi id 15.20.6319.019; Mon, 17 Apr 2023 03:08:37 +0000 Message-ID: <594581df-5fbf-a5e6-0521-962941f2ed90@amperemail.onmicrosoft.com> Date: Mon, 17 Apr 2023 10:08:26 +0700 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:102.0) Gecko/20100101 Thunderbird/102.10.0 Subject: Re: [edk2-platforms][PATCH] ManageabilityPkg: add support for the phosphor ipmi blob transfer protocol To: "Chang, Abner" , Nickle Wang , "devel@edk2.groups.io" CC: Isaac Oram , "Attar, AbdulLateef (Abdul Lateef)" References: <20230412031724.12690-1-nicklew@nvidia.com> <0c49ba9d-25e8-2727-a1bd-c93d2d2d6bce@amperemail.onmicrosoft.com> <2e9e9899-ed63-ffd9-eff4-e8ef5af01950@amperemail.onmicrosoft.com> From: "Tinh Nguyen" In-Reply-To: X-ClientProxiedBy: SG2P153CA0022.APCP153.PROD.OUTLOOK.COM (2603:1096:4:c7::9) To DM5PR0102MB3336.prod.exchangelabs.com (2603:10b6:4:9f::11) Return-Path: tinhnguyen@os.amperecomputing.com MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DM5PR0102MB3336:EE_|PH0PR01MB6585:EE_ X-MS-Office365-Filtering-Correlation-Id: 8278441f-b834-4499-968c-08db3ef10935 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: bfjpA6ltRVcXEpFRNSu1kII7Xlk2qUhKZcguBwQBVz1Ezn3UdOq82TDDMCtvRMq6f74QR84/aMvyHtVFQxJpbuzBx+DM9fTyt6YobFoaNkNC6tOKmkeNpsqf0RMPpaZ1/Cmf/Yg0JE+L9OXwQIi9jDjN5ee16ax3G6gF+zMsr5PRtPDgxZcdShTPcYKK1dEqmHgrOdVkeZh1h69lB8n6HJvEptqRYHpXuLP3c1JHuKJHnNAqqUpC1FXRUOvoajiENvMxGWW/RbCji7A8jKQHqJJdCgUMEcxgNkBlMWuGVPzF/DHlUuG4Jgqmlr7iZd9EJ0Y8BV74GIiCg3FakDLRzRn48v6R+PRZu8GQ6rP5u6bTzmdztvdk05esMyL/l4GGGFecxtScsWUywGVLI7BKMCCnJqVk6DNIwF6uq667pCOT1dAnwjMln07TZyJOv0CF3yo4ef2F5Zl8ud98whFpQG2ZSLeZO5jyx1uwFvYdtwhZyhUDwDPiXr7nhr/WUZCBSRE7U9IqaDY7iWq/4KHuGQKzaHYhMg4Xh/WUTZ0krhdft30bitZRmd8vhl658AtMGBLfRSdmTholsrSCD5aMDFQnxangIJASrqUI9o+5sXSdCv5cADQcKe1STqarQo0WjBCdciXJJqKqLDRXwHDXtebvR4jr5LdW07KyJhWw0TA= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:DM5PR0102MB3336.prod.exchangelabs.com;PTR:;CAT:NONE;SFS:(13230028)(4636009)(366004)(136003)(39850400004)(396003)(376002)(346002)(451199021)(19627235002)(54906003)(110136005)(316002)(4326008)(66946007)(66476007)(66556008)(966005)(478600001)(52116002)(6486002)(6666004)(8936002)(8676002)(41300700001)(5660300002)(30864003)(2906002)(83170400001)(31696002)(38100700002)(38350700002)(2616005)(6512007)(6506007)(26005)(186003)(53546011)(42882007)(83380400001)(31686004)(43740500002)(579004)(559001)(44824005);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?8CSZ8a4lFTIhGT3jvKnRG1JrK+rrApvAHR+vWZ/hZiUJyumFPBu0d3iE8fas?= =?us-ascii?Q?L1I/TnmP0P4EHJEdbfXv7B8wH3oJ/jTUEQLOV/0CeJbUqPlDxASpzutVB3yY?= =?us-ascii?Q?nzwJhsI0/Ds57yauB+TDu8s44XibZeH0/hSoCkG8jCaYyXxCkyv+OpYUDw2m?= =?us-ascii?Q?El6mRg8oogObq5ooAV+GxjR3+OBoBCHtao/cSUtKGLxQ6rL4P3W37fNd3omK?= =?us-ascii?Q?Vfk4FJhSalJvak82pjcXMZ5rgF7W+CHwpMCotFMUp1Z6OlO+XcIuFODfbyoH?= =?us-ascii?Q?pa71vkdxCsxHIGBFc9zuhd9ztKgnU4RBown7ZTXbqU+bKh+xGJJfmdmwp3yU?= =?us-ascii?Q?mJgpxy2/ftgxA/7VGTVTi9yukRbXyFHxIPprbVzPhna+csAKcJZtROdu4Vlt?= =?us-ascii?Q?JFkERYEQJ8INKA8mwVynt8BSuXSwq53poqf6QC9RQZt892K8GCIxVCFZyZU6?= =?us-ascii?Q?c5iO4jdtO7BKBevu1iFMbrvun/PHGr9OsS+E8aFp8NUicSniVCjOLwASVHws?= =?us-ascii?Q?L/b+8Y8WIIMqwcJbOVqMSoNcZrSxkoNS8tngUdsoyj/xnffXCQTWfOoN6OFa?= =?us-ascii?Q?jtnvoDq/H53aOXkExY7PXtpeJNohkRrmMvS9q7y3aBcMbH6mVHaqVQGo/2UJ?= =?us-ascii?Q?Z/4dZSg9zyzU+rWNEqcESNdqC4FbIHQLQByvNP9gDatXqMf9OSnw+rA26uW5?= =?us-ascii?Q?/JdPdlUnTllBitY4hLJn3wyV/n710r6zRSs6Mi7K4gV42iDFGHmP0SuFgWy3?= =?us-ascii?Q?N/j2oEhlxLITcAXP00Nwpnl45wI4JBk2+QIGc/5YPWYDPI/x/FeeygM9Pgb/?= =?us-ascii?Q?GGJPLiHWahgo9FqDl24GUdR5difnPP45Q17JEaz3W1YRSHiyv8ZAyNLXlCJ/?= =?us-ascii?Q?RqQGIPo6HqDPFXRedxz4mBkjvJfXAGnxTtQhYHtNYiVcJPfO77dhr6FK9n8p?= =?us-ascii?Q?xTmRlNbdkz3Unf9tOZAplXaKBAgtTC6tfeaiZBaG2b7lmjxEgNRysJnCrAOH?= =?us-ascii?Q?5/7U5rOhSoEDm2MPPxYGYk675TzA7kif8MGpaOqQWeOf4pH0Zwbd2iyCBPkv?= =?us-ascii?Q?f+Oza/C5oJU5gXmzaO9+4f1C4Qh9UwJPH4Ur7yUFLr1h6FFiFrV1kSxduL+P?= =?us-ascii?Q?wyVl3fFJ7Ykm9gQXcLq3EVUHWBufTbAxUbD11N+sbsBL8kjOXVd8bL3ZC6ST?= =?us-ascii?Q?+9lNACNcB41Zl6SV5mMpqUpFIokMNRf2IDqitrzug5jPwFlkT1RMoe3IhM9C?= =?us-ascii?Q?1eHBpnnDB6ZNkJ3YNOyel5UJ5rd9Y30SFOprNUcoG2WbQSHyAyC77rpU+qd0?= =?us-ascii?Q?15XNOckMETxeK6edx/RYWMY8+QwaDm5sgfAvcEa+e0kn85+TCuUwdR4zLoJH?= =?us-ascii?Q?edvgui3e9dA4KmmBmbNJk3AncUeJZYF40fVEW2Mb0r2agwfLp4z7seC8uMy7?= =?us-ascii?Q?izRE54+eg1NL+j1LAZjCOkigDpkAEKY4MWrKwSHtulMSCUp+vtMffphMEKfQ?= =?us-ascii?Q?ZK90dRdrTCm2D40smYa+cr6XOtjNvcqZv/T51PuO8rciBrqFqcNJPjLDj8mU?= =?us-ascii?Q?vPB096j4KS2mfbyGhhhauNhx8oI8qrZppqtGCmupMLFZ8vxKywJMFDJ/HlT/?= =?us-ascii?Q?BdYwQPOvJY7VsSsMnaqvC1w=3D?= X-OriginatorOrg: amperemail.onmicrosoft.com X-MS-Exchange-CrossTenant-Network-Message-Id: 8278441f-b834-4499-968c-08db3ef10935 X-MS-Exchange-CrossTenant-AuthSource: DM5PR0102MB3336.prod.exchangelabs.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 17 Apr 2023 03:08:37.2859 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 3bc2b170-fd94-476d-b0ce-4229bdc904a7 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: KVadOO9akm+UwyciyI0pZ65vQTMWZle2WsicnDubvJWxQDAyNtOkbLlOeqsBn9ixlosrPnOv0JN7cYWSpmJWdAW/20AFqrJJ6FXjF+GijvZuMcS2G8n2CCUkWkcoyQn0 X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH0PR01MB6585 Content-Language: en-US Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: quoted-printable Hi Abner, On 17/04/2023 10:01, Chang, Abner wrote: > [EXTERNAL EMAIL NOTICE: This email originated from an external sender. Pl= ease be mindful of safe email handling and proprietary information protecti= on practices.] > > > [AMD Official Use Only - General] > > > >> -----Original Message----- >> From: Tinh Nguyen >> Sent: Monday, April 17, 2023 10:25 AM >> To: Chang, Abner ; Nickle Wang >> ; devel@edk2.groups.io >> Cc: Isaac Oram ; Attar, AbdulLateef (Abdul Latee= f) >> >> Subject: Re: [edk2-platforms][PATCH] ManageabilityPkg: add support for t= he >> phosphor ipmi blob transfer protocol >> >> Caution: This message originated from an External Source. Use proper >> caution when opening attachments, clicking links, or responding. >> >> >> On 4/16/2023 5:50 PM, Chang, Abner wrote: >>> [EXTERNAL EMAIL NOTICE: This email originated from an external sender. >> Please be mindful of safe email handling and proprietary information >> protection practices.] >>> >>> [AMD Official Use Only - General] >>> >>> Tink and Nickle, >>> Two feedbacks in below, >>> >>>> -----Original Message----- >>>> From: Tinh Nguyen >>>> Sent: Sunday, April 16, 2023 6:29 PM >>>> To: Nickle Wang;devel@edk2.groups.io >>>> Cc: Chang, Abner; Isaac Oram >>>> ; Attar, AbdulLateef (Abdul Lateef) >>>> >>>> Subject: Re: [edk2-platforms][PATCH] ManageabilityPkg: add support for >> the >>>> phosphor ipmi blob transfer protocol >>>> >>>> Caution: This message originated from an External Source. Use proper >>>> caution when opening attachments, clicking links, or responding. >>>> >>>> >>>> Hi Nickle, >>>> >>>> Please find my inline comments below >>>> >>>> On 4/12/2023 10:17 AM, Nickle Wang wrote: >>>>> [EXTERNAL EMAIL NOTICE: This email originated from an external sender= . >>>> Please be mindful of safe email handling and proprietary information >>>> protection practices.] >>>>> This change implements the blob transfer protocol used in OpenBmc >>>>> documented here:https://github.com/openbmc/phosphor-ipmi-blobs >>>>> >>>>> Signed-off-by: Nick Ramirez >>>>> Cc: Abner Chang >>>>> Cc: Isaac Oram >>>>> Cc: Abdul Lateef Attar >>>>> Cc: Nickle Wang >>>>> Cc: Tinh Nguyen >>>>> --- >>>>> .../ManageabilityPkg/ManageabilityPkg.dec | 6 + >>>>> .../Include/Dsc/Manageability.dsc | 4 +- >>>>> .../IpmiBlobTransferDxe.inf | 39 + >>>>> .../IpmiBlobTransferTestUnitTestsHost.inf | 40 + >>>>> .../Include/Protocol/IpmiBlobTransfer.h | 136 ++ >>>>> .../InternalIpmiBlobTransfer.h | 363 ++++++ >>>>> .../IpmiBlobTransferDxe/IpmiBlobTransferDxe.c | 799 ++++++++++++ >>>>> .../UnitTest/IpmiBlobTransferTestUnitTests.c | 1113 >>>> +++++++++++++++++ >>>>> .../Universal/IpmiBlobTransferDxe/Readme.md | 24 + >>>>> 9 files changed, 2523 insertions(+), 1 deletion(-) >>>>> create mode 100644 >> Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransf >>>> erDxe.inf >>>>> create mode 100644 >> Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiBl >>>> obTransferTestUnitTestsHost.inf >>>>> create mode 100644 >>>> Features/ManageabilityPkg/Include/Protocol/IpmiBlobTransfer.h >>>>> create mode 100644 >> Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/InternalIpmiBlo >>>> bTransfer.h >>>>> create mode 100644 >> Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransf >>>> erDxe.c >>>>> create mode 100644 >> Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiBl >>>> obTransferTestUnitTests.c >>>>> create mode 100644 >>>> Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/Readme.md >>>>> diff --git a/Features/ManageabilityPkg/ManageabilityPkg.dec >>>> b/Features/ManageabilityPkg/ManageabilityPkg.dec >>>>> index 9a930d3e4b..e2d6cccc50 100644 >>>>> --- a/Features/ManageabilityPkg/ManageabilityPkg.dec >>>>> +++ b/Features/ManageabilityPkg/ManageabilityPkg.dec >>>>> @@ -4,6 +4,7 @@ >>>>> # those are related to the platform management. >>>>> # >>>>> # Copyright (C) 2023 Advanced Micro Devices, Inc. All rights >> 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, 0x4= 269, >>>> { 0xA3, 0x1A, 0x38, 0x0F, 0x54, 0xF1, 0xA1, 0x8A } } >>>>> # Manageability Protocol PLDM >>>>> gManageabilityProtocolPldmGuid =3D { 0x3958090D, 0x69DD, 0x4= 868, >>>> { 0x9C, 0x41, 0xC9, 0xAC, 0x31, 0xB5, 0x25, 0xC5 } } >>>>> + >>>>> +[Protocols] >>>>> + >>>>> + ## Include/Protocol/IpmiBlobTransfer.h >>>>> + gEdkiiIpmiBlobTransferProtocolGuid =3D { 0x05837c75, 0x1d65, 0x468= b, >>>> { 0xb1, 0xc2, 0x81, 0xaf, 0x9a, 0x31, 0x5b, 0x2c } } >>>>> diff --git a/Features/ManageabilityPkg/Include/Dsc/Manageability.dsc >>>> b/Features/ManageabilityPkg/Include/Dsc/Manageability.dsc >>>>> index 0d868fdf4a..111d6b91dc 100644 >>>>> --- a/Features/ManageabilityPkg/Include/Dsc/Manageability.dsc >>>>> +++ b/Features/ManageabilityPkg/Include/Dsc/Manageability.dsc >>>>> @@ -2,11 +2,13 @@ >>>>> # Common libraries for Manageabilty Package >>>>> # >>>>> # Copyright (C) 2023 Advanced Micro Devices, Inc. All rights >> reserved.
>>>>> +# Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights >>>> reserved. >>>>> # SPDX-License-Identifier: BSD-2-Clause-Patent >>>>> # >>>>> ## >>>>> [LibraryClasses] >>>>> >> ManageabilityTransportHelperLib|ManageabilityPkg/Library/BaseManageabi >>>> lityTransportHelperLib/BaseManageabilityTransportHelper.inf >>>>> + >> IpmiLib|MdeModulePkg/Library/DxeIpmiLibIpmiProtocol/DxeIpmiLibIpmiPr >>>> otocol.inf >>>>> [LibraryClasses.ARM, LibraryClasses.AARCH64] >>>>> # >>>>> @@ -22,4 +24,4 @@ >>>>> [Components.X64] >>>>> ManageabilityPkg/Universal/IpmiProtocol/Dxe/IpmiProtocolDxe.inf >>>>> ManageabilityPkg/Universal/IpmiProtocol/Smm/IpmiProtocolSmm.inf >>>>> - >>>>> + >> ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransferDxe.inf >>>>> diff --git >> a/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTran >>>> sferDxe.inf >>>> >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTran >>>> sferDxe.inf >>>>> new file mode 100644 >>>>> index 0000000000..28e9d293c1 >>>>> --- /dev/null >>>>> +++ >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTran >>>> sferDxe.inf >>>>> @@ -0,0 +1,39 @@ >>>>> +## @file >>>>> +# IPMI Blob Transfer Protocol DXE Driver. >>>>> +# >>>>> +# Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All >> rights >>>> reserved. >>>>> +# >>>>> +# SPDX-License-Identifier: BSD-2-Clause-Patent >>>>> +# >>>>> + >>>>> +[Defines] >>>>> + INF_VERSION =3D 0x00010005 >>>>> + BASE_NAME =3D IpmiBlobTransferDxe >>>>> + FILE_GUID =3D 6357c804-78bb-4b0c-abdf-c75df94= 2f319 >>>>> + MODULE_TYPE =3D DXE_DRIVER >>>>> + VERSION_STRING =3D 1.0 >>>>> + ENTRY_POINT =3D IpmiBlobTransferDxeDriverEntryP= oint >>>>> + >>>>> +[Sources.common] >>>>> + IpmiBlobTransferDxe.c >>>>> + >>>>> +[LibraryClasses] >>>>> + BaseLib >>>>> + BaseMemoryLib >>>>> + DebugLib >>>>> + IpmiLib >>>>> + MemoryAllocationLib >>>>> + PcdLib >>>>> + UefiBootServicesTableLib >>>>> + UefiDriverEntryPoint >>>>> + >>>>> +[Packages] >>>>> + MdePkg/MdePkg.dec >>>>> + MdeModulePkg/MdeModulePkg.dec >>>>> + ManageabilityPkg/ManageabilityPkg.dec >>>>> + >>>>> +[Protocols] >>>>> + gEdkiiIpmiBlobTransferProtocolGuid >>>>> + >>>>> +[Depex] >>>>> + TRUE >>>>> diff --git >> a/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/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 ho= st >>>> environment. >>>>> +# >>>>> +# Copyright (c) 2020-2023, NVIDIA CORPORATION & AFFILIATES. All >> rights >>>> reserved. >>>>> +# >>>>> +# SPDX-License-Identifier: BSD-2-Clause-Patent >>>>> +## >>>>> + >>>>> +[Defines] >>>>> + INF_VERSION =3D 0x00010006 >>>>> + BASE_NAME =3D IpmiBlobTransferDxeUnitTestsHos= t >>>>> + FILE_GUID =3D 1f5d4095-ea52-432c-b078-86097fe= f6004 >>>>> + MODULE_TYPE =3D HOST_APPLICATION >>>>> + VERSION_STRING =3D 1.0 >>>>> + >>>>> +# >>>>> +# The following information is for reference only >>>>> +# and not required by the build tools. >>>>> +# >>>>> +# VALID_ARCHITECTURES =3D X64 >>>>> +# >>>>> + >>>>> +[Sources] >>>>> + IpmiBlobTransferTestUnitTests.c >>>>> + >>>>> +[Packages] >>>>> + MdePkg/MdePkg.dec >>>>> + MdeModulePkg/MdeModulePkg.dec >>>>> + ManageabilityPkg/ManageabilityPkg.dec >>>>> + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec >>>>> + >>>>> +[LibraryClasses] >>>>> + BaseLib >>>>> + BaseMemoryLib >>>>> + DebugLib >>>>> + UnitTestLib >>>>> + IpmiLib >>>>> + >>>>> +[Protocols] >>>>> + gEdkiiIpmiBlobTransferProtocolGuid >>>>> diff --git >>>> a/Features/ManageabilityPkg/Include/Protocol/IpmiBlobTransfer.h >>>> b/Features/ManageabilityPkg/Include/Protocol/IpmiBlobTransfer.h >>>>> new file mode 100644 >>>>> index 0000000000..8ea71d8816 >>>>> --- /dev/null >>>>> +++ b/Features/ManageabilityPkg/Include/Protocol/IpmiBlobTransfer.h >>>>> @@ -0,0 +1,136 @@ >>>>> +/** @file >>>>> + >>>>> + IPMI Blob Transfer driver >>>>> + >>>>> + Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All >> rights >>>> reserved. >>>>> + >>>>> + SPDX-License-Identifier: BSD-2-Clause-Patent >>>>> + >>>>> +**/ >>>>> +#include >>>>> +#include >>>>> +#include >>>>> + >>>>> +#define IPMI_NETFN_OEM 0x2E >>>>> +#define IPMI_OEM_BLOB_TRANSFER_CMD 0x80 >>>>> +#define IPMI_OEM_BLOB_MAX_DATA_PER_PACKET 64 >>>> It is better to avoid fixing the packet size here. >>>> >>>> - For ssif, get it from "get capabilities" command. If BMC supports on= ly >>>> single-part read/write, this size exceeds BMC capability >>>> >>>> - For kcs, I don't see the limitation >>>> >>>> I think limiting the size here is unsuitable, applications that use th= is >>>> protocol should check the size themselves >>> IPMI blob uses IpmiLib to submit the command and IPMI protocol is the >> one that talks to transport interface. That would be IPMI protocol's >> responsibility to know the exact maximum size of each transfer payload, >> according to the transport interface. >>> From the ManageabilityPkg design, SSIF manageability transport librar= y can >> returns MTU and the capability of single/multi part read/write to caller= (IPMI >> protocol for example). IPMI protocol should determine having a single pa= rt >> transfer or splitting the packet into multi transfers. >>> I can help on SSIF manageability transport library as well if you have = SSIF >> sample code. >> yes I=E2=80=99m preparing the ssif driver, I=E2=80=99m sorry for bein= g late. > That's great, Tinh. I believe there are some missing considerations in th= e ManageabilityPkg and we need more use cases to find it out and improve it= . I will definitely help on this. > >>>>> + >>>>> +#define BLOB_TRANSFER_STAT_OPEN_R BIT0 >>>>> +#define BLOB_TRANSFER_STAT_OPEN_W BIT1 >>>>> +#define BLOB_TRANSFER_STAT_COMMITING BIT2 >>>>> +#define BLOB_TRANSFER_STAT_COMMITTED BIT3 >>>>> +#define BLOB_TRANSFER_STAT_COMMIT_ERROR BIT4 >>>>> +// Bits 5-7 are reserved >>>>> +// Bits 8-15 are blob-specific definitions >>>>> + >>>>> +// >>>>> +// Blob Transfer Function Prototypes >>>>> +// >>>>> +typedef >>>>> +EFI_STATUS >>>>> +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_GET_COUNT)( >>>>> + OUT UINT32 *Count >>>>> + ); >>>>> + >>>>> +typedef >>>>> +EFI_STATUS >>>>> +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_ENUMERATE)( >>>>> + IN UINT32 BlobIndex, >>>>> + OUT CHAR8 *BlobId >>>>> + ); >>>>> + >>>>> +typedef >>>>> +EFI_STATUS >>>>> +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_OPEN)( >>>>> + IN CHAR8 *BlobId, >>>>> + IN UINT16 Flags, >>>>> + OUT UINT16 *SessionId >>>>> + ); >>>>> + >>>>> +typedef >>>>> +EFI_STATUS >>>>> +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_READ)( >>>>> + IN UINT16 SessionId, >>>>> + IN UINT32 Offset, >>>>> + IN UINT32 RequestedSize, >>>>> + OUT UINT8 *Data >>>>> + ); >>>>> + >>>>> +typedef >>>>> +EFI_STATUS >>>>> +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_WRITE)( >>>>> + IN UINT16 SessionId, >>>>> + IN UINT32 Offset, >>>>> + IN UINT8 *Data, >>>>> + IN UINT32 WriteLength >>>>> + ); >>>>> + >>>>> +typedef >>>>> +EFI_STATUS >>>>> +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_COMMIT)( >>>>> + IN UINT16 SessionId, >>>>> + IN UINT8 CommitDataLength, >>>>> + IN UINT8 *CommitData >>>>> + ); >>>>> + >>>>> +typedef >>>>> +EFI_STATUS >>>>> +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_CLOSE)( >>>>> + IN UINT16 SessionId >>>>> + ); >>>>> + >>>>> +typedef >>>>> +EFI_STATUS >>>>> +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_DELETE)( >>>>> + IN CHAR8 *BlobId >>>>> + ); >>>>> + >>>>> +typedef >>>>> +EFI_STATUS >>>>> +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_STAT)( >>>>> + IN CHAR8 *BlobId, >>>>> + OUT UINT16 *BlobState, >>>>> + OUT UINT32 *Size, >>>>> + OUT UINT8 *MetadataLength, >>>>> + OUT UINT8 *Metadata >>>>> + ); >>>>> + >>>>> +typedef >>>>> +EFI_STATUS >>>>> +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_SESSION_STAT)( >>>>> + IN UINT16 SessionId, >>>>> + OUT UINT16 *BlobState, >>>>> + OUT UINT32 *Size, >>>>> + OUT UINT8 *MetadataLength, >>>>> + OUT UINT8 *Metadata >>>>> + ); >>>>> + >>>>> +typedef >>>>> +EFI_STATUS >>>>> +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_WRITE_META)( >>>>> + IN UINT16 SessionId, >>>>> + IN UINT32 Offset, >>>>> + IN UINT8 *Data, >>>>> + IN UINT32 WriteLength >>>>> + ); >>>>> + >>>>> +// >>>>> +// Structure of IPMI_BLOB_TRANSFER_PROTOCOL >>>>> +// >>>>> +struct _IPMI_BLOB_TRANSFER_PROTOCOL { >>>>> + IPMI_BLOB_TRANSFER_PROTOCOL_GET_COUNT BlobGetCount; >>>>> + IPMI_BLOB_TRANSFER_PROTOCOL_ENUMERATE BlobEnumerate; >>>>> + IPMI_BLOB_TRANSFER_PROTOCOL_OPEN BlobOpen; >>>>> + IPMI_BLOB_TRANSFER_PROTOCOL_READ BlobRead; >>>>> + IPMI_BLOB_TRANSFER_PROTOCOL_WRITE BlobWrite; >>>>> + IPMI_BLOB_TRANSFER_PROTOCOL_COMMIT BlobCommit; >>>>> + IPMI_BLOB_TRANSFER_PROTOCOL_CLOSE BlobClose; >>>>> + IPMI_BLOB_TRANSFER_PROTOCOL_DELETE BlobDelete; >>>>> + IPMI_BLOB_TRANSFER_PROTOCOL_STAT BlobStat; >>>>> + IPMI_BLOB_TRANSFER_PROTOCOL_SESSION_STAT BlobSessionStat; >>>>> + IPMI_BLOB_TRANSFER_PROTOCOL_WRITE_META BlobWriteMeta; >>>>> +}; >>>>> + >>>>> +typedef struct _IPMI_BLOB_TRANSFER_PROTOCOL >>>> IPMI_BLOB_TRANSFER_PROTOCOL; >>>>> + >>>>> +extern EFI_GUID gEdkiiIpmiBlobTransferProtocolGuid; >>>>> diff --git >> a/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/InternalIpmiB >>>> lobTransfer.h >>>> >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/InternalIpmiB >>>> lobTransfer.h >>>>> new file mode 100644 >>>>> index 0000000000..14f0dc02bc >>>>> --- /dev/null >>>>> +++ >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/InternalIpmiB >>>> lobTransfer.h >>>>> @@ -0,0 +1,363 @@ >>>>> +/** @file >>>>> + >>>>> + Headers for IPMI Blob Transfer driver >>>>> + >>>>> + Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All >> rights >>>> reserved. >>>>> + >>>>> + SPDX-License-Identifier: BSD-2-Clause-Patent >>>>> + >>>>> +**/ >>>>> + >>>>> +#include >>>>> +#include >>>>> +#include >>>>> +#include >>>>> +#include >>>>> +#include >>>>> + >>>>> +#define PROTOCOL_RESPONSE_OVERHEAD (4 * sizeof(UINT8)) // 1 >>>> byte completion code + 3 bytes OEN >>>>> + >>>>> +// Subcommands for this protocol >>>>> +typedef enum { >>>>> + IpmiBlobTransferSubcommandGetCount =3D 0, >>>>> + IpmiBlobTransferSubcommandEnumerate, >>>>> + IpmiBlobTransferSubcommandOpen, >>>>> + IpmiBlobTransferSubcommandRead, >>>>> + IpmiBlobTransferSubcommandWrite, >>>>> + IpmiBlobTransferSubcommandCommit, >>>>> + IpmiBlobTransferSubcommandClose, >>>>> + IpmiBlobTransferSubcommandDelete, >>>>> + IpmiBlobTransferSubcommandStat, >>>>> + IpmiBlobTransferSubcommandSessionStat, >>>>> + IpmiBlobTransferSubcommandWriteMeta, >>>>> +} IPMI_BLOB_TRANSFER_SUBCOMMANDS; >>>>> + >>>>> +#pragma pack(1) >>>>> + >>>>> +typedef struct { >>>>> + UINT8 OEN[3]; >>>>> + UINT8 SubCommand; >>>>> +} IPMI_BLOB_TRANSFER_HEADER; >>>>> + >>>>> +// >>>>> +// Command 0 - BmcBlobGetCount >>>>> +// The BmcBlobGetCount command expects to receive an empty body. >>>>> +// The BMC will return the number of enumerable blobs >>>>> +// >>>>> +typedef struct { >>>>> + UINT32 BlobCount; >>>>> +} IPMI_BLOB_TRANSFER_GET_COUNT_RESPONSE; >>>>> + >>>>> +// >>>>> +// Command 1 - BmcBlobEnumerate >>>>> +// The BmcBlobEnumerate command expects to receive a body of: >>>>> +// >>>>> +typedef struct { >>>>> + UINT32 BlobIndex; // 0-based index of blob to receive >>>>> +} IPMI_BLOB_TRANSFER_BLOB_ENUMERATE_SEND_DATA; >>>>> + >>>>> +typedef struct { >>>>> + CHAR8 BlobId[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET]; >>>>> +} IPMI_BLOB_TRANSFER_BLOB_ENUMERATE_RESPONSE; >>>>> + >>>>> +// >>>>> +// Command 2 - BmcBlobOpen >>>>> +// The BmcBlobOpen command expects to receive a body of: >>>>> +// >>>>> +typedef struct { >>>>> + UINT16 Flags; >>>>> + CHAR8 BlobId[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET]; >>>>> +} IPMI_BLOB_TRANSFER_BLOB_OPEN_SEND_DATA; >>>>> + >>>>> +#define BLOB_OPEN_FLAG_READ 0 >>>>> +#define BLOB_OPEN_FLAG_WRITE 1 >>>>> +// Bits 2-7 are reserved >>>>> +// Bits 8-15 are blob-specific definitions >>>>> + >>>>> +typedef struct { >>>>> + UINT16 SessionId; >>>>> +} IPMI_BLOB_TRANSFER_BLOB_OPEN_RESPONSE; >>>>> + >>>>> +// >>>>> +// Command 3 - BmcBlobRead >>>>> +// The BmcBlobRead command expects to receive a body of: >>>>> +// >>>>> +typedef struct { >>>>> + UINT16 SessionId; // Returned from BlobOpen >>>>> + UINT32 Offset; >>>>> + UINT32 RequestedSize; >>>>> +} IPMI_BLOB_TRANSFER_BLOB_READ_SEND_DATA; >>>>> + >>>>> +typedef struct { >>>>> + UINT8 Data[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET]; >>>>> +} IPMI_BLOB_TRANSFER_BLOB_READ_RESPONSE; >>>>> + >>>>> +// >>>>> +// Command 4 - BmcBlobWrite >>>>> +// The BmcBlobWrite command expects to receive a body of: >>>>> +// >>>>> +typedef struct { >>>>> + UINT16 SessionId; // Returned from BlobOpen >>>>> + UINT32 Offset; >>>>> + UINT8 Data[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET]; >>>>> +} IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA; >>>>> + >>>>> +// >>>>> +// Command 5 - BmcBlobCommit >>>>> +// The BmcBlobCommit command expects to receive a body of: >>>>> +// >>>>> +typedef struct { >>>>> + UINT16 SessionId; // Returned from BlobOpen >>>>> + UINT8 CommitDataLength; >>>>> + UINT8 CommitData[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET]; >>>>> +} IPMI_BLOB_TRANSFER_BLOB_COMMIT_SEND_DATA; >>>>> + >>>>> +// >>>>> +// Command 6 - BmcBlobClose >>>>> +// The BmcBlobClose command expects to receive a body of: >>>>> +// >>>>> +typedef struct { >>>>> + UINT16 SessionId; // Returned from BlobOpen >>>>> +} IPMI_BLOB_TRANSFER_BLOB_CLOSE_SEND_DATA; >>>>> + >>>>> +// >>>>> +// Command 7 - BmcBlobDelete >>>>> +// NOTE: This command will fail if there are open sessions for this = blob >>>>> +// The BmcBlobDelete command expects to receive a body of: >>>>> +// >>>>> +typedef struct { >>>>> + CHAR8 BlobId[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET]; >>>>> +} IPMI_BLOB_TRANSFER_BLOB_DELETE_SEND_DATA; >>>>> + >>>>> +// >>>>> +// Command 8 - BmcBlobStat >>>>> +// This command returns statistics about a blob. >>>>> +// This command expects to receive a body of: >>>>> +// >>>>> +typedef struct { >>>>> + CHAR8 BlobId[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET]; >>>>> +} IPMI_BLOB_TRANSFER_BLOB_STAT_SEND_DATA; >>>>> + >>>>> +typedef struct { >>>>> + UINT16 BlobState; >>>>> + UINT32 Size; // Size in bytes of the blob >>>>> + UINT8 MetaDataLen; >>>>> + UINT8 MetaData[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET]; >>>>> +} IPMI_BLOB_TRANSFER_BLOB_STAT_RESPONSE; >>>>> + >>>>> +// >>>>> +// Command 9 - BmcBlobSessionStat >>>>> +// Returns same data as BmcBlobState expect for a session, not a blo= b >>>>> +// This command expects to receive a body of: >>>>> +// >>>>> +typedef struct { >>>>> + UINT16 SessionId; >>>>> +} IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_SEND_DATA; >>>>> + >>>>> +typedef struct { >>>>> + UINT16 BlobState; >>>>> + UINT32 Size; // Size in bytes of the blob >>>>> + UINT8 MetaDataLen; >>>>> + UINT8 MetaData[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET]; >>>>> +} IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_RESPONSE; >>>>> + >>>>> +// >>>>> +// Command 10 - BmcBlobWriteMeta >>>>> +// The BmcBlobWriteMeta command expects to receive a body of: >>>>> +// >>>>> +typedef struct { >>>>> + UINT16 SessionId; >>>>> + UINT32 Offset; >>>>> + UINT8 Data[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET]; >>>>> +} IPMI_BLOB_TRANSFER_BLOB_WRITE_META_SEND_DATA; >>>>> + >>>>> +#define IPMI_BLOB_TRANSFER_BLOB_WRITE_META_RESPONSE NULL >>>>> + >>>>> +#pragma pack() >>>>> + >>>>> +/** >>>>> + Calculate CRC-16-CCITT with poly of 0x1021 >>>>> + >>>>> + @param[in] Data The target data. >>>>> + @param[in] DataSize The target data size. >>>>> + >>>>> + @return UINT16 The CRC16 value. >>>>> + >>>>> +**/ >>>>> +UINT16 >>>>> +CalculateCrc16 ( >>>>> + IN UINT8 *Data, >>>>> + IN UINTN DataSize >>>>> + ); >>>>> + >>>>> +EFI_STATUS >>>>> +IpmiBlobTransferSendIpmi ( >>>>> + IN UINT8 SubCommand, >>>>> + IN UINT8 *SendData, >>>>> + IN UINT32 SendDataSize, >>>>> + OUT UINT8 *ResponseData, >>>>> + OUT UINT32 *ResponseDataSize >>>>> + ); >>>>> + >>>>> +/** >>>>> + @param[out] Count The number of active blobs >>>>> + >>>>> + @retval EFI_SUCCESS Successfully retrieved the number o= f >> active >>>> blobs. >>>>> + @retval Other An error occurred >>>>> +**/ >>>>> +EFI_STATUS >>>>> +IpmiBlobTransferGetCount ( >>>>> + OUT UINT32 *Count >>>>> + ); >>>>> + >>>>> +/** >>>>> + @param[in] BlobIndex The 0-based Index of the blob t= o >>>> enumerate >>>>> + @param[out] BlobId The ID of the blob >>>>> + >>>>> + @retval EFI_SUCCESS Successfully enumerated the blo= b. >>>>> + @retval Other An error occurred >>>>> +**/ >>>>> +EFI_STATUS >>>>> +IpmiBlobTransferEnumerate ( >>>>> + IN UINT32 BlobIndex, >>>>> + OUT CHAR8 *BlobId >>>>> + ); >>>>> + >>>>> +/** >>>>> + @param[in] BlobId The ID of the blob to open >>>>> + @param[in] Flags Flags to control how the blob i= s opened >>>>> + @param[out] SessionId A unique session identifier >>>>> + >>>>> + @retval EFI_SUCCESS Successfully opened the blob. >>>>> + @retval Other An error occurred >>>>> +**/ >>>>> +EFI_STATUS >>>>> +IpmiBlobTransferOpen ( >>>>> + IN CHAR8 *BlobId, >>>>> + IN UINT16 Flags, >>>>> + OUT UINT16 *SessionId >>>>> + ); >>>>> + >>>>> +/** >>>>> + @param[in] SessionId The session ID returned from a = call to >>>> BlobOpen >>>>> + @param[in] Offset The offset of the blob from whi= ch to start >>>> reading >>>>> + @param[in] RequestedSize The length of data to read >>>>> + @param[out] Data Data read from the blob >>>>> + >>>>> + @retval EFI_SUCCESS Successfully read from the blob= . >>>>> + @retval Other An error occurred >>>>> +**/ >>>>> +EFI_STATUS >>>>> +IpmiBlobTransferRead ( >>>>> + IN UINT16 SessionId, >>>>> + IN UINT32 Offset, >>>>> + IN UINT32 RequestedSize, >>>>> + OUT UINT8 *Data >>>>> + ); >>>>> + >>>>> +/** >>>>> + @param[in] SessionId The session ID returned from a = call to >>>> BlobOpen >>>>> + @param[in] Offset The offset of the blob from whi= ch to start >>>> writing >>>>> + @param[in] Data A pointer to the data to write >>>>> + >>>>> + @retval EFI_SUCCESS Successfully wrote to the blob. >>>>> + @retval Other An error occurred >>>>> +**/ >>>>> +EFI_STATUS >>>>> +IpmiBlobTransferWrite ( >>>>> + IN UINT16 SessionId, >>>>> + IN UINT32 Offset, >>>>> + IN UINT8 *Data, >>>>> + IN UINT32 WriteLength >>>>> + ); >>>>> + >>>>> +/** >>>>> + @param[in] SessionId The session ID returned from a= call to >>>> BlobOpen >>>>> + @param[in] CommitDataLength The length of data to commit t= o >> the >>>> blob >>>>> + @param[in] CommitData A pointer to the data to commi= t >>>>> + >>>>> + @retval EFI_SUCCESS Successful commit to the blob. >>>>> + @retval Other An error occurred >>>>> +**/ >>>>> +EFI_STATUS >>>>> +IpmiBlobTransferCommit ( >>>>> + IN UINT16 SessionId, >>>>> + IN UINT8 CommitDataLength, >>>>> + IN UINT8 *CommitData >>>>> + ); >>>>> + >>>>> +/** >>>>> + @param[in] SessionId The session ID returned from a = call to >>>> BlobOpen >>>>> + >>>>> + @retval EFI_SUCCESS The blob was closed. >>>>> + @retval Other An error occurred >>>>> +**/ >>>>> +EFI_STATUS >>>>> +IpmiBlobTransferClose ( >>>>> + IN UINT16 SessionId >>>>> + ); >>>>> + >>>>> +/** >>>>> + @param[in] BlobId The BlobId to be deleted >>>>> + >>>>> + @retval EFI_SUCCESS The blob was deleted. >>>>> + @retval Other An error occurred >>>>> +**/ >>>>> +EFI_STATUS >>>>> +IpmiBlobTransferDelete ( >>>>> + IN CHAR8 *BlobId >>>>> + ); >>>>> + >>>>> +/** >>>>> + @param[in] BlobId The Blob ID to gather statistic= s for >>>>> + @param[out] BlobState The current state of the blob >>>>> + @param[out] Size Size in bytes of the blob >>>>> + @param[out] MetadataLength Length of the optional metadata >>>>> + @param[out] Metadata Optional blob-specific metadata >>>>> + >>>>> + @retval EFI_SUCCESS The blob statistics were succes= sfully >>>> gathered. >>>>> + @retval Other An error occurred >>>>> +**/ >>>>> +EFI_STATUS >>>>> +IpmiBlobTransferStat ( >>>>> + IN CHAR8 *BlobId, >>>>> + OUT UINT16 *BlobState, >>>>> + OUT UINT32 *Size, >>>>> + OUT UINT8 *MetadataLength, >>>>> + OUT UINT8 *Metadata >>>>> + ); >>>>> + >>>>> +/** >>>>> + @param[in] SessionId The ID of the session to gather= statistics >> for >>>>> + @param[out] BlobState The current state of the blob >>>>> + @param[out] Size Size in bytes of the blob >>>>> + @param[out] MetadataLength Length of the optional metadata >>>>> + @param[out] Metadata Optional blob-specific metadata >>>>> + >>>>> + @retval EFI_SUCCESS The blob statistics were succes= sfully >>>> gathered. >>>>> + @retval Other An error occurred >>>>> +**/ >>>>> +EFI_STATUS >>>>> +IpmiBlobTransferSessionStat ( >>>>> + IN UINT16 SessionId, >>>>> + OUT UINT16 *BlobState, >>>>> + OUT UINT32 *Size, >>>>> + OUT UINT8 *MetadataLength, >>>>> + OUT UINT8 *Metadata >>>>> + ); >>>>> + >>>>> +/** >>>>> + @param[in] SessionId The ID of the session to write = metadata >> for >>>>> + @param[in] Offset The offset of the metadata to w= rite to >>>>> + @param[in] Data The data to write to the metada= ta >>>>> + >>>>> + @retval EFI_SUCCESS The blob metadata was successfu= lly >> written. >>>>> + @retval Other An error occurred >>>>> +**/ >>>>> +EFI_STATUS >>>>> +IpmiBlobTransferWriteMeta ( >>>>> + IN UINT16 SessionId, >>>>> + IN UINT32 Offset, >>>>> + IN UINT8 *Data, >>>>> + IN UINT32 WriteLength >>>>> + ); >>>>> diff --git >> a/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/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 }; // Open= BMC >> OEN >>>> code in little endian format >>>> >>>> I don=E2=80=99t know what =E2=80=9COen=E2=80=9D means. Should it be = =E2=80=9COem=E2=80=9D or =E2=80=9CIANA=E2=80=9D number? >>> This is the OEM number defined by openbmc phosphor blob transfer >> interface for openbmc. >>> https://github.com/openbmc/phosphor-ipmi-blobs#phosphor-blob- >> transfer-interface >> so it is a short form of "OEM number", that is my mistake for not >> reading the document carefully, thank you >>>> And this number can be configured, other OEMs will have their own >> number. >>> Openbmc is already the OEM that uses this OEN number (49871). I conside= r >> this is a industry standard for openbmc IPMI BLOB transfer and it is >> unnecessary to be override by others, right? Any use case you can think = of to >> make this value configurable? >> >> The first thing that comes to my mind is that it is a part of a message. >> It will have some meaning that helps BMC to know what exactly it needs >> to do. >> >> If OEN is always fixed, why do we need it as a part of the message? > That is defined in IPMI spec for OEM/Group req and response, the first th= ree bytes is the OEM or non-IPMI group that specifies the functionality. Th= e following bytes are defined by the openbmc IPMI commands, such as gpio, I= 2C, blob transfer and etc. oh, I got it. Thanks, -Tinh > > Thanks > Abner > >> Hmm as you suggested, it is good to use it as an industry standard for >> OpenBMC. Let's use fixed number (49871) >> >> If they support more OEN numbers, we will support later >> >>> Thanks >>> Abner >>> >>>> This number should be provided by drivers that consume this protocol >>>> >>>>> + >>>>> +/** >>>>> + Calculate CRC-16-CCITT with poly of 0x1021 >>>>> + >>>>> + @param[in] Data The target data. >>>>> + @param[in] DataSize The target data size. >>>>> + >>>>> + @return UINT16 The CRC16 value. >>>>> + >>>>> +**/ >>>>> +UINT16 >>>>> +CalculateCrc16 ( >>>>> + IN UINT8 *Data, >>>>> + IN UINTN DataSize >>>>> + ) >>>>> +{ >>>>> + UINTN Index; >>>>> + UINTN BitIndex; >>>>> + UINT16 Crc =3D 0xFFFF; >>>>> + UINT16 Poly =3D 0x1021; >>>>> + BOOLEAN XorFlag =3D FALSE; >>>>> + >>>>> + for (Index =3D 0; Index < (DataSize + 2); ++Index) { >>>>> + for (BitIndex =3D 0; BitIndex < 8; ++BitIndex) { >>>>> + XorFlag =3D (Crc & 0x8000) ? TRUE : FALSE; >>>>> + Crc <<=3D 1; >>>>> + if ((Index < DataSize) && (Data[Index] & (1 << (7 - BitIndex))= )) { >>>>> + Crc++; >>>>> + } >>>>> + >>>>> + if (XorFlag =3D=3D TRUE) { >>>>> + Crc ^=3D Poly; >>>>> + } >>>>> + } >>>>> + } >>>>> + >>>>> + #if BLOB_TRANSFER_DEBUG >>>>> + DEBUG ((DEBUG_INFO, "%a: CRC-16-CCITT %x\n", __FUNCTION__, >> Crc)); >>>>> + #endif >>>>> + >>>>> + return Crc; >>>>> +} >>>>> + >>>>> +EFI_STATUS >>>>> +IpmiBlobTransferSendIpmi ( >>>>> + IN UINT8 SubCommand, >>>>> + IN UINT8 *SendData, >>>>> + IN UINT32 SendDataSize, >>>>> + OUT UINT8 *ResponseData, >>>>> + OUT UINT32 *ResponseDataSize >>>>> + ) >>>>> +{ >>>>> + EFI_STATUS Status; >>>>> + UINT8 CompletionCode; >>>>> + UINT16 Crc; >>>>> + UINT8 Oen[3]; >>>>> + UINT8 *IpmiSendData; >>>>> + UINT32 IpmiSendDataSize; >>>>> + UINT8 *IpmiResponseData; >>>>> + UINT8 *ModifiedResponseData; >>>>> + UINT32 IpmiResponseDataSize; >>>>> + IPMI_BLOB_TRANSFER_HEADER Header; >>>>> + >>>>> + Crc =3D 0; >>>>> + >>>>> + // >>>>> + // Prepend the proper header to the SendData >>>>> + // >>>>> + IpmiSendDataSize =3D (sizeof (IPMI_BLOB_TRANSFER_HEADER)); >>>>> + if (SendDataSize) { >>>>> + IpmiSendDataSize +=3D sizeof (Crc) + (sizeof (UINT8) * SendDataS= ize); >>>>> + } >>>>> + >>>>> + IpmiSendData =3D AllocateZeroPool (IpmiSendDataSize); >>>>> + if (IpmiSendData =3D=3D NULL) { >>>>> + return EFI_OUT_OF_RESOURCES; >>>>> + } >>>>> + >>>>> + Header.OEN[0] =3D OpenBmcOen[0]; >>>>> + Header.OEN[1] =3D OpenBmcOen[1]; >>>>> + Header.OEN[2] =3D OpenBmcOen[2]; >>>>> + Header.SubCommand =3D SubCommand; >>>>> + CopyMem (IpmiSendData, &Header, sizeof >>>> (IPMI_BLOB_TRANSFER_HEADER)); >>>>> + if (SendDataSize) { >>>>> + // >>>>> + // Calculate the Crc of the send data >>>>> + // >>>>> + Crc =3D CalculateCrc16 (SendData, SendDataSize); >>>>> + CopyMem (IpmiSendData + sizeof (IPMI_BLOB_TRANSFER_HEADER), >>>> &Crc, sizeof (UINT16)); >>>>> + CopyMem (IpmiSendData + sizeof (IPMI_BLOB_TRANSFER_HEADER) >> + >>>> sizeof (UINT16), SendData, SendDataSize); >>>>> + } >>>>> + >>>>> + #if BLOB_TRANSFER_DEBUG >>>>> + DEBUG ((DEBUG_INFO, "%a: Inputs:\n", __FUNCTION__)); >>>>> + DEBUG ((DEBUG_INFO, "%a: SendDataSize: %02x\nData: ", >>>> __FUNCTION__, SendDataSize)); >>>>> + UINT8 i; >>>>> + for (i =3D 0; i < SendDataSize; i++) { >>>>> + DEBUG ((DEBUG_INFO, "%02x", *((UINT8 *)SendData + i))); >>>>> + } >>>>> + >>>>> + DEBUG ((DEBUG_INFO, "\n")); >>>>> + DEBUG ((DEBUG_INFO, "%a: IpmiSendDataSize: %02x\nData: ", >>>> __FUNCTION__, IpmiSendDataSize)); >>>>> + for (i =3D 0; i < IpmiSendDataSize; i++) { >>>>> + DEBUG ((DEBUG_INFO, "%02x", *((UINT8 *)IpmiSendData + i))); >>>>> + } >>>>> + >>>>> + DEBUG ((DEBUG_INFO, "\n")); >>>>> + #endif >>>>> + >>>>> + IpmiResponseDataSize =3D (*ResponseDataSize + >>>> PROTOCOL_RESPONSE_OVERHEAD); >>>>> + // >>>>> + // If expecting data to be returned, we have to also account for t= he 16 >> bit >>>> CRC >>>>> + // >>>>> + if (*ResponseDataSize) { >>>>> + IpmiResponseDataSize +=3D sizeof (Crc); >>>>> + } >>>>> + >>>>> + IpmiResponseData =3D AllocateZeroPool (IpmiResponseDataSize); >>>>> + if (IpmiResponseData =3D=3D NULL) { >>>>> + return EFI_OUT_OF_RESOURCES; >>>>> + } >>>>> + >>>>> + Status =3D IpmiSubmitCommand ( >>>>> + IPMI_NETFN_OEM, >>>>> + IPMI_OEM_BLOB_TRANSFER_CMD, >>>>> + (VOID *)IpmiSendData, >>>>> + IpmiSendDataSize, >>>>> + (VOID *)IpmiResponseData, >>>>> + &IpmiResponseDataSize >>>>> + ); >>>>> + >>>>> + FreePool (IpmiSendData); >>>>> + ModifiedResponseData =3D IpmiResponseData; >>>>> + >>>>> + #if BLOB_TRANSFER_DEBUG >>>>> + DEBUG ((DEBUG_INFO, "%a: IPMI Response:\n", __FUNCTION__)); >>>>> + DEBUG ((DEBUG_INFO, "%a: ResponseDataSize: %02x\nData: ", >>>> __FUNCTION__, IpmiResponseDataSize)); >>>>> + for (i =3D 0; i < IpmiResponseDataSize; i++) { >>>>> + DEBUG ((DEBUG_INFO, "%02x", *(ModifiedResponseData + i))); >>>>> + } >>>>> + >>>>> + DEBUG ((DEBUG_INFO, "\n")); >>>>> + #endif >>>>> + >>>>> + if (EFI_ERROR (Status)) { >>>>> + return Status; >>>>> + } >>>>> + >>>>> + CompletionCode =3D *ModifiedResponseData; >>>>> + if (CompletionCode !=3D IPMI_COMP_CODE_NORMAL) { >>>>> + DEBUG ((DEBUG_ERROR, "%a: Returning because CompletionCode =3D >>>> 0x%x\n", __FUNCTION__, CompletionCode)); >>>>> + FreePool (IpmiResponseData); >>>>> + return EFI_PROTOCOL_ERROR; >>>>> + } >>>>> + >>>>> + // Strip completion code, we are done with it >>>>> + ModifiedResponseData =3D ModifiedResponseData + sizeof >>>> (CompletionCode); >>>>> + IpmiResponseDataSize -=3D sizeof (CompletionCode); >>>>> + >>>>> + // Check OEN code and verify it matches the OpenBMC OEN >>>>> + CopyMem (Oen, ModifiedResponseData, sizeof (OpenBmcOen)); >>>>> + if (CompareMem (Oen, OpenBmcOen, sizeof (OpenBmcOen)) !=3D 0) { >>>>> + FreePool (IpmiResponseData); >>>>> + return EFI_PROTOCOL_ERROR; >>>>> + } >>>>> + >>>>> + if (IpmiResponseDataSize =3D=3D sizeof (OpenBmcOen)) { >>>>> + // >>>>> + // In this case, there was no response data sent. This is not an= error. >>>>> + // Some messages do not require a response. >>>>> + // >>>>> + *ResponseDataSize =3D 0; >>>>> + FreePool (IpmiResponseData); >>>>> + return Status; >>>>> + // Now we need to validate the CRC then send the Response body >> 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, >>>> IpmiResponseDataSize)) { >>>>> + CopyMem (ResponseData, ModifiedResponseData, >>>> IpmiResponseDataSize); >>>>> + CopyMem (ResponseDataSize, &IpmiResponseDataSize, sizeof >>>> (IpmiResponseDataSize)); >>>>> + FreePool (IpmiResponseData); >>>>> + return EFI_SUCCESS; >>>>> + } else { >>>>> + FreePool (IpmiResponseData); >>>>> + return EFI_CRC_ERROR; >>>>> + } >>>>> + } >>>>> +} >>>>> + >>>>> +/** >>>>> + @param[out] Count The number of active blobs >>>>> + >>>>> + @retval EFI_SUCCESS The command byte stream was >> successfully >>>> submit to the device and a response was successfully received. >>>>> + @retval EFI_PROTOCOL_ERROR The Ipmi command failed >>>>> + @retval EFI_CRC_ERROR The Ipmi command returned a bad >>>> checksum >>>>> +**/ >>>>> +EFI_STATUS >>>>> +IpmiBlobTransferGetCount ( >>>>> + OUT UINT32 *Count >>>>> + ) >>>>> +{ >>>> Please add the argument validation for functions which expose for othe= r >>>> drivers >>>> >>>> >>>>> + EFI_STATUS Status; >>>>> + UINT8 *ResponseData; >>>>> + UINT32 ResponseDataSize; >>>>> + >>>>> + ResponseDataSize =3D sizeof >>>> (IPMI_BLOB_TRANSFER_GET_COUNT_RESPONSE); >>>>> + ResponseData =3D AllocateZeroPool (ResponseDataSize); >>>>> + if (ResponseData =3D=3D NULL) { >>>>> + return EFI_OUT_OF_RESOURCES; >>>>> + } >>>>> + >>>>> + Status =3D IpmiBlobTransferSendIpmi >>>> (IpmiBlobTransferSubcommandGetCount, NULL, 0, (UINT8 >> *)ResponseData, >>>> &ResponseDataSize); >>>>> + if (!EFI_ERROR (Status)) { >>>>> + *Count =3D ((IPMI_BLOB_TRANSFER_GET_COUNT_RESPONSE >>>> *)ResponseData)->BlobCount; >>>>> + } >>>>> + >>>>> + FreePool (ResponseData); >>>>> + return Status; >>>>> +} >>>>> + >>>>> +/** >>>>> + @param[in] BlobIndex The 0-based Index of the blob t= o >>>> enumerate >>>>> + @param[out] BlobId The ID of the blob >>>>> + >>>>> + @retval EFI_SUCCESS Successfully enumerated the blo= b. >>>>> + @retval Other An error occurred >>>>> +**/ >>>>> +EFI_STATUS >>>>> +IpmiBlobTransferEnumerate ( >>>>> + IN UINT32 BlobIndex, >>>>> + OUT CHAR8 *BlobId >>>>> + ) >>>>> +{ >>>>> + EFI_STATUS Status; >>>>> + >>>>> + UINT8 *SendData; >>>>> + UINT8 *ResponseData; >>>>> + UINT32 SendDataSize; >>>>> + UINT32 ResponseDataSize; >>>>> + >>>>> + if (BlobId =3D=3D NULL) { >>>>> + ASSERT (FALSE); >>>>> + return EFI_ABORTED; >>>>> + } >>>>> + >>>>> + ResponseDataSize =3D sizeof >>>> (IPMI_BLOB_TRANSFER_BLOB_ENUMERATE_RESPONSE); >>>>> + ResponseData =3D AllocateZeroPool (ResponseDataSize); >>>>> + if (ResponseData =3D=3D NULL) { >>>>> + return EFI_OUT_OF_RESOURCES; >>>>> + } >>>>> + >>>>> + // >>>>> + // Format send data >>>>> + // >>>>> + SendDataSize =3D sizeof >>>> (IPMI_BLOB_TRANSFER_BLOB_ENUMERATE_SEND_DATA); >>>>> + SendData =3D AllocateZeroPool (SendDataSize); >>>>> + if (SendData =3D=3D NULL) { >>>>> + return EFI_OUT_OF_RESOURCES; >>>>> + } >>>>> + >>>>> + ((IPMI_BLOB_TRANSFER_BLOB_ENUMERATE_SEND_DATA >> *)SendData)- >>>>> BlobIndex =3D BlobIndex; >>>>> + >>>>> + Status =3D IpmiBlobTransferSendIpmi >>>> (IpmiBlobTransferSubcommandEnumerate, SendData, SendDataSize, >> (UINT8 >>>> *)ResponseData, &ResponseDataSize); >>>>> + if (!EFI_ERROR (Status)) { >>>>> + AsciiStrCpyS (BlobId, ResponseDataSize, (CHAR8 *)ResponseData); >>>>> + } >>>>> + >>>>> + FreePool (ResponseData); >>>>> + return Status; >>>>> +} >>>>> + >>>>> +/** >>>>> + @param[in] BlobId The ID of the blob to open >>>>> + @param[in] Flags Flags to control how the blob i= s opened >>>>> + @param[out] SessionId A unique session identifier >>>>> + >>>>> + @retval EFI_SUCCESS Successfully opened the blob. >>>>> + @retval Other An error occurred >>>>> +**/ >>>>> +EFI_STATUS >>>>> +IpmiBlobTransferOpen ( >>>>> + IN CHAR8 *BlobId, >>>>> + IN UINT16 Flags, >>>>> + OUT UINT16 *SessionId >>>>> + ) >>>>> +{ >>>>> + EFI_STATUS Status; >>>>> + UINT8 *SendData; >>>>> + UINT8 *ResponseData; >>>>> + UINT32 SendDataSize; >>>>> + UINT32 ResponseDataSize; >>>>> + CHAR8 *BlobSearch; >>>>> + UINT32 NumBlobs; >>>>> + UINT16 Index; >>>>> + BOOLEAN BlobFound; >>>>> + >>>>> + // >>>>> + // Before opening a blob, need to check if it exists >>>>> + // >>>>> + Status =3D IpmiBlobTransferGetCount (&NumBlobs); >>>> I think it should be removed as that will duplicate work >>>> >>>> The drivers using IPMI blob protocol will "get count" themselves. >>>> >>>>> + if (EFI_ERROR (Status) || (NumBlobs =3D=3D 0)) { >>>>> + if (Status =3D=3D EFI_UNSUPPORTED) { >>>>> + return Status; >>>>> + } >>>>> + >>>>> + DEBUG ((DEBUG_ERROR, "%a: Could not find any blobs: %r\n", >>>> __FUNCTION__, Status)); >>>>> + return EFI_NOT_FOUND; >>>>> + } >>>>> + >>>>> + BlobSearch =3D AllocateZeroPool (sizeof (CHAR8) * >>>> IPMI_OEM_BLOB_MAX_DATA_PER_PACKET); >>>>> + if (BlobSearch =3D=3D NULL) { >>>>> + return EFI_OUT_OF_RESOURCES; >>>>> + } >>>>> + >>>>> + BlobFound =3D FALSE; >>>>> + for (Index =3D 0; Index < NumBlobs; Index++) { >>>>> + Status =3D IpmiBlobTransferEnumerate (Index, BlobSearch); >>>> the same here >>>>> + if ((!EFI_ERROR (Status)) && (AsciiStrCmp (BlobSearch, BlobId) = =3D=3D 0)) >> { >>>>> + BlobFound =3D TRUE; >>>>> + break; >>>>> + } else { >>>>> + continue; >>>>> + } >>>>> + } >>>>> + >>>>> + if (!BlobFound) { >>>>> + DEBUG ((DEBUG_ERROR, "%a: Could not find a blob that matches >> %s\n", >>>> __FUNCTION__, BlobId)); >>>>> + FreePool (BlobSearch); >>>>> + return EFI_NOT_FOUND; >>>>> + } >>>>> + >>>>> + ResponseDataSize =3D sizeof >>>> (IPMI_BLOB_TRANSFER_BLOB_OPEN_RESPONSE); >>>>> + ResponseData =3D AllocateZeroPool (ResponseDataSize); >>>>> + if (ResponseData =3D=3D NULL) { >>>>> + return EFI_OUT_OF_RESOURCES; >>>>> + } >>>>> + >>>>> + // >>>>> + // Format send data >>>>> + // >>>>> + SendDataSize =3D sizeof >>>> (((IPMI_BLOB_TRANSFER_BLOB_OPEN_SEND_DATA *)SendData)->Flags) >> + >>>> ((AsciiStrLen (BlobId)) * sizeof (CHAR8)) + sizeof (CHAR8); >>>>> + SendData =3D AllocateZeroPool (SendDataSize); >>>>> + if (SendData =3D=3D NULL) { >>>>> + return EFI_OUT_OF_RESOURCES; >>>>> + } >>>>> + >>>>> + AsciiStrCpyS (((IPMI_BLOB_TRANSFER_BLOB_OPEN_SEND_DATA >>>> *)SendData)->BlobId, AsciiStrSize (BlobId) / sizeof (CHAR8), BlobId); >>>>> + ((IPMI_BLOB_TRANSFER_BLOB_OPEN_SEND_DATA *)SendData)- >>> Flags >>>> =3D Flags; >>>>> + // append null char to SendData >>>>> + SendData[SendDataSize-1] =3D 0; >>>>> + >>>>> + Status =3D IpmiBlobTransferSendIpmi >>>> (IpmiBlobTransferSubcommandOpen, SendData, SendDataSize, (UINT8 >>>> *)ResponseData, &ResponseDataSize); >>>>> + if (!EFI_ERROR (Status)) { >>>>> + *SessionId =3D ((IPMI_BLOB_TRANSFER_BLOB_OPEN_RESPONSE >>>> *)ResponseData)->SessionId; >>>>> + } >>>>> + >>>>> + FreePool (ResponseData); >>>>> + FreePool (SendData); >>>>> + FreePool (BlobSearch); >>>>> + return Status; >>>>> +} >>>>> + >>>>> +/** >>>>> + @param[in] SessionId The session ID returned from a = call to >>>> BlobOpen >>>>> + @param[in] Offset The offset of the blob from whi= ch to start >>>> reading >>>>> + @param[in] RequestedSize The length of data to read >>>>> + @param[out] Data Data read from the blob >>>>> + >>>>> + @retval EFI_SUCCESS Successfully read from the blob= . >>>>> + @retval Other An error occurred >>>>> +**/ >>>>> +EFI_STATUS >>>>> +IpmiBlobTransferRead ( >>>>> + IN UINT16 SessionId, >>>>> + IN UINT32 Offset, >>>>> + IN UINT32 RequestedSize, >>>>> + OUT UINT8 *Data >>>>> + ) >>>>> +{ >>>>> + EFI_STATUS Status; >>>>> + UINT8 *SendData; >>>>> + UINT8 *ResponseData; >>>>> + UINT32 SendDataSize; >>>>> + UINT32 ResponseDataSize; >>>>> + >>>>> + if (Data =3D=3D NULL) { >>>>> + ASSERT (FALSE); >>>>> + return EFI_ABORTED; >>>>> + } >>>>> + >>>>> + ResponseDataSize =3D RequestedSize * sizeof (UINT8); >>>>> + ResponseData =3D AllocateZeroPool (ResponseDataSize); >>>>> + if (ResponseData =3D=3D NULL) { >>>>> + return EFI_OUT_OF_RESOURCES; >>>>> + } >>>>> + >>>>> + // >>>>> + // Format send data >>>>> + // >>>>> + SendDataSize =3D sizeof >>>> (IPMI_BLOB_TRANSFER_BLOB_READ_SEND_DATA); >>>>> + SendData =3D AllocateZeroPool (SendDataSize); >>>>> + if (SendData =3D=3D NULL) { >>>>> + return EFI_OUT_OF_RESOURCES; >>>>> + } >>>>> + >>>>> + ((IPMI_BLOB_TRANSFER_BLOB_READ_SEND_DATA *)SendData)- >>>>> SessionId =3D SessionId; >>>>> + ((IPMI_BLOB_TRANSFER_BLOB_READ_SEND_DATA *)SendData)- >>>>> Offset =3D Offset; >>>>> + ((IPMI_BLOB_TRANSFER_BLOB_READ_SEND_DATA *)SendData)- >>>>> RequestedSize =3D RequestedSize; >>>>> + >>>>> + Status =3D IpmiBlobTransferSendIpmi >> (IpmiBlobTransferSubcommandRead, >>>> SendData, SendDataSize, (UINT8 *)ResponseData, &ResponseDataSize); >>>>> + if (!EFI_ERROR (Status)) { >>>>> + CopyMem (Data, ((IPMI_BLOB_TRANSFER_BLOB_READ_RESPONSE >>>> *)ResponseData)->Data, ResponseDataSize * sizeof (UINT8)); >>>>> + } >>>>> + >>>>> + FreePool (ResponseData); >>>>> + FreePool (SendData); >>>>> + return Status; >>>>> +} >>>>> + >>>>> +/** >>>>> + @param[in] SessionId The session ID returned from a = call to >>>> BlobOpen >>>>> + @param[in] Offset The offset of the blob from whi= ch to start >>>> writing >>>>> + @param[in] Data A pointer to the data to write >>>>> + >>>>> + @retval EFI_SUCCESS Successfully wrote to the blob. >>>>> + @retval Other An error occurred >>>>> +**/ >>>>> +EFI_STATUS >>>>> +IpmiBlobTransferWrite ( >>>>> + IN UINT16 SessionId, >>>>> + IN UINT32 Offset, >>>>> + IN UINT8 *Data, >>>>> + IN UINT32 WriteLength >>>>> + ) >>>>> +{ >>>>> + EFI_STATUS Status; >>>>> + UINT8 *SendData; >>>>> + UINT32 SendDataSize; >>>>> + UINT32 ResponseDataSize; >>>>> + >>>>> + // >>>>> + // Format send data >>>>> + // >>>>> + SendDataSize =3D sizeof (SessionId) + sizeof (Offset) + WriteLengt= h; >>>>> + SendData =3D AllocateZeroPool (SendDataSize); >>>>> + if (SendData =3D=3D NULL) { >>>>> + return EFI_OUT_OF_RESOURCES; >>>>> + } >>>>> + >>>>> + ((IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA *)SendData)- >>>>> SessionId =3D SessionId; >>>>> + ((IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA *)SendData)- >>>>> Offset =3D Offset; >>>>> + CopyMem (((IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA >>>> *)SendData)->Data, Data, sizeof (UINT8) * WriteLength); >>>>> + >>>>> + ResponseDataSize =3D 0; >>>>> + Status =3D IpmiBlobTransferSendIpmi >>>> (IpmiBlobTransferSubcommandWrite, SendData, SendDataSize, NULL, >>>> &ResponseDataSize); >>>>> + >>>>> + FreePool (SendData); >>>>> + return Status; >>>>> +} >>>>> + >>>>> +/** >>>>> + @param[in] SessionId The session ID returned from a= call to >>>> BlobOpen >>>>> + @param[in] CommitDataLength The length of data to commit t= o >> the >>>> blob >>>>> + @param[in] CommitData A pointer to the data to commi= t >>>>> + >>>>> + @retval EFI_SUCCESS Successful commit to the blob. >>>>> + @retval Other An error occurred >>>>> +**/ >>>>> +EFI_STATUS >>>>> +IpmiBlobTransferCommit ( >>>>> + IN UINT16 SessionId, >>>>> + IN UINT8 CommitDataLength, >>>>> + IN UINT8 *CommitData >>>>> + ) >>>>> +{ >>>>> + EFI_STATUS Status; >>>>> + UINT8 *SendData; >>>>> + UINT32 SendDataSize; >>>>> + UINT32 ResponseDataSize; >>>>> + >>>>> + // >>>>> + // Format send data >>>>> + // >>>>> + SendDataSize =3D sizeof (SessionId) + sizeof (CommitDataLength) + >>>> CommitDataLength; >>>>> + SendData =3D AllocateZeroPool (SendDataSize); >>>>> + if (SendData =3D=3D NULL) { >>>>> + return EFI_OUT_OF_RESOURCES; >>>>> + } >>>>> + >>>>> + ((IPMI_BLOB_TRANSFER_BLOB_COMMIT_SEND_DATA *)SendData)- >>>>> SessionId =3D SessionId; >>>>> + ((IPMI_BLOB_TRANSFER_BLOB_COMMIT_SEND_DATA *)SendData)- >>>>> CommitDataLength =3D CommitDataLength; >>>>> + CopyMem (((IPMI_BLOB_TRANSFER_BLOB_COMMIT_SEND_DATA >>>> *)SendData)->CommitData, CommitData, sizeof (UINT8) * >>>> CommitDataLength); >>>>> + >>>>> + ResponseDataSize =3D 0; >>>>> + >>>>> + Status =3D IpmiBlobTransferSendIpmi >>>> (IpmiBlobTransferSubcommandCommit, SendData, SendDataSize, NULL, >>>> &ResponseDataSize); >>>>> + >>>>> + FreePool (SendData); >>>>> + return Status; >>>>> +} >>>>> + >>>>> +/** >>>>> + @param[in] SessionId The session ID returned from a = call to >>>> BlobOpen >>>>> + >>>>> + @retval EFI_SUCCESS The blob was closed. >>>>> + @retval Other An error occurred >>>>> +**/ >>>>> +EFI_STATUS >>>>> +IpmiBlobTransferClose ( >>>>> + IN UINT16 SessionId >>>>> + ) >>>>> +{ >>>>> + EFI_STATUS Status; >>>>> + UINT8 *SendData; >>>>> + UINT32 SendDataSize; >>>>> + UINT32 ResponseDataSize; >>>>> + >>>>> + // >>>>> + // Format send data >>>>> + // >>>>> + SendDataSize =3D sizeof >>>> (IPMI_BLOB_TRANSFER_BLOB_CLOSE_SEND_DATA); >>>>> + SendData =3D AllocateZeroPool (SendDataSize); >>>>> + if (SendData =3D=3D NULL) { >>>>> + return EFI_OUT_OF_RESOURCES; >>>>> + } >>>>> + >>>>> + ((IPMI_BLOB_TRANSFER_BLOB_CLOSE_SEND_DATA *)SendData)- >>>>> SessionId =3D SessionId; >>>>> + >>>>> + ResponseDataSize =3D 0; >>>>> + >>>>> + Status =3D IpmiBlobTransferSendIpmi >> (IpmiBlobTransferSubcommandClose, >>>> SendData, SendDataSize, NULL, &ResponseDataSize); >>>>> + >>>>> + FreePool (SendData); >>>>> + return Status; >>>>> +} >>>>> + >>>>> +/** >>>>> + @param[in] BlobId The BlobId to be deleted >>>>> + >>>>> + @retval EFI_SUCCESS The blob was deleted. >>>>> + @retval Other An error occurred >>>>> +**/ >>>>> +EFI_STATUS >>>>> +IpmiBlobTransferDelete ( >>>>> + IN CHAR8 *BlobId >>>>> + ) >>>>> +{ >>>>> + EFI_STATUS Status; >>>>> + UINT8 *SendData; >>>>> + UINT32 SendDataSize; >>>>> + UINT32 ResponseDataSize; >>>>> + >>>>> + // >>>>> + // Format send data >>>>> + // >>>>> + SendDataSize =3D sizeof >>>> (IPMI_BLOB_TRANSFER_BLOB_DELETE_SEND_DATA); >>>>> + SendData =3D AllocateZeroPool (SendDataSize); >>>>> + if (SendData =3D=3D NULL) { >>>>> + return EFI_OUT_OF_RESOURCES; >>>>> + } >>>>> + >>>>> + AsciiStrCpyS (((IPMI_BLOB_TRANSFER_BLOB_DELETE_SEND_DATA >>>> *)SendData)->BlobId, AsciiStrLen (BlobId), BlobId); >>>>> + >>>>> + ResponseDataSize =3D 0; >>>>> + >>>>> + Status =3D IpmiBlobTransferSendIpmi >>>> (IpmiBlobTransferSubcommandDelete, SendData, SendDataSize, NULL, >>>> &ResponseDataSize); >>>>> + >>>>> + FreePool (SendData); >>>>> + return Status; >>>>> +} >>>>> + >>>>> +/** >>>>> + @param[in] BlobId The Blob ID to gather statistic= s for >>>>> + @param[out] BlobState The current state of the blob >>>>> + @param[out] Size Size in bytes of the blob >>>>> + @param[out] MetadataLength Length of the optional metadata >>>>> + @param[out] Metadata Optional blob-specific metadata >>>>> + >>>>> + @retval EFI_SUCCESS The blob statistics were succes= sfully >>>> gathered. >>>>> + @retval Other An error occurred >>>>> +**/ >>>>> +EFI_STATUS >>>>> +IpmiBlobTransferStat ( >>>>> + IN CHAR8 *BlobId, >>>>> + OUT UINT16 *BlobState, >>>>> + OUT UINT32 *Size, >>>>> + OUT UINT8 *MetadataLength, >>>>> + OUT UINT8 *Metadata >>>>> + ) >>>>> +{ >>>>> + EFI_STATUS Status; >>>>> + UINT8 *SendData; >>>>> + UINT8 *ResponseData; >>>>> + UINT32 SendDataSize; >>>>> + UINT32 ResponseDataSize; >>>>> + >>>>> + if (Metadata =3D=3D NULL) { >>>>> + ASSERT (FALSE); >>>>> + return EFI_ABORTED; >>>>> + } >>>>> + >>>>> + ResponseDataSize =3D sizeof >>>> (IPMI_BLOB_TRANSFER_BLOB_STAT_RESPONSE); >>>>> + ResponseData =3D AllocateZeroPool (ResponseDataSize); >>>>> + if (ResponseData =3D=3D NULL) { >>>>> + return EFI_OUT_OF_RESOURCES; >>>>> + } >>>>> + >>>>> + // >>>>> + // Format send data >>>>> + // >>>>> + SendDataSize =3D sizeof >>>> (IPMI_BLOB_TRANSFER_BLOB_STAT_SEND_DATA); >>>>> + SendData =3D AllocateZeroPool (SendDataSize); >>>>> + if (SendData =3D=3D NULL) { >>>>> + return EFI_OUT_OF_RESOURCES; >>>>> + } >>>>> + >>>>> + AsciiStrCpyS (((IPMI_BLOB_TRANSFER_BLOB_STAT_SEND_DATA >>>> *)SendData)->BlobId, IPMI_OEM_BLOB_MAX_DATA_PER_PACKET, >> BlobId); >>>>> + >>>>> + Status =3D IpmiBlobTransferSendIpmi >> (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= statistics >> for >>>>> + @param[out] BlobState The current state of the blob >>>>> + @param[out] Size Size in bytes of the blob >>>>> + @param[out] MetadataLength Length of the optional metadata >>>>> + @param[out] Metadata Optional blob-specific metadata >>>>> + >>>>> + @retval EFI_SUCCESS The blob statistics were succes= sfully >>>> gathered. >>>>> + @retval Other An error occurred >>>>> +**/ >>>>> +EFI_STATUS >>>>> +IpmiBlobTransferSessionStat ( >>>>> + IN UINT16 SessionId, >>>>> + OUT UINT16 *BlobState, >>>>> + OUT UINT32 *Size, >>>>> + OUT UINT8 *MetadataLength, >>>>> + OUT UINT8 *Metadata >>>>> + ) >>>>> +{ >>>>> + EFI_STATUS Status; >>>>> + UINT8 *SendData; >>>>> + UINT8 *ResponseData; >>>>> + UINT32 SendDataSize; >>>>> + UINT32 ResponseDataSize; >>>>> + >>>>> + if ((BlobState =3D=3D NULL) || (Size =3D=3D NULL) || (MetadataLeng= th =3D=3D NULL) >>>> || (Metadata =3D=3D NULL)) { >>>>> + ASSERT (FALSE); >>>>> + return EFI_ABORTED; >>>>> + } >>>>> + >>>>> + ResponseDataSize =3D sizeof >>>> (IPMI_BLOB_TRANSFER_BLOB_STAT_RESPONSE); >>>>> + ResponseData =3D AllocateZeroPool (ResponseDataSize); >>>>> + if (ResponseData =3D=3D NULL) { >>>>> + return EFI_OUT_OF_RESOURCES; >>>>> + } >>>>> + >>>>> + // >>>>> + // Format send data >>>>> + // >>>>> + SendDataSize =3D sizeof >>>> (IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_SEND_DATA); >>>>> + SendData =3D AllocateZeroPool (SendDataSize); >>>>> + if (SendData =3D=3D NULL) { >>>>> + return EFI_OUT_OF_RESOURCES; >>>>> + } >>>>> + >>>>> + ((IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_SEND_DATA >>>> *)SendData)->SessionId =3D SessionId; >>>>> + >>>>> + Status =3D IpmiBlobTransferSendIpmi >>>> (IpmiBlobTransferSubcommandSessionStat, SendData, SendDataSize, >> (UINT8 >>>> *)ResponseData, &ResponseDataSize); >>>>> + >>>>> + if (!EFI_ERROR (Status)) { >>>>> + *BlobState =3D >>>> ((IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_RESPONSE >>>> *)ResponseData)->BlobState; >>>>> + *Size =3D >> ((IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_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 = metadata >> for >>>>> + @param[in] Offset The offset of the metadata to w= rite to >>>>> + @param[in] Data The data to write to the metada= ta >>>>> + >>>>> + @retval EFI_SUCCESS The blob metadata was successfu= lly >> written. >>>>> + @retval Other An error occurred >>>>> +**/ >>>>> +EFI_STATUS >>>>> +IpmiBlobTransferWriteMeta ( >>>>> + IN UINT16 SessionId, >>>>> + IN UINT32 Offset, >>>>> + IN UINT8 *Data, >>>>> + IN UINT32 WriteLength >>>>> + ) >>>>> +{ >>>>> + EFI_STATUS Status; >>>>> + UINT8 *SendData; >>>>> + UINT32 SendDataSize; >>>>> + UINT32 ResponseDataSize; >>>>> + >>>>> + // >>>>> + // Format send data >>>>> + // >>>>> + SendDataSize =3D sizeof >>>> (IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA); >>>>> + SendData =3D AllocateZeroPool (SendDataSize); >>>>> + if (SendData =3D=3D NULL) { >>>>> + return EFI_OUT_OF_RESOURCES; >>>>> + } >>>>> + >>>>> + ((IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA *)SendData)- >>>>> SessionId =3D SessionId; >>>>> + ((IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA *)SendData)- >>>>> Offset =3D Offset; >>>>> + CopyMem (((IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA >>>> *)SendData)->Data, Data, sizeof (UINT8) * WriteLength); >>>>> + >>>>> + ResponseDataSize =3D 0; >>>>> + >>>>> + Status =3D IpmiBlobTransferSendIpmi >>>> (IpmiBlobTransferSubcommandWriteMeta, SendData, SendDataSize, >> NULL, >>>> &ResponseDataSize); >>>>> + >>>>> + FreePool (SendData); >>>>> + return Status; >>>>> +} >>>>> + >>>>> +/** >>>>> + This is the declaration of an EFI image entry point. This entry po= int is >>>>> + the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers >>>> including >>>>> + both device drivers and bus drivers. >>>>> + >>>>> + @param[in] ImageHandle The firmware allocated handle for th= e >> UEFI >>>> image. >>>>> + @param[in] SystemTable A pointer to the EFI System Table. >>>>> + >>>>> + @retval EFI_SUCCESS The operation completed successfully= . >>>>> + @retval Others An unexpected error occurred. >>>>> + >>>>> +**/ >>>>> +EFI_STATUS >>>>> +EFIAPI >>>>> +IpmiBlobTransferDxeDriverEntryPoint ( >>>>> + IN EFI_HANDLE ImageHandle, >>>>> + IN EFI_SYSTEM_TABLE *SystemTable >>>>> + ) >>>>> +{ >>>>> + return gBS->InstallMultipleProtocolInterfaces ( >>>>> + &ImageHandle, >>>>> + &gEdkiiIpmiBlobTransferProtocolGuid, >>>>> + (VOID *)&mIpmiBlobTransfer, >>>>> + NULL >>>>> + ); >>>>> +} >>>>> diff --git >> a/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/Ipmi >>>> BlobTransferTestUnitTests.c >>>> >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/Ipm >>>> iBlobTransferTestUnitTests.c >>>>> new file mode 100644 >>>>> index 0000000000..f326467922 >>>>> --- /dev/null >>>>> +++ >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/Ipm >>>> iBlobTransferTestUnitTests.c >>>>> @@ -0,0 +1,1113 @@ >>>>> +/** @file >>>>> +* >>>>> +* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. >>>> 2023 >>>>> +* >>>>> +* SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & >>>> AFFILIATES >>>>> +* SPDX-License-Identifier: BSD-2-Clause-Patent >>>>> +* >>>>> +**/ >>>>> +#include >>>>> +#include >>>>> +#include >>>>> +#include >>>>> +#include >>>>> + >>>>> +#include >>>>> +#include >>>>> +#include >>>>> +#include >>>>> +#include >>>>> + >>>>> +#include >>>>> +#include >>>>> +#include "../InternalIpmiBlobTransfer.h" >>>>> + >>>>> +#define UNIT_TEST_NAME "IPMI Blob Transfer Unit Tests" >>>>> +#define UNIT_TEST_VERSION "1.0" >>>>> + >>>>> +UINT8 InvalidCompletion[] =3D { >>>>> + 0xC0, // CompletionCode >>>>> + 0xCF, 0xC2, 0x00, // OpenBMC OEN >>>>> +}; >>>>> +#define INVALID_COMPLETION_SIZE 4 * sizeof(UINT8) >>>>> + >>>>> +UINT8 NoDataResponse[] =3D { >>>>> + 0x00, // CompletionCode >>>>> + 0xCF, 0xC2, 0x00, // OpenBMC OEN >>>>> +}; >>>>> +#define NO_DATA_RESPONSE_SIZE 4 * sizeof(UINT8) >>>>> + >>>>> +UINT8 BadOenResponse[] =3D { >>>>> + 0x00, // CompletionCode >>>>> + 0xFF, 0xC2, 0x00, // Wrong OEN >>>>> +}; >>>>> +#define BAD_OEN_RESPONSE_SIZE 4 * sizeof(UINT8) >>>>> + >>>>> +UINT8 BadCrcResponse[] =3D { >>>>> + 0x00, // CompletionCode >>>>> + 0xCF, 0xC2, 0x00, // OpenBMC OEN >>>>> + 0x00, 0x00, // CRC >>>>> + 0x01, 0x00, 0x00, 0x00, // Data >>>>> +}; >>>>> +#define BAD_CRC_RESPONSE_SIZE 10 * sizeof(UINT8) >>>>> + >>>>> +UINT8 ValidNoDataResponse[] =3D { >>>>> + 0x00, // CompletionCode >>>>> + 0xCF, 0xC2, 0x00, // OpenBMC OEN >>>>> +}; >>>>> + >>>>> +#define VALID_NODATA_RESPONSE_SIZE 4 * sizeof(UINT8) >>>>> + >>>>> +/** >>>>> + @param[in] Context [Optional] An optional parameter that enabl= es: >>>>> + 1) test-case reuse with varied parameters a= nd >>>>> + 2) test-case re-entry for Target tests that= need a >>>>> + reboot. This parameter is a VOID* and it i= s the >>>>> + responsibility of the test author to ensure= that the >>>>> + contents are well understood by all test ca= ses that may >>>>> + consume it. >>>>> + @retval UNIT_TEST_PASSED The Unit test has completed = and >> the >>>> test >>>>> + case was successful. >>>>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >>>> failed. >>>>> +**/ >>>>> +UNIT_TEST_STATUS >>>>> +EFIAPI >>>>> +GoodCrc ( >>>>> + IN UNIT_TEST_CONTEXT Context >>>>> + ) >>>>> +{ >>>>> + UINT8 Data[5] =3D { 0x12, 0x34, 0x56, 0x78, 0x90 }; >>>>> + UINTN DataSize; >>>>> + UINT16 Crc; >>>>> + >>>>> + DataSize =3D sizeof (Data); >>>>> + >>>>> + Crc =3D CalculateCrc16 (Data, DataSize); >>>>> + >>>>> + UT_ASSERT_EQUAL (Crc, 0xB928); >>>>> + return UNIT_TEST_PASSED; >>>>> +} >>>>> + >>>>> +/** >>>>> + @param[in] Context [Optional] An optional parameter that enabl= es: >>>>> + 1) test-case reuse with varied parameters a= nd >>>>> + 2) test-case re-entry for Target tests that= need a >>>>> + reboot. This parameter is a VOID* and it i= s the >>>>> + responsibility of the test author to ensure= that the >>>>> + contents are well understood by all test ca= ses that may >>>>> + consume it. >>>>> + @retval UNIT_TEST_PASSED The Unit test has completed = and >> the >>>> test >>>>> + case was successful. >>>>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >>>> failed. >>>>> +**/ >>>>> +UNIT_TEST_STATUS >>>>> +EFIAPI >>>>> +BadCrc ( >>>>> + IN UNIT_TEST_CONTEXT Context >>>>> + ) >>>>> +{ >>>>> + UINT8 Data[5] =3D { 0x12, 0x34, 0x56, 0x78, 0x90 }; >>>>> + UINTN DataSize; >>>>> + UINT16 Crc; >>>>> + >>>>> + DataSize =3D sizeof (Data); >>>>> + >>>>> + Crc =3D CalculateCrc16 (Data, DataSize); >>>>> + >>>>> + UT_ASSERT_NOT_EQUAL (Crc, 0x3409); >>>>> + return UNIT_TEST_PASSED; >>>>> +} >>>>> + >>>>> +/** >>>>> + @param[in] Context [Optional] An optional parameter that enabl= es: >>>>> + 1) test-case reuse with varied parameters a= nd >>>>> + 2) test-case re-entry for Target tests that= need a >>>>> + reboot. This parameter is a VOID* and it i= s the >>>>> + responsibility of the test author to ensure= that the >>>>> + contents are well understood by all test ca= ses that may >>>>> + consume it. >>>>> + @retval UNIT_TEST_PASSED The Unit test has completed = and >> the >>>> test >>>>> + case was successful. >>>>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >>>> failed. >>>>> +**/ >>>>> +UNIT_TEST_STATUS >>>>> +EFIAPI >>>>> +SendIpmiBadCompletion ( >>>>> + IN UNIT_TEST_CONTEXT Context >>>>> + ) >>>>> +{ >>>>> + VOID *ResponseData; >>>>> + UINT32 *ResponseDataSize; >>>>> + EFI_STATUS Status; >>>>> + VOID *MockResponseResults =3D NULL; >>>>> + >>>>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool >>>> (INVALID_COMPLETION_SIZE); >>>>> + ResponseDataSize =3D (UINT32 *)AllocateZeroPool (sizeof (UINT32= )); >>>>> + CopyMem (MockResponseResults, &InvalidCompletion, >>>> INVALID_COMPLETION_SIZE); >>>>> + >>>>> + MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >>>> INVALID_COMPLETION_SIZE, EFI_SUCCESS); >>>>> + >>>>> + ResponseData =3D (UINT8 *)AllocateZeroPool (*ResponseDataSize); >>>>> + Status =3D IpmiBlobTransferSendIpmi >>>> (IpmiBlobTransferSubcommandGetCount, NULL, 0, ResponseData, >>>> ResponseDataSize); >>>>> + >>>>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_PROTOCOL_ERROR); >>>>> + FreePool (MockResponseResults); >>>>> + FreePool (ResponseDataSize); >>>>> + FreePool (ResponseData); >>>>> + return UNIT_TEST_PASSED; >>>>> +} >>>>> + >>>>> +/** >>>>> + @param[in] Context [Optional] An optional parameter that enabl= es: >>>>> + 1) test-case reuse with varied parameters a= nd >>>>> + 2) test-case re-entry for Target tests that= need a >>>>> + reboot. This parameter is a VOID* and it i= s the >>>>> + responsibility of the test author to ensure= that the >>>>> + contents are well understood by all test ca= ses that may >>>>> + consume it. >>>>> + @retval UNIT_TEST_PASSED The Unit test has completed = and >> the >>>> test >>>>> + case was successful. >>>>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >>>> failed. >>>>> +**/ >>>>> +UNIT_TEST_STATUS >>>>> +EFIAPI >>>>> +SendIpmiNoDataResponse ( >>>>> + IN UNIT_TEST_CONTEXT Context >>>>> + ) >>>>> +{ >>>>> + VOID *ResponseData; >>>>> + UINT32 *ResponseDataSize; >>>>> + EFI_STATUS Status; >>>>> + VOID *MockResponseResults =3D NULL; >>>>> + >>>>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool >>>> (NO_DATA_RESPONSE_SIZE); >>>>> + ResponseDataSize =3D (UINT32 *)AllocateZeroPool (sizeof (UINT32= )); >>>>> + CopyMem (MockResponseResults, &NoDataResponse, >>>> NO_DATA_RESPONSE_SIZE); >>>>> + >>>>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >>>> NO_DATA_RESPONSE_SIZE, EFI_SUCCESS); >>>>> + if (EFI_ERROR (Status)) { >>>>> + return UNIT_TEST_ERROR_TEST_FAILED; >>>>> + } >>>>> + >>>>> + ResponseData =3D (UINT8 *)AllocateZeroPool (sizeof >> (NoDataResponse)); >>>>> + Status =3D IpmiBlobTransferSendIpmi >>>> (IpmiBlobTransferSubcommandGetCount, NULL, 0, ResponseData, >>>> ResponseDataSize); >>>>> + >>>>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>>>> + UT_ASSERT_EQUAL (*ResponseDataSize, 0); >>>>> + FreePool (MockResponseResults); >>>>> + FreePool (ResponseDataSize); >>>>> + FreePool (ResponseData); >>>>> + return UNIT_TEST_PASSED; >>>>> +} >>>>> + >>>>> +/** >>>>> + @param[in] Context [Optional] An optional parameter that enabl= es: >>>>> + 1) test-case reuse with varied parameters a= nd >>>>> + 2) test-case re-entry for Target tests that= need a >>>>> + reboot. This parameter is a VOID* and it i= s the >>>>> + responsibility of the test author to ensure= that the >>>>> + contents are well understood by all test ca= ses that may >>>>> + consume it. >>>>> + @retval UNIT_TEST_PASSED The Unit test has completed = and >> the >>>> test >>>>> + case was successful. >>>>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >>>> failed. >>>>> +**/ >>>>> +UNIT_TEST_STATUS >>>>> +EFIAPI >>>>> +SendIpmiBadOenResponse ( >>>>> + IN UNIT_TEST_CONTEXT Context >>>>> + ) >>>>> +{ >>>>> + VOID *ResponseData; >>>>> + UINT32 *ResponseDataSize; >>>>> + EFI_STATUS Status; >>>>> + VOID *MockResponseResults =3D NULL; >>>>> + >>>>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool >>>> (BAD_OEN_RESPONSE_SIZE); >>>>> + ResponseDataSize =3D (UINT32 *)AllocateZeroPool (sizeof (UINT32= )); >>>>> + CopyMem (MockResponseResults, &BadOenResponse, >>>> BAD_OEN_RESPONSE_SIZE); >>>>> + >>>>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >>>> BAD_OEN_RESPONSE_SIZE, EFI_SUCCESS); >>>>> + if (EFI_ERROR (Status)) { >>>>> + return UNIT_TEST_ERROR_TEST_FAILED; >>>>> + } >>>>> + >>>>> + ResponseData =3D (UINT8 *)AllocateZeroPool (sizeof >> (BadOenResponse)); >>>>> + Status =3D IpmiBlobTransferSendIpmi >>>> (IpmiBlobTransferSubcommandGetCount, NULL, 0, ResponseData, >>>> ResponseDataSize); >>>>> + >>>>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_PROTOCOL_ERROR); >>>>> + FreePool (MockResponseResults); >>>>> + FreePool (ResponseDataSize); >>>>> + FreePool (ResponseData); >>>>> + return UNIT_TEST_PASSED; >>>>> +} >>>>> + >>>>> +/** >>>>> + @param[in] Context [Optional] An optional parameter that enabl= es: >>>>> + 1) test-case reuse with varied parameters a= nd >>>>> + 2) test-case re-entry for Target tests that= need a >>>>> + reboot. This parameter is a VOID* and it i= s the >>>>> + responsibility of the test author to ensure= that the >>>>> + contents are well understood by all test ca= ses that may >>>>> + consume it. >>>>> + @retval UNIT_TEST_PASSED The Unit test has completed = and >> the >>>> test >>>>> + case was successful. >>>>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >>>> failed. >>>>> +**/ >>>>> +UNIT_TEST_STATUS >>>>> +EFIAPI >>>>> +SendIpmiBadCrcResponse ( >>>>> + IN UNIT_TEST_CONTEXT Context >>>>> + ) >>>>> +{ >>>>> + VOID *ResponseData; >>>>> + UINT32 *ResponseDataSize; >>>>> + EFI_STATUS Status; >>>>> + VOID *MockResponseResults =3D NULL; >>>>> + >>>>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >>>> (BAD_CRC_RESPONSE_SIZE)); >>>>> + ResponseDataSize =3D (UINT32 *)AllocateZeroPool (sizeof (UINT32= )); >>>>> + CopyMem (MockResponseResults, &BadCrcResponse, >>>> BAD_CRC_RESPONSE_SIZE); >>>>> + >>>>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >>>> BAD_CRC_RESPONSE_SIZE, EFI_SUCCESS); >>>>> + if (EFI_ERROR (Status)) { >>>>> + return UNIT_TEST_ERROR_TEST_FAILED; >>>>> + } >>>>> + >>>>> + ResponseData =3D (UINT8 *)AllocateZeroPool (sizeof (BadCrcResponse= )); >>>>> + Status =3D IpmiBlobTransferSendIpmi >>>> (IpmiBlobTransferSubcommandGetCount, NULL, 0, ResponseData, >>>> ResponseDataSize); >>>>> + >>>>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_CRC_ERROR); >>>>> + FreePool (MockResponseResults); >>>>> + FreePool (ResponseDataSize); >>>>> + FreePool (ResponseData); >>>>> + return UNIT_TEST_PASSED; >>>>> +} >>>>> + >>>>> +UINT8 ValidGetCountResponse[] =3D { >>>>> + 0x00, // CompletionCode >>>>> + 0xCF, 0xC2, 0x00, // OpenBMC OEN >>>>> + 0xA4, 0x78, // CRC >>>>> + 0x01, 0x00, 0x00, 0x00, // Data >>>>> +}; >>>>> +#define VALID_GET_COUNT_RESPONSE_SIZE 10 * sizeof(UINT8) >>>>> + >>>>> +/** >>>>> + @param[in] Context [Optional] An optional parameter that enabl= es: >>>>> + 1) test-case reuse with varied parameters a= nd >>>>> + 2) test-case re-entry for Target tests that= need a >>>>> + reboot. This parameter is a VOID* and it i= s the >>>>> + responsibility of the test author to ensure= that the >>>>> + contents are well understood by all test ca= ses that may >>>>> + consume it. >>>>> + @retval UNIT_TEST_PASSED The Unit test has completed = and >> the >>>> test >>>>> + case was successful. >>>>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >>>> failed. >>>>> +**/ >>>>> +UNIT_TEST_STATUS >>>>> +EFIAPI >>>>> +SendIpmiValidCountResponse ( >>>>> + IN UNIT_TEST_CONTEXT Context >>>>> + ) >>>>> +{ >>>>> + UINT8 *ResponseData; >>>>> + UINT32 *ResponseDataSize; >>>>> + EFI_STATUS Status; >>>>> + VOID *MockResponseResults =3D NULL; >>>>> + >>>>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >>>> (VALID_GET_COUNT_RESPONSE_SIZE)); >>>>> + ResponseDataSize =3D (UINT32 *)AllocateZeroPool (sizeof (UINT32= )); >>>>> + CopyMem (MockResponseResults, &ValidGetCountResponse, >>>> VALID_GET_COUNT_RESPONSE_SIZE); >>>>> + >>>>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >>>> VALID_GET_COUNT_RESPONSE_SIZE, EFI_SUCCESS); >>>>> + if (EFI_ERROR (Status)) { >>>>> + return UNIT_TEST_ERROR_TEST_FAILED; >>>>> + } >>>>> + >>>>> + ResponseData =3D AllocateZeroPool (sizeof (ValidGetCountResponse))= ; >>>>> + Status =3D IpmiBlobTransferSendIpmi >>>> (IpmiBlobTransferSubcommandGetCount, NULL, 0, ResponseData, >>>> ResponseDataSize); >>>>> + >>>>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>>>> + FreePool (MockResponseResults); >>>>> + FreePool (ResponseDataSize); >>>>> + FreePool (ResponseData); >>>>> + return UNIT_TEST_PASSED; >>>>> +} >>>>> + >>>>> +/** >>>>> + @param[in] Context [Optional] An optional parameter that enabl= es: >>>>> + 1) test-case reuse with varied parameters a= nd >>>>> + 2) test-case re-entry for Target tests that= need a >>>>> + reboot. This parameter is a VOID* and it i= s the >>>>> + responsibility of the test author to ensure= that the >>>>> + contents are well understood by all test ca= ses that may >>>>> + consume it. >>>>> + @retval UNIT_TEST_PASSED The Unit test has completed = and >> the >>>> test >>>>> + case was successful. >>>>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >>>> failed. >>>>> +**/ >>>>> +UNIT_TEST_STATUS >>>>> +EFIAPI >>>>> +GetCountValidCountResponse ( >>>>> + IN UNIT_TEST_CONTEXT Context >>>>> + ) >>>>> +{ >>>>> + EFI_STATUS Status; >>>>> + UINT32 Count; >>>>> + VOID *MockResponseResults =3D NULL; >>>>> + >>>>> + Count =3D 0; >>>>> + >>>>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >>>> (VALID_GET_COUNT_RESPONSE_SIZE)); >>>>> + CopyMem (MockResponseResults, &ValidGetCountResponse, >>>> VALID_GET_COUNT_RESPONSE_SIZE); >>>>> + >>>>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >>>> VALID_GET_COUNT_RESPONSE_SIZE, EFI_SUCCESS); >>>>> + if (EFI_ERROR (Status)) { >>>>> + return UNIT_TEST_ERROR_TEST_FAILED; >>>>> + } >>>>> + >>>>> + Status =3D IpmiBlobTransferGetCount (&Count); >>>>> + >>>>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>>>> + UT_ASSERT_EQUAL (Count, 1); >>>>> + FreePool (MockResponseResults); >>>>> + return UNIT_TEST_PASSED; >>>>> +} >>>>> + >>>>> +UINT8 ValidEnumerateResponse[] =3D { >>>>> + 0x00, // CompletionCode >>>>> + 0xCF, 0xC2, 0x00, // OpenBMC OEN >>>>> + 0x81, 0x13, // CRC >>>>> + 0x2F, 0x73, 0x6D, 0x62, // Data =3D "/smbios" >>>>> + 0x69, 0x6F, 0x73, 0x00, >>>>> +}; >>>>> +#define VALID_ENUMERATE_RESPONSE_SIZE 14 * sizeof(UINT8) >>>>> + >>>>> +/** >>>>> + @param[in] Context [Optional] An optional parameter that enabl= es: >>>>> + 1) test-case reuse with varied parameters a= nd >>>>> + 2) test-case re-entry for Target tests that= need a >>>>> + reboot. This parameter is a VOID* and it i= s the >>>>> + responsibility of the test author to ensure= that the >>>>> + contents are well understood by all test ca= ses that may >>>>> + consume it. >>>>> + @retval UNIT_TEST_PASSED The Unit test has completed = and >> the >>>> test >>>>> + case was successful. >>>>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >>>> failed. >>>>> +**/ >>>>> +UNIT_TEST_STATUS >>>>> +EFIAPI >>>>> +EnumerateValidResponse ( >>>>> + IN UNIT_TEST_CONTEXT Context >>>>> + ) >>>>> +{ >>>>> + EFI_STATUS Status; >>>>> + CHAR8 *BlobId; >>>>> + VOID *MockResponseResults =3D NULL; >>>>> + >>>>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >>>> (VALID_ENUMERATE_RESPONSE_SIZE)); >>>>> + CopyMem (MockResponseResults, &ValidEnumerateResponse, >>>> VALID_ENUMERATE_RESPONSE_SIZE); >>>>> + >>>>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >>>> VALID_ENUMERATE_RESPONSE_SIZE, EFI_SUCCESS); >>>>> + if (EFI_ERROR (Status)) { >>>>> + return UNIT_TEST_ERROR_TEST_FAILED; >>>>> + } >>>>> + >>>>> + BlobId =3D AllocateZeroPool (sizeof (CHAR8) * >>>> IPMI_OEM_BLOB_MAX_DATA_PER_PACKET); >>>>> + >>>>> + Status =3D IpmiBlobTransferEnumerate (0, BlobId); >>>>> + >>>>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>>>> + UT_ASSERT_MEM_EQUAL (BlobId, "/smbios", 7); >>>>> + FreePool (MockResponseResults); >>>>> + FreePool (BlobId); >>>>> + return UNIT_TEST_PASSED; >>>>> +} >>>>> + >>>>> +/** >>>>> + @param[in] Context [Optional] An optional parameter that enabl= es: >>>>> + 1) test-case reuse with varied parameters a= nd >>>>> + 2) test-case re-entry for Target tests that= need a >>>>> + reboot. This parameter is a VOID* and it i= s the >>>>> + responsibility of the test author to ensure= that the >>>>> + contents are well understood by all test ca= ses that may >>>>> + consume it. >>>>> + @retval UNIT_TEST_PASSED The Unit test has completed = and >> the >>>> test >>>>> + case was successful. >>>>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >>>> failed. >>>>> +**/ >>>>> +UNIT_TEST_STATUS >>>>> +EFIAPI >>>>> +EnumerateInvalidBuffer ( >>>>> + IN UNIT_TEST_CONTEXT Context >>>>> + ) >>>>> +{ >>>>> + CHAR8 *BlobId; >>>>> + EFI_STATUS Status; >>>>> + VOID *MockResponseResults =3D NULL; >>>>> + >>>>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >>>> (VALID_ENUMERATE_RESPONSE_SIZE)); >>>>> + CopyMem (MockResponseResults, &ValidEnumerateResponse, >>>> VALID_ENUMERATE_RESPONSE_SIZE); >>>>> + >>>>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >>>> VALID_ENUMERATE_RESPONSE_SIZE, EFI_SUCCESS); >>>>> + if (EFI_ERROR (Status)) { >>>>> + return UNIT_TEST_ERROR_TEST_FAILED; >>>>> + } >>>>> + >>>>> + BlobId =3D NULL; >>>>> + >>>>> + UT_EXPECT_ASSERT_FAILURE (IpmiBlobTransferEnumerate (0, BlobId), >>>> NULL); >>>>> + >>>>> + FreePool (MockResponseResults); >>>>> + return UNIT_TEST_PASSED; >>>>> +} >>>>> + >>>>> +UINT8 ValidOpenResponse[] =3D { >>>>> + 0x00, // CompletionCode >>>>> + 0xCF, 0xC2, 0x00, // OpenBMC OEN >>>>> + 0x93, 0xD1, // CRC >>>>> + 0x03, 0x00, // SessionId =3D 3 >>>>> +}; >>>>> +#define VALID_OPEN_RESPONSE_SIZE 8 * sizeof(UINT8) >>>>> + >>>>> +/** >>>>> + @param[in] Context [Optional] An optional parameter that enabl= es: >>>>> + 1) test-case reuse with varied parameters a= nd >>>>> + 2) test-case re-entry for Target tests that= need a >>>>> + reboot. This parameter is a VOID* and it i= s the >>>>> + responsibility of the test author to ensure= that the >>>>> + contents are well understood by all test ca= ses that may >>>>> + consume it. >>>>> + @retval UNIT_TEST_PASSED The Unit test has completed = and >> the >>>> test >>>>> + case was successful. >>>>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >>>> failed. >>>>> +**/ >>>>> +UNIT_TEST_STATUS >>>>> +EFIAPI >>>>> +OpenValidResponse ( >>>>> + IN UNIT_TEST_CONTEXT Context >>>>> + ) >>>>> +{ >>>>> + EFI_STATUS Status; >>>>> + CHAR8 *BlobId; >>>>> + UINT16 Flags; >>>>> + UINT16 SessionId; >>>>> + VOID *MockResponseResults =3D NULL; >>>>> + VOID *MockResponseResults2 =3D NULL; >>>>> + VOID *MockResponseResults3 =3D NULL; >>>>> + >>>>> + Flags =3D BLOB_TRANSFER_STAT_OPEN_W; >>>>> + >>>>> + // >>>>> + // An open call effectively leads to three IPMI commands >>>>> + // 1. GetCount of blobs >>>>> + // 2. Enumerate the requested blob >>>>> + // 3. Open the requested blob >>>>> + // >>>>> + // So we'll push three Ipmi responses in this case >>>>> + // >>>>> + >>>>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >>>> (VALID_OPEN_RESPONSE_SIZE)); >>>>> + >>>>> + CopyMem (MockResponseResults, &ValidOpenResponse, >>>> VALID_OPEN_RESPONSE_SIZE); >>>>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >>>> VALID_OPEN_RESPONSE_SIZE, EFI_SUCCESS); >>>>> + if (EFI_ERROR (Status)) { >>>>> + return UNIT_TEST_ERROR_TEST_FAILED; >>>>> + } >>>>> + >>>>> + MockResponseResults2 =3D (UINT8 *)AllocateZeroPool (sizeof >>>> (VALID_ENUMERATE_RESPONSE_SIZE)); >>>>> + CopyMem (MockResponseResults2, &ValidEnumerateResponse, >>>> VALID_ENUMERATE_RESPONSE_SIZE); >>>>> + Status =3D MockIpmiSubmitCommand ((UINT8 >> *)MockResponseResults2, >>>> VALID_ENUMERATE_RESPONSE_SIZE, EFI_SUCCESS); >>>>> + if (EFI_ERROR (Status)) { >>>>> + return UNIT_TEST_ERROR_TEST_FAILED; >>>>> + } >>>>> + >>>>> + MockResponseResults3 =3D (UINT8 *)AllocateZeroPool (sizeof >>>> (VALID_GET_COUNT_RESPONSE_SIZE)); >>>>> + CopyMem (MockResponseResults3, &ValidGetCountResponse, >>>> VALID_GET_COUNT_RESPONSE_SIZE); >>>>> + Status =3D MockIpmiSubmitCommand ((UINT8 >> *)MockResponseResults3, >>>> VALID_GET_COUNT_RESPONSE_SIZE, EFI_SUCCESS); >>>>> + if (EFI_ERROR (Status)) { >>>>> + return UNIT_TEST_ERROR_TEST_FAILED; >>>>> + } >>>>> + >>>>> + BlobId =3D "/smbios"; >>>>> + >>>>> + Status =3D IpmiBlobTransferOpen (BlobId, Flags, &SessionId); >>>>> + >>>>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>>>> + UT_ASSERT_EQUAL (SessionId, 3); >>>>> + FreePool (MockResponseResults); >>>>> + return UNIT_TEST_PASSED; >>>>> +} >>>>> + >>>>> +UINT8 ValidReadResponse[] =3D { >>>>> + 0x00, // CompletionCode >>>>> + 0xCF, 0xC2, 0x00, // OpenBMC OEN >>>>> + 0x21, 0x6F, // CRC >>>>> + 0x00, 0x01, 0x02, 0x03, // Data to read >>>>> +}; >>>>> + >>>>> +#define VALID_READ_RESPONSE_SIZE 10 * sizeof(UINT8) >>>>> + >>>>> +/** >>>>> + @param[in] Context [Optional] An optional parameter that enabl= es: >>>>> + 1) test-case reuse with varied parameters a= nd >>>>> + 2) test-case re-entry for Target tests that= need a >>>>> + reboot. This parameter is a VOID* and it i= s the >>>>> + responsibility of the test author to ensure= that the >>>>> + contents are well understood by all test ca= ses that may >>>>> + consume it. >>>>> + @retval UNIT_TEST_PASSED The Unit test has completed = and >> the >>>> test >>>>> + case was successful. >>>>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >>>> failed. >>>>> +**/ >>>>> +UNIT_TEST_STATUS >>>>> +EFIAPI >>>>> +ReadValidResponse ( >>>>> + IN UNIT_TEST_CONTEXT Context >>>>> + ) >>>>> +{ >>>>> + EFI_STATUS Status; >>>>> + UINT8 *ResponseData; >>>>> + UINT8 ExpectedDataResponse[4] =3D { 0x00, 0x01, 0x02, 0x03 }= ; >>>>> + VOID *MockResponseResults =3D NULL; >>>>> + >>>>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >>>> (VALID_READ_RESPONSE_SIZE)); >>>>> + CopyMem (MockResponseResults, &ValidReadResponse, >>>> VALID_READ_RESPONSE_SIZE); >>>>> + ResponseData =3D AllocateZeroPool (sizeof (ValidReadResponse)); >>>>> + >>>>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >>>> VALID_READ_RESPONSE_SIZE, EFI_SUCCESS); >>>>> + if (EFI_ERROR (Status)) { >>>>> + return UNIT_TEST_ERROR_TEST_FAILED; >>>>> + } >>>>> + >>>>> + Status =3D IpmiBlobTransferRead (0, 0, 4, ResponseData); >>>>> + >>>>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>>>> + UT_ASSERT_MEM_EQUAL (ResponseData, ExpectedDataResponse, 4); >>>>> + FreePool (MockResponseResults); >>>>> + FreePool (ResponseData); >>>>> + return UNIT_TEST_PASSED; >>>>> +} >>>>> + >>>>> +/** >>>>> + @param[in] Context [Optional] An optional parameter that enabl= es: >>>>> + 1) test-case reuse with varied parameters a= nd >>>>> + 2) test-case re-entry for Target tests that= need a >>>>> + reboot. This parameter is a VOID* and it i= s the >>>>> + responsibility of the test author to ensure= that the >>>>> + contents are well understood by all test ca= ses that may >>>>> + consume it. >>>>> + @retval UNIT_TEST_PASSED The Unit test has completed = and >> the >>>> test >>>>> + case was successful. >>>>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >>>> failed. >>>>> +**/ >>>>> +UNIT_TEST_STATUS >>>>> +EFIAPI >>>>> +ReadInvalidBuffer ( >>>>> + IN UNIT_TEST_CONTEXT Context >>>>> + ) >>>>> +{ >>>>> + UINT8 *ResponseData; >>>>> + EFI_STATUS Status; >>>>> + VOID *MockResponseResults =3D NULL; >>>>> + >>>>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >>>> (VALID_READ_RESPONSE_SIZE)); >>>>> + CopyMem (MockResponseResults, &ValidReadResponse, >>>> VALID_READ_RESPONSE_SIZE); >>>>> + ResponseData =3D NULL; >>>>> + >>>>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >>>> VALID_READ_RESPONSE_SIZE, EFI_SUCCESS); >>>>> + if (EFI_ERROR (Status)) { >>>>> + return UNIT_TEST_ERROR_TEST_FAILED; >>>>> + } >>>>> + >>>>> + UT_EXPECT_ASSERT_FAILURE (IpmiBlobTransferRead (0, 0, 4, >>>> ResponseData), NULL); >>>>> + >>>>> + FreePool (MockResponseResults); >>>>> + return UNIT_TEST_PASSED; >>>>> +} >>>>> + >>>>> +/** >>>>> + @param[in] Context [Optional] An optional parameter that enabl= es: >>>>> + 1) test-case reuse with varied parameters a= nd >>>>> + 2) test-case re-entry for Target tests that= need a >>>>> + reboot. This parameter is a VOID* and it i= s the >>>>> + responsibility of the test author to ensure= that the >>>>> + contents are well understood by all test ca= ses that may >>>>> + consume it. >>>>> + @retval UNIT_TEST_PASSED The Unit test has completed = and >> the >>>> test >>>>> + case was successful. >>>>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >>>> failed. >>>>> +**/ >>>>> +UNIT_TEST_STATUS >>>>> +EFIAPI >>>>> +WriteValidResponse ( >>>>> + IN UNIT_TEST_CONTEXT Context >>>>> + ) >>>>> +{ >>>>> + EFI_STATUS Status; >>>>> + UINT8 SendData[4] =3D { 0x00, 0x01, 0x02, 0x03 }; >>>>> + VOID *MockResponseResults =3D NULL; >>>>> + >>>>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >>>> (VALID_NODATA_RESPONSE_SIZE)); >>>>> + CopyMem (MockResponseResults, &ValidNoDataResponse, >>>> VALID_NODATA_RESPONSE_SIZE); >>>>> + >>>>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >>>> VALID_NODATA_RESPONSE_SIZE, EFI_SUCCESS); >>>>> + if (EFI_ERROR (Status)) { >>>>> + return UNIT_TEST_ERROR_TEST_FAILED; >>>>> + } >>>>> + >>>>> + Status =3D IpmiBlobTransferWrite (0, 0, SendData, 4); >>>>> + >>>>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>>>> + FreePool (MockResponseResults); >>>>> + return UNIT_TEST_PASSED; >>>>> +} >>>>> + >>>>> +/** >>>>> + @param[in] Context [Optional] An optional parameter that enabl= es: >>>>> + 1) test-case reuse with varied parameters a= nd >>>>> + 2) test-case re-entry for Target tests that= need a >>>>> + reboot. This parameter is a VOID* and it i= s the >>>>> + responsibility of the test author to ensure= that the >>>>> + contents are well understood by all test ca= ses that may >>>>> + consume it. >>>>> + @retval UNIT_TEST_PASSED The Unit test has completed = and >> the >>>> test >>>>> + case was successful. >>>>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >>>> failed. >>>>> +**/ >>>>> +UNIT_TEST_STATUS >>>>> +EFIAPI >>>>> +CommitValidResponse ( >>>>> + IN UNIT_TEST_CONTEXT Context >>>>> + ) >>>>> +{ >>>>> + EFI_STATUS Status; >>>>> + UINT8 SendData[4] =3D { 0x00, 0x01, 0x02, 0x03 }; >>>>> + VOID *MockResponseResults =3D NULL; >>>>> + >>>>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >>>> (VALID_NODATA_RESPONSE_SIZE)); >>>>> + CopyMem (MockResponseResults, &ValidNoDataResponse, >>>> VALID_NODATA_RESPONSE_SIZE); >>>>> + >>>>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >>>> VALID_NODATA_RESPONSE_SIZE, EFI_SUCCESS); >>>>> + if (EFI_ERROR (Status)) { >>>>> + return UNIT_TEST_ERROR_TEST_FAILED; >>>>> + } >>>>> + >>>>> + Status =3D IpmiBlobTransferCommit (0, 4, SendData); >>>>> + >>>>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>>>> + FreePool (MockResponseResults); >>>>> + return UNIT_TEST_PASSED; >>>>> +} >>>>> + >>>>> +/** >>>>> + @param[in] Context [Optional] An optional parameter that enabl= es: >>>>> + 1) test-case reuse with varied parameters a= nd >>>>> + 2) test-case re-entry for Target tests that= need a >>>>> + reboot. This parameter is a VOID* and it i= s the >>>>> + responsibility of the test author to ensure= that the >>>>> + contents are well understood by all test ca= ses that may >>>>> + consume it. >>>>> + @retval UNIT_TEST_PASSED The Unit test has completed = and >> the >>>> test >>>>> + case was successful. >>>>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >>>> failed. >>>>> +**/ >>>>> +UNIT_TEST_STATUS >>>>> +EFIAPI >>>>> +CloseValidResponse ( >>>>> + IN UNIT_TEST_CONTEXT Context >>>>> + ) >>>>> +{ >>>>> + EFI_STATUS Status; >>>>> + VOID *MockResponseResults =3D NULL; >>>>> + >>>>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >>>> (VALID_NODATA_RESPONSE_SIZE)); >>>>> + CopyMem (MockResponseResults, &ValidNoDataResponse, >>>> VALID_NODATA_RESPONSE_SIZE); >>>>> + >>>>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >>>> VALID_NODATA_RESPONSE_SIZE, EFI_SUCCESS); >>>>> + if (EFI_ERROR (Status)) { >>>>> + return UNIT_TEST_ERROR_TEST_FAILED; >>>>> + } >>>>> + >>>>> + Status =3D IpmiBlobTransferClose (1); >>>>> + >>>>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>>>> + FreePool (MockResponseResults); >>>>> + return UNIT_TEST_PASSED; >>>>> +} >>>>> + >>>>> +/** >>>>> + @param[in] Context [Optional] An optional parameter that enabl= es: >>>>> + 1) test-case reuse with varied parameters a= nd >>>>> + 2) test-case re-entry for Target tests that= need a >>>>> + reboot. This parameter is a VOID* and it i= s the >>>>> + responsibility of the test author to ensure= that the >>>>> + contents are well understood by all test ca= ses that may >>>>> + consume it. >>>>> + @retval UNIT_TEST_PASSED The Unit test has completed = and >> the >>>> test >>>>> + case was successful. >>>>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >>>> failed. >>>>> +**/ >>>>> +UNIT_TEST_STATUS >>>>> +EFIAPI >>>>> +DeleteValidResponse ( >>>>> + IN UNIT_TEST_CONTEXT Context >>>>> + ) >>>>> +{ >>>>> + EFI_STATUS Status; >>>>> + VOID *MockResponseResults =3D NULL; >>>>> + >>>>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >>>> (VALID_NODATA_RESPONSE_SIZE)); >>>>> + CopyMem (MockResponseResults, &ValidNoDataResponse, >>>> VALID_NODATA_RESPONSE_SIZE); >>>>> + >>>>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >>>> VALID_NODATA_RESPONSE_SIZE, EFI_SUCCESS); >>>>> + if (EFI_ERROR (Status)) { >>>>> + return UNIT_TEST_ERROR_TEST_FAILED; >>>>> + } >>>>> + >>>>> + Status =3D IpmiBlobTransferDelete ("/smbios"); >>>>> + >>>>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>>>> + FreePool (MockResponseResults); >>>>> + return UNIT_TEST_PASSED; >>>>> +} >>>>> + >>>>> +UINT8 ValidBlobStatResponse[] =3D { >>>>> + 0x00, // CompletionCode >>>>> + 0xCF, 0xC2, 0x00, // OpenBMC OEN >>>>> + 0x1F, 0x4F, // Crc >>>>> + 0x01, 0x00, // BlobState >>>>> + 0x02, 0x03, 0x04, 0x05, // BlobSize >>>>> + 0x04, // MetaDataLen >>>>> + 0x06, 0x07, 0x08, 0x09, // MetaData >>>>> +}; >>>>> + >>>>> +#define VALID_BLOB_STAT_RESPONSE_SIZE 17 * sizeof(UINT8) >>>>> + >>>>> +/** >>>>> + @param[in] Context [Optional] An optional parameter that enabl= es: >>>>> + 1) test-case reuse with varied parameters a= nd >>>>> + 2) test-case re-entry for Target tests that= need a >>>>> + reboot. This parameter is a VOID* and it i= s the >>>>> + responsibility of the test author to ensure= that the >>>>> + contents are well understood by all test ca= ses that may >>>>> + consume it. >>>>> + @retval UNIT_TEST_PASSED The Unit test has completed = and >> the >>>> test >>>>> + case was successful. >>>>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >>>> failed. >>>>> +**/ >>>>> +UNIT_TEST_STATUS >>>>> +EFIAPI >>>>> +BlobStatValidResponse ( >>>>> + IN UNIT_TEST_CONTEXT Context >>>>> + ) >>>>> +{ >>>>> + EFI_STATUS Status; >>>>> + UINT16 *BlobState; >>>>> + UINT32 *Size; >>>>> + UINT8 *MetadataLength; >>>>> + UINT8 *Metadata; >>>>> + UINT8 *ExpectedMetadata; >>>>> + CHAR8 *BlobId; >>>>> + VOID *MockResponseResults =3D NULL; >>>>> + >>>>> + BlobState =3D AllocateZeroPool (sizeof (UINT16)); >>>>> + Size =3D AllocateZeroPool (sizeof (UINT32)); >>>>> + BlobId =3D "BlobId"; >>>>> + MetadataLength =3D AllocateZeroPool (sizeof (UINT8)); >>>>> + Metadata =3D AllocateZeroPool (4 * sizeof (UINT8)); >>>>> + ExpectedMetadata =3D AllocateZeroPool (4 * sizeof (UINT8)); >>>>> + >>>>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >>>> (VALID_BLOB_STAT_RESPONSE_SIZE)); >>>>> + CopyMem (MockResponseResults, &ValidBlobStatResponse, >>>> VALID_BLOB_STAT_RESPONSE_SIZE); >>>>> + >>>>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >>>> VALID_BLOB_STAT_RESPONSE_SIZE, EFI_SUCCESS); >>>>> + if (EFI_ERROR (Status)) { >>>>> + return UNIT_TEST_ERROR_TEST_FAILED; >>>>> + } >>>>> + >>>>> + Status =3D IpmiBlobTransferStat (BlobId, BlobState, Size, >> MetadataLength, >>>> Metadata); >>>>> + >>>>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>>>> + UT_ASSERT_EQUAL (*BlobState, 1); >>>>> + UT_ASSERT_EQUAL (*Size, 0x05040302); >>>>> + UT_ASSERT_EQUAL (*MetadataLength, 4); >>>>> + UT_ASSERT_MEM_EQUAL (Metadata, ExpectedMetadata, 4); >>>>> + FreePool (MockResponseResults); >>>>> + FreePool (BlobState); >>>>> + FreePool (Size); >>>>> + FreePool (MetadataLength); >>>>> + FreePool (Metadata); >>>>> + return UNIT_TEST_PASSED; >>>>> +} >>>>> + >>>>> +/** >>>>> + @param[in] Context [Optional] An optional parameter that enabl= es: >>>>> + 1) test-case reuse with varied parameters a= nd >>>>> + 2) test-case re-entry for Target tests that= need a >>>>> + reboot. This parameter is a VOID* and it i= s the >>>>> + responsibility of the test author to ensure= that the >>>>> + contents are well understood by all test ca= ses that may >>>>> + consume it. >>>>> + @retval UNIT_TEST_PASSED The Unit test has completed = and >> the >>>> test >>>>> + case was successful. >>>>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >>>> failed. >>>>> +**/ >>>>> +UNIT_TEST_STATUS >>>>> +EFIAPI >>>>> +BlobStatInvalidBuffer ( >>>>> + IN UNIT_TEST_CONTEXT Context >>>>> + ) >>>>> +{ >>>>> + UINT8 *Metadata; >>>>> + EFI_STATUS Status; >>>>> + VOID *MockResponseResults =3D NULL; >>>>> + >>>>> + Metadata =3D NULL; >>>>> + >>>>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >>>> (VALID_BLOB_STAT_RESPONSE_SIZE)); >>>>> + CopyMem (MockResponseResults, &ValidBlobStatResponse, >>>> VALID_BLOB_STAT_RESPONSE_SIZE); >>>>> + >>>>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >>>> VALID_BLOB_STAT_RESPONSE_SIZE, EFI_SUCCESS); >>>>> + if (EFI_ERROR (Status)) { >>>>> + return UNIT_TEST_ERROR_TEST_FAILED; >>>>> + } >>>>> + >>>>> + UT_EXPECT_ASSERT_FAILURE (IpmiBlobTransferStat (NULL, 0, 0, 0, >>>> Metadata), NULL); >>>>> + >>>>> + FreePool (MockResponseResults); >>>>> + return UNIT_TEST_PASSED; >>>>> +} >>>>> + >>>>> +/** >>>>> + @param[in] Context [Optional] An optional parameter that enabl= es: >>>>> + 1) test-case reuse with varied parameters a= nd >>>>> + 2) test-case re-entry for Target tests that= need a >>>>> + reboot. This parameter is a VOID* and it i= s the >>>>> + responsibility of the test author to ensure= that the >>>>> + contents are well understood by all test ca= ses that may >>>>> + consume it. >>>>> + @retval UNIT_TEST_PASSED The Unit test has completed = and >> the >>>> test >>>>> + case was successful. >>>>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >>>> failed. >>>>> +**/ >>>>> +UNIT_TEST_STATUS >>>>> +EFIAPI >>>>> +SessionStatValidResponse ( >>>>> + IN UNIT_TEST_CONTEXT Context >>>>> + ) >>>>> +{ >>>>> + EFI_STATUS Status; >>>>> + UINT16 *BlobState; >>>>> + UINT32 *Size; >>>>> + UINT8 *MetadataLength; >>>>> + UINT8 *Metadata; >>>>> + UINT8 *ExpectedMetadata; >>>>> + VOID *MockResponseResults =3D NULL; >>>>> + >>>>> + BlobState =3D AllocateZeroPool (sizeof (UINT16)); >>>>> + Size =3D AllocateZeroPool (sizeof (UINT32)); >>>>> + MetadataLength =3D AllocateZeroPool (sizeof (UINT8)); >>>>> + Metadata =3D AllocateZeroPool (4 * sizeof (UINT8)); >>>>> + ExpectedMetadata =3D AllocateZeroPool (4 * sizeof (UINT8)); >>>>> + >>>>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >>>> (VALID_BLOB_STAT_RESPONSE_SIZE)); >>>>> + CopyMem (MockResponseResults, &ValidBlobStatResponse, >>>> VALID_BLOB_STAT_RESPONSE_SIZE); >>>>> + >>>>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >>>> VALID_BLOB_STAT_RESPONSE_SIZE, EFI_SUCCESS); >>>>> + if (EFI_ERROR (Status)) { >>>>> + return UNIT_TEST_ERROR_TEST_FAILED; >>>>> + } >>>>> + >>>>> + Status =3D IpmiBlobTransferSessionStat (0, BlobState, Size, >>>> MetadataLength, Metadata); >>>>> + >>>>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>>>> + UT_ASSERT_EQUAL (*BlobState, 1); >>>>> + UT_ASSERT_EQUAL (*Size, 0x05040302); >>>>> + UT_ASSERT_EQUAL (*MetadataLength, 4); >>>>> + UT_ASSERT_MEM_EQUAL (Metadata, ExpectedMetadata, 4); >>>>> + FreePool (MockResponseResults); >>>>> + FreePool (BlobState); >>>>> + FreePool (Size); >>>>> + FreePool (MetadataLength); >>>>> + FreePool (Metadata); >>>>> + return UNIT_TEST_PASSED; >>>>> +} >>>>> + >>>>> +/** >>>>> + @param[in] Context [Optional] An optional parameter that enabl= es: >>>>> + 1) test-case reuse with varied parameters a= nd >>>>> + 2) test-case re-entry for Target tests that= need a >>>>> + reboot. This parameter is a VOID* and it i= s the >>>>> + responsibility of the test author to ensure= that the >>>>> + contents are well understood by all test ca= ses that may >>>>> + consume it. >>>>> + @retval UNIT_TEST_PASSED The Unit test has completed = and >> the >>>> test >>>>> + case was successful. >>>>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >>>> failed. >>>>> +**/ >>>>> +UNIT_TEST_STATUS >>>>> +EFIAPI >>>>> +SessionStatInvalidBuffer ( >>>>> + IN UNIT_TEST_CONTEXT Context >>>>> + ) >>>>> +{ >>>>> + UINT8 *Metadata; >>>>> + EFI_STATUS Status; >>>>> + VOID *MockResponseResults =3D NULL; >>>>> + >>>>> + Metadata =3D NULL; >>>>> + >>>>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >>>> (VALID_BLOB_STAT_RESPONSE_SIZE)); >>>>> + CopyMem (MockResponseResults, &ValidBlobStatResponse, >>>> VALID_BLOB_STAT_RESPONSE_SIZE); >>>>> + >>>>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >>>> VALID_BLOB_STAT_RESPONSE_SIZE, EFI_SUCCESS); >>>>> + if (EFI_ERROR (Status)) { >>>>> + return UNIT_TEST_ERROR_TEST_FAILED; >>>>> + } >>>>> + >>>>> + UT_EXPECT_ASSERT_FAILURE (IpmiBlobTransferSessionStat (0, 0, 0, 0, >>>> Metadata), NULL); >>>>> + >>>>> + FreePool (MockResponseResults); >>>>> + return UNIT_TEST_PASSED; >>>>> +} >>>>> + >>>>> +/** >>>>> + @param[in] Context [Optional] An optional parameter that enabl= es: >>>>> + 1) test-case reuse with varied parameters a= nd >>>>> + 2) test-case re-entry for Target tests that= need a >>>>> + reboot. This parameter is a VOID* and it i= s the >>>>> + responsibility of the test author to ensure= that the >>>>> + contents are well understood by all test ca= ses that may >>>>> + consume it. >>>>> + @retval UNIT_TEST_PASSED The Unit test has completed = and >> the >>>> test >>>>> + case was successful. >>>>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has >>>> failed. >>>>> +**/ >>>>> +UNIT_TEST_STATUS >>>>> +EFIAPI >>>>> +WriteMetaValidResponse ( >>>>> + IN UNIT_TEST_CONTEXT Context >>>>> + ) >>>>> +{ >>>>> + EFI_STATUS Status; >>>>> + VOID *MockResponseResults =3D NULL; >>>>> + >>>>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >>>> (VALID_NODATA_RESPONSE_SIZE)); >>>>> + CopyMem (MockResponseResults, &ValidNoDataResponse, >>>> VALID_NODATA_RESPONSE_SIZE); >>>>> + >>>>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >>>> VALID_NODATA_RESPONSE_SIZE, EFI_SUCCESS); >>>>> + if (EFI_ERROR (Status)) { >>>>> + return UNIT_TEST_ERROR_TEST_FAILED; >>>>> + } >>>>> + >>>>> + Status =3D IpmiBlobTransferWriteMeta (0, 0, NULL, 0); >>>>> + >>>>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>>>> + FreePool (MockResponseResults); >>>>> + return UNIT_TEST_PASSED; >>>>> +} >>>>> + >>>>> +/** >>>>> + Initialize the unit test framework, suite, and unit tests for the >>>>> + sample unit tests and run the unit tests. >>>>> + @retval EFI_SUCCESS All test cases were dispatched. >>>>> + @retval EFI_OUT_OF_RESOURCES There are not enough resources >>>> available to >>>>> + initialize the unit tests. >>>>> +**/ >>>>> +EFI_STATUS >>>>> +EFIAPI >>>>> +SetupAndRunUnitTests ( >>>>> + VOID >>>>> + ) >>>>> +{ >>>>> + EFI_STATUS Status; >>>>> + UNIT_TEST_FRAMEWORK_HANDLE Framework; >>>>> + UNIT_TEST_SUITE_HANDLE IpmiBlobTransfer; >>>>> + >>>>> + Framework =3D NULL; >>>>> + DEBUG ((DEBUG_INFO, "%a: v%a\n", UNIT_TEST_NAME, >>>> UNIT_TEST_VERSION)); >>>>> + >>>>> + Status =3D InitUnitTestFramework (&Framework, UNIT_TEST_NAME, >>>> gEfiCallerBaseName, UNIT_TEST_VERSION); >>>>> + if (EFI_ERROR (Status)) { >>>>> + DEBUG ((DEBUG_ERROR, "Failed to setup Test Framework. Exiting >> with >>>> status =3D %r\n", Status)); >>>>> + ASSERT (FALSE); >>>>> + return Status; >>>>> + } >>>>> + >>>>> + // >>>>> + // Populate the Unit Test Suite. >>>>> + // >>>>> + Status =3D CreateUnitTestSuite (&IpmiBlobTransfer, Framework, "IPM= I >>>> Blob Transfer Tests", "UnitTest.IpmiBlobTransferCB", NULL, NULL); >>>>> + if (EFI_ERROR (Status)) { >>>>> + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for IPMI Blo= b >>>> Transfer Tests\n")); >>>>> + Status =3D EFI_OUT_OF_RESOURCES; >>>>> + return Status; >>>>> + } >>>>> + >>>>> + // CalculateCrc16 >>>>> + Status =3D AddTestCase (IpmiBlobTransfer, "Test CRC Calculation", >>>> "GoodCrc", GoodCrc, NULL, NULL, NULL); >>>>> + Status =3D AddTestCase (IpmiBlobTransfer, "Test Bad CRC Calculatio= n", >>>> "BadCrc", BadCrc, NULL, NULL, NULL); >>>>> + // IpmiBlobTransferSendIpmi >>>>> + Status =3D AddTestCase (IpmiBlobTransfer, "Send IPMI returns bad >>>> completion", "SendIpmiBadCompletion", SendIpmiBadCompletion, NULL, >>>> NULL, NULL); >>>>> + Status =3D AddTestCase (IpmiBlobTransfer, "Send IPMI returns >> successfully >>>> with no data", "SendIpmiNoDataResponse", SendIpmiNoDataResponse, >>>> NULL, NULL, NULL); >>>>> + Status =3D AddTestCase (IpmiBlobTransfer, "Send IPMI returns >> successfully >>>> with bad OEN", "SendIpmiBadOenResponse", SendIpmiBadOenResponse, >>>> NULL, NULL, NULL); >>>>> + Status =3D AddTestCase (IpmiBlobTransfer, "Send IPMI returns >> successfully >>>> with bad CRC", "SendIpmiBadCrcResponse", SendIpmiBadCrcResponse, >>>> NULL, NULL, NULL); >>>>> + Status =3D AddTestCase (IpmiBlobTransfer, "Send IPMI returns with >> valid >>>> GetCount data", "SendIpmiValidCountResponse", >>>> SendIpmiValidCountResponse, NULL, NULL, NULL); >>>>> + // IpmiBlobTransferGetCount >>>>> + Status =3D AddTestCase (IpmiBlobTransfer, "GetCount call with vali= d >> data", >>>> "GetCountValidCountResponse", GetCountValidCountResponse, NULL, >>>> NULL, NULL); >>>>> + // IpmiBlobTransferEnumerate >>>>> + Status =3D AddTestCase (IpmiBlobTransfer, "Enumerate call with val= id >> data", >>>> "EnumerateValidResponse", EnumerateValidResponse, NULL, NULL, >> NULL); >>>>> + Status =3D AddTestCase (IpmiBlobTransfer, "Enumerate call with inv= alid >>>> output buffer", "EnumerateInvalidBuffer", EnumerateInvalidBuffer, NULL= , >>>> NULL, NULL); >>>>> + // IpmiBlobTransferOpen >>>>> + Status =3D AddTestCase (IpmiBlobTransfer, "Open call with valid da= ta", >>>> "OpenValidResponse", OpenValidResponse, NULL, NULL, NULL); >>>>> + // IpmiBlobTransferRead >>>>> + Status =3D AddTestCase (IpmiBlobTransfer, "Read call with valid da= ta", >>>> "ReadValidResponse", ReadValidResponse, NULL, NULL, NULL); >>>>> + Status =3D AddTestCase (IpmiBlobTransfer, "Read call with invalid >> buffer", >>>> "ReadInvalidBuffer", ReadInvalidBuffer, NULL, NULL, NULL); >>>>> + // IpmiBlobTransferWrite >>>>> + Status =3D AddTestCase (IpmiBlobTransfer, "Write call with valid d= ata", >>>> "WriteValidResponse", WriteValidResponse, NULL, NULL, NULL); >>>>> + // IpmiBlobTransferCommit >>>>> + Status =3D AddTestCase (IpmiBlobTransfer, "Commit call with valid = data", >>>> "CommitValidResponse", CommitValidResponse, NULL, NULL, NULL); >>>>> + // IpmiBlobTransferClose >>>>> + Status =3D AddTestCase (IpmiBlobTransfer, "Close call with valid d= ata", >>>> "CloseValidResponse", CloseValidResponse, NULL, NULL, NULL); >>>>> + // IpmiBlobTransferDelete >>>>> + Status =3D AddTestCase (IpmiBlobTransfer, "Delete call with valid = data", >>>> "DeleteValidResponse", DeleteValidResponse, NULL, NULL, NULL); >>>>> + // IpmiBlobTransferStat >>>>> + Status =3D AddTestCase (IpmiBlobTransfer, "Blob Stat call with val= id >> data", >>>> "BlobStatValidResponse", BlobStatValidResponse, NULL, NULL, NULL); >>>>> + Status =3D AddTestCase (IpmiBlobTransfer, "Blob Stat call with inv= alid >>>> buffer", "BlobStatInvalidBuffer", BlobStatInvalidBuffer, NULL, NULL, >> NULL); >>>>> + // IpmiBlobTransferSessionStat >>>>> + Status =3D AddTestCase (IpmiBlobTransfer, "Session Stat call with = valid >>>> data", "SessionStatValidResponse", SessionStatValidResponse, NULL, >> NULL, >>>> NULL); >>>>> + Status =3D AddTestCase (IpmiBlobTransfer, "Session Stat call with = invalid >>>> buffer", "SessionStatInvalidBuffer", SessionStatInvalidBuffer, NULL, N= ULL, >>>> NULL); >>>>> + // IpmiBlobTransferWriteMeta >>>>> + Status =3D AddTestCase (IpmiBlobTransfer, "WriteMeta call with val= id >> data", >>>> "WriteMetaValidResponse", WriteMetaValidResponse, NULL, NULL, >> NULL); >>>>> + >>>>> + // Execute the tests. >>>>> + Status =3D RunAllTestSuites (Framework); >>>>> + return Status; >>>>> +} >>>>> + >>>>> +/** >>>>> + Standard UEFI entry point for target based >>>>> + unit test execution from UEFI Shell. >>>>> +**/ >>>>> +EFI_STATUS >>>>> +EFIAPI >>>>> +BaseLibUnitTestAppEntry ( >>>>> + IN EFI_HANDLE ImageHandle, >>>>> + IN EFI_SYSTEM_TABLE *SystemTable >>>>> + ) >>>>> +{ >>>>> + return SetupAndRunUnitTests (); >>>>> +} >>>>> + >>>>> +/** >>>>> + Standard POSIX C entry point for host based unit test execution. >>>>> +**/ >>>>> +int >>>>> +main ( >>>>> + int argc, >>>>> + char *argv[] >>>>> + ) >>>>> +{ >>>>> + return SetupAndRunUnitTests (); >>>>> +} >>>>> diff --git >> a/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/Readme.md >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/Readme.md >>>>> new file mode 100644 >>>>> index 0000000000..47800f5801 >>>>> --- /dev/null >>>>> +++ >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/Readme.md >>>>> @@ -0,0 +1,24 @@ >>>>> +# IPMI Blob Transfer Interface Driver >>>>> + >>>>> +This DXE module is a UEFI implementation of the Phorphor Blob >> Transfer >>>> Interface defined in OpenBMC >>>>> +https://github.com/openbmc/phosphor-ipmi-blobs >>>>> + >>>>> +## NVIDIA's OpenBMC implements this interface as a protocol, allowin= g >>>> UEFI and BMC to transfer blobs over IPMI. >>>>> + >>>>> +### Usage: >>>>> +Any DXE module that wishes to use this protocol should do the >> 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 successfu= l >>>> unit tests. >>>>> + >>>>> +### Debugging >>>>> +To assist in debugging any issues, change BLOB_TRANSFER_DEBUG to 1 >>>>> -- >>>>> 2.17.1 >>>>>