Produce this protocol for each namespace at NVMe controller.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Tian Feng <[email protected]>
---
MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.c | 68 ++++-
MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.h | 39 ++-
.../Bus/Pci/NvmExpressDxe/NvmExpressBlockIo.c | 326 +++++++++++++++++++++
.../Bus/Pci/NvmExpressDxe/NvmExpressBlockIo.h | 160 +++++++++-
.../Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf | 1 +
MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.c | 8 +-
MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.h | 32 +-
.../Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c | 36 ++-
8 files changed, 628 insertions(+), 42 deletions(-)
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.c
b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.c
index d107d96..9938bf4 100644
--- a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.c
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.c
@@ -155,6 +155,12 @@ EnumerateNvmeDevNamespace (
Device->BlockIo.FlushBlocks = NvmeBlockIoFlushBlocks;
//
+ // Create StorageSecurityProtocol Instance
+ //
+ Device->StorageSecurity.ReceiveData = NvmeStorageSecurityReceiveData;
+ Device->StorageSecurity.SendData = NvmeStorageSecuritySendData;
+
+ //
// Create DiskInfo Protocol instance
//
InitializeDiskInfo (Device);
@@ -211,6 +217,32 @@ EnumerateNvmeDevNamespace (
if(EFI_ERROR(Status)) {
goto Exit;
}
+
+ //
+ // Check if the NVMe controller supports the Security Send and Security
Receive commands
+ //
+ if ((Private->ControllerData->Oacs & SECURITY_SEND_RECEIVE_SUPPORTED) !=
0) {
+ Status = gBS->InstallProtocolInterface (
+ &Device->DeviceHandle,
+ &gEfiStorageSecurityCommandProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &Device->StorageSecurity
+ );
+ if(EFI_ERROR(Status)) {
+ gBS->UninstallMultipleProtocolInterfaces (
+ &Device->DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ Device->DevicePath,
+ &gEfiBlockIoProtocolGuid,
+ &Device->BlockIo,
+ &gEfiDiskInfoProtocolGuid,
+ &Device->DiskInfo,
+ NULL
+ );
+ goto Exit;
+ }
+ }
+
gBS->OpenProtocol (
Private->ControllerHandle,
&gEfiNvmExpressPassThruProtocolGuid,
@@ -339,6 +371,7 @@ UnregisterNvmeNamespace (
EFI_BLOCK_IO_PROTOCOL *BlockIo;
NVME_DEVICE_PRIVATE_DATA *Device;
NVME_CONTROLLER_PRIVATE_DATA *Private;
+ EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *StorageSecurity;
BlockIo = NULL;
@@ -394,6 +427,37 @@ UnregisterNvmeNamespace (
return Status;
}
+ //
+ // If Storage Security Command Protocol is installed, then uninstall this
protocol.
+ //
+ Status = gBS->OpenProtocol (
+ Handle,
+ &gEfiStorageSecurityCommandProtocolGuid,
+ (VOID **) &StorageSecurity,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->UninstallProtocolInterface (
+ Handle,
+ &gEfiStorageSecurityCommandProtocolGuid,
+ &Device->StorageSecurity
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->OpenProtocol (
+ Controller,
+ &gEfiNvmExpressPassThruProtocolGuid,
+ (VOID **) &Private->Passthru,
+ This->DriverBindingHandle,
+ Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ return Status;
+ }
+ }
+
if(Device->DevicePath != NULL) {
FreePool (Device->DevicePath);
}
@@ -480,8 +544,8 @@ NvmExpressDriverBindingSupported (
if ((DevicePathNode.DevPath->Type != MESSAGING_DEVICE_PATH) ||
(DevicePathNode.DevPath->SubType != MSG_NVME_NAMESPACE_DP) ||
- DevicePathNodeLength(DevicePathNode.DevPath) !=
sizeof(NVME_NAMESPACE_DEVICE_PATH)) {
- return EFI_UNSUPPORTED;
+ (DevicePathNodeLength(DevicePathNode.DevPath) !=
sizeof(NVME_NAMESPACE_DEVICE_PATH))) {
+ return EFI_UNSUPPORTED;
}
}
}
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.h
b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.h
index 54baac6..21c6255 100644
--- a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.h
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.h
@@ -30,6 +30,7 @@
#include <Protocol/BlockIo.h>
#include <Protocol/DiskInfo.h>
#include <Protocol/DriverSupportedEfiVersion.h>
+#include <Protocol/StorageSecurityCommand.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
@@ -152,29 +153,30 @@ struct _NVME_CONTROLLER_PRIVATE_DATA {
// Nvme device private data structure
//
struct _NVME_DEVICE_PRIVATE_DATA {
- UINT32 Signature;
+ UINT32 Signature;
- EFI_HANDLE DeviceHandle;
- EFI_HANDLE ControllerHandle;
- EFI_HANDLE DriverBindingHandle;
+ EFI_HANDLE DeviceHandle;
+ EFI_HANDLE ControllerHandle;
+ EFI_HANDLE DriverBindingHandle;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- EFI_UNICODE_STRING_TABLE *ControllerNameTable;
+ EFI_UNICODE_STRING_TABLE *ControllerNameTable;
- UINT32 NamespaceId;
- UINT64 NamespaceUuid;
+ UINT32 NamespaceId;
+ UINT64 NamespaceUuid;
- EFI_BLOCK_IO_MEDIA Media;
- EFI_BLOCK_IO_PROTOCOL BlockIo;
- EFI_DISK_INFO_PROTOCOL DiskInfo;
+ EFI_BLOCK_IO_MEDIA Media;
+ EFI_BLOCK_IO_PROTOCOL BlockIo;
+ EFI_DISK_INFO_PROTOCOL DiskInfo;
+ EFI_STORAGE_SECURITY_COMMAND_PROTOCOL StorageSecurity;
- EFI_LBA NumBlocks;
+ EFI_LBA NumBlocks;
- CHAR16 ModelName[80];
- NVME_ADMIN_NAMESPACE_DATA NamespaceData;
+ CHAR16 ModelName[80];
+ NVME_ADMIN_NAMESPACE_DATA NamespaceData;
- NVME_CONTROLLER_PRIVATE_DATA *Controller;
+ NVME_CONTROLLER_PRIVATE_DATA *Controller;
};
@@ -195,6 +197,13 @@ struct _NVME_DEVICE_PRIVATE_DATA {
NVME_DEVICE_PRIVATE_DATA_SIGNATURE \
)
+#define NVME_DEVICE_PRIVATE_DATA_FROM_STORAGE_SECURITY(a)\
+ CR (a, \
+ NVME_DEVICE_PRIVATE_DATA, \
+ StorageSecurity, \
+ NVME_DEVICE_PRIVATE_DATA_SIGNATURE \
+ )
+
/**
Retrieves a Unicode string that is the user readable name of the driver.
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressBlockIo.c
b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressBlockIo.c
index e7d7651..6cb2f92 100644
--- a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressBlockIo.c
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressBlockIo.c
@@ -345,6 +345,10 @@ NvmeBlockIoReset (
Status = NvmeControllerInit (Private);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
gBS->RestoreTPL (OldTpl);
return Status;
@@ -555,3 +559,325 @@ NvmeBlockIoFlushBlocks (
return Status;
}
+
+/**
+ Trust transfer data from/to NVMe device.
+
+ This function performs one NVMe transaction to do a trust transfer from/to
NVMe device.
+
+ @param Private The pointer to the
NVME_CONTROLLER_PRIVATE_DATA data structure.
+ @param Buffer The pointer to the current transaction
buffer.
+ @param SecurityProtocolId The value of the "Security Protocol"
parameter of
+ the security protocol command to be
sent.
+ @param SecurityProtocolSpecificData The value of the "Security Protocol
Specific" parameter
+ of the security protocol command to be
sent.
+ @param TransferLength The block number or sector count of the
transfer.
+ @param IsTrustSend Indicates whether it is a trust send
operation or not.
+ @param Timeout The timeout, in 100ns units, to use for
the execution
+ of the security protocol command. A
Timeout value of 0
+ means that this function will wait
indefinitely for the
+ security protocol command to execute.
If Timeout is greater
+ than zero, then this function will
return EFI_TIMEOUT
+ if the time required to execute the
receive data command
+ is greater than Timeout.
+ @param TransferLengthOut A pointer to a buffer to store the size
in bytes of the data
+ written to the buffer. Ignore it when
IsTrustSend is TRUE.
+
+ @retval EFI_SUCCESS The data transfer is complete successfully.
+ @return others Some error occurs when transferring data.
+
+**/
+EFI_STATUS
+TrustTransferNvmeDevice (
+ IN OUT NVME_CONTROLLER_PRIVATE_DATA *Private,
+ IN OUT VOID *Buffer,
+ IN UINT8 SecurityProtocolId,
+ IN UINT16 SecurityProtocolSpecificData,
+ IN UINTN TransferLength,
+ IN BOOLEAN IsTrustSend,
+ IN UINT64 Timeout,
+ OUT UINTN *TransferLengthOut
+ )
+{
+ EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
+ EFI_NVM_EXPRESS_COMMAND Command;
+ EFI_NVM_EXPRESS_COMPLETION Completion;
+ EFI_STATUS Status;
+ UINT16 SpecificData;
+
+ 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;
+
+ //
+ // Change Endianness of SecurityProtocolSpecificData
+ //
+ SpecificData = (((SecurityProtocolSpecificData << 8) & 0xFF00) |
(SecurityProtocolSpecificData >> 8));
+
+ if (IsTrustSend) {
+ Command.Cdw0.Opcode = NVME_ADMIN_SECURITY_SEND_CMD;
+ CommandPacket.TransferBuffer = Buffer;
+ CommandPacket.TransferLength = (UINT32)TransferLength;
+ CommandPacket.NvmeCmd->Cdw10 = (UINT32)((SecurityProtocolId << 24) |
(SpecificData << 8));
+ CommandPacket.NvmeCmd->Cdw11 = (UINT32)TransferLength;
+ } else {
+ Command.Cdw0.Opcode = NVME_ADMIN_SECURITY_RECEIVE_CMD;
+ CommandPacket.TransferBuffer = Buffer;
+ CommandPacket.TransferLength = (UINT32)TransferLength;
+ CommandPacket.NvmeCmd->Cdw10 = (UINT32)((SecurityProtocolId << 24) |
(SpecificData << 8));
+ CommandPacket.NvmeCmd->Cdw11 = (UINT32)TransferLength;
+ }
+
+ CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
+ CommandPacket.NvmeCmd->Nsid = NVME_CONTROLLER_ID;
+ CommandPacket.CommandTimeout = Timeout;
+ CommandPacket.QueueType = NVME_ADMIN_QUEUE;
+
+ Status = Private->Passthru.PassThru (
+ &Private->Passthru,
+ NVME_CONTROLLER_ID,
+ &CommandPacket,
+ NULL
+ );
+
+ if (!IsTrustSend) {
+ if (EFI_ERROR (Status)) {
+ *TransferLengthOut = 0;
+ } else {
+ *TransferLengthOut = (UINTN) TransferLength;
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Send a security protocol command to a device that receives data and/or the
result
+ of one or more commands sent by SendData.
+
+ The ReceiveData function sends a security protocol command to the given
MediaId.
+ The security protocol command sent is defined by SecurityProtocolId and
contains
+ the security protocol specific data SecurityProtocolSpecificData. The
function
+ returns the data from the security protocol command in PayloadBuffer.
+
+ For devices supporting the SCSI command set, the security protocol command
is sent
+ using the SECURITY PROTOCOL IN command defined in SPC-4.
+
+ For devices supporting the ATA command set, the security protocol command is
sent
+ using one of the TRUSTED RECEIVE commands defined in ATA8-ACS if
PayloadBufferSize
+ is non-zero.
+
+ If the PayloadBufferSize is zero, the security protocol command is sent
using the
+ Trusted Non-Data command defined in ATA8-ACS.
+
+ If PayloadBufferSize is too small to store the available data from the
security
+ protocol command, the function shall copy PayloadBufferSize bytes into the
+ PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL.
+
+ If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is
non-zero,
+ the function shall return EFI_INVALID_PARAMETER.
+
+ If the given MediaId does not support security protocol commands, the
function shall
+ return EFI_UNSUPPORTED. If there is no media in the device, the function
returns
+ EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the
device,
+ the function returns EFI_MEDIA_CHANGED.
+
+ If the security protocol fails to complete within the Timeout period, the
function
+ shall return EFI_TIMEOUT.
+
+ If the security protocol command completes without an error, the function
shall
+ return EFI_SUCCESS. If the security protocol command completes with an
error, the
+ function shall return EFI_DEVICE_ERROR.
+
+ @param This Indicates a pointer to the calling
context.
+ @param MediaId ID of the medium to receive data from.
+ @param Timeout The timeout, in 100ns units, to use for
the execution
+ of the security protocol command. A
Timeout value of 0
+ means that this function will wait
indefinitely for the
+ security protocol command to execute.
If Timeout is greater
+ than zero, then this function will
return EFI_TIMEOUT
+ if the time required to execute the
receive data command
+ is greater than Timeout.
+ @param SecurityProtocolId The value of the "Security Protocol"
parameter of
+ the security protocol command to be
sent.
+ @param SecurityProtocolSpecificData The value of the "Security Protocol
Specific" parameter
+ of the security protocol command to be
sent.
+ @param PayloadBufferSize Size in bytes of the payload data
buffer.
+ @param PayloadBuffer A pointer to a destination buffer to
store the security
+ protocol command specific payload data
for the security
+ protocol command. The caller is
responsible for having
+ either implicit or explicit ownership
of the buffer.
+ @param PayloadTransferSize A pointer to a buffer to store the size
in bytes of the
+ data written to the payload data buffer.
+
+ @retval EFI_SUCCESS The security protocol command completed
successfully.
+ @retval EFI_WARN_BUFFER_TOO_SMALL The PayloadBufferSize was too small to
store the available
+ data from the device. The PayloadBuffer
contains the truncated data.
+ @retval EFI_UNSUPPORTED The given MediaId does not support
security protocol commands.
+ @retval EFI_DEVICE_ERROR The security protocol command completed
with an error.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId is not for the current
media.
+ @retval EFI_INVALID_PARAMETER The PayloadBuffer or
PayloadTransferSize is NULL and
+ PayloadBufferSize is non-zero.
+ @retval EFI_TIMEOUT A timeout occurred while waiting for
the security
+ protocol command to execute.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmeStorageSecurityReceiveData (
+ IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT64 Timeout,
+ IN UINT8 SecurityProtocolId,
+ IN UINT16 SecurityProtocolSpecificData,
+ IN UINTN PayloadBufferSize,
+ OUT VOID *PayloadBuffer,
+ OUT UINTN *PayloadTransferSize
+ )
+{
+ EFI_STATUS Status;
+ NVME_DEVICE_PRIVATE_DATA *Device;
+
+ Status = EFI_SUCCESS;
+
+ if ((PayloadBuffer == NULL) || (PayloadTransferSize == NULL) ||
(PayloadBufferSize == 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Device = NVME_DEVICE_PRIVATE_DATA_FROM_STORAGE_SECURITY (This);
+
+ if (MediaId != Device->BlockIo.Media->MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (!Device->BlockIo.Media->MediaPresent) {
+ return EFI_NO_MEDIA;
+ }
+
+ Status = TrustTransferNvmeDevice (
+ Device->Controller,
+ PayloadBuffer,
+ SecurityProtocolId,
+ SecurityProtocolSpecificData,
+ PayloadBufferSize,
+ FALSE,
+ Timeout,
+ PayloadTransferSize
+ );
+
+ return Status;
+}
+
+/**
+ Send a security protocol command to a device.
+
+ The SendData function sends a security protocol command containing the
payload
+ PayloadBuffer to the given MediaId. The security protocol command sent is
+ defined by SecurityProtocolId and contains the security protocol specific
data
+ SecurityProtocolSpecificData. If the underlying protocol command requires a
+ specific padding for the command payload, the SendData function shall add
padding
+ bytes to the command payload to satisfy the padding requirements.
+
+ For devices supporting the SCSI command set, the security protocol command
is sent
+ using the SECURITY PROTOCOL OUT command defined in SPC-4.
+
+ For devices supporting the ATA command set, the security protocol command is
sent
+ using one of the TRUSTED SEND commands defined in ATA8-ACS if
PayloadBufferSize
+ is non-zero. If the PayloadBufferSize is zero, the security protocol command
is
+ sent using the Trusted Non-Data command defined in ATA8-ACS.
+
+ If PayloadBuffer is NULL and PayloadBufferSize is non-zero, the function
shall
+ return EFI_INVALID_PARAMETER.
+
+ If the given MediaId does not support security protocol commands, the
function
+ shall return EFI_UNSUPPORTED. If there is no media in the device, the
function
+ returns EFI_NO_MEDIA. If the MediaId is not the ID for the current media in
the
+ device, the function returns EFI_MEDIA_CHANGED.
+
+ If the security protocol fails to complete within the Timeout period, the
function
+ shall return EFI_TIMEOUT.
+
+ If the security protocol command completes without an error, the function
shall return
+ EFI_SUCCESS. If the security protocol command completes with an error, the
function
+ shall return EFI_DEVICE_ERROR.
+
+ @param This Indicates a pointer to the calling
context.
+ @param MediaId ID of the medium to receive data from.
+ @param Timeout The timeout, in 100ns units, to use for
the execution
+ of the security protocol command. A
Timeout value of 0
+ means that this function will wait
indefinitely for the
+ security protocol command to execute.
If Timeout is greater
+ than zero, then this function will
return EFI_TIMEOUT
+ if the time required to execute the
send data command
+ is greater than Timeout.
+ @param SecurityProtocolId The value of the "Security Protocol"
parameter of
+ the security protocol command to be
sent.
+ @param SecurityProtocolSpecificData The value of the "Security Protocol
Specific" parameter
+ of the security protocol command to be
sent.
+ @param PayloadBufferSize Size in bytes of the payload data
buffer.
+ @param PayloadBuffer A pointer to a destination buffer to
store the security
+ protocol command specific payload data
for the security
+ protocol command.
+
+ @retval EFI_SUCCESS The security protocol command completed
successfully.
+ @retval EFI_UNSUPPORTED The given MediaId does not support
security protocol commands.
+ @retval EFI_DEVICE_ERROR The security protocol command completed
with an error.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId is not for the current
media.
+ @retval EFI_INVALID_PARAMETER The PayloadBuffer is NULL and
PayloadBufferSize is non-zero.
+ @retval EFI_TIMEOUT A timeout occurred while waiting for
the security
+ protocol command to execute.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmeStorageSecuritySendData (
+ IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT64 Timeout,
+ IN UINT8 SecurityProtocolId,
+ IN UINT16 SecurityProtocolSpecificData,
+ IN UINTN PayloadBufferSize,
+ IN VOID *PayloadBuffer
+ )
+{
+ EFI_STATUS Status;
+ NVME_DEVICE_PRIVATE_DATA *Device;
+
+ Status = EFI_SUCCESS;
+
+ if ((PayloadBuffer == NULL) && (PayloadBufferSize != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Device = NVME_DEVICE_PRIVATE_DATA_FROM_STORAGE_SECURITY (This);
+
+ if (MediaId != Device->BlockIo.Media->MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (!Device->BlockIo.Media->MediaPresent) {
+ return EFI_NO_MEDIA;
+ }
+
+ Status = TrustTransferNvmeDevice (
+ Device->Controller,
+ PayloadBuffer,
+ SecurityProtocolId,
+ SecurityProtocolSpecificData,
+ PayloadBufferSize,
+ TRUE,
+ Timeout,
+ NULL
+ );
+
+ return Status;
+}
+
+
+
+
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressBlockIo.h
b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressBlockIo.h
index 5f896fe..1c71a81 100644
--- a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressBlockIo.h
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressBlockIo.h
@@ -1,7 +1,7 @@
/** @file
Header file for EFI_BLOCK_IO_PROTOCOL interface.
-Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD
License
which accompanies this distribution. The full text of the license may be
found at
@@ -108,4 +108,162 @@ NvmeBlockIoFlushBlocks (
IN EFI_BLOCK_IO_PROTOCOL *This
);
+/**
+ Send a security protocol command to a device that receives data and/or the
result
+ of one or more commands sent by SendData.
+
+ The ReceiveData function sends a security protocol command to the given
MediaId.
+ The security protocol command sent is defined by SecurityProtocolId and
contains
+ the security protocol specific data SecurityProtocolSpecificData. The
function
+ returns the data from the security protocol command in PayloadBuffer.
+
+ For devices supporting the SCSI command set, the security protocol command
is sent
+ using the SECURITY PROTOCOL IN command defined in SPC-4.
+
+ For devices supporting the ATA command set, the security protocol command is
sent
+ using one of the TRUSTED RECEIVE commands defined in ATA8-ACS if
PayloadBufferSize
+ is non-zero.
+
+ If the PayloadBufferSize is zero, the security protocol command is sent
using the
+ Trusted Non-Data command defined in ATA8-ACS.
+
+ If PayloadBufferSize is too small to store the available data from the
security
+ protocol command, the function shall copy PayloadBufferSize bytes into the
+ PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL.
+
+ If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is
non-zero,
+ the function shall return EFI_INVALID_PARAMETER.
+
+ If the given MediaId does not support security protocol commands, the
function shall
+ return EFI_UNSUPPORTED. If there is no media in the device, the function
returns
+ EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the
device,
+ the function returns EFI_MEDIA_CHANGED.
+
+ If the security protocol fails to complete within the Timeout period, the
function
+ shall return EFI_TIMEOUT.
+
+ If the security protocol command completes without an error, the function
shall
+ return EFI_SUCCESS. If the security protocol command completes with an
error, the
+ function shall return EFI_DEVICE_ERROR.
+
+ @param This Indicates a pointer to the calling
context.
+ @param MediaId ID of the medium to receive data from.
+ @param Timeout The timeout, in 100ns units, to use for
the execution
+ of the security protocol command. A
Timeout value of 0
+ means that this function will wait
indefinitely for the
+ security protocol command to execute.
If Timeout is greater
+ than zero, then this function will
return EFI_TIMEOUT
+ if the time required to execute the
receive data command
+ is greater than Timeout.
+ @param SecurityProtocolId The value of the "Security Protocol"
parameter of
+ the security protocol command to be
sent.
+ @param SecurityProtocolSpecificData The value of the "Security Protocol
Specific" parameter
+ of the security protocol command to be
sent.
+ @param PayloadBufferSize Size in bytes of the payload data
buffer.
+ @param PayloadBuffer A pointer to a destination buffer to
store the security
+ protocol command specific payload data
for the security
+ protocol command. The caller is
responsible for having
+ either implicit or explicit ownership
of the buffer.
+ @param PayloadTransferSize A pointer to a buffer to store the size
in bytes of the
+ data written to the payload data buffer.
+
+ @retval EFI_SUCCESS The security protocol command completed
successfully.
+ @retval EFI_WARN_BUFFER_TOO_SMALL The PayloadBufferSize was too small to
store the available
+ data from the device. The PayloadBuffer
contains the truncated data.
+ @retval EFI_UNSUPPORTED The given MediaId does not support
security protocol commands.
+ @retval EFI_DEVICE_ERROR The security protocol command completed
with an error.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId is not for the current
media.
+ @retval EFI_INVALID_PARAMETER The PayloadBuffer or
PayloadTransferSize is NULL and
+ PayloadBufferSize is non-zero.
+ @retval EFI_TIMEOUT A timeout occurred while waiting for
the security
+ protocol command to execute.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmeStorageSecurityReceiveData (
+ IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT64 Timeout,
+ IN UINT8 SecurityProtocolId,
+ IN UINT16 SecurityProtocolSpecificData,
+ IN UINTN PayloadBufferSize,
+ OUT VOID *PayloadBuffer,
+ OUT UINTN *PayloadTransferSize
+ );
+
+/**
+ Send a security protocol command to a device.
+
+ The SendData function sends a security protocol command containing the
payload
+ PayloadBuffer to the given MediaId. The security protocol command sent is
+ defined by SecurityProtocolId and contains the security protocol specific
data
+ SecurityProtocolSpecificData. If the underlying protocol command requires a
+ specific padding for the command payload, the SendData function shall add
padding
+ bytes to the command payload to satisfy the padding requirements.
+
+ For devices supporting the SCSI command set, the security protocol command
is sent
+ using the SECURITY PROTOCOL OUT command defined in SPC-4.
+
+ For devices supporting the ATA command set, the security protocol command is
sent
+ using one of the TRUSTED SEND commands defined in ATA8-ACS if
PayloadBufferSize
+ is non-zero. If the PayloadBufferSize is zero, the security protocol command
is
+ sent using the Trusted Non-Data command defined in ATA8-ACS.
+
+ If PayloadBuffer is NULL and PayloadBufferSize is non-zero, the function
shall
+ return EFI_INVALID_PARAMETER.
+
+ If the given MediaId does not support security protocol commands, the
function
+ shall return EFI_UNSUPPORTED. If there is no media in the device, the
function
+ returns EFI_NO_MEDIA. If the MediaId is not the ID for the current media in
the
+ device, the function returns EFI_MEDIA_CHANGED.
+
+ If the security protocol fails to complete within the Timeout period, the
function
+ shall return EFI_TIMEOUT.
+
+ If the security protocol command completes without an error, the function
shall return
+ EFI_SUCCESS. If the security protocol command completes with an error, the
function
+ shall return EFI_DEVICE_ERROR.
+
+ @param This Indicates a pointer to the calling
context.
+ @param MediaId ID of the medium to receive data from.
+ @param Timeout The timeout, in 100ns units, to use for
the execution
+ of the security protocol command. A
Timeout value of 0
+ means that this function will wait
indefinitely for the
+ security protocol command to execute.
If Timeout is greater
+ than zero, then this function will
return EFI_TIMEOUT
+ if the time required to execute the
receive data command
+ is greater than Timeout.
+ @param SecurityProtocolId The value of the "Security Protocol"
parameter of
+ the security protocol command to be
sent.
+ @param SecurityProtocolSpecificData The value of the "Security Protocol
Specific" parameter
+ of the security protocol command to be
sent.
+ @param PayloadBufferSize Size in bytes of the payload data
buffer.
+ @param PayloadBuffer A pointer to a destination buffer to
store the security
+ protocol command specific payload data
for the security
+ protocol command.
+
+ @retval EFI_SUCCESS The security protocol command completed
successfully.
+ @retval EFI_UNSUPPORTED The given MediaId does not support
security protocol commands.
+ @retval EFI_DEVICE_ERROR The security protocol command completed
with an error.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId is not for the current
media.
+ @retval EFI_INVALID_PARAMETER The PayloadBuffer is NULL and
PayloadBufferSize is non-zero.
+ @retval EFI_TIMEOUT A timeout occurred while waiting for
the security
+ protocol command to execute.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmeStorageSecuritySendData (
+ IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT64 Timeout,
+ IN UINT8 SecurityProtocolId,
+ IN UINT16 SecurityProtocolSpecificData,
+ IN UINTN PayloadBufferSize,
+ IN VOID *PayloadBuffer
+ );
+
#endif
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
index f73d6af..00acf2b 100644
--- a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
@@ -68,6 +68,7 @@
gEfiNvmExpressPassThruProtocolGuid ## BY_START
gEfiBlockIoProtocolGuid ## BY_START
gEfiDiskInfoProtocolGuid ## BY_START
+ gEfiStorageSecurityCommandProtocolGuid ## BY_START
gEfiDriverSupportedEfiVersionProtocolGuid ## PRODUCES
# [Event]
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.c
b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.c
index e35f3c0..f6b6288 100644
--- a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.c
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.c
@@ -582,7 +582,7 @@ NvmeIdentifyController (
ZeroMem (&Command, sizeof(EFI_NVM_EXPRESS_COMMAND));
ZeroMem (&Completion, sizeof(EFI_NVM_EXPRESS_COMPLETION));
- Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_OPC;
+ Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_CMD;
//
// According to Nvm Express 1.1 spec Figure 38, When not used, the field
shall be cleared to 0h.
// For the Identify command, the Namespace Identifier is only used for the
Namespace data structure.
@@ -641,7 +641,7 @@ NvmeIdentifyNamespace (
CommandPacket.NvmeCmd = &Command;
CommandPacket.NvmeCompletion = &Completion;
- Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_OPC;
+ Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_CMD;
Command.Nsid = NamespaceId;
CommandPacket.TransferBuffer = Buffer;
CommandPacket.TransferLength = sizeof (NVME_ADMIN_NAMESPACE_DATA);
@@ -691,7 +691,7 @@ NvmeCreateIoCompletionQueue (
CommandPacket.NvmeCmd = &Command;
CommandPacket.NvmeCompletion = &Completion;
- Command.Cdw0.Opcode = NVME_ADMIN_CRIOCQ_OPC;
+ Command.Cdw0.Opcode = NVME_ADMIN_CRIOCQ_CMD;
CommandPacket.TransferBuffer = Private->CqBufferPciAddr[1];
CommandPacket.TransferLength = EFI_PAGE_SIZE;
CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
@@ -741,7 +741,7 @@ NvmeCreateIoSubmissionQueue (
CommandPacket.NvmeCmd = &Command;
CommandPacket.NvmeCompletion = &Completion;
- Command.Cdw0.Opcode = NVME_ADMIN_CRIOSQ_OPC;
+ Command.Cdw0.Opcode = NVME_ADMIN_CRIOSQ_CMD;
CommandPacket.TransferBuffer = Private->SqBufferPciAddr[1];
CommandPacket.TransferLength = EFI_PAGE_SIZE;
CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.h
b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.h
index aa0ac35..96d80ec 100644
--- a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.h
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.h
@@ -2,7 +2,7 @@
NvmExpressDxe driver is used to manage non-volatile memory subsystem which
follows
NVM Express specification.
- Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD
License
which accompanies this distribution. The full text of the license may be
found at
@@ -348,6 +348,10 @@ typedef struct {
// Admin Command Set Attributes
//
UINT16 Oacs; /* Optional Admin Command Support */
+ #define NAMESPACE_MANAGEMENT_SUPPORTED BIT3
+ #define FW_DOWNLOAD_ACTIVATE_SUPORTED BIT2
+ #define FORMAT_NVM_SUPPORTED BIT1
+ #define SECURITY_SEND_RECEIVE_SUPPORTED BIT0
UINT8 Acl; /* Abort Command Limit */
UINT8 Aerl; /* Async Event Request Limit */
UINT8 Frmw; /* Firmware updates */
@@ -556,9 +560,9 @@ typedef struct {
// CDW 10
//
UINT32 Lid:8; /* Log Page Identifier */
- #define LID_ERROR_INFO
- #define LID_SMART_INFO
- #define LID_FW_SLOT_INFO
+ #define LID_ERROR_INFO 0x1
+ #define LID_SMART_INFO 0x2
+ #define LID_FW_SLOT_INFO 0x3
UINT32 Rsvd1:8;
UINT32 Numd:12; /* Number of Dwords */
UINT32 Rsvd2:4; /* Reserved as of Nvm Express 1.1 Spec */
@@ -724,9 +728,23 @@ typedef struct {
//
// Nvm Express Admin cmd opcodes
//
-#define NVME_ADMIN_CRIOSQ_OPC 1
-#define NVME_ADMIN_CRIOCQ_OPC 5
-#define NVME_ADMIN_IDENTIFY_OPC 6
+#define NVME_ADMIN_DEIOSQ_CMD 0x00
+#define NVME_ADMIN_CRIOSQ_CMD 0x01
+#define NVME_ADMIN_GET_LOG_PAGE_CMD 0x02
+#define NVME_ADMIN_DEIOCQ_CMD 0x04
+#define NVME_ADMIN_CRIOCQ_CMD 0x05
+#define NVME_ADMIN_IDENTIFY_CMD 0x06
+#define NVME_ADMIN_ABORT_CMD 0x08
+#define NVME_ADMIN_SET_FEATURES_CMD 0x09
+#define NVME_ADMIN_GET_FEATURES_CMD 0x0A
+#define NVME_ADMIN_ASYNC_EVENT_REQUEST_CMD 0x0C
+#define NVME_ADMIN_NAMESACE_MANAGEMENT_CMD 0x0D
+#define NVME_ADMIN_FW_COMMIT_CMD 0x10
+#define NVME_ADMIN_FW_IAMGE_DOWNLOAD_CMD 0x11
+#define NVME_ADMIN_NAMESACE_ATTACHMENT_CMD 0x15
+#define NVME_ADMIN_FORMAT_NVM_CMD 0x80
+#define NVME_ADMIN_SECURITY_SEND_CMD 0x81
+#define NVME_ADMIN_SECURITY_RECEIVE_CMD 0x82
#define NVME_IO_FLUSH_OPC 0
#define NVME_IO_WRITE_OPC 1
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c
b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c
index d37194a..f987152 100644
--- a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c
@@ -433,7 +433,7 @@ NvmExpressPassThru (
// these two cmds are special which requires their data buffer must support
simultaneous access by both the
// processor and a PCI Bus Master. It's caller's responsbility to ensure
this.
//
- if (((Sq->Opc & (BIT0 | BIT1)) != 0) && (Sq->Opc != NVME_ADMIN_CRIOCQ_OPC)
&& (Sq->Opc != NVME_ADMIN_CRIOSQ_OPC)) {
+ if (((Sq->Opc & (BIT0 | BIT1)) != 0) && (Sq->Opc != NVME_ADMIN_CRIOCQ_CMD)
&& (Sq->Opc != NVME_ADMIN_CRIOSQ_CMD)) {
if ((Sq->Opc & BIT0) != 0) {
Flag = EfiPciIoOperationBusMasterRead;
} else {
@@ -567,21 +567,31 @@ NvmExpressPassThru (
}
}
- if ((Private->CqHdbl[QueueType].Cqh ^= 1) == 0) {
- Private->Pt[QueueType] ^= 1;
- }
-
//
- // Copy the Respose Queue entry for this command to the callers response
buffer
+ // Check the NVMe cmd execution result
//
- CopyMem(Packet->NvmeCompletion, Cq, sizeof(EFI_NVM_EXPRESS_COMPLETION));
+ if (Status != EFI_TIMEOUT) {
+ if ((Cq->Sct == 0) && (Cq->Sc == 0)) {
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_DEVICE_ERROR;
+ //
+ // Copy the Respose Queue entry for this command to the callers response
buffer
+ //
+ CopyMem(Packet->NvmeCompletion, Cq, sizeof(EFI_NVM_EXPRESS_COMPLETION));
+
+ //
+ // Dump every completion entry status for debugging.
+ //
+ DEBUG_CODE_BEGIN();
+ NvmeDumpStatus(Cq);
+ DEBUG_CODE_END();
+ }
+ }
- //
- // Dump every completion entry status for debugging.
- //
- DEBUG_CODE_BEGIN();
- NvmeDumpStatus(Cq);
- DEBUG_CODE_END();
+ if ((Private->CqHdbl[QueueType].Cqh ^= 1) == 0) {
+ Private->Pt[QueueType] ^= 1;
+ }
Data = ReadUnaligned32 ((UINT32*)&Private->CqHdbl[QueueType]);
PciIo->Mem.Write (
--
1.9.5.msysgit.0
------------------------------------------------------------------------------
_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-devel