Skip to content

Commit 9504836

Browse files
committed
Merge: Update support for Arm FF-A firmware interface.
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/1208 JIRA: https://issues.redhat.com/browse/RHEL-102692 ## Summary of Changes The following series updates support for Arm FF-A firmware interface. Signed-off-by: Marcin Juszkiewicz <mjuszkiewicz@redhat.com> Approved-by: Lucas Zampieri <lzampier@redhat.com> Approved-by: Mark Salter <msalter@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Scott Weaver <scweaver@redhat.com>
2 parents 2593138 + 73bcf18 commit 9504836

File tree

12 files changed

+967
-182
lines changed

12 files changed

+967
-182
lines changed

Documentation/security/tpm/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ Trusted Platform Module documentation
1010
tpm_vtpm_proxy
1111
xen-tpmfront
1212
tpm_ftpm_tee
13+
tpm_ffa_crb
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
.. SPDX-License-Identifier: GPL-2.0
2+
3+
========================
4+
TPM CRB over FF-A Driver
5+
========================
6+
7+
The TPM Command Response Buffer (CRB) interface is a standard TPM interface
8+
defined in the TCG PC Client Platform TPM Profile (PTP) Specification [1]_.
9+
The CRB provides a structured set of control registers a client uses when
10+
interacting with a TPM as well as a data buffer for storing TPM commands and
11+
responses. A CRB interface can be implemented in:
12+
13+
- hardware registers in a discrete TPM chip
14+
15+
- in memory for a TPM running in isolated environment where shared memory
16+
allows a client to interact with the TPM
17+
18+
The Firmware Framework for Arm A-profile (FF-A) [2]_ is a specification
19+
that defines interfaces and protocols for the following purposes:
20+
21+
- Compartmentalize firmware into software partitions that run in the Arm
22+
Secure world environment (also know as TrustZone)
23+
24+
- Provide a standard interface for software components in the Non-secure
25+
state, for example OS and Hypervisors, to communicate with this firmware.
26+
27+
A TPM can be implemented as an FF-A secure service. This could be a firmware
28+
TPM or could potentially be a TPM service that acts as a proxy to a discrete
29+
TPM chip. An FF-A based TPM abstracts hardware details (e.g. bus controller
30+
and chip selects) away from the OS and can protect locality 4 from access
31+
by an OS. The TCG-defined CRB interface is used by clients to interact
32+
with the TPM service.
33+
34+
The Arm TPM Service Command Response Buffer Interface Over FF-A [3]_
35+
specification defines FF-A messages that can be used by a client to signal
36+
when updates have been made to the CRB.
37+
38+
How the Linux CRB driver interacts with FF-A is summarized below:
39+
40+
- The tpm_crb_ffa driver registers with the FF-A subsystem in the kernel
41+
with an architected TPM service UUID defined in the CRB over FF-A spec.
42+
43+
- If a TPM service is discovered by FF-A, the probe() function in the
44+
tpm_crb_ffa driver runs, and the driver initializes.
45+
46+
- The probing and initialization of the Linux CRB driver is triggered
47+
by the discovery of a TPM advertised via ACPI. The CRB driver can
48+
detect the type of TPM through the ACPI 'start' method. The start
49+
method for Arm FF-A was defined in TCG ACPI v1.4 [4]_.
50+
51+
- When the CRB driver performs its normal functions such as signaling 'start'
52+
and locality request/relinquish it invokes the tpm_crb_ffa_start() funnction
53+
in the tpm_crb_ffa driver which handles the FF-A messaging to the TPM.
54+
55+
References
56+
==========
57+
58+
.. [1] **TCG PC Client Platform TPM Profile (PTP) Specification**
59+
https://trustedcomputinggroup.org/resource/pc-client-platform-tpm-profile-ptp-specification/
60+
.. [2] **Arm Firmware Framework for Arm A-profile (FF-A)**
61+
https://developer.arm.com/documentation/den0077/latest/
62+
.. [3] **Arm TPM Service Command Response Buffer Interface Over FF-A**
63+
https://developer.arm.com/documentation/den0138/latest/
64+
.. [4] **TCG ACPI Specification**
65+
https://trustedcomputinggroup.org/resource/tcg-acpi-specification/

drivers/char/tpm/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,15 @@ config TCG_CRB
210210
from within Linux. To compile this driver as a module, choose
211211
M here; the module will be called tpm_crb.
212212

