From 90398d5558431b733a97ba7e3a2fddcd5f0858f5 Mon Sep 17 00:00:00 2001 From: qianouyang Date: Wed, 12 Sep 2012 10:19:50 +0000 Subject: [PATCH] Add Tper Reset Logic by using MOR bit. Signed-off-by: Ouyang, Qian Reviewed-by: Tian, Feng Dong, Guo git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13727 6f19259b-4bc3-4df7-8a09-765794883524 --- MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c | 208 +++++++++++++++++++ MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.h | 33 +++ MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf | 4 +- 3 files changed, 244 insertions(+), 1 deletion(-) diff --git a/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c b/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c index 8fa0b3f626..17e2614b87 100644 --- a/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c +++ b/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c @@ -18,6 +18,9 @@ #include "AtaBus.h" +UINT8 mMorControl; +BOOLEAN mHasMor; + // // ATA Bus Driver Binding Protocol Instance // @@ -364,6 +367,19 @@ RegisterAtaDevice ( if (EFI_ERROR (Status)) { goto Done; } + DEBUG ((EFI_D_INFO, "Successfully Install Storage Security Protocol on the ATA device\n")); + } + + if (mHasMor) { + if (((mMorControl & 0x01) == 0x01) && ((AtaDevice->IdentifyData->trusted_computing_support & BIT0) != 0)) { + DEBUG ((EFI_D_INFO, + "mMorControl = %x, AtaDevice->IdentifyData->trusted_computing_support & BIT0 = %x\n", + mMorControl, + (AtaDevice->IdentifyData->trusted_computing_support & BIT0) + )); + DEBUG ((EFI_D_INFO, "Try to lock device by sending TPer Reset command...\n")); + InitiateTPerReset(AtaDevice); + } } gBS->OpenProtocol ( @@ -1638,6 +1654,7 @@ InitializeAtaBus( ) { EFI_STATUS Status; + UINTN DataSize; // // Install driver model protocol(s). @@ -1652,5 +1669,196 @@ InitializeAtaBus( ); ASSERT_EFI_ERROR (Status); + // + // Get the MorControl bit. + // + DataSize = sizeof (mMorControl); + Status = gRT->GetVariable ( + MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME, + &gEfiMemoryOverwriteControlDataGuid, + NULL, + &DataSize, + &mMorControl + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_INFO, "AtaBus:gEfiMemoryOverwriteControlDataGuid doesn't exist!!***\n")); + mHasMor = FALSE; + mMorControl = 0; + Status = EFI_SUCCESS; + } else { + DEBUG ((EFI_D_INFO, "AtaBus:Get the gEfiMemoryOverwriteControlDataGuid = %x!!***\n", mMorControl)); + mHasMor = TRUE; + } + return Status; } + +/** + Send TPer Reset command to reset eDrive to lock all protected bands. + Typically, there are 2 mechanism for resetting eDrive. They are: + 1. TPer Reset through IEEE 1667 protocol. + 2. TPer Reset through native TCG protocol. + This routine will detect what protocol the attached eDrive comform to, TCG or + IEEE 1667 protocol. Then send out TPer Reset command separately. + + @param[in] AtaDevice ATA_DEVICE pointer. + +**/ +VOID +InitiateTPerReset ( + IN ATA_DEVICE *AtaDevice + ) +{ + + EFI_STATUS Status; + UINT8 *Buffer; + UINTN XferSize; + UINTN Len; + UINTN Index; + BOOLEAN TcgFlag; + BOOLEAN IeeeFlag; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *Ssp; + SUPPORTED_SECURITY_PROTOCOLS_PARAMETER_DATA *Data; + + Buffer = NULL; + TcgFlag = FALSE; + IeeeFlag = FALSE; + Ssp = &AtaDevice->StorageSecurity; + BlockIo = &AtaDevice->BlockIo; + + // + // ATA8-ACS 7.57.6.1 indicates the Transfer Length field requirements a multiple of 512. + // If the length of the TRUSTED RECEIVE parameter data is greater than the Transfer Length, + // then the device shall return the TRUSTED RECEIVE parameter data truncated to the requested Transfer Length. + // + Len = ROUNDUP512(sizeof(SUPPORTED_SECURITY_PROTOCOLS_PARAMETER_DATA)); + Buffer = AllocateZeroPool(Len); + + if (Buffer == NULL) { + return; + } + + // + // When the Security Protocol field is set to 00h, and SP Specific is set to 0000h in a TRUSTED RECEIVE + // command, the device basic information data shall be returned. + // + Status = Ssp->ReceiveData ( + Ssp, + BlockIo->Media->MediaId, + 100000000, // Timeout 10-sec + 0, // SecurityProtocol + 0, // SecurityProtocolSpecifcData + Len, // PayloadBufferSize, + Buffer, // PayloadBuffer + &XferSize + ); + if (EFI_ERROR (Status)) { + goto Exit; + } + + // + // In returned data, the ListLength field indicates the total length, in bytes, + // of the supported security protocol list. + // + Data = (SUPPORTED_SECURITY_PROTOCOLS_PARAMETER_DATA*)Buffer; + Len = ROUNDUP512(sizeof (SUPPORTED_SECURITY_PROTOCOLS_PARAMETER_DATA) + + (Data->SupportedSecurityListLength[0] << 8) + + (Data->SupportedSecurityListLength[1]) + ); + + // + // Free original buffer and allocate new buffer. + // + FreePool(Buffer); + Buffer = AllocateZeroPool(Len); + if (Buffer == NULL) { + return; + } + + // + // Read full supported security protocol list from device. + // + Status = Ssp->ReceiveData ( + Ssp, + BlockIo->Media->MediaId, + 100000000, // Timeout 10-sec + 0, // SecurityProtocol + 0, // SecurityProtocolSpecifcData + Len, // PayloadBufferSize, + Buffer, // PayloadBuffer + &XferSize + ); + + if (EFI_ERROR (Status)) { + goto Exit; + } + + Data = (SUPPORTED_SECURITY_PROTOCOLS_PARAMETER_DATA*)Buffer; + Len = (Data->SupportedSecurityListLength[0] << 8) + Data->SupportedSecurityListLength[1]; + + // + // Iterate full supported security protocol list to check if TCG or IEEE 1667 protocol + // is supported. + // + for (Index = 0; Index < Len; Index++) { + if (Data->SupportedSecurityProtocol[Index] == SECURITY_PROTOCOL_TCG) { + // + // Found a TCG device. + // + TcgFlag = TRUE; + DEBUG ((EFI_D_INFO, "This device is a TCG protocol device\n")); + break; + } + + if (Data->SupportedSecurityProtocol[Index] == SECURITY_PROTOCOL_IEEE1667) { + // + // Found a IEEE 1667 device. + // + IeeeFlag = TRUE; + DEBUG ((EFI_D_INFO, "This device is a IEEE 1667 protocol device\n")); + break; + } + } + + if (!TcgFlag && !IeeeFlag) { + DEBUG ((EFI_D_INFO, "Neither a TCG nor IEEE 1667 protocol device is found\n")); + goto Exit; + } + + if (TcgFlag) { + // + // As long as TCG protocol is supported, send out a TPer Reset + // TCG command to the device via the TrustedSend command with a non-zero Transfer Length. + // + Status = Ssp->SendData ( + Ssp, + BlockIo->Media->MediaId, + 100000000, // Timeout 10-sec + SECURITY_PROTOCOL_TCG, // SecurityProtocol + 0x0400, // SecurityProtocolSpecifcData + 512, // PayloadBufferSize, + Buffer // PayloadBuffer + ); + + if (!EFI_ERROR (Status)) { + DEBUG ((EFI_D_INFO, "Send TPer Reset Command Successfully !\n")); + } else { + DEBUG ((EFI_D_INFO, "Send TPer Reset Command Fail !\n")); + } + } + + if (IeeeFlag) { + // + // TBD : Perform a TPer Reset via IEEE 1667 Protocol + // + DEBUG ((EFI_D_INFO, "IEEE 1667 Protocol didn't support yet!\n")); + } + +Exit: + + if (Buffer != NULL) { + FreePool(Buffer); + } +} diff --git a/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.h b/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.h index b64a3d3928..d6b0ff8f08 100644 --- a/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.h +++ b/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.h @@ -20,6 +20,7 @@ #include +#include #include #include #include @@ -35,6 +36,7 @@ #include #include #include +#include #include #include @@ -82,6 +84,21 @@ #define ATA_SUB_TASK_SIGNATURE SIGNATURE_32 ('A', 'S', 'T', 'S') #define IS_ALIGNED(addr, size) (((UINTN) (addr) & (size - 1)) == 0) +#define ROUNDUP512(x) (((x) % 512 == 0) ? (x) : ((x) / 512 + 1) * 512) + +#define SECURITY_PROTOCOL_TCG 0x02 +#define SECURITY_PROTOCOL_IEEE1667 0xEE + +// +// ATA Supported Security Protocols List Description. +// Refer to ATA8-ACS Spec 7.57.6.2 Table 69. +// +typedef struct { + UINT8 Reserved1[6]; + UINT8 SupportedSecurityListLength[2]; + UINT8 SupportedSecurityProtocol[1]; +} SUPPORTED_SECURITY_PROTOCOLS_PARAMETER_DATA; + // // ATA bus data structure for ATA controller // @@ -1042,4 +1059,20 @@ AtaStorageSecuritySendData ( IN VOID *PayloadBuffer ); +/** + Send TPer Reset command to reset eDrive to lock all protected bands. + Typically, there are 2 mechanism for resetting eDrive. They are: + 1. TPer Reset through IEEE 1667 protocol. + 2. TPer Reset through native TCG protocol. + This routine will detect what protocol the attached eDrive comform to, TCG or + IEEE 1667 protocol. Then send out TPer Reset command separately. + + @param[in] AtaDevice ATA_DEVICE pointer. + +**/ +VOID +InitiateTPerReset ( + IN ATA_DEVICE *AtaDevice + ); + #endif diff --git a/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf b/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf index edc6df9e31..82f99e5493 100644 --- a/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf +++ b/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf @@ -5,7 +5,7 @@ # in UEFI spec 2.2. It installs Block IO and Disk Info protocol for each ATA device # it enumerates and identifies successfully. # -# Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+# Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.
# # This program and the accompanying materials # are licensed and made available under the terms and conditions of the BSD License @@ -48,6 +48,7 @@ [LibraryClasses] DevicePathLib UefiBootServicesTableLib + UefiRuntimeServicesTableLib MemoryAllocationLib BaseMemoryLib UefiLib @@ -59,6 +60,7 @@ [Guids] gEfiDiskInfoIdeInterfaceGuid # CONSUMES ## GUID gEfiDiskInfoAhciInterfaceGuid # CONSUMES ## GUID + gEfiMemoryOverwriteControlDataGuid # CONSUMES ## GUID [Protocols] gEfiDiskInfoProtocolGuid # BY_START -- 2.39.2