int last_stage_init(void) { #ifndef CONFIG_SPL_BUILD ccdc_eth_init(); #endif if (tpm_init() || tpm_startup(TPM_ST_CLEAR) || tpm_continue_self_test()) { return 1; } mdelay(37); flush_keys(); load_and_run_keyprog(); return 0; }
static int do_tpm_startup(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { enum tpm_startup_type mode; if (argc != 2) return CMD_RET_USAGE; if (!strcasecmp("TPM_ST_CLEAR", argv[1])) { mode = TPM_ST_CLEAR; } else if (!strcasecmp("TPM_ST_STATE", argv[1])) { mode = TPM_ST_STATE; } else if (!strcasecmp("TPM_ST_DEACTIVATED", argv[1])) { mode = TPM_ST_DEACTIVATED; } else { printf("Couldn't recognize mode string: %s\n", argv[1]); return CMD_RET_FAILURE; } return convert_return_code(tpm_startup(mode)); }
int tpm_get_timeouts(struct tpm_chip *chip) { struct tpm_cmd_t tpm_cmd; unsigned long new_timeout[4]; unsigned long old_timeout[4]; struct duration_t *duration_cap; ssize_t rc; if (chip->flags & TPM_CHIP_FLAG_TPM2) { /* Fixed timeouts for TPM2 */ chip->timeout_a = msecs_to_jiffies(TPM2_TIMEOUT_A); chip->timeout_b = msecs_to_jiffies(TPM2_TIMEOUT_B); chip->timeout_c = msecs_to_jiffies(TPM2_TIMEOUT_C); chip->timeout_d = msecs_to_jiffies(TPM2_TIMEOUT_D); chip->duration[TPM_SHORT] = msecs_to_jiffies(TPM2_DURATION_SHORT); chip->duration[TPM_MEDIUM] = msecs_to_jiffies(TPM2_DURATION_MEDIUM); chip->duration[TPM_LONG] = msecs_to_jiffies(TPM2_DURATION_LONG); return 0; } tpm_cmd.header.in = tpm_getcap_header; tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, 0, NULL); if (rc == TPM_ERR_INVALID_POSTINIT) { /* The TPM is not started, we are the first to talk to it. Execute a startup command. */ dev_info(&chip->dev, "Issuing TPM_STARTUP"); if (tpm_startup(chip, TPM_ST_CLEAR)) return rc; tpm_cmd.header.in = tpm_getcap_header; tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, 0, NULL); } if (rc) { dev_err(&chip->dev, "A TPM error (%zd) occurred attempting to determine the timeouts\n", rc); goto duration; } if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || be32_to_cpu(tpm_cmd.header.out.length) != sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32)) return -EINVAL; old_timeout[0] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.a); old_timeout[1] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.b); old_timeout[2] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.c); old_timeout[3] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.d); memcpy(new_timeout, old_timeout, sizeof(new_timeout)); /* * Provide ability for vendor overrides of timeout values in case * of misreporting. */ if (chip->ops->update_timeouts != NULL) chip->timeout_adjusted = chip->ops->update_timeouts(chip, new_timeout); if (!chip->timeout_adjusted) { /* Don't overwrite default if value is 0 */ if (new_timeout[0] != 0 && new_timeout[0] < 1000) { int i; /* timeouts in msec rather usec */ for (i = 0; i != ARRAY_SIZE(new_timeout); i++) new_timeout[i] *= 1000; chip->timeout_adjusted = true; } } /* Report adjusted timeouts */ if (chip->timeout_adjusted) { dev_info(&chip->dev, HW_ERR "Adjusting reported timeouts: A %lu->%luus B %lu->%luus C %lu->%luus D %lu->%luus\n", old_timeout[0], new_timeout[0], old_timeout[1], new_timeout[1], old_timeout[2], new_timeout[2], old_timeout[3], new_timeout[3]); } chip->timeout_a = usecs_to_jiffies(new_timeout[0]); chip->timeout_b = usecs_to_jiffies(new_timeout[1]); chip->timeout_c = usecs_to_jiffies(new_timeout[2]); chip->timeout_d = usecs_to_jiffies(new_timeout[3]); duration: tpm_cmd.header.in = tpm_getcap_header; tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_DURATION; rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, 0, "attempting to determine the durations"); if (rc) return rc; if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || be32_to_cpu(tpm_cmd.header.out.length) != sizeof(tpm_cmd.header.out) + sizeof(u32) + 3 * sizeof(u32)) return -EINVAL; duration_cap = &tpm_cmd.params.getcap_out.cap.duration; chip->duration[TPM_SHORT] = usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_short)); chip->duration[TPM_MEDIUM] = usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_medium)); chip->duration[TPM_LONG] = usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_long)); /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above * value wrong and apparently reports msecs rather than usecs. So we * fix up the resulting too-small TPM_SHORT value to make things work. * We also scale the TPM_MEDIUM and -_LONG values by 1000. */ if (chip->duration[TPM_SHORT] < (HZ / 100)) { chip->duration[TPM_SHORT] = HZ; chip->duration[TPM_MEDIUM] *= 1000; chip->duration[TPM_LONG] *= 1000; chip->duration_adjusted = true; dev_info(&chip->dev, "Adjusting TPM timeout parameters."); } return 0; }
u32 tpm_resume(struct udevice *dev) { return tpm_startup(dev, TPM_ST_STATE); }