Commit c584af1926b7626ef3bdab3354382cb2bd434d36
Committed by
Kent Yoder
1 parent
07b133e606
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
TPM: Issue TPM_STARTUP at driver load if the TPM has not been started
The TPM will respond to TPM_GET_CAP with TPM_ERR_INVALID_POSTINIT if TPM_STARTUP has not been issued. Detect this and automatically issue TPM_STARTUP. This is for embedded applications where the kernel is the first thing to touch the TPM. Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Tested-by: Peter Huewe <peter.huewe@infineon.com> Reviewed-by: Peter Huewe <peter.huewe@infineon.com> Signed-off-by: Kent Yoder <key@linux.vnet.ibm.com>
Showing 2 changed files with 46 additions and 4 deletions Side-by-side Diff
drivers/char/tpm/tpm.c
... | ... | @@ -451,7 +451,7 @@ |
451 | 451 | return -EFAULT; |
452 | 452 | |
453 | 453 | err = be32_to_cpu(cmd->header.out.return_code); |
454 | - if (err != 0) | |
454 | + if (err != 0 && desc) | |
455 | 455 | dev_err(chip->dev, "A TPM error (%d) occurred %s\n", err, desc); |
456 | 456 | |
457 | 457 | return err; |
... | ... | @@ -511,6 +511,25 @@ |
511 | 511 | } |
512 | 512 | EXPORT_SYMBOL_GPL(tpm_gen_interrupt); |
513 | 513 | |
514 | +#define TPM_ORD_STARTUP cpu_to_be32(153) | |
515 | +#define TPM_ST_CLEAR cpu_to_be16(1) | |
516 | +#define TPM_ST_STATE cpu_to_be16(2) | |
517 | +#define TPM_ST_DEACTIVATED cpu_to_be16(3) | |
518 | +static const struct tpm_input_header tpm_startup_header = { | |
519 | + .tag = TPM_TAG_RQU_COMMAND, | |
520 | + .length = cpu_to_be32(12), | |
521 | + .ordinal = TPM_ORD_STARTUP | |
522 | +}; | |
523 | + | |
524 | +static int tpm_startup(struct tpm_chip *chip, __be16 startup_type) | |
525 | +{ | |
526 | + struct tpm_cmd_t start_cmd; | |
527 | + start_cmd.header.in = tpm_startup_header; | |
528 | + start_cmd.params.startup_in.startup_type = startup_type; | |
529 | + return transmit_cmd(chip, &start_cmd, TPM_INTERNAL_RESULT_SIZE, | |
530 | + "attempting to start the TPM"); | |
531 | +} | |
532 | + | |
514 | 533 | int tpm_get_timeouts(struct tpm_chip *chip) |
515 | 534 | { |
516 | 535 | struct tpm_cmd_t tpm_cmd; |
517 | 536 | |
518 | 537 | |
... | ... | @@ -524,11 +543,28 @@ |
524 | 543 | tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; |
525 | 544 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); |
526 | 545 | tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; |
546 | + rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, NULL); | |
527 | 547 | |
528 | - rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, | |
529 | - "attempting to determine the timeouts"); | |
530 | - if (rc) | |
548 | + if (rc == TPM_ERR_INVALID_POSTINIT) { | |
549 | + /* The TPM is not started, we are the first to talk to it. | |
550 | + Execute a startup command. */ | |
551 | + dev_info(chip->dev, "Issuing TPM_STARTUP"); | |
552 | + if (tpm_startup(chip, TPM_ST_CLEAR)) | |
553 | + return rc; | |
554 | + | |
555 | + tpm_cmd.header.in = tpm_getcap_header; | |
556 | + tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; | |
557 | + tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); | |
558 | + tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; | |
559 | + rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, | |
560 | + NULL); | |
561 | + } | |
562 | + if (rc) { | |
563 | + dev_err(chip->dev, | |
564 | + "A TPM error (%zd) occurred attempting to determine the timeouts\n", | |
565 | + rc); | |
531 | 566 | goto duration; |
567 | + } | |
532 | 568 | |
533 | 569 | if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || |
534 | 570 | be32_to_cpu(tpm_cmd.header.out.length) |
drivers/char/tpm/tpm.h
... | ... | @@ -47,6 +47,7 @@ |
47 | 47 | #define TPM_WARN_DOING_SELFTEST 0x802 |
48 | 48 | #define TPM_ERR_DEACTIVATED 0x6 |
49 | 49 | #define TPM_ERR_DISABLED 0x7 |
50 | +#define TPM_ERR_INVALID_POSTINIT 38 | |
50 | 51 | |
51 | 52 | #define TPM_HEADER_SIZE 10 |
52 | 53 | extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr, |
... | ... | @@ -291,6 +292,10 @@ |
291 | 292 | __be32 num_bytes; |
292 | 293 | }__attribute__((packed)); |
293 | 294 | |
295 | +struct tpm_startup_in { | |
296 | + __be16 startup_type; | |
297 | +} __packed; | |
298 | + | |
294 | 299 | typedef union { |
295 | 300 | struct tpm_getcap_params_out getcap_out; |
296 | 301 | struct tpm_readpubek_params_out readpubek_out; |
... | ... | @@ -301,6 +306,7 @@ |
301 | 306 | struct tpm_pcrextend_in pcrextend_in; |
302 | 307 | struct tpm_getrandom_in getrandom_in; |
303 | 308 | struct tpm_getrandom_out getrandom_out; |
309 | + struct tpm_startup_in startup_in; | |
304 | 310 | } tpm_cmd_params; |
305 | 311 | |
306 | 312 | struct tpm_cmd_t { |