tpm_crb: Add command and response buffer chunking support
Subsystems (2)
v5 cover tpm_crb: Add command and response buffer chunking support
The new version of TCG TPM v185 [1] supports sending data/commands in chunks for the CRB (Command Response Buffer) interface. This is in line with the initiative to support PQC algorithms.
This series implements the logic to send and receive larger TPM cmd/rsp between the linux guest and the TPM backend in chunks. Currently, the TPM CRB driver is limited by the physical size of the MMIO window. When userspace attempts to send a payload that exceeds this size, the driver rejects it.
This series introduces chunking support. The driver now checks the CRB interface capability for CRB_INTF_CAP_CRB_CHUNK. If supported by the backend, the driver will slice oversized commands into MMIO-sized chunks, signalling the backend via CRB_START_NEXT_CHUNK, and finalizing with CRB_START_INVOKE. Responses are also read back in a similar chunked manner.
If the backend does not support chunking, the driver retains its legacy behaviour and enforces the standard size limits.
This feature also requires the QEMU to interpret the data in chunks and forward it to the TPM backend and subsequently dispatch the TPM response in chunks back to the linux guest. This is implemented in [2] and already merged into the mainline.
The whole series applied on top of for-next-tpm (including prerequisite) can be found here:
https://github.com/armenon-rh/linux/tree/tpm-crb-linux
[1] https://trustedcomputinggroup.org/wp-content/uploads/PC-Client-Specific-Platform-TPM-Profile-for-TPM-2p0-v1p07_Pub.pdf
[2] https://lore.kernel.org/qemu-devel/[email protected]/
v5
--
- Split [PATCH v4 06/06] into 2. The preparation patch separates the no-chunking send() and recv() from chunking.
- Fixed block comments to respect kernel's preferred multi-line style.
- Added citations to the TCG TPM and NIST FIPS documentations. Explained the logic and newly introduced registers in brief in the git commit message.
v4
--
- Rebased on master (or for-next-tpm, both point to the same commit).
- Resolved one conflict in PATCH v3 05/06, as TPM_BUFSIZE is declared in include/linux/tpm_command.h.
v3
--
- Split patch 2, so that the code is cleaner.
- Re-order the buffer size adjustment patch.
- Rename crb_trigger_tpm to tpm_crb_start.
- Add dispatching logic in send and recv functions. Chunking is separated from no-chunking for clarity.
- Increase TPM_BUFSIZE in the common file include/linux/tpm.h following, [PATCH v9 11/11] tpm-buf: Implement managed allocations
https://lore.kernel.org/linux-integrity/[email protected]/
v2
--
- Add size checks before copying memory.
- Update TPM_BUFSIZE to 8KB.
- Commit messages updated to indicate motivation and logic of the change.
Arun Menon (7):
tpm_crb: Add register definitions of TPM CRB chunking fields
tpm_crb: Split start method into a separate header
tpm_crb: Add start_cmd parameter to tpm_crb_start wrapper
tpm: tis_i2c: Use local 4KB buffer to limit memory usage
tpm: Increase TPM_BUFSIZE to 8KB for chunking support
tpm_crb: Factor crb_send()/crb_recv() bodies into helpers
tpm_crb: Implement command and response chunking logic
drivers/char/tpm/tpm_crb.c | 226 +++++++++++++++++++++++++++------ drivers/char/tpm/tpm_tis_i2c.c | 6 +- include/linux/tpm_command.h | 2 +- 3 files changed, 189 insertions(+), 45 deletions(-)
Signature · 1 line
2.56.0
PATCH v5 1/7 tpm_crb: Add register definitions of TPM CRB chunking fields
From: Arun Menon <[email protected]>
Post-quantum cryptographic (PQC) algorithms can require buffer sizes that exceed the physical capacity of the TPM's Command/Response Buffer (CRB). To support these larger payloads, the TPM 2.0 CRB specification [1] allows for data chunking when the physical MMIO window is smaller than the required buffer size.
To support this protocol, the TPM driver must be able to detect the chunking capability, and signal the backend using specific start method flags, also known as the control area start register bits.
As per sections 6.4.2.2 and 6.5.3.9 of the specification document [1] Add 2 new bit flags to the existing enum crb_start and add the capability bit.
- CRB_INTF_CAP_CRB_CHUNK: A capability bit used to detect if the backend supports chunking.
- CRB_START_NEXT_CHUNK: A control bit to signal the TPM to consume the current command buffer, or to get the next chunk from the response buffer.
- CRB_START_RESP_RETRY: A control bit to signal retransmission of a response buffer.
--- drivers/char/tpm/tpm_crb.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/char/tpm/tpm_crb.c +6 -0
@@ -57,12 +57,18 @@ enum crb_ctrl_sts {enum crb_start {CRB_START_INVOKE =BIT (0 ), +CRB_START_RESP_RETRY =BIT (1 ), +CRB_START_NEXT_CHUNK =BIT (2 ), };enum crb_cancel {CRB_CANCEL_INVOKE =BIT (0 ), }; +enum crb_intf { +CRB_INTF_CAP_CRB_CHUNK =BIT (10 ), +}; +struct crb_regs_head {u32 loc_state;u32 reserved1;
Signature · 1 line
2.56.0
PATCH v5 2/7 tpm_crb: Split start method into a separate header
In reply to Arun MenonFrom: Arun Menon <[email protected]>
The current implementation handles different platform start methods (ACPI, ARM SMC, and ARM FFA) directly within crb_send(). Move this logic into a new helper function, tpm_crb_start(). This is a pure refactor with no functional changes intended.
--- drivers/char/tpm/tpm_crb.c | 52 +++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 23 deletions(-)
drivers/char/tpm/tpm_crb.c +29 -23
@@ -446,6 +446,34 @@ static int tpm_crb_smc_start(struct device *dev, unsigned long func_id) }#endif +static int tpm_crb_start (struct tpm_chip *chip) +{ +struct crb_priv *priv =dev_get_drvdata (&chip->dev); +int rc =0 ; + +/* +* The reason for the extra quirk is that the PTT in 4th Gen Core CPUs +* report only ACPI start but in practice seems to require both +* CRB start, hence invoking CRB start method if hid == MSFT0101. +*/ +if (priv->sm ==ACPI_TPM2_COMMAND_BUFFER || + priv->sm ==ACPI_TPM2_MEMORY_MAPPED || + !strcmp (priv->hid,"MSFT0101" )) +iowrite32 (CRB_START_INVOKE , &priv->regs_t->ctrl_start); +if (priv->sm ==ACPI_TPM2_START_METHOD || + priv->sm ==ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD ) + rc =crb_do_acpi_start (chip); +if (priv->sm ==ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC ) { +iowrite32 (CRB_START_INVOKE , &priv->regs_t->ctrl_start); + rc =tpm_crb_smc_start (&chip->dev, priv->smc_func_id); + } +if (priv->sm ==ACPI_TPM2_CRB_WITH_ARM_FFA ) { +iowrite32 (CRB_START_INVOKE , &priv->regs_t->ctrl_start); + rc =tpm_crb_ffa_start (CRB_FFA_START_TYPE_COMMAND , chip->locality); + } +return rc; +} +static int crb_send (struct tpm_chip *chip,u8 *buf,size_t bufsiz,size_t len) {struct crb_priv *priv =dev_get_drvdata (&chip->dev);
@@ -471,29 +499,7 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t bufsiz, size_t len)/* Make sure that cmd is populated before issuing start. */ wmb (); -/* The reason for the extra quirk is that the PTT in 4th Gen Core CPUs -* report only ACPI start but in practice seems to require both -* CRB start, hence invoking CRB start method if hid == MSFT0101. -*/ -if (priv->sm ==ACPI_TPM2_COMMAND_BUFFER || - priv->sm ==ACPI_TPM2_MEMORY_MAPPED || - !strcmp (priv->hid,"MSFT0101" )) -iowrite32 (CRB_START_INVOKE , &priv->regs_t->ctrl_start); - -if (priv->sm ==ACPI_TPM2_START_METHOD || - priv->sm ==ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD ) - rc =crb_do_acpi_start (chip); - -if (priv->sm ==ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC ) { -iowrite32 (CRB_START_INVOKE , &priv->regs_t->ctrl_start); - rc =tpm_crb_smc_start (&chip->dev, priv->smc_func_id); - } - -if (priv->sm ==ACPI_TPM2_CRB_WITH_ARM_FFA ) { -iowrite32 (CRB_START_INVOKE , &priv->regs_t->ctrl_start); - rc =tpm_crb_ffa_start (CRB_FFA_START_TYPE_COMMAND , chip->locality); - } - + rc =tpm_crb_start (chip);if (rc)return rc;
Signature · 1 line
2.56.0
PATCH v5 3/7 tpm_crb: Add start_cmd parameter to tpm_crb_start wrapper
In reply to Arun MenonFrom: Arun Menon <[email protected]>
The current implementation of tpm_crb_start() is limited to triggering the CRB_START_INVOKE bit. To support command and response chunking, the driver must be able to send other control bits, like CRB_START_NEXT_CHUNK, using the same platform-specific paths.
This commit adds the start_cmd parameter to tpm_crb_start() so the caller can specify which command to send.
--- drivers/char/tpm/tpm_crb.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/char/tpm/tpm_crb.c +5 -5
@@ -446,7 +446,7 @@ static int tpm_crb_smc_start(struct device *dev, unsigned long func_id) }#endif -static int tpm_crb_start (struct tpm_chip *chip) +static int tpm_crb_start (struct tpm_chip *chip,u32 start_cmd) {struct crb_priv *priv =dev_get_drvdata (&chip->dev);int rc =0 ;
@@ -459,16 +459,16 @@ static int tpm_crb_start(struct tpm_chip *chip)if (priv->sm ==ACPI_TPM2_COMMAND_BUFFER || priv->sm ==ACPI_TPM2_MEMORY_MAPPED || !strcmp (priv->hid,"MSFT0101" )) -iowrite32 (CRB_START_INVOKE , &priv->regs_t->ctrl_start); +iowrite32 (start_cmd, &priv->regs_t->ctrl_start);if (priv->sm ==ACPI_TPM2_START_METHOD || priv->sm ==ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD ) rc =crb_do_acpi_start (chip);if (priv->sm ==ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC ) { -iowrite32 (CRB_START_INVOKE , &priv->regs_t->ctrl_start); +iowrite32 (start_cmd, &priv->regs_t->ctrl_start); rc =tpm_crb_smc_start (&chip->dev, priv->smc_func_id); }if (priv->sm ==ACPI_TPM2_CRB_WITH_ARM_FFA ) { -iowrite32 (CRB_START_INVOKE , &priv->regs_t->ctrl_start); +iowrite32 (start_cmd, &priv->regs_t->ctrl_start); rc =tpm_crb_ffa_start (CRB_FFA_START_TYPE_COMMAND , chip->locality); }return rc;
@@ -499,7 +499,7 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t bufsiz, size_t len)/* Make sure that cmd is populated before issuing start. */ wmb (); - rc =tpm_crb_start (chip); + rc =tpm_crb_start (chip,CRB_START_INVOKE );if (rc)return rc;
Signature · 1 line
2.56.0
PATCH v5 4/7 tpm: tis_i2c: Use local 4KB buffer to limit memory usage
In reply to Arun MenonFrom: Arun Menon <[email protected]>
The global increase of TPM_BUFSIZE to 8KB is necessary to support Post-Quantum Cryptography (PQC) payloads. However, applying this increase to the tpm_tis_i2c driver is unnecessary and wasteful due to physical transport limitations as pointed out in [1]
This commit introduces a local buffer limit that is used in the i2c driver.
[1] https://sashiko.dev/#/patchset/20260324071803.324774-1-armenon%40redhat.com?patch=8319
--- drivers/char/tpm/tpm_tis_i2c.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/char/tpm/tpm_tis_i2c.c +4 -2
@@ -55,6 +55,8 @@#define TPM_INTF_CAPABILITY_ZERO 0x0FFFF000#define TPM_I2C_INTERFACE_CAPABILITY_ZERO 0x80000000 +#define TPM_I2C_BUFSIZE 4096 +struct tpm_tis_i2c_phy {struct tpm_tis_data priv;struct i2c_client *i2c_client;
@@ -233,7 +235,7 @@ static int tpm_tis_i2c_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len,int ret;u16 wrote =0 ; -if (len >TPM_BUFSIZE -1 ) +if (len >TPM_I2C_BUFSIZE -1 )return -EIO ; phy->io_buf[0 ] = reg;
@@ -341,7 +343,7 @@ static int tpm_tis_i2c_probe(struct i2c_client *dev)if (!phy)return -ENOMEM ; - phy->io_buf =devm_kzalloc (&dev->dev,TPM_BUFSIZE ,GFP_KERNEL ); + phy->io_buf =devm_kzalloc (&dev->dev,TPM_I2C_BUFSIZE ,GFP_KERNEL );if (!phy->io_buf)return -ENOMEM ;
Signature · 1 line
2.56.0
PATCH v5 5/7 tpm: Increase TPM_BUFSIZE to 8KB for chunking support
In reply to Arun MenonFrom: Arun Menon <[email protected]>
TPM_BUFSIZE limits the TPM2 command the kernel builds before handing it to a chip driver's send() callback. TPM 2.0 Library Part 3:
Commands v185 adds ML-DSA key objects and the ML-KEM TPM2_Encapsulate()/TPM2_Decapsulate() commands (sections 14.10, 14.11) [1]. NIST FIPS 204, Table 2, gives the largest ML-DSA parameter set, ML-DSA-87, a 4896-byte private key and a 2592-byte public key [2].
Loading such a key pair with TPM2_Load, plus header, handle and session, comes to roughly 7.7KB - more than the current 4096-byte TPM_BUFSIZE.
Raise TPM_BUFSIZE to 8192 bytes. It covers this command with headroom, and keeps every kzalloc(TPM_BUFSIZE, ...) call in the TPM stack at an order-1 page allocation rather than a higher order.
This matches the largest parameter set defined today. NIST has already published PQC families with larger keys and signatures than ML-DSA (e.g. FIPS 205/SLH-DSA), so a future algorithm could exceed 8192 bytes. CRB chunking, added later in this series, does not change that; it only lets an already-built command cross a smaller MMIO window in pieces, it does not change how large a command the generic stack can build.
[1] https://medias.cdn.trustedcomputinggroup.org/production/Trusted_Platform_Module_2_0_Library_Part_3_Commands_Version_185_pub_87a5c10230.pdf
[2] https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.204.pdf
--- include/linux/tpm_command.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/linux/tpm_command.h +1 -1
@@ -434,7 +434,7 @@ struct tpm2_context {*/ #define TPM_DIGEST_SIZE 20/* Max TPM v1.2 PCR size */ -#define TPM_BUFSIZE 4096 +#define TPM_BUFSIZE 8192/* * SHA-512 is, as of today, the largest digest in the TCG algorithm repository.
Signature · 1 line
2.56.0
Re: [PATCH v5 5/7] tpm: Increase TPM_BUFSIZE to 8KB for chunking support
Quoted 47 lines · Arun Menon
From: Arun Menon <[email protected]>
TPM_BUFSIZElimits the TPM2 command the kernel builds before handing it to a chip driver'ssend()callback. TPM 2.0 Library Part 3:
Commands v185 adds ML-DSA key objects and the ML-KEM TPM2_Encapsulate()/TPM2_Decapsulate() commands (sections 14.10, 14.11) [1]. NIST FIPS 204, Table 2, gives the largest ML-DSA parameter set, ML-DSA-87, a 4896-byte private key and a 2592-byte public key [2].
Loading such a key pair withTPM2_Load, plus header, handle and session, comes to roughly 7.7KB - more than the current 4096-byteTPM_BUFSIZE.Raise
TPM_BUFSIZEto 8192 bytes. It covers this command with headroom, and keeps everykzalloc(TPM_BUFSIZE, ...)call in the TPM stack at an order-1 page allocation rather than a higher order.This matches the largest parameter set defined today. NIST has already published PQC families with larger keys and signatures than ML-DSA (e.g. FIPS 205/SLH-DSA), so a future algorithm could exceed 8192 bytes. CRB chunking, added later in this series, does not change that; it only lets an already-built command cross a smaller MMIO window in pieces, it does not change how large a command the generic stack can build.
[1] https://medias.cdn.trustedcomputinggroup.org/production/Trusted_Platform_Module_2_0_Library_Part_3_Commands_Version_185_pub_87a5c10230.pdf
[2] https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.204.pdfSigned-off-by Arun Menon <[email protected]>--- include/linux/tpm_command.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)include/linux/tpm_command.h +1
-1@@ -434,7 +434,7 @@ struct tpm2_context {*/ #define TPM_DIGEST_SIZE 20/* Max TPM v1.2 PCR size */ -#define TPM_BUFSIZE 4096 +#define TPM_BUFSIZE 8192/* * SHA-512 is, as of today, the largest digest in the TCG algorithm repository. Signature · 1 line
2.56.0
Br, Jarkko
PATCH v5 6/7 tpm_crb: Factor crb_send()/crb_recv() bodies into helpers
In reply to Arun MenonFrom: Arun Menon <[email protected]>
A later patch adds CRB chunking, which needs its own send/receive loops alongside the existing single-shot transfer. Move the body of crb_send() into tpm_crb_send_no_chunks() and the body of crb_recv() into tpm_crb_recv_no_chunks().
Pure code motion, no behavior change. Also fix the block comment to the kernel's preferred multi-line style.
--- drivers/char/tpm/tpm_crb.c | 71 ++++++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 26 deletions(-)
drivers/char/tpm/tpm_crb.c +45 -26
@@ -369,24 +369,13 @@ static u8 crb_status(struct tpm_chip *chip)return sts; } -static int crb_recv (struct tpm_chip *chip,u8 *buf,size_t count) +static int tpm_crb_recv_no_chunks (struct tpm_chip *chip,u8 *buf,size_t count) {struct crb_priv *priv =dev_get_drvdata (&chip->dev);unsigned int expected; -/* A sanity check that the upper layer wants to get at least the header -* as that is the minimum size for any TPM response. -*/ -if (count <TPM_HEADER_SIZE ) -return -EIO ; - -/* If this bit is set, according to the spec, the TPM is in -* unrecoverable condition. -*/ -if (ioread32 (&priv->regs_t->ctrl_sts) &CRB_CTRL_STS_ERROR ) -return -EIO ; - -/* Read the first 8 bytes in order to get the length of the response. +/* +* Read the first 8 bytes in order to get the length of the response. * We read exactly a quad word in order to make sure that the remaining * reads will be aligned. */
@@ -399,6 +388,28 @@ static int crb_recv(struct tpm_chip *chip, u8 *buf, size_t count)memcpy_fromio (&buf[8 ], &priv->rsp[8 ], expected -8 );return expected; + +} + +static int crb_recv (struct tpm_chip *chip,u8 *buf,size_t count) +{ +struct crb_priv *priv =dev_get_drvdata (&chip->dev); + +/* +* A sanity check that the upper layer wants to get at least the header +* as that is the minimum size for any TPM response. +*/ +if (count <TPM_HEADER_SIZE ) +return -EIO ; + +/* +* If this bit is set, according to the spec, the TPM is in +* unrecoverable condition. +*/ +if (ioread32 (&priv->regs_t->ctrl_sts) &CRB_CTRL_STS_ERROR ) +return -EIO ; + +return tpm_crb_recv_no_chunks (chip, buf, count); }static int crb_do_acpi_start (struct tpm_chip *chip)
@@ -474,12 +485,29 @@ static int tpm_crb_start(struct tpm_chip *chip, u32 start_cmd)return rc; } -static int crb_send (struct tpm_chip *chip,u8 *buf,size_t bufsiz,size_t len) +static int tpm_crb_send_no_chunks (struct tpm_chip *chip,u8 *buf,size_t len) {struct crb_priv *priv =dev_get_drvdata (&chip->dev);int rc =0 ; -/* Zero the cancel register so that the next command will not get +memcpy_toio (priv->cmd, buf, len); + +/* Make sure that cmd is populated before issuing start. */ +wmb (); + + rc =tpm_crb_start (chip,CRB_START_INVOKE ); +if (rc) +return rc; + +return crb_try_pluton_doorbell (priv, false); +} + +static int crb_send (struct tpm_chip *chip,u8 *buf,size_t bufsiz,size_t len) +{ +struct crb_priv *priv =dev_get_drvdata (&chip->dev); + +/* +* Zero the cancel register so that the next command will not get * canceled. */ iowrite32 (0 , &priv->regs_t->ctrl_cancel);
@@ -494,16 +522,7 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t bufsiz, size_t len)if (priv->sm ==ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON )__crb_cmd_ready (&chip->dev, priv, chip->locality); -memcpy_toio (priv->cmd, buf, len); - -/* Make sure that cmd is populated before issuing start. */ -wmb (); - - rc =tpm_crb_start (chip,CRB_START_INVOKE ); -if (rc) -return rc; - -return crb_try_pluton_doorbell (priv, false); +return tpm_crb_send_no_chunks (chip, buf, len); }static void crb_cancel (struct tpm_chip *chip)
Signature · 1 line
2.56.0
Re: [PATCH v5 6/7] tpm_crb: Factor crb_send()/crb_recv() bodies into helpers
Quoted 129 lines · Arun Menon
From: Arun Menon <[email protected]>
A later patch adds CRB chunking, which needs its own send/receive loops alongside the existing single-shot transfer. Move the body of
crb_send()intotpm_crb_send_no_chunks()and the body ofcrb_recv()intotpm_crb_recv_no_chunks().Pure code motion, no behavior change. Also fix the block comment to the kernel's preferred multi-line style.
Signed-off-by Arun Menon <[email protected]>--- drivers/char/tpm/tpm_crb.c | 71 ++++++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 26 deletions(-)drivers/char/tpm/tpm_crb.c +45
-26@@ -369,24 +369,13 @@ static u8 crb_status(struct tpm_chip *chip)return sts; } -static int crb_recv (struct tpm_chip *chip,u8 *buf,size_t count) +static int tpm_crb_recv_no_chunks (struct tpm_chip *chip,u8 *buf,size_t count) {struct crb_priv *priv =dev_get_drvdata (&chip->dev);unsigned int expected; -/* A sanity check that the upper layer wants to get at least the header -* as that is the minimum size for any TPM response. -*/ -if (count <TPM_HEADER_SIZE ) -return -EIO ; - -/* If this bit is set, according to the spec, the TPM is in -* unrecoverable condition. -*/ -if (ioread32 (&priv->regs_t->ctrl_sts) &CRB_CTRL_STS_ERROR ) -return -EIO ; - -/* Read the first 8 bytes in order to get the length of the response. +/* +* Read the first 8 bytes in order to get the length of the response. * We read exactly a quad word in order to make sure that the remaining * reads will be aligned. */ @@ -399,6 +388,28 @@ static int crb_recv(struct tpm_chip *chip, u8 *buf, size_t count)memcpy_fromio (&buf[8 ], &priv->rsp[8 ], expected -8 );return expected; + +} + +static int crb_recv (struct tpm_chip *chip,u8 *buf,size_t count) +{ +struct crb_priv *priv =dev_get_drvdata (&chip->dev); + +/* +* A sanity check that the upper layer wants to get at least the header +* as that is the minimum size for any TPM response. +*/ +if (count <TPM_HEADER_SIZE ) +return -EIO ; + +/* +* If this bit is set, according to the spec, the TPM is in +* unrecoverable condition. +*/ +if (ioread32 (&priv->regs_t->ctrl_sts) &CRB_CTRL_STS_ERROR ) +return -EIO ; + +return tpm_crb_recv_no_chunks (chip, buf, count); }static int crb_do_acpi_start (struct tpm_chip *chip)@@ -474,12 +485,29 @@ static int tpm_crb_start(struct tpm_chip *chip, u32 start_cmd)return rc; } -static int crb_send (struct tpm_chip *chip,u8 *buf,size_t bufsiz,size_t len) +static int tpm_crb_send_no_chunks (struct tpm_chip *chip,u8 *buf,size_t len) {struct crb_priv *priv =dev_get_drvdata (&chip->dev);int rc =0 ; -/* Zero the cancel register so that the next command will not get +memcpy_toio (priv->cmd, buf, len); + +/* Make sure that cmd is populated before issuing start. */ +wmb (); + + rc =tpm_crb_start (chip,CRB_START_INVOKE ); +if (rc) +return rc; + +return crb_try_pluton_doorbell (priv, false); +} + +static int crb_send (struct tpm_chip *chip,u8 *buf,size_t bufsiz,size_t len) +{ +struct crb_priv *priv =dev_get_drvdata (&chip->dev); + +/* +* Zero the cancel register so that the next command will not get * canceled. */ iowrite32 (0 , &priv->regs_t->ctrl_cancel);@@ -494,16 +522,7 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t bufsiz, size_t len)if (priv->sm ==ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON )__crb_cmd_ready (&chip->dev, priv, chip->locality); -memcpy_toio (priv->cmd, buf, len); - -/* Make sure that cmd is populated before issuing start. */ -wmb (); - - rc =tpm_crb_start (chip,CRB_START_INVOKE ); -if (rc) -return rc; - -return crb_try_pluton_doorbell (priv, false); +return tpm_crb_send_no_chunks (chip, buf, len); }static void crb_cancel (struct tpm_chip *chip)Signature · 1 line
2.56.0
Br, Jarkko
PATCH v5 7/7 tpm_crb: Implement command and response chunking logic
In reply to Arun MenonFrom: Arun Menon <[email protected]>
TPMs implemented with the CRB address map in the TCG PC-Client Platform TPM Profile (PTP) for TPM 2.0 are limited to a 3968-byte command/response buffer (v1.07, March 2026, Table 36 and section 6.5.3.9) in [2]. This is smaller than the 7.7KB ML-DSA-87 TPM2_Load from the previous patch. PTP 1.07 adds a chunking mode for exactly this case (sections 6.4.2.2, 6.5.3.9, 6.5.3.10 in [2]), usable by any CRB TPM that implements it.
Send and receive the command/response split into pieces no larger than priv->cmd_size/priv->rsp_size. Write CRB_START_NEXT_CHUNK to ctrl_start after each piece but the last, and wait for the TPM to clear it before sending the next; use CRB_START_INVOKE on the last piece, same as the non-chunked path. Read a response back the same way, in reverse.
On top of the previous patch's tpm_crb_send_no_chunks()/ tpm_crb_recv_no_chunks() split, add:
- rsp_size: response-direction counterpart of cmd_size.
- intf_id: interface ID register, read once at probe time.
- CRB_INTF_CAP_CRB_CHUNK: capability bit in intf_id; crb_send()/ crb_recv() only reject an oversized payload when it is clear.
- tpm_crb_send_chunks()/tpm_crb_recv_chunks(): drive the chunked transfer described above.
This corresponds to the backend implementation in QEMU [1], which reassembles the chunks before handing the command to the TPM emulator.
[1] https://lore.kernel.org/qemu-devel/[email protected]/
[2] https://medias.cdn.trustedcomputinggroup.org/production/PC_Client_Specific_Platform_TPM_Profile_for_TPM_2p0_v1p07_Pub_5643562943.pdf
--- drivers/char/tpm/tpm_crb.c | 119 +++++++++++++++++++++++++++++++++++-- 1 file changed, 115 insertions(+), 4 deletions(-)
drivers/char/tpm/tpm_crb.c +115 -4
@@ -105,11 +105,13 @@ struct crb_priv {u8 __iomem *cmd;u8 __iomem *rsp;u32 cmd_size; +u32 rsp_size;u32 smc_func_id;u32 __iomem *pluton_start_addr;u32 __iomem *pluton_reply_addr;u8 ffa_flags;u8 ffa_attributes; +u32 intf_id; };struct tpm2_crb_smc {
@@ -369,6 +371,13 @@ static u8 crb_status(struct tpm_chip *chip)return sts; } +/* +* tpm_crb_recv_chunks() below needs to drive CRB_START_NEXT_CHUNK through +* tpm_crb_start(), which is defined later in this file next to the other +* platform-specific start methods it dispatches to. +*/ +static int tpm_crb_start (struct tpm_chip *chip,u32 start_cmd); +static int tpm_crb_recv_no_chunks (struct tpm_chip *chip,u8 *buf,size_t count) {struct crb_priv *priv =dev_get_drvdata (&chip->dev);
@@ -388,12 +397,54 @@ static int tpm_crb_recv_no_chunks(struct tpm_chip *chip, u8 *buf, size_t count)memcpy_fromio (&buf[8 ], &priv->rsp[8 ], expected -8 );return expected; +} + +static int tpm_crb_recv_chunks (struct tpm_chip *chip,u8 *buf,size_t count, +unsigned int expected) +{ +struct crb_priv *priv =dev_get_drvdata (&chip->dev); +size_t offset =0 ; +size_t chunk_size; +bool expired; +int rc; + +if (expected > count || expected <TPM_HEADER_SIZE ) +return -EIO ; +/* +* Without this, a bogus zero-sized MMIO window would never make +* forward progress below. +*/ +if (priv->rsp_size ==0 ) +return -EIO ; + +while (offset < expected) { + chunk_size =min_t (size_t, expected - offset, priv->rsp_size); +memcpy_fromio (buf + offset, priv->rsp, chunk_size); + offset += chunk_size; +if (offset == expected) +break ; + + rc =tpm_crb_start (chip,CRB_START_NEXT_CHUNK ); +if (rc) +return rc; + + expired = !crb_wait_for_reg_32 (&priv->regs_t->ctrl_start, +CRB_START_NEXT_CHUNK ,0 , +TPM2_TIMEOUT_C ); +if (expired) { +dev_err (&chip->dev, +"Timeout waiting for backend response\n" ); +return -ETIME ; + } + } +return expected; }static int crb_recv (struct tpm_chip *chip,u8 *buf,size_t count) {struct crb_priv *priv =dev_get_drvdata (&chip->dev); +unsigned int expected;/* * A sanity check that the upper layer wants to get at least the header
@@ -409,7 +460,17 @@ static int crb_recv(struct tpm_chip *chip, u8 *buf, size_t count)if (ioread32 (&priv->regs_t->ctrl_sts) &CRB_CTRL_STS_ERROR )return -EIO ; -return tpm_crb_recv_no_chunks (chip, buf, count); +/* Peek at the first 8 bytes to determine the response size */ + expected =be32_to_cpup ((__be32 *)&priv->rsp[2 ]); + +if (expected <= priv->rsp_size) +return tpm_crb_recv_no_chunks (chip, buf, count); +if (!(priv->intf_id &CRB_INTF_CAP_CRB_CHUNK )) { +dev_err (&chip->dev, +"Response larger than MMIO and chunking not supported\n" ); +return -EIO ; + } +return tpm_crb_recv_chunks (chip, buf, count, expected); }static int crb_do_acpi_start (struct tpm_chip *chip)
@@ -502,6 +563,46 @@ static int tpm_crb_send_no_chunks(struct tpm_chip *chip, u8 *buf, size_t len)return crb_try_pluton_doorbell (priv, false); } +static int tpm_crb_send_chunks (struct tpm_chip *chip,u8 *buf,size_t len) +{ +struct crb_priv *priv =dev_get_drvdata (&chip->dev); +size_t chunk_size; +size_t offset =0 ; +int rc; +bool expired; + +while (offset < len) { + chunk_size =min_t (size_t, len - offset, priv->cmd_size); +if (chunk_size ==0 ) +break ; + +memcpy_toio (priv->cmd, buf + offset, chunk_size); + offset += chunk_size; + +/* Make sure that cmd is populated before issuing start. */ +wmb (); + +if (offset < len) { + rc =tpm_crb_start (chip,CRB_START_NEXT_CHUNK ); +if (rc) +return rc; + expired = !crb_wait_for_reg_32 (&priv->regs_t->ctrl_start, +CRB_START_NEXT_CHUNK ,0 , +TPM2_TIMEOUT_C ); +if (expired) { +dev_err (&chip->dev, +"Timeout waiting for backend to consume chunk\n" ); +return -ETIME ; + } + }else { + rc =tpm_crb_start (chip,CRB_START_INVOKE ); +if (rc) +return rc; + } + } +return crb_try_pluton_doorbell (priv, false); +} +static int crb_send (struct tpm_chip *chip,u8 *buf,size_t bufsiz,size_t len) {struct crb_priv *priv =dev_get_drvdata (&chip->dev);
@@ -512,7 +613,7 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t bufsiz, size_t len)*/ iowrite32 (0 , &priv->regs_t->ctrl_cancel); -if (len > priv->cmd_size) { +if (len > priv->cmd_size && !(priv->intf_id &CRB_INTF_CAP_CRB_CHUNK )) {dev_err (&chip->dev,"invalid command count value %zd %d\n" , len, priv->cmd_size);return -E2BIG ;
@@ -522,7 +623,10 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t bufsiz, size_t len)if (priv->sm ==ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON )__crb_cmd_ready (&chip->dev, priv, chip->locality); -return tpm_crb_send_no_chunks (chip, buf, len); +if (len <= priv->cmd_size) +return tpm_crb_send_no_chunks (chip, buf, len); + +return tpm_crb_send_chunks (chip, buf, len); }static void crb_cancel (struct tpm_chip *chip)
@@ -748,6 +852,11 @@ static int crb_map_io(struct device *dev, struct crb_priv *priv, ret =PTR_ERR (priv->cmd); goto out; } +if (priv->regs_h) + priv->intf_id =ioread32 ((u32 __iomem *)&priv->regs_h->intf_id); + +if (priv->intf_id &CRB_INTF_CAP_CRB_CHUNK ) +dev_info (dev,"CRB Chunking is supported by backend\n" );memcpy_fromio (&__rsp_pa, &priv->regs_t->ctrl_rsp_pa,8 ); rsp_pa =le64_to_cpu (__rsp_pa);
@@ -786,8 +895,10 @@ static int crb_map_io(struct device *dev, struct crb_priv *priv, priv->rsp = priv->cmd; out: -if (!ret) +if (!ret) { priv->cmd_size = cmd_size; + priv->rsp_size = rsp_size; + }__crb_go_idle (dev, priv,0 );
Signature · 1 line
2.56.0
Re: [PATCH v5 7/7] tpm_crb: Implement command and response chunking logic
Quoted 237 lines · Arun Menon
From: Arun Menon <[email protected]>
TPMs implemented with the CRB address map in the TCG PC-Client Platform TPM Profile (PTP) for TPM 2.0 are limited to a 3968-byte command/response buffer (v1.07, March 2026, Table 36 and section 6.5.3.9) in [2]. This is smaller than the 7.7KB ML-DSA-87
TPM2_Loadfrom the previous patch. PTP 1.07 adds a chunking mode for exactly this case (sections 6.4.2.2, 6.5.3.9, 6.5.3.10 in [2]), usable by any CRB TPM that implements it.Send and receive the command/response split into pieces no larger than priv->cmd_size/priv->rsp_size. Write
CRB_START_NEXT_CHUNKtoctrl_startafter each piece but the last, and wait for the TPM to clear it before sending the next; useCRB_START_INVOKEon the last piece, same as the non-chunked path. Read a response back the same way, in reverse.On top of the previous patch's tpm_crb_send_no_chunks()/
tpm_crb_recv_no_chunks()split, add:
-rsp_size: response-direction counterpart ofcmd_size.
-intf_id: interface ID register, read once at probe time.
-CRB_INTF_CAP_CRB_CHUNK: capability bit inintf_id; crb_send()/crb_recv()only reject an oversized payload when it is clear.
- tpm_crb_send_chunks()/tpm_crb_recv_chunks(): drive the chunked transfer described above.This corresponds to the backend implementation in QEMU [1], which reassembles the chunks before handing the command to the TPM emulator.
[1] https://lore.kernel.org/qemu-devel/[email protected]/
[2] https://medias.cdn.trustedcomputinggroup.org/production/PC_Client_Specific_Platform_TPM_Profile_for_TPM_2p0_v1p07_Pub_5643562943.pdfSigned-off-by Arun Menon <[email protected]>--- drivers/char/tpm/tpm_crb.c | 119 +++++++++++++++++++++++++++++++++++-- 1 file changed, 115 insertions(+), 4 deletions(-)drivers/char/tpm/tpm_crb.c +115
-4@@ -105,11 +105,13 @@ struct crb_priv {u8 __iomem *cmd;u8 __iomem *rsp;u32 cmd_size; +u32 rsp_size;u32 smc_func_id;u32 __iomem *pluton_start_addr;u32 __iomem *pluton_reply_addr;u8 ffa_flags;u8 ffa_attributes; +u32 intf_id; };struct tpm2_crb_smc {@@ -369,6 +371,13 @@ static u8 crb_status(struct tpm_chip *chip)return sts; } +/* +* tpm_crb_recv_chunks() below needs to drive CRB_START_NEXT_CHUNK through +* tpm_crb_start(), which is defined later in this file next to the other +* platform-specific start methods it dispatches to. +*/ +static int tpm_crb_start (struct tpm_chip *chip,u32 start_cmd); +static int tpm_crb_recv_no_chunks (struct tpm_chip *chip,u8 *buf,size_t count) {struct crb_priv *priv =dev_get_drvdata (&chip->dev);@@ -388,12 +397,54 @@ static int tpm_crb_recv_no_chunks(struct tpm_chip *chip, u8 *buf, size_t count)memcpy_fromio (&buf[8 ], &priv->rsp[8 ], expected -8 );return expected; +} + +static int tpm_crb_recv_chunks (struct tpm_chip *chip,u8 *buf,size_t count, +unsigned int expected) +{ +struct crb_priv *priv =dev_get_drvdata (&chip->dev); +size_t offset =0 ; +size_t chunk_size; +bool expired; +int rc; + +if (expected > count || expected <TPM_HEADER_SIZE ) +return -EIO ; +/* +* Without this, a bogus zero-sized MMIO window would never make +* forward progress below. +*/ +if (priv->rsp_size ==0 ) +return -EIO ; + +while (offset < expected) { + chunk_size =min_t (size_t, expected - offset, priv->rsp_size); +memcpy_fromio (buf + offset, priv->rsp, chunk_size); + offset += chunk_size; +if (offset == expected) +break ; + + rc =tpm_crb_start (chip,CRB_START_NEXT_CHUNK ); +if (rc) +return rc; + + expired = !crb_wait_for_reg_32 (&priv->regs_t->ctrl_start, +CRB_START_NEXT_CHUNK ,0 , +TPM2_TIMEOUT_C ); +if (expired) { +dev_err (&chip->dev, +"Timeout waiting for backend response\n" ); +return -ETIME ; + } + } +return expected; }static int crb_recv (struct tpm_chip *chip,u8 *buf,size_t count) {struct crb_priv *priv =dev_get_drvdata (&chip->dev); +unsigned int expected;/* * A sanity check that the upper layer wants to get at least the header @@ -409,7 +460,17 @@ static int crb_recv(struct tpm_chip *chip, u8 *buf, size_t count)if (ioread32 (&priv->regs_t->ctrl_sts) &CRB_CTRL_STS_ERROR )return -EIO ; -return tpm_crb_recv_no_chunks (chip, buf, count); +/* Peek at the first 8 bytes to determine the response size */ + expected =be32_to_cpup ((__be32 *)&priv->rsp[2 ]); + +if (expected <= priv->rsp_size) +return tpm_crb_recv_no_chunks (chip, buf, count); +if (!(priv->intf_id &CRB_INTF_CAP_CRB_CHUNK )) { +dev_err (&chip->dev, +"Response larger than MMIO and chunking not supported\n" ); +return -EIO ; + } +return tpm_crb_recv_chunks (chip, buf, count, expected); }static int crb_do_acpi_start (struct tpm_chip *chip)@@ -502,6 +563,46 @@ static int tpm_crb_send_no_chunks(struct tpm_chip *chip, u8 *buf, size_t len)return crb_try_pluton_doorbell (priv, false); } +static int tpm_crb_send_chunks (struct tpm_chip *chip,u8 *buf,size_t len) +{ +struct crb_priv *priv =dev_get_drvdata (&chip->dev); +size_t chunk_size; +size_t offset =0 ; +int rc; +bool expired; + +while (offset < len) { + chunk_size =min_t (size_t, len - offset, priv->cmd_size); +if (chunk_size ==0 ) +break ; + +memcpy_toio (priv->cmd, buf + offset, chunk_size); + offset += chunk_size; + +/* Make sure that cmd is populated before issuing start. */ +wmb (); + +if (offset < len) { + rc =tpm_crb_start (chip,CRB_START_NEXT_CHUNK ); +if (rc) +return rc; + expired = !crb_wait_for_reg_32 (&priv->regs_t->ctrl_start, +CRB_START_NEXT_CHUNK ,0 , +TPM2_TIMEOUT_C ); +if (expired) { +dev_err (&chip->dev, +"Timeout waiting for backend to consume chunk\n" ); +return -ETIME ; + } + }else { + rc =tpm_crb_start (chip,CRB_START_INVOKE ); +if (rc) +return rc; + } + } +return crb_try_pluton_doorbell (priv, false); +} +static int crb_send (struct tpm_chip *chip,u8 *buf,size_t bufsiz,size_t len) {struct crb_priv *priv =dev_get_drvdata (&chip->dev);@@ -512,7 +613,7 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t bufsiz, size_t len)*/ iowrite32 (0 , &priv->regs_t->ctrl_cancel); -if (len > priv->cmd_size) { +if (len > priv->cmd_size && !(priv->intf_id &CRB_INTF_CAP_CRB_CHUNK )) {dev_err (&chip->dev,"invalid command count value %zd %d\n" , len, priv->cmd_size);return -E2BIG ;@@ -522,7 +623,10 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t bufsiz, size_t len)if (priv->sm ==ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON )__crb_cmd_ready (&chip->dev, priv, chip->locality); -return tpm_crb_send_no_chunks (chip, buf, len); +if (len <= priv->cmd_size) +return tpm_crb_send_no_chunks (chip, buf, len); + +return tpm_crb_send_chunks (chip, buf, len); }static void crb_cancel (struct tpm_chip *chip)@@ -748,6 +852,11 @@ static int crb_map_io(struct device *dev, struct crb_priv *priv, ret =PTR_ERR (priv->cmd); goto out; } +if (priv->regs_h) + priv->intf_id =ioread32 ((u32 __iomem *)&priv->regs_h->intf_id); + +if (priv->intf_id &CRB_INTF_CAP_CRB_CHUNK ) +dev_info (dev,"CRB Chunking is supported by backend\n" );memcpy_fromio (&__rsp_pa, &priv->regs_t->ctrl_rsp_pa,8 ); rsp_pa =le64_to_cpu (__rsp_pa);@@ -786,8 +895,10 @@ static int crb_map_io(struct device *dev, struct crb_priv *priv, priv->rsp = priv->cmd; out: -if (!ret) +if (!ret) { priv->cmd_size = cmd_size; + priv->rsp_size = rsp_size; + }__crb_go_idle (dev, priv,0 );Signature · 1 line
2.56.0
Br, Jarkko
Quoted 73 lines · Arun Menon
The new version of TCG TPM v185 [1] supports sending data/commands in chunks for the CRB (Command Response Buffer) interface. This is in line with the initiative to support PQC algorithms.
This series implements the logic to send and receive larger TPM cmd/rsp between the linux guest and the TPM backend in chunks. Currently, the TPM CRB driver is limited by the physical size of the MMIO window. When userspace attempts to send a payload that exceeds this size, the driver rejects it.
This series introduces chunking support. The driver now checks the CRB interface capability for
CRB_INTF_CAP_CRB_CHUNK. If supported by the backend, the driver will slice oversized commands into MMIO-sized chunks, signalling the backend viaCRB_START_NEXT_CHUNK, and finalizing withCRB_START_INVOKE. Responses are also read back in a similar chunked manner.If the backend does not support chunking, the driver retains its legacy behaviour and enforces the standard size limits.
This feature also requires the QEMU to interpret the data in chunks and forward it to the TPM backend and subsequently dispatch the TPM response in chunks back to the linux guest. This is implemented in [2] and already merged into the mainline.
The whole series applied on top of for-next-tpm (including prerequisite) can be found here:
https://github.com/armenon-rh/linux/tree/tpm-crb-linux[1] https://trustedcomputinggroup.org/wp-content/uploads/PC-Client-Specific-Platform-TPM-Profile-for-TPM-2p0-v1p07_Pub.pdf
[2] https://lore.kernel.org/qemu-devel/[email protected]/v5
--
- Split [PATCH v4 06/06] into 2. The preparation patch separates the no-chunkingsend()andrecv()from chunking.
- Fixed block comments to respect kernel's preferred multi-line style.
- Added citations to the TCG TPM and NIST FIPS documentations. Explained the logic and newly introduced registers in brief in the git commit message.v4
--
- Rebased on master (or for-next-tpm, both point to the same commit).
- Resolved one conflict in PATCH v3 05/06, asTPM_BUFSIZEis declared ininclude/linux/tpm_command.h.v3
--
- Split patch 2, so that the code is cleaner.
- Re-order the buffer size adjustment patch.
- Renamecrb_trigger_tpmtotpm_crb_start.
- Add dispatching logic in send and recv functions. Chunking is separated from no-chunking for clarity.
- IncreaseTPM_BUFSIZEin the common fileinclude/linux/tpm.hfollowing, [PATCH v9 11/11] tpm-buf: Implement managed allocations
https://lore.kernel.org/linux-integrity/[email protected]/v2
--
- Add size checks before copying memory.
- UpdateTPM_BUFSIZEto 8KB.
- Commit messages updated to indicate motivation and logic of the change.Arun Menon (7):
tpm_crb: Add register definitions of TPM CRB chunking fields
tpm_crb: Split start method into a separate header
tpm_crb: Addstart_cmdparameter totpm_crb_startwrapper
tpm:tis_i2c: Use local 4KB buffer to limit memory usage
tpm: IncreaseTPM_BUFSIZEto 8KB for chunking support
tpm_crb: Factor crb_send()/crb_recv() bodies into helpers
tpm_crb: Implement command and response chunking logic
Quoted 8 lines
drivers/char/tpm/tpm_crb.c | 226 +++++++++++++++++++++++++++------ drivers/char/tpm/tpm_tis_i2c.c | 6 +- include/linux/tpm_command.h | 2 +- 3 files changed, 189 insertions(+), 45 deletions(-)Signature · 1 line
2.56.0
Applied, thank you.
Br, Jarkko
Jarkko Sakkinen
maintainerQuoted 79 lines · Jarkko Sakkinen
Quoted 78 lines · Arun Menon
The new version of TCG TPM v185 [1] supports sending data/commands in chunks for the CRB (Command Response Buffer) interface. This is in line with the initiative to support PQC algorithms.
This series implements the logic to send and receive larger TPM cmd/rsp between the linux guest and the TPM backend in chunks. Currently, the TPM CRB driver is limited by the physical size of the MMIO window. When userspace attempts to send a payload that exceeds this size, the driver rejects it.
This series introduces chunking support. The driver now checks the CRB interface capability for
CRB_INTF_CAP_CRB_CHUNK. If supported by the backend, the driver will slice oversized commands into MMIO-sized chunks, signalling the backend viaCRB_START_NEXT_CHUNK, and finalizing withCRB_START_INVOKE. Responses are also read back in a similar chunked manner.If the backend does not support chunking, the driver retains its legacy behaviour and enforces the standard size limits.
This feature also requires the QEMU to interpret the data in chunks and forward it to the TPM backend and subsequently dispatch the TPM response in chunks back to the linux guest. This is implemented in [2] and already merged into the mainline.
The whole series applied on top of for-next-tpm (including prerequisite) can be found here:
https://github.com/armenon-rh/linux/tree/tpm-crb-linux[1] https://trustedcomputinggroup.org/wp-content/uploads/PC-Client-Specific-Platform-TPM-Profile-for-TPM-2p0-v1p07_Pub.pdf
[2] https://lore.kernel.org/qemu-devel/[email protected]/v5
--
- Split [PATCH v4 06/06] into 2. The preparation patch separates the no-chunkingsend()andrecv()from chunking.
- Fixed block comments to respect kernel's preferred multi-line style.
- Added citations to the TCG TPM and NIST FIPS documentations. Explained the logic and newly introduced registers in brief in the git commit message.v4
--
- Rebased on master (or for-next-tpm, both point to the same commit).
- Resolved one conflict in PATCH v3 05/06, asTPM_BUFSIZEis declared ininclude/linux/tpm_command.h.v3
--
- Split patch 2, so that the code is cleaner.
- Re-order the buffer size adjustment patch.
- Renamecrb_trigger_tpmtotpm_crb_start.
- Add dispatching logic in send and recv functions. Chunking is separated from no-chunking for clarity.
- IncreaseTPM_BUFSIZEin the common fileinclude/linux/tpm.hfollowing, [PATCH v9 11/11] tpm-buf: Implement managed allocations
https://lore.kernel.org/linux-integrity/[email protected]/v2
--
- Add size checks before copying memory.
- UpdateTPM_BUFSIZEto 8KB.
- Commit messages updated to indicate motivation and logic of the change.Arun Menon (7):
tpm_crb: Add register definitions of TPM CRB chunking fields
tpm_crb: Split start method into a separate header
tpm_crb: Addstart_cmdparameter totpm_crb_startwrapper
tpm:tis_i2c: Use local 4KB buffer to limit memory usage
tpm: IncreaseTPM_BUFSIZEto 8KB for chunking support
tpm_crb: Factor crb_send()/crb_recv() bodies into helpers
tpm_crb: Implement command and response chunking logicdrivers/char/tpm/tpm_crb.c | 226 +++++++++++++++++++++++++++------ drivers/char/tpm/tpm_tis_i2c.c | 6 +- include/linux/tpm_command.h | 2 +- 3 files changed, 189 insertions(+), 45 deletions(-)
Quoted 5 lines
Quoted 3 lines
Signature · 1 line
2.56.0Applied, thank you.
Could you send +1 version that:
1. Applies to my master.
2. There was one issue that kernel test bot complained.
The issue:
Quoted 1 line
Quoted 1 line
drivers/char/tpm/tpm_crb.c:464:34: sparse: sparse: cast removes address space '__iomem' of expression
No worries, just every other day stuff but would help me if you carry out these, thanks. And yeah, the first one is not even a real issue, just unfortuate coincident :-)
I'll apply it as soon as I get it.
Br, Jarkko