mirror of
				https://xff.cz/git/u-boot/
				synced 2025-10-31 18:35:42 +01:00 
			
		
		
		
	tpm_tis_remove() leads to calling tpm_tis_ready() with the IO region unmapped and chip->locality == -1 (locality released). This leads to a crash in mmio_write_bytes(). The patch implements these changes: tpm_tis_remove(): Unmap the IO region after calling tpm_tis_cleanup(). tpm_tis_cleanup(): Request locality before IO output and releasing locality. Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com> Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org> Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
		
			
				
	
	
		
			161 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			161 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| // SPDX-License-Identifier: GPL-2.0
 | |
| /*
 | |
|  * driver for mmio TCG/TIS TPM (trusted platform module).
 | |
|  *
 | |
|  * Specifications at www.trustedcomputinggroup.org
 | |
|  */
 | |
| 
 | |
| #include <common.h>
 | |
| #include <dm.h>
 | |
| #include <log.h>
 | |
| #include <tpm-v2.h>
 | |
| #include <linux/bitops.h>
 | |
| #include <linux/compiler.h>
 | |
| #include <linux/delay.h>
 | |
| #include <linux/errno.h>
 | |
| #include <linux/types.h>
 | |
| #include <linux/io.h>
 | |
| #include <linux/unaligned/be_byteshift.h>
 | |
| #include "tpm_tis.h"
 | |
| #include "tpm_internal.h"
 | |
| 
 | |
| /**
 | |
|  * struct tpm_tis_chip_data - Information about an MMIO TPM
 | |
|  * @pcr_count:          Number of PCR per bank
 | |
|  * @pcr_select_min:	Minimum size in bytes of the pcrSelect array
 | |
|  * @iobase:		Base address
 | |
|  */
 | |
| struct tpm_tis_chip_data {
 | |
| 	unsigned int pcr_count;
 | |
| 	unsigned int pcr_select_min;
 | |
| 	void __iomem *iobase;
 | |
| };
 | |
| 
 | |
| static int mmio_read_bytes(struct udevice *dev, u32 addr, u16 len,
 | |
| 			   u8 *result)
 | |
| {
 | |
| 	struct tpm_tis_chip_data *drv_data = (void *)dev_get_driver_data(dev);
 | |
| 
 | |
| 	while (len--)
 | |
| 		*result++ = ioread8(drv_data->iobase + addr);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int mmio_write_bytes(struct udevice *dev, u32 addr, u16 len,
 | |
| 			    const u8 *value)
 | |
| {
 | |
| 	struct tpm_tis_chip_data *drv_data = (void *)dev_get_driver_data(dev);
 | |
| 
 | |
| 	while (len--)
 | |
| 		iowrite8(*value++, drv_data->iobase + addr);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int mmio_read32(struct udevice *dev, u32 addr, u32 *result)
 | |
| {
 | |
| 	struct tpm_tis_chip_data *drv_data = (void *)dev_get_driver_data(dev);
 | |
| 
 | |
| 	*result = ioread32(drv_data->iobase + addr);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int mmio_write32(struct udevice *dev, u32 addr, u32 value)
 | |
| {
 | |
| 	struct tpm_tis_chip_data *drv_data = (void *)dev_get_driver_data(dev);
 | |
| 
 | |
| 	iowrite32(value, drv_data->iobase + addr);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static struct tpm_tis_phy_ops phy_ops = {
 | |
| 	.read_bytes = mmio_read_bytes,
 | |
| 	.write_bytes = mmio_write_bytes,
 | |
| 	.read32 = mmio_read32,
 | |
| 	.write32 = mmio_write32,
 | |
| };
 | |
| 
 | |
| static int tpm_tis_probe(struct udevice *dev)
 | |
| {
 | |
| 	struct tpm_tis_chip_data *drv_data = (void *)dev_get_driver_data(dev);
 | |
| 	struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
 | |
| 	int ret = 0;
 | |
| 	fdt_addr_t ioaddr;
 | |
| 	u64 sz;
 | |
| 
 | |
| 	ioaddr = dev_read_addr(dev);
 | |
| 	if (ioaddr == FDT_ADDR_T_NONE)
 | |
| 		return log_msg_ret("ioaddr", -EINVAL);
 | |
| 
 | |
| 	ret = dev_read_u64(dev, "reg", &sz);
 | |
| 	if (ret)
 | |
| 		return -EINVAL;
 | |
| 
 | |
| 	drv_data->iobase = ioremap(ioaddr, sz);
 | |
| 	tpm_tis_ops_register(dev, &phy_ops);
 | |
| 	ret = tpm_tis_init(dev);
 | |
| 	if (ret)
 | |
| 		goto iounmap;
 | |
| 
 | |
| 	priv->pcr_count = drv_data->pcr_count;
 | |
| 	priv->pcr_select_min = drv_data->pcr_select_min;
 | |
| 	/*
 | |
| 	 * Although the driver probably works with a TPMv1 our Kconfig
 | |
| 	 * limits the driver to TPMv2 only
 | |
| 	 */
 | |
| 	priv->version = TPM_V2;
 | |
| 
 | |
| 	return ret;
 | |
| iounmap:
 | |
| 	iounmap(drv_data->iobase);
 | |
| 
 | |
| 	return -EINVAL;
 | |
| }
 | |
| 
 | |
| static int tpm_tis_remove(struct udevice *dev)
 | |
| {
 | |
| 	struct tpm_tis_chip_data *drv_data = (void *)dev_get_driver_data(dev);
 | |
| 	int ret;
 | |
| 
 | |
| 	ret = tpm_tis_cleanup(dev);
 | |
| 
 | |
| 	iounmap(drv_data->iobase);
 | |
| 
 | |
| 	return ret;
 | |
| }
 | |
| 
 | |
| static const struct tpm_ops tpm_tis_ops = {
 | |
| 	.open		= tpm_tis_open,
 | |
| 	.close		= tpm_tis_close,
 | |
| 	.get_desc	= tpm_tis_get_desc,
 | |
| 	.send		= tpm_tis_send,
 | |
| 	.recv		= tpm_tis_recv,
 | |
| 	.cleanup	= tpm_tis_cleanup,
 | |
| };
 | |
| 
 | |
| static const struct tpm_tis_chip_data tpm_tis_std_chip_data = {
 | |
| 	.pcr_count = 24,
 | |
| 	.pcr_select_min = 3,
 | |
| };
 | |
| 
 | |
| static const struct udevice_id tpm_tis_ids[] = {
 | |
| 	{
 | |
| 		.compatible = "tcg,tpm-tis-mmio",
 | |
| 		.data = (ulong)&tpm_tis_std_chip_data,
 | |
| 	},
 | |
| 	{ }
 | |
| };
 | |
| 
 | |
| U_BOOT_DRIVER(tpm_tis_mmio) = {
 | |
| 	.name   = "tpm_tis_mmio",
 | |
| 	.id     = UCLASS_TPM,
 | |
| 	.of_match = tpm_tis_ids,
 | |
| 	.ops    = &tpm_tis_ops,
 | |
| 	.probe	= tpm_tis_probe,
 | |
| 	.remove	= tpm_tis_remove,
 | |
| 	.priv_auto	= sizeof(struct tpm_chip),
 | |
| };
 |