lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Wed, 25 Aug 2010 11:03:20 -0400
From:	Peter Jones <pjones@...hat.com>
To:	Colin Watson <cjwatson@...onical.com>
CC:	linux-fbdev@...r.kernel.org, linux-kernel@...r.kernel.org,
	Matthew Garrett <mjg@...hat.com>
Subject: Re: [PATCH] Add new linearfb driver

On 08/25/2010 10:11 AM, Colin Watson wrote:
> Split out linearfb from efifb so that boot loaders can program it as a
> simple linear framebuffer on non-EFI systems.  This is useful for boot
> loaders with their own graphics drivers, e.g. GRUB 2, since in some
> cases on x86 they can set up non-VESA modes and thus can't program
> vesafb.
> 
> efifb is reworked on top of this common code, and it should be possible
> to do the same with some other framebuffer drivers in future.
> 
> Signed-off-by: Colin Watson <cjwatson@...onical.com>
> Acked-by: Matthew Garrett <mjg@...hat.com>
> Cc: Peter Jones <pjones@...hat.com>

Looks reasonable to me.

Acked-by: Peter Jones <pjones@...hat.com>

> ---
>  drivers/video/Kconfig       |   17 ++-
>  drivers/video/Makefile      |    1 +
>  drivers/video/efifb.c       |  222 +----------------------------
>  drivers/video/linearfb.c    |  332 +++++++++++++++++++++++++++++++++++++++++++
>  include/linux/fb.h          |    8 +
>  include/linux/screen_info.h |    2 +
>  6 files changed, 364 insertions(+), 218 deletions(-)
>  create mode 100644 drivers/video/linearfb.c
> 
> diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
> index 59c51d9..a7735ec 100644
> --- a/drivers/video/Kconfig
> +++ b/drivers/video/Kconfig
> @@ -721,13 +721,24 @@ config FB_VESA
>  	  You will get a boot time penguin logo at no additional cost. Please
>  	  read <file:Documentation/fb/vesafb.txt>. If unsure, say Y.
>  
> -config FB_EFI
> -	bool "EFI-based Framebuffer Support"
> -	depends on (FB = y) && X86 && EFI
> +config FB_LINEAR
> +	bool "Simple linear framebuffer support"
> +	depends on FB
>  	select FB_CFB_FILLRECT
>  	select FB_CFB_COPYAREA
>  	select FB_CFB_IMAGEBLIT
>  	help
> +	  This is a simple linear frame buffer device driver. It has no
> +	  hardware-specific programming capability, but must be programmed
> +	  by the boot loader or by another frame buffer driver.
> +
> +	  If unsure, say N.
> +
> +config FB_EFI
> +	bool "EFI-based Framebuffer Support"
> +	depends on (FB = y) && X86 && EFI
> +	select FB_LINEAR
> +	help
>  	  This is the EFI frame buffer device driver. If the firmware on
>  	  your platform is EFI 1.10 or UEFI 2.0, select Y to add support for
>  	  using the EFI framebuffer as your console.
> diff --git a/drivers/video/Makefile b/drivers/video/Makefile
> index ddc2af2..ad74d3b 100644
> --- a/drivers/video/Makefile
> +++ b/drivers/video/Makefile
> @@ -133,6 +133,7 @@ obj-$(CONFIG_FB_MSM)              += msm/
>  obj-$(CONFIG_FB_NUC900)           += nuc900fb.o
>  
>  # Platform or fallback drivers go here
> +obj-$(CONFIG_FB_LINEAR)           += linearfb.o
>  obj-$(CONFIG_FB_UVESA)            += uvesafb.o
>  obj-$(CONFIG_FB_VESA)             += vesafb.o
>  obj-$(CONFIG_FB_EFI)              += efifb.o
> diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c
> index 4a56f46..72e5873 100644
> --- a/drivers/video/efifb.c
> +++ b/drivers/video/efifb.c
> @@ -16,24 +16,6 @@
>  
>  #include <video/vga.h>
>  
> -static struct fb_var_screeninfo efifb_defined __initdata = {
> -	.activate		= FB_ACTIVATE_NOW,
> -	.height			= -1,
> -	.width			= -1,
> -	.right_margin		= 32,
> -	.upper_margin		= 16,
> -	.lower_margin		= 4,
> -	.vsync_len		= 4,
> -	.vmode			= FB_VMODE_NONINTERLACED,
> -};
> -
> -static struct fb_fix_screeninfo efifb_fix __initdata = {
> -	.id			= "EFI VGA",
> -	.type			= FB_TYPE_PACKED_PIXELS,
> -	.accel			= FB_ACCEL_NONE,
> -	.visual			= FB_VISUAL_TRUECOLOR,
> -};
> -
>  enum {
>  	M_I17,		/* 17-Inch iMac */
>  	M_I20,		/* 20-Inch iMac */
> @@ -138,49 +120,6 @@ static int set_system(const struct dmi_system_id *id)
>  	return 0;
>  }
>  
> -static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green,
> -			   unsigned blue, unsigned transp,
> -			   struct fb_info *info)
> -{
> -	/*
> -	 *  Set a single color register. The values supplied are
> -	 *  already rounded down to the hardware's capabilities
> -	 *  (according to the entries in the `var' structure). Return
> -	 *  != 0 for invalid regno.
> -	 */
> -
> -	if (regno >= info->cmap.len)
> -		return 1;
> -
> -	if (regno < 16) {
> -		red   >>= 8;
> -		green >>= 8;
> -		blue  >>= 8;
> -		((u32 *)(info->pseudo_palette))[regno] =
> -			(red   << info->var.red.offset)   |
> -			(green << info->var.green.offset) |
> -			(blue  << info->var.blue.offset);
> -	}
> -	return 0;
> -}
> -
> -static void efifb_destroy(struct fb_info *info)
> -{
> -	if (info->screen_base)
> -		iounmap(info->screen_base);
> -	release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size);
> -	framebuffer_release(info);
> -}
> -
> -static struct fb_ops efifb_ops = {
> -	.owner		= THIS_MODULE,
> -	.fb_destroy	= efifb_destroy,
> -	.fb_setcolreg	= efifb_setcolreg,
> -	.fb_fillrect	= cfb_fillrect,
> -	.fb_copyarea	= cfb_copyarea,
> -	.fb_imageblit	= cfb_imageblit,
> -};
> -
>  static int __init efifb_setup(char *options)
>  {
>  	char *this_opt;
> @@ -215,171 +154,24 @@ static int __init efifb_setup(char *options)
>  
>  static int __devinit efifb_probe(struct platform_device *dev)
>  {
> -	struct fb_info *info;
>  	int err;
> -	unsigned int size_vmode;
> -	unsigned int size_remap;
> -	unsigned int size_total;
> -	int request_succeeded = 0;
> -
> -	if (!screen_info.lfb_depth)
> -		screen_info.lfb_depth = 32;
> -	if (!screen_info.pages)
> -		screen_info.pages = 1;
> -	if (!screen_info.lfb_base) {
> -		printk(KERN_DEBUG "efifb: invalid framebuffer address\n");
> -		return -ENODEV;
> -	}
> -	printk(KERN_INFO "efifb: probing for efifb\n");
> -
> -	/* just assume they're all unset if any are */
> -	if (!screen_info.blue_size) {
> -		screen_info.blue_size = 8;
> -		screen_info.blue_pos = 0;
> -		screen_info.green_size = 8;
> -		screen_info.green_pos = 8;
> -		screen_info.red_size = 8;
> -		screen_info.red_pos = 16;
> -		screen_info.rsvd_size = 8;
> -		screen_info.rsvd_pos = 24;
> -	}
> -
> -	efifb_fix.smem_start = screen_info.lfb_base;
> -	efifb_defined.bits_per_pixel = screen_info.lfb_depth;
> -	efifb_defined.xres = screen_info.lfb_width;
> -	efifb_defined.yres = screen_info.lfb_height;
> -	efifb_fix.line_length = screen_info.lfb_linelength;
> -
> -	/*   size_vmode -- that is the amount of memory needed for the
> -	 *                 used video mode, i.e. the minimum amount of
> -	 *                 memory we need. */
> -	size_vmode = efifb_defined.yres * efifb_fix.line_length;
> -
> -	/*   size_total -- all video memory we have. Used for
> -	 *                 entries, ressource allocation and bounds
> -	 *                 checking. */
> -	size_total = screen_info.lfb_size;
> -	if (size_total < size_vmode)
> -		size_total = size_vmode;
> -
> -	/*   size_remap -- the amount of video memory we are going to
> -	 *                 use for efifb.  With modern cards it is no
> -	 *                 option to simply use size_total as that
> -	 *                 wastes plenty of kernel address space. */
> -	size_remap  = size_vmode * 2;
> -	if (size_remap > size_total)
> -		size_remap = size_total;
> -	if (size_remap % PAGE_SIZE)
> -		size_remap += PAGE_SIZE - (size_remap % PAGE_SIZE);
> -	efifb_fix.smem_len = size_remap;
> -
> -	if (request_mem_region(efifb_fix.smem_start, size_remap, "efifb")) {
> -		request_succeeded = 1;
> -	} else {
> -		/* We cannot make this fatal. Sometimes this comes from magic
> -		   spaces our resource handlers simply don't know about */
> -		printk(KERN_WARNING
> -		       "efifb: cannot reserve video memory at 0x%lx\n",
> -			efifb_fix.smem_start);
> -	}
> -
> -	info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
> -	if (!info) {
> -		printk(KERN_ERR "efifb: cannot allocate framebuffer\n");
> -		err = -ENOMEM;
> -		goto err_release_mem;
> -	}
> -	info->pseudo_palette = info->par;
> -	info->par = NULL;
> -
> -	info->apertures = alloc_apertures(1);
> -	if (!info->apertures) {
> -		err = -ENOMEM;
> -		goto err_release_fb;
> -	}
> -	info->apertures->ranges[0].base = efifb_fix.smem_start;
> -	info->apertures->ranges[0].size = size_remap;
> -
> -	info->screen_base = ioremap(efifb_fix.smem_start, efifb_fix.smem_len);
> -	if (!info->screen_base) {
> -		printk(KERN_ERR "efifb: abort, cannot ioremap video memory "
> -				"0x%x @ 0x%lx\n",
> -			efifb_fix.smem_len, efifb_fix.smem_start);
> -		err = -EIO;
> -		goto err_release_fb;
> -	}
> -
> -	printk(KERN_INFO "efifb: framebuffer at 0x%lx, mapped to 0x%p, "
> -	       "using %dk, total %dk\n",
> -	       efifb_fix.smem_start, info->screen_base,
> -	       size_remap/1024, size_total/1024);
> -	printk(KERN_INFO "efifb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
> -	       efifb_defined.xres, efifb_defined.yres,
> -	       efifb_defined.bits_per_pixel, efifb_fix.line_length,
> -	       screen_info.pages);
> -
> -	efifb_defined.xres_virtual = efifb_defined.xres;
> -	efifb_defined.yres_virtual = efifb_fix.smem_len /
> -					efifb_fix.line_length;
> -	printk(KERN_INFO "efifb: scrolling: redraw\n");
> -	efifb_defined.yres_virtual = efifb_defined.yres;
> -
> -	/* some dummy values for timing to make fbset happy */
> -	efifb_defined.pixclock     = 10000000 / efifb_defined.xres *
> -					1000 / efifb_defined.yres;
> -	efifb_defined.left_margin  = (efifb_defined.xres / 8) & 0xf8;
> -	efifb_defined.hsync_len    = (efifb_defined.xres / 8) & 0xf8;
> -
> -	efifb_defined.red.offset    = screen_info.red_pos;
> -	efifb_defined.red.length    = screen_info.red_size;
> -	efifb_defined.green.offset  = screen_info.green_pos;
> -	efifb_defined.green.length  = screen_info.green_size;
> -	efifb_defined.blue.offset   = screen_info.blue_pos;
> -	efifb_defined.blue.length   = screen_info.blue_size;
> -	efifb_defined.transp.offset = screen_info.rsvd_pos;
> -	efifb_defined.transp.length = screen_info.rsvd_size;
> -
> -	printk(KERN_INFO "efifb: %s: "
> -	       "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
> -	       "Truecolor",
> -	       screen_info.rsvd_size,
> -	       screen_info.red_size,
> -	       screen_info.green_size,
> -	       screen_info.blue_size,
> -	       screen_info.rsvd_pos,
> -	       screen_info.red_pos,
> -	       screen_info.green_pos,
> -	       screen_info.blue_pos);
> -
> -	efifb_fix.ypanstep  = 0;
> -	efifb_fix.ywrapstep = 0;
> +	struct fb_info *info;
>  
> -	info->fbops = &efifb_ops;
> -	info->var = efifb_defined;
> -	info->fix = efifb_fix;
> -	info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE;
> +	if ((err = linearfb_get_info(dev, &info)) < 0)
> +		return err;
>  
> -	if ((err = fb_alloc_cmap(&info->cmap, 256, 0)) < 0) {
> -		printk(KERN_ERR "efifb: cannot allocate colormap\n");
> -		goto err_unmap;
> -	}
> +	strcpy(info->fix.id, "EFI VGA");
>  	if ((err = register_framebuffer(info)) < 0) {
>  		printk(KERN_ERR "efifb: cannot register framebuffer\n");
> -		goto err_fb_dealoc;
> +		goto err_fb_dealloc;
>  	}
>  	printk(KERN_INFO "fb%d: %s frame buffer device\n",
>  		info->node, info->fix.id);
>  	return 0;
>  
> -err_fb_dealoc:
> +err_fb_dealloc:
>  	fb_dealloc_cmap(&info->cmap);
> -err_unmap:
> -	iounmap(info->screen_base);
> -err_release_fb:
> -	framebuffer_release(info);
> -err_release_mem:
> -	if (request_succeeded)
> -		release_mem_region(efifb_fix.smem_start, size_total);
> +	linearfb_destroy(info);
>  	return err;
>  }
>  
> diff --git a/drivers/video/linearfb.c b/drivers/video/linearfb.c
> new file mode 100644
> index 0000000..c93eaac
> --- /dev/null
> +++ b/drivers/video/linearfb.c
> @@ -0,0 +1,332 @@
> +/*
> + * Simple linear framebuffer driver
> + *
> + * This driver does not have any real probing capability; using it requires
> + * programming, either by the boot loader or by another framebuffer driver.
> + *
> + * (c) 2006 Edgar Hucek <gimli@...k-green.com>
> + * Original efi driver written by Gerd Knorr <kraxel@...dbach.in-berlin.de>
> + * Split out to linearfb by Colin Watson <cjwatson@...ntu.com>
> + *
> + */
> +
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/errno.h>
> +#include <linux/fb.h>
> +#include <linux/platform_device.h>
> +#include <linux/screen_info.h>
> +
> +#include <video/vga.h>
> +
> +static struct fb_var_screeninfo linearfb_defined __initdata = {
> +	.activate		= FB_ACTIVATE_NOW,
> +	.height			= -1,
> +	.width			= -1,
> +	.right_margin		= 32,
> +	.upper_margin		= 16,
> +	.lower_margin		= 4,
> +	.vsync_len		= 4,
> +	.vmode			= FB_VMODE_NONINTERLACED,
> +};
> +
> +static struct fb_fix_screeninfo linearfb_fix __initdata = {
> +	.id			= "Linear",
> +	.type			= FB_TYPE_PACKED_PIXELS,
> +	.accel			= FB_ACCEL_NONE,
> +	.visual			= FB_VISUAL_TRUECOLOR,
> +};
> +
> +static int linearfb_setcolreg(unsigned regno, unsigned red, unsigned green,
> +			      unsigned blue, unsigned transp,
> +			      struct fb_info *info)
> +{
> +	/*
> +	 *  Set a single color register. The values supplied are
> +	 *  already rounded down to the hardware's capabilities
> +	 *  (according to the entries in the `var' structure). Return
> +	 *  != 0 for invalid regno.
> +	 */
> +
> +	if (regno >= info->cmap.len)
> +		return 1;
> +
> +	if (regno < 16) {
> +		red   >>= 8;
> +		green >>= 8;
> +		blue  >>= 8;
> +		((u32 *)(info->pseudo_palette))[regno] =
> +			(red   << info->var.red.offset)   |
> +			(green << info->var.green.offset) |
> +			(blue  << info->var.blue.offset);
> +	}
> +	return 0;
> +}
> +
> +void linearfb_destroy(struct fb_info *info)
> +{
> +	if (info->screen_base)
> +		iounmap(info->screen_base);
> +	release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size);
> +	framebuffer_release(info);
> +}
> +EXPORT_SYMBOL(linearfb_destroy);
> +
> +static struct fb_ops linearfb_ops = {
> +	.owner		= THIS_MODULE,
> +	.fb_destroy	= linearfb_destroy,
> +	.fb_setcolreg	= linearfb_setcolreg,
> +	.fb_fillrect	= cfb_fillrect,
> +	.fb_copyarea	= cfb_copyarea,
> +	.fb_imageblit	= cfb_imageblit,
> +};
> +
> +static int __init linearfb_setup(char *options)
> +{
> +	char *this_opt;
> +
> +	if (!options || !*options)
> +		return 0;
> +
> +	while ((this_opt = strsep(&options, ",")) != NULL) {
> +		if (!*this_opt) continue;
> +
> +		if (!strncmp(this_opt, "base:", 5))
> +			screen_info.lfb_base = simple_strtoul(this_opt+5, NULL, 0);
> +		else if (!strncmp(this_opt, "stride:", 7))
> +			screen_info.lfb_linelength = simple_strtoul(this_opt+7, NULL, 0) * 4;
> +		else if (!strncmp(this_opt, "height:", 7))
> +			screen_info.lfb_height = simple_strtoul(this_opt+7, NULL, 0);
> +		else if (!strncmp(this_opt, "width:", 6))
> +			screen_info.lfb_width = simple_strtoul(this_opt+6, NULL, 0);
> +	}
> +	return 0;
> +}
> +
> +int linearfb_get_info(struct platform_device *dev, struct fb_info **p_info)
> +{
> +	int err;
> +	unsigned int size_vmode;
> +	unsigned int size_remap;
> +	unsigned int size_total;
> +	int request_succeeded = 0;
> +	struct fb_info *info;
> +
> +	if (!screen_info.lfb_depth)
> +		screen_info.lfb_depth = 32;
> +	if (!screen_info.pages)
> +		screen_info.pages = 1;
> +	if (!screen_info.lfb_base) {
> +		printk(KERN_DEBUG "linearfb: invalid framebuffer address\n");
> +		return -ENODEV;
> +	}
> +	printk(KERN_INFO "linearfb: probing for linearfb\n");
> +
> +	/* just assume they're all unset if any are */
> +	if (!screen_info.blue_size) {
> +		screen_info.blue_size = 8;
> +		screen_info.blue_pos = 0;
> +		screen_info.green_size = 8;
> +		screen_info.green_pos = 8;
> +		screen_info.red_size = 8;
> +		screen_info.red_pos = 16;
> +		screen_info.rsvd_size = 8;
> +		screen_info.rsvd_pos = 24;
> +	}
> +
> +	linearfb_fix.smem_start = screen_info.lfb_base;
> +	linearfb_defined.bits_per_pixel = screen_info.lfb_depth;
> +	linearfb_defined.xres = screen_info.lfb_width;
> +	linearfb_defined.yres = screen_info.lfb_height;
> +	linearfb_fix.line_length = screen_info.lfb_linelength;
> +
> +	/*   size_vmode -- that is the amount of memory needed for the
> +	 *                 used video mode, i.e. the minimum amount of
> +	 *                 memory we need. */
> +	size_vmode = linearfb_defined.yres * linearfb_fix.line_length;
> +
> +	/*   size_total -- all video memory we have. Used for
> +	 *                 entries, ressource allocation and bounds
> +	 *                 checking. */
> +	size_total = screen_info.lfb_size;
> +	if (size_total < size_vmode)
> +		size_total = size_vmode;
> +
> +	/*   size_remap -- the amount of video memory we are going to
> +	 *                 use for linearfb.  With modern cards it is no
> +	 *                 option to simply use size_total as that
> +	 *                 wastes plenty of kernel address space. */
> +	size_remap  = size_vmode * 2;
> +	if (size_remap > size_total)
> +		size_remap = size_total;
> +	if (size_remap % PAGE_SIZE)
> +		size_remap += PAGE_SIZE - (size_remap % PAGE_SIZE);
> +	linearfb_fix.smem_len = size_remap;
> +
> +	if (request_mem_region(linearfb_fix.smem_start, size_remap,
> +	    "linearfb")) {
> +		request_succeeded = 1;
> +	} else {
> +		/* We cannot make this fatal. Sometimes this comes from magic
> +		   spaces our resource handlers simply don't know about */
> +		printk(KERN_WARNING
> +		       "linearfb: cannot reserve video memory at 0x%lx\n",
> +			linearfb_fix.smem_start);
> +	}
> +
> +	info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
> +	if (!info) {
> +		printk(KERN_ERR "linearfb: cannot allocate framebuffer\n");
> +		err = -ENOMEM;
> +		goto err_release_mem;
> +	}
> +	info->pseudo_palette = info->par;
> +	info->par = NULL;
> +
> +	info->apertures = alloc_apertures(1);
> +	if (!info->apertures) {
> +		err = -ENOMEM;
> +		goto err_release_fb;
> +	}
> +	info->apertures->ranges[0].base = linearfb_fix.smem_start;
> +	info->apertures->ranges[0].size = size_remap;
> +
> +	info->screen_base = ioremap(linearfb_fix.smem_start,
> +				    linearfb_fix.smem_len);
> +	if (!info->screen_base) {
> +		printk(KERN_ERR "linearfb: abort, cannot ioremap video memory "
> +				"0x%x @ 0x%lx\n",
> +			linearfb_fix.smem_len, linearfb_fix.smem_start);
> +		err = -EIO;
> +		goto err_release_fb;
> +	}
> +
> +	printk(KERN_INFO "linearfb: framebuffer at 0x%lx, mapped to 0x%p, "
> +	       "using %dk, total %dk\n",
> +	       linearfb_fix.smem_start, info->screen_base,
> +	       size_remap/1024, size_total/1024);
> +	printk(KERN_INFO
> +	       "linearfb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
> +	       linearfb_defined.xres, linearfb_defined.yres,
> +	       linearfb_defined.bits_per_pixel, linearfb_fix.line_length,
> +	       screen_info.pages);
> +
> +	linearfb_defined.xres_virtual = linearfb_defined.xres;
> +	linearfb_defined.yres_virtual = linearfb_fix.smem_len /
> +					linearfb_fix.line_length;
> +	printk(KERN_INFO "linearfb: scrolling: redraw\n");
> +	linearfb_defined.yres_virtual = linearfb_defined.yres;
> +
> +	/* some dummy values for timing to make fbset happy */
> +	linearfb_defined.pixclock     = 10000000 / linearfb_defined.xres *
> +					1000 / linearfb_defined.yres;
> +	linearfb_defined.left_margin  = (linearfb_defined.xres / 8) & 0xf8;
> +	linearfb_defined.hsync_len    = (linearfb_defined.xres / 8) & 0xf8;
> +
> +	linearfb_defined.red.offset    = screen_info.red_pos;
> +	linearfb_defined.red.length    = screen_info.red_size;
> +	linearfb_defined.green.offset  = screen_info.green_pos;
> +	linearfb_defined.green.length  = screen_info.green_size;
> +	linearfb_defined.blue.offset   = screen_info.blue_pos;
> +	linearfb_defined.blue.length   = screen_info.blue_size;
> +	linearfb_defined.transp.offset = screen_info.rsvd_pos;
> +	linearfb_defined.transp.length = screen_info.rsvd_size;
> +
> +	printk(KERN_INFO "linearfb: %s: "
> +	       "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
> +	       "Truecolor",
> +	       screen_info.rsvd_size,
> +	       screen_info.red_size,
> +	       screen_info.green_size,
> +	       screen_info.blue_size,
> +	       screen_info.rsvd_pos,
> +	       screen_info.red_pos,
> +	       screen_info.green_pos,
> +	       screen_info.blue_pos);
> +
> +	linearfb_fix.ypanstep  = 0;
> +	linearfb_fix.ywrapstep = 0;
> +
> +	info->fbops = &linearfb_ops;
> +	info->var = linearfb_defined;
> +	info->fix = linearfb_fix;
> +	info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE;
> +
> +	if ((err = fb_alloc_cmap(&info->cmap, 256, 0)) < 0) {
> +		printk(KERN_ERR "linearfb: cannot allocate colormap\n");
> +		goto err_unmap;
> +	}
> +	*p_info = info;
> +	return 0;
> +
> +err_unmap:
> +	iounmap(info->screen_base);
> +err_release_fb:
> +	framebuffer_release(info);
> +err_release_mem:
> +	if (request_succeeded)
> +		release_mem_region(linearfb_fix.smem_start, size_total);
> +	return err;
> +}
> +EXPORT_SYMBOL(linearfb_get_info);
> +
> +static int linearfb_probe(struct platform_device *dev)
> +{
> +	int err;
> +	struct fb_info *info;
> +
> +	if ((err = linearfb_get_info(dev, &info)) < 0)
> +		return err;
> +
> +	if ((err = register_framebuffer(info)) < 0) {
> +		printk(KERN_ERR "linearfb: cannot register framebuffer\n");
> +		goto err_fb_dealloc;
> +	}
> +	printk(KERN_INFO "fb%d: %s frame buffer device\n",
> +		info->node, info->fix.id);
> +	return 0;
> +
> +err_fb_dealloc:
> +	fb_dealloc_cmap(&info->cmap);
> +	linearfb_destroy(info);
> +	return err;
> +}
> +
> +static struct platform_driver linearfb_driver = {
> +	.probe	= linearfb_probe,
> +	.driver	= {
> +		.name	= "linearfb",
> +	},
> +};
> +
> +static struct platform_device linearfb_device = {
> +	.name	= "linearfb",
> +};
> +
> +static int __init linearfb_init(void)
> +{
> +	int ret;
> +	char *option = NULL;
> +
> +	if (screen_info.orig_video_isVGA != VIDEO_TYPE_LINEAR)
> +		return -ENODEV;
> +
> +	if (fb_get_options("linearfb", &option))
> +		return -ENODEV;
> +	linearfb_setup(option);
> +
> +	if (!screen_info.lfb_linelength)
> +		return -ENODEV;
> +
> +	ret = platform_driver_register(&linearfb_driver);
> +
> +	if (!ret) {
> +		ret = platform_device_register(&linearfb_device);
> +		if (ret)
> +			platform_driver_unregister(&linearfb_driver);
> +	}
> +	return ret;
> +}
> +module_init(linearfb_init);
> +
> +MODULE_LICENSE("GPL");
> diff --git a/include/linux/fb.h b/include/linux/fb.h
> index 8e5a9df..0913385 100644
> --- a/include/linux/fb.h
> +++ b/include/linux/fb.h
> @@ -1137,6 +1137,14 @@ extern int fb_find_mode(struct fb_var_screeninfo *var,
>  			const struct fb_videomode *default_mode,
>  			unsigned int default_bpp);
>  
> +#ifdef CONFIG_FB_LINEAR
> +struct platform_device;
> +
> +extern void linearfb_destroy(struct fb_info *info);
> +extern int linearfb_get_info(struct platform_device *dev,
> +			     struct fb_info **p_info);
> +#endif /* CONFIG_FB_LINEAR */
> +
>  #endif /* __KERNEL__ */
>  
>  #endif /* _LINUX_FB_H */
> diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h
> index 899fbb4..129f533 100644
> --- a/include/linux/screen_info.h
> +++ b/include/linux/screen_info.h
> @@ -66,6 +66,8 @@ struct screen_info {
>  
>  #define VIDEO_TYPE_EFI		0x70	/* EFI graphic mode		*/
>  
> +#define VIDEO_TYPE_LINEAR	0x80	/* Simple linear frame bufffer	*/
> +
>  #define VIDEO_FLAGS_NOCURSOR	(1 << 0) /* The video mode has no cursor set */
>  
>  #ifdef __KERNEL__


-- 
        Peter

I'd like to start a religion. That's where the money is.
		-- L. Ron Hubbard to Lloyd Eshbach, in 1949;
			quoted by Eshbach in _Over My Shoulder_.

01234567890123456789012345678901234567890123456789012345678901234567890123456789
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