Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
0
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;
}
Пример #5
0
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;
}
Пример #6
0
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;
}
Пример #7
0
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;
}
Пример #8
0
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;
}