From c24097a59ffb10d63c805c4da65476ed6e297c5c Mon Sep 17 00:00:00 2001 From: hhuan13 Date: Wed, 4 May 2011 02:38:43 +0000 Subject: [PATCH] 1. Enabled SSP(StorageSecurityCommandProtocol) for ATA devices. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11614 6f19259b-4bc3-4df7-8a09-765794883524 --- MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c | 287 +++++++++++++++++- MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.h | 208 ++++++++++++- MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf | 2 +- .../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 #include #include +#include #include #include @@ -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.
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 // @@ -59,6 +70,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 // @@ -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; +} -- 2.39.2