From: "Nickle Wang via groups.io" <nicklew=nvidia.com@groups.io>
To: Rebecca Cran <rebecca@bsdio.com>,
"devel@edk2.groups.io" <devel@edk2.groups.io>
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
Date: Fri, 9 Feb 2024 13:34:06 +0000 [thread overview]
Message-ID: <MW4PR12MB703179843519C75A2DCCC611D94B2@MW4PR12MB7031.namprd12.prod.outlook.com> (raw)
In-Reply-To: <e6771d43-ed15-455f-b077-215617c730c4@bsdio.com>
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%2Fgithub.
> com%2Fopenbmc%2Fphosphor-ipmi-
> blobs&data=05%7C02%7Cnicklew%40nvidia.com%7Cb327966e84624368765
> 208dc29010a98%7C43083d15727340c1b7db39efd9ccc17a%7C0%7C0%7C63
> 8430331675542376%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMD
> AiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0%7C%7C%7C&sda
> ta=esHFGSAc5TGBvPUWAOKd22p7DRMZ9UbnBU1jNAh%2Fsb0%3D&reserved
> =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/IpmiBlobTransferD
> xe.inf
> > create mode 100644
> Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiBlob
> TransferTestUnitTestsHost.inf
> > create mode 100644
> Features/ManageabilityPkg/Include/Protocol/IpmiBlobTransfer.h
> > create mode 100644
> Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/InternalIpmiBlobTr
> ansfer.h
> > create mode 100644
> Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransferD
> xe.c
> > create mode 100644
> Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiBlob
> 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/DxeIpmiLibIpmiProt
> 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/IpmiBlobTransfe
> rDxe.inf
> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransfe
> rDxe.inf
> > new file mode 100644
> > index 0000000000..28e9d293c1
> > --- /dev/null
> > +++
> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransfe
> 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/IpmiBl
> obTransferTestUnitTestsHost.inf
> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiBl
> obTransferTestUnitTestsHost.inf
> > new file mode 100644
> > index 0000000000..1f071bbadc
> > --- /dev/null
> > +++
> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiBl
> 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/InternalIpmiBlo
> bTransfer.h
> > new file mode 100644
> > index 0000000000..14f0dc02bc
> > --- /dev/null
> > +++
> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/InternalIpmiBlo
> 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/IpmiBlobTransfe
> rDxe.c
> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransfe
> rDxe.c
> > new file mode 100644
> > index 0000000000..9e663289d5
> > --- /dev/null
> > +++
> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/IpmiBlobTransfe
> 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)*IpmiBlobTransferGetCount,
> > +
> (IPMI_BLOB_TRANSFER_PROTOCOL_ENUMERATE)*IpmiBlobTransferEnumerat
> 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)*IpmiBlobTransferSessionS
> tat,
> > +
> (IPMI_BLOB_TRANSFER_PROTOCOL_WRITE_META)*IpmiBlobTransferWriteMe
> 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/IpmiBl
> obTransferTestUnitTests.c
> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiBl
> obTransferTestUnitTests.c
> > new file mode 100644
> > index 0000000000..f326467922
> > --- /dev/null
> > +++
> b/Features/ManageabilityPkg/Universal/IpmiBlobTransferDxe/UnitTest/IpmiBl
> 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%2Fgithu
> b.com%2Fopenbmc%2Fphosphor-ipmi-
> blobs&data=05%7C02%7Cnicklew%40nvidia.com%7Cb327966e84624368765
> 208dc29010a98%7C43083d15727340c1b7db39efd9ccc17a%7C0%7C0%7C63
> 8430331675551644%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMD
> AiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0%7C%7C%7C&sda
> 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 (#115304): https://edk2.groups.io/g/devel/message/115304
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 13:34 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 [this message]
2024-02-09 16:37 ` Chang, Abner via groups.io
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=MW4PR12MB703179843519C75A2DCCC611D94B2@MW4PR12MB7031.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