diff options
Diffstat (limited to 'MdeModulePkg')
-rw-r--r-- | MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c | 287 | ||||
-rw-r--r-- | MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.h | 208 | ||||
-rw-r--r-- | MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf | 2 | ||||
-rw-r--r-- | MdeModulePkg/Bus/Ata/AtaBusDxe/AtaPassThruExecute.c | 138 |
4 files changed, 622 insertions, 13 deletions
diff --git a/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c b/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c index 437eca725c..12af44dee3 100644 --- a/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c +++ b/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c @@ -72,6 +72,10 @@ ATA_DEVICE gAtaDeviceTemplate = { AtaDiskInfoWhichIde
},
NULL, // DevicePath
+ {
+ AtaStorageSecurityReceiveData,
+ AtaStorageSecuritySendData
+ },
NULL, // AtaBusDriverData
0, // Port
0, // PortMultiplierPort
@@ -327,6 +331,23 @@ RegisterAtaDevice ( goto Done;
}
+ //
+ // See if the ata device support trust computing feature or not.
+ // If yes, then install Storage Security Protocol at the ata device handle.
+ //
+ if ((AtaDevice->IdentifyData->trusted_computing_support & BIT0) != 0) {
+ DEBUG ((EFI_D_INFO, "Found TCG support in Port %x PortMultiplierPort %x\n", Port, PortMultiplierPort));
+ Status = gBS->InstallProtocolInterface (
+ &AtaDevice->Handle,
+ &gEfiStorageSecurityCommandProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &AtaDevice->StorageSecurity
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ }
+
gBS->OpenProtocol (
AtaBusDriverData->Controller,
&gEfiAtaPassThruProtocolGuid,
@@ -370,13 +391,15 @@ UnregisterAtaDevice ( IN EFI_HANDLE Handle
)
{
- EFI_STATUS Status;
- EFI_BLOCK_IO_PROTOCOL *BlockIo;
- EFI_BLOCK_IO2_PROTOCOL *BlockIo2;
- ATA_DEVICE *AtaDevice;
- EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru;
- BlockIo2 = NULL;
- BlockIo = NULL;
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ EFI_BLOCK_IO2_PROTOCOL *BlockIo2;
+ ATA_DEVICE *AtaDevice;
+ EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru;
+ EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *StorageSecurity;
+
+ BlockIo2 = NULL;
+ BlockIo = NULL;
Status = gBS->OpenProtocol (
Handle,
@@ -451,6 +474,37 @@ UnregisterAtaDevice ( 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,
+ &AtaDevice->StorageSecurity
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->OpenProtocol (
+ Controller,
+ &gEfiAtaPassThruProtocolGuid,
+ (VOID **) &AtaPassThru,
+ This->DriverBindingHandle,
+ Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ return Status;
+ }
+ }
+
ReleaseAtaResources (AtaDevice);
return Status;
}
@@ -1321,6 +1375,225 @@ AtaDiskInfoWhichIde ( return EFI_SUCCESS;
}
+/**
+ 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
+AtaStorageSecurityReceiveData (
+ 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;
+ ATA_DEVICE *Private;
+
+ DEBUG ((EFI_D_INFO, "EFI Storage Security Protocol - Read"));
+ if ((PayloadBuffer == NULL || PayloadTransferSize == NULL) && PayloadBufferSize != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ Private = ATA_DEVICE_FROM_STORAGE_SECURITY (This);
+
+ if (MediaId != Private->BlockIo.Media->MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (!Private->BlockIo.Media->MediaPresent) {
+ return EFI_NO_MEDIA;
+ }
+
+ Status = TrustTransferAtaDevice (
+ Private,
+ 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 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
+AtaStorageSecuritySendData (
+ 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;
+ ATA_DEVICE *Private;
+
+ DEBUG ((EFI_D_INFO, "EFI Storage Security Protocol - Send"));
+ if ((PayloadBuffer == NULL) && (PayloadBufferSize != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ Private = ATA_DEVICE_FROM_STORAGE_SECURITY (This);
+
+ if (MediaId != Private->BlockIo.Media->MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ Status = TrustTransferAtaDevice (
+ Private,
+ PayloadBuffer,
+ SecurityProtocolId,
+ SecurityProtocolSpecificData,
+ PayloadBufferSize,
+ TRUE,
+ Timeout,
+ NULL
+ );
+
+ return Status;
+}
/**
The user Entry Point for module AtaBus. The user code starts with this function.
diff --git a/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.h b/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.h index 4d036836e9..66a8a8f730 100644 --- a/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.h +++ b/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.h @@ -25,6 +25,7 @@ #include <Protocol/BlockIo2.h>
#include <Protocol/DiskInfo.h>
#include <Protocol/DevicePath.h>
+#include <Protocol/StorageSecurityCommand.h>
#include <Library/DebugLib.h>
#include <Library/UefiDriverEntryPoint.h>
@@ -75,10 +76,10 @@ //
#define MAX_MODEL_NAME_LEN 40
-#define ATA_TASK_SIGNATURE SIGNATURE_32 ('A', 'T', 'S', 'K')
-#define ATA_DEVICE_SIGNATURE SIGNATURE_32 ('A', 'B', 'I', 'D')
+#define ATA_TASK_SIGNATURE SIGNATURE_32 ('A', 'T', 'S', 'K')
+#define ATA_DEVICE_SIGNATURE SIGNATURE_32 ('A', 'B', 'I', 'D')
-#define IS_ALIGNED(addr, size) (((UINTN) (addr) & (size - 1)) == 0)
+#define IS_ALIGNED(addr, size) (((UINTN) (addr) & (size - 1)) == 0)
//
// Task for the non blocking I/O
@@ -114,6 +115,7 @@ typedef struct { EFI_BLOCK_IO_MEDIA BlockMedia;
EFI_DISK_INFO_PROTOCOL DiskInfo;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_STORAGE_SECURITY_COMMAND_PROTOCOL StorageSecurity;
ATA_BUS_DRIVER_DATA *AtaBusDriverData;
UINT16 Port;
@@ -137,12 +139,13 @@ typedef struct { EFI_UNICODE_STRING_TABLE *ControllerNameTable;
CHAR16 ModelName[MAX_MODEL_NAME_LEN + 1];
- LIST_ENTRY AtaTaskList;
+ LIST_ENTRY AtaTaskList;
} ATA_DEVICE;
#define ATA_DEVICE_FROM_BLOCK_IO(a) CR (a, ATA_DEVICE, BlockIo, ATA_DEVICE_SIGNATURE)
#define ATA_DEVICE_FROM_BLOCK_IO2(a) CR (a, ATA_DEVICE, BlockIo2, ATA_DEVICE_SIGNATURE)
#define ATA_DEVICE_FROM_DISK_INFO(a) CR (a, ATA_DEVICE, DiskInfo, ATA_DEVICE_SIGNATURE)
+#define ATA_DEVICE_FROM_STORAGE_SECURITY(a) CR (a, ATA_DEVICE, StorageSecurity, ATA_DEVICE_SIGNATURE)
#define ATA_AYNS_TASK_FROM_ENTRY(a) CR (a, ATA_BUS_ASYN_TASK, TaskEntry, ATA_TASK_SIGNATURE)
//
@@ -262,6 +265,45 @@ AccessAtaDevice( IN BOOLEAN IsWrite,
IN OUT EFI_BLOCK_IO2_TOKEN *Token
);
+/**
+ Trust transfer data from/to ATA device.
+
+ This function performs one ATA pass through transaction to do a trust transfer from/to
+ ATA device. It chooses the appropriate ATA command and protocol to invoke PassThru
+ interface of ATA pass through.
+
+ @param AtaDevice The ATA child device involved for the operation.
+ @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.
+
+ @retval EFI_SUCCESS The data transfer is complete successfully.
+ @return others Some error occurs when transferring data.
+
+**/
+EFI_STATUS
+EFIAPI
+TrustTransferAtaDevice (
+ IN OUT ATA_DEVICE *AtaDevice,
+ IN OUT VOID *Buffer,
+ IN UINT8 SecurityProtocolId,
+ IN UINT16 SecurityProtocolSpecificData,
+ IN UINTN TransferLength,
+ IN BOOLEAN IsTrustSend,
+ IN UINT64 Timeout,
+ OUT UINTN *TransferLengthOut
+ );
//
// Protocol interface prototypes
@@ -822,4 +864,162 @@ AtaDiskInfoWhichIde ( OUT UINT32 *IdeDevice
);
+/**
+ 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
+AtaStorageSecurityReceiveData (
+ 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
+AtaStorageSecuritySendData (
+ 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/Ata/AtaBusDxe/AtaBusDxe.inf b/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf index 18ed39d429..6cc75ec6d0 100644 --- a/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf +++ b/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf @@ -66,6 +66,6 @@ gEfiBlockIo2ProtocolGuid # BY_START
gEfiAtaPassThruProtocolGuid # TO_START
gEfiDevicePathProtocolGuid # TO_START
-
+ gEfiStorageSecurityCommandProtocolGuid # BY_START
diff --git a/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaPassThruExecute.c b/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaPassThruExecute.c index 1f204193fd..2445f1839f 100644 --- a/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaPassThruExecute.c +++ b/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaPassThruExecute.c @@ -3,7 +3,12 @@ This file implements the low level execution of ATA pass through transaction.
It transforms the high level identity, read/write, reset command to ATA pass
- through command and protocol.
+ through command and protocol.
+
+ NOTE: This file aslo implements the StorageSecurityCommandProtocol(SSP). For input
+ parameter SecurityProtocolSpecificData, ATA spec has no explicitly definition
+ for Security Protocol Specific layout. This implementation uses big edian for
+ Cylinder register.
Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
@@ -19,6 +24,12 @@ #include "AtaBus.h"
+#define ATA_CMD_TRUST_NON_DATA 0x5B
+#define ATA_CMD_TRUST_RECEIVE 0x5C
+#define ATA_CMD_TRUST_RECEIVE_DMA 0x5D
+#define ATA_CMD_TRUST_SEND 0x5E
+#define ATA_CMD_TRUST_SEND_DMA 0x5F
+
//
// Look up table (UdmaValid, IsWrite) for EFI_ATA_PASS_THRU_CMD_PROTOCOL
//
@@ -60,6 +71,21 @@ UINT8 mAtaCommands[][2][2] = { };
//
+// Look up table (UdmaValid, IsTrustSend) for ATA_CMD
+//
+UINT8 mAtaTrustCommands[2][2] = {
+ {
+ ATA_CMD_TRUST_RECEIVE, // PIO read
+ ATA_CMD_TRUST_SEND // PIO write
+ },
+ {
+ ATA_CMD_TRUST_RECEIVE_DMA, // DMA read
+ ATA_CMD_TRUST_SEND_DMA // DMA write
+ }
+};
+
+
+//
// Look up table (Lba48Bit) for maximum transfer block number
//
UINTN mMaxTransferBlockNumber[] = {
@@ -756,3 +782,113 @@ EXIT: return Status;
}
+
+/**
+ Trust transfer data from/to ATA device.
+
+ This function performs one ATA pass through transaction to do a trust transfer from/to
+ ATA device. It chooses the appropriate ATA command and protocol to invoke PassThru
+ interface of ATA pass through.
+
+ @param AtaDevice The ATA child device involved for the operation.
+ @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.
+
+ @retval EFI_SUCCESS The data transfer is complete successfully.
+ @return others Some error occurs when transferring data.
+
+**/
+EFI_STATUS
+EFIAPI
+TrustTransferAtaDevice (
+ IN OUT ATA_DEVICE *AtaDevice,
+ IN OUT VOID *Buffer,
+ IN UINT8 SecurityProtocolId,
+ IN UINT16 SecurityProtocolSpecificData,
+ IN UINTN TransferLength,
+ IN BOOLEAN IsTrustSend,
+ IN UINT64 Timeout,
+ OUT UINTN *TransferLengthOut
+ )
+{
+ EFI_ATA_COMMAND_BLOCK *Acb;
+ EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet;
+ EFI_STATUS Status;
+ VOID *NewBuffer;
+ EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru;
+
+ //
+ // Ensure AtaDevice->UdmaValid and IsTrustSend are valid boolean values
+ //
+ ASSERT ((UINTN) AtaDevice->UdmaValid < 2);
+ ASSERT ((UINTN) IsTrustSend < 2);
+ //
+ // Prepare for ATA command block.
+ //
+ Acb = ZeroMem (&AtaDevice->Acb, sizeof (*Acb));
+ if (TransferLength == 0) {
+ Acb->AtaCommand = ATA_CMD_TRUST_NON_DATA;
+ } else {
+ Acb->AtaCommand = mAtaTrustCommands[AtaDevice->UdmaValid][IsTrustSend];
+ }
+ Acb->AtaFeatures = SecurityProtocolId;
+ Acb->AtaSectorCount = (UINT8) (TransferLength / 512);
+ Acb->AtaSectorNumber = (UINT8) ((TransferLength / 512) >> 8);
+ //
+ // NOTE: ATA Spec has no explicitly definition for Security Protocol Specific layout.
+ // Here use big edian for Cylinder register.
+ //
+ Acb->AtaCylinderHigh = (UINT8) SecurityProtocolSpecificData;
+ Acb->AtaCylinderLow = (UINT8) (SecurityProtocolSpecificData >> 8);
+ Acb->AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 | (AtaDevice->PortMultiplierPort << 4));
+
+ //
+ // Prepare for ATA pass through packet.
+ //
+ Packet = ZeroMem (&AtaDevice->Packet, sizeof (*Packet));
+ if (TransferLength == 0) {
+ Packet->InTransferLength = 0;
+ Packet->OutTransferLength = 0;
+ Packet->Protocol = EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA;
+ } else if (IsTrustSend) {
+ //
+ // Check the alignment of the incoming buffer prior to invoking underlying ATA PassThru
+ //
+ AtaPassThru = AtaDevice->AtaBusDriverData->AtaPassThru;
+ if ((AtaPassThru->Mode->IoAlign > 1) && !IS_ALIGNED (Buffer, AtaPassThru->Mode->IoAlign)) {
+ NewBuffer = AllocateAlignedBuffer (AtaDevice, TransferLength);
+ CopyMem (NewBuffer, Buffer, TransferLength);
+ FreePool (Buffer);
+ Buffer = NewBuffer;
+ }
+ Packet->OutDataBuffer = Buffer;
+ Packet->OutTransferLength = (UINT32) TransferLength;
+ Packet->Protocol = mAtaPassThruCmdProtocols[AtaDevice->UdmaValid][IsTrustSend];
+ } else {
+ Packet->InDataBuffer = Buffer;
+ Packet->InTransferLength = (UINT32) TransferLength;
+ Packet->Protocol = mAtaPassThruCmdProtocols[AtaDevice->UdmaValid][IsTrustSend];
+ }
+ Packet->Length = EFI_ATA_PASS_THRU_LENGTH_BYTES;
+ Packet->Timeout = Timeout;
+
+ Status = AtaDevicePassThru (AtaDevice, NULL, NULL);
+ if (TransferLengthOut != NULL) {
+ if (! IsTrustSend) {
+ *TransferLengthOut = Packet->InTransferLength;
+ }
+ }
+ return Status;
+}
|