/* * recv_data receive data * @param: chip, the tpm chip description * @param: buf, the buffer where the data are received * @param: count, the number of data to receive * @return: the number of bytes read from TPM FIFO. */ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) { int size = 0, burstcnt, len, ret; struct i2c_client *client; client = (struct i2c_client *)TPM_VPRIV(chip); while (size < count && wait_for_stat(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, chip->vendor.timeout_c, &chip->vendor.read_queue) == 0) { burstcnt = get_burstcount(chip); if (burstcnt < 0) return burstcnt; len = min_t(int, burstcnt, count - size); ret = I2C_READ_DATA(client, TPM_DATA_FIFO, buf + size, len); if (ret < 0) return ret; size += len; } 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; }
/* * recv_data receive data * @param: chip, the tpm chip description * @param: buf, the buffer where the data are received * @param: count, the number of data to receive * @return: the number of bytes read from TPM FIFO. */ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) { struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev); int size = 0, burstcnt, len, ret; while (size < count && wait_for_stat(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, chip->timeout_c, &tpm_dev->read_queue, true) == 0) { burstcnt = get_burstcount(chip); if (burstcnt < 0) return burstcnt; len = min_t(int, burstcnt, count - size); ret = tpm_dev->ops->recv(tpm_dev->phy_id, TPM_DATA_FIFO, buf + size, len); if (ret < 0) return ret; size += len; } 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; }
/* * tpm_stm_i2c_send send TPM commands through the I2C bus. * * @param: chip, the tpm_chip description as specified in driver/char/tpm/tpm.h * @param: buf, the buffer to send. * @param: count, the number of bytes to send. * @return: In case of success the number of bytes sent. * In other case, a < 0 value describing the issue. */ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf, size_t len) { u32 status, burstcnt = 0, i, size; int ret; u8 data; struct i2c_client *client; if (chip == NULL) return -EBUSY; if (len < TPM_HEADER_SIZE) return -EBUSY; client = (struct i2c_client *)TPM_VPRIV(chip); client->flags = 0; ret = request_locality(chip); if (ret < 0) return ret; status = tpm_stm_i2c_status(chip); if ((status & TPM_STS_COMMAND_READY) == 0) { tpm_stm_i2c_cancel(chip); if (wait_for_stat (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b, &chip->vendor.int_queue) < 0) { ret = -ETIME; goto out_err; } } for (i = 0 ; i < len - 1 ;) { burstcnt = get_burstcount(chip); size = min_t(int, len - i - 1, burstcnt); ret = I2C_WRITE_DATA(client, TPM_DATA_FIFO, buf, size); if (ret < 0) goto out_err; i += size; } status = tpm_stm_i2c_status(chip); if ((status & TPM_STS_DATA_EXPECT) == 0) { ret = -EIO; goto out_err; } ret = I2C_WRITE_DATA(client, TPM_DATA_FIFO, buf + len - 1, 1); if (ret < 0) goto out_err; status = tpm_stm_i2c_status(chip); if ((status & TPM_STS_DATA_EXPECT) != 0) { ret = -EIO; goto out_err; } data = TPM_STS_GO; I2C_WRITE_DATA(client, TPM_STS, &data, 1); return len; out_err: tpm_stm_i2c_cancel(chip); release_locality(chip); return ret; }
/* * st33zp24_send send TPM commands through the I2C bus. * * @param: chip, the tpm_chip description as specified in driver/char/tpm/tpm.h * @param: buf, the buffer to send. * @param: count, the number of bytes to send. * @return: In case of success the number of bytes sent. * In other case, a < 0 value describing the issue. */ static int st33zp24_send(struct tpm_chip *chip, unsigned char *buf, size_t len) { struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev); u32 status, i, size, ordinal; int burstcnt = 0; int ret; u8 data; if (!chip) return -EBUSY; if (len < TPM_HEADER_SIZE) return -EBUSY; ret = request_locality(chip); if (ret < 0) return ret; status = st33zp24_status(chip); if ((status & TPM_STS_COMMAND_READY) == 0) { st33zp24_cancel(chip); if (wait_for_stat (chip, TPM_STS_COMMAND_READY, chip->timeout_b, &tpm_dev->read_queue, false) < 0) { ret = -ETIME; goto out_err; } } for (i = 0; i < len - 1;) { burstcnt = get_burstcount(chip); if (burstcnt < 0) return burstcnt; size = min_t(int, len - i - 1, burstcnt); ret = tpm_dev->ops->send(tpm_dev->phy_id, TPM_DATA_FIFO, buf + i, size); if (ret < 0) goto out_err; i += size; } status = st33zp24_status(chip); if ((status & TPM_STS_DATA_EXPECT) == 0) { ret = -EIO; goto out_err; } ret = tpm_dev->ops->send(tpm_dev->phy_id, TPM_DATA_FIFO, buf + len - 1, 1); if (ret < 0) goto out_err; status = st33zp24_status(chip); if ((status & TPM_STS_DATA_EXPECT) != 0) { ret = -EIO; goto out_err; } data = TPM_STS_GO; ret = tpm_dev->ops->send(tpm_dev->phy_id, TPM_STS, &data, 1); if (ret < 0) goto out_err; if (chip->flags & TPM_CHIP_FLAG_IRQ) { ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); ret = wait_for_stat(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, tpm_calc_ordinal_duration(chip, ordinal), &tpm_dev->read_queue, false); if (ret < 0) goto out_err; } return len; out_err: st33zp24_cancel(chip); release_locality(chip); return ret; }
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; }