+/**\r
+ Execute Security Protocol In SCSI command on a specific SCSI target.\r
+\r
+ Executes the SCSI Security Protocol In command on the SCSI target specified by ScsiIo.\r
+ If Timeout is zero, then this function waits indefinitely for the command to complete.\r
+ If Timeout is greater than zero, then the command is executed and will timeout after\r
+ Timeout 100 ns units.\r
+ If ScsiIo is NULL, then ASSERT().\r
+ If SenseDataLength is NULL, then ASSERT().\r
+ If HostAdapterStatus is NULL, then ASSERT().\r
+ If TargetStatus is NULL, then ASSERT().\r
+ If TransferLength is NULL, then ASSERT().\r
+\r
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+ gets returned.\r
+\r
+ If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer\r
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+ gets returned.\r
+\r
+ @param[in] ScsiIo SCSI IO Protocol to use.\r
+ @param[in] Timeout The length of timeout period.\r
+ @param[in, out] SenseData A pointer to output sense data.\r
+ @param[in, out] SenseDataLength The length of output sense data.\r
+ @param[out] HostAdapterStatus The status of Host Adapter.\r
+ @param[out] TargetStatus The status of the target.\r
+ @param[in] SecurityProtocol The Security Protocol to use.\r
+ @param[in] SecurityProtocolSpecific The Security Protocol Specific data.\r
+ @param[in] Inc512 If TRUE, 512 increment (INC_512) bit will be set for the\r
+ SECURITY PROTOCOL IN command.\r
+ @param[in] DataLength The size in bytes of the data buffer.\r
+ @param[in, out] DataBuffer A pointer to a data buffer.\r
+ @param[out] TransferLength A pointer to a buffer to store the size in\r
+ bytes of the data written to the data buffer.\r
+\r
+ @retval EFI_SUCCESS Command is executed successfully.\r
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could\r
+ not be transferred. The actual number of bytes transferred is returned in TransferLength.\r
+ @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many\r
+ SCSI Command Packets already queued.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
+ @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by\r
+ the SCSI initiator(i.e., SCSI Host Controller)\r
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ScsiSecurityProtocolInCommand (\r
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
+ IN UINT64 Timeout,\r
+ IN OUT VOID *SenseData, OPTIONAL\r
+ IN OUT UINT8 *SenseDataLength,\r
+ OUT UINT8 *HostAdapterStatus,\r
+ OUT UINT8 *TargetStatus,\r
+ IN UINT8 SecurityProtocol,\r
+ IN UINT16 SecurityProtocolSpecific,\r
+ IN BOOLEAN Inc512,\r
+ IN UINTN DataLength,\r
+ IN OUT VOID *DataBuffer, OPTIONAL\r
+ OUT UINTN *TransferLength\r
+ )\r
+{\r
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
+ EFI_STATUS Status;\r
+ UINT8 Cdb[EFI_SCSI_OP_LENGTH_TWELVE];\r
+\r
+ ASSERT (SenseDataLength != NULL);\r
+ ASSERT (HostAdapterStatus != NULL);\r
+ ASSERT (TargetStatus != NULL);\r
+ ASSERT (ScsiIo != NULL);\r
+ ASSERT (TransferLength != NULL);\r
+ ASSERT (DataLength <= MAX_UINT32);\r
+\r
+ ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
+ ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TWELVE);\r
+\r
+ CommandPacket.Timeout = Timeout;\r
+ CommandPacket.InDataBuffer = DataBuffer;\r
+ CommandPacket.SenseData = SenseData;\r
+ CommandPacket.InTransferLength = (UINT32) DataLength;\r
+ CommandPacket.Cdb = Cdb;\r
+ //\r
+ // Fill Cdb for Security Protocol In Command\r
+ //\r
+ Cdb[0] = EFI_SCSI_OP_SECURITY_PROTOCOL_IN;\r
+ Cdb[1] = SecurityProtocol;\r
+ WriteUnaligned16 ((UINT16 *)&Cdb[2], SwapBytes16 (SecurityProtocolSpecific));\r
+\r
+ if (Inc512) {\r
+ if (DataLength % 512 != 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ Cdb[4] = BIT7;\r
+ WriteUnaligned32 ((UINT32 *)&Cdb[6], SwapBytes32 ((UINT32) DataLength / 512));\r
+ } else {\r
+ WriteUnaligned32 ((UINT32 *)&Cdb[6], SwapBytes32 ((UINT32) DataLength));\r
+ }\r
+\r
+ CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TWELVE;\r
+ CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
+ CommandPacket.SenseDataLength = *SenseDataLength;\r
+\r
+ Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
+\r
+ *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
+ *TargetStatus = CommandPacket.TargetStatus;\r
+ *SenseDataLength = CommandPacket.SenseDataLength;\r
+ *TransferLength = (UINTN) CommandPacket.InTransferLength;\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Execute Security Protocol Out SCSI command on a specific SCSI target.\r
+\r
+ Executes the SCSI Security Protocol Out command on the SCSI target specified by ScsiIo.\r
+ If Timeout is zero, then this function waits indefinitely for the command to complete.\r
+ If Timeout is greater than zero, then the command is executed and will timeout after\r
+ Timeout 100 ns units.\r
+ If ScsiIo is NULL, then ASSERT().\r
+ If SenseDataLength is NULL, then ASSERT().\r
+ If HostAdapterStatus is NULL, then ASSERT().\r
+ If TargetStatus is NULL, then ASSERT().\r
+\r
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+ gets returned.\r
+\r
+ If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer\r
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+ gets returned.\r
+\r
+ @param[in] ScsiIo SCSI IO Protocol to use.\r
+ @param[in] Timeout The length of timeout period.\r
+ @param[in, out] SenseData A pointer to output sense data.\r
+ @param[in, out] SenseDataLength The length of output sense data.\r
+ @param[out] HostAdapterStatus The status of Host Adapter.\r
+ @param[out] TargetStatus The status of the target.\r
+ @param[in] SecurityProtocol The Security Protocol to use.\r
+ @param[in] SecurityProtocolSpecific The Security Protocol Specific data.\r
+ @param[in] Inc512 If TRUE, 512 increment (INC_512) bit will be set for the\r
+ SECURITY PROTOCOL OUT command.\r
+ @param[in] DataLength The size in bytes of the transfer data.\r
+ @param[in, out] DataBuffer A pointer to a data buffer.\r
+\r
+ @retval EFI_SUCCESS Command is executed successfully.\r
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could\r
+ not be transferred. The actual number of bytes transferred is returned in DataLength.\r
+ @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many\r
+ SCSI Command Packets already queued.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
+ @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by\r
+ the SCSI initiator(i.e., SCSI Host Controller)\r
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ScsiSecurityProtocolOutCommand (\r
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
+ IN UINT64 Timeout,\r
+ IN OUT VOID *SenseData, OPTIONAL\r
+ IN OUT UINT8 *SenseDataLength,\r
+ OUT UINT8 *HostAdapterStatus,\r
+ OUT UINT8 *TargetStatus,\r
+ IN UINT8 SecurityProtocol,\r
+ IN UINT16 SecurityProtocolSpecific,\r
+ IN BOOLEAN Inc512,\r
+ IN UINTN DataLength,\r
+ IN OUT VOID *DataBuffer OPTIONAL\r
+ )\r
+{\r
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
+ EFI_STATUS Status;\r
+ UINT8 Cdb[EFI_SCSI_OP_LENGTH_TWELVE];\r
+\r
+ ASSERT (SenseDataLength != NULL);\r
+ ASSERT (HostAdapterStatus != NULL);\r
+ ASSERT (TargetStatus != NULL);\r
+ ASSERT (ScsiIo != NULL);\r
+ ASSERT (DataLength <= MAX_UINT32);\r
+\r
+ ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
+ ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TWELVE);\r
+\r
+ CommandPacket.Timeout = Timeout;\r
+ CommandPacket.OutDataBuffer = DataBuffer;\r
+ CommandPacket.SenseData = SenseData;\r
+ CommandPacket.OutTransferLength = (UINT32) DataLength;\r
+ CommandPacket.Cdb = Cdb;\r
+ //\r
+ // Fill Cdb for Security Protocol Out Command\r
+ //\r
+ Cdb[0] = EFI_SCSI_OP_SECURITY_PROTOCOL_OUT;\r
+ Cdb[1] = SecurityProtocol;\r
+ WriteUnaligned16 ((UINT16 *)&Cdb[2], SwapBytes16 (SecurityProtocolSpecific));\r
+\r
+ if (Inc512) {\r
+ if (DataLength % 512 != 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ Cdb[4] = BIT7;\r
+ WriteUnaligned32 ((UINT32 *)&Cdb[6], SwapBytes32 ((UINT32) DataLength / 512));\r
+ } else {\r
+ WriteUnaligned32 ((UINT32 *)&Cdb[6], SwapBytes32 ((UINT32) DataLength));\r
+ }\r
+\r
+ CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TWELVE;\r
+ CommandPacket.DataDirection = EFI_SCSI_DATA_OUT;\r
+ CommandPacket.SenseDataLength = *SenseDataLength;\r
+\r
+ Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
+\r
+ *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
+ *TargetStatus = CommandPacket.TargetStatus;\r
+ *SenseDataLength = CommandPacket.SenseDataLength;\r
+\r
+ return Status;\r
+}\r
+\r
+\r