[PATCH] vesa: Prevent loading if we conflict with a previously loaded driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



vesa is presumed to be the generic hardware agnostic fallback framebuffer
driver for standard VGA that conflicts with the real drivers. Those
drivers already check and remove vesafb if it is previously loaded, but
in the reverse case where vesafb is loaded afterwards, the VESA driver
will proceed to clobber hardware state and corrupt the displays.

References: https://bugs.launchpad.net/ubuntu/+source/xserver-xorg-video-intel/+bug/1156077
Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx>
---
 drivers/video/fbmem.c  |   31 +++++++++++++++++++++++++++++++
 drivers/video/vesafb.c |   22 ++++++++++++++++++++++
 include/linux/fb.h     |    2 ++
 3 files changed, 55 insertions(+)

diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 7c25408..786cec8 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1722,6 +1722,37 @@ void remove_conflicting_framebuffers(struct apertures_struct *a,
 }
 EXPORT_SYMBOL(remove_conflicting_framebuffers);
 
+bool has_conflicting_framebuffer(struct apertures_struct *a, bool primary)
+{
+	bool ret = false;
+	int i;
+
+	mutex_lock(&registration_lock);
+
+	for (i = 0 ; i < FB_MAX; i++) {
+		struct apertures_struct *gen_aper;
+
+		if (!registered_fb[i])
+			continue;
+
+		if (!(registered_fb[i]->flags & FBINFO_MISC_FIRMWARE))
+			continue;
+
+		gen_aper = registered_fb[i]->apertures;
+		if (fb_do_apertures_overlap(gen_aper, a) ||
+		    (primary && gen_aper && gen_aper->count &&
+		     gen_aper->ranges[0].base == VGA_FB_PHYS)) {
+			ret = true;
+			break;
+		}
+	}
+
+	mutex_unlock(&registration_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(has_conflicting_framebuffer);
+
 /**
  *	register_framebuffer - registers a frame buffer device
  *	@fb_info: frame buffer info structure
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c
index 501b340..51adc4c1 100644
--- a/drivers/video/vesafb.c
+++ b/drivers/video/vesafb.c
@@ -226,6 +226,25 @@ static int __init vesafb_setup(char *options)
 	return 0;
 }
 
+static bool aperture_already_claimed(void)
+{
+	struct apertures_struct *ap;
+	bool ret;
+
+	ap = alloc_apertures(1);
+	if (!ap)
+		return true;
+
+	ap->ranges[0].base = screen_info.lfb_base;
+	ap->ranges[0].size = size_total;
+
+	ret = has_conflicting_framebuffer(ap, true);
+
+	kfree(ap);
+
+	return ret;
+}
+
 static int __init vesafb_probe(struct platform_device *dev)
 {
 	struct fb_info *info;
@@ -237,6 +256,9 @@ static int __init vesafb_probe(struct platform_device *dev)
 	if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB)
 		return -ENODEV;
 
+	if (aperture_already_claimed())
+		return -ENODEV;
+
 	vga_compat = (screen_info.capabilities & 2) ? 0 : 1;
 	vesafb_fix.smem_start = screen_info.lfb_base;
 	vesafb_defined.bits_per_pixel = screen_info.lfb_depth;
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 58b9860..7dfd964 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -611,6 +611,8 @@ extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf,
 extern int register_framebuffer(struct fb_info *fb_info);
 extern int unregister_framebuffer(struct fb_info *fb_info);
 extern int unlink_framebuffer(struct fb_info *fb_info);
+extern bool has_conflicting_framebuffer(struct apertures_struct *a,
+					bool primary);
 extern void remove_conflicting_framebuffers(struct apertures_struct *a,
 				const char *name, bool primary);
 extern int fb_prepare_logo(struct fb_info *fb_info, int rotate);
-- 
1.7.10.4

_______________________________________________
dri-devel mailing list
dri-devel@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/dri-devel


[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux