mirror of https://github.com/acidanthera/audk.git
QuarkPlatformPkg: Add Tpm12DeviceLib instance for Atmel I2C TPM
Add new Tpm12DeviceLib instance for an Atmel I2C TPM Cc: Kelly Steele <kelly.steele@intel.com> Cc: Jiewen Yao <jiewen.yao@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Michael Kinney <michael.d.kinney@intel.com> Reviewed-by: Kelly Steele <kelly.steele@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19730 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
441a3678e1
commit
df8652455e
|
@ -0,0 +1,419 @@
|
|||
/** @file
|
||||
Basic TIS (TPM Interface Specification) functions for Atmel I2C TPM.
|
||||
|
||||
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include <PiPei.h>
|
||||
#include <Library/Tpm12DeviceLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/TimerLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/I2cLib.h>
|
||||
#include <Library/Tpm12CommandLib.h>
|
||||
|
||||
//
|
||||
// Atmel I2C TPM slave address
|
||||
//
|
||||
#define ATMEL_I2C_TPM_SLAVE_ADDRESS 0x29
|
||||
|
||||
//
|
||||
// Maximum I2C transfer size for Atmel I2C TPM
|
||||
//
|
||||
#define ATMEL_I2C_TPM_MAX_TRANSFER_SIZE 0x10
|
||||
|
||||
//
|
||||
// Default TimeOut values in microseconds
|
||||
//
|
||||
#define TIS_TIMEOUT_A ( 750 * 1000) // 750ms
|
||||
#define TIS_TIMEOUT_B (2000 * 1000) // 2s
|
||||
#define TIS_TIMEOUT_C ( 750 * 1000) // 750ms
|
||||
#define TIS_TIMEOUT_D ( 750 * 1000) // 750ms
|
||||
|
||||
/**
|
||||
Send command to Atmel I2c TPM breaking request up into multiple I2C transfers
|
||||
if required.
|
||||
|
||||
@param[in] Buffer Pointer to TPM command data.
|
||||
@param[in] Length Number of bytes of TPM command data.
|
||||
|
||||
@retval EFI_SUCCESS TPM command sent.
|
||||
@retval EFI_NOT_FOUND TPM chip doesn't exit.
|
||||
@retval EFI_TIMEOUT Can't get the TPM control in time.
|
||||
**/
|
||||
EFI_STATUS
|
||||
WriteTpmBufferMultiple (
|
||||
IN UINT8 *Buffer,
|
||||
IN UINTN Length
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_I2C_DEVICE_ADDRESS I2CDeviceAddr;
|
||||
UINTN Index;
|
||||
UINTN PartialLength;
|
||||
|
||||
I2CDeviceAddr.I2CDeviceAddress = ATMEL_I2C_TPM_SLAVE_ADDRESS;
|
||||
|
||||
DEBUG ((EFI_D_VERBOSE, "WriteTpmBufferMultiple: Addr=%02x Length=%02x\n", I2CDeviceAddr.I2CDeviceAddress, Length));
|
||||
|
||||
for (PartialLength = 0; Length > 0; Length -= PartialLength, Buffer += PartialLength) {
|
||||
//
|
||||
// Write data to TPM.
|
||||
//
|
||||
PartialLength = MIN (Length, ATMEL_I2C_TPM_MAX_TRANSFER_SIZE);
|
||||
Status = I2cWriteMultipleByte (
|
||||
I2CDeviceAddr,
|
||||
EfiI2CSevenBitAddrMode,
|
||||
&PartialLength,
|
||||
Buffer
|
||||
);
|
||||
DEBUG ((EFI_D_VERBOSE, " "));
|
||||
for (Index = 0; Index < PartialLength; Index++) {
|
||||
DEBUG ((EFI_D_VERBOSE, "%02x ", Buffer[Index]));
|
||||
}
|
||||
DEBUG ((EFI_D_VERBOSE, "\n"));
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_VERBOSE, " Status = %r\n", Status));
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG ((EFI_D_VERBOSE, " Status = %r\n", Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Receive a response to a command from Atmel I2c TPM breaking response into
|
||||
multiple I2C transfers if required.
|
||||
|
||||
@param[out] Buffer Pointer to TPM response data.
|
||||
@param[in] Length Maximum number of bytes to receive.
|
||||
|
||||
@retval EFI_SUCCESS TPM response received.
|
||||
@retval EFI_NOT_FOUND TPM chip doesn't exit.
|
||||
@retval EFI_TIMEOUT Can't get the TPM control in time.
|
||||
**/
|
||||
EFI_STATUS
|
||||
ReadTpmBufferMultiple (
|
||||
OUT UINT8 *Buffer,
|
||||
IN UINTN Length
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_I2C_DEVICE_ADDRESS I2CDeviceAddr;
|
||||
UINTN WriteLength;
|
||||
UINTN Index;
|
||||
UINTN PartialLength;
|
||||
|
||||
I2CDeviceAddr.I2CDeviceAddress = ATMEL_I2C_TPM_SLAVE_ADDRESS;
|
||||
WriteLength = 0;
|
||||
|
||||
DEBUG ((EFI_D_VERBOSE, "ReadTpmBufferMultiple: Addr=%02x Length=%02x\n", I2CDeviceAddr.I2CDeviceAddress, Length));
|
||||
|
||||
for (PartialLength = 0; Length > 0; Length -= PartialLength, Buffer += PartialLength) {
|
||||
//
|
||||
// Read data from TPM.
|
||||
//
|
||||
PartialLength = MIN (Length, ATMEL_I2C_TPM_MAX_TRANSFER_SIZE);
|
||||
Status = I2cReadMultipleByte (
|
||||
I2CDeviceAddr,
|
||||
EfiI2CSevenBitAddrMode,
|
||||
&WriteLength,
|
||||
&PartialLength,
|
||||
Buffer
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_VERBOSE, " "));
|
||||
for (Index = 0; Index < PartialLength; Index++) {
|
||||
DEBUG ((EFI_D_VERBOSE, "%02x ", Buffer[Index]));
|
||||
}
|
||||
DEBUG ((EFI_D_VERBOSE, "\n"));
|
||||
}
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_VERBOSE, " Status = %r\n", Status));
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG ((EFI_D_VERBOSE, " Status = %r\n", Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
This service requests use TPM12.
|
||||
|
||||
@retval EFI_SUCCESS Get the control of TPM12 chip.
|
||||
@retval EFI_NOT_FOUND TPM12 not found.
|
||||
@retval EFI_DEVICE_ERROR Unexpected device behavior.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tpm12RequestUseTpm (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT8 Data;
|
||||
UINT64 Current;
|
||||
UINT64 Previous;
|
||||
UINT64 Total;
|
||||
UINT64 Start;
|
||||
UINT64 End;
|
||||
UINT64 Timeout;
|
||||
INT64 Cycle;
|
||||
INT64 Delta;
|
||||
|
||||
//
|
||||
// Get the current timer value
|
||||
//
|
||||
Current = GetPerformanceCounter();
|
||||
|
||||
//
|
||||
// Initialize local variables
|
||||
//
|
||||
Start = 0;
|
||||
End = 0;
|
||||
Total = 0;
|
||||
|
||||
//
|
||||
// Retrieve the performance counter properties and compute the number of
|
||||
// performance counter ticks required to reach the maximum TIS timeout of
|
||||
// TIS_TIMEOUT_A. TIS_TIMEOUT_A is in microseconds.
|
||||
//
|
||||
Timeout = DivU64x32 (
|
||||
MultU64x32 (
|
||||
GetPerformanceCounterProperties (&Start, &End),
|
||||
TIS_TIMEOUT_A
|
||||
),
|
||||
1000000
|
||||
);
|
||||
Cycle = End - Start;
|
||||
if (Cycle < 0) {
|
||||
Cycle = -Cycle;
|
||||
}
|
||||
Cycle++;
|
||||
|
||||
//
|
||||
// Attempt to read a byte from the Atmel I2C TPM
|
||||
//
|
||||
do {
|
||||
Status = ReadTpmBufferMultiple (&Data, sizeof(Data));
|
||||
|
||||
Previous = Current;
|
||||
Current = GetPerformanceCounter();
|
||||
Delta = (INT64) (Current - Previous);
|
||||
if (Start > End) {
|
||||
Delta = -Delta;
|
||||
}
|
||||
if (Delta < 0) {
|
||||
Delta += Cycle;
|
||||
}
|
||||
Total += Delta;
|
||||
if (Total >= Timeout) {
|
||||
Status = EFI_TIMEOUT;
|
||||
DEBUG ((EFI_D_ERROR, "Atmel I2C TPM failed to read: %r\n", Status));
|
||||
return Status;
|
||||
}
|
||||
} while (EFI_ERROR (Status));
|
||||
|
||||
//
|
||||
// Send Physical Presence Command to Atmel I2C TPM
|
||||
//
|
||||
Status = Tpm12PhysicalPresence (TPM_PHYSICAL_PRESENCE_PRESENT);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_ERROR, "Atmel I2C TPM failed to submit physical presence command: %r\n", Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
This service enables the sending of commands to the TPM12.
|
||||
|
||||
@param[in] InputParameterBlockSize Size of the TPM12 input parameter block.
|
||||
@param[in] InputParameterBlock Pointer to the TPM12 input parameter block.
|
||||
@param[in,out] OutputParameterBlockSize Size of the TPM12 output parameter block.
|
||||
@param[in] OutputParameterBlock Pointer to the TPM12 output parameter block.
|
||||
|
||||
@retval EFI_SUCCESS The command byte stream was successfully sent to
|
||||
the device and a response was successfully received.
|
||||
@retval EFI_DEVICE_ERROR The command was not successfully sent to the
|
||||
device or a response was not successfully received
|
||||
from the device.
|
||||
@retval EFI_BUFFER_TOO_SMALL The output parameter block is too small.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tpm12SubmitCommand (
|
||||
IN UINT32 InputParameterBlockSize,
|
||||
IN UINT8 *InputParameterBlock,
|
||||
IN OUT UINT32 *OutputParameterBlockSize,
|
||||
IN UINT8 *OutputParameterBlock
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 TpmOutSize;
|
||||
TPM_RSP_COMMAND_HDR *ResponseHeader;
|
||||
UINT64 Current;
|
||||
UINT64 Previous;
|
||||
UINT64 Total;
|
||||
UINT64 Start;
|
||||
UINT64 End;
|
||||
UINT64 Timeout;
|
||||
INT64 Cycle;
|
||||
INT64 Delta;
|
||||
|
||||
//
|
||||
// Make sure response buffer is big enough to hold a response header
|
||||
//
|
||||
if (*OutputParameterBlockSize < sizeof (TPM_RSP_COMMAND_HDR)) {
|
||||
Status = EFI_BUFFER_TOO_SMALL;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the current timer value
|
||||
//
|
||||
Current = GetPerformanceCounter();
|
||||
|
||||
//
|
||||
// Initialize local variables
|
||||
//
|
||||
Start = 0;
|
||||
End = 0;
|
||||
Total = 0;
|
||||
|
||||
//
|
||||
// Retrieve the performance counter properties and compute the number of
|
||||
// performance counter ticks required to reach the maximum TIS timeout of
|
||||
// TIS_TIMEOUT_A. TIS_TIMEOUT_A is in microseconds.
|
||||
//
|
||||
Timeout = DivU64x32 (
|
||||
MultU64x32 (
|
||||
GetPerformanceCounterProperties (&Start, &End),
|
||||
TIS_TIMEOUT_A
|
||||
),
|
||||
1000000
|
||||
);
|
||||
Cycle = End - Start;
|
||||
if (Cycle < 0) {
|
||||
Cycle = -Cycle;
|
||||
}
|
||||
Cycle++;
|
||||
|
||||
//
|
||||
// Send command
|
||||
//
|
||||
do {
|
||||
Status = WriteTpmBufferMultiple (InputParameterBlock, InputParameterBlockSize);
|
||||
|
||||
Previous = Current;
|
||||
Current = GetPerformanceCounter();
|
||||
Delta = (INT64) (Current - Previous);
|
||||
if (Start > End) {
|
||||
Delta = -Delta;
|
||||
}
|
||||
if (Delta < 0) {
|
||||
Delta += Cycle;
|
||||
}
|
||||
Total += Delta;
|
||||
if (Total >= Timeout) {
|
||||
Status = EFI_TIMEOUT;
|
||||
goto Done;
|
||||
}
|
||||
} while (EFI_ERROR (Status));
|
||||
|
||||
//
|
||||
// Receive response header
|
||||
//
|
||||
do {
|
||||
Status = ReadTpmBufferMultiple (OutputParameterBlock, sizeof (TPM_RSP_COMMAND_HDR));
|
||||
|
||||
Previous = Current;
|
||||
Current = GetPerformanceCounter();
|
||||
Delta = (INT64) (Current - Previous);
|
||||
if (Start > End) {
|
||||
Delta = -Delta;
|
||||
}
|
||||
if (Delta < 0) {
|
||||
Delta += Cycle;
|
||||
}
|
||||
Total += Delta;
|
||||
if (Total >= Timeout) {
|
||||
Status = EFI_TIMEOUT;
|
||||
goto Done;
|
||||
}
|
||||
} while (EFI_ERROR (Status));
|
||||
|
||||
//
|
||||
// Check the response data header (tag, parasize and returncode)
|
||||
//
|
||||
ResponseHeader = (TPM_RSP_COMMAND_HDR *)OutputParameterBlock;
|
||||
if (SwapBytes16 (ReadUnaligned16 (&ResponseHeader->tag)) != TPM_TAG_RSP_COMMAND) {
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
TpmOutSize = SwapBytes32 (ReadUnaligned32 (&ResponseHeader->paramSize));
|
||||
if (TpmOutSize == sizeof (TPM_RSP_COMMAND_HDR)) {
|
||||
Status = EFI_SUCCESS;
|
||||
goto Done;
|
||||
}
|
||||
if (TpmOutSize < sizeof (TPM_RSP_COMMAND_HDR)) {
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto Done;
|
||||
}
|
||||
if (*OutputParameterBlockSize < TpmOutSize) {
|
||||
Status = EFI_BUFFER_TOO_SMALL;
|
||||
goto Done;
|
||||
}
|
||||
*OutputParameterBlockSize = TpmOutSize;
|
||||
|
||||
//
|
||||
// Receive the remaining data in the response header
|
||||
//
|
||||
do {
|
||||
Status = ReadTpmBufferMultiple (
|
||||
OutputParameterBlock + sizeof (TPM_RSP_COMMAND_HDR),
|
||||
TpmOutSize - sizeof (TPM_RSP_COMMAND_HDR)
|
||||
);
|
||||
|
||||
Previous = Current;
|
||||
Current = GetPerformanceCounter();
|
||||
Delta = (INT64) (Current - Previous);
|
||||
if (Start > End) {
|
||||
Delta = -Delta;
|
||||
}
|
||||
if (Delta < 0) {
|
||||
Delta += Cycle;
|
||||
}
|
||||
Total += Delta;
|
||||
if (Total >= Timeout) {
|
||||
Status = EFI_TIMEOUT;
|
||||
goto Done;
|
||||
}
|
||||
} while (EFI_ERROR (Status));
|
||||
|
||||
Done:
|
||||
DEBUG ((
|
||||
EFI_D_VERBOSE,
|
||||
"Tpm12SubmitCommand() Status = %r Time = %ld ms\n",
|
||||
Status,
|
||||
DivU64x64Remainder (
|
||||
MultU64x32 (Total, 1000),
|
||||
GetPerformanceCounterProperties (NULL, NULL),
|
||||
NULL
|
||||
)
|
||||
));
|
||||
|
||||
return Status;
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
## @file
|
||||
# Provides some common functions for the TCG feature for Atmel I2C TPM.
|
||||
#
|
||||
# This instance provides basic TPM Interface Specification (TIS) functions
|
||||
# or Atmel I2C TPM.
|
||||
#
|
||||
# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = Tpm12DeviceLibAtmelI2c
|
||||
MODULE_UNI_FILE = Tpm12DeviceLibAtmelI2c.uni
|
||||
FILE_GUID = A0C0B7EF-99FF-417F-8B9F-5AD4701D90D6
|
||||
MODULE_TYPE = PEIM
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = Tpm12DeviceLib|PEIM DXE_DRIVER DXE_SMM_DRIVER UEFI_DRIVER
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64
|
||||
#
|
||||
|
||||
[Sources]
|
||||
TisPc.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
SecurityPkg/SecurityPkg.dec
|
||||
QuarkSocPkg/QuarkSocPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
TimerLib
|
||||
DebugLib
|
||||
I2cLib
|
||||
Tpm12CommandLib
|
|
@ -0,0 +1,21 @@
|
|||
// /** @file
|
||||
// Provides some common functions for the TCG feature for Atmel I2C TPM.
|
||||
//
|
||||
// This instance provides basic TPM Interface Specification (TIS) functions
|
||||
// for Atmel I2C TPM.
|
||||
//
|
||||
// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
|
||||
//
|
||||
// This program and the accompanying materials
|
||||
// are licensed and made available under the terms and conditions of the BSD License
|
||||
// which accompanies this distribution. The full text of the license may be found at
|
||||
// http://opensource.org/licenses/bsd-license.php
|
||||
// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
//
|
||||
// **/
|
||||
|
||||
#string STR_MODULE_ABSTRACT #language en-US "Provides some common functions for the TCG feature for Atmel I2C TPM."
|
||||
|
||||
#string STR_MODULE_DESCRIPTION #language en-US "This instance provides basic TPM Interface Specification (TIS) functions for Atmel I2C TPM."
|
||||
|
Loading…
Reference in New Issue