Commit fd0186ce authored by Lucas De Marchi's avatar Lucas De Marchi

drm/i915/bios: do not discard address space

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: default avatarLucas De Marchi <lucas.demarchi@intel.com>
Reviewed-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20191126225110.8127-2-lucas.demarchi@intel.com
parent d5746bf2
...@@ -1925,28 +1925,52 @@ bool intel_bios_is_valid_vbt(const void *buf, size_t size) ...@@ -1925,28 +1925,52 @@ bool intel_bios_is_valid_vbt(const void *buf, size_t size)
return vbt; 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; size_t i;
/* Scour memory looking for the VBT signature. */ /* Scour memory looking for the VBT signature. */
for (i = 0; i + 4 < size; i++) { for (i = 0; i + 4 < size; i++) {
void *vbt;
if (ioread32(oprom + i) != *((const u32 *)"$VBT")) if (ioread32(oprom + i) != *((const u32 *)"$VBT"))
continue; continue;
/* p = oprom + i;
* This is the one place where we explicitly discard the address size -= i;
* space (__iomem) of the BIOS/VBT.
*/
vbt = (void __force *)oprom + i;
if (intel_bios_is_valid_vbt(vbt, size - i))
return vbt;
break; 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; return NULL;
} }
...@@ -1982,7 +2006,7 @@ void intel_bios_init(struct drm_i915_private *dev_priv) ...@@ -1982,7 +2006,7 @@ void intel_bios_init(struct drm_i915_private *dev_priv)
if (!oprom) if (!oprom)
goto out; goto out;
vbt = find_vbt(oprom, size); vbt = copy_vbt(oprom, size);
if (!vbt) if (!vbt)
goto out; goto out;
...@@ -2020,6 +2044,9 @@ void intel_bios_init(struct drm_i915_private *dev_priv) ...@@ -2020,6 +2044,9 @@ void intel_bios_init(struct drm_i915_private *dev_priv)
if (oprom) if (oprom)
pci_unmap_rom(pdev, oprom); pci_unmap_rom(pdev, oprom);
if (vbt != dev_priv->opregion.vbt)
kfree(vbt);
} }
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment