|
@@ -540,6 +540,47 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space,
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(tpm_transmit_cmd);
|
|
|
|
|
|
+#define TPM_ORD_STARTUP 153
|
|
|
+#define TPM_ST_CLEAR 1
|
|
|
+
|
|
|
+/**
|
|
|
+ * tpm_startup - turn on the TPM
|
|
|
+ * @chip: TPM chip to use
|
|
|
+ *
|
|
|
+ * Normally the firmware should start the TPM. This function is provided as a
|
|
|
+ * workaround if this does not happen. A legal case for this could be for
|
|
|
+ * example when a TPM emulator is used.
|
|
|
+ *
|
|
|
+ * Return: same as tpm_transmit_cmd()
|
|
|
+ */
|
|
|
+int tpm_startup(struct tpm_chip *chip)
|
|
|
+{
|
|
|
+ struct tpm_buf buf;
|
|
|
+ int rc;
|
|
|
+
|
|
|
+ dev_info(&chip->dev, "starting up the TPM manually\n");
|
|
|
+
|
|
|
+ if (chip->flags & TPM_CHIP_FLAG_TPM2) {
|
|
|
+ rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_STARTUP);
|
|
|
+ if (rc < 0)
|
|
|
+ return rc;
|
|
|
+
|
|
|
+ tpm_buf_append_u16(&buf, TPM2_SU_CLEAR);
|
|
|
+ } else {
|
|
|
+ rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_STARTUP);
|
|
|
+ if (rc < 0)
|
|
|
+ return rc;
|
|
|
+
|
|
|
+ tpm_buf_append_u16(&buf, TPM_ST_CLEAR);
|
|
|
+ }
|
|
|
+
|
|
|
+ rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0,
|
|
|
+ "attempting to start the TPM");
|
|
|
+
|
|
|
+ tpm_buf_destroy(&buf);
|
|
|
+ return rc;
|
|
|
+}
|
|
|
+
|
|
|
#define TPM_DIGEST_SIZE 20
|
|
|
#define TPM_RET_CODE_IDX 6
|
|
|
#define TPM_INTERNAL_RESULT_SIZE 200
|
|
@@ -586,27 +627,6 @@ ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(tpm_getcap);
|
|
|
|
|
|
-#define TPM_ORD_STARTUP 153
|
|
|
-#define TPM_ST_CLEAR cpu_to_be16(1)
|
|
|
-#define TPM_ST_STATE cpu_to_be16(2)
|
|
|
-#define TPM_ST_DEACTIVATED cpu_to_be16(3)
|
|
|
-static const struct tpm_input_header tpm_startup_header = {
|
|
|
- .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
|
|
|
- .length = cpu_to_be32(12),
|
|
|
- .ordinal = cpu_to_be32(TPM_ORD_STARTUP)
|
|
|
-};
|
|
|
-
|
|
|
-static int tpm_startup(struct tpm_chip *chip, __be16 startup_type)
|
|
|
-{
|
|
|
- struct tpm_cmd_t start_cmd;
|
|
|
- start_cmd.header.in = tpm_startup_header;
|
|
|
-
|
|
|
- start_cmd.params.startup_in.startup_type = startup_type;
|
|
|
- return tpm_transmit_cmd(chip, NULL, &start_cmd,
|
|
|
- TPM_INTERNAL_RESULT_SIZE, 0,
|
|
|
- 0, "attempting to start the TPM");
|
|
|
-}
|
|
|
-
|
|
|
int tpm_get_timeouts(struct tpm_chip *chip)
|
|
|
{
|
|
|
cap_t cap;
|
|
@@ -636,10 +656,7 @@ int tpm_get_timeouts(struct tpm_chip *chip)
|
|
|
rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, NULL,
|
|
|
sizeof(cap.timeout));
|
|
|
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\n");
|
|
|
- if (tpm_startup(chip, TPM_ST_CLEAR))
|
|
|
+ if (tpm_startup(chip))
|
|
|
return rc;
|
|
|
|
|
|
rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap,
|