213+
config TCG_ARM_CRB_FFA
214+
tristate "TPM CRB over Arm FF-A Transport"
215+
depends on ARM_FFA_TRANSPORT && TCG_CRB
216+
default TCG_CRB
217+
help
218+
If the Arm FF-A transport is used to access the TPM say Yes.
219+
To compile this driver as a module, choose M here; the module
220+
will be called tpm_crb_ffa.
221+
213222
config TCG_VTPM_PROXY
214223
tristate "VTPM Proxy Interface"
215224
depends on TCG_TPM

drivers/char/tpm/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ obj-$(CONFIG_TCG_IBMVTPM) += tpm_ibmvtpm.o
4242
obj-$(CONFIG_TCG_TIS_ST33ZP24) += st33zp24/
4343
obj-$(CONFIG_TCG_XEN) += xen-tpmfront.o
4444
obj-$(CONFIG_TCG_CRB) += tpm_crb.o
45+
obj-$(CONFIG_TCG_ARM_CRB_FFA) += tpm_crb_ffa.o
4546
obj-$(CONFIG_TCG_VTPM_PROXY) += tpm_vtpm_proxy.o
4647
obj-$(CONFIG_TCG_FTPM_TEE) += tpm_ftpm_tee.o
4748
obj-$(CONFIG_TCG_SVSM) += tpm_svsm.o

drivers/char/tpm/tpm_crb.c

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#ifdef CONFIG_ARM64
2020
#include <linux/arm-smccc.h>
2121
#endif
22+
#include "tpm_crb_ffa.h"
2223
#include "tpm.h"
2324

2425
#define ACPI_SIG_TPM2 "TPM2"
@@ -100,6 +101,8 @@ struct crb_priv {
100101
u32 smc_func_id;
101102
u32 __iomem *pluton_start_addr;
102103
u32 __iomem *pluton_reply_addr;
104+
u8 ffa_flags;
105+
u8 ffa_attributes;
103106
};
104107

