Calling the validate_vbt before assiging the opregion vbt blob. Size of the VBT blob cant be more than 6KB when VBT is present in mailbox 4. Cc: Jani Nikula <jani.nikula@xxxxxxxxx> Signed-off-by: Deepak M <m.deepak@xxxxxxxxx> --- drivers/gpu/drm/i915/i915_drv.h | 3 +++ drivers/gpu/drm/i915/intel_bios.c | 43 +++++++++++++++++++---------------- drivers/gpu/drm/i915/intel_opregion.c | 31 +++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 135d32a..8cf8375 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3324,6 +3324,9 @@ intel_opregion_notify_adapter(struct drm_device *dev, pci_power_t state) } #endif +const struct vbt_header *validate_vbt(const void *_vbt, size_t size, + const char *source); + /* intel_acpi.c */ #ifdef CONFIG_ACPI extern void intel_register_dsm_handler(void); diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 6756a1c..57a77aa 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -1237,16 +1237,15 @@ static const struct dmi_system_id intel_no_opregion_vbt[] = { { } }; -static const struct bdb_header *validate_vbt(const void *base, +const struct vbt_header *validate_vbt(const void *_vbt, size_t size, - const void *_vbt, const char *source) { - size_t offset = _vbt - base; - const struct vbt_header *vbt = _vbt; + const struct vbt_header *vbt = (const struct vbt_header *)_vbt; const struct bdb_header *bdb; + size_t offset; - if (offset + sizeof(struct vbt_header) > size) { + if (sizeof(struct vbt_header) > size) { DRM_DEBUG_DRIVER("VBT header incomplete\n"); return NULL; } @@ -1256,26 +1255,26 @@ static const struct bdb_header *validate_vbt(const void *base, return NULL; } - offset += vbt->bdb_offset; + offset = vbt->bdb_offset; if (offset + sizeof(struct bdb_header) > size) { DRM_DEBUG_DRIVER("BDB header incomplete\n"); return NULL; } - bdb = base + offset; + bdb = (const void *)_vbt + offset; if (offset + bdb->bdb_size > size) { DRM_DEBUG_DRIVER("BDB incomplete\n"); return NULL; } DRM_DEBUG_KMS("Using VBT from %s: %20s\n", - source, vbt->signature); - return bdb; + source, vbt->signature); + return vbt; } -static const struct bdb_header *find_vbt(void __iomem *bios, size_t size) +static const struct vbt_header *find_vbt(void __iomem *bios, size_t size) { - const struct bdb_header *bdb = NULL; + const struct vbt_header *vbt = NULL; size_t i; /* Scour memory looking for the VBT signature. */ @@ -1289,12 +1288,12 @@ static const struct bdb_header *find_vbt(void __iomem *bios, size_t size) */ void *_bios = (void __force *) bios; - bdb = validate_vbt(_bios, size, _bios + i, "PCI ROM"); + vbt = validate_vbt(_bios + i, size - i, "PCI ROM"); break; } } - return bdb; + return vbt; } /** @@ -1311,6 +1310,7 @@ intel_parse_bios(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct pci_dev *pdev = dev->pdev; + const struct vbt_header *vbt = NULL; const struct bdb_header *bdb = NULL; u8 __iomem *bios = NULL; @@ -1319,23 +1319,26 @@ intel_parse_bios(struct drm_device *dev) init_vbt_defaults(dev_priv); - /* XXX Should this validation be moved to intel_opregion.c? */ - if (!dmi_check_system(intel_no_opregion_vbt) && dev_priv->opregion.vbt) - bdb = validate_vbt(dev_priv->opregion.header, OPREGION_SIZE, - dev_priv->opregion.vbt, "OpRegion"); + if (!dmi_check_system(intel_no_opregion_vbt) && + dev_priv->opregion.vbt) { + vbt = (const struct vbt_header *)dev_priv->opregion.vbt; + bdb = (const void *)dev_priv->opregion.vbt + vbt->bdb_offset; + } - if (bdb == NULL) { + if (vbt == NULL) { size_t size; bios = pci_map_rom(pdev, &size); if (!bios) return -1; - bdb = find_vbt(bios, size); - if (!bdb) { + vbt = find_vbt(bios, size); + if (!vbt) { pci_unmap_rom(pdev, bios); return -1; } + + bdb = (const void *)vbt + vbt->bdb_offset; } /* Grab useful general definitions */ diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index 43b7c3b..4a78282 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c @@ -48,6 +48,27 @@ #define OPREGION_VBT_OFFSET 0x400 #define OPREGION_ASLE_EXT_OFFSET 0x1C00 +#define MAILBOX_4_SIZE 0x1800 + +/* + * Opregion Structure: + * +-------------------------------+ + * | Mailbox1 : ACPI | + * | Offset : 0x100 | + * +-------------------------------+ + * | Mailbox2 : SWSCI | + * | Offset : 0x200 | + * +-------------------------------+ + * | Mailbox3 : ASLE | + * | Offset : 0x300 | + * +-------------------------------+ + * | Mailbox4 : VBT | + * | Offset : 0x400 | + * +-------------------------------+ + * | Mailbox5 : ASLE_EXT | + * | Offset : 0x1C00 | + * +-------------------------------+ +*/ #define OPREGION_SIGNATURE "IntelGraphicsMem" #define MBOX_ACPI (1<<0) #define MBOX_SWSCI (1<<1) @@ -910,6 +931,7 @@ int intel_opregion_setup(struct drm_device *dev) struct intel_opregion *opregion = &dev_priv->opregion; u32 asls, mboxes; char buf[sizeof(OPREGION_SIGNATURE)]; + const struct vbt_header *vbt = NULL; int err = 0; void *base; @@ -940,6 +962,15 @@ int intel_opregion_setup(struct drm_device *dev) err = -EINVAL; goto err_out; } + + vbt = validate_vbt(base + OPREGION_VBT_OFFSET, + MAILBOX_4_SIZE, "OpRegion"); + + if (vbt == NULL) { + err = -EINVAL; + goto err_out; + } + opregion->header = base; opregion->vbt = base + OPREGION_VBT_OFFSET; -- 1.9.1 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx