From: "Chang, Abner via groups.io" <abner.chang=amd.com@groups.io>
To: Nickle Wang <nicklew@nvidia.com>,
Rebecca Cran <rebecca@bsdio.com>,
"devel@edk2.groups.io" <devel@edk2.groups.io>
Cc: Isaac Oram <isaac.w.oram@intel.com>,
"Attar, AbdulLateef (Abdul Lateef)" <AbdulLateef.Attar@amd.com>,
Tinh Nguyen <tinhnguyen@amperemail.onmicrosoft.com>
Subject: Re: [edk2-devel] [edk2-platforms][PATCH] ManageabilityPkg: add support for the phosphor ipmi blob transfer protocol
Date: Fri, 9 Feb 2024 16:37:48 +0000 [thread overview]
Message-ID: <LV8PR12MB94522E71FB2DF30818D2AD67EA4B2@LV8PR12MB9452.namprd12.prod.outlook.com> (raw)
In-Reply-To: <MW4PR12MB703179843519C75A2DCCC611D94B2@MW4PR12MB7031.namprd12.prod.outlook.com>
[AMD Official Use Only - General]
Yeah, I forget this patch set and seems we don't have any follow up conversation after below feedbacks from community.
https://edk2.groups.io/g/devel/message/103116
https://edk2.groups.io/g/devel/message/103087
So Nickle, does NV still has the plan to upstream IPMI blob edk2 implementation? We should keep driving upstream the implementation as industry needs it to incorporate with OpenBMC.
Hi Rebessa,
As we are on Chinese New Year holidays now, please expect the delay response.
Thanks
Abner
> -----Original Message-----
> From: Nickle Wang <nicklew@nvidia.com>
> Sent: Friday, February 9, 2024 9:34 PM
> To: Rebecca Cran <rebecca@bsdio.com>; devel@edk2.groups.io
> Cc: Chang, Abner <Abner.Chang@amd.com>; Isaac Oram
> <isaac.w.oram@intel.com>; Attar, AbdulLateef (Abdul Lateef)
> <AbdulLateef.Attar@amd.com>; Tinh Nguyen
> <tinhnguyen@amperemail.onmicrosoft.com>
> Subject: RE: [edk2-devel] [edk2-platforms][PATCH] ManageabilityPkg: add
> support for the phosphor ipmi blob transfer protocol
>
> Caution: This message originated from an External Source. Use proper caution
> when opening attachments, clicking links, or responding.
>
>
> Hi Rebecca,
>
> There is change to this driver on NVIDIA GitHub here:
> https://github.com/NVIDIA/edk2-
> nvidia/tree/main/Silicon/NVIDIA/Drivers/IpmiBlobTransferDxe
>
> Regards,
> Nickle
>
> > -----Original Message-----
> > From: Rebecca Cran <rebecca@bsdio.com>
> > Sent: Friday, February 9, 2024 7:53 AM
> > To: devel@edk2.groups.io; Nickle Wang <nicklew@nvidia.com>
> > Cc: Abner Chang <abner.chang@amd.com>; Isaac Oram
> > <isaac.w.oram@intel.com>; Abdul Lateef Attar
> > <AbdulLateef.Attar@amd.com>; Tinh Nguyen
> > <tinhnguyen@amperemail.onmicrosoft.com>
> > Subject: Re: [edk2-devel] [edk2-platforms][PATCH] ManageabilityPkg: add
> > support for the phosphor ipmi blob transfer protocol
> >
> > External email: Use caution opening links or attachments
> >
> >
> > Was this change abandoned?
> >
> > I've realized it would be useful to have in the firmware I'm working on,
> > and was wondering if there's a newer revision of this patch somewhere?
> >
> >
> > --
> > Rebecca Cran
> >
> >
> > On 4/11/23 21:17, Nickle Wang via groups.io wrote:
> > > This change implements the blob transfer protocol used in OpenBmc
> > > documented here:
> >
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgith
> ub.
> > com%2Fopenbmc%2Fphosphor-ipmi-
> >
> blobs&data=05%7C02%7Cnicklew%40nvidia.com%7Cb327966e846243687
> 65
> >
> 208dc29010a98%7C43083d15727340c1b7db39efd9ccc17a%7C0%7C0%7C
> 63
> >
> 8430331675542376%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAw
> MD
> >
> AiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0%7C%7C%7C&s
> da
> >
> ta=esHFGSAc5TGBvPUWAOKd22p7DRMZ9UbnBU1jNAh%2Fsb0%3D&reserv
> ed
> > =0
> > >
> > > Signed-off-by: Nick Ramirez <nramirez@nvidia.com>
> > > Cc: Abner Chang <abner.chang@amd.com>
> > > Cc: Isaac Oram <isaac.w.oram@intel.com>
> > > Cc: Abdul Lateef Attar <AbdulLateef.Attar@amd.com>
> > > Cc: Nickle Wang <nicklew@nvidia.com>
> > > Cc: Tinh Nguyen <tinhnguyen@amperemail.onmicrosoft.com>
> > > ---
> > > .../ManageabilityPkg/ManageabilityPkg.dec | 6 +
> > > .../Include/Dsc/Manageability.dsc | 4 +-
> > > .../IpmiBlobTransferDxe.inf | 39 +
> > > .../IpmiBlobTransferTestUnitTestsHost.inf | 40 +
> > > .../Include/Protocol/IpmiBlobTransfer.h | 136 ++
> > > .../InternalIpmiBlobTransfer.h | 363 ++++++
> > > .../IpmiBlobTransferDxe/IpmiBlobTransferDxe.c | 799 ++++++++++++
> > > .../UnitTest/IpmiBlobTransferTestUnitTests.c | 1113
> +++++++++++++++++
> > > .../Universal/IpmiBlobTransferDxe/Readme.md | 24 +
> > > 9 files changed, 2523 insertions(+), 1 deletion(-)
> > > create mode 100644
> >
> Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransfer
> D
> > xe.inf
> > > create mode 100644
> >
> Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiBlo
> b
> > TransferTestUnitTestsHost.inf
> > > create mode 100644
> > Features/ManageabilityPkg/Include/Protocol/IpmiBlobTransfer.h
> > > create mode 100644
> >
> Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/InternalIpmiBlob
> Tr
> > ansfer.h
> > > create mode 100644
> >
> Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransfer
> D
> > xe.c
> > > create mode 100644
> >
> Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiBlo
> b
> > TransferTestUnitTests.c
> > > create mode 100644
> > Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/Readme.md
> > >
> > > diff --git a/Features/ManageabilityPkg/ManageabilityPkg.dec
> > b/Features/ManageabilityPkg/ManageabilityPkg.dec
> > > index 9a930d3e4b..e2d6cccc50 100644
> > > --- a/Features/ManageabilityPkg/ManageabilityPkg.dec
> > > +++ b/Features/ManageabilityPkg/ManageabilityPkg.dec
> > > @@ -4,6 +4,7 @@
> > > # those are related to the platform management.
> > > #
> > > # Copyright (C) 2023 Advanced Micro Devices, Inc. All rights
> reserved.<BR>
> > > +# Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights
> > reserved.
> > > # SPDX-License-Identifier: BSD-2-Clause-Patent
> > > #
> > > ##
> > > @@ -48,3 +49,8 @@
> > > gManageabilityProtocolMctpGuid = { 0x76FED8F1, 0x0BE5, 0x4269,
> > { 0xA3, 0x1A, 0x38, 0x0F, 0x54, 0xF1, 0xA1, 0x8A } }
> > > # Manageability Protocol PLDM
> > > gManageabilityProtocolPldmGuid = { 0x3958090D, 0x69DD, 0x4868,
> > { 0x9C, 0x41, 0xC9, 0xAC, 0x31, 0xB5, 0x25, 0xC5 } }
> > > +
> > > +[Protocols]
> > > +
> > > + ## Include/Protocol/IpmiBlobTransfer.h
> > > + gEdkiiIpmiBlobTransferProtocolGuid = { 0x05837c75, 0x1d65, 0x468b,
> > { 0xb1, 0xc2, 0x81, 0xaf, 0x9a, 0x31, 0x5b, 0x2c } }
> > > diff --git a/Features/ManageabilityPkg/Include/Dsc/Manageability.dsc
> > b/Features/ManageabilityPkg/Include/Dsc/Manageability.dsc
> > > index 0d868fdf4a..111d6b91dc 100644
> > > --- a/Features/ManageabilityPkg/Include/Dsc/Manageability.dsc
> > > +++ b/Features/ManageabilityPkg/Include/Dsc/Manageability.dsc
> > > @@ -2,11 +2,13 @@
> > > # Common libraries for Manageabilty Package
> > > #
> > > # Copyright (C) 2023 Advanced Micro Devices, Inc. All rights
> reserved.<BR>
> > > +# Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights
> > reserved.
> > > # SPDX-License-Identifier: BSD-2-Clause-Patent
> > > #
> > > ##
> > > [LibraryClasses]
> > >
> >
> ManageabilityTransportHelperLib|ManageabilityPkg/Library/BaseManageabili
> > tyTransportHelperLib/BaseManageabilityTransportHelper.inf
> > > +
> >
> IpmiLib|MdeModulePkg/Library/DxeIpmiLibIpmiProtocol/DxeIpmiLibIpmiPro
> t
> > ocol.inf
> > >
> > > [LibraryClasses.ARM, LibraryClasses.AARCH64]
> > > #
> > > @@ -22,4 +24,4 @@
> > > [Components.X64]
> > > ManageabilityPkg/Universal/IpmiProtocol/Dxe/IpmiProtocolDxe.inf
> > > ManageabilityPkg/Universal/IpmiProtocol/Smm/IpmiProtocolSmm.inf
> > > -
> > > +
> ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransferDxe.inf
> > > diff --git
> >
> a/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransf
> e
> > rDxe.inf
> >
> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransf
> e
> > rDxe.inf
> > > new file mode 100644
> > > index 0000000000..28e9d293c1
> > > --- /dev/null
> > > +++
> >
> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransf
> e
> > rDxe.inf
> > > @@ -0,0 +1,39 @@
> > > +## @file
> > > +# IPMI Blob Transfer Protocol DXE Driver.
> > > +#
> > > +# Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All
> rights
> > reserved.
> > > +#
> > > +# SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +#
> > > +
> > > +[Defines]
> > > + INF_VERSION = 0x00010005
> > > + BASE_NAME = IpmiBlobTransferDxe
> > > + FILE_GUID = 6357c804-78bb-4b0c-abdf-c75df942f319
> > > + MODULE_TYPE = DXE_DRIVER
> > > + VERSION_STRING = 1.0
> > > + ENTRY_POINT = IpmiBlobTransferDxeDriverEntryPoint
> > > +
> > > +[Sources.common]
> > > + IpmiBlobTransferDxe.c
> > > +
> > > +[LibraryClasses]
> > > + BaseLib
> > > + BaseMemoryLib
> > > + DebugLib
> > > + IpmiLib
> > > + MemoryAllocationLib
> > > + PcdLib
> > > + UefiBootServicesTableLib
> > > + UefiDriverEntryPoint
> > > +
> > > +[Packages]
> > > + MdePkg/MdePkg.dec
> > > + MdeModulePkg/MdeModulePkg.dec
> > > + ManageabilityPkg/ManageabilityPkg.dec
> > > +
> > > +[Protocols]
> > > + gEdkiiIpmiBlobTransferProtocolGuid
> > > +
> > > +[Depex]
> > > + TRUE
> > > diff --git
> >
> a/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiB
> l
> > obTransferTestUnitTestsHost.inf
> >
> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiB
> l
> > obTransferTestUnitTestsHost.inf
> > > new file mode 100644
> > > index 0000000000..1f071bbadc
> > > --- /dev/null
> > > +++
> >
> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiB
> l
> > obTransferTestUnitTestsHost.inf
> > > @@ -0,0 +1,40 @@
> > > +## @file
> > > +# Unit tests of the Ipmi blob transfer driver that are run from a host
> > environment.
> > > +#
> > > +# Copyright (c) 2020-2023, NVIDIA CORPORATION & AFFILIATES. All
> rights
> > reserved.
> > > +#
> > > +# SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +##
> > > +
> > > +[Defines]
> > > + INF_VERSION = 0x00010006
> > > + BASE_NAME = IpmiBlobTransferDxeUnitTestsHost
> > > + FILE_GUID = 1f5d4095-ea52-432c-b078-86097fef6004
> > > + MODULE_TYPE = HOST_APPLICATION
> > > + VERSION_STRING = 1.0
> > > +
> > > +#
> > > +# The following information is for reference only
> > > +# and not required by the build tools.
> > > +#
> > > +# VALID_ARCHITECTURES = X64
> > > +#
> > > +
> > > +[Sources]
> > > + IpmiBlobTransferTestUnitTests.c
> > > +
> > > +[Packages]
> > > + MdePkg/MdePkg.dec
> > > + MdeModulePkg/MdeModulePkg.dec
> > > + ManageabilityPkg/ManageabilityPkg.dec
> > > + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
> > > +
> > > +[LibraryClasses]
> > > + BaseLib
> > > + BaseMemoryLib
> > > + DebugLib
> > > + UnitTestLib
> > > + IpmiLib
> > > +
> > > +[Protocols]
> > > + gEdkiiIpmiBlobTransferProtocolGuid
> > > diff --git
> a/Features/ManageabilityPkg/Include/Protocol/IpmiBlobTransfer.h
> > b/Features/ManageabilityPkg/Include/Protocol/IpmiBlobTransfer.h
> > > new file mode 100644
> > > index 0000000000..8ea71d8816
> > > --- /dev/null
> > > +++ b/Features/ManageabilityPkg/Include/Protocol/IpmiBlobTransfer.h
> > > @@ -0,0 +1,136 @@
> > > +/** @file
> > > +
> > > + IPMI Blob Transfer driver
> > > +
> > > + Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights
> > reserved.
> > > +
> > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +
> > > +**/
> > > +#include <Library/IpmiLib.h>
> > > +#include <Library/UefiBootServicesTableLib.h>
> > > +#include <IndustryStandard/Ipmi.h>
> > > +
> > > +#define IPMI_NETFN_OEM 0x2E
> > > +#define IPMI_OEM_BLOB_TRANSFER_CMD 0x80
> > > +#define IPMI_OEM_BLOB_MAX_DATA_PER_PACKET 64
> > > +
> > > +#define BLOB_TRANSFER_STAT_OPEN_R BIT0
> > > +#define BLOB_TRANSFER_STAT_OPEN_W BIT1
> > > +#define BLOB_TRANSFER_STAT_COMMITING BIT2
> > > +#define BLOB_TRANSFER_STAT_COMMITTED BIT3
> > > +#define BLOB_TRANSFER_STAT_COMMIT_ERROR BIT4
> > > +// Bits 5-7 are reserved
> > > +// Bits 8-15 are blob-specific definitions
> > > +
> > > +//
> > > +// Blob Transfer Function Prototypes
> > > +//
> > > +typedef
> > > +EFI_STATUS
> > > +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_GET_COUNT)(
> > > + OUT UINT32 *Count
> > > + );
> > > +
> > > +typedef
> > > +EFI_STATUS
> > > +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_ENUMERATE)(
> > > + IN UINT32 BlobIndex,
> > > + OUT CHAR8 *BlobId
> > > + );
> > > +
> > > +typedef
> > > +EFI_STATUS
> > > +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_OPEN)(
> > > + IN CHAR8 *BlobId,
> > > + IN UINT16 Flags,
> > > + OUT UINT16 *SessionId
> > > + );
> > > +
> > > +typedef
> > > +EFI_STATUS
> > > +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_READ)(
> > > + IN UINT16 SessionId,
> > > + IN UINT32 Offset,
> > > + IN UINT32 RequestedSize,
> > > + OUT UINT8 *Data
> > > + );
> > > +
> > > +typedef
> > > +EFI_STATUS
> > > +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_WRITE)(
> > > + IN UINT16 SessionId,
> > > + IN UINT32 Offset,
> > > + IN UINT8 *Data,
> > > + IN UINT32 WriteLength
> > > + );
> > > +
> > > +typedef
> > > +EFI_STATUS
> > > +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_COMMIT)(
> > > + IN UINT16 SessionId,
> > > + IN UINT8 CommitDataLength,
> > > + IN UINT8 *CommitData
> > > + );
> > > +
> > > +typedef
> > > +EFI_STATUS
> > > +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_CLOSE)(
> > > + IN UINT16 SessionId
> > > + );
> > > +
> > > +typedef
> > > +EFI_STATUS
> > > +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_DELETE)(
> > > + IN CHAR8 *BlobId
> > > + );
> > > +
> > > +typedef
> > > +EFI_STATUS
> > > +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_STAT)(
> > > + IN CHAR8 *BlobId,
> > > + OUT UINT16 *BlobState,
> > > + OUT UINT32 *Size,
> > > + OUT UINT8 *MetadataLength,
> > > + OUT UINT8 *Metadata
> > > + );
> > > +
> > > +typedef
> > > +EFI_STATUS
> > > +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_SESSION_STAT)(
> > > + IN UINT16 SessionId,
> > > + OUT UINT16 *BlobState,
> > > + OUT UINT32 *Size,
> > > + OUT UINT8 *MetadataLength,
> > > + OUT UINT8 *Metadata
> > > + );
> > > +
> > > +typedef
> > > +EFI_STATUS
> > > +(EFIAPI *IPMI_BLOB_TRANSFER_PROTOCOL_WRITE_META)(
> > > + IN UINT16 SessionId,
> > > + IN UINT32 Offset,
> > > + IN UINT8 *Data,
> > > + IN UINT32 WriteLength
> > > + );
> > > +
> > > +//
> > > +// Structure of IPMI_BLOB_TRANSFER_PROTOCOL
> > > +//
> > > +struct _IPMI_BLOB_TRANSFER_PROTOCOL {
> > > + IPMI_BLOB_TRANSFER_PROTOCOL_GET_COUNT BlobGetCount;
> > > + IPMI_BLOB_TRANSFER_PROTOCOL_ENUMERATE BlobEnumerate;
> > > + IPMI_BLOB_TRANSFER_PROTOCOL_OPEN BlobOpen;
> > > + IPMI_BLOB_TRANSFER_PROTOCOL_READ BlobRead;
> > > + IPMI_BLOB_TRANSFER_PROTOCOL_WRITE BlobWrite;
> > > + IPMI_BLOB_TRANSFER_PROTOCOL_COMMIT BlobCommit;
> > > + IPMI_BLOB_TRANSFER_PROTOCOL_CLOSE BlobClose;
> > > + IPMI_BLOB_TRANSFER_PROTOCOL_DELETE BlobDelete;
> > > + IPMI_BLOB_TRANSFER_PROTOCOL_STAT BlobStat;
> > > + IPMI_BLOB_TRANSFER_PROTOCOL_SESSION_STAT BlobSessionStat;
> > > + IPMI_BLOB_TRANSFER_PROTOCOL_WRITE_META BlobWriteMeta;
> > > +};
> > > +
> > > +typedef struct _IPMI_BLOB_TRANSFER_PROTOCOL
> > IPMI_BLOB_TRANSFER_PROTOCOL;
> > > +
> > > +extern EFI_GUID gEdkiiIpmiBlobTransferProtocolGuid;
> > > diff --git
> >
> a/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/InternalIpmiBlo
> > bTransfer.h
> >
> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/InternalIpmiBl
> o
> > bTransfer.h
> > > new file mode 100644
> > > index 0000000000..14f0dc02bc
> > > --- /dev/null
> > > +++
> >
> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/InternalIpmiBl
> o
> > bTransfer.h
> > > @@ -0,0 +1,363 @@
> > > +/** @file
> > > +
> > > + Headers for IPMI Blob Transfer driver
> > > +
> > > + Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights
> > reserved.
> > > +
> > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +
> > > +**/
> > > +
> > > +#include <Library/BaseLib.h>
> > > +#include <Library/BaseMemoryLib.h>
> > > +#include <Library/DebugLib.h>
> > > +#include <Library/IpmiLib.h>
> > > +#include <Library/MemoryAllocationLib.h>
> > > +#include <Library/PcdLib.h>
> > > +
> > > +#define PROTOCOL_RESPONSE_OVERHEAD (4 * sizeof(UINT8)) // 1
> byte
> > completion code + 3 bytes OEN
> > > +
> > > +// Subcommands for this protocol
> > > +typedef enum {
> > > + IpmiBlobTransferSubcommandGetCount = 0,
> > > + IpmiBlobTransferSubcommandEnumerate,
> > > + IpmiBlobTransferSubcommandOpen,
> > > + IpmiBlobTransferSubcommandRead,
> > > + IpmiBlobTransferSubcommandWrite,
> > > + IpmiBlobTransferSubcommandCommit,
> > > + IpmiBlobTransferSubcommandClose,
> > > + IpmiBlobTransferSubcommandDelete,
> > > + IpmiBlobTransferSubcommandStat,
> > > + IpmiBlobTransferSubcommandSessionStat,
> > > + IpmiBlobTransferSubcommandWriteMeta,
> > > +} IPMI_BLOB_TRANSFER_SUBCOMMANDS;
> > > +
> > > +#pragma pack(1)
> > > +
> > > +typedef struct {
> > > + UINT8 OEN[3];
> > > + UINT8 SubCommand;
> > > +} IPMI_BLOB_TRANSFER_HEADER;
> > > +
> > > +//
> > > +// Command 0 - BmcBlobGetCount
> > > +// The BmcBlobGetCount command expects to receive an empty body.
> > > +// The BMC will return the number of enumerable blobs
> > > +//
> > > +typedef struct {
> > > + UINT32 BlobCount;
> > > +} IPMI_BLOB_TRANSFER_GET_COUNT_RESPONSE;
> > > +
> > > +//
> > > +// Command 1 - BmcBlobEnumerate
> > > +// The BmcBlobEnumerate command expects to receive a body of:
> > > +//
> > > +typedef struct {
> > > + UINT32 BlobIndex; // 0-based index of blob to receive
> > > +} IPMI_BLOB_TRANSFER_BLOB_ENUMERATE_SEND_DATA;
> > > +
> > > +typedef struct {
> > > + CHAR8 BlobId[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET];
> > > +} IPMI_BLOB_TRANSFER_BLOB_ENUMERATE_RESPONSE;
> > > +
> > > +//
> > > +// Command 2 - BmcBlobOpen
> > > +// The BmcBlobOpen command expects to receive a body of:
> > > +//
> > > +typedef struct {
> > > + UINT16 Flags;
> > > + CHAR8 BlobId[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET];
> > > +} IPMI_BLOB_TRANSFER_BLOB_OPEN_SEND_DATA;
> > > +
> > > +#define BLOB_OPEN_FLAG_READ 0
> > > +#define BLOB_OPEN_FLAG_WRITE 1
> > > +// Bits 2-7 are reserved
> > > +// Bits 8-15 are blob-specific definitions
> > > +
> > > +typedef struct {
> > > + UINT16 SessionId;
> > > +} IPMI_BLOB_TRANSFER_BLOB_OPEN_RESPONSE;
> > > +
> > > +//
> > > +// Command 3 - BmcBlobRead
> > > +// The BmcBlobRead command expects to receive a body of:
> > > +//
> > > +typedef struct {
> > > + UINT16 SessionId; // Returned from BlobOpen
> > > + UINT32 Offset;
> > > + UINT32 RequestedSize;
> > > +} IPMI_BLOB_TRANSFER_BLOB_READ_SEND_DATA;
> > > +
> > > +typedef struct {
> > > + UINT8 Data[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET];
> > > +} IPMI_BLOB_TRANSFER_BLOB_READ_RESPONSE;
> > > +
> > > +//
> > > +// Command 4 - BmcBlobWrite
> > > +// The BmcBlobWrite command expects to receive a body of:
> > > +//
> > > +typedef struct {
> > > + UINT16 SessionId; // Returned from BlobOpen
> > > + UINT32 Offset;
> > > + UINT8 Data[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET];
> > > +} IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA;
> > > +
> > > +//
> > > +// Command 5 - BmcBlobCommit
> > > +// The BmcBlobCommit command expects to receive a body of:
> > > +//
> > > +typedef struct {
> > > + UINT16 SessionId; // Returned from BlobOpen
> > > + UINT8 CommitDataLength;
> > > + UINT8 CommitData[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET];
> > > +} IPMI_BLOB_TRANSFER_BLOB_COMMIT_SEND_DATA;
> > > +
> > > +//
> > > +// Command 6 - BmcBlobClose
> > > +// The BmcBlobClose command expects to receive a body of:
> > > +//
> > > +typedef struct {
> > > + UINT16 SessionId; // Returned from BlobOpen
> > > +} IPMI_BLOB_TRANSFER_BLOB_CLOSE_SEND_DATA;
> > > +
> > > +//
> > > +// Command 7 - BmcBlobDelete
> > > +// NOTE: This command will fail if there are open sessions for this blob
> > > +// The BmcBlobDelete command expects to receive a body of:
> > > +//
> > > +typedef struct {
> > > + CHAR8 BlobId[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET];
> > > +} IPMI_BLOB_TRANSFER_BLOB_DELETE_SEND_DATA;
> > > +
> > > +//
> > > +// Command 8 - BmcBlobStat
> > > +// This command returns statistics about a blob.
> > > +// This command expects to receive a body of:
> > > +//
> > > +typedef struct {
> > > + CHAR8 BlobId[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET];
> > > +} IPMI_BLOB_TRANSFER_BLOB_STAT_SEND_DATA;
> > > +
> > > +typedef struct {
> > > + UINT16 BlobState;
> > > + UINT32 Size; // Size in bytes of the blob
> > > + UINT8 MetaDataLen;
> > > + UINT8 MetaData[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET];
> > > +} IPMI_BLOB_TRANSFER_BLOB_STAT_RESPONSE;
> > > +
> > > +//
> > > +// Command 9 - BmcBlobSessionStat
> > > +// Returns same data as BmcBlobState expect for a session, not a blob
> > > +// This command expects to receive a body of:
> > > +//
> > > +typedef struct {
> > > + UINT16 SessionId;
> > > +} IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_SEND_DATA;
> > > +
> > > +typedef struct {
> > > + UINT16 BlobState;
> > > + UINT32 Size; // Size in bytes of the blob
> > > + UINT8 MetaDataLen;
> > > + UINT8 MetaData[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET];
> > > +} IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_RESPONSE;
> > > +
> > > +//
> > > +// Command 10 - BmcBlobWriteMeta
> > > +// The BmcBlobWriteMeta command expects to receive a body of:
> > > +//
> > > +typedef struct {
> > > + UINT16 SessionId;
> > > + UINT32 Offset;
> > > + UINT8 Data[IPMI_OEM_BLOB_MAX_DATA_PER_PACKET];
> > > +} IPMI_BLOB_TRANSFER_BLOB_WRITE_META_SEND_DATA;
> > > +
> > > +#define IPMI_BLOB_TRANSFER_BLOB_WRITE_META_RESPONSE NULL
> > > +
> > > +#pragma pack()
> > > +
> > > +/**
> > > + Calculate CRC-16-CCITT with poly of 0x1021
> > > +
> > > + @param[in] Data The target data.
> > > + @param[in] DataSize The target data size.
> > > +
> > > + @return UINT16 The CRC16 value.
> > > +
> > > +**/
> > > +UINT16
> > > +CalculateCrc16 (
> > > + IN UINT8 *Data,
> > > + IN UINTN DataSize
> > > + );
> > > +
> > > +EFI_STATUS
> > > +IpmiBlobTransferSendIpmi (
> > > + IN UINT8 SubCommand,
> > > + IN UINT8 *SendData,
> > > + IN UINT32 SendDataSize,
> > > + OUT UINT8 *ResponseData,
> > > + OUT UINT32 *ResponseDataSize
> > > + );
> > > +
> > > +/**
> > > + @param[out] Count The number of active blobs
> > > +
> > > + @retval EFI_SUCCESS Successfully retrieved the number of active
> > blobs.
> > > + @retval Other An error occurred
> > > +**/
> > > +EFI_STATUS
> > > +IpmiBlobTransferGetCount (
> > > + OUT UINT32 *Count
> > > + );
> > > +
> > > +/**
> > > + @param[in] BlobIndex The 0-based Index of the blob to
> enumerate
> > > + @param[out] BlobId The ID of the blob
> > > +
> > > + @retval EFI_SUCCESS Successfully enumerated the blob.
> > > + @retval Other An error occurred
> > > +**/
> > > +EFI_STATUS
> > > +IpmiBlobTransferEnumerate (
> > > + IN UINT32 BlobIndex,
> > > + OUT CHAR8 *BlobId
> > > + );
> > > +
> > > +/**
> > > + @param[in] BlobId The ID of the blob to open
> > > + @param[in] Flags Flags to control how the blob is opened
> > > + @param[out] SessionId A unique session identifier
> > > +
> > > + @retval EFI_SUCCESS Successfully opened the blob.
> > > + @retval Other An error occurred
> > > +**/
> > > +EFI_STATUS
> > > +IpmiBlobTransferOpen (
> > > + IN CHAR8 *BlobId,
> > > + IN UINT16 Flags,
> > > + OUT UINT16 *SessionId
> > > + );
> > > +
> > > +/**
> > > + @param[in] SessionId The session ID returned from a call to
> > BlobOpen
> > > + @param[in] Offset The offset of the blob from which to start
> > reading
> > > + @param[in] RequestedSize The length of data to read
> > > + @param[out] Data Data read from the blob
> > > +
> > > + @retval EFI_SUCCESS Successfully read from the blob.
> > > + @retval Other An error occurred
> > > +**/
> > > +EFI_STATUS
> > > +IpmiBlobTransferRead (
> > > + IN UINT16 SessionId,
> > > + IN UINT32 Offset,
> > > + IN UINT32 RequestedSize,
> > > + OUT UINT8 *Data
> > > + );
> > > +
> > > +/**
> > > + @param[in] SessionId The session ID returned from a call to
> > BlobOpen
> > > + @param[in] Offset The offset of the blob from which to start
> > writing
> > > + @param[in] Data A pointer to the data to write
> > > +
> > > + @retval EFI_SUCCESS Successfully wrote to the blob.
> > > + @retval Other An error occurred
> > > +**/
> > > +EFI_STATUS
> > > +IpmiBlobTransferWrite (
> > > + IN UINT16 SessionId,
> > > + IN UINT32 Offset,
> > > + IN UINT8 *Data,
> > > + IN UINT32 WriteLength
> > > + );
> > > +
> > > +/**
> > > + @param[in] SessionId The session ID returned from a call to
> > BlobOpen
> > > + @param[in] CommitDataLength The length of data to commit to the
> > blob
> > > + @param[in] CommitData A pointer to the data to commit
> > > +
> > > + @retval EFI_SUCCESS Successful commit to the blob.
> > > + @retval Other An error occurred
> > > +**/
> > > +EFI_STATUS
> > > +IpmiBlobTransferCommit (
> > > + IN UINT16 SessionId,
> > > + IN UINT8 CommitDataLength,
> > > + IN UINT8 *CommitData
> > > + );
> > > +
> > > +/**
> > > + @param[in] SessionId The session ID returned from a call to
> > BlobOpen
> > > +
> > > + @retval EFI_SUCCESS The blob was closed.
> > > + @retval Other An error occurred
> > > +**/
> > > +EFI_STATUS
> > > +IpmiBlobTransferClose (
> > > + IN UINT16 SessionId
> > > + );
> > > +
> > > +/**
> > > + @param[in] BlobId The BlobId to be deleted
> > > +
> > > + @retval EFI_SUCCESS The blob was deleted.
> > > + @retval Other An error occurred
> > > +**/
> > > +EFI_STATUS
> > > +IpmiBlobTransferDelete (
> > > + IN CHAR8 *BlobId
> > > + );
> > > +
> > > +/**
> > > + @param[in] BlobId The Blob ID to gather statistics 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 successfully
> > gathered.
> > > + @retval Other An error occurred
> > > +**/
> > > +EFI_STATUS
> > > +IpmiBlobTransferStat (
> > > + IN CHAR8 *BlobId,
> > > + OUT UINT16 *BlobState,
> > > + OUT UINT32 *Size,
> > > + OUT UINT8 *MetadataLength,
> > > + OUT UINT8 *Metadata
> > > + );
> > > +
> > > +/**
> > > + @param[in] SessionId The ID of the session to gather statistics for
> > > + @param[out] BlobState The current state of the blob
> > > + @param[out] Size Size in bytes of the blob
> > > + @param[out] MetadataLength Length of the optional metadata
> > > + @param[out] Metadata Optional blob-specific metadata
> > > +
> > > + @retval EFI_SUCCESS The blob statistics were successfully
> > gathered.
> > > + @retval Other An error occurred
> > > +**/
> > > +EFI_STATUS
> > > +IpmiBlobTransferSessionStat (
> > > + IN UINT16 SessionId,
> > > + OUT UINT16 *BlobState,
> > > + OUT UINT32 *Size,
> > > + OUT UINT8 *MetadataLength,
> > > + OUT UINT8 *Metadata
> > > + );
> > > +
> > > +/**
> > > + @param[in] SessionId The ID of the session to write metadata for
> > > + @param[in] Offset The offset of the metadata to write to
> > > + @param[in] Data The data to write to the metadata
> > > +
> > > + @retval EFI_SUCCESS The blob metadata was successfully
> written.
> > > + @retval Other An error occurred
> > > +**/
> > > +EFI_STATUS
> > > +IpmiBlobTransferWriteMeta (
> > > + IN UINT16 SessionId,
> > > + IN UINT32 Offset,
> > > + IN UINT8 *Data,
> > > + IN UINT32 WriteLength
> > > + );
> > > diff --git
> >
> a/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransf
> e
> > rDxe.c
> >
> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransf
> e
> > rDxe.c
> > > new file mode 100644
> > > index 0000000000..9e663289d5
> > > --- /dev/null
> > > +++
> >
> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransf
> e
> > rDxe.c
> > > @@ -0,0 +1,799 @@
> > > +/** @file
> > > +
> > > + IPMI Blob Transfer driver
> > > +
> > > + Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights
> > reserved.
> > > +
> > > + SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +
> > > +**/
> > > +#include <Protocol/IpmiBlobTransfer.h>
> > > +
> > > +#include "InternalIpmiBlobTransfer.h"
> > > +
> > > +#define BLOB_TRANSFER_DEBUG 0
> > > +
> > > +STATIC CONST IPMI_BLOB_TRANSFER_PROTOCOL mIpmiBlobTransfer = {
> > > +
> >
> (IPMI_BLOB_TRANSFER_PROTOCOL_GET_COUNT)*IpmiBlobTransferGetCoun
> t,
> > > +
> >
> (IPMI_BLOB_TRANSFER_PROTOCOL_ENUMERATE)*IpmiBlobTransferEnumera
> t
> > e,
> > > + (IPMI_BLOB_TRANSFER_PROTOCOL_OPEN)*IpmiBlobTransferOpen,
> > > + (IPMI_BLOB_TRANSFER_PROTOCOL_READ)*IpmiBlobTransferRead,
> > > + (IPMI_BLOB_TRANSFER_PROTOCOL_WRITE)*IpmiBlobTransferWrite,
> > > +
> (IPMI_BLOB_TRANSFER_PROTOCOL_COMMIT)*IpmiBlobTransferCommit,
> > > + (IPMI_BLOB_TRANSFER_PROTOCOL_CLOSE)*IpmiBlobTransferClose,
> > > + (IPMI_BLOB_TRANSFER_PROTOCOL_DELETE)*IpmiBlobTransferDelete,
> > > + (IPMI_BLOB_TRANSFER_PROTOCOL_STAT)*IpmiBlobTransferStat,
> > > +
> >
> (IPMI_BLOB_TRANSFER_PROTOCOL_SESSION_STAT)*IpmiBlobTransferSession
> S
> > tat,
> > > +
> >
> (IPMI_BLOB_TRANSFER_PROTOCOL_WRITE_META)*IpmiBlobTransferWriteM
> e
> > ta
> > > +};
> > > +
> > > +const UINT8 OpenBmcOen[] = { 0xCF, 0xC2, 0x00 }; // OpenBMC
> OEN
> > code in little endian format
> > > +
> > > +/**
> > > + Calculate CRC-16-CCITT with poly of 0x1021
> > > +
> > > + @param[in] Data The target data.
> > > + @param[in] DataSize The target data size.
> > > +
> > > + @return UINT16 The CRC16 value.
> > > +
> > > +**/
> > > +UINT16
> > > +CalculateCrc16 (
> > > + IN UINT8 *Data,
> > > + IN UINTN DataSize
> > > + )
> > > +{
> > > + UINTN Index;
> > > + UINTN BitIndex;
> > > + UINT16 Crc = 0xFFFF;
> > > + UINT16 Poly = 0x1021;
> > > + BOOLEAN XorFlag = FALSE;
> > > +
> > > + for (Index = 0; Index < (DataSize + 2); ++Index) {
> > > + for (BitIndex = 0; BitIndex < 8; ++BitIndex) {
> > > + XorFlag = (Crc & 0x8000) ? TRUE : FALSE;
> > > + Crc <<= 1;
> > > + if ((Index < DataSize) && (Data[Index] & (1 << (7 - BitIndex)))) {
> > > + Crc++;
> > > + }
> > > +
> > > + if (XorFlag == TRUE) {
> > > + Crc ^= Poly;
> > > + }
> > > + }
> > > + }
> > > +
> > > + #if BLOB_TRANSFER_DEBUG
> > > + DEBUG ((DEBUG_INFO, "%a: CRC-16-CCITT %x\n", __FUNCTION__,
> Crc));
> > > + #endif
> > > +
> > > + return Crc;
> > > +}
> > > +
> > > +EFI_STATUS
> > > +IpmiBlobTransferSendIpmi (
> > > + IN UINT8 SubCommand,
> > > + IN UINT8 *SendData,
> > > + IN UINT32 SendDataSize,
> > > + OUT UINT8 *ResponseData,
> > > + OUT UINT32 *ResponseDataSize
> > > + )
> > > +{
> > > + EFI_STATUS Status;
> > > + UINT8 CompletionCode;
> > > + UINT16 Crc;
> > > + UINT8 Oen[3];
> > > + UINT8 *IpmiSendData;
> > > + UINT32 IpmiSendDataSize;
> > > + UINT8 *IpmiResponseData;
> > > + UINT8 *ModifiedResponseData;
> > > + UINT32 IpmiResponseDataSize;
> > > + IPMI_BLOB_TRANSFER_HEADER Header;
> > > +
> > > + Crc = 0;
> > > +
> > > + //
> > > + // Prepend the proper header to the SendData
> > > + //
> > > + IpmiSendDataSize = (sizeof (IPMI_BLOB_TRANSFER_HEADER));
> > > + if (SendDataSize) {
> > > + IpmiSendDataSize += sizeof (Crc) + (sizeof (UINT8) * SendDataSize);
> > > + }
> > > +
> > > + IpmiSendData = AllocateZeroPool (IpmiSendDataSize);
> > > + if (IpmiSendData == NULL) {
> > > + return EFI_OUT_OF_RESOURCES;
> > > + }
> > > +
> > > + Header.OEN[0] = OpenBmcOen[0];
> > > + Header.OEN[1] = OpenBmcOen[1];
> > > + Header.OEN[2] = OpenBmcOen[2];
> > > + Header.SubCommand = SubCommand;
> > > + CopyMem (IpmiSendData, &Header, sizeof
> > (IPMI_BLOB_TRANSFER_HEADER));
> > > + if (SendDataSize) {
> > > + //
> > > + // Calculate the Crc of the send data
> > > + //
> > > + Crc = CalculateCrc16 (SendData, SendDataSize);
> > > + CopyMem (IpmiSendData + sizeof (IPMI_BLOB_TRANSFER_HEADER),
> > &Crc, sizeof (UINT16));
> > > + CopyMem (IpmiSendData + sizeof (IPMI_BLOB_TRANSFER_HEADER) +
> > sizeof (UINT16), SendData, SendDataSize);
> > > + }
> > > +
> > > + #if BLOB_TRANSFER_DEBUG
> > > + DEBUG ((DEBUG_INFO, "%a: Inputs:\n", __FUNCTION__));
> > > + DEBUG ((DEBUG_INFO, "%a: SendDataSize: %02x\nData: ",
> > __FUNCTION__, SendDataSize));
> > > + UINT8 i;
> > > + for (i = 0; i < SendDataSize; i++) {
> > > + DEBUG ((DEBUG_INFO, "%02x", *((UINT8 *)SendData + i)));
> > > + }
> > > +
> > > + DEBUG ((DEBUG_INFO, "\n"));
> > > + DEBUG ((DEBUG_INFO, "%a: IpmiSendDataSize: %02x\nData: ",
> > __FUNCTION__, IpmiSendDataSize));
> > > + for (i = 0; i < IpmiSendDataSize; i++) {
> > > + DEBUG ((DEBUG_INFO, "%02x", *((UINT8 *)IpmiSendData + i)));
> > > + }
> > > +
> > > + DEBUG ((DEBUG_INFO, "\n"));
> > > + #endif
> > > +
> > > + IpmiResponseDataSize = (*ResponseDataSize +
> > PROTOCOL_RESPONSE_OVERHEAD);
> > > + //
> > > + // If expecting data to be returned, we have to also account for the 16 bit
> > CRC
> > > + //
> > > + if (*ResponseDataSize) {
> > > + IpmiResponseDataSize += sizeof (Crc);
> > > + }
> > > +
> > > + IpmiResponseData = AllocateZeroPool (IpmiResponseDataSize);
> > > + if (IpmiResponseData == NULL) {
> > > + return EFI_OUT_OF_RESOURCES;
> > > + }
> > > +
> > > + Status = IpmiSubmitCommand (
> > > + IPMI_NETFN_OEM,
> > > + IPMI_OEM_BLOB_TRANSFER_CMD,
> > > + (VOID *)IpmiSendData,
> > > + IpmiSendDataSize,
> > > + (VOID *)IpmiResponseData,
> > > + &IpmiResponseDataSize
> > > + );
> > > +
> > > + FreePool (IpmiSendData);
> > > + ModifiedResponseData = IpmiResponseData;
> > > +
> > > + #if BLOB_TRANSFER_DEBUG
> > > + DEBUG ((DEBUG_INFO, "%a: IPMI Response:\n", __FUNCTION__));
> > > + DEBUG ((DEBUG_INFO, "%a: ResponseDataSize: %02x\nData: ",
> > __FUNCTION__, IpmiResponseDataSize));
> > > + for (i = 0; i < IpmiResponseDataSize; i++) {
> > > + DEBUG ((DEBUG_INFO, "%02x", *(ModifiedResponseData + i)));
> > > + }
> > > +
> > > + DEBUG ((DEBUG_INFO, "\n"));
> > > + #endif
> > > +
> > > + if (EFI_ERROR (Status)) {
> > > + return Status;
> > > + }
> > > +
> > > + CompletionCode = *ModifiedResponseData;
> > > + if (CompletionCode != IPMI_COMP_CODE_NORMAL) {
> > > + DEBUG ((DEBUG_ERROR, "%a: Returning because CompletionCode =
> > 0x%x\n", __FUNCTION__, CompletionCode));
> > > + FreePool (IpmiResponseData);
> > > + return EFI_PROTOCOL_ERROR;
> > > + }
> > > +
> > > + // Strip completion code, we are done with it
> > > + ModifiedResponseData = ModifiedResponseData + sizeof
> > (CompletionCode);
> > > + IpmiResponseDataSize -= sizeof (CompletionCode);
> > > +
> > > + // Check OEN code and verify it matches the OpenBMC OEN
> > > + CopyMem (Oen, ModifiedResponseData, sizeof (OpenBmcOen));
> > > + if (CompareMem (Oen, OpenBmcOen, sizeof (OpenBmcOen)) != 0) {
> > > + FreePool (IpmiResponseData);
> > > + return EFI_PROTOCOL_ERROR;
> > > + }
> > > +
> > > + if (IpmiResponseDataSize == sizeof (OpenBmcOen)) {
> > > + //
> > > + // In this case, there was no response data sent. This is not an error.
> > > + // Some messages do not require a response.
> > > + //
> > > + *ResponseDataSize = 0;
> > > + FreePool (IpmiResponseData);
> > > + return Status;
> > > + // Now we need to validate the CRC then send the Response body back
> > > + } else {
> > > + // Strip the OEN, we are done with it now
> > > + ModifiedResponseData = ModifiedResponseData + sizeof (Oen);
> > > + IpmiResponseDataSize -= sizeof (Oen);
> > > + // Then validate the Crc
> > > + CopyMem (&Crc, ModifiedResponseData, sizeof (Crc));
> > > + ModifiedResponseData = ModifiedResponseData + sizeof (Crc);
> > > + IpmiResponseDataSize -= sizeof (Crc);
> > > +
> > > + if (Crc == CalculateCrc16 (ModifiedResponseData,
> IpmiResponseDataSize))
> > {
> > > + CopyMem (ResponseData, ModifiedResponseData,
> > IpmiResponseDataSize);
> > > + CopyMem (ResponseDataSize, &IpmiResponseDataSize, sizeof
> > (IpmiResponseDataSize));
> > > + FreePool (IpmiResponseData);
> > > + return EFI_SUCCESS;
> > > + } else {
> > > + FreePool (IpmiResponseData);
> > > + return EFI_CRC_ERROR;
> > > + }
> > > + }
> > > +}
> > > +
> > > +/**
> > > + @param[out] Count The number of active blobs
> > > +
> > > + @retval EFI_SUCCESS The command byte stream was successfully
> > submit to the device and a response was successfully received.
> > > + @retval EFI_PROTOCOL_ERROR The Ipmi command failed
> > > + @retval EFI_CRC_ERROR The Ipmi command returned a bad
> > checksum
> > > +**/
> > > +EFI_STATUS
> > > +IpmiBlobTransferGetCount (
> > > + OUT UINT32 *Count
> > > + )
> > > +{
> > > + EFI_STATUS Status;
> > > + UINT8 *ResponseData;
> > > + UINT32 ResponseDataSize;
> > > +
> > > + ResponseDataSize = sizeof
> > (IPMI_BLOB_TRANSFER_GET_COUNT_RESPONSE);
> > > + ResponseData = AllocateZeroPool (ResponseDataSize);
> > > + if (ResponseData == NULL) {
> > > + return EFI_OUT_OF_RESOURCES;
> > > + }
> > > +
> > > + Status = IpmiBlobTransferSendIpmi
> > (IpmiBlobTransferSubcommandGetCount, NULL, 0, (UINT8 *)ResponseData,
> > &ResponseDataSize);
> > > + if (!EFI_ERROR (Status)) {
> > > + *Count = ((IPMI_BLOB_TRANSFER_GET_COUNT_RESPONSE
> > *)ResponseData)->BlobCount;
> > > + }
> > > +
> > > + FreePool (ResponseData);
> > > + return Status;
> > > +}
> > > +
> > > +/**
> > > + @param[in] BlobIndex The 0-based Index of the blob to
> enumerate
> > > + @param[out] BlobId The ID of the blob
> > > +
> > > + @retval EFI_SUCCESS Successfully enumerated the blob.
> > > + @retval Other An error occurred
> > > +**/
> > > +EFI_STATUS
> > > +IpmiBlobTransferEnumerate (
> > > + IN UINT32 BlobIndex,
> > > + OUT CHAR8 *BlobId
> > > + )
> > > +{
> > > + EFI_STATUS Status;
> > > +
> > > + UINT8 *SendData;
> > > + UINT8 *ResponseData;
> > > + UINT32 SendDataSize;
> > > + UINT32 ResponseDataSize;
> > > +
> > > + if (BlobId == NULL) {
> > > + ASSERT (FALSE);
> > > + return EFI_ABORTED;
> > > + }
> > > +
> > > + ResponseDataSize = sizeof
> > (IPMI_BLOB_TRANSFER_BLOB_ENUMERATE_RESPONSE);
> > > + ResponseData = AllocateZeroPool (ResponseDataSize);
> > > + if (ResponseData == NULL) {
> > > + return EFI_OUT_OF_RESOURCES;
> > > + }
> > > +
> > > + //
> > > + // Format send data
> > > + //
> > > + SendDataSize = sizeof
> > (IPMI_BLOB_TRANSFER_BLOB_ENUMERATE_SEND_DATA);
> > > + SendData = AllocateZeroPool (SendDataSize);
> > > + if (SendData == NULL) {
> > > + return EFI_OUT_OF_RESOURCES;
> > > + }
> > > +
> > > + ((IPMI_BLOB_TRANSFER_BLOB_ENUMERATE_SEND_DATA *)SendData)-
> > >BlobIndex = BlobIndex;
> > > +
> > > + Status = IpmiBlobTransferSendIpmi
> > (IpmiBlobTransferSubcommandEnumerate, SendData, SendDataSize,
> (UINT8
> > *)ResponseData, &ResponseDataSize);
> > > + if (!EFI_ERROR (Status)) {
> > > + AsciiStrCpyS (BlobId, ResponseDataSize, (CHAR8 *)ResponseData);
> > > + }
> > > +
> > > + FreePool (ResponseData);
> > > + return Status;
> > > +}
> > > +
> > > +/**
> > > + @param[in] BlobId The ID of the blob to open
> > > + @param[in] Flags Flags to control how the blob is opened
> > > + @param[out] SessionId A unique session identifier
> > > +
> > > + @retval EFI_SUCCESS Successfully opened the blob.
> > > + @retval Other An error occurred
> > > +**/
> > > +EFI_STATUS
> > > +IpmiBlobTransferOpen (
> > > + IN CHAR8 *BlobId,
> > > + IN UINT16 Flags,
> > > + OUT UINT16 *SessionId
> > > + )
> > > +{
> > > + EFI_STATUS Status;
> > > + UINT8 *SendData;
> > > + UINT8 *ResponseData;
> > > + UINT32 SendDataSize;
> > > + UINT32 ResponseDataSize;
> > > + CHAR8 *BlobSearch;
> > > + UINT32 NumBlobs;
> > > + UINT16 Index;
> > > + BOOLEAN BlobFound;
> > > +
> > > + //
> > > + // Before opening a blob, need to check if it exists
> > > + //
> > > + Status = IpmiBlobTransferGetCount (&NumBlobs);
> > > + if (EFI_ERROR (Status) || (NumBlobs == 0)) {
> > > + if (Status == EFI_UNSUPPORTED) {
> > > + return Status;
> > > + }
> > > +
> > > + DEBUG ((DEBUG_ERROR, "%a: Could not find any blobs: %r\n",
> > __FUNCTION__, Status));
> > > + return EFI_NOT_FOUND;
> > > + }
> > > +
> > > + BlobSearch = AllocateZeroPool (sizeof (CHAR8) *
> > IPMI_OEM_BLOB_MAX_DATA_PER_PACKET);
> > > + if (BlobSearch == NULL) {
> > > + return EFI_OUT_OF_RESOURCES;
> > > + }
> > > +
> > > + BlobFound = FALSE;
> > > + for (Index = 0; Index < NumBlobs; Index++) {
> > > + Status = IpmiBlobTransferEnumerate (Index, BlobSearch);
> > > + if ((!EFI_ERROR (Status)) && (AsciiStrCmp (BlobSearch, BlobId) == 0)) {
> > > + BlobFound = TRUE;
> > > + break;
> > > + } else {
> > > + continue;
> > > + }
> > > + }
> > > +
> > > + if (!BlobFound) {
> > > + DEBUG ((DEBUG_ERROR, "%a: Could not find a blob that matches
> %s\n",
> > __FUNCTION__, BlobId));
> > > + FreePool (BlobSearch);
> > > + return EFI_NOT_FOUND;
> > > + }
> > > +
> > > + ResponseDataSize = sizeof
> > (IPMI_BLOB_TRANSFER_BLOB_OPEN_RESPONSE);
> > > + ResponseData = AllocateZeroPool (ResponseDataSize);
> > > + if (ResponseData == NULL) {
> > > + return EFI_OUT_OF_RESOURCES;
> > > + }
> > > +
> > > + //
> > > + // Format send data
> > > + //
> > > + SendDataSize = sizeof
> (((IPMI_BLOB_TRANSFER_BLOB_OPEN_SEND_DATA
> > *)SendData)->Flags) + ((AsciiStrLen (BlobId)) * sizeof (CHAR8)) + sizeof
> > (CHAR8);
> > > + SendData = AllocateZeroPool (SendDataSize);
> > > + if (SendData == 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
> =
> > Flags;
> > > + // append null char to SendData
> > > + SendData[SendDataSize-1] = 0;
> > > +
> > > + Status = IpmiBlobTransferSendIpmi
> (IpmiBlobTransferSubcommandOpen,
> > SendData, SendDataSize, (UINT8 *)ResponseData, &ResponseDataSize);
> > > + if (!EFI_ERROR (Status)) {
> > > + *SessionId = ((IPMI_BLOB_TRANSFER_BLOB_OPEN_RESPONSE
> > *)ResponseData)->SessionId;
> > > + }
> > > +
> > > + FreePool (ResponseData);
> > > + FreePool (SendData);
> > > + FreePool (BlobSearch);
> > > + return Status;
> > > +}
> > > +
> > > +/**
> > > + @param[in] SessionId The session ID returned from a call to
> > BlobOpen
> > > + @param[in] Offset The offset of the blob from which to start
> > reading
> > > + @param[in] RequestedSize The length of data to read
> > > + @param[out] Data Data read from the blob
> > > +
> > > + @retval EFI_SUCCESS Successfully read from the blob.
> > > + @retval Other An error occurred
> > > +**/
> > > +EFI_STATUS
> > > +IpmiBlobTransferRead (
> > > + IN UINT16 SessionId,
> > > + IN UINT32 Offset,
> > > + IN UINT32 RequestedSize,
> > > + OUT UINT8 *Data
> > > + )
> > > +{
> > > + EFI_STATUS Status;
> > > + UINT8 *SendData;
> > > + UINT8 *ResponseData;
> > > + UINT32 SendDataSize;
> > > + UINT32 ResponseDataSize;
> > > +
> > > + if (Data == NULL) {
> > > + ASSERT (FALSE);
> > > + return EFI_ABORTED;
> > > + }
> > > +
> > > + ResponseDataSize = RequestedSize * sizeof (UINT8);
> > > + ResponseData = AllocateZeroPool (ResponseDataSize);
> > > + if (ResponseData == NULL) {
> > > + return EFI_OUT_OF_RESOURCES;
> > > + }
> > > +
> > > + //
> > > + // Format send data
> > > + //
> > > + SendDataSize = sizeof
> (IPMI_BLOB_TRANSFER_BLOB_READ_SEND_DATA);
> > > + SendData = AllocateZeroPool (SendDataSize);
> > > + if (SendData == NULL) {
> > > + return EFI_OUT_OF_RESOURCES;
> > > + }
> > > +
> > > + ((IPMI_BLOB_TRANSFER_BLOB_READ_SEND_DATA *)SendData)-
> >SessionId
> > = SessionId;
> > > + ((IPMI_BLOB_TRANSFER_BLOB_READ_SEND_DATA *)SendData)->Offset
> > = Offset;
> > > + ((IPMI_BLOB_TRANSFER_BLOB_READ_SEND_DATA *)SendData)-
> > >RequestedSize = RequestedSize;
> > > +
> > > + Status = IpmiBlobTransferSendIpmi
> (IpmiBlobTransferSubcommandRead,
> > SendData, SendDataSize, (UINT8 *)ResponseData, &ResponseDataSize);
> > > + if (!EFI_ERROR (Status)) {
> > > + CopyMem (Data, ((IPMI_BLOB_TRANSFER_BLOB_READ_RESPONSE
> > *)ResponseData)->Data, ResponseDataSize * sizeof (UINT8));
> > > + }
> > > +
> > > + FreePool (ResponseData);
> > > + FreePool (SendData);
> > > + return Status;
> > > +}
> > > +
> > > +/**
> > > + @param[in] SessionId The session ID returned from a call to
> > BlobOpen
> > > + @param[in] Offset The offset of the blob from which to start
> > writing
> > > + @param[in] Data A pointer to the data to write
> > > +
> > > + @retval EFI_SUCCESS Successfully wrote to the blob.
> > > + @retval Other An error occurred
> > > +**/
> > > +EFI_STATUS
> > > +IpmiBlobTransferWrite (
> > > + IN UINT16 SessionId,
> > > + IN UINT32 Offset,
> > > + IN UINT8 *Data,
> > > + IN UINT32 WriteLength
> > > + )
> > > +{
> > > + EFI_STATUS Status;
> > > + UINT8 *SendData;
> > > + UINT32 SendDataSize;
> > > + UINT32 ResponseDataSize;
> > > +
> > > + //
> > > + // Format send data
> > > + //
> > > + SendDataSize = sizeof (SessionId) + sizeof (Offset) + WriteLength;
> > > + SendData = AllocateZeroPool (SendDataSize);
> > > + if (SendData == NULL) {
> > > + return EFI_OUT_OF_RESOURCES;
> > > + }
> > > +
> > > + ((IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA *)SendData)-
> > >SessionId = SessionId;
> > > + ((IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA *)SendData)-
> >Offset
> > = Offset;
> > > + CopyMem (((IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA
> > *)SendData)->Data, Data, sizeof (UINT8) * WriteLength);
> > > +
> > > + ResponseDataSize = 0;
> > > + Status = IpmiBlobTransferSendIpmi
> > (IpmiBlobTransferSubcommandWrite, SendData, SendDataSize, NULL,
> > &ResponseDataSize);
> > > +
> > > + FreePool (SendData);
> > > + return Status;
> > > +}
> > > +
> > > +/**
> > > + @param[in] SessionId The session ID returned from a call to
> > BlobOpen
> > > + @param[in] CommitDataLength The length of data to commit to the
> > blob
> > > + @param[in] CommitData A pointer to the data to commit
> > > +
> > > + @retval EFI_SUCCESS Successful commit to the blob.
> > > + @retval Other An error occurred
> > > +**/
> > > +EFI_STATUS
> > > +IpmiBlobTransferCommit (
> > > + IN UINT16 SessionId,
> > > + IN UINT8 CommitDataLength,
> > > + IN UINT8 *CommitData
> > > + )
> > > +{
> > > + EFI_STATUS Status;
> > > + UINT8 *SendData;
> > > + UINT32 SendDataSize;
> > > + UINT32 ResponseDataSize;
> > > +
> > > + //
> > > + // Format send data
> > > + //
> > > + SendDataSize = sizeof (SessionId) + sizeof (CommitDataLength) +
> > CommitDataLength;
> > > + SendData = AllocateZeroPool (SendDataSize);
> > > + if (SendData == NULL) {
> > > + return EFI_OUT_OF_RESOURCES;
> > > + }
> > > +
> > > + ((IPMI_BLOB_TRANSFER_BLOB_COMMIT_SEND_DATA *)SendData)-
> > >SessionId = SessionId;
> > > + ((IPMI_BLOB_TRANSFER_BLOB_COMMIT_SEND_DATA *)SendData)-
> > >CommitDataLength = CommitDataLength;
> > > + CopyMem (((IPMI_BLOB_TRANSFER_BLOB_COMMIT_SEND_DATA
> > *)SendData)->CommitData, CommitData, sizeof (UINT8) *
> > CommitDataLength);
> > > +
> > > + ResponseDataSize = 0;
> > > +
> > > + Status = IpmiBlobTransferSendIpmi
> > (IpmiBlobTransferSubcommandCommit, SendData, SendDataSize, NULL,
> > &ResponseDataSize);
> > > +
> > > + FreePool (SendData);
> > > + return Status;
> > > +}
> > > +
> > > +/**
> > > + @param[in] SessionId The session ID returned from a call to
> > BlobOpen
> > > +
> > > + @retval EFI_SUCCESS The blob was closed.
> > > + @retval Other An error occurred
> > > +**/
> > > +EFI_STATUS
> > > +IpmiBlobTransferClose (
> > > + IN UINT16 SessionId
> > > + )
> > > +{
> > > + EFI_STATUS Status;
> > > + UINT8 *SendData;
> > > + UINT32 SendDataSize;
> > > + UINT32 ResponseDataSize;
> > > +
> > > + //
> > > + // Format send data
> > > + //
> > > + SendDataSize = sizeof
> (IPMI_BLOB_TRANSFER_BLOB_CLOSE_SEND_DATA);
> > > + SendData = AllocateZeroPool (SendDataSize);
> > > + if (SendData == NULL) {
> > > + return EFI_OUT_OF_RESOURCES;
> > > + }
> > > +
> > > + ((IPMI_BLOB_TRANSFER_BLOB_CLOSE_SEND_DATA *)SendData)-
> > >SessionId = SessionId;
> > > +
> > > + ResponseDataSize = 0;
> > > +
> > > + Status = IpmiBlobTransferSendIpmi
> (IpmiBlobTransferSubcommandClose,
> > SendData, SendDataSize, NULL, &ResponseDataSize);
> > > +
> > > + FreePool (SendData);
> > > + return Status;
> > > +}
> > > +
> > > +/**
> > > + @param[in] BlobId The BlobId to be deleted
> > > +
> > > + @retval EFI_SUCCESS The blob was deleted.
> > > + @retval Other An error occurred
> > > +**/
> > > +EFI_STATUS
> > > +IpmiBlobTransferDelete (
> > > + IN CHAR8 *BlobId
> > > + )
> > > +{
> > > + EFI_STATUS Status;
> > > + UINT8 *SendData;
> > > + UINT32 SendDataSize;
> > > + UINT32 ResponseDataSize;
> > > +
> > > + //
> > > + // Format send data
> > > + //
> > > + SendDataSize = sizeof
> > (IPMI_BLOB_TRANSFER_BLOB_DELETE_SEND_DATA);
> > > + SendData = AllocateZeroPool (SendDataSize);
> > > + if (SendData == NULL) {
> > > + return EFI_OUT_OF_RESOURCES;
> > > + }
> > > +
> > > + AsciiStrCpyS (((IPMI_BLOB_TRANSFER_BLOB_DELETE_SEND_DATA
> > *)SendData)->BlobId, AsciiStrLen (BlobId), BlobId);
> > > +
> > > + ResponseDataSize = 0;
> > > +
> > > + Status = IpmiBlobTransferSendIpmi
> (IpmiBlobTransferSubcommandDelete,
> > SendData, SendDataSize, NULL, &ResponseDataSize);
> > > +
> > > + FreePool (SendData);
> > > + return Status;
> > > +}
> > > +
> > > +/**
> > > + @param[in] BlobId The Blob ID to gather statistics for
> > > + @param[out] BlobState The current state of the blob
> > > + @param[out] Size Size in bytes of the blob
> > > + @param[out] MetadataLength Length of the optional metadata
> > > + @param[out] Metadata Optional blob-specific metadata
> > > +
> > > + @retval EFI_SUCCESS The blob statistics were successfully
> > gathered.
> > > + @retval Other An error occurred
> > > +**/
> > > +EFI_STATUS
> > > +IpmiBlobTransferStat (
> > > + IN CHAR8 *BlobId,
> > > + OUT UINT16 *BlobState,
> > > + OUT UINT32 *Size,
> > > + OUT UINT8 *MetadataLength,
> > > + OUT UINT8 *Metadata
> > > + )
> > > +{
> > > + EFI_STATUS Status;
> > > + UINT8 *SendData;
> > > + UINT8 *ResponseData;
> > > + UINT32 SendDataSize;
> > > + UINT32 ResponseDataSize;
> > > +
> > > + if (Metadata == NULL) {
> > > + ASSERT (FALSE);
> > > + return EFI_ABORTED;
> > > + }
> > > +
> > > + ResponseDataSize = sizeof
> > (IPMI_BLOB_TRANSFER_BLOB_STAT_RESPONSE);
> > > + ResponseData = AllocateZeroPool (ResponseDataSize);
> > > + if (ResponseData == NULL) {
> > > + return EFI_OUT_OF_RESOURCES;
> > > + }
> > > +
> > > + //
> > > + // Format send data
> > > + //
> > > + SendDataSize = sizeof (IPMI_BLOB_TRANSFER_BLOB_STAT_SEND_DATA);
> > > + SendData = AllocateZeroPool (SendDataSize);
> > > + if (SendData == NULL) {
> > > + return EFI_OUT_OF_RESOURCES;
> > > + }
> > > +
> > > + AsciiStrCpyS (((IPMI_BLOB_TRANSFER_BLOB_STAT_SEND_DATA
> > *)SendData)->BlobId, IPMI_OEM_BLOB_MAX_DATA_PER_PACKET, BlobId);
> > > +
> > > + Status = IpmiBlobTransferSendIpmi (IpmiBlobTransferSubcommandStat,
> > SendData, SendDataSize, (UINT8 *)ResponseData, &ResponseDataSize);
> > > + if (!EFI_ERROR (Status)) {
> > > + *BlobState = ((IPMI_BLOB_TRANSFER_BLOB_STAT_RESPONSE
> > *)ResponseData)->BlobState;
> > > + *Size = ((IPMI_BLOB_TRANSFER_BLOB_STAT_RESPONSE
> > *)ResponseData)->Size;
> > > + *MetadataLength = ((IPMI_BLOB_TRANSFER_BLOB_STAT_RESPONSE
> > *)ResponseData)->MetaDataLen;
> > > +
> > > + CopyMem (&Metadata,
> > &((IPMI_BLOB_TRANSFER_BLOB_STAT_RESPONSE *)ResponseData)-
> > >MetaData, sizeof (((IPMI_BLOB_TRANSFER_BLOB_STAT_RESPONSE
> > *)ResponseData)->MetaData));
> > > + }
> > > +
> > > + FreePool (ResponseData);
> > > + FreePool (SendData);
> > > + return Status;
> > > +}
> > > +
> > > +/**
> > > + @param[in] SessionId The ID of the session to gather statistics for
> > > + @param[out] BlobState The current state of the blob
> > > + @param[out] Size Size in bytes of the blob
> > > + @param[out] MetadataLength Length of the optional metadata
> > > + @param[out] Metadata Optional blob-specific metadata
> > > +
> > > + @retval EFI_SUCCESS The blob statistics were successfully
> > 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 == NULL) || (Size == NULL) || (MetadataLength == NULL)
> ||
> > (Metadata == NULL)) {
> > > + ASSERT (FALSE);
> > > + return EFI_ABORTED;
> > > + }
> > > +
> > > + ResponseDataSize = sizeof
> > (IPMI_BLOB_TRANSFER_BLOB_STAT_RESPONSE);
> > > + ResponseData = AllocateZeroPool (ResponseDataSize);
> > > + if (ResponseData == NULL) {
> > > + return EFI_OUT_OF_RESOURCES;
> > > + }
> > > +
> > > + //
> > > + // Format send data
> > > + //
> > > + SendDataSize = sizeof
> > (IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_SEND_DATA);
> > > + SendData = AllocateZeroPool (SendDataSize);
> > > + if (SendData == NULL) {
> > > + return EFI_OUT_OF_RESOURCES;
> > > + }
> > > +
> > > + ((IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_SEND_DATA
> *)SendData)-
> > >SessionId = SessionId;
> > > +
> > > + Status = IpmiBlobTransferSendIpmi
> > (IpmiBlobTransferSubcommandSessionStat, SendData, SendDataSize,
> (UINT8
> > *)ResponseData, &ResponseDataSize);
> > > +
> > > + if (!EFI_ERROR (Status)) {
> > > + *BlobState =
> ((IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_RESPONSE
> > *)ResponseData)->BlobState;
> > > + *Size = ((IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_RESPONSE
> > *)ResponseData)->Size;
> > > + *MetadataLength =
> > ((IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_RESPONSE
> *)ResponseData)-
> > >MetaDataLen;
> > > +
> > > + CopyMem (&Metadata,
> > &((IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_RESPONSE
> *)ResponseData)-
> > >MetaData, sizeof
> (((IPMI_BLOB_TRANSFER_BLOB_SESSION_STAT_RESPONSE
> > *)ResponseData)->MetaData));
> > > + }
> > > +
> > > + FreePool (ResponseData);
> > > + FreePool (SendData);
> > > + return Status;
> > > +}
> > > +
> > > +/**
> > > + @param[in] SessionId The ID of the session to write metadata for
> > > + @param[in] Offset The offset of the metadata to write to
> > > + @param[in] Data The data to write to the metadata
> > > +
> > > + @retval EFI_SUCCESS The blob metadata was successfully
> written.
> > > + @retval Other An error occurred
> > > +**/
> > > +EFI_STATUS
> > > +IpmiBlobTransferWriteMeta (
> > > + IN UINT16 SessionId,
> > > + IN UINT32 Offset,
> > > + IN UINT8 *Data,
> > > + IN UINT32 WriteLength
> > > + )
> > > +{
> > > + EFI_STATUS Status;
> > > + UINT8 *SendData;
> > > + UINT32 SendDataSize;
> > > + UINT32 ResponseDataSize;
> > > +
> > > + //
> > > + // Format send data
> > > + //
> > > + SendDataSize = sizeof
> (IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA);
> > > + SendData = AllocateZeroPool (SendDataSize);
> > > + if (SendData == NULL) {
> > > + return EFI_OUT_OF_RESOURCES;
> > > + }
> > > +
> > > + ((IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA *)SendData)-
> > >SessionId = SessionId;
> > > + ((IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA *)SendData)-
> >Offset
> > = Offset;
> > > + CopyMem (((IPMI_BLOB_TRANSFER_BLOB_WRITE_SEND_DATA
> > *)SendData)->Data, Data, sizeof (UINT8) * WriteLength);
> > > +
> > > + ResponseDataSize = 0;
> > > +
> > > + Status = IpmiBlobTransferSendIpmi
> > (IpmiBlobTransferSubcommandWriteMeta, SendData, SendDataSize, NULL,
> > &ResponseDataSize);
> > > +
> > > + FreePool (SendData);
> > > + return Status;
> > > +}
> > > +
> > > +/**
> > > + This is the declaration of an EFI image entry point. This entry point is
> > > + the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers
> including
> > > + both device drivers and bus drivers.
> > > +
> > > + @param[in] ImageHandle The firmware allocated handle for the UEFI
> > image.
> > > + @param[in] SystemTable A pointer to the EFI System Table.
> > > +
> > > + @retval EFI_SUCCESS The operation completed successfully.
> > > + @retval Others An unexpected error occurred.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +EFIAPI
> > > +IpmiBlobTransferDxeDriverEntryPoint (
> > > + IN EFI_HANDLE ImageHandle,
> > > + IN EFI_SYSTEM_TABLE *SystemTable
> > > + )
> > > +{
> > > + return gBS->InstallMultipleProtocolInterfaces (
> > > + &ImageHandle,
> > > + &gEdkiiIpmiBlobTransferProtocolGuid,
> > > + (VOID *)&mIpmiBlobTransfer,
> > > + NULL
> > > + );
> > > +}
> > > diff --git
> >
> a/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiB
> l
> > obTransferTestUnitTests.c
> >
> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiB
> l
> > obTransferTestUnitTests.c
> > > new file mode 100644
> > > index 0000000000..f326467922
> > > --- /dev/null
> > > +++
> >
> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiB
> l
> > obTransferTestUnitTests.c
> > > @@ -0,0 +1,1113 @@
> > > +/** @file
> > > +*
> > > +* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
> > > +*
> > > +* SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION &
> > AFFILIATES
> > > +* SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +*
> > > +**/
> > > +#include <stdarg.h>
> > > +#include <stddef.h>
> > > +#include <setjmp.h>
> > > +#include <stdint.h>
> > > +#include <cmocka.h>
> > > +
> > > +#include <Uefi.h>
> > > +#include <Library/BaseMemoryLib.h>
> > > +#include <Library/DebugLib.h>
> > > +#include <Library/MemoryAllocationLib.h>
> > > +#include <Library/HostBasedTestStubLib/IpmiStubLib.h>
> > > +
> > > +#include <Library/UnitTestLib.h>
> > > +#include <Protocol/IpmiBlobTransfer.h>
> > > +#include "../InternalIpmiBlobTransfer.h"
> > > +
> > > +#define UNIT_TEST_NAME "IPMI Blob Transfer Unit Tests"
> > > +#define UNIT_TEST_VERSION "1.0"
> > > +
> > > +UINT8 InvalidCompletion[] = {
> > > + 0xC0, // CompletionCode
> > > + 0xCF, 0xC2, 0x00, // OpenBMC OEN
> > > +};
> > > +#define INVALID_COMPLETION_SIZE 4 * sizeof(UINT8)
> > > +
> > > +UINT8 NoDataResponse[] = {
> > > + 0x00, // CompletionCode
> > > + 0xCF, 0xC2, 0x00, // OpenBMC OEN
> > > +};
> > > +#define NO_DATA_RESPONSE_SIZE 4 * sizeof(UINT8)
> > > +
> > > +UINT8 BadOenResponse[] = {
> > > + 0x00, // CompletionCode
> > > + 0xFF, 0xC2, 0x00, // Wrong OEN
> > > +};
> > > +#define BAD_OEN_RESPONSE_SIZE 4 * sizeof(UINT8)
> > > +
> > > +UINT8 BadCrcResponse[] = {
> > > + 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[] = {
> > > + 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 need a
> > > + reboot. This parameter is a VOID* and it is the
> > > + responsibility of the test author to ensure that the
> > > + contents are well understood by all test cases that may
> > > + consume it.
> > > + @retval UNIT_TEST_PASSED The Unit test has completed and the
> > test
> > > + case was successful.
> > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has
> failed.
> > > +**/
> > > +UNIT_TEST_STATUS
> > > +EFIAPI
> > > +GoodCrc (
> > > + IN UNIT_TEST_CONTEXT Context
> > > + )
> > > +{
> > > + UINT8 Data[5] = { 0x12, 0x34, 0x56, 0x78, 0x90 };
> > > + UINTN DataSize;
> > > + UINT16 Crc;
> > > +
> > > + DataSize = sizeof (Data);
> > > +
> > > + Crc = CalculateCrc16 (Data, DataSize);
> > > +
> > > + UT_ASSERT_EQUAL (Crc, 0xB928);
> > > + return UNIT_TEST_PASSED;
> > > +}
> > > +
> > > +/**
> > > + @param[in] Context [Optional] An optional parameter that enables:
> > > + 1) test-case reuse with varied parameters and
> > > + 2) test-case re-entry for Target tests that need a
> > > + reboot. This parameter is a VOID* and it is the
> > > + responsibility of the test author to ensure that the
> > > + contents are well understood by all test cases that may
> > > + consume it.
> > > + @retval UNIT_TEST_PASSED The Unit test has completed and the
> > test
> > > + case was successful.
> > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has
> failed.
> > > +**/
> > > +UNIT_TEST_STATUS
> > > +EFIAPI
> > > +BadCrc (
> > > + IN UNIT_TEST_CONTEXT Context
> > > + )
> > > +{
> > > + UINT8 Data[5] = { 0x12, 0x34, 0x56, 0x78, 0x90 };
> > > + UINTN DataSize;
> > > + UINT16 Crc;
> > > +
> > > + DataSize = sizeof (Data);
> > > +
> > > + Crc = CalculateCrc16 (Data, DataSize);
> > > +
> > > + UT_ASSERT_NOT_EQUAL (Crc, 0x3409);
> > > + return UNIT_TEST_PASSED;
> > > +}
> > > +
> > > +/**
> > > + @param[in] Context [Optional] An optional parameter that enables:
> > > + 1) test-case reuse with varied parameters and
> > > + 2) test-case re-entry for Target tests that need a
> > > + reboot. This parameter is a VOID* and it is the
> > > + responsibility of the test author to ensure that the
> > > + contents are well understood by all test cases that may
> > > + consume it.
> > > + @retval UNIT_TEST_PASSED The Unit test has completed and the
> > test
> > > + case was successful.
> > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has
> failed.
> > > +**/
> > > +UNIT_TEST_STATUS
> > > +EFIAPI
> > > +SendIpmiBadCompletion (
> > > + IN UNIT_TEST_CONTEXT Context
> > > + )
> > > +{
> > > + VOID *ResponseData;
> > > + UINT32 *ResponseDataSize;
> > > + EFI_STATUS Status;
> > > + VOID *MockResponseResults = NULL;
> > > +
> > > + MockResponseResults = (UINT8 *)AllocateZeroPool
> > (INVALID_COMPLETION_SIZE);
> > > + ResponseDataSize = (UINT32 *)AllocateZeroPool (sizeof (UINT32));
> > > + CopyMem (MockResponseResults, &InvalidCompletion,
> > INVALID_COMPLETION_SIZE);
> > > +
> > > + MockIpmiSubmitCommand ((UINT8 *)MockResponseResults,
> > INVALID_COMPLETION_SIZE, EFI_SUCCESS);
> > > +
> > > + ResponseData = (UINT8 *)AllocateZeroPool (*ResponseDataSize);
> > > + Status = 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 need a
> > > + reboot. This parameter is a VOID* and it is the
> > > + responsibility of the test author to ensure that the
> > > + contents are well understood by all test cases that may
> > > + consume it.
> > > + @retval UNIT_TEST_PASSED The Unit test has completed and the
> > test
> > > + case was successful.
> > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has
> failed.
> > > +**/
> > > +UNIT_TEST_STATUS
> > > +EFIAPI
> > > +SendIpmiNoDataResponse (
> > > + IN UNIT_TEST_CONTEXT Context
> > > + )
> > > +{
> > > + VOID *ResponseData;
> > > + UINT32 *ResponseDataSize;
> > > + EFI_STATUS Status;
> > > + VOID *MockResponseResults = NULL;
> > > +
> > > + MockResponseResults = (UINT8 *)AllocateZeroPool
> > (NO_DATA_RESPONSE_SIZE);
> > > + ResponseDataSize = (UINT32 *)AllocateZeroPool (sizeof (UINT32));
> > > + CopyMem (MockResponseResults, &NoDataResponse,
> > NO_DATA_RESPONSE_SIZE);
> > > +
> > > + Status = MockIpmiSubmitCommand ((UINT8 *)MockResponseResults,
> > NO_DATA_RESPONSE_SIZE, EFI_SUCCESS);
> > > + if (EFI_ERROR (Status)) {
> > > + return UNIT_TEST_ERROR_TEST_FAILED;
> > > + }
> > > +
> > > + ResponseData = (UINT8 *)AllocateZeroPool (sizeof (NoDataResponse));
> > > + Status = 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 need a
> > > + reboot. This parameter is a VOID* and it is the
> > > + responsibility of the test author to ensure that the
> > > + contents are well understood by all test cases that may
> > > + consume it.
> > > + @retval UNIT_TEST_PASSED The Unit test has completed and the
> > test
> > > + case was successful.
> > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has
> failed.
> > > +**/
> > > +UNIT_TEST_STATUS
> > > +EFIAPI
> > > +SendIpmiBadOenResponse (
> > > + IN UNIT_TEST_CONTEXT Context
> > > + )
> > > +{
> > > + VOID *ResponseData;
> > > + UINT32 *ResponseDataSize;
> > > + EFI_STATUS Status;
> > > + VOID *MockResponseResults = NULL;
> > > +
> > > + MockResponseResults = (UINT8 *)AllocateZeroPool
> > (BAD_OEN_RESPONSE_SIZE);
> > > + ResponseDataSize = (UINT32 *)AllocateZeroPool (sizeof (UINT32));
> > > + CopyMem (MockResponseResults, &BadOenResponse,
> > BAD_OEN_RESPONSE_SIZE);
> > > +
> > > + Status = MockIpmiSubmitCommand ((UINT8 *)MockResponseResults,
> > BAD_OEN_RESPONSE_SIZE, EFI_SUCCESS);
> > > + if (EFI_ERROR (Status)) {
> > > + return UNIT_TEST_ERROR_TEST_FAILED;
> > > + }
> > > +
> > > + ResponseData = (UINT8 *)AllocateZeroPool (sizeof (BadOenResponse));
> > > + Status = 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 need a
> > > + reboot. This parameter is a VOID* and it is the
> > > + responsibility of the test author to ensure that the
> > > + contents are well understood by all test cases that may
> > > + consume it.
> > > + @retval UNIT_TEST_PASSED The Unit test has completed and the
> > test
> > > + case was successful.
> > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has
> failed.
> > > +**/
> > > +UNIT_TEST_STATUS
> > > +EFIAPI
> > > +SendIpmiBadCrcResponse (
> > > + IN UNIT_TEST_CONTEXT Context
> > > + )
> > > +{
> > > + VOID *ResponseData;
> > > + UINT32 *ResponseDataSize;
> > > + EFI_STATUS Status;
> > > + VOID *MockResponseResults = NULL;
> > > +
> > > + MockResponseResults = (UINT8 *)AllocateZeroPool (sizeof
> > (BAD_CRC_RESPONSE_SIZE));
> > > + ResponseDataSize = (UINT32 *)AllocateZeroPool (sizeof (UINT32));
> > > + CopyMem (MockResponseResults, &BadCrcResponse,
> > BAD_CRC_RESPONSE_SIZE);
> > > +
> > > + Status = MockIpmiSubmitCommand ((UINT8 *)MockResponseResults,
> > BAD_CRC_RESPONSE_SIZE, EFI_SUCCESS);
> > > + if (EFI_ERROR (Status)) {
> > > + return UNIT_TEST_ERROR_TEST_FAILED;
> > > + }
> > > +
> > > + ResponseData = (UINT8 *)AllocateZeroPool (sizeof (BadCrcResponse));
> > > + Status = 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[] = {
> > > + 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 need a
> > > + reboot. This parameter is a VOID* and it is the
> > > + responsibility of the test author to ensure that the
> > > + contents are well understood by all test cases that may
> > > + consume it.
> > > + @retval UNIT_TEST_PASSED The Unit test has completed and the
> > test
> > > + case was successful.
> > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has
> failed.
> > > +**/
> > > +UNIT_TEST_STATUS
> > > +EFIAPI
> > > +SendIpmiValidCountResponse (
> > > + IN UNIT_TEST_CONTEXT Context
> > > + )
> > > +{
> > > + UINT8 *ResponseData;
> > > + UINT32 *ResponseDataSize;
> > > + EFI_STATUS Status;
> > > + VOID *MockResponseResults = NULL;
> > > +
> > > + MockResponseResults = (UINT8 *)AllocateZeroPool (sizeof
> > (VALID_GET_COUNT_RESPONSE_SIZE));
> > > + ResponseDataSize = (UINT32 *)AllocateZeroPool (sizeof (UINT32));
> > > + CopyMem (MockResponseResults, &ValidGetCountResponse,
> > VALID_GET_COUNT_RESPONSE_SIZE);
> > > +
> > > + Status = MockIpmiSubmitCommand ((UINT8 *)MockResponseResults,
> > VALID_GET_COUNT_RESPONSE_SIZE, EFI_SUCCESS);
> > > + if (EFI_ERROR (Status)) {
> > > + return UNIT_TEST_ERROR_TEST_FAILED;
> > > + }
> > > +
> > > + ResponseData = AllocateZeroPool (sizeof (ValidGetCountResponse));
> > > + Status = 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 need a
> > > + reboot. This parameter is a VOID* and it is the
> > > + responsibility of the test author to ensure that the
> > > + contents are well understood by all test cases that may
> > > + consume it.
> > > + @retval UNIT_TEST_PASSED The Unit test has completed and the
> > test
> > > + case was successful.
> > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has
> failed.
> > > +**/
> > > +UNIT_TEST_STATUS
> > > +EFIAPI
> > > +GetCountValidCountResponse (
> > > + IN UNIT_TEST_CONTEXT Context
> > > + )
> > > +{
> > > + EFI_STATUS Status;
> > > + UINT32 Count;
> > > + VOID *MockResponseResults = NULL;
> > > +
> > > + Count = 0;
> > > +
> > > + MockResponseResults = (UINT8 *)AllocateZeroPool (sizeof
> > (VALID_GET_COUNT_RESPONSE_SIZE));
> > > + CopyMem (MockResponseResults, &ValidGetCountResponse,
> > VALID_GET_COUNT_RESPONSE_SIZE);
> > > +
> > > + Status = MockIpmiSubmitCommand ((UINT8 *)MockResponseResults,
> > VALID_GET_COUNT_RESPONSE_SIZE, EFI_SUCCESS);
> > > + if (EFI_ERROR (Status)) {
> > > + return UNIT_TEST_ERROR_TEST_FAILED;
> > > + }
> > > +
> > > + Status = IpmiBlobTransferGetCount (&Count);
> > > +
> > > + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS);
> > > + UT_ASSERT_EQUAL (Count, 1);
> > > + FreePool (MockResponseResults);
> > > + return UNIT_TEST_PASSED;
> > > +}
> > > +
> > > +UINT8 ValidEnumerateResponse[] = {
> > > + 0x00, // CompletionCode
> > > + 0xCF, 0xC2, 0x00, // OpenBMC OEN
> > > + 0x81, 0x13, // CRC
> > > + 0x2F, 0x73, 0x6D, 0x62, // Data = "/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 need a
> > > + reboot. This parameter is a VOID* and it is the
> > > + responsibility of the test author to ensure that the
> > > + contents are well understood by all test cases that may
> > > + consume it.
> > > + @retval UNIT_TEST_PASSED The Unit test has completed and the
> > test
> > > + case was successful.
> > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has
> failed.
> > > +**/
> > > +UNIT_TEST_STATUS
> > > +EFIAPI
> > > +EnumerateValidResponse (
> > > + IN UNIT_TEST_CONTEXT Context
> > > + )
> > > +{
> > > + EFI_STATUS Status;
> > > + CHAR8 *BlobId;
> > > + VOID *MockResponseResults = NULL;
> > > +
> > > + MockResponseResults = (UINT8 *)AllocateZeroPool (sizeof
> > (VALID_ENUMERATE_RESPONSE_SIZE));
> > > + CopyMem (MockResponseResults, &ValidEnumerateResponse,
> > VALID_ENUMERATE_RESPONSE_SIZE);
> > > +
> > > + Status = MockIpmiSubmitCommand ((UINT8 *)MockResponseResults,
> > VALID_ENUMERATE_RESPONSE_SIZE, EFI_SUCCESS);
> > > + if (EFI_ERROR (Status)) {
> > > + return UNIT_TEST_ERROR_TEST_FAILED;
> > > + }
> > > +
> > > + BlobId = AllocateZeroPool (sizeof (CHAR8) *
> > IPMI_OEM_BLOB_MAX_DATA_PER_PACKET);
> > > +
> > > + Status = 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 need a
> > > + reboot. This parameter is a VOID* and it is the
> > > + responsibility of the test author to ensure that the
> > > + contents are well understood by all test cases that may
> > > + consume it.
> > > + @retval UNIT_TEST_PASSED The Unit test has completed and the
> > test
> > > + case was successful.
> > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has
> failed.
> > > +**/
> > > +UNIT_TEST_STATUS
> > > +EFIAPI
> > > +EnumerateInvalidBuffer (
> > > + IN UNIT_TEST_CONTEXT Context
> > > + )
> > > +{
> > > + CHAR8 *BlobId;
> > > + EFI_STATUS Status;
> > > + VOID *MockResponseResults = NULL;
> > > +
> > > + MockResponseResults = (UINT8 *)AllocateZeroPool (sizeof
> > (VALID_ENUMERATE_RESPONSE_SIZE));
> > > + CopyMem (MockResponseResults, &ValidEnumerateResponse,
> > VALID_ENUMERATE_RESPONSE_SIZE);
> > > +
> > > + Status = MockIpmiSubmitCommand ((UINT8 *)MockResponseResults,
> > VALID_ENUMERATE_RESPONSE_SIZE, EFI_SUCCESS);
> > > + if (EFI_ERROR (Status)) {
> > > + return UNIT_TEST_ERROR_TEST_FAILED;
> > > + }
> > > +
> > > + BlobId = NULL;
> > > +
> > > + UT_EXPECT_ASSERT_FAILURE (IpmiBlobTransferEnumerate (0, BlobId),
> > NULL);
> > > +
> > > + FreePool (MockResponseResults);
> > > + return UNIT_TEST_PASSED;
> > > +}
> > > +
> > > +UINT8 ValidOpenResponse[] = {
> > > + 0x00, // CompletionCode
> > > + 0xCF, 0xC2, 0x00, // OpenBMC OEN
> > > + 0x93, 0xD1, // CRC
> > > + 0x03, 0x00, // SessionId = 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 need a
> > > + reboot. This parameter is a VOID* and it is the
> > > + responsibility of the test author to ensure that the
> > > + contents are well understood by all test cases that may
> > > + consume it.
> > > + @retval UNIT_TEST_PASSED The Unit test has completed and the
> > test
> > > + case was successful.
> > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has
> failed.
> > > +**/
> > > +UNIT_TEST_STATUS
> > > +EFIAPI
> > > +OpenValidResponse (
> > > + IN UNIT_TEST_CONTEXT Context
> > > + )
> > > +{
> > > + EFI_STATUS Status;
> > > + CHAR8 *BlobId;
> > > + UINT16 Flags;
> > > + UINT16 SessionId;
> > > + VOID *MockResponseResults = NULL;
> > > + VOID *MockResponseResults2 = NULL;
> > > + VOID *MockResponseResults3 = NULL;
> > > +
> > > + Flags = 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 = (UINT8 *)AllocateZeroPool (sizeof
> > (VALID_OPEN_RESPONSE_SIZE));
> > > +
> > > + CopyMem (MockResponseResults, &ValidOpenResponse,
> > VALID_OPEN_RESPONSE_SIZE);
> > > + Status = MockIpmiSubmitCommand ((UINT8 *)MockResponseResults,
> > VALID_OPEN_RESPONSE_SIZE, EFI_SUCCESS);
> > > + if (EFI_ERROR (Status)) {
> > > + return UNIT_TEST_ERROR_TEST_FAILED;
> > > + }
> > > +
> > > + MockResponseResults2 = (UINT8 *)AllocateZeroPool (sizeof
> > (VALID_ENUMERATE_RESPONSE_SIZE));
> > > + CopyMem (MockResponseResults2, &ValidEnumerateResponse,
> > VALID_ENUMERATE_RESPONSE_SIZE);
> > > + Status = MockIpmiSubmitCommand ((UINT8 *)MockResponseResults2,
> > VALID_ENUMERATE_RESPONSE_SIZE, EFI_SUCCESS);
> > > + if (EFI_ERROR (Status)) {
> > > + return UNIT_TEST_ERROR_TEST_FAILED;
> > > + }
> > > +
> > > + MockResponseResults3 = (UINT8 *)AllocateZeroPool (sizeof
> > (VALID_GET_COUNT_RESPONSE_SIZE));
> > > + CopyMem (MockResponseResults3, &ValidGetCountResponse,
> > VALID_GET_COUNT_RESPONSE_SIZE);
> > > + Status = MockIpmiSubmitCommand ((UINT8 *)MockResponseResults3,
> > VALID_GET_COUNT_RESPONSE_SIZE, EFI_SUCCESS);
> > > + if (EFI_ERROR (Status)) {
> > > + return UNIT_TEST_ERROR_TEST_FAILED;
> > > + }
> > > +
> > > + BlobId = "/smbios";
> > > +
> > > + Status = IpmiBlobTransferOpen (BlobId, Flags, &SessionId);
> > > +
> > > + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS);
> > > + UT_ASSERT_EQUAL (SessionId, 3);
> > > + FreePool (MockResponseResults);
> > > + return UNIT_TEST_PASSED;
> > > +}
> > > +
> > > +UINT8 ValidReadResponse[] = {
> > > + 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 need a
> > > + reboot. This parameter is a VOID* and it is the
> > > + responsibility of the test author to ensure that the
> > > + contents are well understood by all test cases that may
> > > + consume it.
> > > + @retval UNIT_TEST_PASSED The Unit test has completed and the
> > test
> > > + case was successful.
> > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has
> failed.
> > > +**/
> > > +UNIT_TEST_STATUS
> > > +EFIAPI
> > > +ReadValidResponse (
> > > + IN UNIT_TEST_CONTEXT Context
> > > + )
> > > +{
> > > + EFI_STATUS Status;
> > > + UINT8 *ResponseData;
> > > + UINT8 ExpectedDataResponse[4] = { 0x00, 0x01, 0x02, 0x03 };
> > > + VOID *MockResponseResults = NULL;
> > > +
> > > + MockResponseResults = (UINT8 *)AllocateZeroPool (sizeof
> > (VALID_READ_RESPONSE_SIZE));
> > > + CopyMem (MockResponseResults, &ValidReadResponse,
> > VALID_READ_RESPONSE_SIZE);
> > > + ResponseData = AllocateZeroPool (sizeof (ValidReadResponse));
> > > +
> > > + Status = MockIpmiSubmitCommand ((UINT8 *)MockResponseResults,
> > VALID_READ_RESPONSE_SIZE, EFI_SUCCESS);
> > > + if (EFI_ERROR (Status)) {
> > > + return UNIT_TEST_ERROR_TEST_FAILED;
> > > + }
> > > +
> > > + Status = 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 need a
> > > + reboot. This parameter is a VOID* and it is the
> > > + responsibility of the test author to ensure that the
> > > + contents are well understood by all test cases that may
> > > + consume it.
> > > + @retval UNIT_TEST_PASSED The Unit test has completed and the
> > test
> > > + case was successful.
> > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has
> failed.
> > > +**/
> > > +UNIT_TEST_STATUS
> > > +EFIAPI
> > > +ReadInvalidBuffer (
> > > + IN UNIT_TEST_CONTEXT Context
> > > + )
> > > +{
> > > + UINT8 *ResponseData;
> > > + EFI_STATUS Status;
> > > + VOID *MockResponseResults = NULL;
> > > +
> > > + MockResponseResults = (UINT8 *)AllocateZeroPool (sizeof
> > (VALID_READ_RESPONSE_SIZE));
> > > + CopyMem (MockResponseResults, &ValidReadResponse,
> > VALID_READ_RESPONSE_SIZE);
> > > + ResponseData = NULL;
> > > +
> > > + Status = 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 need a
> > > + reboot. This parameter is a VOID* and it is the
> > > + responsibility of the test author to ensure that the
> > > + contents are well understood by all test cases that may
> > > + consume it.
> > > + @retval UNIT_TEST_PASSED The Unit test has completed and the
> > test
> > > + case was successful.
> > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has
> failed.
> > > +**/
> > > +UNIT_TEST_STATUS
> > > +EFIAPI
> > > +WriteValidResponse (
> > > + IN UNIT_TEST_CONTEXT Context
> > > + )
> > > +{
> > > + EFI_STATUS Status;
> > > + UINT8 SendData[4] = { 0x00, 0x01, 0x02, 0x03 };
> > > + VOID *MockResponseResults = NULL;
> > > +
> > > + MockResponseResults = (UINT8 *)AllocateZeroPool (sizeof
> > (VALID_NODATA_RESPONSE_SIZE));
> > > + CopyMem (MockResponseResults, &ValidNoDataResponse,
> > VALID_NODATA_RESPONSE_SIZE);
> > > +
> > > + Status = MockIpmiSubmitCommand ((UINT8 *)MockResponseResults,
> > VALID_NODATA_RESPONSE_SIZE, EFI_SUCCESS);
> > > + if (EFI_ERROR (Status)) {
> > > + return UNIT_TEST_ERROR_TEST_FAILED;
> > > + }
> > > +
> > > + Status = 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 need a
> > > + reboot. This parameter is a VOID* and it is the
> > > + responsibility of the test author to ensure that the
> > > + contents are well understood by all test cases that may
> > > + consume it.
> > > + @retval UNIT_TEST_PASSED The Unit test has completed and the
> > test
> > > + case was successful.
> > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has
> failed.
> > > +**/
> > > +UNIT_TEST_STATUS
> > > +EFIAPI
> > > +CommitValidResponse (
> > > + IN UNIT_TEST_CONTEXT Context
> > > + )
> > > +{
> > > + EFI_STATUS Status;
> > > + UINT8 SendData[4] = { 0x00, 0x01, 0x02, 0x03 };
> > > + VOID *MockResponseResults = NULL;
> > > +
> > > + MockResponseResults = (UINT8 *)AllocateZeroPool (sizeof
> > (VALID_NODATA_RESPONSE_SIZE));
> > > + CopyMem (MockResponseResults, &ValidNoDataResponse,
> > VALID_NODATA_RESPONSE_SIZE);
> > > +
> > > + Status = MockIpmiSubmitCommand ((UINT8 *)MockResponseResults,
> > VALID_NODATA_RESPONSE_SIZE, EFI_SUCCESS);
> > > + if (EFI_ERROR (Status)) {
> > > + return UNIT_TEST_ERROR_TEST_FAILED;
> > > + }
> > > +
> > > + Status = 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 need a
> > > + reboot. This parameter is a VOID* and it is the
> > > + responsibility of the test author to ensure that the
> > > + contents are well understood by all test cases that may
> > > + consume it.
> > > + @retval UNIT_TEST_PASSED The Unit test has completed and the
> > test
> > > + case was successful.
> > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has
> failed.
> > > +**/
> > > +UNIT_TEST_STATUS
> > > +EFIAPI
> > > +CloseValidResponse (
> > > + IN UNIT_TEST_CONTEXT Context
> > > + )
> > > +{
> > > + EFI_STATUS Status;
> > > + VOID *MockResponseResults = NULL;
> > > +
> > > + MockResponseResults = (UINT8 *)AllocateZeroPool (sizeof
> > (VALID_NODATA_RESPONSE_SIZE));
> > > + CopyMem (MockResponseResults, &ValidNoDataResponse,
> > VALID_NODATA_RESPONSE_SIZE);
> > > +
> > > + Status = MockIpmiSubmitCommand ((UINT8 *)MockResponseResults,
> > VALID_NODATA_RESPONSE_SIZE, EFI_SUCCESS);
> > > + if (EFI_ERROR (Status)) {
> > > + return UNIT_TEST_ERROR_TEST_FAILED;
> > > + }
> > > +
> > > + Status = 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 need a
> > > + reboot. This parameter is a VOID* and it is the
> > > + responsibility of the test author to ensure that the
> > > + contents are well understood by all test cases that may
> > > + consume it.
> > > + @retval UNIT_TEST_PASSED The Unit test has completed and the
> > test
> > > + case was successful.
> > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has
> failed.
> > > +**/
> > > +UNIT_TEST_STATUS
> > > +EFIAPI
> > > +DeleteValidResponse (
> > > + IN UNIT_TEST_CONTEXT Context
> > > + )
> > > +{
> > > + EFI_STATUS Status;
> > > + VOID *MockResponseResults = NULL;
> > > +
> > > + MockResponseResults = (UINT8 *)AllocateZeroPool (sizeof
> > (VALID_NODATA_RESPONSE_SIZE));
> > > + CopyMem (MockResponseResults, &ValidNoDataResponse,
> > VALID_NODATA_RESPONSE_SIZE);
> > > +
> > > + Status = MockIpmiSubmitCommand ((UINT8 *)MockResponseResults,
> > VALID_NODATA_RESPONSE_SIZE, EFI_SUCCESS);
> > > + if (EFI_ERROR (Status)) {
> > > + return UNIT_TEST_ERROR_TEST_FAILED;
> > > + }
> > > +
> > > + Status = IpmiBlobTransferDelete ("/smbios");
> > > +
> > > + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS);
> > > + FreePool (MockResponseResults);
> > > + return UNIT_TEST_PASSED;
> > > +}
> > > +
> > > +UINT8 ValidBlobStatResponse[] = {
> > > + 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 need a
> > > + reboot. This parameter is a VOID* and it is the
> > > + responsibility of the test author to ensure that the
> > > + contents are well understood by all test cases that may
> > > + consume it.
> > > + @retval UNIT_TEST_PASSED The Unit test has completed and the
> > test
> > > + case was successful.
> > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has
> failed.
> > > +**/
> > > +UNIT_TEST_STATUS
> > > +EFIAPI
> > > +BlobStatValidResponse (
> > > + IN UNIT_TEST_CONTEXT Context
> > > + )
> > > +{
> > > + EFI_STATUS Status;
> > > + UINT16 *BlobState;
> > > + UINT32 *Size;
> > > + UINT8 *MetadataLength;
> > > + UINT8 *Metadata;
> > > + UINT8 *ExpectedMetadata;
> > > + CHAR8 *BlobId;
> > > + VOID *MockResponseResults = NULL;
> > > +
> > > + BlobState = AllocateZeroPool (sizeof (UINT16));
> > > + Size = AllocateZeroPool (sizeof (UINT32));
> > > + BlobId = "BlobId";
> > > + MetadataLength = AllocateZeroPool (sizeof (UINT8));
> > > + Metadata = AllocateZeroPool (4 * sizeof (UINT8));
> > > + ExpectedMetadata = AllocateZeroPool (4 * sizeof (UINT8));
> > > +
> > > + MockResponseResults = (UINT8 *)AllocateZeroPool (sizeof
> > (VALID_BLOB_STAT_RESPONSE_SIZE));
> > > + CopyMem (MockResponseResults, &ValidBlobStatResponse,
> > VALID_BLOB_STAT_RESPONSE_SIZE);
> > > +
> > > + Status = MockIpmiSubmitCommand ((UINT8 *)MockResponseResults,
> > VALID_BLOB_STAT_RESPONSE_SIZE, EFI_SUCCESS);
> > > + if (EFI_ERROR (Status)) {
> > > + return UNIT_TEST_ERROR_TEST_FAILED;
> > > + }
> > > +
> > > + Status = IpmiBlobTransferStat (BlobId, BlobState, Size, MetadataLength,
> > Metadata);
> > > +
> > > + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS);
> > > + UT_ASSERT_EQUAL (*BlobState, 1);
> > > + UT_ASSERT_EQUAL (*Size, 0x05040302);
> > > + UT_ASSERT_EQUAL (*MetadataLength, 4);
> > > + UT_ASSERT_MEM_EQUAL (Metadata, ExpectedMetadata, 4);
> > > + FreePool (MockResponseResults);
> > > + FreePool (BlobState);
> > > + FreePool (Size);
> > > + FreePool (MetadataLength);
> > > + FreePool (Metadata);
> > > + return UNIT_TEST_PASSED;
> > > +}
> > > +
> > > +/**
> > > + @param[in] Context [Optional] An optional parameter that enables:
> > > + 1) test-case reuse with varied parameters and
> > > + 2) test-case re-entry for Target tests that need a
> > > + reboot. This parameter is a VOID* and it is the
> > > + responsibility of the test author to ensure that the
> > > + contents are well understood by all test cases that may
> > > + consume it.
> > > + @retval UNIT_TEST_PASSED The Unit test has completed and the
> > test
> > > + case was successful.
> > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has
> failed.
> > > +**/
> > > +UNIT_TEST_STATUS
> > > +EFIAPI
> > > +BlobStatInvalidBuffer (
> > > + IN UNIT_TEST_CONTEXT Context
> > > + )
> > > +{
> > > + UINT8 *Metadata;
> > > + EFI_STATUS Status;
> > > + VOID *MockResponseResults = NULL;
> > > +
> > > + Metadata = NULL;
> > > +
> > > + MockResponseResults = (UINT8 *)AllocateZeroPool (sizeof
> > (VALID_BLOB_STAT_RESPONSE_SIZE));
> > > + CopyMem (MockResponseResults, &ValidBlobStatResponse,
> > VALID_BLOB_STAT_RESPONSE_SIZE);
> > > +
> > > + Status = 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 need a
> > > + reboot. This parameter is a VOID* and it is the
> > > + responsibility of the test author to ensure that the
> > > + contents are well understood by all test cases that may
> > > + consume it.
> > > + @retval UNIT_TEST_PASSED The Unit test has completed and the
> > test
> > > + case was successful.
> > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has
> failed.
> > > +**/
> > > +UNIT_TEST_STATUS
> > > +EFIAPI
> > > +SessionStatValidResponse (
> > > + IN UNIT_TEST_CONTEXT Context
> > > + )
> > > +{
> > > + EFI_STATUS Status;
> > > + UINT16 *BlobState;
> > > + UINT32 *Size;
> > > + UINT8 *MetadataLength;
> > > + UINT8 *Metadata;
> > > + UINT8 *ExpectedMetadata;
> > > + VOID *MockResponseResults = NULL;
> > > +
> > > + BlobState = AllocateZeroPool (sizeof (UINT16));
> > > + Size = AllocateZeroPool (sizeof (UINT32));
> > > + MetadataLength = AllocateZeroPool (sizeof (UINT8));
> > > + Metadata = AllocateZeroPool (4 * sizeof (UINT8));
> > > + ExpectedMetadata = AllocateZeroPool (4 * sizeof (UINT8));
> > > +
> > > + MockResponseResults = (UINT8 *)AllocateZeroPool (sizeof
> > (VALID_BLOB_STAT_RESPONSE_SIZE));
> > > + CopyMem (MockResponseResults, &ValidBlobStatResponse,
> > VALID_BLOB_STAT_RESPONSE_SIZE);
> > > +
> > > + Status = MockIpmiSubmitCommand ((UINT8 *)MockResponseResults,
> > VALID_BLOB_STAT_RESPONSE_SIZE, EFI_SUCCESS);
> > > + if (EFI_ERROR (Status)) {
> > > + return UNIT_TEST_ERROR_TEST_FAILED;
> > > + }
> > > +
> > > + Status = IpmiBlobTransferSessionStat (0, BlobState, Size,
> MetadataLength,
> > Metadata);
> > > +
> > > + UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS);
> > > + UT_ASSERT_EQUAL (*BlobState, 1);
> > > + UT_ASSERT_EQUAL (*Size, 0x05040302);
> > > + UT_ASSERT_EQUAL (*MetadataLength, 4);
> > > + UT_ASSERT_MEM_EQUAL (Metadata, ExpectedMetadata, 4);
> > > + FreePool (MockResponseResults);
> > > + FreePool (BlobState);
> > > + FreePool (Size);
> > > + FreePool (MetadataLength);
> > > + FreePool (Metadata);
> > > + return UNIT_TEST_PASSED;
> > > +}
> > > +
> > > +/**
> > > + @param[in] Context [Optional] An optional parameter that enables:
> > > + 1) test-case reuse with varied parameters and
> > > + 2) test-case re-entry for Target tests that need a
> > > + reboot. This parameter is a VOID* and it is the
> > > + responsibility of the test author to ensure that the
> > > + contents are well understood by all test cases that may
> > > + consume it.
> > > + @retval UNIT_TEST_PASSED The Unit test has completed and the
> > test
> > > + case was successful.
> > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has
> failed.
> > > +**/
> > > +UNIT_TEST_STATUS
> > > +EFIAPI
> > > +SessionStatInvalidBuffer (
> > > + IN UNIT_TEST_CONTEXT Context
> > > + )
> > > +{
> > > + UINT8 *Metadata;
> > > + EFI_STATUS Status;
> > > + VOID *MockResponseResults = NULL;
> > > +
> > > + Metadata = NULL;
> > > +
> > > + MockResponseResults = (UINT8 *)AllocateZeroPool (sizeof
> > (VALID_BLOB_STAT_RESPONSE_SIZE));
> > > + CopyMem (MockResponseResults, &ValidBlobStatResponse,
> > VALID_BLOB_STAT_RESPONSE_SIZE);
> > > +
> > > + Status = 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 need a
> > > + reboot. This parameter is a VOID* and it is the
> > > + responsibility of the test author to ensure that the
> > > + contents are well understood by all test cases that may
> > > + consume it.
> > > + @retval UNIT_TEST_PASSED The Unit test has completed and the
> > test
> > > + case was successful.
> > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has
> failed.
> > > +**/
> > > +UNIT_TEST_STATUS
> > > +EFIAPI
> > > +WriteMetaValidResponse (
> > > + IN UNIT_TEST_CONTEXT Context
> > > + )
> > > +{
> > > + EFI_STATUS Status;
> > > + VOID *MockResponseResults = NULL;
> > > +
> > > + MockResponseResults = (UINT8 *)AllocateZeroPool (sizeof
> > (VALID_NODATA_RESPONSE_SIZE));
> > > + CopyMem (MockResponseResults, &ValidNoDataResponse,
> > VALID_NODATA_RESPONSE_SIZE);
> > > +
> > > + Status = MockIpmiSubmitCommand ((UINT8 *)MockResponseResults,
> > VALID_NODATA_RESPONSE_SIZE, EFI_SUCCESS);
> > > + if (EFI_ERROR (Status)) {
> > > + return UNIT_TEST_ERROR_TEST_FAILED;
> > > + }
> > > +
> > > + Status = 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 = NULL;
> > > + DEBUG ((DEBUG_INFO, "%a: v%a\n", UNIT_TEST_NAME,
> > UNIT_TEST_VERSION));
> > > +
> > > + Status = InitUnitTestFramework (&Framework, UNIT_TEST_NAME,
> > gEfiCallerBaseName, UNIT_TEST_VERSION);
> > > + if (EFI_ERROR (Status)) {
> > > + DEBUG ((DEBUG_ERROR, "Failed to setup Test Framework. Exiting with
> > status = %r\n", Status));
> > > + ASSERT (FALSE);
> > > + return Status;
> > > + }
> > > +
> > > + //
> > > + // Populate the Unit Test Suite.
> > > + //
> > > + Status = 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 = EFI_OUT_OF_RESOURCES;
> > > + return Status;
> > > + }
> > > +
> > > + // CalculateCrc16
> > > + Status = AddTestCase (IpmiBlobTransfer, "Test CRC Calculation",
> > "GoodCrc", GoodCrc, NULL, NULL, NULL);
> > > + Status = AddTestCase (IpmiBlobTransfer, "Test Bad CRC Calculation",
> > "BadCrc", BadCrc, NULL, NULL, NULL);
> > > + // IpmiBlobTransferSendIpmi
> > > + Status = AddTestCase (IpmiBlobTransfer, "Send IPMI returns bad
> > completion", "SendIpmiBadCompletion", SendIpmiBadCompletion, NULL,
> > NULL, NULL);
> > > + Status = AddTestCase (IpmiBlobTransfer, "Send IPMI returns successfully
> > with no data", "SendIpmiNoDataResponse", SendIpmiNoDataResponse,
> NULL,
> > NULL, NULL);
> > > + Status = AddTestCase (IpmiBlobTransfer, "Send IPMI returns successfully
> > with bad OEN", "SendIpmiBadOenResponse", SendIpmiBadOenResponse,
> > NULL, NULL, NULL);
> > > + Status = AddTestCase (IpmiBlobTransfer, "Send IPMI returns successfully
> > with bad CRC", "SendIpmiBadCrcResponse", SendIpmiBadCrcResponse,
> NULL,
> > NULL, NULL);
> > > + Status = AddTestCase (IpmiBlobTransfer, "Send IPMI returns with valid
> > GetCount data", "SendIpmiValidCountResponse",
> > SendIpmiValidCountResponse, NULL, NULL, NULL);
> > > + // IpmiBlobTransferGetCount
> > > + Status = AddTestCase (IpmiBlobTransfer, "GetCount call with valid data",
> > "GetCountValidCountResponse", GetCountValidCountResponse, NULL,
> NULL,
> > NULL);
> > > + // IpmiBlobTransferEnumerate
> > > + Status = AddTestCase (IpmiBlobTransfer, "Enumerate call with valid
> data",
> > "EnumerateValidResponse", EnumerateValidResponse, NULL, NULL, NULL);
> > > + Status = AddTestCase (IpmiBlobTransfer, "Enumerate call with invalid
> > output buffer", "EnumerateInvalidBuffer", EnumerateInvalidBuffer, NULL,
> > NULL, NULL);
> > > + // IpmiBlobTransferOpen
> > > + Status = AddTestCase (IpmiBlobTransfer, "Open call with valid data",
> > "OpenValidResponse", OpenValidResponse, NULL, NULL, NULL);
> > > + // IpmiBlobTransferRead
> > > + Status = AddTestCase (IpmiBlobTransfer, "Read call with valid data",
> > "ReadValidResponse", ReadValidResponse, NULL, NULL, NULL);
> > > + Status = AddTestCase (IpmiBlobTransfer, "Read call with invalid buffer",
> > "ReadInvalidBuffer", ReadInvalidBuffer, NULL, NULL, NULL);
> > > + // IpmiBlobTransferWrite
> > > + Status = AddTestCase (IpmiBlobTransfer, "Write call with valid data",
> > "WriteValidResponse", WriteValidResponse, NULL, NULL, NULL);
> > > + // IpmiBlobTransferCommit
> > > + Status = AddTestCase (IpmiBlobTransfer, "Commit call with valid data",
> > "CommitValidResponse", CommitValidResponse, NULL, NULL, NULL);
> > > + // IpmiBlobTransferClose
> > > + Status = AddTestCase (IpmiBlobTransfer, "Close call with valid data",
> > "CloseValidResponse", CloseValidResponse, NULL, NULL, NULL);
> > > + // IpmiBlobTransferDelete
> > > + Status = AddTestCase (IpmiBlobTransfer, "Delete call with valid data",
> > "DeleteValidResponse", DeleteValidResponse, NULL, NULL, NULL);
> > > + // IpmiBlobTransferStat
> > > + Status = AddTestCase (IpmiBlobTransfer, "Blob Stat call with valid data",
> > "BlobStatValidResponse", BlobStatValidResponse, NULL, NULL, NULL);
> > > + Status = AddTestCase (IpmiBlobTransfer, "Blob Stat call with invalid
> buffer",
> > "BlobStatInvalidBuffer", BlobStatInvalidBuffer, NULL, NULL, NULL);
> > > + // IpmiBlobTransferSessionStat
> > > + Status = AddTestCase (IpmiBlobTransfer, "Session Stat call with valid
> data",
> > "SessionStatValidResponse", SessionStatValidResponse, NULL, NULL, NULL);
> > > + Status = AddTestCase (IpmiBlobTransfer, "Session Stat call with invalid
> > buffer", "SessionStatInvalidBuffer", SessionStatInvalidBuffer, NULL, NULL,
> > NULL);
> > > + // IpmiBlobTransferWriteMeta
> > > + Status = AddTestCase (IpmiBlobTransfer, "WriteMeta call with valid
> data",
> > "WriteMetaValidResponse", WriteMetaValidResponse, NULL, NULL, NULL);
> > > +
> > > + // Execute the tests.
> > > + Status = RunAllTestSuites (Framework);
> > > + return Status;
> > > +}
> > > +
> > > +/**
> > > + Standard UEFI entry point for target based
> > > + unit test execution from UEFI Shell.
> > > +**/
> > > +EFI_STATUS
> > > +EFIAPI
> > > +BaseLibUnitTestAppEntry (
> > > + IN EFI_HANDLE ImageHandle,
> > > + IN EFI_SYSTEM_TABLE *SystemTable
> > > + )
> > > +{
> > > + return SetupAndRunUnitTests ();
> > > +}
> > > +
> > > +/**
> > > + Standard POSIX C entry point for host based unit test execution.
> > > +**/
> > > +int
> > > +main (
> > > + int argc,
> > > + char *argv[]
> > > + )
> > > +{
> > > + return SetupAndRunUnitTests ();
> > > +}
> > > diff --git
> > a/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/Readme.md
> > b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/Readme.md
> > > new file mode 100644
> > > index 0000000000..47800f5801
> > > --- /dev/null
> > > +++
> > b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/Readme.md
> > > @@ -0,0 +1,24 @@
> > > +# IPMI Blob Transfer Interface Driver
> > > +
> > > +This DXE module is a UEFI implementation of the Phorphor Blob Transfer
> > Interface defined in OpenBMC
> > >
> >
> +https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit
> hu
> > b.com%2Fopenbmc%2Fphosphor-ipmi-
> >
> blobs&data=05%7C02%7Cnicklew%40nvidia.com%7Cb327966e846243687
> 65
> >
> 208dc29010a98%7C43083d15727340c1b7db39efd9ccc17a%7C0%7C0%7C
> 63
> >
> 8430331675551644%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAw
> MD
> >
> AiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0%7C%7C%7C&s
> da
> > ta=WdwXQUKvHs3bv4KI9rbvvvQ3jJOFlWRhBczJAke9vL0%3D&reserved=0
> > > +
> > > +## NVIDIA's OpenBMC implements this interface as a protocol, allowing
> > UEFI and BMC to transfer blobs over IPMI.
> > > +
> > > +### Usage:
> > > +Any DXE module that wishes to use this protocol should do the following:
> > > +1) The module should have a dependency on
> > gEdkiiIpmiBlobTransferProtocolGuid in its inf "Depex" section
> > > +2) The module should list gEdkiiIpmiBlobTransferProtocolGuid in its inf
> > "Protocol" section
> > > +3) The module's entry point should do a LocateProtocol on
> > gEdkiiIpmiBlobTransferProtocolGuid
> > > +
> > > +### A sample flow of protocol usage is as follows:
> > > +1) A call to IpmiBlobTransferOpen ()
> > > +2) Iterative calls to IpmiBlobTransferWrite
> > > +3) A call to IpmiBlobTransferClose ()
> > > +
> > > +### Unit Tests:
> > > +IpmiBlobTransferDxe/UnitTest/ contains host based unit tests of this
> > implementation.
> > > +Any changes to IpmiBlobTransferDxe should include proof of successful
> unit
> > tests.
> > > +
> > > +### Debugging
> > > +To assist in debugging any issues, change BLOB_TRANSFER_DEBUG to 1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#115309): https://edk2.groups.io/g/devel/message/115309
Mute This Topic: https://groups.io/mt/98212643/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
next prev parent reply other threads:[~2024-02-09 16:37 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-04-12 3:17 [edk2-platforms][PATCH] ManageabilityPkg: add support for the phosphor ipmi blob transfer protocol Nickle Wang
2023-04-13 4:29 ` Chang, Abner
2023-04-16 10:28 ` Tinh Nguyen
2023-04-16 10:50 ` Chang, Abner
2023-04-17 2:24 ` Tinh Nguyen
2023-04-17 3:01 ` Chang, Abner
2023-04-17 3:08 ` Tinh Nguyen
2023-04-17 2:20 ` [edk2-devel] " Thang Nguyen OS
2023-04-17 11:38 ` Mike Maslenkin
2024-02-08 23:52 ` Rebecca Cran
2024-02-09 13:34 ` Nickle Wang via groups.io
2024-02-09 16:37 ` Chang, Abner via groups.io [this message]
2024-05-13 9:02 ` Nhi Pham via groups.io
2024-05-14 1:56 ` Nickle Wang via groups.io
2024-05-14 2:25 ` Nhi Pham via groups.io
2024-05-15 15:14 ` Nickle Wang via groups.io
2024-05-16 8:39 ` Nhi Pham via groups.io
2024-05-16 8:44 ` Chang, Abner via groups.io
2024-05-16 8:49 ` Nhi Pham via groups.io
2024-05-16 8:53 ` Chang, Abner via groups.io
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=LV8PR12MB94522E71FB2DF30818D2AD67EA4B2@LV8PR12MB9452.namprd12.prod.outlook.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox