On Thu, Feb 16, 2017 at 06:40:02PM +0000, Davide Guerri wrote: > Sorry I missed 1 line: > > [20417.678952] ACPI resource is [mem 0xfed40000-0xfed4087f flags 0x200]
The BIOS is broken.. That range declared in the ACPI is too small Or the cmd_size is too big: > [20417.678990] map request is is [mem 0xfed40080-0xfed40fff flags 0x200] I have no idea which. If we trust the ACPI table then the cmd_size is 2047 bytes If we trust the register then it is 3967.. Try this? diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c index a7c870af916c3d..2d16cc4aa0f43b 100644 --- a/drivers/char/tpm/tpm_crb.c +++ b/drivers/char/tpm/tpm_crb.c @@ -233,6 +233,8 @@ static void __iomem *crb_map_res(struct device *dev, struct crb_priv *priv, .flags = IORESOURCE_MEM, }; + printk("map request is is %pr\n",&new_res); + /* Detect a 64 bit address on a 32 bit system */ if (start != new_res.start) return (void __iomem *) ERR_PTR(-EINVAL); @@ -243,6 +245,26 @@ static void __iomem *crb_map_res(struct device *dev, struct crb_priv *priv, return priv->iobase + (new_res.start - io_res->start); } +/* + * Work around broken BIOSs that return inconsistent values from the ACPI + * region vs the registers. Trust the ACPI region. + */ +static u64 crb_clamp_cmd_size(struct device *dev, struct resource *io_res, + u64 start, u64 size) +{ + if (io_res->start > start || io_res->end < start) + return size; + + if (start + size - 1 <= io_res->end) + return size; + + dev_err(dev, + FW_BUG "ACPI region does not cover the entire command/response buffer. %pr vs %llx %llx\n", + io_res, start, size); + + return io_res->end - start + 1; +} + static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, struct acpi_table_tpm2 *buf) { @@ -267,6 +289,8 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, return -EINVAL; } + printk("ACPI resource is %pr\n",&io_res); + priv->iobase = devm_ioremap_resource(dev, &io_res); if (IS_ERR(priv->iobase)) return PTR_ERR(priv->iobase); @@ -278,14 +302,16 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, cmd_pa = ((u64) ioread32(&priv->cca->cmd_pa_high) << 32) | (u64) ioread32(&priv->cca->cmd_pa_low); - cmd_size = ioread32(&priv->cca->cmd_size); + cmd_size = crb_clamp_cmd_size(dev, &io_res, cmd_pa, + ioread32(&priv->cca->cmd_size)); priv->cmd = crb_map_res(dev, priv, &io_res, cmd_pa, cmd_size); if (IS_ERR(priv->cmd)) return PTR_ERR(priv->cmd); memcpy_fromio(&rsp_pa, &priv->cca->rsp_pa, 8); rsp_pa = le64_to_cpu(rsp_pa); - rsp_size = ioread32(&priv->cca->rsp_size); + rsp_size = crb_clamp_cmd_size(dev, &io_res, rsp_pa, + ioread32(&priv->cca->rsp_size)); if (cmd_pa != rsp_pa) { priv->rsp = crb_map_res(dev, priv, &io_res, rsp_pa, rsp_size); ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot _______________________________________________ tpmdd-devel mailing list tpmdd-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/tpmdd-devel