123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375 |
- /** @file
- TCG MOR (Memory Overwrite Request) Control Driver.
- This driver initialize MemoryOverwriteRequestControl variable. It
- will clear MOR_CLEAR_MEMORY_BIT bit if it is set. It will also do TPer Reset for
- those encrypted drives through EFI_STORAGE_SECURITY_COMMAND_PROTOCOL at EndOfDxe.
- Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "TcgMor.h"
- UINT8 mMorControl;
- /**
- Ready to Boot Event notification handler.
- @param[in] Event Event whose notification function is being invoked
- @param[in] Context Pointer to the notification function's context
- **/
- VOID
- EFIAPI
- OnReadyToBoot (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
- {
- EFI_STATUS Status;
- UINTN DataSize;
- if (MOR_CLEAR_MEMORY_VALUE (mMorControl) == 0x0) {
- //
- // MorControl is expected, directly return to avoid unnecessary variable operation
- //
- return ;
- }
- //
- // Clear MOR_CLEAR_MEMORY_BIT
- //
- DEBUG ((EFI_D_INFO, "TcgMor: Clear MorClearMemory bit\n"));
- mMorControl &= 0xFE;
- DataSize = sizeof (mMorControl);
- Status = gRT->SetVariable (
- MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
- &gEfiMemoryOverwriteControlDataGuid,
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
- DataSize,
- &mMorControl
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "TcgMor: Clear MOR_CLEAR_MEMORY_BIT failure, Status = %r\n"));
- }
- }
- /**
- 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] Ssp The pointer to EFI_STORAGE_SECURITY_COMMAND_PROTOCOL instance.
- @param[in] MediaId ID of the medium to receive data from or send data to.
- **/
- VOID
- InitiateTPerReset (
- IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *Ssp,
- IN UINT32 MediaId
- )
- {
- EFI_STATUS Status;
- UINT8 *Buffer;
- UINTN XferSize;
- UINTN Len;
- UINTN Index;
- BOOLEAN TcgFlag;
- BOOLEAN IeeeFlag;
- SUPPORTED_SECURITY_PROTOCOLS_PARAMETER_DATA *Data;
- Buffer = NULL;
- TcgFlag = FALSE;
- IeeeFlag = FALSE;
- //
- // 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,
- 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,
- 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,
- 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);
- }
- }
- /**
- Notification function of END_OF_DXE.
- @param[in] Event Event whose notification function is being invoked.
- @param[in] Context Pointer to the notification function's context.
- **/
- VOID
- EFIAPI
- TPerResetAtEndOfDxe (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
- {
- EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *Ssp;
- EFI_BLOCK_IO_PROTOCOL *BlockIo;
- EFI_STATUS Status;
- UINTN HandleCount;
- EFI_HANDLE *HandleBuffer;
- UINTN Index;
- //
- // Locate all SSP protocol instances.
- //
- HandleCount = 0;
- HandleBuffer = NULL;
- Status = gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiStorageSecurityCommandProtocolGuid,
- NULL,
- &HandleCount,
- &HandleBuffer
- );
- if (EFI_ERROR (Status) || (HandleCount == 0) || (HandleBuffer == NULL)) {
- return;
- }
- for (Index = 0; Index < HandleCount; Index ++) {
- //
- // Get the SSP interface.
- //
- Status = gBS->HandleProtocol(
- HandleBuffer[Index],
- &gEfiStorageSecurityCommandProtocolGuid,
- (VOID **) &Ssp
- );
- if (EFI_ERROR (Status)) {
- continue;
- }
- Status = gBS->HandleProtocol(
- HandleBuffer[Index],
- &gEfiBlockIoProtocolGuid,
- (VOID **) &BlockIo
- );
- if (EFI_ERROR (Status)) {
- continue;
- }
- InitiateTPerReset (Ssp, BlockIo->Media->MediaId);
- }
- FreePool (HandleBuffer);
- }
- /**
- Entry Point for TCG MOR Control driver.
- @param[in] ImageHandle Image handle of this driver.
- @param[in] SystemTable A Pointer to the EFI System Table.
- @retval EFI_SUCCESS
- @return Others Some error occurs.
- **/
- EFI_STATUS
- EFIAPI
- MorDriverEntryPoint (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
- {
- EFI_STATUS Status;
- UINTN DataSize;
- EFI_EVENT Event;
- ///
- /// The firmware is required to create the MemoryOverwriteRequestControl UEFI variable.
- ///
- DataSize = sizeof (mMorControl);
- Status = gRT->GetVariable (
- MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
- &gEfiMemoryOverwriteControlDataGuid,
- NULL,
- &DataSize,
- &mMorControl
- );
- if (EFI_ERROR (Status)) {
- //
- // Set default value to 0
- //
- mMorControl = 0;
- Status = gRT->SetVariable (
- MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
- &gEfiMemoryOverwriteControlDataGuid,
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
- DataSize,
- &mMorControl
- );
- DEBUG ((EFI_D_INFO, "TcgMor: Create MOR variable! Status = %r\n", Status));
- } else {
- //
- // Create a Ready To Boot Event and Clear the MorControl bit in the call back function.
- //
- DEBUG ((DEBUG_INFO, "TcgMor: Create ReadyToBoot Event for MorControl Bit cleaning!\n"));
- Status = EfiCreateEventReadyToBootEx (
- TPL_CALLBACK,
- OnReadyToBoot,
- NULL,
- &Event
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- //
- // Register EFI_END_OF_DXE_EVENT_GROUP_GUID event.
- //
- DEBUG ((EFI_D_INFO, "TcgMor: Create EndofDxe Event for Mor TPer Reset!\n"));
- Status = gBS->CreateEventEx (
- EVT_NOTIFY_SIGNAL,
- TPL_CALLBACK,
- TPerResetAtEndOfDxe,
- NULL,
- &gEfiEndOfDxeEventGroupGuid,
- &Event
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- }
- return Status;
- }
|