// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2004 IBM Corporation * Copyright (C) 2014 Intel Corporation * * Authors: * Jarkko Sakkinen <[email protected]> * Leendert van Doorn <[email protected]> * Dave Safford <[email protected]> * Reiner Sailer <[email protected]> * Kylene Hall <[email protected]> * * Maintained by: <[email protected]> * * TPM chip management routines. */ #include <linux/poll.h> #include <linux/slab.h> #include <linux/mutex.h> #include <linux/spinlock.h> #include <linux/freezer.h> #include <linux/major.h> #include <linux/tpm_eventlog.h> #include <linux/hw_random.h> #include "tpm.h" DEFINE_IDR(…); static DEFINE_MUTEX(idr_lock); const struct class tpm_class = …; const struct class tpmrm_class = …; dev_t tpm_devt; static int tpm_request_locality(struct tpm_chip *chip) { … } static void tpm_relinquish_locality(struct tpm_chip *chip) { … } static int tpm_cmd_ready(struct tpm_chip *chip) { … } static int tpm_go_idle(struct tpm_chip *chip) { … } static void tpm_clk_enable(struct tpm_chip *chip) { … } static void tpm_clk_disable(struct tpm_chip *chip) { … } /** * 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) { … } EXPORT_SYMBOL_GPL(…); /** * 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) { … } EXPORT_SYMBOL_GPL(…); /** * 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) { … } EXPORT_SYMBOL_GPL(…); /** * 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) { … } EXPORT_SYMBOL_GPL(…); /** * tpm_default_chip() - find a TPM chip and get a reference to it */ struct tpm_chip *tpm_default_chip(void) { … } EXPORT_SYMBOL_GPL(…); /** * 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) { … } /** * 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. */ static void tpm_dev_release(struct device *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) { … } /** * 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, const struct tpm_class_ops *ops) { … } EXPORT_SYMBOL_GPL(…); static void tpm_put_device(void *dev) { … } /** * 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, const struct tpm_class_ops *ops) { … } EXPORT_SYMBOL_GPL(…); static int tpm_add_char_device(struct tpm_chip *chip) { … } static void tpm_del_char_device(struct tpm_chip *chip) { … } static void tpm_del_legacy_sysfs(struct tpm_chip *chip) { … } /* 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. */ static int tpm_add_legacy_sysfs(struct tpm_chip *chip) { … } static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait) { … } static bool tpm_is_hwrng_enabled(struct tpm_chip *chip) { … } static int tpm_add_hwrng(struct tpm_chip *chip) { … } static int tpm_get_pcr_allocation(struct tpm_chip *chip) { … } /* * 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) { … } EXPORT_SYMBOL_GPL(…); /* * 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) { … } EXPORT_SYMBOL_GPL(…); /* * 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) { … } EXPORT_SYMBOL_GPL(…);