1 diff -Nru a/Documentation/fb/00-INDEX b/Documentation/fb/00-INDEX
2 --- a/Documentation/fb/00-INDEX 2004-08-26 21:34:52 +02:00
3 +++ b/Documentation/fb/00-INDEX 2004-08-26 21:34:52 +02:00
5 - info on the Matrox frame buffer driver
7 - info on the PowerVR 2 frame buffer driver
9 + - info on the Framebuffer Splash
11 - info on the TGA (DECChip 21030) frame buffer driver
13 diff -Nru a/Documentation/fb/splash.txt b/Documentation/fb/splash.txt
14 --- /dev/null Wed Dec 31 16:00:00 196900
15 +++ b/Documentation/fb/splash.txt 2004-08-26 21:34:52 +02:00
20 +The framebuffer splash is a kernel feature that allows displaying a background
21 +picture on selected consoles and switching the first console to the so-called
22 +silent mode, while booting/rebooting/shutting down the system.
24 +What do I need to get it to work?
25 +---------------------------------
27 +To get fb splash up-and-running you will have to:
28 + 1) get a copy of splashutils from (FIXME URL)
29 + 2) get some splash themes (FIXME URL)
30 + 3) build the kernel helper program
31 + 4) build your kernel with the FB_SPLASH option enabled.
33 +To get fb splash operational right after fbcon initialization is finished, you
34 +will have to include a theme and the kernel helper into your initramfs image.
35 +Please refer to splashutils documentation for instructions on how to do that.
40 +The framebuffer splash can work in two modes: verbose and silent. The first
41 +one means "console with a background image". The latter one is a concept
42 +first introduced in bootsplash. When silent mode is active, the console is
43 +switched to a graphic mode and no text is displayed. It's up to the userspace
44 +programs to display something (a progress bar for example) on the screen.
46 +Kernel command line parameters
47 +------------------------------
49 +Framebuffer splash can be configured from the kernel command line by passing
50 +options in the following way: "splash=option1,option2".
52 +The following options are recognized:
54 +off - do not enable fbsplash after fbcon initialization; this is
56 +verbose - switch fbsplash to verbose mode after fbcon is initialized
57 +silent - switch fbsplash to silent mode after fbcon is initialized
59 +theme:<name> - use theme 'name' on the first console, default theme name
60 + is 'default' (who'd have guessed?)
62 +Example - you want to get verbose splash with the theme 'tux' right after
64 + splash=verbose,theme:tux
69 +The userspace splash helper (by default: /sbin/splash_helper) is called by the
70 +kernel whenever an important event occurs and the kernel needs some kind of
71 +job to be carried out. Important events include console switches and graphic
72 +mode switches (the kernel requests background images and config for the current
73 +console). The splash helper must be accessible at all times. If it's not,
74 +fbsplash will be switched off automatically.
76 +It's possible to set path to the splash helper by writing it to
77 +/proc/sys/kernel/fbsplash.
79 +*****************************************************************************
81 +The information below is mostly technical stuff. If you don't plan to develop
82 +something fbsplash-related, there's probably no need to read it.
87 +The splash protocol defines a communication interface between the kernel and
88 +the userspace splash helper.
90 +The kernel side is responsible for:
92 + o rendering console text, using an image as a background (instead of a
93 + standard solid color fbcon uses),
94 + o accepting commands from the user via ioctls on the fbsplash device,
95 + o calling the userspace helper to set things up as soon as the fb subsystem is
98 +The userspace helper is responsible for everything else, including parsing
99 +configuration files, decompressing the image files whenever the kernel needs
100 +it, and communicating with the kernel if necessary.
102 +The splash protocol specifies how communication is done in both ways:
103 +kernel->userspace and userspace->helper.
108 +The kernel communicates with the userspace helper by calling it and specifying
109 +the task that to be done in a series of arguments.
111 +The arguments follow the pattern:
112 +<splash protocol version> <command> <parameters>
114 +All commands defined in splash protocol v1 have the following parameters:
117 + splash mode - 'v' indicates verbose, 's' indicates silent
120 +Splash protocol v1 specifies the following commands:
124 + The kernel issues this command to request image data. It's up to the userspace
125 + helper to find a background image appropriate for the specified theme and the
126 + current resolution. The userspace helper should respond by issuing the
127 + FBIOSPLASH_SETPIC ioctl.
131 + The kernel issues this command if either 'verbose' or 'silent' has been
132 + specified in splash= on the kernel command line. Upon receiving this command,
133 + the userspace helper should find a proper configuration file for the
134 + specified theme and the current resolution, and issue the FBIOSPLASH_SETCFG.
135 + FBIOSPLASH_SETPIC and FBIOSPLASH_SETSTATE commands.
137 + When the userspace helper is called in an early phase of the boot process
138 + (right after the initialization of fbcon), no filesystems will be mounted.
139 + The helper program should mount sysfs and then create the appropriate
140 + framebuffer, fbsplash and tty0 devices (if they don't already exist) to get
141 + current display settings and to be able to communicate with the kernel side.
143 + Note that the console sem is not held when the kernel calls splash_helper
144 + with the 'init' command. The splash helper should perform all ioctls with
145 + origin set to FB_SPLASH_IO_ORIG_USER.
149 + The kernel issues this command on a mode change. The helper's response should
150 + be similar to the response to the 'init' command. Note that this time the
151 + console sem is held and all ioctls must be performed with origin set to
152 + FB_SPLASH_IO_ORIG_KERNEL.
158 +Userspace programs can communicate with the kernel side via ioctls on the
159 +on the fbsplash device. These ioctls are to be used by both the userspace helper
160 +(called only by the kernel) and userspace configuration tools (run by the users).
161 +The splash helper should set the origin field to FB_SPLASH_IO_ORIG_KERNEL when
162 +doing the appropriate ioctls. All userspace configuration tools should use
163 +FB_SPLASH_IO_ORIG_USER. Failure to set the appropriate value in the origin
164 +field when performing ioctls from the kernel helper may result in a deadlock.
166 +The framebuffer splash provides the following ioctls (all defined in linux/fb.h):
169 +description: sets the global fbsplash mode
170 +argument: unsigned int; values: FB_SPLASH_MODE_VERBOSE, FB_SPLASH_MODE_SILENT
173 +description: gets the global fbsplash mode
174 +argument: unsigned int*; values as in FBIOSPLASH_SETMODE
177 +description: loads a background picture for a virtual console
178 +argument: struct fb_splash_iowrapper*; data: struct fb_image*
180 +If called for consoles other than the current foreground one, the picture data
183 +If the current virtual console is running in a 8-bpp mode, the cmap substruct
184 +of fb_image has to be filled appropriately: start should be set to 16 (first 16
185 +colors are reserved for fbcon), len to a value <= 240 and red, green and blue
186 +should point to valid cmap data. The transp field is ingored. The fields dx, dy
187 +bg_color, fg_color in fb_image are ignored as well.
190 +description: sets the fbsplash config for a virtual console
191 +argument: struct fb_splash_iowrapper*; data: struct vc_splash*;
192 + the structure has to be filled with valid data.
195 +description: gets the fbsplash config for a virtual console
196 +argument: struct fb_splash_iowrapper*; data: struct vc_splash*
199 +description: sets the fbsplash state for a virtual console
200 +argument: struct fb_splash_iowrapper*; data: unsigned int*
201 + values: 0 = disabled, 1 = enabled.
204 +description: gets the fbsplash state for a virtual console
205 +argument: struct fb_splash_iowrapper*; data: unsigned int*
206 + values: as in FBIOSPLASH_SETSTATE
208 +Info on used structures:
210 +Definition of struct vc_splash can be found in linux/console_splash.h, it's
211 +heavily commented, so no special descriptions are necessary. Note that
212 +the 'theme' field should point to a string no longer than FB_SPLASH_THEME_LEN.
213 +When FBIOSPLASH_GETCFG call is performed, the theme field should point to a
214 +char buffer of length FB_SPLASH_THEME_LEN.
216 +Definition of struct fb_splash_iowrapper can be found in linux/fb.h.
217 +The fields in this struct have the following meaning:
220 +Virtual console number.
223 +Specifies if the ioctl is performed as a response to a kernel request. The
224 +splash helper should set this field to FB_SPLASH_IO_ORIG_KERNEL, userspace
225 +programs should set it to FB_SPLASH_IO_ORIG_USER. This field is necessary to
226 +avoid console semaphore deadlocks.
229 +Pointer to a data structure appropriate for the performed ioctl. Type of
230 +the data struct is specified in the ioctls description, for example 'data:
231 +struct vc_splash*' means that the 'data' field should be a pointer to a
234 +*****************************************************************************
239 +Original idea & implementation by:
240 + Volker Poplawski <volker@poplawski.de>, Stefan Reinauer <stepan@suse.de>,
241 + Steffen Winterfeldt <snwint@suse.de>, Michael Schroeder <mls@suse.de>,
242 + Ken Wimer <wimer@suse.de>.
244 +Splash protocol redesign, current implementation, docs by:
245 + Michal Januszewski <spock@gentoo.org>
247 diff -Nru a/drivers/char/keyboard.c b/drivers/char/keyboard.c
248 --- a/drivers/char/keyboard.c 2004-08-26 21:34:52 +02:00
249 +++ b/drivers/char/keyboard.c 2004-08-26 21:34:52 +02:00
251 #include <linux/sysrq.h>
252 #include <linux/input.h>
254 +#include "../video/fbsplash.h"
256 static void kbd_disconnect(struct input_handle *handle);
257 extern void ctrl_alt_del(void);
259 @@ -1057,6 +1059,12 @@
260 if (emulate_raw(vc, keycode, !down << 7))
261 if (keycode < BTN_MISC)
262 printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode);
264 + /* switch splash to verbose mode if ESC or F2 is pressed */
265 + if (down == 1 && (keycode == KEY_ESC || keycode == KEY_F2)) {
266 + if (fbsplash_verbose())
270 #ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */
271 if (keycode == KEY_SYSRQ && (sysrq_down || (down == 1 && sysrq_alt))) {
272 diff -Nru a/drivers/char/n_tty.c b/drivers/char/n_tty.c
273 --- a/drivers/char/n_tty.c 2004-08-26 21:34:52 +02:00
274 +++ b/drivers/char/n_tty.c 2004-08-26 21:34:52 +02:00
276 #include <asm/system.h>
277 #include <asm/bitops.h>
279 +#include "../video/fbsplash.h"
281 /* number of characters left in xmit buffer before select has we have room */
282 #define WAKEUP_CHARS 256
285 if (!tty->read_buf) {
286 printk("n_tty_read_chan: called with read_buf == NULL?!?\n");
290 + /* automatically switch splash to verbose mode if someone tries to
292 + if (file->f_dentry->d_inode->i_rdev == MKDEV(TTY_MAJOR,0) ||
293 + file->f_dentry->d_inode->i_rdev == MKDEV(TTY_MAJOR,1) ||
294 + file->f_dentry->d_inode->i_rdev == MKDEV(TTYAUX_MAJOR,0) ||
295 + file->f_dentry->d_inode->i_rdev == MKDEV(TTYAUX_MAJOR,1)) {
296 + fbsplash_verbose();
299 /* Job control check -- must be done at start and after
300 diff -Nru a/drivers/video/Kconfig b/drivers/video/Kconfig
301 --- a/drivers/video/Kconfig 2004-08-26 21:34:52 +02:00
302 +++ b/drivers/video/Kconfig 2004-08-26 21:34:52 +02:00
303 @@ -1011,5 +1011,15 @@
304 source "drivers/video/logo/Kconfig"
309 + bool "Support for the framebuffer splash"
310 + depends on FRAMEBUFFER_CONSOLE=y
313 + This option enables support for the Linux boot-up splash screen and
314 + graphical backgrounds on consoles. Note that you will need userspace
315 + splashutils in order to take advantage of these features. Refer to
316 + Documentation/fb/splash.txt for more information.
320 diff -Nru a/drivers/video/Makefile b/drivers/video/Makefile
321 --- a/drivers/video/Makefile 2004-08-26 21:34:52 +02:00
322 +++ b/drivers/video/Makefile 2004-08-26 21:34:52 +02:00
325 obj-$(CONFIG_VT) += console/
326 obj-$(CONFIG_LOGO) += logo/
327 +obj-$(CONFIG_FB_SPLASH) += fbsplash.o cfbsplash.o
329 obj-$(CONFIG_FB) += fbmem.o fbmon.o fbcmap.o fbsysfs.o modedb.o softcursor.o
330 # Only include macmodes.o if we have FB support and are PPC
331 diff -Nru a/drivers/video/cfbsplash.c b/drivers/video/cfbsplash.c
332 --- /dev/null Wed Dec 31 16:00:00 196900
333 +++ b/drivers/video/cfbsplash.c 2004-08-26 21:34:52 +02:00
336 + * linux/drivers/video/cfbsplash.c -- Framebuffer splash render functions
338 + * Copyright (C) 2004 Michal Januszewski <spock@gentoo.org>
340 + * Code based upon "Bootsplash" (C) 2001-2003
341 + * Volker Poplawski <volker@poplawski.de>,
342 + * Stefan Reinauer <stepan@suse.de>,
343 + * Steffen Winterfeldt <snwint@suse.de>,
344 + * Michael Schroeder <mls@suse.de>,
345 + * Ken Wimer <wimer@suse.de>.
347 + * This file is subject to the terms and conditions of the GNU General Public
348 + * License. See the file COPYING in the main directory of this archive for
351 +#include <linux/config.h>
352 +#include <linux/module.h>
353 +#include <linux/types.h>
354 +#include <linux/fb.h>
355 +#include <linux/vt_kern.h>
356 +#include <asm/irq.h>
357 +#include <asm/system.h>
359 +#include "console/fbcon.h"
360 +#include "fbsplash.h"
362 +#define parse_pixel(shift,bpp,type) \
364 + if (d & (0x80 >> (shift))) \
365 + dd2[(shift)] = fgx; \
367 + dd2[(shift)] = transparent ? *(type *)splash_src : bgx; \
368 + splash_src += (bpp); \
371 +void fbsplash_renderc(struct fb_info *info, int ypos, int xpos, int height,
372 + int width, u8* src, u32 fgx, u32 bgx, u8 transparent)
376 + int bytespp = ((info->var.bits_per_pixel + 7) >> 3);
377 + unsigned int d = ypos * info->fix.line_length + xpos * bytespp;
380 + u8* splash_src = (u8 *)(info->splash.data + d);
381 + u8* dst = (u8 *)(info->screen_base + d);
383 + if ((ypos + height) > info->var.yres || (xpos + width) > info->var.xres)
386 + for (y = 0; y < height; y++) {
387 + switch (info->var.bits_per_pixel) {
390 + for (x = 0; x < width; x++) {
398 + *(u32 *)splash_src : bgx;
402 + fb_writel(dd, dst);
407 + for (x = 0; x < width; x++) {
415 + (*(u32 *)splash_src & 0xffffff) : bgx;
419 +#ifdef __LITTLE_ENDIAN
420 + fb_writew(dd & 0xffff, dst);
422 + fb_writeb((dd >> 16), dst);
424 + fb_writew(dd >> 8, dst);
426 + fb_writeb(dd & 0xff, dst);
432 + for (x = 0; x < width; x += 2) {
436 + parse_pixel(0, 2, u16);
437 + parse_pixel(1, 2, u16);
438 +#ifdef __LITTLE_ENDIAN
439 + dd = dd2[0] | (dd2[1] << 16);
441 + dd = dd2[1] | (dd2[1] << 16);
444 + fb_writel(dd, dst);
450 + for (x = 0; x < width; x += 4) {
454 + parse_pixel(0, 1, u8);
455 + parse_pixel(1, 1, u8);
456 + parse_pixel(2, 1, u8);
457 + parse_pixel(3, 1, u8);
459 +#ifdef __LITTLE_ENDIAN
460 + dd = dd2[0] | (dd2[1] << 8) | (dd2[2] << 16) | (dd2[3] << 24);
462 + dd = dd2[3] | (dd2[2] << 8) | (dd2[1] << 16) | (dd2[0] << 24);
465 + fb_writel(dd, dst);
470 + d = info->fix.line_length - width * bytespp;
477 + ((info->fix.visual == FB_VISUAL_TRUECOLOR || \
478 + info->fix.visual == FB_VISUAL_DIRECTCOLOR) ? \
479 + ((u32*)info->pseudo_palette)[a] : a)
481 +void fbsplash_putcs(struct vc_data *vc, struct fb_info *info,
482 + const unsigned short *s, int count, int yy, int xx)
484 + unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
485 + int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
486 + int fgshift = (vc->vc_hi_font_mask) ? 9 : 8;
487 + int fg_color, bg_color, transparent;
492 + u16 c = scr_readw(s);
494 + fg_color = attr_fgcol(fgshift, c);
495 + bg_color = attr_bgcol(bgshift, c);
496 + transparent = vc->vc_splash.bg_color == bg_color;
498 + xx = xx * vc->vc_font.width + vc->vc_splash.tx;
499 + yy = yy * vc->vc_font.height + vc->vc_splash.ty;
501 + fgx = cc2cx(fg_color);
502 + bgx = cc2cx(bg_color);
505 + c = scr_readw(s++);
506 + src = vc->vc_font.data + (c & charmask) * vc->vc_font.height *
507 + ((vc->vc_font.width + 7) >> 3);
509 + fbsplash_renderc(info, yy, xx, vc->vc_font.height,
510 + vc->vc_font.width, src, fgx, bgx, transparent);
511 + xx += vc->vc_font.width;
515 +void fbsplash_putc(struct vc_data *vc, struct fb_info *info, int c,
516 + int ypos, int xpos)
518 + unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
519 + int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
520 + int fgshift = (vc->vc_hi_font_mask) ? 9 : 8;
521 + u32 bg_color = attr_bgcol(bgshift, c);
522 + u32 fg_color = attr_fgcol(fgshift, c);
523 + u8 *src = vc->vc_font.data + (c & charmask) * vc->vc_font.height *
524 + ((vc->vc_font.width + 7) >> 3);
525 + xpos = xpos * vc->vc_font.width + vc->vc_splash.tx;
526 + ypos = ypos * vc->vc_font.height + vc->vc_splash.ty;
528 + fbsplash_renderc(info, ypos, xpos, vc->vc_font.height, vc->vc_font.width,
529 + src, cc2cx(fg_color), cc2cx(bg_color),
530 + vc->vc_splash.bg_color == bg_color);
533 +void fbsplash_cursor(struct fb_info *info, struct fb_cursor *cursor)
536 + unsigned int dsize, s_pitch;
537 + char *t = (char *)info->cursor.image.data;
538 + struct vc_data* vc;
540 + vc = vc_cons[info->currcon].d;
542 + if (cursor->set & FB_CUR_SETSIZE) {
543 + info->cursor.image.height = cursor->image.height;
544 + info->cursor.image.width = cursor->image.width;
546 + if (cursor->set & FB_CUR_SETPOS) {
547 + info->cursor.image.dx = cursor->image.dx;
548 + info->cursor.image.dy = cursor->image.dy;
550 + if (cursor->set & FB_CUR_SETHOT)
551 + info->cursor.hot = cursor->hot;
552 + if (cursor->set & FB_CUR_SETCMAP) {
553 + if (cursor->image.depth == 1) {
554 + info->cursor.image.bg_color = cursor->image.bg_color;
555 + info->cursor.image.fg_color = cursor->image.fg_color;
557 + if (cursor->image.cmap.len)
558 + fb_copy_cmap(&cursor->image.cmap,
559 + &info->cursor.image.cmap);
561 + info->cursor.image.depth = cursor->image.depth;
563 + s_pitch = (info->cursor.image.width + 7) >> 3;
564 + dsize = s_pitch * info->cursor.image.height;
565 + if (info->cursor.enable) {
566 + switch (info->cursor.rop) {
568 + for (i = 0; i < dsize; i++)
569 + t[i] = cursor->image.data[i] ^ info->cursor.mask[i];
573 + for (i = 0; i < dsize; i++)
574 + t[i] = cursor->image.data[i] & info->cursor.mask[i];
577 + } else if (t != cursor->image.data)
578 + memcpy(t, cursor->image.data, dsize);
580 + fbsplash_renderc(info,
581 + info->cursor.image.dy + vc->vc_splash.ty,
582 + info->cursor.image.dx + vc->vc_splash.tx,
583 + info->cursor.image.height,
584 + info->cursor.image.width,
585 + (u8*)info->cursor.image.data,
586 + cc2cx(info->cursor.image.fg_color),
587 + cc2cx(info->cursor.image.bg_color),
588 + info->cursor.image.bg_color == vc->vc_splash.bg_color);
591 +static void splashset(u8 *dst, int height, int width, int dstbytes,
598 + if (bpp == 16 || bpp == 8)
601 + while (height-- > 0) {
607 + for (i=0; i < width; i++) {
608 + fb_writel(bgx, p); p += 4;
612 + for (i=0; i < width; i++) {
613 +#ifdef __LITTLE_ENDIAN
614 + fb_writew((bgx & 0xffff),(u16*)p); p += 2;
615 + fb_writeb((bgx >> 16),p++);
617 + fb_writew((bgx >> 8),(u16*)p); p += 2;
618 + fb_writeb((bgx & 0xff),p++);
622 + for (i=0; i < width/4; i++) {
623 + fb_writel(bgx,p); p += 4;
624 + fb_writel(bgx,p); p += 4;
627 + fb_writel(bgx,p); p += 4;
630 + fb_writew(bgx,(u16*)p);
633 + for (i=0; i < width/4; i++) {
634 + fb_writel(bgx,p); p += 4;
638 + fb_writew(bgx,p); p += 2;
641 + fb_writeb(bgx,(u8*)p);
649 +void fbsplash_copy(u8 *dst, u8 *src, int height, int width, int linebytes,
654 + while (height-- > 0) {
655 + u32 *p = (u32 *)dst;
656 + u32 *q = (u32 *)src;
661 + for (i=0; i < width; i++)
662 + fb_writel(*q++, p++);
665 + for (i=0; i < (width*3/4); i++)
666 + fb_writel(*q++, p++);
667 + if ((width*3) % 4) {
669 + fb_writeb(*(u8*)q, (u8*)p);
670 + } else if (width & 1) {
671 + fb_writew(*(u16*)q, (u16*)p);
672 + fb_writeb(*(u8*)((u16*)q+1),(u8*)((u16*)p+2));
677 + for (i=0; i < width/4; i++) {
678 + fb_writel(*q++, p++);
679 + fb_writel(*q++, p++);
682 + fb_writel(*q++, p++);
684 + fb_writew(*(u16*)q, (u16*)p);
687 + for (i=0; i < width/4; i++)
688 + fb_writel(*q++, p++);
691 + fb_writew(*(u16*)q, (u16*)p);
692 + q = (u32*) ((u16*)q + 1);
693 + p = (u32*) ((u16*)p + 1);
696 + fb_writeb(*(u8*)q, (u8*)p);
705 +static void splashfill(struct fb_info *info, int sy, int sx, int height,
708 + int d = sy * info->fix.line_length + sx * ((info->var.bits_per_pixel + 7) >> 3);
710 + fbsplash_copy((u8 *)(info->screen_base + d), (u8 *)(info->splash.data + d),
711 + height, width, info->fix.line_length, info->var.bits_per_pixel);
714 +void fbsplash_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx,
715 + int height, int width)
717 + int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
718 + int bg_color = attr_bgcol_ec(bgshift, vc);
719 + int transparent = vc->vc_splash.bg_color == bg_color;
722 + sy = sy * vc->vc_font.height + vc->vc_splash.ty;
723 + sx = sx * vc->vc_font.width + vc->vc_splash.tx;
724 + height *= vc->vc_font.height;
725 + width *= vc->vc_font.width;
728 + splashfill(info, sy, sx, height, width);
730 + dst = (u8 *)(info->screen_base + sy * info->fix.line_length +
731 + sx * ((info->var.bits_per_pixel + 7) >> 3));
732 + splashset(dst, height, width, info->fix.line_length, cc2cx(bg_color),
733 + info->var.bits_per_pixel);
737 +void fbsplash_clear_margins(struct vc_data *vc, struct fb_info *info,
740 + unsigned int tw = vc->vc_cols*vc->vc_font.width;
741 + unsigned int th = vc->vc_rows*vc->vc_font.height;
743 + if (!bottom_only) {
745 + splashfill(info, 0, 0, vc->vc_splash.ty, info->var.xres);
747 + splashfill(info, vc->vc_splash.ty, 0, th, vc->vc_splash.tx);
749 + splashfill(info, vc->vc_splash.ty, vc->vc_splash.tx + tw, th,
750 + info->var.xres - vc->vc_splash.tx - tw);
752 + splashfill(info, vc->vc_splash.ty + th, 0,
753 + info->var.yres - vc->vc_splash.ty - th, info->var.xres);
756 +void fbsplash_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y,
757 + int sx, int dx, int width)
759 + u16 *d = (u16 *) (vc->vc_origin + vc->vc_size_row * y + dx * 2);
760 + u16 *s = d + (dx - sx);
763 + u16 *le = d + width;
770 + if (attr != (c & 0xff00)) {
773 + fbsplash_putcs(vc, info, start, d - start, y, x);
778 + if (s >= ls && s < le && c == scr_readw(s)) {
780 + fbsplash_putcs(vc, info, start, d - start, y, x);
781 + x += d - start + 1;
792 + fbsplash_putcs(vc, info, start, d - start, y, x);
795 +void fbsplash_blank(struct vc_data *vc, struct fb_info *info, int blank)
798 + splashset((u8 *)info->screen_base, info->var.yres, info->var.xres,
799 + info->fix.line_length, 0, info->var.bits_per_pixel);
801 + update_screen(vc->vc_num);
802 + fbsplash_clear_margins(vc, info, 0);
806 diff -Nru a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
807 --- a/drivers/video/console/fbcon.c 2004-08-26 21:34:52 +02:00
808 +++ b/drivers/video/console/fbcon.c 2004-08-26 21:34:52 +02:00
813 +#include "../fbsplash.h"
816 # define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
818 info->cursor.rop == ROP_COPY || !vc || !CON_IS_VISIBLE(vc)
819 || registered_fb[(int) con2fb_map[vc->vc_num]] != info)
822 acquire_console_sem();
823 info->cursor.enable ^= 1;
824 - info->fbops->fb_cursor(info, &info->cursor);
825 + if (fbsplash_active(info, vc_cons[info->currcon].d)) {
826 + fbsplash_cursor(info, &info->cursor);
828 + info->fbops->fb_cursor(info, &info->cursor);
830 release_console_sem();
834 area.sy = sy * vc->vc_font.height;
835 area.dx = dx * vc->vc_font.width;
836 area.dy = dy * vc->vc_font.height;
838 + if (fbsplash_active(info, vc)) {
839 + area.sx += vc->vc_splash.tx;
840 + area.sy += vc->vc_splash.ty;
841 + area.dx += vc->vc_splash.tx;
842 + area.dy += vc->vc_splash.ty;
845 area.height = height * vc->vc_font.height;
846 area.width = width * vc->vc_font.width;
849 int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
850 struct fb_fillrect region;
852 + if (fbsplash_active(info, vc)) {
853 + fbsplash_clear(vc, info, sy, sx, height, width);
857 region.color = attr_bgcol_ec(bgshift, vc);
858 region.dx = sx * vc->vc_font.width;
859 region.dy = sy * vc->vc_font.height;
861 struct fb_image image;
862 u8 *src, *dst, *buf = NULL;
864 + if (fbsplash_active(info, vc)) {
865 + fbsplash_putcs(vc, info, s, count, yy, xx);
870 buf = kmalloc(cellsize, GFP_KERNEL);
873 unsigned int bs = info->var.yres - bh;
874 struct fb_fillrect region;
876 + if (fbsplash_active(info, vc)) {
877 + if (!fbsplash_isverbose)
879 + fbsplash_clear_margins(vc, info, bottom_only);
884 region.rop = ROP_COPY;
888 cols = info->var.xres / vc->vc_font.width;
889 rows = info->var.yres / vc->vc_font.height;
891 + if (fbsplash_active(info, vc)) {
892 + cols = vc->vc_splash.twidth / vc->vc_font.width;
893 + rows = vc->vc_splash.theight / vc->vc_font.height;
896 vc_resize(vc->vc_num, cols, rows);
898 DPRINTK("mode: %s\n", info->fix.id);
900 if (info_idx == -1 || info == NULL)
902 if (vc->vc_num != display_fg || (info->flags & FBINFO_MODULE) ||
903 - (info->fix.type == FB_TYPE_TEXT))
904 + (info->fix.type == FB_TYPE_TEXT) || fbsplash_active(info, vc))
907 info->var.xoffset = info->var.yoffset = p->yscroll = 0; /* reset wrap/pan */
908 @@ -1166,7 +1203,11 @@
909 if (info->cursor.rop == ROP_XOR) {
910 info->cursor.enable = 0;
911 info->cursor.rop = ROP_COPY;
912 - info->fbops->fb_cursor(info, &cursor);
913 + if (fbsplash_active(info, vc)) {
914 + fbsplash_cursor(info, &cursor);
916 + info->fbops->fb_cursor(info, &cursor);
921 @@ -1246,7 +1287,11 @@
924 info->cursor.rop = ROP_XOR;
925 - info->fbops->fb_cursor(info, &cursor);
926 + if (fbsplash_active(info, vc)) {
927 + fbsplash_cursor(info, &cursor);
929 + info->fbops->fb_cursor(info, &cursor);
931 vbl_cursor_cnt = CURSOR_DRAW_DELAY;
934 @@ -1685,7 +1730,7 @@
937 fbcon_softback_note(vc, t, count);
938 - if (logo_shown >= 0)
939 + if (logo_shown >= 0 || fbsplash_active(info, vc))
941 switch (p->scrollmode) {
943 @@ -1772,6 +1817,8 @@
945 if (count > vc->vc_rows) /* Maximum realistic size */
947 + if (fbsplash_active(info, vc))
949 switch (p->scrollmode) {
951 accel_bmove(vc, info, t, 0, t + count, 0,
952 @@ -1914,6 +1961,13 @@
957 + if (fbsplash_active(info, vc) && sy == dy && height == 1) {
958 + /* must use slower redraw bmove to keep background pic intact */
959 + fbsplash_bmove_redraw(vc, info, sy, sx, dx, width);
963 accel_bmove(vc, info, real_y(p, sy), sx, real_y(p, dy), dx,
966 @@ -1968,7 +2022,8 @@
967 var.yres = height * fh;
968 x_diff = info->var.xres - var.xres;
969 y_diff = info->var.yres - var.yres;
970 - if (x_diff < 0 || x_diff > fw || (y_diff < 0 || y_diff > fh)) {
972 + if ((x_diff < 0 || x_diff > fw || (y_diff < 0 || y_diff > fh)) && !vc->vc_splash.state) {
973 struct fb_videomode *mode;
975 DPRINTK("attempting resize %ix%i\n", var.xres, var.yres);
976 @@ -2014,6 +2069,15 @@
977 struct fb_var_screeninfo var;
980 + if (fbsplash_active_vc(vc)) {
981 + struct vc_data *vc_curr = vc_cons[info->currcon].d;
983 + if (!vc_curr->vc_splash.theme || strcmp(vc->vc_splash.theme, vc_curr->vc_splash.theme)) {
984 + if (fbsplash_call_helper("getpic", vc->vc_num))
985 + fbsplash_disable(vc, 0);
990 int l = fbcon_softback_size / vc->vc_size_row;
992 @@ -2144,6 +2208,12 @@
993 fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW);
995 if (!info->fbops->fb_blank) {
997 + if (fbsplash_active(info, vc)) {
998 + fbsplash_blank(vc, info, blank);
1003 unsigned short oldc;
1005 @@ -2312,9 +2382,16 @@
1009 + u32 xres = info->var.xres, yres = info->var.yres;
1010 /* reset wrap/pan */
1011 info->var.xoffset = info->var.yoffset = p->yscroll = 0;
1012 - vc_resize(vc->vc_num, info->var.xres / w, info->var.yres / h);
1014 + if (fbsplash_active(info, vc)) {
1015 + xres = vc->vc_splash.twidth;
1016 + yres = vc->vc_splash.theight;
1019 + vc_resize(vc->vc_num, xres / w, yres / h);
1020 if (CON_IS_VISIBLE(vc) && softback_buf) {
1021 int l = fbcon_softback_size / vc->vc_size_row;
1023 @@ -2493,7 +2570,62 @@
1025 fb_copy_cmap(fb_default_cmap(1 << depth), &palette_cmap);
1027 - return fb_set_cmap(&palette_cmap, info);
1028 + if (fbsplash_active(info, vc) && info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
1030 + u16 *red, *green, *blue;
1032 + int minlen = min(min(info->var.red.length, info->var.green.length),
1033 + info->var.blue.length);
1036 + struct fb_cmap cmap = {
1038 + .len = (1 << minlen),
1045 + red = kmalloc(256 * sizeof(u16) * 3, GFP_KERNEL);
1050 + green = red + 256;
1051 + blue = green + 265;
1053 + cmap.green = green;
1056 + for (i = 0; i < cmap.len; i++) {
1057 + red[i] = green[i] = blue[i] = (0xffff * i)/(cmap.len-1);
1060 + h = fb_set_cmap(&cmap, info);
1062 + for (j = i = 0; i < 16; i++) {
1065 + col = ((vc->vc_palette[j++] >> (8-minlen))
1066 + << info->var.red.offset);
1067 + col |= ((vc->vc_palette[j++] >> (8-minlen))
1068 + << info->var.green.offset);
1069 + col |= ((vc->vc_palette[j++] >> (8-minlen))
1070 + << info->var.blue.offset);
1072 + ((u32 *)info->pseudo_palette)[k] = col;
1079 + } else if (fbsplash_active(info, vc) && info->var.bits_per_pixel == 8 &&
1080 + info->splash.cmap.red != NULL)
1081 + fb_set_cmap(&info->splash.cmap, info);
1083 +out: return fb_set_cmap(&palette_cmap, info);
1086 static u16 *fbcon_screen_pos(struct vc_data *vc, int offset)
1087 @@ -2673,7 +2805,10 @@
1089 /* Clear cursor, restore saved data */
1090 info->cursor.enable = 0;
1091 - info->fbops->fb_cursor(info, &info->cursor);
1092 + if (fbsplash_active(info, vc_cons[info->currcon].d))
1093 + fbsplash_cursor(info, &info->cursor);
1095 + info->fbops->fb_cursor(info, &info->cursor);
1098 static void fbcon_resumed(struct fb_info *info)
1099 @@ -2704,7 +2839,14 @@
1100 var_to_display(p, &info->var, info);
1101 cols = info->var.xres / vc->vc_font.width;
1102 rows = info->var.yres / vc->vc_font.height;
1103 - vc_resize(vc->vc_num, cols, rows);
1105 + if (!fbsplash_active(info, vc)) {
1106 + vc_resize(vc->vc_num, cols, rows);
1108 + if (fbsplash_call_helper("modechange", vc->vc_num))
1109 + fbsplash_disable(vc, 0);
1112 updatescrollmode(p, info, vc);
1114 scrollback_current = 0;
1115 @@ -2842,6 +2984,7 @@
1116 acquire_console_sem();
1117 fb_register_client(&fbcon_event_notifier);
1118 release_console_sem();
1121 for (i = 0; i < MAX_NR_CONSOLES; i++)
1123 diff -Nru a/drivers/video/fbsplash.c b/drivers/video/fbsplash.c
1124 --- /dev/null Wed Dec 31 16:00:00 196900
1125 +++ b/drivers/video/fbsplash.c 2004-08-26 21:34:52 +02:00
1128 + * linux/drivers/video/fbsplash.c -- Framebuffer splash routines
1130 + * Copyright (C) 2004 Michal Januszewski <spock@gentoo.org>
1132 + * Code based upon "Bootsplash" (C) 2001-2003
1133 + * Volker Poplawski <volker@poplawski.de>,
1134 + * Stefan Reinauer <stepan@suse.de>,
1135 + * Steffen Winterfeldt <snwint@suse.de>,
1136 + * Michael Schroeder <mls@suse.de>,
1137 + * Ken Wimer <wimer@suse.de>.
1139 + * Splash render routines are located in /linux/drivers/video/cfbsplash.c
1141 + * This file is subject to the terms and conditions of the GNU General Public
1142 + * License. See the file COPYING in the main directory of this archive for
1146 +#include <linux/config.h>
1147 +#include <linux/module.h>
1148 +#include <linux/kernel.h>
1149 +#include <linux/string.h>
1150 +#include <linux/types.h>
1151 +#include <linux/fb.h>
1152 +#include <linux/vt_kern.h>
1153 +#include <linux/vmalloc.h>
1154 +#include <linux/unistd.h>
1155 +#include <linux/syscalls.h>
1156 +#include <linux/init.h>
1157 +#include <linux/proc_fs.h>
1158 +#include <linux/workqueue.h>
1159 +#include <linux/kmod.h>
1160 +#include <linux/miscdevice.h>
1161 +#include <linux/device.h>
1162 +#include <linux/fs.h>
1164 +#include <asm/uaccess.h>
1165 +#include <asm/irq.h>
1166 +#include <asm/system.h>
1168 +#include "console/fbcon.h"
1169 +#include "fbsplash.h"
1171 +#define SPLASH_VERSION "0.9"
1174 +#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
1176 +#define DPRINTK(fmt, args...)
1179 +static void splash_work_verbose(void *data);
1180 +static int fbsplash_enable(struct vc_data *vc);
1182 +DECLARE_WORK(splash_wq_verbose, splash_work_verbose, NULL);
1184 +int fbsplash_mode = 0;
1185 +char fbsplash_path[KMOD_PATH_LEN] = "/sbin/splash_helper";
1186 +static char fbsplash_theme[FB_SPLASH_THEME_LEN] __initdata = "default";
1188 +int fbsplash_call_helper(char* cmd, unsigned short vc)
1192 + "PATH=/sbin:/bin",
1198 + unsigned char fb = (int) con2fb_map[vc];
1206 + (fbsplash_mode == FB_SPLASH_MODE_SILENT) ? "s" : "v",
1207 + vc_cons[vc].d->vc_splash.theme,
1211 + snprintf(tfb,5,"%d",fb);
1212 + snprintf(tcons,5,"%d",vc);
1214 + return call_usermodehelper(fbsplash_path, argv, envp, 1);
1217 +int fbsplash_verbose(void)
1219 + if (fbsplash_mode == FB_SPLASH_MODE_VERBOSE)
1222 + fbsplash_mode = FB_SPLASH_MODE_VERBOSE;
1224 + /* We have to do the switch from a workqueue helper, because chances are this
1225 + * function gets called from interrupt context, and we can't get hold of the
1226 + * console sem this way. */
1227 + schedule_work(&splash_wq_verbose);
1232 +/* Switches the first console to verbose mode. */
1233 +static void splash_work_verbose(void *data)
1235 + struct fb_info *info;
1236 + struct vc_data *vc;
1238 + vc = vc_cons[0].d;
1239 + info = registered_fb[(int) con2fb_map[vc->vc_num]];
1244 + printk(KERN_INFO "fbsplash: switching to verbose mode\n");
1246 + vt_cons[0]->vc_mode = KD_TEXT;
1248 + acquire_console_sem();
1249 + do_unblank_screen(0);
1251 + if (info->splash.data) {
1252 + fbsplash_enable(vc);
1254 + fbsplash_disable(vc, 1);
1256 + release_console_sem();
1259 +/* Disables fbsplash on a virtual console; called with console sem held. */
1260 +int fbsplash_disable(struct vc_data *vc, unsigned char redraw)
1262 + struct fb_info* info;
1264 + if (!vc->vc_splash.state)
1267 + info = registered_fb[(int) con2fb_map[vc->vc_num]];
1272 + vc->vc_splash.state = 0;
1273 + vc_resize(vc->vc_num, info->var.xres / vc->vc_font.width,
1274 + info->var.yres / vc->vc_font.height);
1276 + if (fg_console == vc->vc_num && redraw) {
1277 + redraw_screen(fg_console, 0);
1278 + update_region(fg_console, vc->vc_origin +
1279 + vc->vc_size_row * vc->vc_top,
1280 + vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2);
1283 + printk(KERN_INFO "fbsplash: switched splash state to 'off' on console %d\n",
1289 +/* Enables fbsplash on a virtual console; called with console sem held. */
1290 +static int fbsplash_enable(struct vc_data *vc)
1292 + struct fb_info* info;
1294 + info = registered_fb[(int) con2fb_map[vc->vc_num]];
1296 + if (vc->vc_splash.twidth == 0 || vc->vc_splash.theight == 0 ||
1297 + info == NULL || !info->splash.data || vc->vc_splash.state)
1300 + vc->vc_splash.state = 1;
1301 + vc_resize(vc->vc_num, vc->vc_splash.twidth / vc->vc_font.width,
1302 + vc->vc_splash.theight / vc->vc_font.height);
1304 + if (fg_console == vc->vc_num) {
1305 + redraw_screen(fg_console, 0);
1306 + update_region(fg_console, vc->vc_origin +
1307 + vc->vc_size_row * vc->vc_top,
1308 + vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2);
1309 + fbsplash_clear_margins(vc, info, 0);
1312 + printk(KERN_INFO "fbsplash: switched splash state to 'on' on console %d\n",
1318 +static int __init splash_setup(char *options)
1322 + while ((this_opt = strsep(&options, ",")) != NULL) {
1324 + if (!strcmp(this_opt, "silent")) {
1325 + fbsplash_mode = FB_SPLASH_MODE_SILENT;
1326 + printk(KERN_INFO "fbsplash: silent\n");
1327 + } else if (!strcmp(this_opt, "verbose")) {
1328 + fbsplash_mode = FB_SPLASH_MODE_VERBOSE;
1329 + printk(KERN_INFO "fbsplash: verbose\n");
1330 + } else if (!strcmp(this_opt, "off")) {
1331 + fbsplash_mode = 0;
1332 + } else if (!strncmp(this_opt, "theme:", 6)) {
1333 + strncpy(fbsplash_theme, this_opt+6, 64);
1334 + printk(KERN_INFO "fbsplash: theme %s\n", fbsplash_theme);
1336 + printk(KERN_WARNING "fbsplash: unrecognized option %s\n", this_opt);
1342 +__setup("splash=", splash_setup);
1344 +static int splash_get_info(char *buf, char **start, off_t fpos, int length)
1348 + p += sprintf(p, "Framebuffer splash v%s, mode: %s\n", SPLASH_VERSION,
1349 + ((fbsplash_mode == 2) ? "silent" : (fbsplash_mode == 1) ? "verbose" : "off"));
1354 +static inline int fbsplash_ioctl_dosetstate(struct vc_data *vc, unsigned int __user* state, unsigned char origin)
1358 + if (get_user(tmp, state))
1361 + if (origin == FB_SPLASH_IO_ORIG_USER)
1362 + acquire_console_sem();
1364 + ret = fbsplash_disable(vc, 1);
1366 + ret = fbsplash_enable(vc);
1367 + if (origin == FB_SPLASH_IO_ORIG_USER)
1368 + release_console_sem();
1373 +static inline int fbsplash_ioctl_dogetstate(struct vc_data *vc, unsigned int __user *state)
1375 + return put_user(vc->vc_splash.state, (unsigned int __user*) state);
1378 +static int fbsplash_ioctl_dosetcfg(struct vc_data *vc, struct vc_splash __user *arg, unsigned char origin)
1380 + struct vc_splash cfg;
1381 + struct fb_info *info;
1385 + info = registered_fb[(int) con2fb_map[vc->vc_num]];
1387 + if (copy_from_user(&cfg, arg, sizeof(struct vc_splash)))
1389 + if (info == NULL || !cfg.twidth || !cfg.theight ||
1390 + cfg.tx + cfg.twidth > info->var.xres ||
1391 + cfg.ty + cfg.theight > info->var.yres)
1394 + len = strlen_user(cfg.theme);
1395 + if (!len || len > FB_SPLASH_THEME_LEN)
1397 + tmp = kmalloc(len, GFP_KERNEL);
1400 + if (copy_from_user(tmp, (void __user *)cfg.theme, len))
1405 + /* If this ioctl is a response to a request from kernel, the console sem
1406 + * is already held; we also don't need to disable splash because either the
1407 + * new config and background picture will be successfully loaded, and the
1408 + * splash will stay on, or in case of a failure it'll be turned off in fbcon. */
1409 + if (origin == FB_SPLASH_IO_ORIG_USER) {
1410 + acquire_console_sem();
1411 + if (vc->vc_splash.state)
1412 + fbsplash_disable(vc, 1);
1415 + if (vc->vc_splash.theme)
1416 + kfree(vc->vc_splash.theme);
1418 + vc->vc_splash = cfg;
1420 + if (origin == FB_SPLASH_IO_ORIG_USER)
1421 + release_console_sem();
1423 + printk(KERN_INFO "fbsplash: console %d using theme '%s'\n",
1424 + vc->vc_num, vc->vc_splash.theme);
1428 +static int fbsplash_ioctl_dogetcfg(struct vc_data *vc, struct vc_splash __user *arg)
1430 + struct vc_splash splash;
1433 + if (get_user(tmp, &arg->theme))
1436 + splash = vc->vc_splash;
1437 + splash.theme = tmp;
1439 + if (vc->vc_splash.theme) {
1440 + if (copy_to_user(tmp, vc->vc_splash.theme, strlen(vc->vc_splash.theme) + 1))
1443 + if (put_user(0, tmp))
1446 + if (copy_to_user(arg, &splash, sizeof(struct vc_splash)))
1452 +static int fbsplash_ioctl_dosetpic(struct vc_data *vc, struct fb_image __user *arg, unsigned char origin)
1454 + struct fb_image img;
1455 + struct fb_info *info;
1459 + if (vc->vc_num != fg_console)
1462 + info = registered_fb[(int) con2fb_map[vc->vc_num]];
1467 + if (copy_from_user(&img, arg, sizeof(struct fb_image)))
1470 + if (img.width != info->var.xres || img.height != info->var.yres) {
1471 + printk(KERN_ERR "fbsplash: picture dimensions mismatch\n");
1475 + if (img.depth != info->var.bits_per_pixel) {
1476 + printk(KERN_ERR "fbsplash: picture depth mismatch\n");
1480 + if (img.depth == 8) {
1481 + if (!img.cmap.len || !img.cmap.red || !img.cmap.green ||
1485 + tmp = vmalloc(img.cmap.len * 3 * 2);
1489 + if (copy_from_user(tmp, (void __user*)img.cmap.red, img.cmap.len * 2) ||
1490 + copy_from_user(tmp + (img.cmap.len << 1),
1491 + (void __user*)img.cmap.green, (img.cmap.len << 1)) ||
1492 + copy_from_user(tmp + (img.cmap.len << 2),
1493 + (void __user*)img.cmap.blue, (img.cmap.len << 1))) {
1498 + img.cmap.transp = NULL;
1499 + img.cmap.red = (u16*)tmp;
1500 + img.cmap.green = img.cmap.red + img.cmap.len;
1501 + img.cmap.blue = img.cmap.green + img.cmap.len;
1503 + img.cmap.red = NULL;
1506 + len = ((img.depth + 7) >> 3) * img.width * img.height;
1507 + tmp = vmalloc(len);
1512 + if (copy_from_user(tmp, (void __user*)img.data, len))
1517 + /* If this ioctl is a response to a request from kernel, the console sem
1518 + * is already held. */
1519 + if (origin == FB_SPLASH_IO_ORIG_USER)
1520 + acquire_console_sem();
1522 + if (info->splash.data)
1523 + vfree((u8*)info->splash.data);
1524 + if (info->splash.cmap.red)
1525 + vfree(info->splash.cmap.red);
1527 + info->splash = img;
1529 + if (origin == FB_SPLASH_IO_ORIG_USER)
1530 + release_console_sem();
1534 +out: if (img.cmap.red)
1535 + vfree(img.cmap.red);
1541 +static int splash_ioctl(struct inode * inode, struct file *filp, u_int cmd,
1544 + struct fb_splash_iowrapper __user *wrapper = (void __user*) arg;
1545 + struct vc_data *vc = NULL;
1546 + unsigned short vc_num = 0;
1547 + unsigned char origin = 0;
1548 + void __user *data = NULL;
1550 + if (cmd != FBIOSPLASH_SETMODE && cmd != FBIOSPLASH_GETMODE)
1552 + if (verify_area(VERIFY_READ, wrapper,
1553 + sizeof(struct fb_splash_iowrapper)))
1556 + __get_user(vc_num, &wrapper->vc);
1557 + __get_user(origin, &wrapper->origin);
1558 + __get_user(data, &wrapper->data);
1560 + if (!vc_cons_allocated(vc_num))
1563 + vc = vc_cons[vc_num].d;
1568 + case FBIOSPLASH_SETMODE:
1569 + if (arg != FB_SPLASH_MODE_SILENT && arg != FB_SPLASH_MODE_VERBOSE)
1572 + if (fbsplash_mode == arg)
1575 + fbsplash_mode = arg;
1576 + if (arg == FB_SPLASH_MODE_VERBOSE)
1577 + splash_work_verbose(NULL);
1580 + case FBIOSPLASH_GETMODE:
1581 + return put_user(fbsplash_mode, (unsigned int __user *)arg);
1582 + case FBIOSPLASH_SETPIC:
1583 + return fbsplash_ioctl_dosetpic(vc, (struct fb_image __user*)data, origin);
1584 + case FBIOSPLASH_SETCFG:
1585 + return fbsplash_ioctl_dosetcfg(vc, (struct vc_splash*)data, origin);
1586 + case FBIOSPLASH_GETCFG:
1587 + return fbsplash_ioctl_dogetcfg(vc, (struct vc_splash*)data);
1588 + case FBIOSPLASH_SETSTATE:
1589 + return fbsplash_ioctl_dosetstate(vc, (unsigned int *)data, origin);
1590 + case FBIOSPLASH_GETSTATE:
1591 + return fbsplash_ioctl_dogetstate(vc, (unsigned int *)data);
1593 + return -ENOIOCTLCMD;
1597 +static struct file_operations splash_ops = {
1598 + .owner = THIS_MODULE,
1599 + .ioctl = splash_ioctl
1602 +static struct miscdevice splash_dev = {
1603 + .minor = MISC_DYNAMIC_MINOR,
1604 + .name = "fbsplash",
1605 + .fops = &splash_ops
1608 +int fbsplash_init(void)
1610 + struct proc_dir_entry *splash_proc;
1611 + struct fb_info *info;
1612 + struct vc_data *vc;
1615 + vc = vc_cons[0].d;
1616 + info = registered_fb[0];
1618 + for (i = 0; i < num_registered_fb; i++) {
1619 + registered_fb[i]->splash.data = NULL;
1620 + registered_fb[i]->splash.cmap.red = NULL;
1623 + for (i = 0; i < MAX_NR_CONSOLES && vc_cons[i].d; i++) {
1624 + vc_cons[i].d->vc_splash.state = vc_cons[i].d->vc_splash.twidth =
1625 + vc_cons[i].d->vc_splash.theight = 0;
1626 + vc_cons[i].d->vc_splash.theme = NULL;
1629 + i = misc_register(&splash_dev);
1631 + printk(KERN_ERR "fbsplash: failed to register device\n");
1635 +#ifdef CONFIG_PROC_FS
1636 + splash_proc = create_proc_info_entry("fbsplash", 0, NULL, splash_get_info);
1638 + splash_proc->owner = THIS_MODULE;
1641 + if (fbsplash_mode && info) {
1642 + vc->vc_splash.theme = kmalloc((strlen(fbsplash_theme)+1) * sizeof(char), GFP_KERNEL);
1643 + strcpy(vc->vc_splash.theme, fbsplash_theme);
1644 + if (fbsplash_call_helper("init", 0))
1645 + fbsplash_mode = FB_SPLASH_MODE_VERBOSE;
1647 + fbsplash_mode = FB_SPLASH_MODE_VERBOSE;
1653 +EXPORT_SYMBOL(fbsplash_path);
1654 diff -Nru a/drivers/video/fbsplash.h b/drivers/video/fbsplash.h
1655 --- /dev/null Wed Dec 31 16:00:00 196900
1656 +++ b/drivers/video/fbsplash.h 2004-08-26 21:34:52 +02:00
1659 + * linux/drivers/video/fbsplash.h -- Framebuffer splash headers
1661 + * Copyright (C) 2004 Michal Januszewski <spock@gentoo.org>
1665 +#ifndef __FB_SPLASH_H
1666 +#define __FB_SPLASH_H
1668 +#ifndef _LINUX_FB_H
1669 +#include <linux/fb.h>
1676 +#ifdef CONFIG_FB_SPLASH
1678 +int fbsplash_init(void);
1679 +int fbsplash_verbose(void);
1680 +int fbsplash_call_helper(char* cmd, unsigned short cons);
1681 +int fbsplash_disable(struct vc_data *vc, unsigned char redraw);
1684 +void fbsplash_putcs(struct vc_data *vc, struct fb_info *info, const unsigned short *s, int count, int yy, int xx);
1685 +void fbsplash_putc(struct vc_data *vc, struct fb_info *info, int c, int ypos, int xpos);
1686 +void fbsplash_cursor(struct fb_info *info, struct fb_cursor *cursor);
1687 +void fbsplash_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx, int height, int width);
1688 +void fbsplash_clear_margins(struct vc_data *vc, struct fb_info *info, int bottom_only);
1689 +void fbsplash_blank(struct vc_data *vc, struct fb_info *info, int blank);
1690 +void fbsplash_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y, int sx, int dx, int width);
1691 +void fbsplash_copy(u8 *dst, u8 *src, int height, int width, int linebytes, int bpp);
1694 +void acquire_console_sem(void);
1695 +void release_console_sem(void);
1696 +void do_unblank_screen(int entering_gfx);
1698 +extern int fbsplash_mode;
1699 +#define fbsplash_isverbose (fbsplash_mode == FB_SPLASH_MODE_VERBOSE)
1700 +#define fbsplash_issilent (fbsplash_mode == FB_SPLASH_MODE_SILENT)
1702 +/* struct vc_data *y */
1703 +#define fbsplash_active_vc(y) (y->vc_splash.state && y->vc_splash.theme)
1705 +/* struct fb_info *x, struct vc_data *y */
1706 +#define fbsplash_active(x,y) (x->splash.data && fbsplash_active_vc(y) && \
1707 + x->splash.width == x->var.xres && \
1708 + x->splash.height == x->var.yres && \
1709 + x->splash.depth == x->var.bits_per_pixel)
1711 +#else /* CONFIG_FB_SPLASH */
1713 +static inline void fbsplash_putcs(struct vc_data *vc, struct fb_info *info, const unsigned short *s, int count, int yy, int xx) {}
1714 +static inline void fbsplash_putc(struct vc_data *vc, struct fb_info *info, int c, int ypos, int xpos) {}
1715 +static inline void fbsplash_cursor(struct fb_info *info, struct fb_cursor *cursor) {}
1716 +static inline void fbsplash_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx, int height, int width) {}
1717 +static inline void fbsplash_clear_margins(struct vc_data *vc, struct fb_info *info, int bottom_only) {}
1718 +static inline void fbsplash_blank(struct vc_data *vc, struct fb_info *info, int blank) {}
1719 +static inline void fbsplash_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y, int sx, int dx, int width) {}
1720 +static inline int fbsplash_call_helper(char* cmd, unsigned short cons) { return 0; }
1721 +static inline int fbsplash_init(void) { return 0; }
1722 +static inline int fbsplash_verbose(void) { return 0; }
1723 +static inline int fbsplash_disable(struct vc_data *vc, unsigned char redraw) { return 0; }
1725 +#define fbsplash_issilent (0)
1726 +#define fbsplash_isverbose (1)
1727 +#define fbsplash_active_vc(y) (0)
1728 +#define fbsplash_active(x,y) (0)
1730 +#endif /* CONFIG_FB_SPLASH */
1732 +#endif /* __FB_SPLASH_H */
1733 diff -Nru a/include/linux/console_splash.h b/include/linux/console_splash.h
1734 --- /dev/null Wed Dec 31 16:00:00 196900
1735 +++ b/include/linux/console_splash.h 2004-08-26 21:34:52 +02:00
1737 +#ifndef _LINUX_CONSOLE_SPLASH_H_
1738 +#define _LINUX_CONSOLE_SPLASH_H_ 1
1740 +/* A structure used by the framebuffer splash code (drivers/video/fbsplash.c) */
1742 + __u8 bg_color; /* The color that is to be treated as transparent */
1743 + __u8 state; /* Current splash state: 0 = off, 1 = on */
1744 + __u16 tx, ty; /* Top left corner coordinates of the text field */
1745 + __u16 twidth, theight; /* Width and height of the text field */
1750 diff -Nru a/include/linux/console_struct.h b/include/linux/console_struct.h
1751 --- a/include/linux/console_struct.h 2004-08-26 21:34:52 +02:00
1752 +++ b/include/linux/console_struct.h 2004-08-26 21:34:52 +02:00
1757 +#include <linux/console_splash.h>
1760 unsigned short vc_num; /* Console number */
1762 struct vc_data **vc_display_fg; /* [!] Ptr to var holding fg console for this display */
1763 unsigned long vc_uni_pagedir;
1764 unsigned long *vc_uni_pagedir_loc; /* [!] Location of uni_pagedir variable for this console */
1766 + struct vc_splash vc_splash;
1767 /* additional information is in vt_kern.h */
1770 diff -Nru a/include/linux/fb.h b/include/linux/fb.h
1771 --- a/include/linux/fb.h 2004-08-26 21:34:52 +02:00
1772 +++ b/include/linux/fb.h 2004-08-26 21:34:52 +02:00
1775 #define FB_MAX 32 /* sufficient for now */
1777 +struct fb_splash_iowrapper
1779 + unsigned short vc; /* Virtual console */
1780 + unsigned char origin; /* Point of origin of the request */
1786 #define FBIOGET_VSCREENINFO 0x4600
1788 #define FBIOGET_HWCINFO 0x4616
1789 #define FBIOPUT_MODEINFO 0x4617
1790 #define FBIOGET_DISPINFO 0x4618
1792 +#define FBIOSPLASH_SETCFG _IOWR('F', 0x19, struct fb_splash_iowrapper)
1793 +#define FBIOSPLASH_GETCFG _IOR('F', 0x1A, struct fb_splash_iowrapper)
1794 +#define FBIOSPLASH_SETSTATE _IOWR('F', 0x1B, struct fb_splash_iowrapper)
1795 +#define FBIOSPLASH_GETSTATE _IOR('F', 0x1C, struct fb_splash_iowrapper)
1796 +#define FBIOSPLASH_SETMODE _IOWR('F', 0x1D, unsigned int)
1797 +#define FBIOSPLASH_GETMODE _IOR('F', 0x1E, unsigned int)
1798 +#define FBIOSPLASH_SETPIC _IOWR('F', 0x1F, struct fb_splash_iowrapper)
1800 +#define FB_SPLASH_MODE_VERBOSE 1 /* Verbose mode */
1801 +#define FB_SPLASH_MODE_SILENT 2 /* Silent mode */
1802 +#define FB_SPLASH_THEME_LEN 128 /* Maximum lenght of a theme name */
1803 +#define FB_SPLASH_IO_ORIG_KERNEL 0 /* Kernel ioctl origin */
1804 +#define FB_SPLASH_IO_ORIG_USER 1 /* User ioctl origin */
1806 #define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */
1807 #define FB_TYPE_PLANES 1 /* Non interleaved planes */
1809 #define FBINFO_STATE_RUNNING 0
1810 #define FBINFO_STATE_SUSPENDED 1
1811 u32 state; /* Hardware state i.e suspend */
1813 + struct fb_image splash;
1815 /* From here on everything is device dependent */
1817 diff -Nru a/include/linux/sysctl.h b/include/linux/sysctl.h
1818 --- a/include/linux/sysctl.h 2004-08-26 21:34:52 +02:00
1819 +++ b/include/linux/sysctl.h 2004-08-26 21:34:52 +02:00
1821 KERN_SPARC_SCONS_PWROFF=64, /* int: serial console power-off halt */
1822 KERN_HZ_TIMER=65, /* int: hz timer on or off */
1823 KERN_UNKNOWN_NMI_PANIC=66, /* int: unknown nmi panic flag */
1824 + KERN_FBSPLASH=67, /* string: path to fbsplash helper */
1828 diff -Nru a/kernel/panic.c b/kernel/panic.c
1829 --- a/kernel/panic.c 2004-08-26 21:34:52 +02:00
1830 +++ b/kernel/panic.c 2004-08-26 21:34:52 +02:00
1832 #include <linux/syscalls.h>
1833 #include <linux/interrupt.h>
1834 #include <linux/nmi.h>
1835 +#include "../drivers/video/fbsplash.h"
1840 * We can't use the "normal" timers since we just panicked..
1842 printk(KERN_EMERG "Rebooting in %d seconds..",panic_timeout);
1843 + fbsplash_verbose();
1845 for (i = 0; i < panic_timeout; i++) {
1846 touch_nmi_watchdog();
1849 disabled_wait(caller);
1852 + fbsplash_verbose();
1857 diff -Nru a/kernel/power/console.c b/kernel/power/console.c
1858 --- a/kernel/power/console.c 2004-08-26 21:34:52 +02:00
1859 +++ b/kernel/power/console.c 2004-08-26 21:34:52 +02:00
1861 #include <linux/console.h>
1864 +#include "../drivers/video/fbsplash.h"
1866 static int new_loglevel = 10;
1867 static int orig_loglevel;
1868 static int orig_fgconsole, orig_kmsg;
1870 console_loglevel = new_loglevel;
1872 #ifdef SUSPEND_CONSOLE
1873 + if (fbsplash_issilent)
1874 + fbsplash_verbose();
1876 acquire_console_sem();
1878 orig_fgconsole = fg_console;
1879 diff -Nru a/kernel/sysctl.c b/kernel/sysctl.c
1880 --- a/kernel/sysctl.c 2004-08-26 21:34:52 +02:00
1881 +++ b/kernel/sysctl.c 2004-08-26 21:34:52 +02:00
1883 #ifdef CONFIG_HOTPLUG
1884 extern char hotplug_path[];
1886 +#ifdef CONFIG_FB_SPLASH
1887 +extern char fbsplash_path[];
1889 #ifdef CONFIG_CHR_DEV_SG
1890 extern int sg_big_buff;
1892 @@ -409,6 +412,17 @@
1893 .ctl_name = KERN_HOTPLUG,
1894 .procname = "hotplug",
1895 .data = &hotplug_path,
1896 + .maxlen = KMOD_PATH_LEN,
1898 + .proc_handler = &proc_dostring,
1899 + .strategy = &sysctl_string,
1902 +#ifdef CONFIG_FB_SPLASH
1904 + .ctl_name = KERN_FBSPLASH,
1905 + .procname = "fbsplash",
1906 + .data = &fbsplash_path,
1907 .maxlen = KMOD_PATH_LEN,
1909 .proc_handler = &proc_dostring,