static int tpm_tis_i2c_recv_data(struct udevice *dev, u8 *buf, size_t count) { struct tpm_chip *chip = dev_get_priv(dev); size_t size = 0; ssize_t burstcnt; int rc; while (size < count) { burstcnt = tpm_tis_i2c_get_burstcount(dev); /* burstcount < 0 -> tpm is busy */ if (burstcnt < 0) return burstcnt; /* Limit received data to max left */ if (burstcnt > (count - size)) burstcnt = count - size; rc = tpm_tis_i2c_read(dev, TPM_DATA_FIFO(chip->locality), &(buf[size]), burstcnt); if (rc == 0) size += burstcnt; } return size; }
static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) { size_t size = 0; ssize_t burstcnt; u8 retries = 0; int rc; while (size < count) { burstcnt = get_burstcount(chip); /* burstcnt < 0 = TPM is busy */ if (burstcnt < 0) return burstcnt; /* limit received data to max. left */ if (burstcnt > (count - size)) burstcnt = count - size; rc = iic_tpm_read(TPM_DATA_FIFO(chip->vendor.locality), &(buf[size]), burstcnt); if (rc == 0) size += burstcnt; else if (rc < 0) retries++; /* avoid endless loop in case of broken HW */ if (retries > MAX_COUNT_LONG) return -EIO; } return size; }
static int recv_data(struct tpm_chip* tpm, uint8_t* buf, size_t count) { int size = 0; int burstcnt; while( size < count && wait_for_stat(tpm, TPM_STS_DATA_AVAIL | TPM_STS_VALID, tpm->timeout_c, &tpm->read_queue) == 0) { burstcnt = get_burstcount(tpm); for(; burstcnt > 0 && size < count; --burstcnt) { buf[size++] = ioread8(TPM_DATA_FIFO(tpm, tpm->locality)); } } return size; }
static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) { int rc, status; ssize_t burstcnt; size_t count = 0; u8 retries = 0; u8 sts = TPM_STS_GO; if (len > TPM_BUFSIZE) return -E2BIG; /* command is too long for our tpm, sorry */ if (request_locality(chip, 0) < 0) return -EBUSY; status = tpm_tis_i2c_status(chip); if ((status & TPM_STS_COMMAND_READY) == 0) { tpm_tis_i2c_ready(chip); if (wait_for_stat (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b, &status) < 0) { rc = -ETIME; goto out_err; } } while (count < len - 1) { burstcnt = get_burstcount(chip); /* burstcnt < 0 = TPM is busy */ if (burstcnt < 0) return burstcnt; if (burstcnt > (len - 1 - count)) burstcnt = len - 1 - count; rc = iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality), &(buf[count]), burstcnt); if (rc == 0) count += burstcnt; else if (rc < 0) retries++; /* avoid endless loop in case of broken HW */ if (retries > MAX_COUNT_LONG) { rc = -EIO; goto out_err; } wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status); if ((status & TPM_STS_DATA_EXPECT) == 0) { rc = -EIO; goto out_err; } } /* write last byte */ iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality), &(buf[count]), 1); wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status); if ((status & TPM_STS_DATA_EXPECT) != 0) { rc = -EIO; goto out_err; } /* go and do it */ iic_tpm_write(TPM_STS(chip->vendor.locality), &sts, 1); return len; out_err: tpm_tis_i2c_ready(chip); /* The TPM needs some time to clean up here, * so we sleep rather than keeping the bus busy */ usleep_range(SLEEP_DURATION_RESET_LOW, SLEEP_DURATION_RESET_HI); release_locality(chip, chip->vendor.locality, 0); return rc; }
static int tpm_tis_i2c_send(struct udevice *dev, const u8 *buf, size_t len) { struct tpm_chip *chip = dev_get_priv(dev); int rc, status; size_t burstcnt; size_t count = 0; int retry = 0; u8 sts = TPM_STS_GO; debug("%s: len=%d\n", __func__, len); if (len > TPM_DEV_BUFSIZE) return -E2BIG; /* Command is too long for our tpm, sorry */ if (tpm_tis_i2c_request_locality(dev, 0) < 0) return -EBUSY; status = tpm_tis_i2c_status(dev); if ((status & TPM_STS_COMMAND_READY) == 0) { rc = tpm_tis_i2c_ready(dev); if (rc) return rc; rc = tpm_tis_i2c_wait_for_stat(dev, TPM_STS_COMMAND_READY, chip->timeout_b, &status); if (rc) return rc; } burstcnt = tpm_tis_i2c_get_burstcount(dev); /* burstcount < 0 -> tpm is busy */ if (burstcnt < 0) return burstcnt; while (count < len) { udelay(300); if (burstcnt > len - count) burstcnt = len - count; #ifdef CONFIG_TPM_TIS_I2C_BURST_LIMITATION if (retry && burstcnt > CONFIG_TPM_TIS_I2C_BURST_LIMITATION_LEN) burstcnt = CONFIG_TPM_TIS_I2C_BURST_LIMITATION_LEN; #endif /* CONFIG_TPM_TIS_I2C_BURST_LIMITATION */ rc = tpm_tis_i2c_write(dev, TPM_DATA_FIFO(chip->locality), &(buf[count]), burstcnt); if (rc == 0) count += burstcnt; else { debug("%s: error\n", __func__); if (retry++ > 10) return -EIO; rc = tpm_tis_i2c_wait_for_stat(dev, TPM_STS_VALID, chip->timeout_c, &status); if (rc) return rc; if ((status & TPM_STS_DATA_EXPECT) == 0) return -EIO; } } /* Go and do it */ rc = tpm_tis_i2c_write(dev, TPM_STS(chip->locality), &sts, 1); if (rc < 0) return rc; debug("%s: done, rc=%d\n", __func__, rc); return len; }
int tpm_tis_send(struct tpm_chip* tpm, uint8_t* buf, size_t len) { int rc; int status, burstcnt = 0; int count = 0; uint32_t ordinal; if(tpm_tis_request_locality(tpm, tpm->locality) < 0) { return -EBUSY; } status = tpm_tis_status(tpm); if((status & TPM_STS_COMMAND_READY) == 0) { tpm_tis_ready(tpm); if(wait_for_stat(tpm, TPM_STS_COMMAND_READY, tpm->timeout_b, &tpm->int_queue) < 0) { rc = -ETIME; goto out_err; } } while(count < len - 1) { burstcnt = get_burstcount(tpm); for(;burstcnt > 0 && count < len -1; --burstcnt) { iowrite8(TPM_DATA_FIFO(tpm, tpm->locality), buf[count++]); } wait_for_stat(tpm, TPM_STS_VALID, tpm->timeout_c, &tpm->int_queue); status = tpm_tis_status(tpm); if((status & TPM_STS_DATA_EXPECT) == 0) { rc = -EIO; goto out_err; } } /*Write last byte*/ iowrite8(TPM_DATA_FIFO(tpm, tpm->locality), buf[count]); wait_for_stat(tpm, TPM_STS_VALID, tpm->timeout_c, &tpm->read_queue); status = tpm_tis_status(tpm); if((status & TPM_STS_DATA_EXPECT) != 0) { rc = -EIO; goto out_err; } /*go and do it*/ iowrite8(TPM_STS(tpm, tpm->locality), TPM_STS_GO); if(tpm->irq) { /*Wait for interrupt */ ordinal = be32_to_cpu(*(buf + 6)); if(wait_for_stat(tpm, TPM_STS_DATA_AVAIL | TPM_STS_VALID, tpm_calc_ordinal_duration(tpm, ordinal), &tpm->read_queue) < 0) { rc = -ETIME; goto out_err; } } #ifdef HAVE_LIBC if(tpm->fd >= 0) { files[tpm->fd].read = 0; files[tpm->fd].tpm_tis.respgot = 0; files[tpm->fd].tpm_tis.offset = 0; } #endif return len; out_err: tpm_tis_ready(tpm); release_locality(tpm, tpm->locality, 0); return rc; }
static int cr50_i2c_tis_send(struct tpm_chip *chip, uint8_t *buf, size_t len) { int status; size_t burstcnt, limit, sent = 0; uint8_t tpm_go[4] = { TPM_STS_GO }; struct stopwatch sw; stopwatch_init_msecs_expire(&sw, CR50_TIMEOUT_LONG_MS); /* Wait until TPM is ready for a command */ while (!(cr50_i2c_tis_status(chip) & TPM_STS_COMMAND_READY)) { if (stopwatch_expired(&sw)) { printk(BIOS_ERR, "%s: Command ready timeout\n", __func__); return -1; } cr50_i2c_tis_ready(chip); } while (len > 0) { uint8_t mask = TPM_STS_VALID; /* Wait for data if this is not the first chunk */ if (sent > 0) mask |= TPM_STS_DATA_EXPECT; /* Read burst count and check status */ if (cr50_i2c_wait_burststs(chip, mask, &burstcnt, &status) < 0) goto out_err; /* Use burstcnt - 1 to account for the address byte * that is inserted by cr50_i2c_write() */ limit = min(burstcnt - 1, len); if (cr50_i2c_write(chip, TPM_DATA_FIFO(chip->vendor.locality), &buf[sent], limit) != 0) { printk(BIOS_ERR, "%s: Write failed\n", __func__); goto out_err; } sent += limit; len -= limit; } /* Ensure TPM is not expecting more data */ if (cr50_i2c_wait_burststs(chip, TPM_STS_VALID, &burstcnt, &status) < 0) goto out_err; if (status & TPM_STS_DATA_EXPECT) { printk(BIOS_ERR, "%s: Data still expected\n", __func__); goto out_err; } /* Start the TPM command */ if (cr50_i2c_write(chip, TPM_STS(chip->vendor.locality), tpm_go, sizeof(tpm_go)) < 0) { printk(BIOS_ERR, "%s: Start command failed\n", __func__); goto out_err; } return sent; out_err: /* Abort current transaction if still pending */ if (cr50_i2c_tis_status(chip) & TPM_STS_COMMAND_READY) cr50_i2c_tis_ready(chip); return -1; }
static int cr50_i2c_tis_recv(struct tpm_chip *chip, uint8_t *buf, size_t buf_len) { size_t burstcnt, current, len, expected; uint8_t addr = TPM_DATA_FIFO(chip->vendor.locality); uint8_t mask = TPM_STS_VALID | TPM_STS_DATA_AVAIL; int status; if (buf_len < TPM_HEADER_SIZE) goto out_err; if (cr50_i2c_wait_burststs(chip, mask, &burstcnt, &status) < 0) { printk(BIOS_ERR, "%s: First chunk not available\n", __func__); goto out_err; } /* Read first chunk of burstcnt bytes */ if (cr50_i2c_read(chip, addr, buf, burstcnt) != 0) { printk(BIOS_ERR, "%s: Read failed\n", __func__); goto out_err; } /* Determine expected data in the return buffer */ expected = read_be32(buf + TPM_RSP_SIZE_BYTE); if (expected > buf_len) { printk(BIOS_ERR, "%s: Too much data: %zu > %zu\n", __func__, expected, buf_len); goto out_err; } /* Now read the rest of the data */ current = burstcnt; while (current < expected) { /* Read updated burst count and check status */ if (cr50_i2c_wait_burststs(chip, mask, &burstcnt, &status) < 0) goto out_err; len = min(burstcnt, expected - current); if (cr50_i2c_read(chip, addr, buf + current, len) != 0) { printk(BIOS_ERR, "%s: Read failed\n", __func__); goto out_err; } current += len; } /* Ensure TPM is done reading data */ if (cr50_i2c_wait_burststs(chip, TPM_STS_VALID, &burstcnt, &status) < 0) goto out_err; if (status & TPM_STS_DATA_AVAIL) { printk(BIOS_ERR, "%s: Data still available\n", __func__); goto out_err; } return current; out_err: /* Abort current transaction if still pending */ if (cr50_i2c_tis_status(chip) & TPM_STS_COMMAND_READY) cr50_i2c_tis_ready(chip); return -1; }