diff options
Diffstat (limited to 'MdeModulePkg/Bus/Pci/NvmExpressDxe/UnitTest/MediaSanitizeUnitTest.c')
-rw-r--r-- | MdeModulePkg/Bus/Pci/NvmExpressDxe/UnitTest/MediaSanitizeUnitTest.c | 1128 |
1 files changed, 1128 insertions, 0 deletions
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/UnitTest/MediaSanitizeUnitTest.c b/MdeModulePkg/Bus/Pci/NvmExpressDxe/UnitTest/MediaSanitizeUnitTest.c new file mode 100644 index 0000000000..b8728580c5 --- /dev/null +++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/UnitTest/MediaSanitizeUnitTest.c @@ -0,0 +1,1128 @@ +/** @file -- MediaSanitizeUnitTest.c
+ Placeholder/framework for developing a Media Sanitize unit test package.
+
+ Copyright (c) Microsoft Corporation.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UnitTestLib.h>
+#include <Library/UefiApplicationEntryPoint.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/NvmExpressPassthru.h>
+#include <Protocol/MediaSanitize.h>
+
+#include "../NvmExpress.h"
+#include "../NvmExpressBlockIo.h"
+#include "../NvmExpressMediaSanitize.h"
+#include "../NvmExpressHci.h"
+
+/**
+ Helper function for Nvme pass thru.
+
+ @param[in] This Private Data.
+ @param[in] NamespaceId Name Space Id.
+ @param[in,out] Packet Transfer Buffer.
+ @param[in] Event Event handle.
+
+ **/
+EFI_STATUS
+EFIAPI
+NvmeDeviceUnitTestPassthru (
+ IN EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *This,
+ IN UINT32 NamespaceId,
+ IN OUT EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *Packet,
+ IN EFI_EVENT Event OPTIONAL
+ )
+{
+ //
+ // Parse command packet for unit testing
+ //
+ EFI_NVM_EXPRESS_COMMAND *Command;
+ EFI_NVM_EXPRESS_COMPLETION *Completion;
+ NVME_CQ *Cqe;
+ NVME_ADMIN_FORMAT_NVM FormatNvmCdw10;
+ NVME_ADMIN_SANITIZE SanitizeCdw1011;
+
+ ASSERT (This);
+ ASSERT (Packet);
+
+ Command = Packet->NvmeCmd;
+ Completion = Packet->NvmeCompletion;
+ Cqe = (NVME_CQ *)Completion;
+
+ ZeroMem (&FormatNvmCdw10, sizeof (NVME_ADMIN_FORMAT_NVM));
+ ZeroMem (&SanitizeCdw1011, sizeof (NVME_ADMIN_SANITIZE));
+
+ switch (Command->Cdw0.Opcode) {
+ case NVME_ADMIN_FORMAT_NVM_CMD:
+ UT_LOG_VERBOSE ("%a: Opcode = NVME_ADMIN_FORMAT_NVM_CMD\n", __func__);
+
+ CopyMem (&FormatNvmCdw10, &Command->Cdw10, sizeof (NVME_ADMIN_FORMAT_NVM));
+
+ //
+ // FormatNVM Check 1: Validate SES parameter
+ //
+ if (FormatNvmCdw10.Ses > 0x2) {
+ Cqe->Sct = NVME_CQE_SCT_GENERIC_CMD_STATUS;
+ Cqe->Sc = NVME_CQE_SC_INVALID_FIELD_IN_CMD;
+
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // FormatNVM Check 2: Validate LbaIndex parameter
+ //
+ if (FormatNvmCdw10.Lbaf > 0x1) {
+ Cqe->Sct = NVME_CQE_SCT_GENERIC_CMD_STATUS;
+ Cqe->Sc = NVME_CQE_SC_INVALID_FIELD_IN_CMD;
+
+ return EFI_INVALID_PARAMETER;
+ }
+
+ break;
+ case NVME_ADMIN_SANITIZE_CMD:
+ UT_LOG_VERBOSE ("%a: Opcode = NVME_ADMIN_SANITIZE_CMD\n", __func__);
+
+ CopyMem (&SanitizeCdw1011, &Command->Cdw10, sizeof (NVME_ADMIN_SANITIZE));
+
+ //
+ // Sanitize Check 1: Validate Sanitize Action parameter
+ //
+ if (SanitizeCdw1011.Sanact > 0x4) {
+ Cqe->Sct = NVME_CQE_SCT_GENERIC_CMD_STATUS;
+ Cqe->Sc = NVME_CQE_SC_INVALID_FIELD_IN_CMD;
+
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Sanitize Check 2: Validate overwrite action with non-NULL overwrite pattern
+ //
+ if (((SanitizeCdw1011.Sanact == SANITIZE_ACTION_OVERWRITE) && (SanitizeCdw1011.Ovrpat != 0xDEADBEEF)) ||
+ ((SanitizeCdw1011.Sanact != SANITIZE_ACTION_OVERWRITE) && (SanitizeCdw1011.Ovrpat != 0)))
+ {
+ Cqe->Sct = NVME_CQE_SCT_GENERIC_CMD_STATUS;
+ Cqe->Sc = NVME_CQE_SC_INVALID_FIELD_IN_CMD;
+
+ return EFI_INVALID_PARAMETER;
+ }
+
+ break;
+ default:
+ UT_LOG_VERBOSE ("%a: Invalid Opcode = 0x%x!!!\n", __func__, Command->Cdw0.Opcode);
+ break;
+ }
+
+ //
+ // Populate CQE (completion queue entry based on opcode and parameters
+ //
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Helper function to simulate read.
+
+ @param[in] Private Private Data.
+ @param[in] NamespaceId Name Space Id.
+ @param[in] Buffer Transfer Buffer.
+
+ **/
+EFI_STATUS
+NvmeIdentifyNamespace (
+ IN NVME_CONTROLLER_PRIVATE_DATA *Private,
+ IN UINT32 NamespaceId,
+ IN VOID *Buffer
+ )
+{
+ EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
+ EFI_NVM_EXPRESS_COMMAND Command;
+ EFI_NVM_EXPRESS_COMPLETION Completion;
+
+ ZeroMem (&CommandPacket, sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
+ ZeroMem (&Command, sizeof (EFI_NVM_EXPRESS_COMMAND));
+ ZeroMem (&Completion, sizeof (EFI_NVM_EXPRESS_COMPLETION));
+
+ CommandPacket.NvmeCmd = &Command;
+ CommandPacket.NvmeCompletion = &Completion;
+ Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_CMD;
+ Command.Nsid = NamespaceId;
+ CommandPacket.TransferBuffer = Buffer;
+ CommandPacket.TransferLength = sizeof (NVME_ADMIN_NAMESPACE_DATA);
+ CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
+ CommandPacket.QueueType = NVME_ADMIN_QUEUE;
+
+ //
+ // Set bit 0 (Cns bit) to 1 to identify a namespace
+ //
+ CommandPacket.NvmeCmd->Cdw10 = 0;
+ CommandPacket.NvmeCmd->Flags = CDW10_VALID;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Helper function to simulate read.
+
+ @param[in] Device Private Data.
+ @param[out] Buffer Buffer to read into.
+ @param[in] Lba Logical Block Addess to read from.
+ @param[in] Blocks Number of blocks.
+
+ **/
+EFI_STATUS
+NvmeUnitTestRead (
+ IN NVME_DEVICE_PRIVATE_DATA *Device,
+ OUT VOID *Buffer,
+ IN UINT64 Lba,
+ IN UINTN Blocks
+ )
+{
+ UT_ASSERT_NOT_NULL (Device);
+ Buffer = NULL;
+ Lba = 0;
+ Blocks = 0;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Helper function to simulate write.
+
+ @param[in] Device Private Data.
+ @param[in] Buffer Buffer to write.
+ @param[in] Lba Logical Block Addess to write.
+ @param[in] Blocks Number of blocks.
+
+ **/
+EFI_STATUS
+NvmeUnitTestWrite (
+ IN NVME_DEVICE_PRIVATE_DATA *Device,
+ IN VOID *Buffer,
+ IN UINT64 Lba,
+ IN UINTN Blocks
+ )
+{
+ UT_ASSERT_NOT_NULL (Device);
+ Buffer = NULL;
+ Lba = 0;
+ Blocks = 0;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Simulated BlockIo read block function.
+
+ @param[in] This BlockIo Protocol.
+ @param[in] MediaId Id of the media.
+ @param[in] Lba Logical Block Address.
+ @param[in] BufferSize Size of Buffer.
+ @param[out] Buffer Actual buffer to use to read.
+
+ **/
+EFI_STATUS
+EFIAPI
+NvmeBlockIoReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ NVME_DEVICE_PRIVATE_DATA *Device;
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_MEDIA *Media;
+ UINTN BlockSize;
+ UINTN NumberOfBlocks;
+ UINTN IoAlign;
+
+ //
+ // Check parameters.
+ //
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Media = This->Media;
+
+ if (MediaId != Media->MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ BlockSize = Media->BlockSize;
+ if ((BufferSize % BlockSize) != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ NumberOfBlocks = BufferSize / BlockSize;
+ if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ IoAlign = Media->IoAlign;
+ if ((IoAlign > 0) && (((UINTN)Buffer & (IoAlign - 1)) != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This);
+ Status = NvmeUnitTestRead (Device, Buffer, Lba, NumberOfBlocks);
+
+ return Status;
+}
+
+/**
+ Simulated BlockIo write block function.
+
+ @param[in] This BlockIo Protocol.
+ @param[in] MediaId Id of the media.
+ @param[in] Lba Logical Block Address.
+ @param[in] BufferSize Size of Buffer.
+ @param[in] Buffer Actual buffer to use to write.
+
+ **/
+EFI_STATUS
+EFIAPI
+NvmeBlockIoWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ NVME_DEVICE_PRIVATE_DATA *Device;
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_MEDIA *Media;
+ UINTN BlockSize;
+ UINTN NumberOfBlocks;
+ UINTN IoAlign;
+
+ //
+ // Check parameters.
+ //
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Media = This->Media;
+
+ if (MediaId != Media->MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ BlockSize = Media->BlockSize;
+ if ((BufferSize % BlockSize) != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ NumberOfBlocks = BufferSize / BlockSize;
+ if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ IoAlign = Media->IoAlign;
+ if ((IoAlign > 0) && (((UINTN)Buffer & (IoAlign - 1)) != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This);
+ Status = NvmeUnitTestWrite (Device, Buffer, Lba, NumberOfBlocks);
+
+ return Status;
+}
+
+/**
+ Simulated BlockIo read block ex function.
+
+ @param[in] This BlockIo2 Protocol.
+ @param[in] MediaId Id of the media.
+ @param[in] Lba Logical Block Address.
+ @param[in,out] Token Block Io2 token.
+
+ @param[in] BufferSize Size of Buffer.
+ @param[out] Buffer Actual buffer to use to read.
+
+ **/
+EFI_STATUS
+EFIAPI
+NvmeBlockIoReadBlocksEx (
+ IN EFI_BLOCK_IO2_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN OUT EFI_BLOCK_IO2_TOKEN *Token,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ NVME_DEVICE_PRIVATE_DATA *Device;
+ EFI_BLOCK_IO_MEDIA *Media;
+ UINTN BlockSize;
+ UINTN NumberOfBlocks;
+ UINTN IoAlign;
+ EFI_STATUS Status;
+
+ //
+ // Check parameters.
+ //
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Media = This->Media;
+
+ if (MediaId != Media->MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BlockSize = Media->BlockSize;
+ if ((BufferSize % BlockSize) != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ NumberOfBlocks = BufferSize / BlockSize;
+ if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ IoAlign = Media->IoAlign;
+ if ((IoAlign > 0) && (((UINTN)Buffer & (IoAlign - 1)) != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2 (This);
+ Status = NvmeUnitTestRead (Device, Buffer, Lba, NumberOfBlocks);
+
+ return Status;
+}
+
+/**
+ Simulated BlockIo write block ex function.
+
+ @param[in] This BlockIo2 Protocol.
+ @param[in] MediaId Id of the media.
+ @param[in] Lba Logical Block Address.
+ @param[in,out] Token Block Io2 token.
+ @param[in] BufferSize Size of Buffer.
+
+ @param[in] Buffer Actual buffer to use to write.
+
+ **/
+EFI_STATUS
+EFIAPI
+NvmeBlockIoWriteBlocksEx (
+ IN EFI_BLOCK_IO2_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN OUT EFI_BLOCK_IO2_TOKEN *Token,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ NVME_DEVICE_PRIVATE_DATA *Device;
+ EFI_BLOCK_IO_MEDIA *Media;
+ UINTN BlockSize;
+ UINTN NumberOfBlocks;
+ UINTN IoAlign;
+ EFI_STATUS Status;
+
+ //
+ // Check parameters.
+ //
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Media = This->Media;
+
+ if (MediaId != Media->MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BlockSize = Media->BlockSize;
+ if ((BufferSize % BlockSize) != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ NumberOfBlocks = BufferSize / BlockSize;
+ if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ IoAlign = Media->IoAlign;
+ if ((IoAlign > 0) && (((UINTN)Buffer & (IoAlign - 1)) != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2 (This);
+ Status = NvmeUnitTestWrite (Device, Buffer, Lba, NumberOfBlocks);
+
+ return Status;
+}
+
+/**
+ MediaSanitizePurgeUnitTest to initialize a Private Namespace instance.
+
+ @param[in] ppDevice Nvme Private Data structure to destory and free.
+ **/
+UNIT_TEST_STATUS
+EFIAPI
+NvmeDestroyDeviceInstance (
+ NVME_DEVICE_PRIVATE_DATA **ppDevice
+ )
+{
+ //
+ // Free in following order to to avoid dangling pointers:
+ //
+ // 1 - NVME_ADMIN_CONTROLLER_DATA
+ // 2 - NVME_CONTROLLER_PRIVATE_DATA
+ // 3 - NVME_DEVICE_PRIVATE_DATA
+ //
+ FreePool ((*ppDevice)->Controller->ControllerData);
+ (*ppDevice)->Controller->ControllerData = NULL;
+
+ FreePool ((*ppDevice)->Controller);
+ (*ppDevice)->Controller = NULL;
+
+ FreePool ((*ppDevice));
+ *ppDevice = NULL;
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ MediaSanitizePurgeUnitTest to initialize a Private Namespace instance.
+
+ @param[in] ppDevice Nvme Private Data structure to initialize.
+ **/
+UNIT_TEST_STATUS
+EFIAPI
+NvmeCreateDeviceInstance (
+ NVME_DEVICE_PRIVATE_DATA **ppDevice
+ )
+{
+ NVME_ADMIN_NAMESPACE_DATA *NamespaceData;
+ NVME_CONTROLLER_PRIVATE_DATA *Private;
+ NVME_DEVICE_PRIVATE_DATA *Device;
+
+ Private = AllocateZeroPool (sizeof (NVME_CONTROLLER_PRIVATE_DATA));
+
+ Private->Signature = NVME_CONTROLLER_PRIVATE_DATA_SIGNATURE;
+ Private->Cid[0] = 0;
+ Private->Cid[1] = 0;
+ Private->Cid[2] = 0;
+ Private->Pt[0] = 0;
+ Private->Pt[1] = 0;
+ Private->Pt[2] = 0;
+ Private->SqTdbl[0].Sqt = 0;
+ Private->SqTdbl[1].Sqt = 0;
+ Private->SqTdbl[2].Sqt = 0;
+ Private->CqHdbl[0].Cqh = 0;
+ Private->CqHdbl[1].Cqh = 0;
+ Private->CqHdbl[2].Cqh = 0;
+ Private->AsyncSqHead = 0;
+
+ Private->ControllerData = (NVME_ADMIN_CONTROLLER_DATA *)AllocateZeroPool (sizeof (NVME_ADMIN_CONTROLLER_DATA));
+
+ UT_LOG_VERBOSE ("%a: Allocated and Initialized NVME_CONTROLLER_PRIVATE_DATA\n", __func__);
+ UT_LOG_VERBOSE ("%a: Allocated and Initialized NVME_ADMIN_CONTROLLER_DATA\n", __func__);
+
+ Private->ControllerData->Nn = 1; // One namespace
+ Private->ControllerData->Sanicap.Bes = 1; // Block Erase Supported
+ Private->ControllerData->Sanicap.Ces = 1; // Crypto Erase Supported
+ Private->ControllerData->Sanicap.Ows = 1; // Overwrite Supported
+
+ NamespaceData = AllocateZeroPool (sizeof (NVME_ADMIN_NAMESPACE_DATA));
+ UT_LOG_VERBOSE ("%a: Allocated and Initialized NVME_ADMIN_NAMESPACE_DATA\n", __func__);
+
+ Device = (NVME_DEVICE_PRIVATE_DATA *)(AllocateZeroPool (sizeof (NVME_DEVICE_PRIVATE_DATA)));
+
+ //
+ // Initialize SSD namespace instance data
+ //
+ Device->Signature = NVME_DEVICE_PRIVATE_DATA_SIGNATURE;
+ Device->NamespaceId = 0;
+ Device->NamespaceUuid = 1;
+
+ Device->Controller = Private;
+
+ //
+ // Build BlockIo media structure
+ //
+ Device->Media.MediaId = 0;
+ Device->Media.RemovableMedia = FALSE;
+ Device->Media.MediaPresent = TRUE;
+ Device->Media.LogicalPartition = FALSE;
+ Device->Media.ReadOnly = FALSE;
+ Device->Media.WriteCaching = FALSE;
+ Device->Media.BlockSize = (UINT32)(1 << 9); // 512 byte sector size
+
+ Device->Media.LastBlock = 0x4000; // NamespaceData=>Nsze
+ Device->Media.LogicalBlocksPerPhysicalBlock = 1;
+ Device->Media.LowestAlignedLba = 1;
+
+ Device->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION2;
+ Device->BlockIo.Media = &Device->Media;
+ Device->BlockIo.ReadBlocks = NvmeBlockIoReadBlocks;
+ Device->BlockIo.WriteBlocks = NvmeBlockIoWriteBlocks;
+
+ Device->BlockIo2.Media = &Device->Media;
+ Device->BlockIo2.ReadBlocksEx = NvmeBlockIoReadBlocksEx;
+ Device->BlockIo2.WriteBlocksEx = NvmeBlockIoWriteBlocksEx;
+
+ Device->MediaSanitize.Revision = MEDIA_SANITIZE_PROTOCOL_REVISION;
+ Device->MediaSanitize.Media = &Device->Media;
+ Device->MediaSanitize.MediaClear = NvmExpressMediaClear;
+ Device->MediaSanitize.MediaPurge = NvmExpressMediaPurge;
+ Device->MediaSanitize.MediaFormat = NvmExpressMediaFormat;
+
+ Device->Controller->Passthru.Mode = 0;
+ Device->Controller->Passthru.PassThru = NvmeDeviceUnitTestPassthru;
+ Device->Controller->Passthru.BuildDevicePath = NULL;
+ Device->Controller->Passthru.GetNamespace = NULL;
+ Device->Controller->Passthru.GetNextNamespace = NULL;
+
+ CopyMem (&Device->NamespaceData, NamespaceData, sizeof (NVME_ADMIN_NAMESPACE_DATA));
+ *ppDevice = Device;
+
+ UT_LOG_VERBOSE ("%a: Allocated and Initialized NVME_DEVICE_PRIVATE_DATA\n", __func__);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ MediaSanitizePurgeUnitTest to Test calls to NvmExpressMediaPurge.
+
+ @param[in] Context Unit test case context
+ **/
+UNIT_TEST_STATUS
+EFIAPI
+MediaSanitizePurgeUnitTest (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ UINT32 PurgeAction;
+ UINT32 OverwritePattern;
+ UNIT_TEST_STATUS UnitTestStatus;
+ NVME_DEVICE_PRIVATE_DATA *NvmeDevice;
+ EFI_STATUS Status;
+
+ UnitTestStatus = UNIT_TEST_PASSED;
+ NvmeDevice = NULL;
+ Status = EFI_SUCCESS;
+
+ UnitTestStatus = NvmeCreateDeviceInstance (&NvmeDevice);
+
+ UT_ASSERT_STATUS_EQUAL (UnitTestStatus, UNIT_TEST_PASSED);
+ UT_ASSERT_NOT_NULL (NvmeDevice);
+
+ UT_LOG_VERBOSE ("%a: Create Device Instance Status = 0x%x\n", __func__, UnitTestStatus);
+ UT_LOG_VERBOSE ("%a: Device = 0x%x\n", __func__, NvmeDevice);
+ UT_LOG_VERBOSE ("%a: Device->BlockIo = 0x%x\n", __func__, NvmeDevice->BlockIo);
+ UT_LOG_VERBOSE ("%a: Device->Signature = 0x%x\n", __func__, NvmeDevice->Signature);
+
+ //
+ // Case 1: Block Erase
+ //
+ PurgeAction = SANITIZE_ACTION_BLOCK_ERASE;
+ OverwritePattern = 0;
+
+ Status = NvmExpressMediaPurge (
+ &NvmeDevice->MediaSanitize,
+ NvmeDevice->Media.MediaId,
+ PurgeAction,
+ OverwritePattern
+ );
+
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ UnitTestStatus = NvmeDestroyDeviceInstance (&NvmeDevice);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ NvmeSanitizeUnitTest to Test calls to NvmExpressSanitize.
+
+ @param[in] Context Unit test case context
+ **/
+UNIT_TEST_STATUS
+EFIAPI
+NvmeSanitizeUnitTest (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ UINT32 NamespaceId;
+ UINT32 SanitizeAction;
+ UINT32 NoDeallocateAfterSanitize;
+ UINT32 OverwritePattern;
+ UNIT_TEST_STATUS UnitTestStatus;
+ NVME_DEVICE_PRIVATE_DATA *NvmeDevice;
+ EFI_STATUS Status;
+
+ NamespaceId = 0;
+ UnitTestStatus = UNIT_TEST_PASSED;
+ NvmeDevice = NULL;
+ Status = EFI_SUCCESS;
+ SanitizeAction = SANITIZE_ACTION_BLOCK_ERASE;
+ NoDeallocateAfterSanitize = 0;
+ OverwritePattern = 0;
+
+ UnitTestStatus = NvmeCreateDeviceInstance (&NvmeDevice);
+
+ UT_ASSERT_STATUS_EQUAL (UnitTestStatus, UNIT_TEST_PASSED);
+ UT_ASSERT_NOT_NULL (NvmeDevice);
+
+ UT_LOG_VERBOSE ("%a: Create Device Instance Status = 0x%x\n", __func__, UnitTestStatus);
+ UT_LOG_VERBOSE ("%a: Device = 0x%x\n", __func__, NvmeDevice);
+ UT_LOG_VERBOSE ("%a: Device->BlockIo = 0x%x\n", __func__, NvmeDevice->BlockIo);
+ UT_LOG_VERBOSE ("%a: Device->Signature = 0x%x\n", __func__, NvmeDevice->Signature);
+
+ //
+ // Case 1: Block Erase
+ //
+ SanitizeAction = SANITIZE_ACTION_BLOCK_ERASE;
+ NoDeallocateAfterSanitize = 0;
+ OverwritePattern = 0;
+
+ Status = NvmExpressSanitize (
+ &NvmeDevice->BlockIo,
+ NamespaceId,
+ SanitizeAction,
+ NoDeallocateAfterSanitize,
+ OverwritePattern
+ );
+
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ //
+ // Case 2: Crypto Erase
+ //
+ SanitizeAction = SANITIZE_ACTION_CRYPTO_ERASE;
+ NoDeallocateAfterSanitize = 0;
+ OverwritePattern = 0;
+
+ Status = NvmExpressSanitize (
+ &NvmeDevice->BlockIo,
+ NamespaceId,
+ SanitizeAction,
+ NoDeallocateAfterSanitize,
+ OverwritePattern
+ );
+
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ //
+ // Case 3: Overwrite
+ //
+ SanitizeAction = SANITIZE_ACTION_OVERWRITE;
+ NoDeallocateAfterSanitize = 0;
+ OverwritePattern = 0xDEADBEEF;
+
+ Status = NvmExpressSanitize (
+ &NvmeDevice->BlockIo,
+ NamespaceId,
+ SanitizeAction,
+ NoDeallocateAfterSanitize,
+ OverwritePattern
+ );
+
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ //
+ // Case 4: Block Erase (invalid overwrite pattern)
+ //
+ SanitizeAction = SANITIZE_ACTION_BLOCK_ERASE;
+ NoDeallocateAfterSanitize = 0;
+ OverwritePattern = 0xDEADBEEF;
+
+ Status = NvmExpressSanitize (
+ &NvmeDevice->BlockIo,
+ NamespaceId,
+ SanitizeAction,
+ NoDeallocateAfterSanitize,
+ OverwritePattern
+ );
+
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+
+ //
+ // Case 5: Overwrite (invalid overwrite pattern)
+ //
+ SanitizeAction = SANITIZE_ACTION_OVERWRITE;
+ NoDeallocateAfterSanitize = 0;
+ OverwritePattern = 0;
+
+ Status = NvmExpressSanitize (
+ &NvmeDevice->BlockIo,
+ NamespaceId,
+ SanitizeAction,
+ NoDeallocateAfterSanitize,
+ OverwritePattern
+ );
+
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+
+ UnitTestStatus = NvmeDestroyDeviceInstance (&NvmeDevice);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ NvmeFormatNvmUnitTest to Test calls to NvmExpressFormatNvm.
+
+ @param[in] Context Unit test case context
+ **/
+UNIT_TEST_STATUS
+EFIAPI
+NvmeFormatNvmUnitTest (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ UINT32 NamespaceId;
+ UINT32 Ses;
+ UINT32 Flbas;
+ NVME_DEVICE_PRIVATE_DATA *NvmeDevice;
+ UNIT_TEST_STATUS UnitTestStatus;
+ EFI_STATUS Status;
+
+ NamespaceId = 0;
+ NvmeDevice = NULL;
+ UnitTestStatus = UNIT_TEST_PASSED;
+ Status = EFI_SUCCESS;
+
+ UnitTestStatus = NvmeCreateDeviceInstance (&NvmeDevice);
+
+ UT_ASSERT_STATUS_EQUAL (UnitTestStatus, UNIT_TEST_PASSED);
+ UT_ASSERT_NOT_NULL (NvmeDevice);
+
+ UT_LOG_VERBOSE ("%a: Create Device Instance Status = 0x%x\n", __func__, UnitTestStatus);
+ UT_LOG_VERBOSE ("%a: Device = 0x%x\n", __func__, NvmeDevice);
+ UT_LOG_VERBOSE ("%a: Device->BlockIo = 0x%x\n", __func__, NvmeDevice->BlockIo);
+ UT_LOG_VERBOSE ("%a: Device->Signature = 0x%x\n", __func__, NvmeDevice->Signature);
+
+ //
+ // Case 1: User Data Erase (Flbas = 0)
+ //
+ Ses = SES_USER_DATA_ERASE;
+ Flbas = 0;
+ Status = NvmExpressFormatNvm (
+ &NvmeDevice->BlockIo,
+ NamespaceId,
+ Ses,
+ Flbas
+ );
+
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ //
+ // Case 2: Crypto Erase (Flbas = 0)
+ //
+ Ses = SES_CRYPTO_ERASE;
+ Flbas = 0;
+ Status = NvmExpressFormatNvm (
+ &NvmeDevice->BlockIo,
+ NamespaceId,
+ Ses,
+ Flbas
+ );
+
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ //
+ // Case 3: User Data Erase (Invalid Flbas = 3)
+ //
+ Ses = SES_USER_DATA_ERASE;
+ Flbas = 3;
+ Status = NvmExpressFormatNvm (
+ &NvmeDevice->BlockIo,
+ NamespaceId,
+ Ses,
+ Flbas
+ );
+
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+
+ //
+ // Case 4: Invalid SES (Flba = 0)
+ //
+ Ses = 0xFF;
+ Flbas = 0;
+ Status = NvmExpressFormatNvm (
+ &NvmeDevice->BlockIo,
+ NamespaceId,
+ Ses,
+ Flbas
+ );
+
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+
+ UnitTestStatus = NvmeDestroyDeviceInstance (&NvmeDevice);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Baseline Unit Test.
+
+ @param[in] Context Unit test case context
+ **/
+UNIT_TEST_STATUS
+EFIAPI
+UnitTestBaseline (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ UINT32 A;
+ UINT32 B;
+ UINT32 C;
+
+ A = 1;
+ B = 1;
+ C = A + B;
+
+ UT_ASSERT_EQUAL (C, 2);
+ UT_ASSERT_NOT_EQUAL (0, 1);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Test Case that locks a variable using the Variable Policy Protocol with a
+ policy other than LOCK_NOW then attempts to lock the same variable using the
+ Variable Lock Protocol. The call to Variable Policy is expected to succeed
+ and the call to Variable Lock is expected to fail.
+
+ @retval EFI_SUCCES Success
+ @retval Other Error
+ **/
+EFI_STATUS
+EFIAPI
+MediaSanitizeUnitTestEntry (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UNIT_TEST_FRAMEWORK_HANDLE Framework;
+ UNIT_TEST_SUITE_HANDLE NvmeFormatNvmTestSuite;
+ UNIT_TEST_SUITE_HANDLE NvmeSanitizeTestSuite;
+ UNIT_TEST_SUITE_HANDLE MediaSanitizeProtocolTestSuite;
+
+ Framework = NULL;
+
+ #define UNIT_TEST_NAME "Media Sanitize Protocol Unit Test"
+ #define UNIT_TEST_VERSION "1.0"
+
+ DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_NAME, UNIT_TEST_VERSION));
+
+ //
+ // Start setting up the test framework for running the tests.
+ //
+ Status = InitUnitTestFramework (
+ &Framework,
+ UNIT_TEST_NAME,
+ gEfiCallerBaseName,
+ UNIT_TEST_VERSION
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status = %r\n", Status));
+ goto EXIT;
+ }
+
+ //
+ // Populate the NVM Express Format NVM Unit Test Suite.
+ //
+ Status = CreateUnitTestSuite (
+ &NvmeFormatNvmTestSuite,
+ Framework,
+ "NVM Express Format NVM Test Suite",
+ "Nvm.Express.Format.Nvm",
+ NULL,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for NvmeFormatNvmTestSuite. Status = %r\n", Status));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT;
+ }
+
+ //
+ // Add baseline sanity test case
+ //
+ AddTestCase (
+ NvmeFormatNvmTestSuite, // Test Suite Handle
+ "Baseline Format NVM Unit Test", // Test Description
+ "FormatNVM", // Test Class
+ UnitTestBaseline, // UNIT_TEST_FUNCTION()
+ NULL, // (Optional) UNIT_TEST_PREREQUISITE()
+ NULL, // (Optional) UNIT_TEST_CLEANUP()
+ NULL // (Optional) UNIT_TEST_CONTEXT
+ );
+
+ //
+ // Add test case for NvmExpressFormatNvm()
+ //
+ AddTestCase (
+ NvmeFormatNvmTestSuite, // Test Suite Handle
+ "Admin Format NVM Command Unit Test", // Test Description
+ "FormatNVM", // Test Class
+ NvmeFormatNvmUnitTest, // UNIT_TEST_FUNCTION()
+ NULL, // (Optional) UNIT_TEST_PREREQUISITE()
+ NULL, // (Optional) UNIT_TEST_CLEANUP()
+ NULL // (Optional) UNIT_TEST_CONTEXT
+ );
+
+ //
+ // Populate the NVM Express Sanitize Unit Test Suite.
+ //
+ Status = CreateUnitTestSuite (
+ &NvmeSanitizeTestSuite,
+ Framework,
+ "NVM Express Sanitize Test Suite",
+ "Nvm.Express.Sanitize",
+ NULL,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for NvmeSanitizTestSuite. Status = %r\n", Status));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT;
+ }
+
+ //
+ // Add baseline sanity test
+ //
+ AddTestCase (
+ NvmeSanitizeTestSuite, // Test Suite Handle
+ "Baseline Sanitize Unit Test", // Test Description
+ "Sanitize", // Test Class
+ UnitTestBaseline, // UNIT_TEST_FUNCTION()
+ NULL, // (Optional) UNIT_TEST_PREREQUISITE()
+ NULL, // (Optional) UNIT_TEST_CLEANUP()
+ NULL // (Optional) UNIT_TEST_CONTEXT
+ );
+
+ //
+ // Add test case for NvmExressSanitize()
+ //
+ AddTestCase (
+ NvmeSanitizeTestSuite, // Test Suite Handle
+ "Admin Sanitize Command Unit Test", // Test Description
+ "Sanitize", // Test Class
+ NvmeSanitizeUnitTest, // UNIT_TEST_FUNCTION()
+ NULL, // (Optional) UNIT_TEST_PREREQUISITE()
+ NULL, // (Optional) UNIT_TEST_CLEANUP()
+ NULL // (Optional) UNIT_TEST_CONTEXT
+ );
+
+ //
+ // Populate the Media Sanitize Protocol Unit Test Suite.
+ //
+ Status = CreateUnitTestSuite (
+ &MediaSanitizeProtocolTestSuite,
+ Framework,
+ "Media Sanitize Protocol Test Suite",
+ "Media.Sanitize.Protocol",
+ NULL,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MediaSanitizeProtocolTestSuite. Status = %r\n", Status));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT;
+ }
+
+ //
+ // Add test case for Media Purge
+ //
+ AddTestCase (
+ MediaSanitizeProtocolTestSuite, // Test Suite Handle
+ "Baseline MediaSanitize Unit Test", // Test Description
+ "MediaSanitize", // Test Class
+ UnitTestBaseline, // UNIT_TEST_FUNCTION()
+ NULL, // (Optional) UNIT_TEST_PREREQUISITE()
+ NULL, // (Optional) UNIT_TEST_CLEANUP()
+ NULL // (Optional) UNIT_TEST_CONTEXT
+ );
+
+ //
+ // Add test case for Media Purge
+ //
+ AddTestCase (
+ MediaSanitizeProtocolTestSuite, // Test Suite Handle
+ "Protocol Media Sanitize Unit Test", // Test Description
+ "MediaPurge", // Test Class
+ MediaSanitizePurgeUnitTest, // UNIT_TEST_FUNCTION()
+ NULL, // (Optional) UNIT_TEST_PREREQUISITE()
+ NULL, // (Optional) UNIT_TEST_CLEANUP()
+ NULL // (Optional) UNIT_TEST_CONTEXT
+ );
+
+ //
+ // Execute the tests.
+ //
+ Status = RunAllTestSuites (Framework);
+
+EXIT:
+ if (Framework) {
+ FreeUnitTestFramework (Framework);
+ }
+
+ return Status;
+}
+
+///
+/// Avoid ECC error for function name that starts with lower case letter
+///
+#define MediaSanitizeUnitTestMain main
+
+/**
+ Standard POSIX C entry point for host based unit test execution.
+
+ @param[in] Argc Number of arguments
+ @param[in] Argv Array of pointers to arguments
+
+ @retval 0 Success
+ @retval other Error
+**/
+INT32
+MediaSanitizeUnitTestMain (
+ IN INT32 Argc,
+ IN CHAR8 *Argv[]
+ )
+{
+ return MediaSanitizeUnitTestEntry ();
+}
|