SecurityPkg: Tpm2DeviceLibFfa: Introduce TPM device library over FF-A
This change introduces a `Tpm2DeviceLibFfa` library to support TPM over FF-A. The implementation follows the TPM over FF-A spec v1.0 BET: https://developer.arm.com/documentation/den0138/latest/ The change is tested on QEMU SBSA virtual platform and proprietary hardware platforms. Co-authored-by: Raymond Diaz <raymonddiaz@microsoft.com> Signed-off-by: Kun Qin <kun.qin@microsoft.com>
This commit is contained in:
90
SecurityPkg/Library/Tpm2DeviceLibFfa/Tpm2DeviceLibFfa.c
Normal file
90
SecurityPkg/Library/Tpm2DeviceLibFfa/Tpm2DeviceLibFfa.c
Normal file
@@ -0,0 +1,90 @@
|
||||
/** @file
|
||||
This library provides an implementation of Tpm2DeviceLib
|
||||
using ARM64 SMC calls to request TPM service.
|
||||
|
||||
The implementation is only supporting the Command Response Buffer (CRB)
|
||||
for sharing data with the TPM.
|
||||
|
||||
Copyright (c), Microsoft Corporation.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
**/
|
||||
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/Tpm2DeviceLib.h>
|
||||
#include <IndustryStandard/Tpm20.h>
|
||||
|
||||
#include "Tpm2DeviceLibFfa.h"
|
||||
|
||||
/**
|
||||
Send a command to TPM for execution and return response data.
|
||||
Used during boot only.
|
||||
|
||||
@retval EFI_SUCCESS Command was successfully sent to the TPM
|
||||
and the response was copied to the Output buffer.
|
||||
@retval Other Some error occurred in communication with the TPM.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tpm2SubmitCommand (
|
||||
IN UINT32 InputParameterBlockSize,
|
||||
IN UINT8 *InputParameterBlock,
|
||||
IN OUT UINT32 *OutputParameterBlockSize,
|
||||
IN UINT8 *OutputParameterBlock
|
||||
)
|
||||
{
|
||||
return FfaTpm2SubmitCommand (
|
||||
InputParameterBlockSize,
|
||||
InputParameterBlock,
|
||||
OutputParameterBlockSize,
|
||||
OutputParameterBlock
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
This service requests use TPM2.
|
||||
Since every communication with the TPM is blocking
|
||||
you are always good to start communicating with the TPM.
|
||||
|
||||
@retval EFI_SUCCESS Get the control of TPM2 chip.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tpm2RequestUseTpm (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return FfaTpm2RequestUseTpm ();
|
||||
}
|
||||
|
||||
/**
|
||||
This service register TPM2 device.
|
||||
|
||||
@param Tpm2Device TPM2 device
|
||||
|
||||
@retval EFI_UNSUPPORTED System does not support register this TPM2 device.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tpm2RegisterTpm2DeviceLib (
|
||||
IN TPM2_DEVICE_INTERFACE *Tpm2Device
|
||||
)
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
Check that we have an address for the CRB
|
||||
|
||||
@retval EFI_SUCCESS The entry point is executed successfully.
|
||||
@retval EFI_NO_MAPPING The TPM base address is not set up.
|
||||
@retval EFI_UNSUPPORTED The TPM interface type is not supported.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tpm2DeviceLibFfaConstructor (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return InternalTpm2DeviceLibFfaConstructor ();
|
||||
}
|
||||
213
SecurityPkg/Library/Tpm2DeviceLibFfa/Tpm2DeviceLibFfa.h
Normal file
213
SecurityPkg/Library/Tpm2DeviceLibFfa/Tpm2DeviceLibFfa.h
Normal file
@@ -0,0 +1,213 @@
|
||||
/** @file
|
||||
Provides function interfaces to communicate with TPM 2.0 device
|
||||
|
||||
This library helps to use TPM 2.0 device in library function API
|
||||
based on SMC using Command Response Buffer (CRB).
|
||||
|
||||
The TPM2DeviceLib library is sitting at the bottom of the TPM stack in UEFI.
|
||||
It is responsible for sending and receiving commands to and from the TPM.
|
||||
|
||||
This TPM library performs the following actions:
|
||||
|
||||
1) Receives a TPM command from the upper TPM layers.
|
||||
2) Moves the TPM command into the Command/Response Buffer (CRB).
|
||||
a) The address of the CRB is received through:
|
||||
gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress
|
||||
b) The interface to the CRB is described in:
|
||||
https://trustedcomputinggroup.org/wp-content/uploads/Mobile-Command-Response-Buffer-Interface-v2-r12-Specification_FINAL2.pdf
|
||||
3) Set the CRB start bit to indicate that a TPM command is sitting in the CRB.
|
||||
4) Execute an SMC instruction to transfer execution to the Secure Monitor in EL3.
|
||||
4) The CRB/TPM command moves through the following components:
|
||||
NS -> SP -> TPM
|
||||
5) After returning from the SMC instruction the TPM command has been processed.
|
||||
6) Check status codes etc.
|
||||
7) Read the response length from the CRB and copy the response into the output buffer delivered with the TPM command.
|
||||
8) Return back to the upper layers of the TPM stack.
|
||||
|
||||
This module is only to be used during boot. This will not persist after exit boot services is called.
|
||||
|
||||
Copyright (c), Microsoft Corporation.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
**/
|
||||
|
||||
#ifndef TPM2_DEVICE_LIB_FFA_H_
|
||||
#define TPM2_DEVICE_LIB_FFA_H_
|
||||
|
||||
/**
|
||||
This function is used to get the TPM interface version.
|
||||
|
||||
@param[out] Version - Supplies the pointer to the TPM interface version.
|
||||
|
||||
@retval EFI_SUCCESS The TPM command was successfully sent to the TPM
|
||||
and the response was copied to the Output buffer.
|
||||
@retval EFI_INVALID_PARAMETER The TPM command buffer is NULL or the TPM command
|
||||
buffer size is 0.
|
||||
@retval EFI_DEVICE_ERROR An error occurred in communication with the TPM.
|
||||
**/
|
||||
EFI_STATUS
|
||||
Tpm2GetInterfaceVersion (
|
||||
OUT UINT32 *Version
|
||||
);
|
||||
|
||||
/**
|
||||
This function is used to get the TPM feature information.
|
||||
|
||||
@param[out] FeatureInfo - Supplies the pointer to the feature information.
|
||||
|
||||
@retval EFI_SUCCESS The TPM command was successfully sent to the TPM
|
||||
and the response was copied to the Output buffer.
|
||||
@retval EFI_INVALID_PARAMETER The TPM command buffer is NULL or the TPM command
|
||||
buffer size is 0.
|
||||
@retval EFI_DEVICE_ERROR An error occurred in communication with the TPM.
|
||||
**/
|
||||
EFI_STATUS
|
||||
Tpm2GetFeatureInfo (
|
||||
OUT UINT32 *FeatureInfo
|
||||
);
|
||||
|
||||
/**
|
||||
This service enables the sending of commands to the TPM2.
|
||||
|
||||
@param[in] FuncQualifier Function qualifier.
|
||||
@param[in] LocalityQualifier Locality qualifier.
|
||||
|
||||
@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
|
||||
Tpm2ServiceStart (
|
||||
IN UINT64 FuncQualifier,
|
||||
IN UINT64 LocalityQualifier
|
||||
);
|
||||
|
||||
/**
|
||||
Register TPM2 device notification.
|
||||
|
||||
@param[in] NotificationTypeQualifier Notification type qualifier.
|
||||
@param[in] vCpuId vCPU ID.
|
||||
@param[in] NotificationId Bitmap ID for the notification.
|
||||
|
||||
@retval EFI_SUCCESS The command was successfully sent to the device and a response was successfully received.
|
||||
@retval Others Some error occurred in communication with the device.
|
||||
**/
|
||||
EFI_STATUS
|
||||
Tpm2RegisterNotification (
|
||||
IN BOOLEAN NotificationTypeQualifier,
|
||||
IN UINT16 vCpuId,
|
||||
IN UINT64 NotificationId
|
||||
);
|
||||
|
||||
/**
|
||||
Unregister TPM2 device notification.
|
||||
|
||||
@retval EFI_SUCCESS The command was successfully sent to the device and a response was successfully received.
|
||||
@retval Others Some error occurred in communication with the device.
|
||||
**/
|
||||
EFI_STATUS
|
||||
Tpm2UnregisterNotification (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Issue a finished notification command to the TPM service over FF-A.
|
||||
|
||||
@retval EFI_SUCCESS The command was successfully sent to the device and a response was successfully received.
|
||||
@retval Others Some error occurred in communication with the device.
|
||||
**/
|
||||
EFI_STATUS
|
||||
Tpm2FinishNotified (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Return cached PTP CRB interface IdleByPass state.
|
||||
|
||||
@return Cached PTP CRB interface IdleByPass state.
|
||||
**/
|
||||
UINT8
|
||||
GetCachedIdleByPass (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Return PTP interface type.
|
||||
|
||||
@param[in] Register Pointer to PTP register.
|
||||
|
||||
@return PTP interface type.
|
||||
**/
|
||||
TPM2_PTP_INTERFACE_TYPE
|
||||
Tpm2GetPtpInterface (
|
||||
IN VOID *Register
|
||||
);
|
||||
|
||||
/**
|
||||
Return PTP CRB interface IdleByPass state.
|
||||
|
||||
@param[in] Register Pointer to PTP register.
|
||||
|
||||
@return PTP CRB interface IdleByPass state.
|
||||
**/
|
||||
UINT8
|
||||
Tpm2GetIdleByPass (
|
||||
IN VOID *Register
|
||||
);
|
||||
|
||||
/**
|
||||
This service enables the sending of commands to the TPM2.
|
||||
|
||||
@param[in] InputParameterBlockSize Size of the TPM2 input parameter block.
|
||||
@param[in] InputParameterBlock Pointer to the TPM2 input parameter block.
|
||||
@param[in,out] OutputParameterBlockSize Size of the TPM2 output parameter block.
|
||||
@param[in] OutputParameterBlock Pointer to the TPM2 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
|
||||
FfaTpm2SubmitCommand (
|
||||
IN UINT32 InputParameterBlockSize,
|
||||
IN UINT8 *InputParameterBlock,
|
||||
IN OUT UINT32 *OutputParameterBlockSize,
|
||||
IN UINT8 *OutputParameterBlock
|
||||
);
|
||||
|
||||
/**
|
||||
This service requests use TPM2 over FF-A.
|
||||
|
||||
@retval EFI_SUCCESS Get the control of TPM2 chip.
|
||||
@retval EFI_NOT_FOUND TPM2 not found.
|
||||
@retval EFI_DEVICE_ERROR Unexpected device behavior.
|
||||
**/
|
||||
EFI_STATUS
|
||||
FfaTpm2RequestUseTpm (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Dump PTP register information.
|
||||
|
||||
@param[in] Register Pointer to PTP register.
|
||||
**/
|
||||
VOID
|
||||
DumpPtpInfo (
|
||||
IN VOID *Register
|
||||
);
|
||||
|
||||
/**
|
||||
Check that we have an address for the CRB
|
||||
|
||||
@retval EFI_SUCCESS The entry point is executed successfully.
|
||||
@retval EFI_NO_MAPPING The TPM base address is not set up.
|
||||
@retval EFI_UNSUPPORTED The TPM interface type is not supported.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
InternalTpm2DeviceLibFfaConstructor (
|
||||
VOID
|
||||
);
|
||||
|
||||
#endif /* _TPM2_DEVICE_LIB_SMC_H_ */
|
||||
52
SecurityPkg/Library/Tpm2DeviceLibFfa/Tpm2DeviceLibFfa.inf
Normal file
52
SecurityPkg/Library/Tpm2DeviceLibFfa/Tpm2DeviceLibFfa.inf
Normal file
@@ -0,0 +1,52 @@
|
||||
## @file
|
||||
# Provides function interfaces to communicate with TPM 2.0 device
|
||||
#
|
||||
# This library helps to use TPM 2.0 device in library function API
|
||||
# based on FF-A using Command Response Buffer (CRB).
|
||||
#
|
||||
# Copyright (c), Microsoft Corporation.
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = Tpm2DeviceLibFfa
|
||||
FILE_GUID = 30AB5914-CB27-4022-89A9-9942FBDB14E7
|
||||
MODULE_TYPE = BASE
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = Tpm2DeviceLib
|
||||
CONSTRUCTOR = Tpm2DeviceLibFfaConstructor
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = AARCH64
|
||||
#
|
||||
|
||||
[Sources.common]
|
||||
Tpm2DeviceLibFfa.c
|
||||
Tpm2ServiceFfaRaw.c
|
||||
Tpm2DeviceLibFfaBase.c
|
||||
Tpm2Ptp.c
|
||||
Tpm2DeviceLibFfa.h
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
SecurityPkg/SecurityPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
DebugLib
|
||||
TimerLib
|
||||
BaseMemoryLib
|
||||
IoLib
|
||||
ArmFfaLib
|
||||
|
||||
[Guids]
|
||||
gTpm2ServiceFfaGuid
|
||||
|
||||
[Pcd.common]
|
||||
gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress ## CONSUMES
|
||||
gEfiSecurityPkgTokenSpaceGuid.PcdActiveTpmInterfaceType ## PRODUCES
|
||||
gEfiSecurityPkgTokenSpaceGuid.PcdTpmServiceFfaPartitionId ## SOMETIMES_PRODUCES
|
||||
83
SecurityPkg/Library/Tpm2DeviceLibFfa/Tpm2DeviceLibFfaBase.c
Normal file
83
SecurityPkg/Library/Tpm2DeviceLibFfa/Tpm2DeviceLibFfaBase.c
Normal file
@@ -0,0 +1,83 @@
|
||||
/** @file
|
||||
This library provides an implementation of Tpm2DeviceLib
|
||||
using ARM64 SMC calls to request TPM service.
|
||||
|
||||
The implementation is only supporting the Command Response Buffer (CRB)
|
||||
for sharing data with the TPM.
|
||||
|
||||
Copyright (c), Microsoft Corporation.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
**/
|
||||
|
||||
#include <IndustryStandard/ArmFfaSvc.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/Tpm2DeviceLib.h>
|
||||
#include <IndustryStandard/ArmStdSmc.h>
|
||||
#include <IndustryStandard/Tpm20.h>
|
||||
#include <Library/TimerLib.h>
|
||||
|
||||
#include "Tpm2DeviceLibFfa.h"
|
||||
|
||||
TPM2_PTP_INTERFACE_TYPE mActiveTpmInterfaceType;
|
||||
UINT8 mCRBIdleByPass;
|
||||
|
||||
/**
|
||||
Return cached PTP CRB interface IdleByPass state.
|
||||
|
||||
@return Cached PTP CRB interface IdleByPass state.
|
||||
**/
|
||||
UINT8
|
||||
GetCachedIdleByPass (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return mCRBIdleByPass;
|
||||
}
|
||||
|
||||
/**
|
||||
Check that we have an address for the CRB
|
||||
|
||||
@retval EFI_SUCCESS The entry point is executed successfully.
|
||||
@retval EFI_NO_MAPPING The TPM base address is not set up.
|
||||
@retval EFI_UNSUPPORTED The TPM interface type is not supported.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
InternalTpm2DeviceLibFfaConstructor (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
mActiveTpmInterfaceType = PcdGet8 (PcdActiveTpmInterfaceType);
|
||||
mCRBIdleByPass = 0xFF;
|
||||
|
||||
if (PcdGet64 (PcdTpmBaseAddress) == 0) {
|
||||
Status = EFI_NO_MAPPING;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
//
|
||||
// Start by checking the PCD out of the gate and read from the CRB if it is invalid
|
||||
//
|
||||
if (mActiveTpmInterfaceType == 0xFF) {
|
||||
mActiveTpmInterfaceType = Tpm2GetPtpInterface ((VOID *)(UINTN)PcdGet64 (PcdTpmBaseAddress));
|
||||
PcdSet8S (PcdActiveTpmInterfaceType, mActiveTpmInterfaceType);
|
||||
}
|
||||
|
||||
if (mActiveTpmInterfaceType != Tpm2PtpInterfaceCrb) {
|
||||
Status = EFI_UNSUPPORTED;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
DEBUG ((DEBUG_INFO, "Setting Tpm Active Interface Type %d\n", mActiveTpmInterfaceType));
|
||||
mCRBIdleByPass = Tpm2GetIdleByPass ((VOID *)(UINTN)PcdGet64 (PcdTpmBaseAddress));
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
Exit:
|
||||
return Status;
|
||||
}
|
||||
433
SecurityPkg/Library/Tpm2DeviceLibFfa/Tpm2Ptp.c
Normal file
433
SecurityPkg/Library/Tpm2DeviceLibFfa/Tpm2Ptp.c
Normal file
@@ -0,0 +1,433 @@
|
||||
/** @file
|
||||
PTP (Platform TPM Profile) CRB (Command Response Buffer) interface used by dTPM2.0 library.
|
||||
|
||||
Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c), Microsoft Corporation.
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include <IndustryStandard/Tpm20.h>
|
||||
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/TimerLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/Tpm2DeviceLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
|
||||
#include <IndustryStandard/TpmPtp.h>
|
||||
#include <Guid/Tpm2ServiceFfa.h>
|
||||
|
||||
#include "Tpm2DeviceLibFfa.h"
|
||||
|
||||
/**
|
||||
Check whether TPM PTP register exist.
|
||||
|
||||
@param[in] Reg Pointer to PTP register.
|
||||
|
||||
@retval TRUE TPM PTP exists.
|
||||
@retval FALSE TPM PTP is not found.
|
||||
**/
|
||||
BOOLEAN
|
||||
Tpm2IsPtpPresence (
|
||||
IN VOID *Reg
|
||||
)
|
||||
{
|
||||
UINT8 RegRead;
|
||||
|
||||
RegRead = MmioRead8 ((UINTN)Reg);
|
||||
if (RegRead == 0xFF) {
|
||||
//
|
||||
// No TPM chip
|
||||
//
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
Return PTP interface type.
|
||||
|
||||
@param[in] Register Pointer to PTP register.
|
||||
|
||||
@return PTP interface type.
|
||||
**/
|
||||
TPM2_PTP_INTERFACE_TYPE
|
||||
Tpm2GetPtpInterface (
|
||||
IN VOID *Register
|
||||
)
|
||||
{
|
||||
PTP_CRB_INTERFACE_IDENTIFIER InterfaceId;
|
||||
PTP_FIFO_INTERFACE_CAPABILITY InterfaceCapability;
|
||||
|
||||
if (!Tpm2IsPtpPresence (Register)) {
|
||||
return Tpm2PtpInterfaceMax;
|
||||
}
|
||||
|
||||
//
|
||||
// Check interface id
|
||||
//
|
||||
InterfaceId.Uint32 = MmioRead32 ((UINTN)&((PTP_CRB_REGISTERS *)Register)->InterfaceId);
|
||||
InterfaceCapability.Uint32 = MmioRead32 ((UINTN)&((PTP_FIFO_REGISTERS *)Register)->InterfaceCapability);
|
||||
|
||||
if ((InterfaceId.Bits.InterfaceType == PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_CRB) &&
|
||||
(InterfaceId.Bits.InterfaceVersion == PTP_INTERFACE_IDENTIFIER_INTERFACE_VERSION_CRB) &&
|
||||
(InterfaceId.Bits.CapCRB != 0))
|
||||
{
|
||||
return Tpm2PtpInterfaceCrb;
|
||||
}
|
||||
|
||||
if ((InterfaceId.Bits.InterfaceType == PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_FIFO) &&
|
||||
(InterfaceId.Bits.InterfaceVersion == PTP_INTERFACE_IDENTIFIER_INTERFACE_VERSION_FIFO) &&
|
||||
(InterfaceId.Bits.CapFIFO != 0) &&
|
||||
(InterfaceCapability.Bits.InterfaceVersion == INTERFACE_CAPABILITY_INTERFACE_VERSION_PTP))
|
||||
{
|
||||
return Tpm2PtpInterfaceFifo;
|
||||
}
|
||||
|
||||
if (InterfaceId.Bits.InterfaceType == PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_TIS) {
|
||||
return Tpm2PtpInterfaceTis;
|
||||
}
|
||||
|
||||
return Tpm2PtpInterfaceMax;
|
||||
}
|
||||
|
||||
/**
|
||||
Return PTP CRB interface IdleByPass state.
|
||||
|
||||
@param[in] Register Pointer to PTP register.
|
||||
|
||||
@return PTP CRB interface IdleByPass state.
|
||||
**/
|
||||
UINT8
|
||||
Tpm2GetIdleByPass (
|
||||
IN VOID *Register
|
||||
)
|
||||
{
|
||||
PTP_CRB_INTERFACE_IDENTIFIER InterfaceId;
|
||||
|
||||
//
|
||||
// Check interface id
|
||||
//
|
||||
InterfaceId.Uint32 = MmioRead32 ((UINTN)&((PTP_CRB_REGISTERS *)Register)->InterfaceId);
|
||||
|
||||
return (UINT8)(InterfaceId.Bits.CapCRBIdleBypass);
|
||||
}
|
||||
|
||||
/**
|
||||
Get the control of TPM chip.
|
||||
|
||||
@param[in] CrbReg Pointer to CRB register.
|
||||
|
||||
@retval EFI_SUCCESS Get the control of TPM chip.
|
||||
@retval EFI_INVALID_PARAMETER CrbReg is NULL.
|
||||
@retval EFI_NOT_FOUND TPM chip doesn't exit.
|
||||
@retval EFI_TIMEOUT Can't get the TPM control in time.
|
||||
**/
|
||||
EFI_STATUS
|
||||
PtpCrbRequestUseTpm (
|
||||
IN PTP_CRB_REGISTERS_PTR CrbReg
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
if (!Tpm2IsPtpPresence (CrbReg)) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
MmioWrite32 ((UINTN)&CrbReg->LocalityControl, PTP_CRB_LOCALITY_CONTROL_REQUEST_ACCESS);
|
||||
Status = Tpm2ServiceStart (
|
||||
TPM2_FFA_START_FUNC_QUALIFIER_LOCALITY,
|
||||
0
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "PtpCrbRequestUseTpm: Request access failed - %r\n", Status));
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
// Double check to see if the locality we requested is granted or not.
|
||||
if ((MmioRead32 ((UINTN)&CrbReg->LocalityStatus) & PTP_CRB_LOCALITY_STATUS_GRANTED) == 0) {
|
||||
DEBUG ((DEBUG_ERROR, "PtpCrbRequestUseTpm: Locality not granted - %r\n", Status));
|
||||
Status = EFI_TIMEOUT;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Exit:
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Send a command to TPM for execution and return response data.
|
||||
|
||||
@param[in] CrbReg TPM register space base address.
|
||||
@param[in] BufferIn Buffer for command data.
|
||||
@param[in] SizeIn Size of command data.
|
||||
@param[in, out] BufferOut Buffer for response data.
|
||||
@param[in, out] SizeOut Size of response data.
|
||||
|
||||
@retval EFI_SUCCESS Operation completed successfully.
|
||||
@retval EFI_BUFFER_TOO_SMALL Response data buffer is too small.
|
||||
@retval EFI_DEVICE_ERROR Unexpected device behavior.
|
||||
@retval EFI_UNSUPPORTED Unsupported TPM version
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
PtpCrbTpmCommand (
|
||||
IN PTP_CRB_REGISTERS_PTR CrbReg,
|
||||
IN UINT8 *BufferIn,
|
||||
IN UINT32 SizeIn,
|
||||
IN OUT UINT8 *BufferOut,
|
||||
IN OUT UINT32 *SizeOut
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 Index;
|
||||
UINT32 TpmOutSize;
|
||||
UINT16 Data16;
|
||||
UINT32 Data32;
|
||||
|
||||
DEBUG_CODE_BEGIN ();
|
||||
UINTN DebugSize;
|
||||
|
||||
DEBUG ((DEBUG_VERBOSE, "PtpCrbTpmCommand Send - "));
|
||||
if (SizeIn > 0x100) {
|
||||
DebugSize = 0x40;
|
||||
} else {
|
||||
DebugSize = SizeIn;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < DebugSize; Index++) {
|
||||
DEBUG ((DEBUG_VERBOSE, "%02x ", BufferIn[Index]));
|
||||
}
|
||||
|
||||
if (DebugSize != SizeIn) {
|
||||
DEBUG ((DEBUG_VERBOSE, "...... "));
|
||||
for (Index = SizeIn - 0x20; Index < SizeIn; Index++) {
|
||||
DEBUG ((DEBUG_VERBOSE, "%02x ", BufferIn[Index]));
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG ((DEBUG_VERBOSE, "\n"));
|
||||
DEBUG_CODE_END ();
|
||||
|
||||
TpmOutSize = 0;
|
||||
|
||||
//
|
||||
// STEP 1:
|
||||
// Ready is any time the TPM is ready to receive a command, following a write
|
||||
// of 1 by software to Request.cmdReady, as indicated by the Status field
|
||||
// being cleared to 0.
|
||||
//
|
||||
MmioWrite32 ((UINTN)&CrbReg->CrbControlRequest, PTP_CRB_CONTROL_AREA_REQUEST_COMMAND_READY);
|
||||
Status = Tpm2ServiceStart (
|
||||
TPM2_FFA_START_FUNC_QUALIFIER_COMMAND,
|
||||
0
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "PtpCrbTpmCommand: Request command ready failed - %r\n", Status));
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < SizeIn; Index++) {
|
||||
MmioWrite8 ((UINTN)&CrbReg->CrbDataBuffer[Index], BufferIn[Index]);
|
||||
}
|
||||
|
||||
//
|
||||
// STEP 2:
|
||||
// Command Execution occurs after receipt of a 1 to Start and the TPM
|
||||
// clearing Start to 0.
|
||||
//
|
||||
MmioWrite32 ((UINTN)&CrbReg->CrbControlStart, PTP_CRB_CONTROL_START);
|
||||
Status = Tpm2ServiceStart (
|
||||
TPM2_FFA_START_FUNC_QUALIFIER_COMMAND,
|
||||
0
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "PtpCrbTpmCommand: Control start failed - %r\n", Status));
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
//
|
||||
// STEP 3:
|
||||
// Command Completion occurs after completion of a command (indicated by the
|
||||
// TPM clearing TPM_CRB_CTRL_Start_x to 0) and before a write of a 1 by the
|
||||
// software to Request.goIdle.
|
||||
//
|
||||
|
||||
//
|
||||
// Get response data header
|
||||
//
|
||||
for (Index = 0; Index < sizeof (TPM2_RESPONSE_HEADER); Index++) {
|
||||
BufferOut[Index] = MmioRead8 ((UINTN)&CrbReg->CrbDataBuffer[Index]);
|
||||
}
|
||||
|
||||
DEBUG_CODE_BEGIN ();
|
||||
DEBUG ((DEBUG_VERBOSE, "PtpCrbTpmCommand ReceiveHeader - "));
|
||||
for (Index = 0; Index < sizeof (TPM2_RESPONSE_HEADER); Index++) {
|
||||
DEBUG ((DEBUG_VERBOSE, "%02x ", BufferOut[Index]));
|
||||
}
|
||||
|
||||
DEBUG ((DEBUG_VERBOSE, "\n"));
|
||||
DEBUG_CODE_END ();
|
||||
//
|
||||
// Check the response data header (tag, parasize and returncode)
|
||||
//
|
||||
CopyMem (&Data16, BufferOut, sizeof (UINT16));
|
||||
// TPM2 should not use this RSP_COMMAND
|
||||
if (SwapBytes16 (Data16) == TPM_ST_RSP_COMMAND) {
|
||||
DEBUG ((DEBUG_ERROR, "TPM2: TPM_ST_RSP error - %x\n", TPM_ST_RSP_COMMAND));
|
||||
Status = EFI_UNSUPPORTED;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
CopyMem (&Data32, (BufferOut + 2), sizeof (UINT32));
|
||||
TpmOutSize = SwapBytes32 (Data32);
|
||||
if (*SizeOut < TpmOutSize) {
|
||||
//
|
||||
// Command completed, but buffer is not enough
|
||||
//
|
||||
Status = EFI_BUFFER_TOO_SMALL;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
*SizeOut = TpmOutSize;
|
||||
//
|
||||
// Continue reading the remaining data
|
||||
//
|
||||
for (Index = sizeof (TPM2_RESPONSE_HEADER); Index < TpmOutSize; Index++) {
|
||||
BufferOut[Index] = MmioRead8 ((UINTN)&CrbReg->CrbDataBuffer[Index]);
|
||||
}
|
||||
|
||||
DEBUG_CODE_BEGIN ();
|
||||
DEBUG ((DEBUG_VERBOSE, "PtpCrbTpmCommand Receive - "));
|
||||
for (Index = 0; Index < TpmOutSize; Index++) {
|
||||
DEBUG ((DEBUG_VERBOSE, "%02x ", BufferOut[Index]));
|
||||
}
|
||||
|
||||
DEBUG ((DEBUG_VERBOSE, "\n"));
|
||||
DEBUG_CODE_END ();
|
||||
|
||||
Exit:
|
||||
|
||||
//
|
||||
// Return to Idle state by setting TPM_CRB_CTRL_STS_x.Status.goIdle to 1.
|
||||
//
|
||||
MmioWrite32 ((UINTN)&CrbReg->CrbControlRequest, PTP_CRB_CONTROL_AREA_REQUEST_GO_IDLE);
|
||||
Status = Tpm2ServiceStart (
|
||||
TPM2_FFA_START_FUNC_QUALIFIER_COMMAND,
|
||||
0
|
||||
);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Dump PTP register information.
|
||||
|
||||
@param[in] Register Pointer to PTP register.
|
||||
**/
|
||||
VOID
|
||||
DumpPtpInfo (
|
||||
IN VOID *Register
|
||||
)
|
||||
{
|
||||
PTP_CRB_INTERFACE_IDENTIFIER InterfaceId;
|
||||
PTP_FIFO_INTERFACE_CAPABILITY InterfaceCapability;
|
||||
UINT8 StatusEx;
|
||||
UINT16 Vid;
|
||||
UINT16 Did;
|
||||
UINT8 Rid;
|
||||
|
||||
if (!Tpm2IsPtpPresence (Register)) {
|
||||
return;
|
||||
}
|
||||
|
||||
InterfaceId.Uint32 = MmioRead32 ((UINTN)&((PTP_CRB_REGISTERS *)Register)->InterfaceId);
|
||||
InterfaceCapability.Uint32 = MmioRead32 ((UINTN)&((PTP_FIFO_REGISTERS *)Register)->InterfaceCapability);
|
||||
StatusEx = MmioRead8 ((UINTN)&((PTP_FIFO_REGISTERS *)Register)->StatusEx);
|
||||
|
||||
//
|
||||
// Dump InterfaceId Register for PTP
|
||||
//
|
||||
DEBUG ((DEBUG_INFO, "InterfaceId - 0x%08x\n", InterfaceId.Uint32));
|
||||
DEBUG ((DEBUG_INFO, " InterfaceType - 0x%02x\n", InterfaceId.Bits.InterfaceType));
|
||||
if (InterfaceId.Bits.InterfaceType != PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_TIS) {
|
||||
DEBUG ((DEBUG_INFO, " InterfaceVersion - 0x%02x\n", InterfaceId.Bits.InterfaceVersion));
|
||||
DEBUG ((DEBUG_INFO, " CapFIFO - 0x%x\n", InterfaceId.Bits.CapFIFO));
|
||||
DEBUG ((DEBUG_INFO, " CapCRB - 0x%x\n", InterfaceId.Bits.CapCRB));
|
||||
}
|
||||
|
||||
//
|
||||
// Dump Capability Register for TIS and FIFO
|
||||
//
|
||||
DEBUG ((DEBUG_INFO, "InterfaceCapability - 0x%08x\n", InterfaceCapability.Uint32));
|
||||
if ((InterfaceId.Bits.InterfaceType == PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_TIS) ||
|
||||
(InterfaceId.Bits.InterfaceType == PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_FIFO))
|
||||
{
|
||||
DEBUG ((DEBUG_INFO, " InterfaceVersion - 0x%x\n", InterfaceCapability.Bits.InterfaceVersion));
|
||||
}
|
||||
|
||||
//
|
||||
// Dump StatusEx Register for PTP FIFO
|
||||
//
|
||||
DEBUG ((DEBUG_INFO, "StatusEx - 0x%02x\n", StatusEx));
|
||||
if (InterfaceCapability.Bits.InterfaceVersion == INTERFACE_CAPABILITY_INTERFACE_VERSION_PTP) {
|
||||
DEBUG ((DEBUG_INFO, " TpmFamily - 0x%x\n", (StatusEx & PTP_FIFO_STS_EX_TPM_FAMILY) >> PTP_FIFO_STS_EX_TPM_FAMILY_OFFSET));
|
||||
}
|
||||
|
||||
Vid = MmioRead16 ((UINTN)&((PTP_CRB_REGISTERS *)Register)->Vid);
|
||||
Did = MmioRead16 ((UINTN)&((PTP_CRB_REGISTERS *)Register)->Did);
|
||||
Rid = (UINT8)InterfaceId.Bits.Rid;
|
||||
|
||||
DEBUG ((DEBUG_INFO, "VID - 0x%04x\n", Vid));
|
||||
DEBUG ((DEBUG_INFO, "DID - 0x%04x\n", Did));
|
||||
DEBUG ((DEBUG_INFO, "RID - 0x%02x\n", Rid));
|
||||
}
|
||||
|
||||
/**
|
||||
This service enables the sending of commands to the TPM2.
|
||||
|
||||
@param[in] InputParameterBlockSize Size of the TPM2 input parameter block.
|
||||
@param[in] InputParameterBlock Pointer to the TPM2 input parameter block.
|
||||
@param[in,out] OutputParameterBlockSize Size of the TPM2 output parameter block.
|
||||
@param[in] OutputParameterBlock Pointer to the TPM2 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
|
||||
FfaTpm2SubmitCommand (
|
||||
IN UINT32 InputParameterBlockSize,
|
||||
IN UINT8 *InputParameterBlock,
|
||||
IN OUT UINT32 *OutputParameterBlockSize,
|
||||
IN UINT8 *OutputParameterBlock
|
||||
)
|
||||
{
|
||||
return PtpCrbTpmCommand (
|
||||
(PTP_CRB_REGISTERS_PTR)(UINTN)PcdGet64 (PcdTpmBaseAddress),
|
||||
InputParameterBlock,
|
||||
InputParameterBlockSize,
|
||||
OutputParameterBlock,
|
||||
OutputParameterBlockSize
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
This service requests use TPM2 over FF-A.
|
||||
|
||||
@retval EFI_SUCCESS Get the control of TPM2 chip.
|
||||
@retval EFI_NOT_FOUND TPM2 not found.
|
||||
@retval EFI_DEVICE_ERROR Unexpected device behavior.
|
||||
**/
|
||||
EFI_STATUS
|
||||
FfaTpm2RequestUseTpm (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return PtpCrbRequestUseTpm ((PTP_CRB_REGISTERS_PTR)(UINTN)PcdGet64 (PcdTpmBaseAddress));
|
||||
}
|
||||
441
SecurityPkg/Library/Tpm2DeviceLibFfa/Tpm2ServiceFfaRaw.c
Normal file
441
SecurityPkg/Library/Tpm2DeviceLibFfa/Tpm2ServiceFfaRaw.c
Normal file
@@ -0,0 +1,441 @@
|
||||
/** @file
|
||||
This library provides an implementation of Tpm2DeviceLib
|
||||
using ARM64 SMC calls to request TPM service.
|
||||
|
||||
The implementation is only supporting the Command Response Buffer (CRB)
|
||||
for sharing data with the TPM.
|
||||
|
||||
Copyright (c), Microsoft Corporation.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include <Uefi.h>
|
||||
#include <Pi/PiMultiPhase.h>
|
||||
#include <IndustryStandard/ArmFfaSvc.h>
|
||||
#include <IndustryStandard/ArmFfaBootInfo.h>
|
||||
#include <IndustryStandard/ArmFfaPartInfo.h>
|
||||
#include <Guid/Tpm2ServiceFfa.h>
|
||||
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/Tpm2DeviceLib.h>
|
||||
#include <Library/ArmFfaLib.h>
|
||||
|
||||
#include "Tpm2DeviceLibFfa.h"
|
||||
|
||||
UINT32 mFfaTpm2PartitionId = MAX_UINT32;
|
||||
|
||||
/**
|
||||
Check the return status from the FF-A call and returns EFI_STATUS
|
||||
|
||||
@param EFI_LOAD_ERROR FF-A status code returned in x0
|
||||
|
||||
@retval EFI_SUCCESS The entry point is executed successfully.
|
||||
**/
|
||||
EFI_STATUS
|
||||
TranslateTpmReturnStatus (
|
||||
UINTN TpmReturnStatus
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
switch (TpmReturnStatus) {
|
||||
case TPM2_FFA_SUCCESS_OK:
|
||||
case TPM2_FFA_SUCCESS_OK_RESULTS_RETURNED:
|
||||
Status = EFI_SUCCESS;
|
||||
break;
|
||||
|
||||
case TPM2_FFA_ERROR_NOFUNC:
|
||||
Status = EFI_NOT_FOUND;
|
||||
break;
|
||||
|
||||
case TPM2_FFA_ERROR_NOTSUP:
|
||||
Status = EFI_UNSUPPORTED;
|
||||
break;
|
||||
|
||||
case TPM2_FFA_ERROR_INVARG:
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
break;
|
||||
|
||||
case TPM2_FFA_ERROR_INV_CRB_CTRL_DATA:
|
||||
Status = EFI_COMPROMISED_DATA;
|
||||
break;
|
||||
|
||||
case TPM2_FFA_ERROR_ALREADY:
|
||||
Status = EFI_ALREADY_STARTED;
|
||||
break;
|
||||
|
||||
case TPM2_FFA_ERROR_DENIED:
|
||||
Status = EFI_ACCESS_DENIED;
|
||||
break;
|
||||
|
||||
case TPM2_FFA_ERROR_NOMEM:
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
break;
|
||||
|
||||
default:
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
This function is used to get the TPM service partition id.
|
||||
|
||||
@param[out] PartitionId - Supplies the pointer to the TPM service partition id.
|
||||
|
||||
@retval EFI_SUCCESS The TPM command was successfully sent to the TPM
|
||||
and the response was copied to the Output buffer.
|
||||
@retval EFI_INVALID_PARAMETER The TPM command buffer is NULL or the TPM command
|
||||
buffer size is 0.
|
||||
@retval EFI_DEVICE_ERROR An error occurred in communication with the TPM.
|
||||
**/
|
||||
EFI_STATUS
|
||||
GetTpmServicePartitionId (
|
||||
OUT UINT32 *PartitionId
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 Count;
|
||||
UINT32 Size;
|
||||
EFI_FFA_PART_INFO_DESC *TpmPartInfo;
|
||||
VOID *TxBuffer;
|
||||
UINT64 TxBufferSize;
|
||||
VOID *RxBuffer;
|
||||
UINT64 RxBufferSize;
|
||||
UINT16 PartId;
|
||||
|
||||
if (PartitionId == NULL) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (mFfaTpm2PartitionId != MAX_UINT32) {
|
||||
*PartitionId = mFfaTpm2PartitionId;
|
||||
Status = EFI_SUCCESS;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (PcdGet16 (PcdTpmServiceFfaPartitionId) != 0) {
|
||||
mFfaTpm2PartitionId = PcdGet16 (PcdTpmServiceFfaPartitionId);
|
||||
*PartitionId = mFfaTpm2PartitionId;
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Status = ArmFfaLibPartitionIdGet (&PartId);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"Failed to get partition id. Status: %r\n",
|
||||
Status
|
||||
));
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Status = ArmFfaLibGetRxTxBuffers (
|
||||
&TxBuffer,
|
||||
&TxBufferSize,
|
||||
&RxBuffer,
|
||||
&RxBufferSize
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "Failed to get Rx/Tx Buffer. Status: %r\n", Status));
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Status = ArmFfaLibPartitionInfoGet (
|
||||
&gTpm2ServiceFfaGuid,
|
||||
FFA_PART_INFO_FLAG_TYPE_DESC,
|
||||
&Count,
|
||||
&Size
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "Failed to get Tpm2 partition info. Status: %r\n", Status));
|
||||
goto RxRelease;
|
||||
}
|
||||
|
||||
if ((Count != 1) || (Size < sizeof (EFI_FFA_PART_INFO_DESC))) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
DEBUG ((DEBUG_ERROR, "Invalid partition Info(%g). Count: %d, Size: %d\n", &gTpm2ServiceFfaGuid, Count, Size));
|
||||
} else {
|
||||
TpmPartInfo = (EFI_FFA_PART_INFO_DESC *)RxBuffer;
|
||||
mFfaTpm2PartitionId = TpmPartInfo->PartitionId;
|
||||
*PartitionId = mFfaTpm2PartitionId;
|
||||
|
||||
Status = PcdSet16S (PcdTpmServiceFfaPartitionId, mFfaTpm2PartitionId);
|
||||
}
|
||||
|
||||
RxRelease:
|
||||
ArmFfaLibRxRelease (PartId);
|
||||
|
||||
Exit:
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
This function is used to get the TPM interface version.
|
||||
|
||||
@param[out] Version - Supplies the pointer to the TPM interface version.
|
||||
|
||||
@retval EFI_SUCCESS The TPM command was successfully sent to the TPM
|
||||
and the response was copied to the Output buffer.
|
||||
@retval EFI_INVALID_PARAMETER The TPM command buffer is NULL or the TPM command
|
||||
buffer size is 0.
|
||||
@retval EFI_DEVICE_ERROR An error occurred in communication with the TPM.
|
||||
**/
|
||||
EFI_STATUS
|
||||
Tpm2GetInterfaceVersion (
|
||||
OUT UINT32 *Version
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
DIRECT_MSG_ARGS FfaDirectReq2Args;
|
||||
|
||||
if (Version == NULL) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (mFfaTpm2PartitionId == MAX_UINT32) {
|
||||
GetTpmServicePartitionId (&mFfaTpm2PartitionId);
|
||||
}
|
||||
|
||||
ZeroMem (&FfaDirectReq2Args, sizeof (DIRECT_MSG_ARGS));
|
||||
FfaDirectReq2Args.Arg0 = TPM2_FFA_GET_INTERFACE_VERSION;
|
||||
|
||||
Status = ArmFfaLibMsgSendDirectReq2 (mFfaTpm2PartitionId, &gTpm2ServiceFfaGuid, &FfaDirectReq2Args);
|
||||
while (Status == EFI_INTERRUPT_PENDING) {
|
||||
// We are assuming vCPU0 of the TPM SP since it is UP.
|
||||
Status = ArmFfaLibRun (mFfaTpm2PartitionId, 0x00);
|
||||
}
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Status = TranslateTpmReturnStatus (FfaDirectReq2Args.Arg0);
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
*Version = FfaDirectReq2Args.Arg1;
|
||||
}
|
||||
|
||||
Exit:
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
This function is used to get the TPM feature information.
|
||||
|
||||
@param[out] FeatureInfo - Supplies the pointer to the feature information.
|
||||
|
||||
@retval EFI_SUCCESS The TPM command was successfully sent to the TPM
|
||||
and the response was copied to the Output buffer.
|
||||
@retval EFI_INVALID_PARAMETER The TPM command buffer is NULL or the TPM command
|
||||
buffer size is 0.
|
||||
@retval EFI_DEVICE_ERROR An error occurred in communication with the TPM.
|
||||
**/
|
||||
EFI_STATUS
|
||||
Tpm2GetFeatureInfo (
|
||||
OUT UINT32 *FeatureInfo
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
DIRECT_MSG_ARGS FfaDirectReq2Args;
|
||||
|
||||
if (FeatureInfo == NULL) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (mFfaTpm2PartitionId == MAX_UINT32) {
|
||||
GetTpmServicePartitionId (&mFfaTpm2PartitionId);
|
||||
}
|
||||
|
||||
ZeroMem (&FfaDirectReq2Args, sizeof (DIRECT_MSG_ARGS));
|
||||
FfaDirectReq2Args.Arg0 = TPM2_FFA_GET_FEATURE_INFO;
|
||||
FfaDirectReq2Args.Arg1 = TPM_SERVICE_FEATURE_SUPPORT_NOTIFICATION;
|
||||
|
||||
Status = ArmFfaLibMsgSendDirectReq2 (mFfaTpm2PartitionId, &gTpm2ServiceFfaGuid, &FfaDirectReq2Args);
|
||||
while (Status == EFI_INTERRUPT_PENDING) {
|
||||
// We are assuming vCPU0 of the TPM SP since it is UP.
|
||||
Status = ArmFfaLibRun (mFfaTpm2PartitionId, 0x00);
|
||||
}
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Status = TranslateTpmReturnStatus (FfaDirectReq2Args.Arg0);
|
||||
|
||||
Exit:
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
This service enables the sending of commands to the TPM2.
|
||||
|
||||
@param[in] FuncQualifier Function qualifier.
|
||||
@param[in] LocalityQualifier Locality qualifier.
|
||||
|
||||
@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
|
||||
Tpm2ServiceStart (
|
||||
IN UINT64 FuncQualifier,
|
||||
IN UINT64 LocalityQualifier
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
DIRECT_MSG_ARGS FfaDirectReq2Args;
|
||||
|
||||
if (mFfaTpm2PartitionId == MAX_UINT32) {
|
||||
GetTpmServicePartitionId (&mFfaTpm2PartitionId);
|
||||
}
|
||||
|
||||
ZeroMem (&FfaDirectReq2Args, sizeof (DIRECT_MSG_ARGS));
|
||||
FfaDirectReq2Args.Arg0 = TPM2_FFA_START;
|
||||
FfaDirectReq2Args.Arg1 = (FuncQualifier & 0xFF);
|
||||
FfaDirectReq2Args.Arg2 = (LocalityQualifier & 0xFF);
|
||||
|
||||
Status = ArmFfaLibMsgSendDirectReq2 (mFfaTpm2PartitionId, &gTpm2ServiceFfaGuid, &FfaDirectReq2Args);
|
||||
while (Status == EFI_INTERRUPT_PENDING) {
|
||||
// We are assuming vCPU0 of the TPM SP since it is UP.
|
||||
Status = ArmFfaLibRun (mFfaTpm2PartitionId, 0x00);
|
||||
}
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Status = TranslateTpmReturnStatus (FfaDirectReq2Args.Arg0);
|
||||
|
||||
Exit:
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Register TPM2 device notification.
|
||||
|
||||
@param[in] NotificationTypeQualifier Notification type qualifier.
|
||||
@param[in] vCpuId vCPU ID.
|
||||
@param[in] NotificationId Bitmap ID for the notification.
|
||||
|
||||
@retval EFI_SUCCESS The command was successfully sent to the device and a response was successfully received.
|
||||
@retval Others Some error occurred in communication with the device.
|
||||
**/
|
||||
EFI_STATUS
|
||||
Tpm2RegisterNotification (
|
||||
IN BOOLEAN NotificationTypeQualifier,
|
||||
IN UINT16 vCpuId,
|
||||
IN UINT64 NotificationId
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
DIRECT_MSG_ARGS FfaDirectReq2Args;
|
||||
|
||||
if (mFfaTpm2PartitionId == MAX_UINT32) {
|
||||
GetTpmServicePartitionId (&mFfaTpm2PartitionId);
|
||||
}
|
||||
|
||||
ZeroMem (&FfaDirectReq2Args, sizeof (DIRECT_MSG_ARGS));
|
||||
FfaDirectReq2Args.Arg0 = TPM2_FFA_REGISTER_FOR_NOTIFICATION;
|
||||
FfaDirectReq2Args.Arg1 = (NotificationTypeQualifier << 16 | vCpuId);
|
||||
FfaDirectReq2Args.Arg2 = (NotificationId & 0xFF);
|
||||
|
||||
Status = ArmFfaLibMsgSendDirectReq2 (mFfaTpm2PartitionId, &gTpm2ServiceFfaGuid, &FfaDirectReq2Args);
|
||||
while (Status == EFI_INTERRUPT_PENDING) {
|
||||
// We are assuming vCPU0 of the TPM SP since it is UP.
|
||||
Status = ArmFfaLibRun (mFfaTpm2PartitionId, 0x00);
|
||||
}
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Status = TranslateTpmReturnStatus (FfaDirectReq2Args.Arg0);
|
||||
|
||||
Exit:
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Unregister TPM2 device notification.
|
||||
|
||||
@retval EFI_SUCCESS The command was successfully sent to the device and a response was successfully received.
|
||||
@retval Others Some error occurred in communication with the device.
|
||||
**/
|
||||
EFI_STATUS
|
||||
Tpm2UnregisterNotification (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
DIRECT_MSG_ARGS FfaDirectReq2Args;
|
||||
|
||||
if (mFfaTpm2PartitionId == MAX_UINT32) {
|
||||
GetTpmServicePartitionId (&mFfaTpm2PartitionId);
|
||||
}
|
||||
|
||||
ZeroMem (&FfaDirectReq2Args, sizeof (DIRECT_MSG_ARGS));
|
||||
FfaDirectReq2Args.Arg0 = TPM2_FFA_UNREGISTER_FROM_NOTIFICATION;
|
||||
|
||||
Status = ArmFfaLibMsgSendDirectReq2 (mFfaTpm2PartitionId, &gTpm2ServiceFfaGuid, &FfaDirectReq2Args);
|
||||
while (Status == EFI_INTERRUPT_PENDING) {
|
||||
// We are assuming vCPU0 of the TPM SP since it is UP.
|
||||
Status = ArmFfaLibRun (mFfaTpm2PartitionId, 0x00);
|
||||
}
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Status = TranslateTpmReturnStatus (FfaDirectReq2Args.Arg0);
|
||||
|
||||
Exit:
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Issue a finished notification command to the TPM service over FF-A.
|
||||
|
||||
@retval EFI_SUCCESS The command was successfully sent to the device and a response was successfully received.
|
||||
@retval Others Some error occurred in communication with the device.
|
||||
**/
|
||||
EFI_STATUS
|
||||
Tpm2FinishNotified (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
DIRECT_MSG_ARGS FfaDirectReq2Args;
|
||||
|
||||
if (mFfaTpm2PartitionId == MAX_UINT32) {
|
||||
GetTpmServicePartitionId (&mFfaTpm2PartitionId);
|
||||
}
|
||||
|
||||
ZeroMem (&FfaDirectReq2Args, sizeof (DIRECT_MSG_ARGS));
|
||||
FfaDirectReq2Args.Arg0 = TPM2_FFA_FINISH_NOTIFIED;
|
||||
|
||||
Status = ArmFfaLibMsgSendDirectReq2 (mFfaTpm2PartitionId, &gTpm2ServiceFfaGuid, &FfaDirectReq2Args);
|
||||
while (Status == EFI_INTERRUPT_PENDING) {
|
||||
// We are assuming vCPU0 of the TPM SP since it is UP.
|
||||
Status = ArmFfaLibRun (mFfaTpm2PartitionId, 0x00);
|
||||
}
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Status = TranslateTpmReturnStatus (FfaDirectReq2Args.Arg0);
|
||||
|
||||
Exit:
|
||||
return Status;
|
||||
}
|
||||
@@ -425,6 +425,7 @@
|
||||
[Components.AARCH64]
|
||||
SecurityPkg/Tcg/Tcg2StandaloneMmArm/Tcg2StandaloneMmArm.inf
|
||||
SecurityPkg/Tcg/Tcg2AcpiFfa/Tcg2AcpiFfa.inf
|
||||
SecurityPkg/Library/Tpm2DeviceLibFfa/Tpm2DeviceLibFfa.inf
|
||||
|
||||
[BuildOptions]
|
||||
MSFT:*_*_IA32_DLINK_FLAGS = /ALIGN:256
|
||||
|
||||
Reference in New Issue
Block a user