mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-03 19:26:01 -04:00
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: Lucas De Marchi <lucas.demarchi@intel.com> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20191126225110.8127-2-lucas.demarchi@intel.com
This commit is contained in:
@@ -1925,28 +1925,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;
|
||||
}
|
||||
|
||||
@@ -1982,7 +2006,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;
|
||||
|
||||
@@ -2020,6 +2044,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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user