Beispiel #1
0
/*
 * Locality could be already claimed (if this is a later coreboot stage and
 * the RO did not release it), or not yet claimed, if this is verstage or the
 * older RO did release it.
 */
static int claim_locality(struct tpm_chip *chip)
{
	uint8_t access;
	const uint8_t mask = TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY;

	if (cr50_i2c_read(chip, TPM_ACCESS(0), &access, sizeof(access)))
		return -1;

	if ((access & mask) == mask) {
		printk(BIOS_INFO, "Locality already claimed\n");
		return 0;
	}

	access = TPM_ACCESS_REQUEST_USE;
	if (cr50_i2c_write(chip, TPM_ACCESS(0),
			   &access, sizeof(access)))
		return -1;

	if (cr50_i2c_read(chip, TPM_ACCESS(0), &access, sizeof(access)))
		return -1;

	if ((access & mask) != mask) {
		printk(BIOS_INFO, "Failed to claim locality.\n");
		return -1;
	}

	return 0;
}
Beispiel #2
0
void release_locality(struct tpm_chip* tpm, int l, int force)
{
   if (locality_enabled(tpm, l) && (force || (ioread8(TPM_ACCESS(tpm, l)) &
	       (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) ==
	    (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID))) {
      iowrite8(TPM_ACCESS(tpm, l), TPM_ACCESS_RELINQUISH_LOCALITY);
   }
}
Beispiel #3
0
/* implementation similar to tpm_tis */
static void release_locality(struct tpm_chip *chip, int loc, int force)
{
	u8 buf;
	if (iic_tpm_read(TPM_ACCESS(loc), &buf, 1) < 0)
		return;

	if (force || (buf & (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) ==
	    (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) {
		buf = TPM_ACCESS_ACTIVE_LOCALITY;
		iic_tpm_write(TPM_ACCESS(loc), &buf, 1);
	}
}
Beispiel #4
0
static void tpm_tis_i2c_release_locality(struct udevice *dev, int loc,
					 int force)
{
	const u8 mask = TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID;
	u8 buf;

	if (tpm_tis_i2c_read(dev, TPM_ACCESS(loc), &buf, 1) < 0)
		return;

	if (force || (buf & mask) == mask) {
		buf = TPM_ACCESS_ACTIVE_LOCALITY;
		tpm_tis_i2c_write(dev, TPM_ACCESS(loc), &buf, 1);
	}
}
Beispiel #5
0
int tpm_tis_request_locality(struct tpm_chip* tpm, int l) {

   s_time_t stop;
   /*Make sure locality is valid */
   if(!locality_enabled(tpm, l)) {
      printk("tpm_tis_change_locality() Tried to change to locality %d, but it is disabled or invalid!\n", l);
      return -1;
   }
   /* Check if we already have the current locality */
   if(check_locality(tpm, l) >= 0) {
      return tpm->locality = l;
   }
   /* Set the new locality*/
   iowrite8(TPM_ACCESS(tpm, l), TPM_ACCESS_REQUEST_USE);

   if(tpm->irq) {
      /* Wait for interrupt */
      wait_event_deadline(tpm->int_queue, (check_locality(tpm, l) >= 0), NOW() + tpm->timeout_a);

      /* FIXME: Handle timeout event, should return error in that case */
      return l;
   } else {
      /* Wait for burstcount */
      stop = NOW() + tpm->timeout_a;
      do {
	 if(check_locality(tpm, l) >= 0) {
	    return tpm->locality = l;
	 }
	 msleep(TPM_TIMEOUT);
      } while(NOW() < stop);
   }

   printk("REQ LOCALITY FAILURE\n");
   return -1;
}
Beispiel #6
0
static int check_locality(struct tpm_chip* tpm, int l) {
   if(locality_enabled(tpm, l) && (ioread8(TPM_ACCESS(tpm, l)) &
	    (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
	 (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) {
      return l;
   }
   return -1;
}
Beispiel #7
0
static int check_locality(struct tpm_chip *chip, int loc)
{
	u8 buf;
	int rc;

	rc = iic_tpm_read(TPM_ACCESS(loc), &buf, 1);
	if (rc < 0)
		return rc;

	if ((buf & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
	    (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) {
		chip->vendor.locality = loc;
		return loc;
	}

	return -EIO;
}
Beispiel #8
0
/*
 * Cr50 processes reset requests asynchronously and consceivably could be busy
 * executing a long command and not reacting to the reset pulse for a while.
 *
 * This function will make sure that the AP does not proceed with boot until
 * TPM finished reset processing.
 */
static int process_reset(struct tpm_chip *chip)
{
	struct stopwatch sw;
	int rv = 0;
	uint8_t access;

	/*
	 * Locality is released by TPM reset.
	 *
	 * If locality is taken at this point, this could be due to the fact
	 * that the TPM is performing a long operation and has not processed
	 * reset request yet. We'll wait up to CR50_TIMEOUT_INIT_MS and see if
	 * it releases locality when reset is processed.
	 */
	stopwatch_init_msecs_expire(&sw, CR50_TIMEOUT_INIT_MS);
	do {
		const uint8_t mask =
			TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY;

		rv = cr50_i2c_read(chip, TPM_ACCESS(0),
				   &access, sizeof(access));
		if (rv || ((access & mask) == mask)) {
			/*
			 * Don't bombard the chip with traffic, let it keep
			 * processing the command.
			 */
			mdelay(2);
			continue;
		}

		printk(BIOS_INFO, "TPM ready after %ld ms\n",
		       stopwatch_duration_msecs(&sw));

		return 0;
	} while (!stopwatch_expired(&sw));

	if (rv)
		printk(BIOS_ERR, "Failed to read TPM\n");
	else
		printk(BIOS_ERR,
			"TPM failed to reset after %ld ms, status: %#x\n",
			stopwatch_duration_msecs(&sw), access);

	return -1;
}
Beispiel #9
0
static int tpm_tis_i2c_check_locality(struct udevice *dev, int loc)
{
	const u8 mask = TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID;
	struct tpm_chip *chip = dev_get_priv(dev);
	u8 buf;
	int rc;

	rc = tpm_tis_i2c_read(dev, TPM_ACCESS(loc), &buf, 1);
	if (rc < 0)
		return rc;

	if ((buf & mask) == mask) {
		chip->locality = loc;
		return loc;
	}

	return -ENOENT;
}
Beispiel #10
0
static int request_locality(struct tpm_chip *chip, int loc)
{
	unsigned long stop;
	u8 buf = TPM_ACCESS_REQUEST_USE;

	if (check_locality(chip, loc) >= 0)
		return loc;

	iic_tpm_write(TPM_ACCESS(loc), &buf, 1);

	/* wait for burstcount */
	stop = jiffies + chip->vendor.timeout_a;
	do {
		if (check_locality(chip, loc) >= 0)
			return loc;
		usleep_range(TPM_TIMEOUT_US_LOW, TPM_TIMEOUT_US_HI);
	} while (time_before(jiffies, stop));

	return -ETIME;
}
Beispiel #11
0
static int tpm_tis_i2c_request_locality(struct udevice *dev, int loc)
{
	struct tpm_chip *chip = dev_get_priv(dev);
	unsigned long start, stop;
	u8 buf = TPM_ACCESS_REQUEST_USE;
	int rc;

	rc = tpm_tis_i2c_check_locality(dev, loc);
	if (rc >= 0) {
		debug("%s: Already have locality\n", __func__);
		return loc;  /* We already have the locality */
	} else if (rc != -ENOENT) {
		debug("%s: Failed to get locality: %d\n", __func__, rc);
		return rc;
	}

	rc = tpm_tis_i2c_write(dev, TPM_ACCESS(loc), &buf, 1);
	if (rc) {
		debug("%s: Failed to write to TPM: %d\n", __func__, rc);
		return rc;
	}

	/* Wait for burstcount */
	start = get_timer(0);
	stop = chip->timeout_a;
	do {
		rc = tpm_tis_i2c_check_locality(dev, loc);
		if (rc >= 0) {
			debug("%s: Have locality\n", __func__);
			return loc;
		} else if (rc != -ENOENT) {
			debug("%s: Failed to get locality: %d\n", __func__, rc);
			return rc;
		}
		mdelay(TPM_TIMEOUT_MS);
	} while (get_timer(start) < stop);
	debug("%s: Timeout getting locality: %d\n", __func__, rc);

	return rc;
}