Skip to content

Commit

Permalink
Introduce Tpm2DeviceLibFfa for TPM over FF-A (#341)
Browse files Browse the repository at this point in the history
## Description

This change introduces a `Tpm2DeviceLibFfa` library to support TPM over
FF-A.

This is the initial effort to move all FF-A related support to mainline.

For details on how to complete these options and their meaning refer to
[CONTRIBUTING.md](https://github.com/microsoft/mu/blob/HEAD/CONTRIBUTING.md).

- [x] Impacts functionality?
- [ ] Impacts security?
- [ ] Breaking change?
- [ ] Includes tests?
- [ ] Includes documentation?
- [ ] Backport to release branch?

## How This Was Tested

N/A

## Integration Instructions

N/A
  • Loading branch information
kuqin12 authored Feb 26, 2025
1 parent 2da5ed1 commit cf7b818
Show file tree
Hide file tree
Showing 9 changed files with 1,312 additions and 1 deletion.
3 changes: 2 additions & 1 deletion ArmPkg/ArmPkg.ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@
"MdeModulePkg/MdeModulePkg.dec",
"MdePkg/MdePkg.dec",
"ShellPkg/ShellPkg.dec",
"StandaloneMmPkg/StandaloneMmPkg.dec"
"StandaloneMmPkg/StandaloneMmPkg.dec", # MU_CHANGE
"SecurityPkg/SecurityPkg.dec", # MU_CHANGE
],
# For host based unit tests
"AcceptableDependencies-HOST_APPLICATION":[
Expand Down
4 changes: 4 additions & 0 deletions ArmPkg/ArmPkg.dec
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@
gArmMpCoreInfoGuid = { 0xa4ee0728, 0xe5d7, 0x4ac5, {0xb2, 0x1e, 0x65, 0x8e, 0xd8, 0x57, 0xe8, 0x34} }

# MU_CHANGE [BEGIN]
## TPM Service over FF-A
# Include/Guid/Tpm2ServiceFfa.h
gEfiTpm2ServiceFfaGuid = { 0x17b862a4, 0x1806, 0x4faf, { 0x86, 0xb3, 0x08, 0x9a, 0x58, 0x35, 0x38, 0x61 } }

## SMMU config data
# Include/Guid/SmmuConfig.h
gSmmuConfigHobGuid = { 0xcd56ec8f, 0x75f1, 0x440a, { 0xaa, 0x48, 0x09, 0x58, 0xb1, 0x1c, 0x9a, 0xa7 } }
Expand Down
1 change: 1 addition & 0 deletions ArmPkg/ArmPkg.dsc
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@
ArmPkg/Library/SemihostLib/SemihostLib.inf
ArmPkg/Library/ArmExceptionLib/ArmExceptionLib.inf
ArmPkg/Library/ArmExceptionLib/ArmRelocateExceptionLib.inf
ArmPkg/Library/Tpm2DeviceLibFfa/Tpm2DeviceLibFfa.inf # MU_CHANGE

ArmPkg/Drivers/CpuDxe/CpuDxe.inf
ArmPkg/Drivers/CpuPei/CpuPei.inf
Expand Down
40 changes: 40 additions & 0 deletions ArmPkg/Include/Guid/Tpm2ServiceFfa.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/** @file
Provides function interfaces to communicate with TPM 2.0 service through FF-A.
Copyright (c), Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#ifndef TPM2_SERVICE_FFA_H_
#define TPM2_SERVICE_FFA_H_

#define EFI_TPM2_SERVICE_FFA_GUID \
{ 0x17b862a4, 0x1806, 0x4faf, { 0x86, 0xb3, 0x08, 0x9a, 0x58, 0x35, 0x38, 0x61 } }

#define TPM2_FFA_GET_INTERFACE_VERSION 0x0f000001
#define TPM2_FFA_GET_FEATURE_INFO 0x0f000101
#define TPM2_FFA_START 0x0f000201
#define TPM2_FFA_REGISTER_FOR_NOTIFICATION 0x0f000301
#define TPM2_FFA_UNREGISTER_FROM_NOTIFICATION 0x0f000401
#define TPM2_FFA_FINISH_NOTIFIED 0x0f000501

#define TPM2_FFA_SUCCESS_OK 0x05000001
#define TPM2_FFA_SUCCESS_OK_RESULTS_RETURNED 0x05000002

#define TPM2_FFA_ERROR_NOFUNC 0x8e000001
#define TPM2_FFA_ERROR_NOTSUP 0x8e000002
#define TPM2_FFA_ERROR_INVARG 0x8e000005
#define TPM2_FFA_ERROR_INV_CRB_CTRL_DATA 0x8e000006
#define TPM2_FFA_ERROR_ALREADY 0x8e000009
#define TPM2_FFA_ERROR_DENIED 0x8e00000a
#define TPM2_FFA_ERROR_NOMEM 0x8e00000b

#define TPM_SERVICE_FEATURE_SUPPORT_NOTIFICATION 0xfea70000

#define TPM2_FFA_START_FUNC_QUALIFIER_COMMAND 0x0
#define TPM2_FFA_START_FUNC_QUALIFIER_LOCALITY 0x1

extern EFI_GUID gEfiTpm2ServiceFfaGuid;

#endif /* TPM2_SERVICE_FFA_H_ */
207 changes: 207 additions & 0 deletions ArmPkg/Library/Tpm2DeviceLibFfa/Tpm2DeviceLibFfa.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
/** @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;
}

/**
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 the return status from the FF-A call and returns EFI_STATUS
@param FfaReturnStatus FF-A return status
@retval EFI_SUCCESS The entry point is executed successfully.
@retval Others Other corresponding EFI_STATUS.
**/
EFI_STATUS
TranslateFfaReturnStatus (
UINTN FfaReturnStatus
)
{
EFI_STATUS Status;

switch (FfaReturnStatus) {
case ARM_FFA_RET_SUCCESS:
Status = EFI_SUCCESS;
break;

case ARM_FFA_RET_NOT_SUPPORTED:
Status = EFI_UNSUPPORTED;
break;

case ARM_FFA_RET_INVALID_PARAMETERS:
Status = EFI_INVALID_PARAMETER;
break;

case ARM_FFA_RET_NO_MEMORY:
Status = EFI_BUFFER_TOO_SMALL;
break;

case ARM_FFA_RET_BUSY:
Status = EFI_WRITE_PROTECTED;
break;

case ARM_FFA_RET_INTERRUPTED:
Status = EFI_MEDIA_CHANGED;
break;

case ARM_FFA_RET_DENIED:
Status = EFI_ACCESS_DENIED;
break;

case ARM_FFA_RET_RETRY:
Status = EFI_LOAD_ERROR;
break;

case ARM_FFA_RET_ABORTED:
Status = EFI_ABORTED;
break;

case ARM_FFA_RET_NODATA:
Status = EFI_NOT_FOUND;
break;

case ARM_FFA_RET_NOT_READY:
Status = EFI_NOT_READY;
break;

default:
Status = EFI_DEVICE_ERROR;
}

return Status;
}

/**
Check that we have an address for the CRB
@retval EFI_SUCCESS The entry point is executed successfully.
@retval EFI_NOT_STARTED The TPM base address is not set up.
@retval EFI_UNSUPPORTED The TPM interface type is not supported.
**/
EFI_STATUS
EFIAPI
Tpm2DeviceLibFfaConstructor (
VOID
)
{
EFI_STATUS Status;

mActiveTpmInterfaceType = PcdGet8 (PcdActiveTpmInterfaceType);
mCRBIdleByPass = 0xFF;

if (PcdGet64 (PcdTpmBaseAddress) == 0) {
Status = EFI_NOT_STARTED;
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;
}
Loading

0 comments on commit cf7b818

Please sign in to comment.