On Fri, Nov 08, 2019 at 01:13:53PM -0800, Lucas De Marchi wrote:
> 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)
> 
> Signed-off-by: Lucas De Marchi <lucas.demar...@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 c79781e1ccbf..c079febae9c8 100644
> --- a/drivers/gpu/drm/i915/display/intel_bios.c
> +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> @@ -1811,28 +1811,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 const 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;
>  }
>  
> @@ -1866,7 +1890,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;
>  
> @@ -1902,6 +1926,9 @@ void intel_bios_init(struct drm_i915_private *dev_priv)
>  
>       if (oprom)
>               pci_unmap_rom(pdev, oprom);

lgtm
Reviewed-by: Ville Syrjälä <ville.syrj...@linux.intel.com>

As a followup we could now move the rom map/unamp into copy_vbt() as
there's no longer any need to keep it mapped across the whole thing.

> +
> +     if (vbt != dev_priv->opregion.vbt)
> +             kfree(vbt);
>  }
>  
>  /**
> -- 
> 2.24.0

-- 
Ville Syrjälä
Intel
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to