lkml.org 
[lkml]   [2011]   [Apr]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[34-longterm 072/209] efifb: check that the base address is plausible on pci systems
    Date
    From: Peter Jones <pjones@redhat.com>

    =====================================================================
    | This is a commit scheduled for the next v2.6.34 longterm release. |
    | If you see a problem with using this for longterm, please comment.|
    =====================================================================

    commit 85a00d9bbfb4704fbf368944b1cb9fed8f1598c5 upstream.

    Some Apple machines have identical DMI data but different memory
    configurations for the video. Given that, check that the address in our
    table is actually within the range of a PCI BAR on a VGA device in the
    machine.

    This also fixes up the return value from set_system(), which has always
    been wrong, but never resulted in bad behavior since there's only ever
    been one matching entry in the dmi table.

    The patch

    1) stops people's machines from crashing when we get their display wrong,
    which seems to be unfortunately inevitable,

    2) allows us to support identical dmi data with differing video memory
    configurations

    This also adds me as the efifb maintainer, since I've effectively been
    acting as such for quite some time.

    Signed-off-by: Peter Jones <pjones@redhat.com>
    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
    ---
    MAINTAINERS | 6 +++++
    drivers/video/efifb.c | 61 +++++++++++++++++++++++++++++++++++++++---------
    2 files changed, 55 insertions(+), 12 deletions(-)

    diff --git a/MAINTAINERS b/MAINTAINERS
    index d329b05..502b380 100644
    --- a/MAINTAINERS
    +++ b/MAINTAINERS
    @@ -2104,6 +2104,12 @@ W: http://acpi4asus.sf.net
    S: Maintained
    F: drivers/platform/x86/eeepc-laptop.c

    +EFIFB FRAMEBUFFER DRIVER
    +L: linux-fbdev@vger.kernel.org
    +M: Peter Jones <pjones@redhat.com>
    +S: Maintained
    +F: drivers/video/efifb.c
    +
    EFS FILESYSTEM
    W: http://aeschi.ch.eu.org/efs/
    S: Orphan
    diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c
    index ecf4055..e090f8e 100644
    --- a/drivers/video/efifb.c
    +++ b/drivers/video/efifb.c
    @@ -13,7 +13,7 @@
    #include <linux/platform_device.h>
    #include <linux/screen_info.h>
    #include <linux/dmi.h>
    -
    +#include <linux/pci.h>
    #include <video/vga.h>

    static struct fb_var_screeninfo efifb_defined __initdata = {
    @@ -116,7 +116,7 @@ static int set_system(const struct dmi_system_id *id)
    {
    struct efifb_dmi_info *info = id->driver_data;
    if (info->base == 0)
    - return -ENODEV;
    + return 0;

    printk(KERN_INFO "efifb: dmi detected %s - framebuffer at %p "
    "(%dx%d, stride %d)\n", id->ident,
    @@ -124,18 +124,55 @@ static int set_system(const struct dmi_system_id *id)
    info->stride);

    /* Trust the bootloader over the DMI tables */
    - if (screen_info.lfb_base == 0)
    + if (screen_info.lfb_base == 0) {
    +#if defined(CONFIG_PCI)
    + struct pci_dev *dev = NULL;
    + int found_bar = 0;
    +#endif
    screen_info.lfb_base = info->base;
    - if (screen_info.lfb_linelength == 0)
    - screen_info.lfb_linelength = info->stride;
    - if (screen_info.lfb_width == 0)
    - screen_info.lfb_width = info->width;
    - if (screen_info.lfb_height == 0)
    - screen_info.lfb_height = info->height;
    - if (screen_info.orig_video_isVGA == 0)
    - screen_info.orig_video_isVGA = VIDEO_TYPE_EFI;

    - return 0;
    +#if defined(CONFIG_PCI)
    + /* make sure that the address in the table is actually on a
    + * VGA device's PCI BAR */
    +
    + for_each_pci_dev(dev) {
    + int i;
    + if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
    + continue;
    + for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
    + resource_size_t start, end;
    +
    + start = pci_resource_start(dev, i);
    + if (start == 0)
    + break;
    + end = pci_resource_end(dev, i);
    + if (screen_info.lfb_base >= start &&
    + screen_info.lfb_base < end) {
    + found_bar = 1;
    + }
    + }
    + }
    + if (!found_bar)
    + screen_info.lfb_base = 0;
    +#endif
    + }
    + if (screen_info.lfb_base) {
    + if (screen_info.lfb_linelength == 0)
    + screen_info.lfb_linelength = info->stride;
    + if (screen_info.lfb_width == 0)
    + screen_info.lfb_width = info->width;
    + if (screen_info.lfb_height == 0)
    + screen_info.lfb_height = info->height;
    + if (screen_info.orig_video_isVGA == 0)
    + screen_info.orig_video_isVGA = VIDEO_TYPE_EFI;
    + } else {
    + screen_info.lfb_linelength = 0;
    + screen_info.lfb_width = 0;
    + screen_info.lfb_height = 0;
    + screen_info.orig_video_isVGA = 0;
    + return 0;
    + }
    + return 1;
    }

    static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green,
    --
    1.7.4.4


    \
     
     \ /
      Last update: 2011-04-14 19:55    [W:0.028 / U:183.324 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site