uterm: fbdev: add udlfb workaround

udlfb incorrectly reports framebuffer sizes. That is, if we request a
framebuffer twice the size as the real framebuffer for double-bufferring,
it will accept these values and report success. We can even map this
virtual framebuffer successfully! However, the memory that is internally
allocated is only the real smaller framebuffer and we will get segfaults.
This might even leak internal kernel memory so we should fix this on
kernel-side as soon as possible.

Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
This commit is contained in:
David Herrmann 2012-08-11 11:32:55 +02:00
parent e5dfe1164d
commit faa12b6a61

View File

@ -116,6 +116,17 @@ static int display_activate_force(struct uterm_display *disp,
log_info("activating display %s to %ux%u %u bpp", disp->fbdev.node,
vinfo->xres, vinfo->yres, vinfo->bits_per_pixel);
disp->flags |= DISPLAY_DBUF;
/* udlfb is broken as it reports the sizes of the virtual framebuffer
* (even mmap() accepts it) but the actual size that we can access
* without segfaults is the _real_ framebuffer. Therefore, disable
* double-buffering for it.
* TODO: fix this kernel-side! */
if (!strcmp(finfo->id, "udlfb")) {
disp->flags &= ~DISPLAY_DBUF;
vinfo->yres_virtual = vinfo->yres;
}
ret = ioctl(disp->fbdev.fd, FBIOPUT_VSCREENINFO, vinfo);
if (ret) {
@ -123,16 +134,16 @@ static int display_activate_force(struct uterm_display *disp,
vinfo->yres_virtual = vinfo->yres;
ret = ioctl(disp->fbdev.fd, FBIOPUT_VSCREENINFO, vinfo);
if (ret) {
log_err("cannot set vinfo (%d): %m",
errno);
log_debug("cannot reset fb offsets (%d): %m", errno);
return -EFAULT;
}
log_debug("disabling double buffering");
} else {
disp->flags |= DISPLAY_DBUF;
log_debug("enabling double buffering");
}
if (disp->flags & DISPLAY_DBUF)
log_debug("enabling double buffering");
else
log_debug("disabling double buffering");
ret = refresh_info(disp);
if (ret)
return ret;