Loading drivers/char/tpm/tpm-interface.c +126 −32 Original line number Diff line number Diff line Loading @@ -369,20 +369,40 @@ static int tpm_validate_command(struct tpm_chip *chip, return -EINVAL; } /** * tmp_transmit - Internal kernel interface to transmit TPM commands. * * @chip: TPM chip to use * @buf: TPM command buffer * @bufsiz: length of the TPM command buffer * @flags: tpm transmit flags - bitmap * * Return: * 0 when the operation is successful. * A negative number for system errors (errno). */ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, u8 *buf, size_t bufsiz, unsigned int flags) static int tpm_request_locality(struct tpm_chip *chip) { int rc; if (!chip->ops->request_locality) return 0; rc = chip->ops->request_locality(chip, 0); if (rc < 0) return rc; chip->locality = rc; return 0; } static void tpm_relinquish_locality(struct tpm_chip *chip) { int rc; if (!chip->ops->relinquish_locality) return; rc = chip->ops->relinquish_locality(chip, chip->locality); if (rc) dev_err(&chip->dev, "%s: : error %d\n", __func__, rc); chip->locality = -1; } static ssize_t tpm_try_transmit(struct tpm_chip *chip, struct tpm_space *space, u8 *buf, size_t bufsiz, unsigned int flags) { struct tpm_output_header *header = (void *)buf; int rc; Loading Loading @@ -422,8 +442,6 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, if (!(flags & TPM_TRANSMIT_UNLOCKED)) mutex_lock(&chip->tpm_mutex); if (chip->dev.parent) pm_runtime_get_sync(chip->dev.parent); if (chip->ops->clk_enable != NULL) chip->ops->clk_enable(chip, true); Loading @@ -431,19 +449,20 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, /* Store the decision as chip->locality will be changed. */ need_locality = chip->locality == -1; if (!(flags & TPM_TRANSMIT_RAW) && need_locality && chip->ops->request_locality) { rc = chip->ops->request_locality(chip, 0); if (!(flags & TPM_TRANSMIT_RAW) && need_locality) { rc = tpm_request_locality(chip); if (rc < 0) goto out_no_locality; chip->locality = rc; } if (chip->dev.parent) pm_runtime_get_sync(chip->dev.parent); rc = tpm2_prepare_space(chip, space, ordinal, buf); if (rc) goto out; rc = chip->ops->send(chip, (u8 *) buf, count); rc = chip->ops->send(chip, buf, count); if (rc < 0) { if (rc != -EPIPE) dev_err(&chip->dev, Loading Loading @@ -480,7 +499,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, goto out; out_recv: len = chip->ops->recv(chip, (u8 *) buf, bufsiz); len = chip->ops->recv(chip, buf, bufsiz); if (len < 0) { rc = len; dev_err(&chip->dev, Loading @@ -499,27 +518,95 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, rc = tpm2_commit_space(chip, space, ordinal, buf, &len); out: if (need_locality && chip->ops->relinquish_locality) { chip->ops->relinquish_locality(chip, chip->locality); chip->locality = -1; } if (chip->dev.parent) pm_runtime_put_sync(chip->dev.parent); if (need_locality) tpm_relinquish_locality(chip); out_no_locality: if (chip->ops->clk_enable != NULL) chip->ops->clk_enable(chip, false); if (chip->dev.parent) pm_runtime_put_sync(chip->dev.parent); if (!(flags & TPM_TRANSMIT_UNLOCKED)) mutex_unlock(&chip->tpm_mutex); return rc ? rc : len; } /** * tmp_transmit_cmd - send a tpm command to the device * tpm_transmit - Internal kernel interface to transmit TPM commands. * * @chip: TPM chip to use * @space: tpm space * @buf: TPM command buffer * @bufsiz: length of the TPM command buffer * @flags: tpm transmit flags - bitmap * * A wrapper around tpm_try_transmit that handles TPM2_RC_RETRY * returns from the TPM and retransmits the command after a delay up * to a maximum wait of TPM2_DURATION_LONG. * * Note: TPM1 never returns TPM2_RC_RETRY so the retry logic is TPM2 * only * * Return: * the length of the return when the operation is successful. * A negative number for system errors (errno). */ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, u8 *buf, size_t bufsiz, unsigned int flags) { struct tpm_output_header *header = (struct tpm_output_header *)buf; /* space for header and handles */ u8 save[TPM_HEADER_SIZE + 3*sizeof(u32)]; unsigned int delay_msec = TPM2_DURATION_SHORT; u32 rc = 0; ssize_t ret; const size_t save_size = min(space ? sizeof(save) : TPM_HEADER_SIZE, bufsiz); /* the command code is where the return code will be */ u32 cc = be32_to_cpu(header->return_code); /* * Subtlety here: if we have a space, the handles will be * transformed, so when we restore the header we also have to * restore the handles. */ memcpy(save, buf, save_size); for (;;) { ret = tpm_try_transmit(chip, space, buf, bufsiz, flags); if (ret < 0) break; rc = be32_to_cpu(header->return_code); if (rc != TPM2_RC_RETRY && rc != TPM2_RC_TESTING) break; /* * return immediately if self test returns test * still running to shorten boot time. */ if (rc == TPM2_RC_TESTING && cc == TPM2_CC_SELF_TEST) break; delay_msec *= 2; if (delay_msec > TPM2_DURATION_LONG) { if (rc == TPM2_RC_RETRY) dev_err(&chip->dev, "in retry loop\n"); else dev_err(&chip->dev, "self test is still running\n"); break; } tpm_msleep(delay_msec); memcpy(buf, save, save_size); } return ret; } /** * tpm_transmit_cmd - send a tpm command to the device * The function extracts tpm out header return code * * @chip: TPM chip to use * @space: tpm space * @buf: TPM command buffer * @bufsiz: length of the buffer * @min_rsp_body_length: minimum expected length of response body Loading @@ -532,7 +619,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, * A positive number for a TPM error. */ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space, const void *buf, size_t bufsiz, void *buf, size_t bufsiz, size_t min_rsp_body_length, unsigned int flags, const char *desc) { Loading @@ -540,7 +627,7 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space, int err; ssize_t len; len = tpm_transmit(chip, space, (u8 *)buf, bufsiz, flags); len = tpm_transmit(chip, space, buf, bufsiz, flags); if (len < 0) return len; Loading Loading @@ -666,6 +753,8 @@ int tpm_get_timeouts(struct tpm_chip *chip) msecs_to_jiffies(TPM2_DURATION_MEDIUM); chip->duration[TPM_LONG] = msecs_to_jiffies(TPM2_DURATION_LONG); chip->duration[TPM_LONG_LONG] = msecs_to_jiffies(TPM2_DURATION_LONG_LONG); chip->flags |= TPM_CHIP_FLAG_HAVE_TIMEOUTS; return 0; Loading Loading @@ -754,6 +843,7 @@ int tpm_get_timeouts(struct tpm_chip *chip) usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_medium)); chip->duration[TPM_LONG] = usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_long)); chip->duration[TPM_LONG_LONG] = 0; /* not used under 1.2 */ /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above * value wrong and apparently reports msecs rather than usecs. So we Loading Loading @@ -969,6 +1059,10 @@ int tpm_do_selftest(struct tpm_chip *chip) loops = jiffies_to_msecs(duration) / delay_msec; rc = tpm_continue_selftest(chip); if (rc == TPM_ERR_INVALID_POSTINIT) { chip->flags |= TPM_CHIP_FLAG_ALWAYS_POWERED; dev_info(&chip->dev, "TPM not ready (%d)\n", rc); } /* This may fail if there was no TPM driver during a suspend/resume * cycle; some may return 10 (BAD_ORDINAL), others 28 (FAILEDSELFTEST) */ Loading drivers/char/tpm/tpm.h +21 −11 Original line number Diff line number Diff line Loading @@ -67,7 +67,9 @@ enum tpm_duration { TPM_SHORT = 0, TPM_MEDIUM = 1, TPM_LONG = 2, TPM_LONG_LONG = 3, TPM_UNDEFINED, TPM_NUM_DURATIONS = TPM_UNDEFINED, }; #define TPM_WARN_RETRY 0x800 Loading @@ -81,6 +83,9 @@ enum tpm_duration { enum tpm2_const { TPM2_PLATFORM_PCR = 24, TPM2_PCR_SELECT_MIN = ((TPM2_PLATFORM_PCR + 7) / 8), }; enum tpm2_timeouts { TPM2_TIMEOUT_A = 750, TPM2_TIMEOUT_B = 2000, TPM2_TIMEOUT_C = 200, Loading @@ -88,6 +93,8 @@ enum tpm2_const { TPM2_DURATION_SHORT = 20, TPM2_DURATION_MEDIUM = 750, TPM2_DURATION_LONG = 2000, TPM2_DURATION_LONG_LONG = 300000, TPM2_DURATION_DEFAULT = 120000, }; enum tpm2_structures { Loading @@ -104,10 +111,12 @@ enum tpm2_return_codes { TPM2_RC_HASH = 0x0083, /* RC_FMT1 */ TPM2_RC_HANDLE = 0x008B, TPM2_RC_INITIALIZE = 0x0100, /* RC_VER1 */ TPM2_RC_FAILURE = 0x0101, TPM2_RC_DISABLED = 0x0120, TPM2_RC_COMMAND_CODE = 0x0143, TPM2_RC_TESTING = 0x090A, /* RC_WARN */ TPM2_RC_REFERENCE_H0 = 0x0910, TPM2_RC_RETRY = 0x0922, }; enum tpm2_algorithms { Loading @@ -123,6 +132,7 @@ enum tpm2_algorithms { enum tpm2_command_codes { TPM2_CC_FIRST = 0x011F, TPM2_CC_CREATE_PRIMARY = 0x0131, TPM2_CC_SELF_TEST = 0x0143, TPM2_CC_STARTUP = 0x0144, TPM2_CC_SHUTDOWN = 0x0145, Loading Loading @@ -227,7 +237,7 @@ struct tpm_chip { unsigned long timeout_c; /* jiffies */ unsigned long timeout_d; /* jiffies */ bool timeout_adjusted; unsigned long duration[3]; /* jiffies */ unsigned long duration[TPM_NUM_DURATIONS]; /* jiffies */ bool duration_adjusted; struct dentry *bios_dir[TPM_NUM_EVENT_LOG_FILES]; Loading Loading @@ -506,7 +516,7 @@ enum tpm_transmit_flags { ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, u8 *buf, size_t bufsiz, unsigned int flags); ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space, const void *buf, size_t bufsiz, void *buf, size_t bufsiz, size_t min_rsp_body_length, unsigned int flags, const char *desc); int tpm_startup(struct tpm_chip *chip); Loading drivers/char/tpm/tpm2-cmd.c +21 −41 Original line number Diff line number Diff line Loading @@ -31,10 +31,6 @@ struct tpm2_startup_in { __be16 startup_type; } __packed; struct tpm2_self_test_in { u8 full_test; } __packed; struct tpm2_get_tpm_pt_in { __be32 cap_id; __be32 property_id; Loading @@ -60,7 +56,6 @@ struct tpm2_get_random_out { union tpm2_cmd_params { struct tpm2_startup_in startup_in; struct tpm2_self_test_in selftest_in; struct tpm2_get_tpm_pt_in get_tpm_pt_in; struct tpm2_get_tpm_pt_out get_tpm_pt_out; struct tpm2_get_random_in getrandom_in; Loading Loading @@ -90,6 +85,8 @@ static struct tpm2_hash tpm2_hash_map[] = { * of time the chip could take to return the result. The values * of the SHORT, MEDIUM, and LONG durations are taken from the * PC Client Profile (PTP) specification. * LONG_LONG is for commands that generates keys which empirically * takes longer time on some systems. */ static const u8 tpm2_ordinal_duration[TPM2_CC_LAST - TPM2_CC_FIRST + 1] = { TPM_UNDEFINED, /* 11F */ Loading @@ -110,7 +107,7 @@ static const u8 tpm2_ordinal_duration[TPM2_CC_LAST - TPM2_CC_FIRST + 1] = { TPM_UNDEFINED, /* 12e */ TPM_UNDEFINED, /* 12f */ TPM_UNDEFINED, /* 130 */ TPM_UNDEFINED, /* 131 */ TPM_LONG_LONG, /* 131 */ TPM_UNDEFINED, /* 132 */ TPM_UNDEFINED, /* 133 */ TPM_UNDEFINED, /* 134 */ Loading Loading @@ -144,7 +141,7 @@ static const u8 tpm2_ordinal_duration[TPM2_CC_LAST - TPM2_CC_FIRST + 1] = { TPM_UNDEFINED, /* 150 */ TPM_UNDEFINED, /* 151 */ TPM_UNDEFINED, /* 152 */ TPM_UNDEFINED, /* 153 */ TPM_LONG_LONG, /* 153 */ TPM_UNDEFINED, /* 154 */ TPM_UNDEFINED, /* 155 */ TPM_UNDEFINED, /* 156 */ Loading Loading @@ -821,22 +818,12 @@ unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal) duration = chip->duration[index]; if (duration <= 0) duration = 2 * 60 * HZ; duration = msecs_to_jiffies(TPM2_DURATION_DEFAULT); return duration; } EXPORT_SYMBOL_GPL(tpm2_calc_ordinal_duration); #define TPM2_SELF_TEST_IN_SIZE \ (sizeof(struct tpm_input_header) + \ sizeof(struct tpm2_self_test_in)) static const struct tpm_input_header tpm2_selftest_header = { .tag = cpu_to_be16(TPM2_ST_NO_SESSIONS), .length = cpu_to_be32(TPM2_SELF_TEST_IN_SIZE), .ordinal = cpu_to_be32(TPM2_CC_SELF_TEST) }; /** * tpm2_do_selftest() - ensure that all self tests have passed * Loading @@ -852,27 +839,24 @@ static const struct tpm_input_header tpm2_selftest_header = { */ static int tpm2_do_selftest(struct tpm_chip *chip) { struct tpm_buf buf; int full; int rc; unsigned int delay_msec = 10; long duration; struct tpm2_cmd cmd; duration = jiffies_to_msecs( tpm2_calc_ordinal_duration(chip, TPM2_CC_SELF_TEST)); while (1) { cmd.header.in = tpm2_selftest_header; cmd.params.selftest_in.full_test = 0; rc = tpm_transmit_cmd(chip, NULL, &cmd, TPM2_SELF_TEST_IN_SIZE, 0, 0, "continue selftest"); for (full = 0; full < 2; full++) { rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_SELF_TEST); if (rc) return rc; if (rc != TPM2_RC_TESTING || delay_msec >= duration) break; tpm_buf_append_u8(&buf, full); rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, "attempting the self test"); tpm_buf_destroy(&buf); /* wait longer than before */ delay_msec *= 2; tpm_msleep(delay_msec); if (rc == TPM2_RC_TESTING) rc = TPM2_RC_SUCCESS; if (rc == TPM2_RC_INITIALIZE || rc == TPM2_RC_SUCCESS) return rc; } return rc; Loading Loading @@ -1058,10 +1042,8 @@ int tpm2_auto_startup(struct tpm_chip *chip) goto out; rc = tpm2_do_selftest(chip); if (rc != 0 && rc != TPM2_RC_INITIALIZE) { dev_err(&chip->dev, "TPM self test failed\n"); if (rc && rc != TPM2_RC_INITIALIZE) goto out; } if (rc == TPM2_RC_INITIALIZE) { rc = tpm_startup(chip); Loading @@ -1069,11 +1051,9 @@ int tpm2_auto_startup(struct tpm_chip *chip) goto out; rc = tpm2_do_selftest(chip); if (rc) { dev_err(&chip->dev, "TPM self test failed\n"); if (rc) goto out; } } rc = tpm2_get_pcr_allocation(chip); if (rc) Loading drivers/char/tpm/tpm_crb.c +78 −35 Original line number Diff line number Diff line Loading @@ -112,6 +112,25 @@ struct tpm2_crb_smc { u32 smc_func_id; }; static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value, unsigned long timeout) { ktime_t start; ktime_t stop; start = ktime_get(); stop = ktime_add(start, ms_to_ktime(timeout)); do { if ((ioread32(reg) & mask) == value) return true; usleep_range(50, 100); } while (ktime_before(ktime_get(), stop)); return ((ioread32(reg) & mask) == value); } /** * crb_go_idle - request tpm crb device to go the idle state * Loading @@ -128,7 +147,7 @@ struct tpm2_crb_smc { * * Return: 0 always */ static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv) static int crb_go_idle(struct device *dev, struct crb_priv *priv) { if ((priv->sm == ACPI_TPM2_START_METHOD) || (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) || Loading @@ -136,28 +155,15 @@ static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv) return 0; iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req); /* we don't really care when this settles */ return 0; if (!crb_wait_for_reg_32(&priv->regs_t->ctrl_req, CRB_CTRL_REQ_GO_IDLE/* mask */, 0, /* value */ TPM2_TIMEOUT_C)) { dev_warn(dev, "goIdle timed out\n"); return -ETIME; } static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value, unsigned long timeout) { ktime_t start; ktime_t stop; start = ktime_get(); stop = ktime_add(start, ms_to_ktime(timeout)); do { if ((ioread32(reg) & mask) == value) return true; usleep_range(50, 100); } while (ktime_before(ktime_get(), stop)); return false; return 0; } /** Loading @@ -175,8 +181,7 @@ static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value, * * Return: 0 on success -ETIME on timeout; */ static int __maybe_unused crb_cmd_ready(struct device *dev, struct crb_priv *priv) static int crb_cmd_ready(struct device *dev, struct crb_priv *priv) { if ((priv->sm == ACPI_TPM2_START_METHOD) || (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) || Loading @@ -195,9 +200,9 @@ static int __maybe_unused crb_cmd_ready(struct device *dev, return 0; } static int crb_request_locality(struct tpm_chip *chip, int loc) static int __crb_request_locality(struct device *dev, struct crb_priv *priv, int loc) { struct crb_priv *priv = dev_get_drvdata(&chip->dev); u32 value = CRB_LOC_STATE_LOC_ASSIGNED | CRB_LOC_STATE_TPM_REG_VALID_STS; Loading @@ -207,21 +212,45 @@ static int crb_request_locality(struct tpm_chip *chip, int loc) iowrite32(CRB_LOC_CTRL_REQUEST_ACCESS, &priv->regs_h->loc_ctrl); if (!crb_wait_for_reg_32(&priv->regs_h->loc_state, value, value, TPM2_TIMEOUT_C)) { dev_warn(&chip->dev, "TPM_LOC_STATE_x.requestAccess timed out\n"); dev_warn(dev, "TPM_LOC_STATE_x.requestAccess timed out\n"); return -ETIME; } return 0; } static void crb_relinquish_locality(struct tpm_chip *chip, int loc) static int crb_request_locality(struct tpm_chip *chip, int loc) { struct crb_priv *priv = dev_get_drvdata(&chip->dev); return __crb_request_locality(&chip->dev, priv, loc); } static int __crb_relinquish_locality(struct device *dev, struct crb_priv *priv, int loc) { u32 mask = CRB_LOC_STATE_LOC_ASSIGNED | CRB_LOC_STATE_TPM_REG_VALID_STS; u32 value = CRB_LOC_STATE_TPM_REG_VALID_STS; if (!priv->regs_h) return; return 0; iowrite32(CRB_LOC_CTRL_RELINQUISH, &priv->regs_h->loc_ctrl); if (!crb_wait_for_reg_32(&priv->regs_h->loc_state, mask, value, TPM2_TIMEOUT_C)) { dev_warn(dev, "TPM_LOC_STATE_x.requestAccess timed out\n"); return -ETIME; } return 0; } static int crb_relinquish_locality(struct tpm_chip *chip, int loc) { struct crb_priv *priv = dev_get_drvdata(&chip->dev); return __crb_relinquish_locality(&chip->dev, priv, loc); } static u8 crb_status(struct tpm_chip *chip) Loading Loading @@ -442,6 +471,7 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, u32 pa_high, pa_low; u64 cmd_pa; u32 cmd_size; __le64 __rsp_pa; u64 rsp_pa; u32 rsp_size; int ret; Loading Loading @@ -475,6 +505,10 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, dev_warn(dev, FW_BUG "Bad ACPI memory layout"); } ret = __crb_request_locality(dev, priv, 0); if (ret) return ret; priv->regs_t = crb_map_res(dev, priv, &io_res, buf->control_address, sizeof(struct crb_regs_tail)); if (IS_ERR(priv->regs_t)) Loading Loading @@ -503,8 +537,8 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, goto out; } memcpy_fromio(&rsp_pa, &priv->regs_t->ctrl_rsp_pa, 8); rsp_pa = le64_to_cpu(rsp_pa); memcpy_fromio(&__rsp_pa, &priv->regs_t->ctrl_rsp_pa, 8); rsp_pa = le64_to_cpu(__rsp_pa); rsp_size = crb_fixup_cmd_size(dev, &io_res, rsp_pa, ioread32(&priv->regs_t->ctrl_rsp_size)); Loading @@ -531,6 +565,8 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, crb_go_idle(dev, priv); __crb_relinquish_locality(dev, priv, 0); return ret; } Loading Loading @@ -588,10 +624,14 @@ static int crb_acpi_add(struct acpi_device *device) chip->acpi_dev_handle = device->handle; chip->flags = TPM_CHIP_FLAG_TPM2; rc = crb_cmd_ready(dev, priv); rc = __crb_request_locality(dev, priv, 0); if (rc) return rc; rc = crb_cmd_ready(dev, priv); if (rc) goto out; pm_runtime_get_noresume(dev); pm_runtime_set_active(dev); pm_runtime_enable(dev); Loading @@ -601,12 +641,15 @@ static int crb_acpi_add(struct acpi_device *device) crb_go_idle(dev, priv); pm_runtime_put_noidle(dev); pm_runtime_disable(dev); return rc; goto out; } pm_runtime_put(dev); pm_runtime_put_sync(dev); return 0; out: __crb_relinquish_locality(dev, priv, 0); return rc; } static int crb_acpi_remove(struct acpi_device *device) Loading drivers/char/tpm/tpm_tis_core.c +3 −1 Original line number Diff line number Diff line Loading @@ -143,11 +143,13 @@ static bool check_locality(struct tpm_chip *chip, int l) return false; } static void release_locality(struct tpm_chip *chip, int l) static int release_locality(struct tpm_chip *chip, int l) { struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY); return 0; } static int request_locality(struct tpm_chip *chip, int l) Loading Loading
drivers/char/tpm/tpm-interface.c +126 −32 Original line number Diff line number Diff line Loading @@ -369,20 +369,40 @@ static int tpm_validate_command(struct tpm_chip *chip, return -EINVAL; } /** * tmp_transmit - Internal kernel interface to transmit TPM commands. * * @chip: TPM chip to use * @buf: TPM command buffer * @bufsiz: length of the TPM command buffer * @flags: tpm transmit flags - bitmap * * Return: * 0 when the operation is successful. * A negative number for system errors (errno). */ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, u8 *buf, size_t bufsiz, unsigned int flags) static int tpm_request_locality(struct tpm_chip *chip) { int rc; if (!chip->ops->request_locality) return 0; rc = chip->ops->request_locality(chip, 0); if (rc < 0) return rc; chip->locality = rc; return 0; } static void tpm_relinquish_locality(struct tpm_chip *chip) { int rc; if (!chip->ops->relinquish_locality) return; rc = chip->ops->relinquish_locality(chip, chip->locality); if (rc) dev_err(&chip->dev, "%s: : error %d\n", __func__, rc); chip->locality = -1; } static ssize_t tpm_try_transmit(struct tpm_chip *chip, struct tpm_space *space, u8 *buf, size_t bufsiz, unsigned int flags) { struct tpm_output_header *header = (void *)buf; int rc; Loading Loading @@ -422,8 +442,6 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, if (!(flags & TPM_TRANSMIT_UNLOCKED)) mutex_lock(&chip->tpm_mutex); if (chip->dev.parent) pm_runtime_get_sync(chip->dev.parent); if (chip->ops->clk_enable != NULL) chip->ops->clk_enable(chip, true); Loading @@ -431,19 +449,20 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, /* Store the decision as chip->locality will be changed. */ need_locality = chip->locality == -1; if (!(flags & TPM_TRANSMIT_RAW) && need_locality && chip->ops->request_locality) { rc = chip->ops->request_locality(chip, 0); if (!(flags & TPM_TRANSMIT_RAW) && need_locality) { rc = tpm_request_locality(chip); if (rc < 0) goto out_no_locality; chip->locality = rc; } if (chip->dev.parent) pm_runtime_get_sync(chip->dev.parent); rc = tpm2_prepare_space(chip, space, ordinal, buf); if (rc) goto out; rc = chip->ops->send(chip, (u8 *) buf, count); rc = chip->ops->send(chip, buf, count); if (rc < 0) { if (rc != -EPIPE) dev_err(&chip->dev, Loading Loading @@ -480,7 +499,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, goto out; out_recv: len = chip->ops->recv(chip, (u8 *) buf, bufsiz); len = chip->ops->recv(chip, buf, bufsiz); if (len < 0) { rc = len; dev_err(&chip->dev, Loading @@ -499,27 +518,95 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, rc = tpm2_commit_space(chip, space, ordinal, buf, &len); out: if (need_locality && chip->ops->relinquish_locality) { chip->ops->relinquish_locality(chip, chip->locality); chip->locality = -1; } if (chip->dev.parent) pm_runtime_put_sync(chip->dev.parent); if (need_locality) tpm_relinquish_locality(chip); out_no_locality: if (chip->ops->clk_enable != NULL) chip->ops->clk_enable(chip, false); if (chip->dev.parent) pm_runtime_put_sync(chip->dev.parent); if (!(flags & TPM_TRANSMIT_UNLOCKED)) mutex_unlock(&chip->tpm_mutex); return rc ? rc : len; } /** * tmp_transmit_cmd - send a tpm command to the device * tpm_transmit - Internal kernel interface to transmit TPM commands. * * @chip: TPM chip to use * @space: tpm space * @buf: TPM command buffer * @bufsiz: length of the TPM command buffer * @flags: tpm transmit flags - bitmap * * A wrapper around tpm_try_transmit that handles TPM2_RC_RETRY * returns from the TPM and retransmits the command after a delay up * to a maximum wait of TPM2_DURATION_LONG. * * Note: TPM1 never returns TPM2_RC_RETRY so the retry logic is TPM2 * only * * Return: * the length of the return when the operation is successful. * A negative number for system errors (errno). */ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, u8 *buf, size_t bufsiz, unsigned int flags) { struct tpm_output_header *header = (struct tpm_output_header *)buf; /* space for header and handles */ u8 save[TPM_HEADER_SIZE + 3*sizeof(u32)]; unsigned int delay_msec = TPM2_DURATION_SHORT; u32 rc = 0; ssize_t ret; const size_t save_size = min(space ? sizeof(save) : TPM_HEADER_SIZE, bufsiz); /* the command code is where the return code will be */ u32 cc = be32_to_cpu(header->return_code); /* * Subtlety here: if we have a space, the handles will be * transformed, so when we restore the header we also have to * restore the handles. */ memcpy(save, buf, save_size); for (;;) { ret = tpm_try_transmit(chip, space, buf, bufsiz, flags); if (ret < 0) break; rc = be32_to_cpu(header->return_code); if (rc != TPM2_RC_RETRY && rc != TPM2_RC_TESTING) break; /* * return immediately if self test returns test * still running to shorten boot time. */ if (rc == TPM2_RC_TESTING && cc == TPM2_CC_SELF_TEST) break; delay_msec *= 2; if (delay_msec > TPM2_DURATION_LONG) { if (rc == TPM2_RC_RETRY) dev_err(&chip->dev, "in retry loop\n"); else dev_err(&chip->dev, "self test is still running\n"); break; } tpm_msleep(delay_msec); memcpy(buf, save, save_size); } return ret; } /** * tpm_transmit_cmd - send a tpm command to the device * The function extracts tpm out header return code * * @chip: TPM chip to use * @space: tpm space * @buf: TPM command buffer * @bufsiz: length of the buffer * @min_rsp_body_length: minimum expected length of response body Loading @@ -532,7 +619,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, * A positive number for a TPM error. */ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space, const void *buf, size_t bufsiz, void *buf, size_t bufsiz, size_t min_rsp_body_length, unsigned int flags, const char *desc) { Loading @@ -540,7 +627,7 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space, int err; ssize_t len; len = tpm_transmit(chip, space, (u8 *)buf, bufsiz, flags); len = tpm_transmit(chip, space, buf, bufsiz, flags); if (len < 0) return len; Loading Loading @@ -666,6 +753,8 @@ int tpm_get_timeouts(struct tpm_chip *chip) msecs_to_jiffies(TPM2_DURATION_MEDIUM); chip->duration[TPM_LONG] = msecs_to_jiffies(TPM2_DURATION_LONG); chip->duration[TPM_LONG_LONG] = msecs_to_jiffies(TPM2_DURATION_LONG_LONG); chip->flags |= TPM_CHIP_FLAG_HAVE_TIMEOUTS; return 0; Loading Loading @@ -754,6 +843,7 @@ int tpm_get_timeouts(struct tpm_chip *chip) usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_medium)); chip->duration[TPM_LONG] = usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_long)); chip->duration[TPM_LONG_LONG] = 0; /* not used under 1.2 */ /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above * value wrong and apparently reports msecs rather than usecs. So we Loading Loading @@ -969,6 +1059,10 @@ int tpm_do_selftest(struct tpm_chip *chip) loops = jiffies_to_msecs(duration) / delay_msec; rc = tpm_continue_selftest(chip); if (rc == TPM_ERR_INVALID_POSTINIT) { chip->flags |= TPM_CHIP_FLAG_ALWAYS_POWERED; dev_info(&chip->dev, "TPM not ready (%d)\n", rc); } /* This may fail if there was no TPM driver during a suspend/resume * cycle; some may return 10 (BAD_ORDINAL), others 28 (FAILEDSELFTEST) */ Loading
drivers/char/tpm/tpm.h +21 −11 Original line number Diff line number Diff line Loading @@ -67,7 +67,9 @@ enum tpm_duration { TPM_SHORT = 0, TPM_MEDIUM = 1, TPM_LONG = 2, TPM_LONG_LONG = 3, TPM_UNDEFINED, TPM_NUM_DURATIONS = TPM_UNDEFINED, }; #define TPM_WARN_RETRY 0x800 Loading @@ -81,6 +83,9 @@ enum tpm_duration { enum tpm2_const { TPM2_PLATFORM_PCR = 24, TPM2_PCR_SELECT_MIN = ((TPM2_PLATFORM_PCR + 7) / 8), }; enum tpm2_timeouts { TPM2_TIMEOUT_A = 750, TPM2_TIMEOUT_B = 2000, TPM2_TIMEOUT_C = 200, Loading @@ -88,6 +93,8 @@ enum tpm2_const { TPM2_DURATION_SHORT = 20, TPM2_DURATION_MEDIUM = 750, TPM2_DURATION_LONG = 2000, TPM2_DURATION_LONG_LONG = 300000, TPM2_DURATION_DEFAULT = 120000, }; enum tpm2_structures { Loading @@ -104,10 +111,12 @@ enum tpm2_return_codes { TPM2_RC_HASH = 0x0083, /* RC_FMT1 */ TPM2_RC_HANDLE = 0x008B, TPM2_RC_INITIALIZE = 0x0100, /* RC_VER1 */ TPM2_RC_FAILURE = 0x0101, TPM2_RC_DISABLED = 0x0120, TPM2_RC_COMMAND_CODE = 0x0143, TPM2_RC_TESTING = 0x090A, /* RC_WARN */ TPM2_RC_REFERENCE_H0 = 0x0910, TPM2_RC_RETRY = 0x0922, }; enum tpm2_algorithms { Loading @@ -123,6 +132,7 @@ enum tpm2_algorithms { enum tpm2_command_codes { TPM2_CC_FIRST = 0x011F, TPM2_CC_CREATE_PRIMARY = 0x0131, TPM2_CC_SELF_TEST = 0x0143, TPM2_CC_STARTUP = 0x0144, TPM2_CC_SHUTDOWN = 0x0145, Loading Loading @@ -227,7 +237,7 @@ struct tpm_chip { unsigned long timeout_c; /* jiffies */ unsigned long timeout_d; /* jiffies */ bool timeout_adjusted; unsigned long duration[3]; /* jiffies */ unsigned long duration[TPM_NUM_DURATIONS]; /* jiffies */ bool duration_adjusted; struct dentry *bios_dir[TPM_NUM_EVENT_LOG_FILES]; Loading Loading @@ -506,7 +516,7 @@ enum tpm_transmit_flags { ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, u8 *buf, size_t bufsiz, unsigned int flags); ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space, const void *buf, size_t bufsiz, void *buf, size_t bufsiz, size_t min_rsp_body_length, unsigned int flags, const char *desc); int tpm_startup(struct tpm_chip *chip); Loading
drivers/char/tpm/tpm2-cmd.c +21 −41 Original line number Diff line number Diff line Loading @@ -31,10 +31,6 @@ struct tpm2_startup_in { __be16 startup_type; } __packed; struct tpm2_self_test_in { u8 full_test; } __packed; struct tpm2_get_tpm_pt_in { __be32 cap_id; __be32 property_id; Loading @@ -60,7 +56,6 @@ struct tpm2_get_random_out { union tpm2_cmd_params { struct tpm2_startup_in startup_in; struct tpm2_self_test_in selftest_in; struct tpm2_get_tpm_pt_in get_tpm_pt_in; struct tpm2_get_tpm_pt_out get_tpm_pt_out; struct tpm2_get_random_in getrandom_in; Loading Loading @@ -90,6 +85,8 @@ static struct tpm2_hash tpm2_hash_map[] = { * of time the chip could take to return the result. The values * of the SHORT, MEDIUM, and LONG durations are taken from the * PC Client Profile (PTP) specification. * LONG_LONG is for commands that generates keys which empirically * takes longer time on some systems. */ static const u8 tpm2_ordinal_duration[TPM2_CC_LAST - TPM2_CC_FIRST + 1] = { TPM_UNDEFINED, /* 11F */ Loading @@ -110,7 +107,7 @@ static const u8 tpm2_ordinal_duration[TPM2_CC_LAST - TPM2_CC_FIRST + 1] = { TPM_UNDEFINED, /* 12e */ TPM_UNDEFINED, /* 12f */ TPM_UNDEFINED, /* 130 */ TPM_UNDEFINED, /* 131 */ TPM_LONG_LONG, /* 131 */ TPM_UNDEFINED, /* 132 */ TPM_UNDEFINED, /* 133 */ TPM_UNDEFINED, /* 134 */ Loading Loading @@ -144,7 +141,7 @@ static const u8 tpm2_ordinal_duration[TPM2_CC_LAST - TPM2_CC_FIRST + 1] = { TPM_UNDEFINED, /* 150 */ TPM_UNDEFINED, /* 151 */ TPM_UNDEFINED, /* 152 */ TPM_UNDEFINED, /* 153 */ TPM_LONG_LONG, /* 153 */ TPM_UNDEFINED, /* 154 */ TPM_UNDEFINED, /* 155 */ TPM_UNDEFINED, /* 156 */ Loading Loading @@ -821,22 +818,12 @@ unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal) duration = chip->duration[index]; if (duration <= 0) duration = 2 * 60 * HZ; duration = msecs_to_jiffies(TPM2_DURATION_DEFAULT); return duration; } EXPORT_SYMBOL_GPL(tpm2_calc_ordinal_duration); #define TPM2_SELF_TEST_IN_SIZE \ (sizeof(struct tpm_input_header) + \ sizeof(struct tpm2_self_test_in)) static const struct tpm_input_header tpm2_selftest_header = { .tag = cpu_to_be16(TPM2_ST_NO_SESSIONS), .length = cpu_to_be32(TPM2_SELF_TEST_IN_SIZE), .ordinal = cpu_to_be32(TPM2_CC_SELF_TEST) }; /** * tpm2_do_selftest() - ensure that all self tests have passed * Loading @@ -852,27 +839,24 @@ static const struct tpm_input_header tpm2_selftest_header = { */ static int tpm2_do_selftest(struct tpm_chip *chip) { struct tpm_buf buf; int full; int rc; unsigned int delay_msec = 10; long duration; struct tpm2_cmd cmd; duration = jiffies_to_msecs( tpm2_calc_ordinal_duration(chip, TPM2_CC_SELF_TEST)); while (1) { cmd.header.in = tpm2_selftest_header; cmd.params.selftest_in.full_test = 0; rc = tpm_transmit_cmd(chip, NULL, &cmd, TPM2_SELF_TEST_IN_SIZE, 0, 0, "continue selftest"); for (full = 0; full < 2; full++) { rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_SELF_TEST); if (rc) return rc; if (rc != TPM2_RC_TESTING || delay_msec >= duration) break; tpm_buf_append_u8(&buf, full); rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, "attempting the self test"); tpm_buf_destroy(&buf); /* wait longer than before */ delay_msec *= 2; tpm_msleep(delay_msec); if (rc == TPM2_RC_TESTING) rc = TPM2_RC_SUCCESS; if (rc == TPM2_RC_INITIALIZE || rc == TPM2_RC_SUCCESS) return rc; } return rc; Loading Loading @@ -1058,10 +1042,8 @@ int tpm2_auto_startup(struct tpm_chip *chip) goto out; rc = tpm2_do_selftest(chip); if (rc != 0 && rc != TPM2_RC_INITIALIZE) { dev_err(&chip->dev, "TPM self test failed\n"); if (rc && rc != TPM2_RC_INITIALIZE) goto out; } if (rc == TPM2_RC_INITIALIZE) { rc = tpm_startup(chip); Loading @@ -1069,11 +1051,9 @@ int tpm2_auto_startup(struct tpm_chip *chip) goto out; rc = tpm2_do_selftest(chip); if (rc) { dev_err(&chip->dev, "TPM self test failed\n"); if (rc) goto out; } } rc = tpm2_get_pcr_allocation(chip); if (rc) Loading
drivers/char/tpm/tpm_crb.c +78 −35 Original line number Diff line number Diff line Loading @@ -112,6 +112,25 @@ struct tpm2_crb_smc { u32 smc_func_id; }; static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value, unsigned long timeout) { ktime_t start; ktime_t stop; start = ktime_get(); stop = ktime_add(start, ms_to_ktime(timeout)); do { if ((ioread32(reg) & mask) == value) return true; usleep_range(50, 100); } while (ktime_before(ktime_get(), stop)); return ((ioread32(reg) & mask) == value); } /** * crb_go_idle - request tpm crb device to go the idle state * Loading @@ -128,7 +147,7 @@ struct tpm2_crb_smc { * * Return: 0 always */ static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv) static int crb_go_idle(struct device *dev, struct crb_priv *priv) { if ((priv->sm == ACPI_TPM2_START_METHOD) || (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) || Loading @@ -136,28 +155,15 @@ static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv) return 0; iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req); /* we don't really care when this settles */ return 0; if (!crb_wait_for_reg_32(&priv->regs_t->ctrl_req, CRB_CTRL_REQ_GO_IDLE/* mask */, 0, /* value */ TPM2_TIMEOUT_C)) { dev_warn(dev, "goIdle timed out\n"); return -ETIME; } static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value, unsigned long timeout) { ktime_t start; ktime_t stop; start = ktime_get(); stop = ktime_add(start, ms_to_ktime(timeout)); do { if ((ioread32(reg) & mask) == value) return true; usleep_range(50, 100); } while (ktime_before(ktime_get(), stop)); return false; return 0; } /** Loading @@ -175,8 +181,7 @@ static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value, * * Return: 0 on success -ETIME on timeout; */ static int __maybe_unused crb_cmd_ready(struct device *dev, struct crb_priv *priv) static int crb_cmd_ready(struct device *dev, struct crb_priv *priv) { if ((priv->sm == ACPI_TPM2_START_METHOD) || (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) || Loading @@ -195,9 +200,9 @@ static int __maybe_unused crb_cmd_ready(struct device *dev, return 0; } static int crb_request_locality(struct tpm_chip *chip, int loc) static int __crb_request_locality(struct device *dev, struct crb_priv *priv, int loc) { struct crb_priv *priv = dev_get_drvdata(&chip->dev); u32 value = CRB_LOC_STATE_LOC_ASSIGNED | CRB_LOC_STATE_TPM_REG_VALID_STS; Loading @@ -207,21 +212,45 @@ static int crb_request_locality(struct tpm_chip *chip, int loc) iowrite32(CRB_LOC_CTRL_REQUEST_ACCESS, &priv->regs_h->loc_ctrl); if (!crb_wait_for_reg_32(&priv->regs_h->loc_state, value, value, TPM2_TIMEOUT_C)) { dev_warn(&chip->dev, "TPM_LOC_STATE_x.requestAccess timed out\n"); dev_warn(dev, "TPM_LOC_STATE_x.requestAccess timed out\n"); return -ETIME; } return 0; } static void crb_relinquish_locality(struct tpm_chip *chip, int loc) static int crb_request_locality(struct tpm_chip *chip, int loc) { struct crb_priv *priv = dev_get_drvdata(&chip->dev); return __crb_request_locality(&chip->dev, priv, loc); } static int __crb_relinquish_locality(struct device *dev, struct crb_priv *priv, int loc) { u32 mask = CRB_LOC_STATE_LOC_ASSIGNED | CRB_LOC_STATE_TPM_REG_VALID_STS; u32 value = CRB_LOC_STATE_TPM_REG_VALID_STS; if (!priv->regs_h) return; return 0; iowrite32(CRB_LOC_CTRL_RELINQUISH, &priv->regs_h->loc_ctrl); if (!crb_wait_for_reg_32(&priv->regs_h->loc_state, mask, value, TPM2_TIMEOUT_C)) { dev_warn(dev, "TPM_LOC_STATE_x.requestAccess timed out\n"); return -ETIME; } return 0; } static int crb_relinquish_locality(struct tpm_chip *chip, int loc) { struct crb_priv *priv = dev_get_drvdata(&chip->dev); return __crb_relinquish_locality(&chip->dev, priv, loc); } static u8 crb_status(struct tpm_chip *chip) Loading Loading @@ -442,6 +471,7 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, u32 pa_high, pa_low; u64 cmd_pa; u32 cmd_size; __le64 __rsp_pa; u64 rsp_pa; u32 rsp_size; int ret; Loading Loading @@ -475,6 +505,10 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, dev_warn(dev, FW_BUG "Bad ACPI memory layout"); } ret = __crb_request_locality(dev, priv, 0); if (ret) return ret; priv->regs_t = crb_map_res(dev, priv, &io_res, buf->control_address, sizeof(struct crb_regs_tail)); if (IS_ERR(priv->regs_t)) Loading Loading @@ -503,8 +537,8 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, goto out; } memcpy_fromio(&rsp_pa, &priv->regs_t->ctrl_rsp_pa, 8); rsp_pa = le64_to_cpu(rsp_pa); memcpy_fromio(&__rsp_pa, &priv->regs_t->ctrl_rsp_pa, 8); rsp_pa = le64_to_cpu(__rsp_pa); rsp_size = crb_fixup_cmd_size(dev, &io_res, rsp_pa, ioread32(&priv->regs_t->ctrl_rsp_size)); Loading @@ -531,6 +565,8 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, crb_go_idle(dev, priv); __crb_relinquish_locality(dev, priv, 0); return ret; } Loading Loading @@ -588,10 +624,14 @@ static int crb_acpi_add(struct acpi_device *device) chip->acpi_dev_handle = device->handle; chip->flags = TPM_CHIP_FLAG_TPM2; rc = crb_cmd_ready(dev, priv); rc = __crb_request_locality(dev, priv, 0); if (rc) return rc; rc = crb_cmd_ready(dev, priv); if (rc) goto out; pm_runtime_get_noresume(dev); pm_runtime_set_active(dev); pm_runtime_enable(dev); Loading @@ -601,12 +641,15 @@ static int crb_acpi_add(struct acpi_device *device) crb_go_idle(dev, priv); pm_runtime_put_noidle(dev); pm_runtime_disable(dev); return rc; goto out; } pm_runtime_put(dev); pm_runtime_put_sync(dev); return 0; out: __crb_relinquish_locality(dev, priv, 0); return rc; } static int crb_acpi_remove(struct acpi_device *device) Loading
drivers/char/tpm/tpm_tis_core.c +3 −1 Original line number Diff line number Diff line Loading @@ -143,11 +143,13 @@ static bool check_locality(struct tpm_chip *chip, int l) return false; } static void release_locality(struct tpm_chip *chip, int l) static int release_locality(struct tpm_chip *chip, int l) { struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY); return 0; } static int request_locality(struct tpm_chip *chip, int l) Loading