From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail05.groups.io (mail05.groups.io [45.79.224.7]) by spool.mail.gandi.net (Postfix) with ESMTPS id D05817803DA for ; Fri, 17 May 2024 08:34:55 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=reNA7onLmKszsQFsFqDh+4bKNG14KziWTsiQFKIeo/s=; c=relaxed/simple; d=groups.io; h=Message-ID:Date:User-Agent:Subject:To:Cc:References:From:In-Reply-To:MIME-Version:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Resent-Date:Resent-From:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Language:Content-Type:Content-Transfer-Encoding; s=20240206; t=1715934894; v=1; b=AkeuIDuGiyb+l0rdaK0lVMmxUT9M2W2JHvGxpdXhnzSxYgv9YzqjtYJxb1RSqPaUCpDzS187 T/XqKsXjewGSub6EU1a4ILawYD45KG7BTskbj8XhGwxp8a0jNsp2b/VquZ97mYsQUh5f9gTo4vu Kb+B/m4nHCabfqQYBTr5AEnjOH4N6fAEsmx+GX+deoDmm1sKRHd7EqzUyM+e5aTd217X/8QsPNO ZmayKzE8XLOeEaScthD1k2aZjpu4L4ip6eV1nXAhSrrLsTzwg3odhG8DDV8aMVQcCbT0uLgFEaP ZEUE3RRlGrTn+oXw6SV7V6i/aBdvd+yveIfwAVxuUdtmg== X-Received: by 127.0.0.2 with SMTP id KhcMYY7687511xOoZYRKLE3E; Fri, 17 May 2024 01:34:54 -0700 X-Received: from NAM11-BN8-obe.outbound.protection.outlook.com (NAM11-BN8-obe.outbound.protection.outlook.com [40.107.236.139]) by mx.groups.io with SMTP id smtpd.web11.35813.1715934888067907311 for ; Fri, 17 May 2024 01:34:48 -0700 X-Received: from PH0PR01MB7287.prod.exchangelabs.com (2603:10b6:510:10a::21) by SA3PR01MB8523.prod.exchangelabs.com (2603:10b6:806:39b::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7587.28; Fri, 17 May 2024 08:34:41 +0000 X-Received: from PH0PR01MB7287.prod.exchangelabs.com ([fe80::9ee2:336e:a1f6:486b]) by PH0PR01MB7287.prod.exchangelabs.com ([fe80::9ee2:336e:a1f6:486b%4]) with mapi id 15.20.7587.028; Fri, 17 May 2024 08:34:41 +0000 Message-ID: Date: Fri, 17 May 2024 15:34:32 +0700 User-Agent: Mozilla Thunderbird Subject: Re: [edk2-devel] [edk2-platforms][PATCH v2] ManageabilityPkg: add support for the phosphor ipmi blob transfer protocol To: "Chang, Abner" , Nickle Wang , "devel@edk2.groups.io" Cc: "Attar, AbdulLateef (Abdul Lateef)" , Tinh Nguyen , Thang Nguyen OS , Mike Maslenkin References: <20240515150629.236739-1-nicklew@nvidia.com> <7d928ca7-e312-4a2e-9470-cbd96fbdc643@os.amperecomputing.com> From: "Nhi Pham via groups.io" In-Reply-To: X-ClientProxiedBy: SGXP274CA0023.SGPP274.PROD.OUTLOOK.COM (2603:1096:4:b8::35) To PH0PR01MB7287.prod.exchangelabs.com (2603:10b6:510:10a::21) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PH0PR01MB7287:EE_|SA3PR01MB8523:EE_ X-MS-Office365-Filtering-Correlation-Id: ce694b6f-edc2-4e5d-b4cf-08dc764c3233 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam-Message-Info: =?utf-8?B?QmlrYk96TkVpMTN1dTlJMXY4bEpmRnU5dXRpelpLWGVyLzRWZkgvTTZ5ZWRv?= =?utf-8?B?OTRoSGRxMlpNZjVxeHNndTQ1Y2FkbElZdTBCVjkzUEk0a1hUTmhERE9tV2Nj?= =?utf-8?B?U3hCYUR2OUczL21ET0ZrVnNUK0xVOUVIVWVGb2RXdy95UGJDdEQ0UDFYYkFJ?= =?utf-8?B?RFR3QmdqQjBacXBsYXI1YjR6MzN5STJ2SDgzZGk0LzdLNFhmV3Z3dzljcVk2?= =?utf-8?B?YTk0OWlleUdxdjV4SitXbkZZeVZhdURQNTJxUm9tenN4REVMUU9ZQ0NjeUpN?= =?utf-8?B?TXZSaXUwNXVSc3g5cGpzbU1WS1dJMXhWaCt0VUJMQ2lRek83by9ldHl6TlZn?= =?utf-8?B?WUR6VExraW1yU2VvK1d1b2tsTEh3SFV1RWVuNmZFR01MMGd6S1oxdzFjb0wx?= =?utf-8?B?VkZmYWVTanJpRVM3dnIvOVVmY2l3a05TSldjTXVUWmhoaER5aFFxNWpGRXlZ?= =?utf-8?B?M2c0c3BmSEd3QVZJdXNLRjB5bnUxSmhoWGZtblpWWGNVQlk3bjQwdmxsZ0to?= =?utf-8?B?eWpsTk9mYnB6emx1L2xrMTBSOEhTY0oyaXJJUXJEajRpZE02R21QV1dXZ2Uy?= =?utf-8?B?dHFiNFFQbU1WSFVqREdsZGVlT3Y1UFZnbkNNbmcwc1NaUXlxL1dMYTFCenBP?= =?utf-8?B?bUs5bXZrRHV2N2hPNmFoc214TTJVNmYzSXg2SFdRa1E3SEt1WkU1ZFNZMjRI?= =?utf-8?B?NmlGRkVlOERtVmJwZFhOZU5oMk81d21Pa0VFQnN6RG9JL2kzZnZqN2dsUDdP?= =?utf-8?B?dEcycXliM2w0UU5FT1ZZSVBXcnNzL2djOUNheERuQTB6a1kvTUVqTnpCam9i?= =?utf-8?B?eTFkbU53UTlQQ3ZqTlBoSmxjdWU1Z3lBL3JHZzV6ZC9EdjVMVW1tM2ZvOXlZ?= =?utf-8?B?RXlnQmRLcC9TK2RlOVpDYVFNMFM5cmFnTkc4OU1VUnhYRk1qSDZsWFRLa2NJ?= =?utf-8?B?M3JsaTdGR0FRRllnS2Vqd255eW8rMkxIV3RPWncxRWh3ZXJjTHF4SFhleUdx?= =?utf-8?B?RGFzc1hyUVl2eFAvazlIRy9mVzdheG1rY1hJcE9QVEFQSmNuSUwyRDh5eFdu?= =?utf-8?B?ZkQvOXdTZ29JTUZhTjVRelVsUmpuMkNsZmpic2FiQWVnUmVqY21CUmdCMlk0?= =?utf-8?B?RWpVcE1IUFhUQnFWVXBESkoxYlYzQmFMb2IzbERQbmYrbXViUXljWXhTc1Ix?= =?utf-8?B?VXlJcUhpTGI4V0NMN2oxeXFQcEw5ZkJ5Y1IvWlVlVjM0bmYvWFhMUElqcVJy?= =?utf-8?B?eW5aRGViY3Z3M1I4VXA0Z0xGRnlhSllpM1Y5TXREWGlyZXEwOGxVQUQyWjNP?= =?utf-8?B?eWhWeUlmSE1XNlhSeWR5MkJIbGIxclJsQ3piVS84SVE2alRHN3A4bmRCa1NO?= =?utf-8?B?MHhjYzNZMXVhR3NHdDB5TDdTT2VBcXhkNUdZR0pEV1RicDhWZzZQd1QrZ3Jp?= =?utf-8?B?bm5LRVhabXhOTHJURmNsamhjM3h1K2Fya0JQdERiaXVabUpNdHF3cVhucnZ3?= =?utf-8?B?SGNBR25KUU9ubXpucUQ0VmxYaytZcC9reS9pbGs1VVNTK0h3c3VYbWxjdUFP?= =?utf-8?B?eHNjYXFLQXNhT21QNzNYM2N2TnZXeEViemo0MnVyU3lYV3FGVWZiSkdRK1J2?= =?utf-8?Q?OalWY4wvhlNex6iEG9RVEMH3DaCMS/jCyvuLofnb+OWw=3D?= X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?ZHpPTnR2WnFoMnczaEpoenZFQzdHQURYdnFhbjRzbTkrZXc0aC9zL0tPZ3NH?= =?utf-8?B?T1BobmliWWdpZVltUHNNem03SC9vV2VaTm1PQzBDNm9VcGFYT2JCR3dDZjhy?= =?utf-8?B?L2N2WjBJdmNRV0h1b2lUNk5wWmNYNmVYSm8vSjhrcWk0M0EvWG9pWWphOG96?= =?utf-8?B?eVZGczhUZnl2dmVwLzJ6SDFKOFNYeHhuVnNTVWVFdVE3T3ZmWTE1SzZ6a3pN?= =?utf-8?B?QldXRGFzcW82TmNRQW4vK2NXcW9ZVGF2RzUvOWJhV0g0cCtJRWR2Zkw4cCsy?= =?utf-8?B?TGJYT2VwTWRIdjRZeUZMY0dvOWNka0tTRVBBc0U4SnVPM0dTd2dUSk0xcHdo?= =?utf-8?B?cnZUeTJteVhuLytmcUE3OU96MEhmV1ZUL0JoMmFBNTIxbzNuUW10VHZjVVJj?= =?utf-8?B?cjk0ME53ZGJ2eW40eTRWUXpZb3dFNlZubkhXRmI0WlZDTVN2QTdCS05HNWxq?= =?utf-8?B?QUg5OTFxSEJmMlBGR0dVZkhDT3dkNjYySWtvbkU4TXpoTW91WSsxL0FPNzRa?= =?utf-8?B?eS8zcHZjd1BWeDFNZW9CQlFaeDZpZzdlaWF3aXFsc0hSNTk4MU15eUtJWitj?= =?utf-8?B?dXpEVFpXaU9DN2M0TDkySi9zT0tVc3FFcWh4ZXZyeTFvN1EraXBocWVsSVFS?= =?utf-8?B?amVtMWNMbVdBQWx6a0tmdjlhWkZBdXp1MVZmNlkrUmxkQXFwdjJlbkpLOWZK?= =?utf-8?B?d2svT0JyRittZUdsSmlmOG5aVzJBWEpiU1FFTExMNUpIZU9xSDJ1SWxOaXpH?= =?utf-8?B?ZVBTUlBjUFFLaGpCY3Iyb1ZPQzdMTExoWUxGdmlHSlNJbU4valhqVms4SkN0?= =?utf-8?B?eHp6OWhuV050cWNsaC84anczdWt2YVUwS3hJbC9ROW5wZjRQQXJXcmxmV3Va?= =?utf-8?B?dmxLcFBoUHhxMGF5R1o3VW1UZ3pCVGQreTkrQ3VUYzFnTjJBeXNLQktmMzVY?= =?utf-8?B?ZE4vRGdNUHhmQXoyRTlmUU1WaThZbFhycmtsRkJiMGdOU1NUd0grajJTNXVy?= =?utf-8?B?WjBPTzdleGxKQUd2d2lrR0dHMXlqVjdLL1RVSXNUWjhCc2pPaFR2ZjVJdEZC?= =?utf-8?B?cG1laWRTajQvUWFLQ2Q2U21acXRFZ3Q3ZWR4Qk51YnRYd0YxclFsbGoyYWoz?= =?utf-8?B?TmlqbWZMUUNtTmhEL05xdW9mKzZSNEJtQmtWS1lpNGtVa3V3TmZPaFREV2hW?= =?utf-8?B?WUc1S2RVZWN4WWdKMEdSNWE2N0NpK0RGS3VHcjBUbHB0Um5QTFBMVjRnNmVO?= =?utf-8?B?WElmQmd6cmFndWZ6R2dOdEE5ZEhDSWNHRG5UdUFDekprKzdMZHZod2NXTTZM?= =?utf-8?B?TU1hQnluYXdBUEd4cWpNOWh1RlpjelRWQTY4Qm83YjM4Y1kyaGhnL29LTkVm?= =?utf-8?B?blRMb3gvQ00wbFVIb0VkUkpTSHYyZys0UmVGQzJpcktnd3R1RFlVL0FhWmhI?= =?utf-8?B?Zjg0Q3plZ2tDVmhrTWE4Y01rc1VUbGdBRk0xSjdFTkZ0dUpyaTFGaUt1b0JN?= =?utf-8?B?YW91aVgxMzFmdUgvZ1lYR0FTcHBBTmYwTE1vSC9jT1pSbVo3VERic2lkeHRv?= =?utf-8?B?azZNZkhSalExVHR6V2F5b1p2elRlRmwvTGozVzF2cDQzNXhEejlBWmxaZGxK?= =?utf-8?B?ZHV0VElmb2VOb3dSVTNvV2h6OHcycWw3bWhBT3krVWxlaXhud2czQUtTZmd1?= =?utf-8?B?Mkx4anFsLzIydmVwV2RVZ2hqblJJd3RkWDA1M0N3dGtWeDlvUE1ib09ZbGtV?= =?utf-8?B?a285bUZMaUwwNk4vY3k4NU1oclhCNUVjNzJab2tDUys0UE83K1Fwb1NXdWdO?= =?utf-8?B?a2dsRTJZYXNJL2RMK2pOV29uekFYbmYxMGpqWk9ZbUM1QUxNKzhmNXREYjZ4?= =?utf-8?B?ajZQMzkvN2lKVlJEMXdVQ09LbjJzZjRsNzIzc0pENXVSUjZBamxCOUpGNTNP?= =?utf-8?B?QjNtSEV5UDJNU1I5cXpNL1lDcVBuQVNtNjVaaGRYNVpNZTJyQnE2VHhMV1ZL?= =?utf-8?B?bUFlMHJUckRoajR2bWpLdW9RSTNXRml2TlhYZHk3dzF1MndDdTFrZ1hsaCtz?= =?utf-8?B?bDc4dTQ0b255ZXR5VldMUXMvY2VISE5iU1ZPNVZIbWVBZHZVVUJYT0FvcHNP?= =?utf-8?B?VGpRa2dFZ0srakJQaktCU21GRWxoK0kxU3N0cU9GNFJIclp3Um9VOW1mOVpw?= =?utf-8?B?Rmc9PQ==?= X-OriginatorOrg: os.amperecomputing.com X-MS-Exchange-CrossTenant-Network-Message-Id: ce694b6f-edc2-4e5d-b4cf-08dc764c3233 X-MS-Exchange-CrossTenant-AuthSource: PH0PR01MB7287.prod.exchangelabs.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 17 May 2024 08:34:41.6630 (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: uuzCdogDm3Yq2gXj0QH+eno0co5QmsEmsYVC516Ejc/fDhptfIuZ7kZNOhtUCum4G35F+pZIpPW3lX7GhRYJ5WbzUOBqWPHUXdQ0p494zw8= X-MS-Exchange-Transport-CrossTenantHeadersStamped: SA3PR01MB8523 Precedence: Bulk List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Resent-Date: Fri, 17 May 2024 01:34:48 -0700 Resent-From: nhi@os.amperecomputing.com Reply-To: devel@edk2.groups.io,nhi@os.amperecomputing.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: mVp3M7GCQ0izVwNG9jYuh3czx7686176AA= Content-Language: en-US Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: quoted-printable X-GND-Status: LEGIT Authentication-Results: spool.mail.gandi.net; dkim=pass header.d=groups.io header.s=20240206 header.b=AkeuIDuG; dmarc=pass (policy=none) header.from=groups.io; spf=pass (spool.mail.gandi.net: domain of bounce@groups.io designates 45.79.224.7 as permitted sender) smtp.mailfrom=bounce@groups.io Hi Abner, It' hard to say actually. I don't spend full-time for open-source work.=20 But I will try to complete it within 2 weeks or sooner. Most of Ampere Altra drivers including IPMI SSIF are living at=20 https://github.com/AmpereComputing/edk2-platforms. The effort now is to=20 port to be compatible with ManageabilityPkg. Regards, Nhi On 5/17/2024 3:16 PM, Chang, Abner wrote: > [AMD Official Use Only - AMD Internal Distribution Only] >=20 > Hi Nhi, > How much effort you think to have the SSIF ManageabilityPkg port? >=20 > Regards, > Abner >=20 >> -----Original Message----- >> From: Nhi Pham >> Sent: Friday, May 17, 2024 3:49 PM >> To: Nickle Wang ; devel@edk2.groups.io >> Cc: Chang, Abner ; Attar, AbdulLateef (Abdul >> Lateef) ; Tinh Nguyen >> ; Thang Nguyen OS >> ; Mike Maslenkin >> >> Subject: Re: [edk2-platforms][PATCH v2] ManageabilityPkg: add support fo= r >> the phosphor ipmi blob transfer protocol >> >> Caution: This message originated from an External Source. Use proper cau= tion >> when opening attachments, clicking links, or responding. >> >> >> Hi Nickle, >> >> Please see my comments inline... >> >> P/s: I just realized that I can not test this protocol without IPMI SSIF >> to be compatible with ManageabilityPkg framework. >> >> On 5/15/2024 10:06 PM, Nickle Wang wrote: >>> REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3D4773 >>> >>> This change implements the blob transfer protocol used in OpenBmc >>> documented here: https://github.com/openbmc/phosphor-ipmi-blobs >>> >>> Signed-off-by: Nick Ramirez >>> Co-authored-by: Nickle Wang >>> Cc: Abner Chang >>> Cc: Abdul Lateef Attar >>> Cc: Tinh Nguyen >>> Cc: Nhi Pham >>> Cc: Thang Nguyen OS >>> Cc: Mike Maslenkin >>> --- >>> .../ManageabilityPkg/ManageabilityPkg.dec | 3 + >>> .../Include/Manageability.dsc | 2 + >>> .../IpmiBlobTransferDxe.inf | 39 + >>> .../IpmiBlobTransferTestUnitTestsHost.inf | 40 + >>> .../Include/Protocol/IpmiBlobTransfer.h | 253 ++++ >>> .../InternalIpmiBlobTransfer.h | 407 ++++++ >>> .../IpmiBlobTransferDxe/IpmiBlobTransferDxe.c | 872 +++++++++++++ >>> .../UnitTest/IpmiBlobTransferTestUnitTests.c | 1113 +++++++++++++++= ++ >>> .../Universal/IpmiBlobTransferDxe/Readme.md | 24 + >>> 9 files changed, 2753 insertions(+) >>> create mode 100644 >> Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransfer >> Dxe.inf >>> create mode 100644 >> Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiBlo >> bTransferTestUnitTestsHost.inf >>> create mode 100644 >> Features/ManageabilityPkg/Include/Protocol/IpmiBlobTransfer.h >>> create mode 100644 >> Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/InternalIpmiBlob >> Transfer.h >>> create mode 100644 >> Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransfer >> Dxe.c >>> create mode 100644 >> Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiBlo >> bTransferTestUnitTests.c >>> create mode 100644 >> Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/Readme.md >>> >>> diff --git a/Features/ManageabilityPkg/ManageabilityPkg.dec >> b/Features/ManageabilityPkg/ManageabilityPkg.dec >>> index eb0ee67cba..dc1d00162c 100644 >>> --- a/Features/ManageabilityPkg/ManageabilityPkg.dec >>> +++ b/Features/ManageabilityPkg/ManageabilityPkg.dec >>> @@ -4,6 +4,7 @@ >>> # those are related to the platform management. >>> # >>> # Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserve= d.
>>> +# Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights >> reserved. >>> # SPDX-License-Identifier: BSD-2-Clause-Patent >>> # >>> ## >>> @@ -58,6 +59,8 @@ >>> gEdkiiPldmProtocolGuid =3D { 0x60997616, 0xDB70, 0x= 4B5F, { 0x86, >> 0xA4, 0x09, 0x58, 0xA3, 0x71, 0x47, 0xB4 } } >>> gEdkiiPldmSmbiosTransferProtocolGuid =3D { 0xFA431C3C, 0x816B, 0x= 4B32, >> { 0xA3, 0xE0, 0xAD, 0x9B, 0x7F, 0x64, 0x27, 0x2E } } >>> gEdkiiMctpProtocolGuid =3D { 0xE93465C1, 0x9A31, 0x= 4C96, { 0x92, >> 0x56, 0x22, 0x0A, 0xE1, 0x80, 0xB4, 0x1B } } >>> + ## Include/Protocol/IpmiBlobTransfer.h >>> + gEdkiiIpmiBlobTransferProtocolGuid =3D { 0x05837c75, 0x1d65, 0x46= 8b, >> { 0xb1, 0xc2, 0x81, 0xaf, 0x9a, 0x31, 0x5b, 0x2c } } >>> >>> [PcdsFixedAtBuild] >>> ## This value is the MCTP Interface source and destination endpoin= t ID for >> transmiting MCTP message. >>> diff --git a/Features/ManageabilityPkg/Include/Manageability.dsc >> b/Features/ManageabilityPkg/Include/Manageability.dsc >>> index 2e410df9ba..aae343a733 100644 >>> --- a/Features/ManageabilityPkg/Include/Manageability.dsc >>> +++ b/Features/ManageabilityPkg/Include/Manageability.dsc >>> @@ -2,6 +2,7 @@ >>> # Common libraries for Manageabilty Package >>> # >>> # Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserve= d.
>>> +# Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights >> reserved. >>> # SPDX-License-Identifier: BSD-2-Clause-Patent >>> # >>> ## >>> @@ -37,6 +38,7 @@ >>> [Components.X64, Components.AARCH64] >>> !if gManageabilityPkgTokenSpaceGuid.PcdManageabilityDxeIpmiEnable = =3D=3D >> TRUE >>> ManageabilityPkg/Universal/IpmiProtocol/Dxe/IpmiProtocolDxe.inf >>> + >> ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransferDxe.inf >>> !endif >>> >>> [Components.X64] >>> diff --git >> a/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransf >> erDxe.inf >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransf >> erDxe.inf >>> new file mode 100644 >>> index 0000000000..108f4bb5f8 >>> --- /dev/null >>> +++ >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransf >> erDxe.inf >>> @@ -0,0 +1,39 @@ >>> +## @file >>> +# IPMI Blob Transfer Protocol DXE Driver. >>> +# >>> +# Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. All right= s >> reserved. >>> +# >>> +# SPDX-License-Identifier: BSD-2-Clause-Patent >>> +# >>> + >>> +[Defines] >>> + INF_VERSION =3D 0x00010005 >>> + BASE_NAME =3D IpmiBlobTransferDxe >>> + FILE_GUID =3D 6357c804-78bb-4b0c-abdf-c75df942f= 319 >>> + MODULE_TYPE =3D DXE_DRIVER >>> + VERSION_STRING =3D 1.0 >>> + ENTRY_POINT =3D IpmiBlobTransferDxeDriverEntryPoi= nt >>> + >>> +[Sources.common] >>> + IpmiBlobTransferDxe.c >>> + >>> +[LibraryClasses] >>> + BaseLib >>> + BaseMemoryLib >>> + DebugLib >>> + IpmiLib >>> + MemoryAllocationLib >>> + PcdLib >>> + UefiBootServicesTableLib >>> + UefiDriverEntryPoint >>> + >>> +[Packages] >>> + MdePkg/MdePkg.dec >>> + MdeModulePkg/MdeModulePkg.dec >>> + ManageabilityPkg/ManageabilityPkg.dec >>> + >>> +[Protocols] >>> + gEdkiiIpmiBlobTransferProtocolGuid >>> + >>> +[Depex] >>> + TRUE >>> diff --git >> a/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiB >> lobTransferTestUnitTestsHost.inf >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiB >> lobTransferTestUnitTestsHost.inf >>> new file mode 100644 >>> index 0000000000..dab6858f09 >>> --- /dev/null >>> +++ >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiB >> lobTransferTestUnitTestsHost.inf >>> @@ -0,0 +1,40 @@ >>> +## @file >>> +# Unit tests of the Ipmi blob transfer driver that are run from a host >> environment. >>> +# >>> +# Copyright (c) 2020-2024, NVIDIA CORPORATION & AFFILIATES. All rights >> reserved. >>> +# >>> +# SPDX-License-Identifier: BSD-2-Clause-Patent >>> +## >>> + >>> +[Defines] >>> + INF_VERSION =3D 0x00010006 >>> + BASE_NAME =3D IpmiBlobTransferDxeUnitTestsHost >>> + FILE_GUID =3D 1f5d4095-ea52-432c-b078-86097fef6= 004 >>> + MODULE_TYPE =3D HOST_APPLICATION >>> + VERSION_STRING =3D 1.0 >>> + >>> +# >>> +# The following information is for reference only >>> +# and not required by the build tools. >>> +# >>> +# VALID_ARCHITECTURES =3D X64 >>> +# >>> + >>> +[Sources] >>> + IpmiBlobTransferTestUnitTests.c >>> + >>> +[Packages] >>> + MdePkg/MdePkg.dec >>> + MdeModulePkg/MdeModulePkg.dec >>> + ManageabilityPkg/ManageabilityPkg.dec >>> + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec >>> + >>> +[LibraryClasses] >>> + BaseLib >>> + BaseMemoryLib >>> + DebugLib >>> + UnitTestLib >>> + IpmiLib >>> + >>> +[Protocols] >>> + gEdkiiIpmiBlobTransferProtocolGuid >>> diff --git a/Features/ManageabilityPkg/Include/Protocol/IpmiBlobTransfe= r.h >> b/Features/ManageabilityPkg/Include/Protocol/IpmiBlobTransfer.h >>> new file mode 100644 >>> index 0000000000..14b5294314 >>> --- /dev/null >>> +++ b/Features/ManageabilityPkg/Include/Protocol/IpmiBlobTransfer.h >>> @@ -0,0 +1,253 @@ >>> +/** @file >>> + >>> + IPMI Blob Transfer driver >>> + >>> + Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. All rights >> reserved. >>> + >>> + SPDX-License-Identifier: BSD-2-Clause-Patent >>> + >>> + @Par: https://github.com/openbmc/phosphor-ipmi- >> blobs/blob/master/README.md >>> +**/ >> >> Lack of header guard >> #ifndef IPMI_BLOB_TRANSFER_H_ >> >>> +#include >>> +#include >>> +#include >>> +#include >>> + >>> +#define IPMI_OEM_BLOB_TRANSFER_CMD 0x80 >>> + >>> +#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 >>> + >>> +// >>> +// OpenBMC OEN code in little endian format >>> +// >>> +const UINT8 OpenBmcOen[] =3D { 0xCF, 0xC2, 0x00 }; >> >> const -> CONST >> >> Should we add a PCD for the OEN to be configured by platform specific >> BMC? Or this protocol is only to support OpenBMC. >> >>> + >>> +// >>> +// Blob Transfer Function Prototypes >>> +// >>> + >>> +/** >>> + This function retrieves the count of blob transfers available throug= h the >> IPMI. >>> + >>> + @param[out] Count The number of active blobs >>> + >>> + @retval EFI_SUCCESS Successfully retrieved the number of = active >> blobs. >>> + @retval Other An error occurred >>> +**/ >>> +typedef >>> +EFI_STATUS >>> +(EFIAPI *EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_GET_COUNT)( >>> + OUT UINT32 *Count >>> + ); >>> + >>> +/** >>> + This function enumerates blob transfers available through the IPMI. >>> + >>> + @param[in] BlobIndex The 0-based Index of the blob to = enumerate >>> + @param[out] BlobId The ID of the blob >>> + >>> + @retval EFI_SUCCESS Successfully enumerated the blob. >>> + @retval Other An error occurred >>> +**/ >>> +typedef >>> +EFI_STATUS >>> +(EFIAPI *EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_ENUMERATE)( >>> + IN UINT32 BlobIndex, >>> + OUT CHAR8 *BlobId >>> + ); >>> + >>> +/** >>> + This function is designed to open a session for a specific blob >>> + identified by its ID, using the IPMI. >>> + >>> + @param[in] BlobId The ID of the blob to open >>> + @param[in] Flags Flags to control how the blob is = opened >>> + @param[out] SessionId A unique session identifier >>> + >>> + @retval EFI_SUCCESS Successfully opened the blob. >>> + @retval Other An error occurred >>> +**/ >>> +typedef >>> +EFI_STATUS >>> +(EFIAPI *EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_OPEN)( >>> + IN CHAR8 *BlobId, >>> + IN UINT16 Flags, >>> + OUT UINT16 *SessionId >>> + ); >>> + >>> +/** >>> + This function reads data from a blob over the IPMI. >>> + >>> + @param[in] SessionId The session ID returned from a ca= ll to >> BlobOpen >>> + @param[in] Offset The offset of the blob from which= to start >> reading >>> + @param[in] RequestedSize The length of data to read >>> + @param[out] Data Data read from the blob >>> + >>> + @retval EFI_SUCCESS Successfully read from the blob. >>> + @retval Other An error occurred >>> +**/ >>> +typedef >>> +EFI_STATUS >>> +(EFIAPI *EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_READ)( >>> + IN UINT16 SessionId, >>> + IN UINT32 Offset, >>> + IN UINT32 RequestedSize, >>> + OUT UINT8 *Data >>> + ); >>> + >>> +/** >>> + This function writes data to a blob over the IPMI. >>> + >>> + @param[in] SessionId The session ID returned from a ca= ll to >> BlobOpen >>> + @param[in] Offset The offset of the blob from which= to start >> writing >>> + @param[in] Data A pointer to the data to write >>> + @param[in] WriteLength The length to write >>> + >>> + @retval EFI_SUCCESS Successfully wrote to the blob. >>> + @retval Other An error occurred >>> +**/ >>> +typedef >>> +EFI_STATUS >>> +(EFIAPI *EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_WRITE)( >>> + IN UINT16 SessionId, >>> + IN UINT32 Offset, >>> + IN UINT8 *Data, >>> + IN UINT32 WriteLength >>> + ); >>> + >>> +/** >>> + This function commits data to a blob over the IPMI. >>> + >>> + @param[in] SessionId The session ID returned from a c= all to >> BlobOpen >>> + @param[in] CommitDataLength The length of data to commit to = the >> blob >>> + @param[in] CommitData A pointer to the data to commit >>> + >>> + @retval EFI_SUCCESS Successful commit to the blob. >>> + @retval Other An error occurred >>> +**/ >>> +typedef >>> +EFI_STATUS >>> +(EFIAPI *EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_COMMIT)( >>> + IN UINT16 SessionId, >>> + IN UINT8 CommitDataLength, >>> + IN UINT8 *CommitData >>> + ); >>> + >>> +/** >>> + This function close a session associated with a blob transfer over t= he IPMI. >>> + >>> + @param[in] SessionId The session ID returned from a ca= ll to >> BlobOpen >>> + >>> + @retval EFI_SUCCESS The blob was closed. >>> + @retval Other An error occurred >>> +**/ >>> +typedef >>> +EFI_STATUS >>> +(EFIAPI *EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_CLOSE)( >>> + IN UINT16 SessionId >>> + ); >>> + >>> +/** >>> + This function deletes a specific blob identified by its ID over the = IPMI. >>> + >>> + @param[in] BlobId The BlobId to be deleted >>> + >>> + @retval EFI_SUCCESS The blob was deleted. >>> + @retval Other An error occurred >>> +**/ >>> +typedef >>> +EFI_STATUS >>> +(EFIAPI *EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_DELETE)( >>> + IN CHAR8 *BlobId >>> + ); >>> + >>> +/** >>> + This function retrieve the status of a specific blob identified by B= lobId from >> an IPMI. >>> + >>> + @param[in] BlobId The Blob ID to gather statistics = for >>> + @param[out] BlobState The current state of the blob >>> + @param[out] Size Size in bytes of the blob >>> + @param[out] MetadataLength Length of the optional metadata >>> + @param[out] Metadata Optional blob-specific metadata >>> + >>> + @retval EFI_SUCCESS The blob statistics were successf= ully >> gathered. >>> + @retval Other An error occurred >>> +**/ >>> +typedef >>> +EFI_STATUS >>> +(EFIAPI *EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_STAT)( >>> + IN CHAR8 *BlobId, >>> + OUT UINT16 *BlobState, >>> + OUT UINT32 *Size, >>> + OUT UINT8 *MetadataLength, >>> + OUT UINT8 *Metadata >>> + ); >>> + >>> +/** >>> + This function query the status of a blob transfer session in an IPMI= . >>> + >>> + @param[in] SessionId The ID of the session to gather s= tatistics for >>> + @param[out] BlobState The current state of the blob >>> + @param[out] Size Size in bytes of the blob >>> + @param[out] MetadataLength Length of the optional metadata >>> + @param[out] Metadata Optional blob-specific metadata >>> + >>> + @retval EFI_SUCCESS The blob statistics were successf= ully >> gathered. >>> + @retval Other An error occurred >>> +**/ >>> +typedef >>> +EFI_STATUS >>> +(EFIAPI *EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_SESSION_STAT)( >>> + IN UINT16 SessionId, >>> + OUT UINT16 *BlobState, >>> + OUT UINT32 *Size, >>> + OUT UINT8 *MetadataLength, >>> + OUT UINT8 *Metadata >>> + ); >>> + >>> +/** >>> + This function writes metadata to a blob associated with a session in= an >> IPMI. >>> + >>> + @param[in] SessionId The ID of the session to write me= tadata for >>> + @param[in] Offset The offset of the metadata to wri= te to >>> + @param[in] Data The data to write to the metadata >>> + @param[in] WriteLength The length to write >>> + >>> + @retval EFI_SUCCESS The blob metadata was successfull= y written. >>> + @retval Other An error occurred >>> +**/ >>> +typedef >>> +EFI_STATUS >>> +(EFIAPI *EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_WRITE_META)( >>> + IN UINT16 SessionId, >>> + IN UINT32 Offset, >>> + IN UINT8 *Data, >>> + IN UINT32 WriteLength >>> + ); >>> + >>> +// >>> +// Structure of EDKII_IPMI_BLOB_TRANSFER_PROTOCOL >>> +// >>> +struct _EDKII_IPMI_BLOB_TRANSFER_PROTOCOL { >>> + EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_GET_COUNT BlobGetCount; >>> + EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_ENUMERATE >> BlobEnumerate; >>> + EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_OPEN BlobOpen; >>> + EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_READ BlobRead; >>> + EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_WRITE BlobWrite; >>> + EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_COMMIT BlobCommit; >>> + EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_CLOSE BlobClose; >>> + EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_DELETE BlobDelete; >>> + EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_STAT BlobStat; >>> + EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_SESSION_STAT >> BlobSessionStat; >>> + EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_WRITE_META >> BlobWriteMeta; >>> +}; >>> + >>> +typedef struct _EDKII_IPMI_BLOB_TRANSFER_PROTOCOL >> EDKII_IPMI_BLOB_TRANSFER_PROTOCOL; >>> + >>> +extern EFI_GUID gEdkiiIpmiBlobTransferProtocolGuid; >>> diff --git >> a/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/InternalIpmiBl= o >> bTransfer.h >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/InternalIpmiBl >> obTransfer.h >>> new file mode 100644 >>> index 0000000000..3e90dc6871 >>> --- /dev/null >>> +++ >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/InternalIpmiBl >> obTransfer.h >>> @@ -0,0 +1,407 @@ >>> +/** @file >>> + >>> + Headers for IPMI Blob Transfer driver >>> + >>> + Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. All rights >> reserved. >>> + >>> + SPDX-License-Identifier: BSD-2-Clause-Patent >>> + >>> +**/ >>> + >> >> Lack of header guard >> #ifndef INTERNAL_IPMI_BLOB_TRANSFER_H_ >> >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> + >>> +#define PROTOCOL_RESPONSE_OVERHEAD (4 * sizeof(UINT8)) // 1 >> byte completion code + 3 bytes OEN >> >> Nit: Add a space after sizeof >> >>> +#define BLOB_MAX_DATA_PER_PACKET 64 >> >> Should it be moved to Include/Protocol/IpmiBlobTransfer.h? The caller >> could need to be aware the max length of the package. >> >>> + >>> +// 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[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[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[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[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[BLOB_MAX_DATA_PER_PACKET]; >>> +} IPMI_BLOB_TRANSFER_BLOB_COMMIT_SEND_DATA; >>> + >>> +// >>> +// Command 6 - BmcBlobClose >>> +// The BmcBlobClose command expects to receive a body of: >>> +// >>> +typedef struct { >>> + UINT16 SessionId; // Returned from BlobOpen >>> +} IPMI_BLOB_TRANSFER_BLOB_CLOSE_SEND_DATA; >>> + >>> +// >>> +// Command 7 - BmcBlobDelete >>> +// NOTE: This command will fail if there are open sessions for this bl= ob >>> +// The BmcBlobDelete command expects to receive a body of: >>> +// >>> +typedef struct { >>> + CHAR8 BlobId[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[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[BLOB_MAX_DATA_PER_PACKET]; >>> +} IPMI_BLOB_TRANSFER_BLOB_STAT_RESPONSE; >>> + >>> +// >>> +// Command 9 - BmcBlobSessionStat >>> +// Returns same data as BmcBlobState expect for a session, not a blob >>> +// This command expects to receive a body of: >>> +// >>> +typedef struct { >>> + UINT16 SessionId; >>> +} IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_SEND_DATA; >>> + >>> +typedef struct { >>> + UINT16 BlobState; >>> + UINT32 Size; // Size in bytes of the blob >>> + UINT8 MetaDataLen; >>> + UINT8 MetaData[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[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 >>> +CalculateCrc16Ccitt ( >>> + IN UINT8 *Data, >>> + IN UINTN DataSize >>> + ); >>> + >>> +/** >>> + This function does blob transfer over IPMI command. >>> + >>> + @param[in] SubCommand The specific sub-command to be execute= d >> as part of >>> + the blob transfer operation. >>> + @param[in] SendData A pointer to the data buffer that cont= ains the >> data to be sent. >>> + @param[in] SendDataSize The size of the data to be sent, in by= tes. >>> + @param[out] ResponseData A pointer to the buffer where the resp= onse >> data will be stored. >>> + @param[out] ResponseDataSize A pointer to a variable that will hold= the >> size of the response >>> + data received. >>> + >>> + @retval EFI_SUCCESS Successfully sends blob data. >>> + @retval EFI_OUT_OF_RESOURCES Memory allocation fails. >>> + @retval EFI_PROTOCOL_ERROR Communication errors. >>> + @retval EFI_CRC_ERROR Data integrity checks fail. >>> + @retval Other An error occurred >>> + >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferSendIpmi ( >>> + IN UINT8 SubCommand, >>> + IN UINT8 *SendData, >>> + IN UINT32 SendDataSize, >>> + OUT UINT8 *ResponseData, >>> + OUT UINT32 *ResponseDataSize >>> + ); >>> + >>> +/** >>> + This function retrieves the count of blob transfers available throug= h the >> IPMI. >>> + >>> + @param[out] Count The number of active blobs >>> + >>> + @retval EFI_SUCCESS Successfully retrieved the number of = active >> blobs. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferGetCount ( >>> + OUT UINT32 *Count >>> + ); >>> + >>> +/** >>> + This function enumerates blob transfers available through the IPMI. >>> + >>> + @param[in] BlobIndex The 0-based Index of the blob to = enumerate >>> + @param[out] BlobId The ID of the blob >>> + >>> + @retval EFI_SUCCESS Successfully enumerated the blob. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferEnumerate ( >>> + IN UINT32 BlobIndex, >>> + OUT CHAR8 *BlobId >>> + ); >>> + >>> +/** >>> + This function is designed to open a session for a specific blob >>> + identified by its ID, using the IPMI. >>> + >>> + @param[in] BlobId The ID of the blob to open >>> + @param[in] Flags Flags to control how the blob is = opened >>> + @param[out] SessionId A unique session identifier >>> + >>> + @retval EFI_SUCCESS Successfully opened the blob. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferOpen ( >>> + IN CHAR8 *BlobId, >>> + IN UINT16 Flags, >>> + OUT UINT16 *SessionId >>> + ); >>> + >>> +/** >>> + This function reads data from a blob over the IPMI. >>> + >>> + @param[in] SessionId The session ID returned from a ca= ll to >> BlobOpen >>> + @param[in] Offset The offset of the blob from which= to start >> reading >>> + @param[in] RequestedSize The length of data to read >>> + @param[out] Data Data read from the blob >>> + >>> + @retval EFI_SUCCESS Successfully read from the blob. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferRead ( >>> + IN UINT16 SessionId, >>> + IN UINT32 Offset, >>> + IN UINT32 RequestedSize, >>> + OUT UINT8 *Data >>> + ); >>> + >>> +/** >>> + This function writes data to a blob over the IPMI. >>> + >>> + @param[in] SessionId The session ID returned from a ca= ll to >> BlobOpen >>> + @param[in] Offset The offset of the blob from which= to start >> writing >>> + @param[in] Data A pointer to the data to write >>> + @param[in] WriteLength The length 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 >>> + ); >>> + >>> +/** >>> + This function commits data to a blob over the IPMI. >>> + >>> + @param[in] SessionId The session ID returned from a c= all to >> BlobOpen >>> + @param[in] CommitDataLength The length of data to commit to = the >> blob >>> + @param[in] CommitData A pointer to the data to commit >>> + >>> + @retval EFI_SUCCESS Successful commit to the blob. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferCommit ( >>> + IN UINT16 SessionId, >>> + IN UINT8 CommitDataLength, >>> + IN UINT8 *CommitData >>> + ); >>> + >>> +/** >>> + This function close a session associated with a blob transfer over t= he IPMI. >>> + >>> + @param[in] SessionId The session ID returned from a ca= ll to >> BlobOpen >>> + >>> + @retval EFI_SUCCESS The blob was closed. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferClose ( >>> + IN UINT16 SessionId >>> + ); >>> + >>> +/** >>> + This function deletes a specific blob identified by its ID over the = IPMI. >>> + >>> + @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 >>> + ); >>> + >>> +/** >>> + This function retrieve the status of a specific blob identified by B= lobId from >> an IPMI. >>> + >>> + @param[in] BlobId The Blob ID to gather statistics = for >>> + @param[out] BlobState The current state of the blob >>> + @param[out] Size Size in bytes of the blob >>> + @param[out] MetadataLength Length of the optional metadata >>> + @param[out] Metadata Optional blob-specific metadata >>> + >>> + @retval EFI_SUCCESS The blob statistics were successf= ully >> gathered. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferStat ( >>> + IN CHAR8 *BlobId, >>> + OUT UINT16 *BlobState, >>> + OUT UINT32 *Size, >>> + OUT UINT8 *MetadataLength, >>> + OUT UINT8 *Metadata >>> + ); >>> + >>> +/** >>> + This function query the status of a blob transfer session in an IPMI= . >>> + >>> + @param[in] SessionId The ID of the session to gather s= tatistics for >>> + @param[out] BlobState The current state of the blob >>> + @param[out] Size Size in bytes of the blob >>> + @param[out] MetadataLength Length of the optional metadata >>> + @param[out] Metadata Optional blob-specific metadata >>> + >>> + @retval EFI_SUCCESS The blob statistics were successf= ully >> gathered. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferSessionStat ( >>> + IN UINT16 SessionId, >>> + OUT UINT16 *BlobState, >>> + OUT UINT32 *Size, >>> + OUT UINT8 *MetadataLength, >>> + OUT UINT8 *Metadata >>> + ); >>> + >>> +/** >>> + This function writes metadata to a blob associated with a session in= an >> IPMI. >>> + >>> + @param[in] SessionId The ID of the session to write me= tadata for >>> + @param[in] Offset The offset of the metadata to wri= te to >>> + @param[in] Data The data to write to the metadata >>> + @param[in] WriteLength The length to write >>> + >>> + @retval EFI_SUCCESS The blob metadata was successfull= y written. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferWriteMeta ( >>> + IN UINT16 SessionId, >>> + IN UINT32 Offset, >>> + IN UINT8 *Data, >>> + IN UINT32 WriteLength >>> + ); >>> diff --git >> a/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransf >> erDxe.c >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransf >> erDxe.c >>> new file mode 100644 >>> index 0000000000..b8a2db193b >>> --- /dev/null >>> +++ >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransf >> erDxe.c >>> @@ -0,0 +1,872 @@ >>> +/** @file >>> + >>> + IPMI Blob Transfer driver >>> + >>> + Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. All rights >> reserved. >>> + >>> + SPDX-License-Identifier: BSD-2-Clause-Patent >>> + >>> +**/ >>> +#include >>> + >>> +#include "InternalIpmiBlobTransfer.h" >>> + >>> +#define BLOB_TRANSFER_DEBUG DEBUG_MANAGEABILITY >>> + >>> +STATIC CONST EDKII_IPMI_BLOB_TRANSFER_PROTOCOL >> mIpmiBlobTransfer =3D { >>> + >> (EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_GET_COUNT)*IpmiBlobTransferGe >> tCount, >>> + >> (EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_ENUMERATE)*IpmiBlobTransferEn >> umerate, >>> + >> (EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_OPEN)*IpmiBlobTransferOpen, >>> + (EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_READ)*IpmiBlobTransferRead, >>> + >> (EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_WRITE)*IpmiBlobTransferWrite, >>> + >> (EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_COMMIT)*IpmiBlobTransferCom >> mit, >>> + >> (EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_CLOSE)*IpmiBlobTransferClose, >>> + >> (EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_DELETE)*IpmiBlobTransferDelete, >>> + (EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_STAT)*IpmiBlobTransferStat, >>> + >> (EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_SESSION_STAT)*IpmiBlobTransfer >> SessionStat, >>> + >> (EDKII_IPMI_BLOB_TRANSFER_PROTOCOL_WRITE_META)*IpmiBlobTransfer >> WriteMeta >>> +}; >>> + >>> +/** >>> + 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 >>> +CalculateCrc16Ccitt ( >>> + IN UINT8 *Data, >>> + IN UINTN DataSize >>> + ) >>> +{ >>> + UINTN Index; >>> + UINTN BitIndex; >>> + UINT16 Crc; >>> + UINT16 Poly; >>> + BOOLEAN XorFlag; >>> + >>> + Crc =3D 0xFFFF; >>> + Poly =3D 0x1021; >>> + 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; >>> + } >>> + } >>> + } >>> + >>> + DEBUG ((BLOB_TRANSFER_DEBUG, "%a: CRC-16-CCITT %x\n", __func__, >> Crc)); >>> + >>> + return Crc; >>> +} >>> + >>> +/** >>> + This function does blob transfer over IPMI command. >>> + >>> + @param[in] SubCommand The specific sub-command to be execute= d >> as part of >>> + the blob transfer operation. >>> + @param[in] SendData A pointer to the data buffer that cont= ains the >> data to be sent. >>> + @param[in] SendDataSize The size of the data to be sent, in by= tes. >>> + @param[out] ResponseData A pointer to the buffer where the resp= onse >> data will be stored. >>> + @param[out] ResponseDataSize A pointer to a variable that will hold= the >> size of the response >>> + data received. >>> + >>> + @retval EFI_SUCCESS Successfully sends blob data. >>> + @retval EFI_OUT_OF_RESOURCES Memory allocation fails. >>> + @retval EFI_PROTOCOL_ERROR Communication errors. >>> + @retval EFI_CRC_ERROR Data integrity checks fail. >>> + @retval Other An error occurred >>> + >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferSendIpmi ( >>> + IN UINT8 SubCommand, >>> + IN UINT8 *SendData, >>> + IN UINT32 SendDataSize, >> >> Should describe SendData and SendDataSize as OPTIONAL >> >>> + 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; >>> + >> >> Should validate the pointer of input arguments: SendData, ResponseData, >> ResponseDataSize. >> >>> + Crc =3D 0; >>> + >>> + // >>> + // Prepend the proper header to the SendData >>> + // >>> + IpmiSendDataSize =3D (sizeof (IPMI_BLOB_TRANSFER_HEADER)); >>> + if (SendDataSize) { >>> + IpmiSendDataSize +=3D sizeof (Crc) + (sizeof (UINT8) * SendDataSiz= e); >>> + } >>> + >>> + IpmiSendData =3D AllocateZeroPool (IpmiSendDataSize); >>> + if (IpmiSendData =3D=3D NULL) { >>> + return EFI_OUT_OF_RESOURCES; >>> + } >>> + >>> + Header.OEN[0] =3D OpenBmcOen[0]; >>> + Header.OEN[1] =3D OpenBmcOen[1]; >>> + Header.OEN[2] =3D OpenBmcOen[2]; >>> + Header.SubCommand =3D SubCommand; >>> + CopyMem (IpmiSendData, &Header, sizeof >> (IPMI_BLOB_TRANSFER_HEADER)); >>> + if (SendDataSize) { >> >> if (SendDataSize !=3D 0) >> >>> + // >>> + // Calculate the Crc of the send data >>> + // >>> + Crc =3D CalculateCrc16Ccitt (SendData, SendDataSize); >>> + CopyMem (IpmiSendData + sizeof (IPMI_BLOB_TRANSFER_HEADER), >> &Crc, sizeof (UINT16)); >>> + CopyMem (IpmiSendData + sizeof (IPMI_BLOB_TRANSFER_HEADER) + >> sizeof (UINT16), SendData, SendDataSize); >>> + } >>> + >>> + DEBUG_CODE_BEGIN (); >>> + DEBUG ((BLOB_TRANSFER_DEBUG, "%a: Inputs:\n", __func__)); >>> + DEBUG ((BLOB_TRANSFER_DEBUG, "%a: SendDataSize: %02x\nData: ", >> __func__, SendDataSize)); >>> + UINT8 i; >>> + >>> + for (i =3D 0; i < SendDataSize; i++) { >>> + DEBUG ((BLOB_TRANSFER_DEBUG, "%02x", *((UINT8 *)SendData + i))); >>> + } >>> + >>> + DEBUG ((BLOB_TRANSFER_DEBUG, "\n")); >>> + DEBUG ((BLOB_TRANSFER_DEBUG, "%a: IpmiSendDataSize: %02x\nData: >> ", __func__, IpmiSendDataSize)); >>> + for (i =3D 0; i < IpmiSendDataSize; i++) { >>> + DEBUG ((BLOB_TRANSFER_DEBUG, "%02x", *((UINT8 *)IpmiSendData + >> i))); >>> + } >>> + >>> + DEBUG ((BLOB_TRANSFER_DEBUG, "\n")); >>> + DEBUG_CODE_END (); >>> + >>> + IpmiResponseDataSize =3D (*ResponseDataSize + >> PROTOCOL_RESPONSE_OVERHEAD); >>> + // >>> + // If expecting data to be returned, we have to also account for the= 16 bit >> CRC >>> + // >>> + if (*ResponseDataSize) { >> >> if (*ResponseDataSize !=3D 0) >> >>> + 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; >>> + >>> + DEBUG_CODE_BEGIN (); >>> + DEBUG ((BLOB_TRANSFER_DEBUG, "%a: IPMI Response:\n", __func__)); >>> + DEBUG ((BLOB_TRANSFER_DEBUG, "%a: ResponseDataSize: %02x\nData: >> ", __func__, IpmiResponseDataSize)); >>> + UINT8 i; >>> + >>> + for (i =3D 0; i < IpmiResponseDataSize; i++) { >>> + DEBUG ((BLOB_TRANSFER_DEBUG, "%02x", *(ModifiedResponseData + >> i))); >>> + } >>> + >>> + DEBUG ((BLOB_TRANSFER_DEBUG, "\n")); >>> + DEBUG_CODE_END (); >>> + >>> + 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", __func__, CompletionCode)); >>> + FreePool (IpmiResponseData); >>> + return EFI_PROTOCOL_ERROR; >>> + } >>> + >>> + // Strip completion code, we are done with it >>> + ModifiedResponseData =3D ModifiedResponseData + sizeof >> (CompletionCode); >>> + IpmiResponseDataSize -=3D sizeof (CompletionCode); >>> + >>> + // Check OEN code and verify it matches the OpenBMC OEN >>> + CopyMem (Oen, ModifiedResponseData, sizeof (OpenBmcOen)); >>> + if (CompareMem (Oen, OpenBmcOen, sizeof (OpenBmcOen)) !=3D 0) { >>> + FreePool (IpmiResponseData); >>> + return EFI_PROTOCOL_ERROR; >>> + } >>> + >>> + if (IpmiResponseDataSize =3D=3D sizeof (OpenBmcOen)) { >>> + // >>> + // In this case, there was no response data sent. This is not an e= rror. >>> + // Some messages do not require a response. >>> + // >>> + *ResponseDataSize =3D 0; >>> + FreePool (IpmiResponseData); >>> + return Status; >>> + // Now we need to validate the CRC then send the Response body bac= k >>> + } else { >>> + // Strip the OEN, we are done with it now >>> + ModifiedResponseData =3D ModifiedResponseData + sizeof (Oen); >>> + IpmiResponseDataSize -=3D sizeof (Oen); >>> + // Then validate the Crc >>> + CopyMem (&Crc, ModifiedResponseData, sizeof (Crc)); >>> + ModifiedResponseData =3D ModifiedResponseData + sizeof (Crc); >>> + IpmiResponseDataSize -=3D sizeof (Crc); >>> + >>> + if (Crc =3D=3D CalculateCrc16Ccitt (ModifiedResponseData, >> IpmiResponseDataSize)) { >>> + CopyMem (ResponseData, ModifiedResponseData, >> IpmiResponseDataSize); >>> + CopyMem (ResponseDataSize, &IpmiResponseDataSize, sizeof >> (IpmiResponseDataSize)); >>> + FreePool (IpmiResponseData); >>> + return EFI_SUCCESS; >>> + } else { >>> + FreePool (IpmiResponseData); >>> + return EFI_CRC_ERROR; >>> + } >>> + } >>> +} >>> + >>> +/** >>> + This function retrieves the count of blob transfers available throug= h the >> IPMI. >>> + >>> + @param[out] Count The number of active blobs >>> + >>> + @retval EFI_SUCCESS Successfully retrieved the number of = active >> blobs. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferGetCount ( >>> + OUT UINT32 *Count >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT8 *ResponseData; >>> + UINT32 ResponseDataSize; >>> + >>> + if (Count =3D=3D NULL) { >>> + return EFI_INVALID_PARAMETER; >>> + } >>> + >>> + 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; >>> +} >>> + >>> +/** >>> + This function enumerates blob transfers available through the IPMI. >>> + >>> + @param[in] BlobIndex The 0-based Index of the blob to = enumerate >>> + @param[out] BlobId The ID of the blob >>> + >>> + @retval EFI_SUCCESS Successfully enumerated the blob. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferEnumerate ( >>> + IN UINT32 BlobIndex, >>> + OUT CHAR8 *BlobId >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + >>> + UINT8 *SendData; >>> + UINT8 *ResponseData; >>> + UINT32 SendDataSize; >>> + UINT32 ResponseDataSize; >>> + >>> + if (BlobId =3D=3D NULL) { >>> + ASSERT (FALSE); >>> + return EFI_ABORTED; >> >> Should return EFI_INVALID_PARAMETER for input validation? >> >>> + } >>> + >>> + 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) { >> >> FreePool (ResponseData); >> >>> + 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; >>> +} >>> + >>> +/** >>> + This function is designed to open a session for a specific blob >>> + identified by its ID, using the IPMI. >>> + >>> + @param[in] BlobId The ID of the blob to open >>> + @param[in] Flags Flags to control how the blob is = opened >> >> It would be good if we can list out all flag definitions here. Actually, >> I don't know how to input for this argument. >> >> Are they BLOB_OPEN_FLAG_READ and BLOB_OPEN_FLAG_WRITE in the >> private >> include header? >> >>> + @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; >>> + >>> + if ((BlobId =3D=3D NULL) || (SessionId =3D=3D NULL)) { >>> + return EFI_INVALID_PARAMETER; >>> + } >>> + >>> + // >>> + // Before opening a blob, need to check if it exists >> >> I'm thinking the caller sequence here. Typically, the caller might check >> the presence of a blob by calling GetCount () and Enumerate () before >> opening a blob session. This check here could waste time. Or, do we call >> open direction the blob session without pre-checking? >> >>> + // >>> + Status =3D IpmiBlobTransferGetCount (&NumBlobs); >>> + if (EFI_ERROR (Status) || (NumBlobs =3D=3D 0)) { >>> + if (Status =3D=3D EFI_UNSUPPORTED) { >>> + return Status; >>> + } >>> + >>> + DEBUG ((DEBUG_ERROR, "%a: Could not find any blobs: %r\n", __func_= _, >> Status)); >>> + return EFI_NOT_FOUND; >>> + } >>> + >>> + BlobSearch =3D AllocateZeroPool (sizeof (CHAR8) * >> BLOB_MAX_DATA_PER_PACKET); >>> + if (BlobSearch =3D=3D NULL) { >>> + return EFI_OUT_OF_RESOURCES; >>> + } >>> + >>> + BlobFound =3D FALSE; >>> + for (Index =3D 0; Index < NumBlobs; Index++) { >>> + Status =3D IpmiBlobTransferEnumerate (Index, BlobSearch); >>> + if ((!EFI_ERROR (Status)) && (AsciiStrCmp (BlobSearch, BlobId) =3D= =3D 0)) { >>> + BlobFound =3D TRUE; >>> + break; >>> + } else { >>> + continue; >>> + } >>> + } >>> + >>> + if (!BlobFound) { >>> + DEBUG ((DEBUG_ERROR, "%a: Could not find a blob that matches %a\n"= , >> __func__, 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; >> >> Nit: add spaces around minus (-) for readability. >> >>> + >>> + 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; >>> +} >>> + >>> +/** >>> + This function reads data from a blob over the IPMI. >>> + >>> + @param[in] SessionId The session ID returned from a ca= ll to >> BlobOpen >>> + @param[in] Offset The offset of the blob from which= to start >> reading >>> + @param[in] RequestedSize The length of data to read >>> + @param[out] Data Data read from the blob >>> + >>> + @retval EFI_SUCCESS Successfully read from the blob. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferRead ( >>> + IN UINT16 SessionId, >> >> There might be developer mistake when executing the transfer before >> opening the session. How do we handle this failure path? Do we need to >> maintain a state machine for that? >> >> This comment applies to other functions as well. >> >>> + 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; >> >> Should return EFI_INVALID_PARAMETER? >> >>> + } >>> + >>> + ResponseDataSize =3D RequestedSize * sizeof (UINT8); >> >> Should check the RequestedSize against BLOB_MAX_DATA_PER_PACKET? >> >>> + 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) { >> >> FreePool (ResponseData); >> >>> + 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; >>> +} >>> + >>> +/** >>> + This function writes data to a blob over the IPMI. >>> + >>> + @param[in] SessionId The session ID returned from a ca= ll to >> BlobOpen >>> + @param[in] Offset The offset of the blob from which= to start >> writing >>> + @param[in] Data A pointer to the data to write >>> + @param[in] WriteLength The length 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; >>> + >>> + if (Data =3D=3D NULL) { >>> + return EFI_INVALID_PARAMETER; >>> + } >>> + >>> + // >>> + // Format send data >>> + // >>> + SendDataSize =3D sizeof (SessionId) + sizeof (Offset) + WriteLength; >> >> Should we check whether or not the WriteLength is equal to or less than >> BLOB_MAX_DATA_PER_PACKET? >> >>> + 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; >>> +} >>> + >>> +/** >>> + This function commits data to a blob over the IPMI. >>> + >>> + @param[in] SessionId The session ID returned from a c= all to >> BlobOpen >>> + @param[in] CommitDataLength The length of data to commit to = the >> blob >>> + @param[in] CommitData A pointer to the data to commit >>> + >>> + @retval EFI_SUCCESS Successful commit to the blob. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferCommit ( >>> + IN UINT16 SessionId, >>> + IN UINT8 CommitDataLength, >>> + IN UINT8 *CommitData >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT8 *SendData; >>> + UINT32 SendDataSize; >>> + UINT32 ResponseDataSize; >>> + >>> + if (CommitData =3D=3D NULL) { >> >> According to the spec https://github.com/openbmc/phosphor-ipmi-blobs, >> the commit data is block-specific optional. >> >> For instance, the commit data is optional for SMBIOS blob transfer. Look >> at https://github.com/openbmc/smbios-mdr >> >>> + return EFI_INVALID_PARAMETER; >>> + } >>> + >>> + // >>> + // 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; >>> +} >>> + >>> +/** >>> + This function close a session associated with a blob transfer over t= he IPMI. >>> + >>> + @param[in] SessionId The session ID returned from a ca= ll to >> BlobOpen >>> + >>> + @retval EFI_SUCCESS The blob was closed. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferClose ( >>> + IN UINT16 SessionId >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT8 *SendData; >>> + UINT32 SendDataSize; >>> + UINT32 ResponseDataSize; >>> + >>> + // >>> + // Format send data >>> + // >>> + SendDataSize =3D sizeof (IPMI_BLOB_TRANSFER_BLOB_CLOSE_SEND_DATA); >>> + SendData =3D AllocateZeroPool (SendDataSize); >>> + if (SendData =3D=3D NULL) { >>> + return EFI_OUT_OF_RESOURCES; >>> + } >>> + >>> + ((IPMI_BLOB_TRANSFER_BLOB_CLOSE_SEND_DATA *)SendData)- >>> SessionId =3D SessionId; >>> + >>> + ResponseDataSize =3D 0; >>> + >>> + Status =3D IpmiBlobTransferSendIpmi (IpmiBlobTransferSubcommandClose= , >> SendData, SendDataSize, NULL, &ResponseDataSize); >>> + >>> + FreePool (SendData); >>> + return Status; >>> +} >>> + >>> +/** >>> + This function deletes a specific blob identified by its ID over the = IPMI. >>> + >>> + @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; >>> + >>> + if (BlobId =3D=3D NULL) { >>> + return EFI_INVALID_PARAMETER; >>> + } >>> + >>> + // >>> + // 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 (IpmiBlobTransferSubcommandDelet= e, >> SendData, SendDataSize, NULL, &ResponseDataSize); >>> + >>> + FreePool (SendData); >>> + return Status; >>> +} >>> + >>> +/** >>> + This function retrieve the status of a specific blob identified by B= lobId from >> an IPMI. >>> + >>> + @param[in] BlobId The Blob ID to gather statistics = for >>> + @param[out] BlobState The current state of the blob >>> + @param[out] Size Size in bytes of the blob >>> + @param[out] MetadataLength Length of the optional metadata >>> + @param[out] Metadata Optional blob-specific metadata >>> + >>> + @retval EFI_SUCCESS The blob statistics were successf= ully >> gathered. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferStat ( >>> + IN CHAR8 *BlobId, >>> + OUT UINT16 *BlobState, >>> + OUT UINT32 *Size, >>> + OUT UINT8 *MetadataLength, >>> + OUT UINT8 *Metadata >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT8 *SendData; >>> + UINT8 *ResponseData; >>> + UINT32 SendDataSize; >>> + UINT32 ResponseDataSize; >>> + >>> + if ((BlobId =3D=3D NULL) || (BlobState =3D=3D NULL) || (Size =3D=3D = NULL) || >> (MetadataLength =3D=3D NULL)) { >> >> Could we make Metadata **per spec**, MetadataLength, and Size optional? >> We could not care them rather than BlobState. >> >> This comment applies to IpmiBlobTransferSessionStat () as well. >> >>> + return EFI_INVALID_PARAMETER; >>> + } >>> + >>> + 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, 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; >>> +} >>> + >>> +/** >>> + This function query the status of a blob transfer session in an IPMI= . >>> + >>> + @param[in] SessionId The ID of the session to gather s= tatistics for >>> + @param[out] BlobState The current state of the blob >>> + @param[out] Size Size in bytes of the blob >>> + @param[out] MetadataLength Length of the optional metadata >>> + @param[out] Metadata Optional blob-specific metadata >>> + >>> + @retval EFI_SUCCESS The blob statistics were successf= ully >> gathered. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferSessionStat ( >>> + IN UINT16 SessionId, >>> + OUT UINT16 *BlobState, >>> + OUT UINT32 *Size, >>> + OUT UINT8 *MetadataLength, >>> + OUT UINT8 *Metadata >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT8 *SendData; >>> + UINT8 *ResponseData; >>> + UINT32 SendDataSize; >>> + UINT32 ResponseDataSize; >>> + >>> + if ((BlobState =3D=3D NULL) || (Size =3D=3D NULL) || (MetadataLength= =3D=3D NULL) || >> (Metadata =3D=3D NULL)) { >>> + ASSERT (FALSE); >>> + return EFI_ABORTED; >>> + } >>> + >>> + ResponseDataSize =3D sizeof >> (IPMI_BLOB_TRANSFER_BLOB_STAT_RESPONSE); >>> + ResponseData =3D AllocateZeroPool (ResponseDataSize); >>> + if (ResponseData =3D=3D NULL) { >>> + return EFI_OUT_OF_RESOURCES; >>> + } >>> + >>> + // >>> + // Format send data >>> + // >>> + SendDataSize =3D sizeof >> (IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_SEND_DATA); >>> + SendData =3D AllocateZeroPool (SendDataSize); >>> + if (SendData =3D=3D NULL) { >>> + return EFI_OUT_OF_RESOURCES; >>> + } >>> + >>> + ((IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_SEND_DATA *)SendData)- >>> SessionId =3D SessionId; >>> + >>> + Status =3D IpmiBlobTransferSendIpmi >> (IpmiBlobTransferSubcommandSessionStat, SendData, SendDataSize, (UINT8 >> *)ResponseData, &ResponseDataSize); >>> + >>> + if (!EFI_ERROR (Status)) { >>> + *BlobState =3D >> ((IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_RESPONSE *)ResponseData)- >>> BlobState; >>> + *Size =3D ((IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_RESPONS= E >> *)ResponseData)->Size; >>> + *MetadataLength =3D >> ((IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_RESPONSE *)ResponseData)- >>> MetaDataLen; >>> + >>> + CopyMem (&Metadata, >> &((IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_RESPONSE >> *)ResponseData)->MetaData, sizeof >> (((IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_RESPONSE *)ResponseData)- >>> MetaData)); >>> + } >>> + >>> + FreePool (ResponseData); >>> + FreePool (SendData); >>> + return Status; >>> +} >>> + >>> +/** >>> + This function writes metadata to a blob associated with a session in= an >> IPMI. >>> + >>> + @param[in] SessionId The ID of the session to write me= tadata for >>> + @param[in] Offset The offset of the metadata to wri= te to >>> + @param[in] Data The data to write to the metadata >>> + @param[in] WriteLength The length to write >>> + >>> + @retval EFI_SUCCESS The blob metadata was successfull= y written. >>> + @retval Other An error occurred >>> +**/ >>> +EFI_STATUS >>> +IpmiBlobTransferWriteMeta ( >>> + IN UINT16 SessionId, >>> + IN UINT32 Offset, >>> + IN UINT8 *Data, >> >> How do callers know the data format of metadata for writing correctly? >> >>> + IN UINT32 WriteLength >> >> Should check with BLOB_MAX_DATA_PER_PACKET >> >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT8 *SendData; >>> + UINT32 SendDataSize; >>> + UINT32 ResponseDataSize; >>> + >>> + if (Data =3D=3D NULL) { >>> + return EFI_INVALID_PARAMETER; >>> + } >>> + >>> + // >>> + // Format send data >>> + // >>> + SendDataSize =3D sizeof >> (IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA); >>> + SendData =3D AllocateZeroPool (SendDataSize); >>> + if (SendData =3D=3D NULL) { >>> + return EFI_OUT_OF_RESOURCES; >>> + } >>> + >>> + ((IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA *)SendData)- >>> SessionId =3D SessionId; >>> + ((IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA *)SendData)->Offset >> =3D Offset; >>> + CopyMem (((IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA >> *)SendData)->Data, Data, sizeof (UINT8) * WriteLength); >>> + >>> + ResponseDataSize =3D 0; >>> + >>> + Status =3D IpmiBlobTransferSendIpmi >> (IpmiBlobTransferSubcommandWriteMeta, SendData, SendDataSize, NULL, >> &ResponseDataSize); >>> + >>> + FreePool (SendData); >>> + return Status; >>> +} >>> + >>> +/** >>> + This is the declaration of an EFI image entry point. This entry poin= t is >>> + the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers >> including >>> + both device drivers and bus drivers. >>> + >>> + @param[in] ImageHandle The firmware allocated handle for the = UEFI >> image. >>> + @param[in] SystemTable A pointer to the EFI System Table. >>> + >>> + @retval EFI_SUCCESS The operation completed successfully. >>> + @retval Others An unexpected error occurred. >>> + >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +IpmiBlobTransferDxeDriverEntryPoint ( >>> + IN EFI_HANDLE ImageHandle, >>> + IN EFI_SYSTEM_TABLE *SystemTable >>> + ) >>> +{ >>> + return gBS->InstallMultipleProtocolInterfaces ( >>> + &ImageHandle, >> >> Nit: Typically, we could also use gImageHandle instead. >> >>> + &gEdkiiIpmiBlobTransferProtocolGuid, >>> + (VOID *)&mIpmiBlobTransfer, >>> + NULL >>> + ); >>> +} >>> diff --git >> a/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiB >> lobTransferTestUnitTests.c >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiB >> lobTransferTestUnitTests.c >>> new file mode 100644 >>> index 0000000000..0f728527b8 >>> --- /dev/null >>> +++ >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiB >> lobTransferTestUnitTests.c >>> @@ -0,0 +1,1113 @@ >>> +/** @file >>> +* >>> +* Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved. >>> +* >>> +* SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION >> & AFFILIATES >>> +* SPDX-License-Identifier: BSD-2-Clause-Patent >>> +* >>> +**/ >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> + >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> + >>> +#include >>> +#include >>> +#include "../InternalIpmiBlobTransfer.h" >>> + >>> +#define UNIT_TEST_NAME "IPMI Blob Transfer Unit Tests" >>> +#define UNIT_TEST_VERSION "1.0" >>> + >>> +UINT8 InvalidCompletion[] =3D { >>> + 0xC0, // CompletionCode >>> + 0xCF, 0xC2, 0x00, // OpenBMC OEN >>> +}; >>> +#define INVALID_COMPLETION_SIZE 4 * sizeof(UINT8) >>> + >>> +UINT8 NoDataResponse[] =3D { >>> + 0x00, // CompletionCode >>> + 0xCF, 0xC2, 0x00, // OpenBMC OEN >>> +}; >>> +#define NO_DATA_RESPONSE_SIZE 4 * sizeof(UINT8) >>> + >>> +UINT8 BadOenResponse[] =3D { >>> + 0x00, // CompletionCode >>> + 0xFF, 0xC2, 0x00, // Wrong OEN >>> +}; >>> +#define BAD_OEN_RESPONSE_SIZE 4 * sizeof(UINT8) >>> + >>> +UINT8 BadCrcResponse[] =3D { >>> + 0x00, // CompletionCode >>> + 0xCF, 0xC2, 0x00, // OpenBMC OEN >>> + 0x00, 0x00, // CRC >>> + 0x01, 0x00, 0x00, 0x00, // Data >>> +}; >>> +#define BAD_CRC_RESPONSE_SIZE 10 * sizeof(UINT8) >>> + >>> +UINT8 ValidNoDataResponse[] =3D { >>> + 0x00, // CompletionCode >>> + 0xCF, 0xC2, 0x00, // OpenBMC OEN >>> +}; >>> + >>> +#define VALID_NODATA_RESPONSE_SIZE 4 * sizeof(UINT8) >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fail= ed. >>> +**/ >>> +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 CalculateCrc16Ccitt (Data, DataSize); >>> + >>> + UT_ASSERT_EQUAL (Crc, 0xB928); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fail= ed. >>> +**/ >>> +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 CalculateCrc16Ccitt (Data, DataSize); >>> + >>> + UT_ASSERT_NOT_EQUAL (Crc, 0x3409); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fail= ed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +SendIpmiBadCompletion ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + VOID *ResponseData; >>> + UINT32 *ResponseDataSize; >>> + EFI_STATUS Status; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool >> (INVALID_COMPLETION_SIZE); >>> + ResponseDataSize =3D (UINT32 *)AllocateZeroPool (sizeof (UINT32))= ; >>> + CopyMem (MockResponseResults, &InvalidCompletion, >> INVALID_COMPLETION_SIZE); >>> + >>> + MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> INVALID_COMPLETION_SIZE, EFI_SUCCESS); >>> + >>> + ResponseData =3D (UINT8 *)AllocateZeroPool (*ResponseDataSize); >>> + Status =3D IpmiBlobTransferSendIpmi >> (IpmiBlobTransferSubcommandGetCount, NULL, 0, ResponseData, >> ResponseDataSize); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_PROTOCOL_ERROR); >>> + FreePool (MockResponseResults); >>> + FreePool (ResponseDataSize); >>> + FreePool (ResponseData); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fail= ed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +SendIpmiNoDataResponse ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + VOID *ResponseData; >>> + UINT32 *ResponseDataSize; >>> + EFI_STATUS Status; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool >> (NO_DATA_RESPONSE_SIZE); >>> + ResponseDataSize =3D (UINT32 *)AllocateZeroPool (sizeof (UINT32))= ; >>> + CopyMem (MockResponseResults, &NoDataResponse, >> NO_DATA_RESPONSE_SIZE); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> NO_DATA_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + ResponseData =3D (UINT8 *)AllocateZeroPool (sizeof (NoDataResponse))= ; >>> + Status =3D IpmiBlobTransferSendIpmi >> (IpmiBlobTransferSubcommandGetCount, NULL, 0, ResponseData, >> ResponseDataSize); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>> + UT_ASSERT_EQUAL (*ResponseDataSize, 0); >>> + FreePool (MockResponseResults); >>> + FreePool (ResponseDataSize); >>> + FreePool (ResponseData); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fail= ed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +SendIpmiBadOenResponse ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + VOID *ResponseData; >>> + UINT32 *ResponseDataSize; >>> + EFI_STATUS Status; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool >> (BAD_OEN_RESPONSE_SIZE); >>> + ResponseDataSize =3D (UINT32 *)AllocateZeroPool (sizeof (UINT32))= ; >>> + CopyMem (MockResponseResults, &BadOenResponse, >> BAD_OEN_RESPONSE_SIZE); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> BAD_OEN_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + ResponseData =3D (UINT8 *)AllocateZeroPool (sizeof (BadOenResponse))= ; >>> + Status =3D IpmiBlobTransferSendIpmi >> (IpmiBlobTransferSubcommandGetCount, NULL, 0, ResponseData, >> ResponseDataSize); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_PROTOCOL_ERROR); >>> + FreePool (MockResponseResults); >>> + FreePool (ResponseDataSize); >>> + FreePool (ResponseData); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fail= ed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +SendIpmiBadCrcResponse ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + VOID *ResponseData; >>> + UINT32 *ResponseDataSize; >>> + EFI_STATUS Status; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (BAD_CRC_RESPONSE_SIZE)); >>> + ResponseDataSize =3D (UINT32 *)AllocateZeroPool (sizeof (UINT32))= ; >>> + CopyMem (MockResponseResults, &BadCrcResponse, >> BAD_CRC_RESPONSE_SIZE); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> BAD_CRC_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + ResponseData =3D (UINT8 *)AllocateZeroPool (sizeof (BadCrcResponse))= ; >>> + Status =3D IpmiBlobTransferSendIpmi >> (IpmiBlobTransferSubcommandGetCount, NULL, 0, ResponseData, >> ResponseDataSize); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_CRC_ERROR); >>> + FreePool (MockResponseResults); >>> + FreePool (ResponseDataSize); >>> + FreePool (ResponseData); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +UINT8 ValidGetCountResponse[] =3D { >>> + 0x00, // CompletionCode >>> + 0xCF, 0xC2, 0x00, // OpenBMC OEN >>> + 0xA4, 0x78, // CRC >>> + 0x01, 0x00, 0x00, 0x00, // Data >>> +}; >>> +#define VALID_GET_COUNT_RESPONSE_SIZE 10 * sizeof(UINT8) >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fail= ed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +SendIpmiValidCountResponse ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + UINT8 *ResponseData; >>> + UINT32 *ResponseDataSize; >>> + EFI_STATUS Status; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_GET_COUNT_RESPONSE_SIZE)); >>> + ResponseDataSize =3D (UINT32 *)AllocateZeroPool (sizeof (UINT32))= ; >>> + CopyMem (MockResponseResults, &ValidGetCountResponse, >> VALID_GET_COUNT_RESPONSE_SIZE); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> VALID_GET_COUNT_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + ResponseData =3D AllocateZeroPool (sizeof (ValidGetCountResponse)); >>> + Status =3D IpmiBlobTransferSendIpmi >> (IpmiBlobTransferSubcommandGetCount, NULL, 0, ResponseData, >> ResponseDataSize); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>> + FreePool (MockResponseResults); >>> + FreePool (ResponseDataSize); >>> + FreePool (ResponseData); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fail= ed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +GetCountValidCountResponse ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT32 Count; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + Count =3D 0; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_GET_COUNT_RESPONSE_SIZE)); >>> + CopyMem (MockResponseResults, &ValidGetCountResponse, >> VALID_GET_COUNT_RESPONSE_SIZE); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> VALID_GET_COUNT_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + Status =3D IpmiBlobTransferGetCount (&Count); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>> + UT_ASSERT_EQUAL (Count, 1); >>> + FreePool (MockResponseResults); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +UINT8 ValidEnumerateResponse[] =3D { >>> + 0x00, // CompletionCode >>> + 0xCF, 0xC2, 0x00, // OpenBMC OEN >>> + 0x81, 0x13, // CRC >>> + 0x2F, 0x73, 0x6D, 0x62, // Data =3D "/smbios" >>> + 0x69, 0x6F, 0x73, 0x00, >>> +}; >>> +#define VALID_ENUMERATE_RESPONSE_SIZE 14 * sizeof(UINT8) >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fail= ed. >>> +**/ >>> +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) * >> BLOB_MAX_DATA_PER_PACKET); >>> + >>> + Status =3D IpmiBlobTransferEnumerate (0, BlobId); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>> + UT_ASSERT_MEM_EQUAL (BlobId, "/smbios", 7); >>> + FreePool (MockResponseResults); >>> + FreePool (BlobId); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fail= ed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +EnumerateInvalidBuffer ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + CHAR8 *BlobId; >>> + EFI_STATUS Status; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_ENUMERATE_RESPONSE_SIZE)); >>> + CopyMem (MockResponseResults, &ValidEnumerateResponse, >> VALID_ENUMERATE_RESPONSE_SIZE); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> VALID_ENUMERATE_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + BlobId =3D NULL; >>> + >>> + UT_EXPECT_ASSERT_FAILURE (IpmiBlobTransferEnumerate (0, BlobId), >> NULL); >>> + >>> + FreePool (MockResponseResults); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +UINT8 ValidOpenResponse[] =3D { >>> + 0x00, // CompletionCode >>> + 0xCF, 0xC2, 0x00, // OpenBMC OEN >>> + 0x93, 0xD1, // CRC >>> + 0x03, 0x00, // SessionId =3D 3 >>> +}; >>> +#define VALID_OPEN_RESPONSE_SIZE 8 * sizeof(UINT8) >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fail= ed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +OpenValidResponse ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + CHAR8 *BlobId; >>> + UINT16 Flags; >>> + UINT16 SessionId; >>> + VOID *MockResponseResults =3D NULL; >>> + VOID *MockResponseResults2 =3D NULL; >>> + VOID *MockResponseResults3 =3D NULL; >>> + >>> + Flags =3D BLOB_TRANSFER_STAT_OPEN_W; >>> + >>> + // >>> + // An open call effectively leads to three IPMI commands >>> + // 1. GetCount of blobs >>> + // 2. Enumerate the requested blob >>> + // 3. Open the requested blob >>> + // >>> + // So we'll push three Ipmi responses in this case >>> + // >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_OPEN_RESPONSE_SIZE)); >>> + >>> + CopyMem (MockResponseResults, &ValidOpenResponse, >> VALID_OPEN_RESPONSE_SIZE); >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> VALID_OPEN_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + MockResponseResults2 =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_ENUMERATE_RESPONSE_SIZE)); >>> + CopyMem (MockResponseResults2, &ValidEnumerateResponse, >> VALID_ENUMERATE_RESPONSE_SIZE); >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults2, >> VALID_ENUMERATE_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + MockResponseResults3 =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_GET_COUNT_RESPONSE_SIZE)); >>> + CopyMem (MockResponseResults3, &ValidGetCountResponse, >> VALID_GET_COUNT_RESPONSE_SIZE); >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults3, >> VALID_GET_COUNT_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + BlobId =3D "/smbios"; >>> + >>> + Status =3D IpmiBlobTransferOpen (BlobId, Flags, &SessionId); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>> + UT_ASSERT_EQUAL (SessionId, 3); >>> + FreePool (MockResponseResults); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +UINT8 ValidReadResponse[] =3D { >>> + 0x00, // CompletionCode >>> + 0xCF, 0xC2, 0x00, // OpenBMC OEN >>> + 0x21, 0x6F, // CRC >>> + 0x00, 0x01, 0x02, 0x03, // Data to read >>> +}; >>> + >>> +#define VALID_READ_RESPONSE_SIZE 10 * sizeof(UINT8) >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fail= ed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +ReadValidResponse ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT8 *ResponseData; >>> + UINT8 ExpectedDataResponse[4] =3D { 0x00, 0x01, 0x02, 0x03 }; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_READ_RESPONSE_SIZE)); >>> + CopyMem (MockResponseResults, &ValidReadResponse, >> VALID_READ_RESPONSE_SIZE); >>> + ResponseData =3D AllocateZeroPool (sizeof (ValidReadResponse)); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> VALID_READ_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + Status =3D IpmiBlobTransferRead (0, 0, 4, ResponseData); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>> + UT_ASSERT_MEM_EQUAL (ResponseData, ExpectedDataResponse, 4); >>> + FreePool (MockResponseResults); >>> + FreePool (ResponseData); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fail= ed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +ReadInvalidBuffer ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + UINT8 *ResponseData; >>> + EFI_STATUS Status; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_READ_RESPONSE_SIZE)); >>> + CopyMem (MockResponseResults, &ValidReadResponse, >> VALID_READ_RESPONSE_SIZE); >>> + ResponseData =3D NULL; >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> VALID_READ_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + UT_EXPECT_ASSERT_FAILURE (IpmiBlobTransferRead (0, 0, 4, >> ResponseData), NULL); >>> + >>> + FreePool (MockResponseResults); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fail= ed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +WriteValidResponse ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT8 SendData[4] =3D { 0x00, 0x01, 0x02, 0x03 }; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_NODATA_RESPONSE_SIZE)); >>> + CopyMem (MockResponseResults, &ValidNoDataResponse, >> VALID_NODATA_RESPONSE_SIZE); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> VALID_NODATA_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + Status =3D IpmiBlobTransferWrite (0, 0, SendData, 4); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>> + FreePool (MockResponseResults); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fail= ed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +CommitValidResponse ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT8 SendData[4] =3D { 0x00, 0x01, 0x02, 0x03 }; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_NODATA_RESPONSE_SIZE)); >>> + CopyMem (MockResponseResults, &ValidNoDataResponse, >> VALID_NODATA_RESPONSE_SIZE); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> VALID_NODATA_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + Status =3D IpmiBlobTransferCommit (0, 4, SendData); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>> + FreePool (MockResponseResults); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fail= ed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +CloseValidResponse ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_NODATA_RESPONSE_SIZE)); >>> + CopyMem (MockResponseResults, &ValidNoDataResponse, >> VALID_NODATA_RESPONSE_SIZE); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> VALID_NODATA_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + Status =3D IpmiBlobTransferClose (1); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>> + FreePool (MockResponseResults); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fail= ed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +DeleteValidResponse ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_NODATA_RESPONSE_SIZE)); >>> + CopyMem (MockResponseResults, &ValidNoDataResponse, >> VALID_NODATA_RESPONSE_SIZE); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> VALID_NODATA_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + Status =3D IpmiBlobTransferDelete ("/smbios"); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>> + FreePool (MockResponseResults); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +UINT8 ValidBlobStatResponse[] =3D { >>> + 0x00, // CompletionCode >>> + 0xCF, 0xC2, 0x00, // OpenBMC OEN >>> + 0x1F, 0x4F, // Crc >>> + 0x01, 0x00, // BlobState >>> + 0x02, 0x03, 0x04, 0x05, // BlobSize >>> + 0x04, // MetaDataLen >>> + 0x06, 0x07, 0x08, 0x09, // MetaData >>> +}; >>> + >>> +#define VALID_BLOB_STAT_RESPONSE_SIZE 17 * sizeof(UINT8) >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fail= ed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +BlobStatValidResponse ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UINT16 *BlobState; >>> + UINT32 *Size; >>> + UINT8 *MetadataLength; >>> + UINT8 *Metadata; >>> + UINT8 *ExpectedMetadata; >>> + CHAR8 *BlobId; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + BlobState =3D AllocateZeroPool (sizeof (UINT16)); >>> + Size =3D AllocateZeroPool (sizeof (UINT32)); >>> + BlobId =3D "BlobId"; >>> + MetadataLength =3D AllocateZeroPool (sizeof (UINT8)); >>> + Metadata =3D AllocateZeroPool (4 * sizeof (UINT8)); >>> + ExpectedMetadata =3D AllocateZeroPool (4 * sizeof (UINT8)); >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_BLOB_STAT_RESPONSE_SIZE)); >>> + CopyMem (MockResponseResults, &ValidBlobStatResponse, >> VALID_BLOB_STAT_RESPONSE_SIZE); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> VALID_BLOB_STAT_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + Status =3D IpmiBlobTransferStat (BlobId, BlobState, Size, MetadataLe= ngth, >> Metadata); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>> + UT_ASSERT_EQUAL (*BlobState, 1); >>> + UT_ASSERT_EQUAL (*Size, 0x05040302); >>> + UT_ASSERT_EQUAL (*MetadataLength, 4); >>> + UT_ASSERT_MEM_EQUAL (Metadata, ExpectedMetadata, 4); >>> + FreePool (MockResponseResults); >>> + FreePool (BlobState); >>> + FreePool (Size); >>> + FreePool (MetadataLength); >>> + FreePool (Metadata); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fail= ed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +BlobStatInvalidBuffer ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + UINT8 *Metadata; >>> + EFI_STATUS Status; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + Metadata =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_BLOB_STAT_RESPONSE_SIZE)); >>> + CopyMem (MockResponseResults, &ValidBlobStatResponse, >> VALID_BLOB_STAT_RESPONSE_SIZE); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> VALID_BLOB_STAT_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + UT_EXPECT_ASSERT_FAILURE (IpmiBlobTransferStat (NULL, 0, 0, 0, >> Metadata), NULL); >>> + >>> + FreePool (MockResponseResults); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fail= ed. >>> +**/ >>> +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, Metadata= Length, >> Metadata); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>> + UT_ASSERT_EQUAL (*BlobState, 1); >>> + UT_ASSERT_EQUAL (*Size, 0x05040302); >>> + UT_ASSERT_EQUAL (*MetadataLength, 4); >>> + UT_ASSERT_MEM_EQUAL (Metadata, ExpectedMetadata, 4); >>> + FreePool (MockResponseResults); >>> + FreePool (BlobState); >>> + FreePool (Size); >>> + FreePool (MetadataLength); >>> + FreePool (Metadata); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fail= ed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +SessionStatInvalidBuffer ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + UINT8 *Metadata; >>> + EFI_STATUS Status; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + Metadata =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_BLOB_STAT_RESPONSE_SIZE)); >>> + CopyMem (MockResponseResults, &ValidBlobStatResponse, >> VALID_BLOB_STAT_RESPONSE_SIZE); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> VALID_BLOB_STAT_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + UT_EXPECT_ASSERT_FAILURE (IpmiBlobTransferSessionStat (0, 0, 0, 0, >> Metadata), NULL); >>> + >>> + FreePool (MockResponseResults); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + @param[in] Context [Optional] An optional parameter that enables= : >>> + 1) test-case reuse with varied parameters and >>> + 2) test-case re-entry for Target tests that n= eed a >>> + reboot. This parameter is a VOID* and it is = the >>> + responsibility of the test author to ensure t= hat the >>> + contents are well understood by all test case= s that may >>> + consume it. >>> + @retval UNIT_TEST_PASSED The Unit test has completed an= d the >> test >>> + case was successful. >>> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fail= ed. >>> +**/ >>> +UNIT_TEST_STATUS >>> +EFIAPI >>> +WriteMetaValidResponse ( >>> + IN UNIT_TEST_CONTEXT Context >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + VOID *MockResponseResults =3D NULL; >>> + >>> + MockResponseResults =3D (UINT8 *)AllocateZeroPool (sizeof >> (VALID_NODATA_RESPONSE_SIZE)); >>> + CopyMem (MockResponseResults, &ValidNoDataResponse, >> VALID_NODATA_RESPONSE_SIZE); >>> + >>> + Status =3D MockIpmiSubmitCommand ((UINT8 *)MockResponseResults, >> VALID_NODATA_RESPONSE_SIZE, EFI_SUCCESS); >>> + if (EFI_ERROR (Status)) { >>> + return UNIT_TEST_ERROR_TEST_FAILED; >>> + } >>> + >>> + Status =3D IpmiBlobTransferWriteMeta (0, 0, NULL, 0); >>> + >>> + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS); >>> + FreePool (MockResponseResults); >>> + return UNIT_TEST_PASSED; >>> +} >>> + >>> +/** >>> + Initialize the unit test framework, suite, and unit tests for the >>> + sample unit tests and run the unit tests. >>> + @retval EFI_SUCCESS All test cases were dispatched. >>> + @retval EFI_OUT_OF_RESOURCES There are not enough resources >> available to >>> + initialize the unit tests. >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +SetupAndRunUnitTests ( >>> + VOID >>> + ) >>> +{ >>> + EFI_STATUS Status; >>> + UNIT_TEST_FRAMEWORK_HANDLE Framework; >>> + UNIT_TEST_SUITE_HANDLE IpmiBlobTransfer; >>> + >>> + Framework =3D NULL; >>> + DEBUG ((DEBUG_INFO, "%a: v%a\n", UNIT_TEST_NAME, >> UNIT_TEST_VERSION)); >>> + >>> + Status =3D InitUnitTestFramework (&Framework, UNIT_TEST_NAME, >> gEfiCallerBaseName, UNIT_TEST_VERSION); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG ((DEBUG_ERROR, "Failed to setup Test Framework. Exiting with >> status =3D %r\n", Status)); >>> + ASSERT (FALSE); >>> + return Status; >>> + } >>> + >>> + // >>> + // Populate the Unit Test Suite. >>> + // >>> + Status =3D CreateUnitTestSuite (&IpmiBlobTransfer, Framework, "IPMI = Blob >> Transfer Tests", "UnitTest.IpmiBlobTransferCB", NULL, NULL); >>> + if (EFI_ERROR (Status)) { >>> + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for IPMI Blob >> Transfer Tests\n")); >>> + Status =3D EFI_OUT_OF_RESOURCES; >>> + return Status; >>> + } >>> + >>> + // CalculateCrc16Ccitt >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Test CRC Calculation", >> "GoodCrc", GoodCrc, NULL, NULL, NULL); >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Test Bad CRC Calculation"= , >> "BadCrc", BadCrc, NULL, NULL, NULL); >>> + // IpmiBlobTransferSendIpmi >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Send IPMI returns bad >> completion", "SendIpmiBadCompletion", SendIpmiBadCompletion, NULL, >> NULL, NULL); >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Send IPMI returns success= fully >> with no data", "SendIpmiNoDataResponse", SendIpmiNoDataResponse, >> NULL, NULL, NULL); >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Send IPMI returns success= fully >> with bad OEN", "SendIpmiBadOenResponse", SendIpmiBadOenResponse, >> NULL, NULL, NULL); >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Send IPMI returns success= fully >> with bad CRC", "SendIpmiBadCrcResponse", SendIpmiBadCrcResponse, NULL, >> NULL, NULL); >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Send IPMI returns with va= lid >> GetCount data", "SendIpmiValidCountResponse", >> SendIpmiValidCountResponse, NULL, NULL, NULL); >>> + // IpmiBlobTransferGetCount >>> + Status =3D AddTestCase (IpmiBlobTransfer, "GetCount call with valid = data", >> "GetCountValidCountResponse", GetCountValidCountResponse, NULL, NULL, >> NULL); >>> + // IpmiBlobTransferEnumerate >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Enumerate call with valid= data", >> "EnumerateValidResponse", EnumerateValidResponse, NULL, NULL, NULL); >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Enumerate call with inval= id >> output buffer", "EnumerateInvalidBuffer", EnumerateInvalidBuffer, NULL, >> NULL, NULL); >>> + // IpmiBlobTransferOpen >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Open call with valid data= ", >> "OpenValidResponse", OpenValidResponse, NULL, NULL, NULL); >>> + // IpmiBlobTransferRead >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Read call with valid data= ", >> "ReadValidResponse", ReadValidResponse, NULL, NULL, NULL); >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Read call with invalid bu= ffer", >> "ReadInvalidBuffer", ReadInvalidBuffer, NULL, NULL, NULL); >>> + // IpmiBlobTransferWrite >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Write call with valid dat= a", >> "WriteValidResponse", WriteValidResponse, NULL, NULL, NULL); >>> + // IpmiBlobTransferCommit >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Commit call with valid da= ta", >> "CommitValidResponse", CommitValidResponse, NULL, NULL, NULL); >>> + // IpmiBlobTransferClose >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Close call with valid dat= a", >> "CloseValidResponse", CloseValidResponse, NULL, NULL, NULL); >>> + // IpmiBlobTransferDelete >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Delete call with valid da= ta", >> "DeleteValidResponse", DeleteValidResponse, NULL, NULL, NULL); >>> + // IpmiBlobTransferStat >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Blob Stat call with valid= data", >> "BlobStatValidResponse", BlobStatValidResponse, NULL, NULL, NULL); >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Blob Stat call with inval= id buffer", >> "BlobStatInvalidBuffer", BlobStatInvalidBuffer, NULL, NULL, NULL); >>> + // IpmiBlobTransferSessionStat >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Session Stat call with va= lid data", >> "SessionStatValidResponse", SessionStatValidResponse, NULL, NULL, NULL); >>> + Status =3D AddTestCase (IpmiBlobTransfer, "Session Stat call with in= valid >> buffer", "SessionStatInvalidBuffer", SessionStatInvalidBuffer, NULL, NUL= L, >> NULL); >>> + // IpmiBlobTransferWriteMeta >>> + Status =3D AddTestCase (IpmiBlobTransfer, "WriteMeta call with valid= data", >> "WriteMetaValidResponse", WriteMetaValidResponse, NULL, NULL, NULL); >>> + >>> + // Execute the tests. >>> + Status =3D RunAllTestSuites (Framework); >>> + return Status; >>> +} >>> + >>> +/** >>> + Standard UEFI entry point for target based >>> + unit test execution from UEFI Shell. >>> +**/ >>> +EFI_STATUS >>> +EFIAPI >>> +BaseLibUnitTestAppEntry ( >>> + IN EFI_HANDLE ImageHandle, >>> + IN EFI_SYSTEM_TABLE *SystemTable >>> + ) >>> +{ >>> + return SetupAndRunUnitTests (); >>> +} >>> + >>> +/** >>> + Standard POSIX C entry point for host based unit test execution. >>> +**/ >>> +int >>> +main ( >>> + int argc, >>> + char *argv[] >>> + ) >>> +{ >>> + return SetupAndRunUnitTests (); >>> +} >>> diff --git >> a/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/Readme.md >> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/Readme.md >>> new file mode 100644 >>> index 0000000000..9eed5d3728 >>> --- /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 >>> + >>> +## OpenBMC implements this interface as a protocol, allowing UEFI and >> BMC to transfer blobs over IPMI. >>> + >>> +### Usage: >>> +Any DXE module that wishes to use this protocol should do the followin= g: >>> +1) The module should have a dependency on >> gEdkiiIpmiBlobTransferProtocolGuid in its inf "Depex" section >>> +2) The module should list gEdkiiIpmiBlobTransferProtocolGuid in its in= f >> "Protocol" section >>> +3) The module's entry point should do a LocateProtocol on >> gEdkiiIpmiBlobTransferProtocolGuid >>> + >>> +### A sample flow of protocol usage is as follows: >>> +1) A call to IpmiBlobTransferOpen () >>> +2) Iterative calls to IpmiBlobTransferWrite >>> +3) A call to IpmiBlobTransferClose () >>> + >>> +### Unit Tests: >>> +IpmiBlobTransferDxe/UnitTest/ contains host based unit tests of this >> implementation. >>> +Any changes to IpmiBlobTransferDxe should include proof of successful = unit >> tests. >>> + >>> +### Debugging >>> +To assist in debugging any issues, change BLOB_TRANSFER_DEBUG to >> desired debug level, such as DEBUG_ERROR or DEBUG_INFO. -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#118995): https://edk2.groups.io/g/devel/message/118995 Mute This Topic: https://groups.io/mt/106115743/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-