staticint tpm_cmd_ready(struct tpm_chip *chip)
{ if (!chip->ops->cmd_ready) return 0;
return chip->ops->cmd_ready(chip);
}
staticint tpm_go_idle(struct tpm_chip *chip)
{ if (!chip->ops->go_idle) return 0;
return chip->ops->go_idle(chip);
}
staticvoid tpm_clk_enable(struct tpm_chip *chip)
{ if (chip->ops->clk_enable)
chip->ops->clk_enable(chip, true);
}
staticvoid tpm_clk_disable(struct tpm_chip *chip)
{ if (chip->ops->clk_enable)
chip->ops->clk_enable(chip, false);
}
/** * tpm_chip_start() - power on the TPM * @chip: a TPM chip to use * * Return: * * The response length - OK * * -errno - A system error
*/ int tpm_chip_start(struct tpm_chip *chip)
{ int ret;
tpm_clk_enable(chip);
if (chip->locality == -1) {
ret = tpm_request_locality(chip); if (ret) {
tpm_clk_disable(chip); return ret;
}
}
ret = tpm_cmd_ready(chip); if (ret) {
tpm_relinquish_locality(chip);
tpm_clk_disable(chip); return ret;
}
return 0;
}
EXPORT_SYMBOL_GPL(tpm_chip_start);
/** * tpm_chip_stop() - power off the TPM * @chip: a TPM chip to use * * Return: * * The response length - OK * * -errno - A system error
*/ void tpm_chip_stop(struct tpm_chip *chip)
{
tpm_go_idle(chip);
tpm_relinquish_locality(chip);
tpm_clk_disable(chip);
}
EXPORT_SYMBOL_GPL(tpm_chip_stop);
/** * tpm_try_get_ops() - Get a ref to the tpm_chip * @chip: Chip to ref * * The caller must already have some kind of locking to ensure that chip is * valid. This function will lock the chip so that the ops member can be * accessed safely. The locking prevents tpm_chip_unregister from * completing, so it should not be held for long periods. * * Returns -ERRNO if the chip could not be got.
*/ int tpm_try_get_ops(struct tpm_chip *chip)
{ int rc = -EIO;
if (chip->flags & TPM_CHIP_FLAG_DISABLE) return rc;
get_device(&chip->dev);
down_read(&chip->ops_sem); if (!chip->ops) goto out_ops;
mutex_lock(&chip->tpm_mutex);
/* tmp_chip_start may issue IO that is denied while suspended */ if (chip->flags & TPM_CHIP_FLAG_SUSPENDED) goto out_lock;
/** * tpm_put_ops() - Release a ref to the tpm_chip * @chip: Chip to put * * This is the opposite pair to tpm_try_get_ops(). After this returns chip may * be kfree'd.
*/ void tpm_put_ops(struct tpm_chip *chip)
{
tpm_chip_stop(chip);
mutex_unlock(&chip->tpm_mutex);
up_read(&chip->ops_sem);
put_device(&chip->dev);
}
EXPORT_SYMBOL_GPL(tpm_put_ops);
/** * tpm_default_chip() - find a TPM chip and get a reference to it
*/ struct tpm_chip *tpm_default_chip(void)
{ struct tpm_chip *chip, *res = NULL; int chip_num = 0; int chip_prev;
mutex_lock(&idr_lock);
do {
chip_prev = chip_num;
chip = idr_get_next(&dev_nums_idr, &chip_num); if (chip) {
get_device(&chip->dev);
res = chip; break;
}
} while (chip_prev != chip_num);
/** * tpm_find_get_ops() - find and reserve a TPM chip * @chip: a &struct tpm_chip instance, %NULL for the default chip * * Finds a TPM chip and reserves its class device and operations. The chip must * be released with tpm_put_ops() after use. * This function is for internal use only. It supports existing TPM callers * by accepting NULL, but those callers should be converted to pass in a chip * directly. * * Return: * A reserved &struct tpm_chip instance. * %NULL if a chip is not found. * %NULL if the chip is not available.
*/ struct tpm_chip *tpm_find_get_ops(struct tpm_chip *chip)
{ int rc;
if (chip) { if (!tpm_try_get_ops(chip)) return chip; return NULL;
}
chip = tpm_default_chip(); if (!chip) return NULL;
rc = tpm_try_get_ops(chip); /* release additional reference we got from tpm_default_chip() */
put_device(&chip->dev); if (rc) return NULL; return chip;
}
/** * tpm_dev_release() - free chip memory and the device number * @dev: the character device for the TPM chip * * This is used as the release function for the character device.
*/ staticvoid tpm_dev_release(struct device *dev)
{ struct tpm_chip *chip = container_of(dev, struct tpm_chip, dev);
/** * tpm_class_shutdown() - prepare the TPM device for loss of power. * @dev: device to which the chip is associated. * * Issues a TPM2_Shutdown command prior to loss of power, as required by the * TPM 2.0 spec. Then, calls bus- and device- specific shutdown code. * * Return: always 0 (i.e. success)
*/ int tpm_class_shutdown(struct device *dev)
{ struct tpm_chip *chip = container_of(dev, struct tpm_chip, dev);
down_write(&chip->ops_sem); if (chip->flags & TPM_CHIP_FLAG_TPM2) { if (!tpm_chip_start(chip)) {
tpm2_end_auth_session(chip);
tpm2_shutdown(chip, TPM2_SU_CLEAR);
tpm_chip_stop(chip);
}
}
chip->ops = NULL;
up_write(&chip->ops_sem);
return 0;
}
/** * tpm_chip_alloc() - allocate a new struct tpm_chip instance * @pdev: device to which the chip is associated * At this point pdev mst be initialized, but does not have to * be registered * @ops: struct tpm_class_ops instance * * Allocates a new struct tpm_chip instance and assigns a free * device number for it. Must be paired with put_device(&chip->dev).
*/ struct tpm_chip *tpm_chip_alloc(struct device *pdev, conststruct tpm_class_ops *ops)
{ struct tpm_chip *chip; int rc;
chip = kzalloc(sizeof(*chip), GFP_KERNEL); if (chip == NULL) return ERR_PTR(-ENOMEM);
/** * tpmm_chip_alloc() - allocate a new struct tpm_chip instance * @pdev: parent device to which the chip is associated * @ops: struct tpm_class_ops instance * * Same as tpm_chip_alloc except devm is used to do the put_device
*/ struct tpm_chip *tpmm_chip_alloc(struct device *pdev, conststruct tpm_class_ops *ops)
{ struct tpm_chip *chip; int rc;
chip = tpm_chip_alloc(pdev, ops); if (IS_ERR(chip)) return chip;
rc = devm_add_action_or_reset(pdev,
tpm_put_device,
&chip->dev); if (rc) return ERR_PTR(rc);
/* Make the chip unavailable. */
mutex_lock(&idr_lock);
idr_replace(&dev_nums_idr, NULL, chip->dev_num);
mutex_unlock(&idr_lock);
/* Make the driver uncallable. */
down_write(&chip->ops_sem);
/* * Check if chip->ops is still valid: In case that the controller * drivers shutdown handler unregisters the controller in its * shutdown handler we are called twice and chip->ops to NULL.
*/ if (chip->ops) { if (chip->flags & TPM_CHIP_FLAG_TPM2) { if (!tpm_chip_start(chip)) {
tpm2_shutdown(chip, TPM2_SU_CLEAR);
tpm_chip_stop(chip);
}
}
chip->ops = NULL;
}
up_write(&chip->ops_sem);
}
for (i = chip->groups[0]->attrs; *i != NULL; ++i)
sysfs_remove_link(&chip->dev.parent->kobj, (*i)->name);
}
/* For compatibility with legacy sysfs paths we provide symlinks from the * parent dev directory to selected names within the tpm chip directory. Old * kernel versions created these files directly under the parent.
*/ staticint tpm_add_legacy_sysfs(struct tpm_chip *chip)
{ struct attribute **i; int rc;
if (chip->flags & (TPM_CHIP_FLAG_TPM2 | TPM_CHIP_FLAG_VIRTUAL) ||
tpm_is_firmware_upgrade(chip)) return 0;
/* * tpm_chip_bootstrap() - Boostrap TPM chip after power on * @chip: TPM chip to use. * * Initialize TPM chip after power on. This a one-shot function: subsequent * calls will have no effect.
*/ int tpm_chip_bootstrap(struct tpm_chip *chip)
{ int rc;
if (chip->flags & TPM_CHIP_FLAG_BOOTSTRAPPED) return 0;
/* * tpm_chip_register() - create a character device for the TPM chip * @chip: TPM chip to use. * * Creates a character device for the TPM chip and adds sysfs attributes for * the device. As the last step this function adds the chip to the list of TPM * chips available for in-kernel use. * * This function should be only called after the chip initialization is * complete.
*/ int tpm_chip_register(struct tpm_chip *chip)
{ int rc;
rc = tpm_chip_bootstrap(chip); if (rc) return rc;
tpm_sysfs_add_device(chip);
tpm_bios_log_setup(chip);
tpm_add_ppi(chip);
rc = tpm_add_hwrng(chip); if (rc) goto out_ppi;
rc = tpm_add_char_device(chip); if (rc) goto out_hwrng;
rc = tpm_add_legacy_sysfs(chip); if (rc) {
tpm_chip_unregister(chip); return rc;
}
return 0;
out_hwrng: if (tpm_is_hwrng_enabled(chip))
hwrng_unregister(&chip->hwrng);
out_ppi:
tpm_bios_log_teardown(chip);
/* * tpm_chip_unregister() - release the TPM driver * @chip: TPM chip to use. * * Takes the chip first away from the list of available TPM chips and then * cleans up all the resources reserved by tpm_chip_register(). * * Once this function returns the driver call backs in 'op's will not be * running and will no longer start. * * NOTE: This function should be only called before deinitializing chip * resources.
*/ void tpm_chip_unregister(struct tpm_chip *chip)
{ #ifdef CONFIG_TCG_TPM2_HMAC int rc;
rc = tpm_try_get_ops(chip); if (!rc) {
tpm2_end_auth_session(chip);
tpm_put_ops(chip);
} #endif
tpm_del_legacy_sysfs(chip); if (tpm_is_hwrng_enabled(chip))
hwrng_unregister(&chip->hwrng);
tpm_bios_log_teardown(chip); if (chip->flags & TPM_CHIP_FLAG_TPM2 && !tpm_is_firmware_upgrade(chip))
tpm_devs_remove(chip);
tpm_del_char_device(chip);
}
EXPORT_SYMBOL_GPL(tpm_chip_unregister);
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.