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
[email protected]
https://lists.sourceforge.net/lists/listinfo/tpmdd-devel