105108
struct tpm2_crb_smc {
@@ -110,6 +113,14 @@ struct tpm2_crb_smc {
110113
u32 smc_func_id;
111114
};
112115

116+
/* CRB over FFA start method parameters in TCG2 ACPI table */
117+
struct tpm2_crb_ffa {
118+
u8 flags;
119+
u8 attributes;
120+
u16 partition_id;
121+
u8 reserved[8];
122+
};
123+
113124
struct tpm2_crb_pluton {
114125
u64 start_addr;
115126
u64 reply_addr;
@@ -122,7 +133,8 @@ static inline bool tpm_crb_has_idle(u32 start_method)
122133
{
123134
return !(start_method == ACPI_TPM2_START_METHOD ||
124135
start_method == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD ||
125-
start_method == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC);
136+
start_method == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC ||
137+
start_method == ACPI_TPM2_CRB_WITH_ARM_FFA);
126138
}
127139

128140
static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value,
@@ -261,13 +273,20 @@ static int crb_cmd_ready(struct tpm_chip *chip)
261273
static int __crb_request_locality(struct device *dev,
262274
struct crb_priv *priv, int loc)
263275
{
264-
u32 value = CRB_LOC_STATE_LOC_ASSIGNED |
265-
CRB_LOC_STATE_TPM_REG_VALID_STS;
276+
u32 value = CRB_LOC_STATE_LOC_ASSIGNED | CRB_LOC_STATE_TPM_REG_VALID_STS;
277+
int rc;
266278

267279
if (!priv->regs_h)
268280
return 0;
269281

270282
iowrite32(CRB_LOC_CTRL_REQUEST_ACCESS, &priv->regs_h->loc_ctrl);
283+
284+
if (priv->sm == ACPI_TPM2_CRB_WITH_ARM_FFA) {
285+
rc = tpm_crb_ffa_start(CRB_FFA_START_TYPE_LOCALITY_REQUEST, loc);
286+
if (rc)
287+
return rc;
288+
}
289+
271290
if (!crb_wait_for_reg_32(&priv->regs_h->loc_state, value, value,
272291
TPM2_TIMEOUT_C)) {
273292
dev_warn(dev, "TPM_LOC_STATE_x.requestAccess timed out\n");
@@ -287,14 +306,21 @@ static int crb_request_locality(struct tpm_chip *chip, int loc)
287306
static int __crb_relinquish_locality(struct device *dev,
288307
struct crb_priv *priv, int loc)
289308
{
290-
u32 mask = CRB_LOC_STATE_LOC_ASSIGNED |
291-
CRB_LOC_STATE_TPM_REG_VALID_STS;
309+
u32 mask = CRB_LOC_STATE_LOC_ASSIGNED | CRB_LOC_STATE_TPM_REG_VALID_STS;
292310
u32 value = CRB_LOC_STATE_TPM_REG_VALID_STS;
311+
int rc;
293312

294313
if (!priv->regs_h)
295314
return 0;
296315

297316
iowrite32(CRB_LOC_CTRL_RELINQUISH, &priv->regs_h->loc_ctrl);
317+
318+
if (priv->sm == ACPI_TPM2_CRB_WITH_ARM_FFA) {
319+
rc = tpm_crb_ffa_start(CRB_FFA_START_TYPE_LOCALITY_REQUEST, loc);
320+
if (rc)
321+
return rc;
322+
}
323+
298324
if (!crb_wait_for_reg_32(&priv->regs_h->loc_state, mask, value,
299325
TPM2_TIMEOUT_C)) {
300326
dev_warn(dev, "TPM_LOC_STATE_x.Relinquish timed out\n");
@@ -443,6 +469,11 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len)
443469
rc = tpm_crb_smc_start(&chip->dev, priv->smc_func_id);
444470
}
445471

472+
if (priv->sm == ACPI_TPM2_CRB_WITH_ARM_FFA) {
473+
iowrite32(CRB_START_INVOKE, &priv->regs_t->ctrl_start);
474+
rc = tpm_crb_ffa_start(CRB_FFA_START_TYPE_COMMAND, chip->locality);
475+
}
476+
446477
if (rc)
447478
return rc;
448479

@@ -452,13 +483,20 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len)
452483
static void crb_cancel(struct tpm_chip *chip)
453484
{
454485
struct crb_priv *priv = dev_get_drvdata(&chip->dev);
486+
int rc;
455487

456488
iowrite32(CRB_CANCEL_INVOKE, &priv->regs_t->ctrl_cancel);
457489

458490
if ((priv->sm == ACPI_TPM2_START_METHOD ||
459491
priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) &&
460492
crb_do_acpi_start(chip))
461493
dev_err(&chip->dev, "ACPI Start failed\n");
494+
495+
if (priv->sm == ACPI_TPM2_CRB_WITH_ARM_FFA) {
496+
rc = tpm_crb_ffa_start(CRB_FFA_START_TYPE_COMMAND, chip->locality);
497+
if (rc)
498+
dev_err(&chip->dev, "FF-A Start failed\n");
499+
}
462500
}
463501

464502
static bool crb_req_canceled(struct tpm_chip *chip, u8 status)
@@ -616,6 +654,7 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
616654
* stuff that puts the control area outside the ACPI IO region.
617655
*/
618656
if (priv->sm == ACPI_TPM2_COMMAND_BUFFER ||
657+
priv->sm == ACPI_TPM2_CRB_WITH_ARM_FFA ||
619658
priv->sm == ACPI_TPM2_MEMORY_MAPPED) {
620659
if (iores &&
621660
buf->control_address == iores->start +
@@ -737,6 +776,7 @@ static int crb_acpi_add(struct acpi_device *device)
737776
struct tpm_chip *chip;
738777
struct device *dev = &device->dev;
739778
struct tpm2_crb_smc *crb_smc;
779+
struct tpm2_crb_ffa *crb_ffa;
740780
struct tpm2_crb_pluton *crb_pluton;
741781
acpi_status status;
742782
u32 sm;
@@ -775,6 +815,27 @@ static int crb_acpi_add(struct acpi_device *device)
775815
priv->smc_func_id = crb_smc->smc_func_id;
776816
}
777817

818+
if (sm == ACPI_TPM2_CRB_WITH_ARM_FFA) {
819+
if (buf->header.length < (sizeof(*buf) + sizeof(*crb_ffa))) {
820+
dev_err(dev,
821+
FW_BUG "TPM2 ACPI table has wrong size %u for start method type %d\n",
822+
buf->header.length,
823+
ACPI_TPM2_CRB_WITH_ARM_FFA);
824+
rc = -EINVAL;
825+
goto out;
826+
}
827+
crb_ffa = ACPI_ADD_PTR(struct tpm2_crb_ffa, buf, sizeof(*buf));
828+
priv->ffa_flags = crb_ffa->flags;
829+
priv->ffa_attributes = crb_ffa->attributes;
830+
rc = tpm_crb_ffa_init();
831+
if (rc) {
832+
/* If FF-A driver is not available yet, request probe retry */
833+
if (rc == -ENOENT)
834+
rc = -EPROBE_DEFER;
835+
goto out;
836+
}
837+
}
838+
778839
if (sm == ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON) {
779840
if (buf->header.length < (sizeof(*buf) + sizeof(*crb_pluton))) {
780841
dev_err(dev,

0 commit comments

Comments
 (0)