/* check current status */
status = chip->ops->status(chip); if ((status & mask) == mask) return 0;
sts_mask = mask & (TPM_STS_VALID | TPM_STS_DATA_AVAIL |
TPM_STS_COMMAND_READY); /* check what status changes can be handled by irqs */
sts_mask = tpm_tis_filter_sts_mask(priv->int_mask, sts_mask);
stop = jiffies + timeout; /* process status changes with irq support */ if (sts_mask) {
ret = -ETIME;
again:
timeout = stop - jiffies; if ((long)timeout <= 0) return -ETIME;
rc = wait_event_interruptible_timeout(*queue,
wait_for_tpm_stat_cond(chip, sts_mask, check_cancel,
&canceled),
timeout); if (rc > 0) { if (canceled) return -ECANCELED;
ret = 0;
} if (rc == -ERESTARTSYS && freezing(current)) {
clear_thread_flag(TIF_SIGPENDING); goto again;
}
}
if (ret) return ret;
mask &= ~sts_mask; if (!mask) /* all done */ return 0; /* process status changes without irq support */ do {
usleep_range(priv->timeout_min, priv->timeout_max);
status = chip->ops->status(chip); if ((status & mask) == mask) return 0;
} while (time_before(jiffies, stop)); return -ETIME;
}
/* Before we attempt to access the TPM we must see that the valid bit is set. * The specification says that this bit is 0 at reset and remains 0 until the * 'TPM has gone through its self test and initialization and has established * correct values in the other bits.'
*/ staticint wait_startup(struct tpm_chip *chip, int l)
{ struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); unsignedlong stop = jiffies + chip->timeout_a;
if (unlikely((status & TPM_STS_READ_ZERO) != 0)) { if (!test_and_set_bit(TPM_TIS_INVALID_STATUS, &priv->flags)) { /* * If this trips, the chances are the read is * returning 0xff because the locality hasn't been * acquired. Usually because tpm_try_get_ops() hasn't * been called before doing a TPM operation.
*/
dev_err(&chip->dev, "invalid TPM_STS.x 0x%02x, dumping stack for forensics\n",
status);
/* * Dump stack for forensics, as invalid TPM_STS.x could be * potentially triggered by impaired tpm_try_get_ops() or * tpm_find_get_ops().
*/
dump_stack();
}
staticint tpm_tis_try_recv(struct tpm_chip *chip, u8 *buf, size_t count)
{ struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); int size = 0; int status;
u32 expected; int rc;
size = recv_data(chip, buf, TPM_HEADER_SIZE); /* read first 10 bytes, including tag, paramsize, and result */ if (size < TPM_HEADER_SIZE) {
dev_err(&chip->dev, "Unable to read header\n"); goto out;
}
if (rc == -EIO) /* Data transfer errors, indicated by EIO, can be * recovered by rereading the response.
*/
tpm_tis_write8(priv, TPM_STS(priv->locality),
TPM_STS_RESPONSE_RETRY); else break;
}
tpm_tis_ready(chip);
return rc;
}
/* * If interrupts are used (signaled by an irq set in the vendor structure) * tpm.c can skip polling for the data to be available as the interrupt is * waited for here
*/ staticint tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len)
{ struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); int rc, status, burstcnt;
size_t count = 0; bool itpm = test_bit(TPM_TIS_ITPM_WORKAROUND, &priv->flags);
status = tpm_tis_status(chip); if ((status & TPM_STS_COMMAND_READY) == 0) {
tpm_tis_ready(chip); if (wait_for_tpm_stat
(chip, TPM_STS_COMMAND_READY, chip->timeout_b,
&priv->int_queue, false) < 0) {
rc = -ETIME; goto out_err;
}
}
while (count < len - 1) {
burstcnt = get_burstcount(chip); if (burstcnt < 0) {
dev_err(&chip->dev, "Unable to read burstcount\n");
rc = burstcnt; goto out_err;
}
burstcnt = min_t(int, burstcnt, len - count - 1);
rc = tpm_tis_write_bytes(priv, TPM_DATA_FIFO(priv->locality),
burstcnt, buf + count); if (rc < 0) goto out_err;
/* * If interrupts are used (signaled by an irq set in the vendor structure) * tpm.c can skip polling for the data to be available as the interrupt is * waited for here
*/ staticint tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len)
{ struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); int rc;
u32 ordinal; unsignedlong dur; unsignedinttry;
for (try = 0; try < TPM_RETRY; try++) {
rc = tpm_tis_send_data(chip, buf, len); if (rc >= 0) /* Data transfer done successfully */ break; elseif (rc != -EAGAIN && rc != -EIO) /* Data transfer failed, not recoverable */ return rc;
/* Try to get a TPM version 1.2 or 1.1 TPM_CAP_VERSION_INFO */
rc = tpm1_getcap(chip, TPM_CAP_VERSION_1_2, &cap, "attempting to determine the 1.2 version", sizeof(cap.version2)); if (!rc) {
version = &cap.version2.version;
} else {
rc = tpm1_getcap(chip, TPM_CAP_VERSION_1_1, &cap, "attempting to determine the 1.1 version", sizeof(cap.version1));
if (rc) goto out;
version = &cap.version1;
}
for (i = 0; i != ARRAY_SIZE(vendor_dur_overrides); i++) { if (vendor_dur_overrides[i].did_vid != did_vid) continue;
for (i = 0; i != ARRAY_SIZE(vendor_timeout_overrides); i++) { if (vendor_timeout_overrides[i].did_vid != did_vid) continue;
memcpy(timeout_cap, vendor_timeout_overrides[i].timeout_us, sizeof(vendor_timeout_overrides[i].timeout_us));
chip->timeout_adjusted = true;
}
out: if (chip->ops->clk_enable != NULL)
chip->ops->clk_enable(chip, false);
return;
}
/* * Early probing for iTPM with STS_DATA_EXPECT flaw. * Try sending command without itpm flag set and if that * fails, repeat with itpm flag set.
*/ staticint probe_itpm(struct tpm_chip *chip)
{ struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); int rc = 0; staticconst u8 cmd_getticks[] = {
0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a,
0x00, 0x00, 0x00, 0xf1
};
size_t len = sizeof(cmd_getticks);
u16 vendor;
if (test_bit(TPM_TIS_ITPM_WORKAROUND, &priv->flags)) return 0;
/* Register the IRQ and issue a command that will cause an interrupt. If an * irq is seen then leave the chip setup for IRQ operation, otherwise reverse * everything and leave in polling mode. Returns 0 on success.
*/ staticint tpm_tis_probe_irq_single(struct tpm_chip *chip, u32 intmask, int flags, int irq)
{ struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
u8 original_int_vec; int rc;
u32 int_status;
rc = devm_request_threaded_irq(chip->dev.parent, irq, NULL,
tis_int_handler, IRQF_ONESHOT | flags,
dev_name(&chip->dev), chip); if (rc) {
dev_info(&chip->dev, "Unable to request irq: %d for probe\n",
irq); return -1;
}
priv->irq = irq;
rc = tpm_tis_request_locality(chip, 0); if (rc < 0) return rc;
/* Clear all existing */
rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality), int_status); if (rc < 0) goto restore_irqs; /* Turn on */
rc = tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality),
intmask | TPM_GLOBAL_INT_ENABLE); if (rc < 0) goto restore_irqs;
clear_bit(TPM_TIS_IRQ_TESTED, &priv->flags);
/* Generate an interrupt by having the core call through to * tpm_tis_send
*/
tpm_tis_gen_interrupt(chip);
restore_irqs: /* tpm_tis_send will either confirm the interrupt is working or it * will call disable_irq which undoes all of the above.
*/ if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) {
tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality),
original_int_vec);
rc = -1;
}
/* Try to find the IRQ the TPM is using. This is for legacy x86 systems that * do not have ACPI/etc. We typically expect the interrupt to be declared if * present.
*/ staticvoid tpm_tis_probe_irq(struct tpm_chip *chip, u32 intmask)
{ struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
u8 original_int_vec; int i, rc;
rc = tpm_tis_read8(priv, TPM_INT_VECTOR(priv->locality),
&original_int_vec); if (rc < 0) return;
if (!original_int_vec) { if (IS_ENABLED(CONFIG_X86)) for (i = 3; i <= 15; i++) if (!tpm_tis_probe_irq_single(chip, intmask, 0,
i)) return;
} elseif (!tpm_tis_probe_irq_single(chip, intmask, 0,
original_int_vec)) return;
}
tpm_tis_write32(priv, reg, ~TPM_GLOBAL_INT_ENABLE & interrupt); if (priv->free_irq_work.func)
flush_work(&priv->free_irq_work);
tpm_tis_clkrun_enable(chip, false);
if (priv->ilb_base_addr)
iounmap(priv->ilb_base_addr);
}
EXPORT_SYMBOL_GPL(tpm_tis_remove);
/** * tpm_tis_clkrun_enable() - Keep clkrun protocol disabled for entire duration * of a single TPM command * @chip: TPM chip to use * @value: 1 - Disable CLKRUN protocol, so that clocks are free running * 0 - Enable CLKRUN protocol * Call this function directly in tpm_tis_remove() in error or driver removal * path, since the chip->ops is set to NULL in tpm_chip_unregister().
*/ staticvoid tpm_tis_clkrun_enable(struct tpm_chip *chip, bool value)
{ struct tpm_tis_data *data = dev_get_drvdata(&chip->dev);
u32 clkrun_val;
if (!IS_ENABLED(CONFIG_X86) || !is_bsw() ||
!data->ilb_base_addr) return;
if (value) {
data->clkrun_enabled++; if (data->clkrun_enabled > 1) return;
clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET);
#ifdef CONFIG_HAS_IOPORT /* * Write any random value on port 0x80 which is on LPC, to make * sure LPC clock is running before sending any TPM command.
*/
outb(0xCC, 0x80); #endif
}
if (priv->manufacturer_id == TPM_VID_IFX)
set_bit(TPM_TIS_STATUS_VALID_RETRY, &priv->flags);
if (is_bsw()) {
priv->ilb_base_addr = ioremap(INTEL_LEGACY_BLK_BASE_ADDR,
ILB_REMAP_SIZE); if (!priv->ilb_base_addr) return -ENOMEM;
clkrun_val = ioread32(priv->ilb_base_addr + LPC_CNTRL_OFFSET); /* Check if CLKRUN# is already not enabled in the LPC bus */ if (!(clkrun_val & LPC_CLKRUN_EN)) {
iounmap(priv->ilb_base_addr);
priv->ilb_base_addr = NULL;
}
}
if (chip->ops->clk_enable != NULL)
chip->ops->clk_enable(chip, true);
/* Take control of the TPM's interrupt hardware and shut it off */
rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask); if (rc < 0) goto out_err;
/* Figure out the capabilities */
rc = tpm_tis_read32(priv, TPM_INTF_CAPS(priv->locality), &intfcaps); if (rc < 0) goto out_err;
dev_dbg(dev, "TPM interface capabilities (0x%x):\n",
intfcaps); if (intfcaps & TPM_INTF_BURST_COUNT_STATIC)
dev_dbg(dev, "\tBurst Count Static\n"); if (intfcaps & TPM_INTF_CMD_READY_INT) {
intmask |= TPM_INTF_CMD_READY_INT;
dev_dbg(dev, "\tCommand Ready Int Support\n");
} if (intfcaps & TPM_INTF_INT_EDGE_FALLING)
dev_dbg(dev, "\tInterrupt Edge Falling\n"); if (intfcaps & TPM_INTF_INT_EDGE_RISING)
dev_dbg(dev, "\tInterrupt Edge Rising\n"); if (intfcaps & TPM_INTF_INT_LEVEL_LOW)
dev_dbg(dev, "\tInterrupt Level Low\n"); if (intfcaps & TPM_INTF_INT_LEVEL_HIGH)
dev_dbg(dev, "\tInterrupt Level High\n"); if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT) {
intmask |= TPM_INTF_LOCALITY_CHANGE_INT;
dev_dbg(dev, "\tLocality Change Int Support\n");
} if (intfcaps & TPM_INTF_STS_VALID_INT) {
intmask |= TPM_INTF_STS_VALID_INT;
dev_dbg(dev, "\tSts Valid Int Support\n");
} if (intfcaps & TPM_INTF_DATA_AVAIL_INT) {
intmask |= TPM_INTF_DATA_AVAIL_INT;
dev_dbg(dev, "\tData Avail Int Support\n");
}
rc = tpm_chip_bootstrap(chip); if (rc) goto out_err;
if (irq != -1) { /* * Before doing irq testing issue a command to the TPM in polling mode * to make sure it works. May as well use that command to set the * proper timeouts for the driver.
*/
rc = tpm_tis_request_locality(chip, 0); if (rc < 0) goto out_err;
rc = tpm_get_timeouts(chip);
tpm_tis_relinquish_locality(chip, 0);
if (rc) {
dev_err(dev, "Could not get TPM timeouts and durations\n");
rc = -ENODEV; goto out_err;
}
if (irq)
tpm_tis_probe_irq_single(chip, intmask, IRQF_SHARED,
irq); else
tpm_tis_probe_irq(chip, intmask);
if (chip->flags & TPM_CHIP_FLAG_IRQ) {
priv->int_mask = intmask;
} else {
dev_err(&chip->dev, FW_BUG "TPM interrupt not working, polling instead\n");
/* * Re-enable interrupts that device may have lost or BIOS/firmware may * have disabled.
*/
rc = tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality), priv->irq); if (rc < 0) {
dev_err(&chip->dev, "Setting IRQ failed.\n"); return;
}
int tpm_tis_resume(struct device *dev)
{ struct tpm_chip *chip = dev_get_drvdata(dev); int ret;
ret = tpm_chip_start(chip); if (ret) return ret;
if (chip->flags & TPM_CHIP_FLAG_IRQ)
tpm_tis_reenable_interrupts(chip);
/* * TPM 1.2 requires self-test on resume. This function actually returns * an error code but for unknown reason it isn't handled.
*/ if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
tpm1_do_selftest(chip);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.