[Intel-gfx] [PATCH 1/3] drm/i915/bios: do not discard address space
Lucas De Marchi
lucas.demarchi at intel.com
Wed Nov 20 23:46:06 UTC 2019
When we map the VBT through pci_map_rom() we may not be allowed
to simply discard the address space and go on reading the memory.
That doesn't work on my test system, but by dumping the rom via
sysfs I can can get the correct vbt. So change our find_vbt() to do
the same as done by pci_read_rom(), i.e. use memcpy_fromio().
v2: the just the minimal changes by not bothering with the unaligned io
reads: this can be done on top (from Ville and Jani)
v3: drop const in function return since now we are copying the vbt,
rather than just finding it
Signed-off-by: Lucas De Marchi <lucas.demarchi at intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
---
drivers/gpu/drm/i915/display/intel_bios.c | 51 +++++++++++++++++------
1 file changed, 39 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index f6a9a5ccb556..8bdfc1d55040 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -1896,28 +1896,52 @@ bool intel_bios_is_valid_vbt(const void *buf, size_t size)
return vbt;
}
-static const struct vbt_header *find_vbt(void __iomem *oprom, size_t size)
+static struct vbt_header *copy_vbt(void __iomem *oprom, size_t size)
{
+ void __iomem *p = NULL;
+ struct vbt_header *vbt;
+ u16 vbt_size;
size_t i;
/* Scour memory looking for the VBT signature. */
for (i = 0; i + 4 < size; i++) {
- void *vbt;
-
if (ioread32(oprom + i) != *((const u32 *)"$VBT"))
continue;
- /*
- * This is the one place where we explicitly discard the address
- * space (__iomem) of the BIOS/VBT.
- */
- vbt = (void __force *)oprom + i;
- if (intel_bios_is_valid_vbt(vbt, size - i))
- return vbt;
-
+ p = oprom + i;
+ size -= i;
break;
}
+ if (!p)
+ return NULL;
+
+ if (sizeof(struct vbt_header) > size) {
+ DRM_DEBUG_DRIVER("VBT header incomplete\n");
+ return NULL;
+ }
+
+ vbt_size = ioread16(p + offsetof(struct vbt_header, vbt_size));
+ if (vbt_size > size) {
+ DRM_DEBUG_DRIVER("VBT incomplete (vbt_size overflows)\n");
+ return NULL;
+ }
+
+ /* The rest will be validated by intel_bios_is_valid_vbt() */
+ vbt = kmalloc(vbt_size, GFP_KERNEL);
+ if (!vbt)
+ return NULL;
+
+ memcpy_fromio(vbt, p, vbt_size);
+
+ if (!intel_bios_is_valid_vbt(vbt, vbt_size))
+ goto err_free_vbt;
+
+ return vbt;
+
+err_free_vbt:
+ kfree(vbt);
+
return NULL;
}
@@ -1953,7 +1977,7 @@ void intel_bios_init(struct drm_i915_private *dev_priv)
if (!oprom)
goto out;
- vbt = find_vbt(oprom, size);
+ vbt = copy_vbt(oprom, size);
if (!vbt)
goto out;
@@ -1990,6 +2014,9 @@ void intel_bios_init(struct drm_i915_private *dev_priv)
if (oprom)
pci_unmap_rom(pdev, oprom);
+
+ if (vbt != dev_priv->opregion.vbt)
+ kfree(vbt);
}
/**
--
2.24.0
More information about the Intel-gfx
mailing list