Gentoo Archives: gentoo-commits

From: Mike Pagano <mpagano@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/linux-patches:4.8 commit in: /
Date: Tue, 11 Oct 2016 00:07:51
Message-Id: 1476144451.87cd8ce6b13f62532e383db6302117fd51ed9f62.mpagano@gentoo
1 commit: 87cd8ce6b13f62532e383db6302117fd51ed9f62
2 Author: Mike Pagano <mpagano <AT> gentoo <DOT> org>
3 AuthorDate: Tue Oct 11 00:07:31 2016 +0000
4 Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org>
5 CommitDate: Tue Oct 11 00:07:31 2016 +0000
6 URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=87cd8ce6
7
8 Bootsplash ported by Uladzimir Bely. (Bug #596126)
9
10 0000_README | 4 +
11 4200_fbcondecor.patch | 2095 +++++++++++++++++++++++++++++++++++++++++++++++++
12 2 files changed, 2099 insertions(+)
13
14 diff --git a/0000_README b/0000_README
15 index 55d306f..4af14fd 100644
16 --- a/0000_README
17 +++ b/0000_README
18 @@ -59,6 +59,10 @@ Patch: 2900_dev-root-proc-mount-fix.patch
19 From: https://bugs.gentoo.org/show_bug.cgi?id=438380
20 Desc: Ensure that /dev/root doesn't appear in /proc/mounts when bootint without an initramfs.
21
22 +Patch: 4200_fbcondecor.patch
23 +From: http://www.mepiscommunity.org/fbcondecor
24 +Desc: Bootsplash ported by Uladzimir Bely. (Bug #596126)
25 +
26 Patch: 4400_alpha-sysctl-uac.patch
27 From: Tobias Klausmann (klausman@g.o) and http://bugs.gentoo.org/show_bug.cgi?id=217323
28 Desc: Enable control of the unaligned access control policy from sysctl
29
30 diff --git a/4200_fbcondecor.patch b/4200_fbcondecor.patch
31 new file mode 100644
32 index 0000000..f7d9879
33 --- /dev/null
34 +++ b/4200_fbcondecor.patch
35 @@ -0,0 +1,2095 @@
36 +diff --git a/Documentation/fb/00-INDEX b/Documentation/fb/00-INDEX
37 +index fe85e7c..2230930 100644
38 +--- a/Documentation/fb/00-INDEX
39 ++++ b/Documentation/fb/00-INDEX
40 +@@ -23,6 +23,8 @@ ep93xx-fb.txt
41 + - info on the driver for EP93xx LCD controller.
42 + fbcon.txt
43 + - intro to and usage guide for the framebuffer console (fbcon).
44 ++fbcondecor.txt
45 ++ - info on the Framebuffer Console Decoration
46 + framebuffer.txt
47 + - introduction to frame buffer devices.
48 + gxfb.txt
49 +diff --git a/Documentation/fb/fbcondecor.txt b/Documentation/fb/fbcondecor.txt
50 +new file mode 100644
51 +index 0000000..637209e
52 +--- /dev/null
53 ++++ b/Documentation/fb/fbcondecor.txt
54 +@@ -0,0 +1,207 @@
55 ++What is it?
56 ++-----------
57 ++
58 ++The framebuffer decorations are a kernel feature which allows displaying a
59 ++background picture on selected consoles.
60 ++
61 ++What do I need to get it to work?
62 ++---------------------------------
63 ++
64 ++To get fbcondecor up-and-running you will have to:
65 ++ 1) get a copy of splashutils [1] or a similar program
66 ++ 2) get some fbcondecor themes
67 ++ 3) build the kernel helper program
68 ++ 4) build your kernel with the FB_CON_DECOR option enabled.
69 ++
70 ++To get fbcondecor operational right after fbcon initialization is finished, you
71 ++will have to include a theme and the kernel helper into your initramfs image.
72 ++Please refer to splashutils documentation for instructions on how to do that.
73 ++
74 ++[1] The splashutils package can be downloaded from:
75 ++ http://github.com/alanhaggai/fbsplash
76 ++
77 ++The userspace helper
78 ++--------------------
79 ++
80 ++The userspace fbcondecor helper (by default: /sbin/fbcondecor_helper) is called by the
81 ++kernel whenever an important event occurs and the kernel needs some kind of
82 ++job to be carried out. Important events include console switches and video
83 ++mode switches (the kernel requests background images and configuration
84 ++parameters for the current console). The fbcondecor helper must be accessible at
85 ++all times. If it's not, fbcondecor will be switched off automatically.
86 ++
87 ++It's possible to set path to the fbcondecor helper by writing it to
88 ++/proc/sys/kernel/fbcondecor.
89 ++
90 ++*****************************************************************************
91 ++
92 ++The information below is mostly technical stuff. There's probably no need to
93 ++read it unless you plan to develop a userspace helper.
94 ++
95 ++The fbcondecor protocol
96 ++-----------------------
97 ++
98 ++The fbcondecor protocol defines a communication interface between the kernel and
99 ++the userspace fbcondecor helper.
100 ++
101 ++The kernel side is responsible for:
102 ++
103 ++ * rendering console text, using an image as a background (instead of a
104 ++ standard solid color fbcon uses),
105 ++ * accepting commands from the user via ioctls on the fbcondecor device,
106 ++ * calling the userspace helper to set things up as soon as the fb subsystem
107 ++ is initialized.
108 ++
109 ++The userspace helper is responsible for everything else, including parsing
110 ++configuration files, decompressing the image files whenever the kernel needs
111 ++it, and communicating with the kernel if necessary.
112 ++
113 ++The fbcondecor protocol specifies how communication is done in both ways:
114 ++kernel->userspace and userspace->helper.
115 ++
116 ++Kernel -> Userspace
117 ++-------------------
118 ++
119 ++The kernel communicates with the userspace helper by calling it and specifying
120 ++the task to be done in a series of arguments.
121 ++
122 ++The arguments follow the pattern:
123 ++<fbcondecor protocol version> <command> <parameters>
124 ++
125 ++All commands defined in fbcondecor protocol v2 have the following parameters:
126 ++ virtual console
127 ++ framebuffer number
128 ++ theme
129 ++
130 ++Fbcondecor protocol v1 specified an additional 'fbcondecor mode' after the
131 ++framebuffer number. Fbcondecor protocol v1 is deprecated and should not be used.
132 ++
133 ++Fbcondecor protocol v2 specifies the following commands:
134 ++
135 ++getpic
136 ++------
137 ++ The kernel issues this command to request image data. It's up to the
138 ++ userspace helper to find a background image appropriate for the specified
139 ++ theme and the current resolution. The userspace helper should respond by
140 ++ issuing the FBIOCONDECOR_SETPIC ioctl.
141 ++
142 ++init
143 ++----
144 ++ The kernel issues this command after the fbcondecor device is created and
145 ++ the fbcondecor interface is initialized. Upon receiving 'init', the userspace
146 ++ helper should parse the kernel command line (/proc/cmdline) or otherwise
147 ++ decide whether fbcondecor is to be activated.
148 ++
149 ++ To activate fbcondecor on the first console the helper should issue the
150 ++ FBIOCONDECOR_SETCFG, FBIOCONDECOR_SETPIC and FBIOCONDECOR_SETSTATE commands,
151 ++ in the above-mentioned order.
152 ++
153 ++ When the userspace helper is called in an early phase of the boot process
154 ++ (right after the initialization of fbcon), no filesystems will be mounted.
155 ++ The helper program should mount sysfs and then create the appropriate
156 ++ framebuffer, fbcondecor and tty0 devices (if they don't already exist) to get
157 ++ current display settings and to be able to communicate with the kernel side.
158 ++ It should probably also mount the procfs to be able to parse the kernel
159 ++ command line parameters.
160 ++
161 ++ Note that the console sem is not held when the kernel calls fbcondecor_helper
162 ++ with the 'init' command. The fbcondecor helper should perform all ioctls with
163 ++ origin set to FBCON_DECOR_IO_ORIG_USER.
164 ++
165 ++modechange
166 ++----------
167 ++ The kernel issues this command on a mode change. The helper's response should
168 ++ be similar to the response to the 'init' command. Note that this time the
169 ++ console sem is held and all ioctls must be performed with origin set to
170 ++ FBCON_DECOR_IO_ORIG_KERNEL.
171 ++
172 ++
173 ++Userspace -> Kernel
174 ++-------------------
175 ++
176 ++Userspace programs can communicate with fbcondecor via ioctls on the
177 ++fbcondecor device. These ioctls are to be used by both the userspace helper
178 ++(called only by the kernel) and userspace configuration tools (run by the users).
179 ++
180 ++The fbcondecor helper should set the origin field to FBCON_DECOR_IO_ORIG_KERNEL
181 ++when doing the appropriate ioctls. All userspace configuration tools should
182 ++use FBCON_DECOR_IO_ORIG_USER. Failure to set the appropriate value in the origin
183 ++field when performing ioctls from the kernel helper will most likely result
184 ++in a console deadlock.
185 ++
186 ++FBCON_DECOR_IO_ORIG_KERNEL instructs fbcondecor not to try to acquire the console
187 ++semaphore. Not surprisingly, FBCON_DECOR_IO_ORIG_USER instructs it to acquire
188 ++the console sem.
189 ++
190 ++The framebuffer console decoration provides the following ioctls (all defined in
191 ++linux/fb.h):
192 ++
193 ++FBIOCONDECOR_SETPIC
194 ++description: loads a background picture for a virtual console
195 ++argument: struct fbcon_decor_iowrapper*; data: struct fb_image*
196 ++notes:
197 ++If called for consoles other than the current foreground one, the picture data
198 ++will be ignored.
199 ++
200 ++If the current virtual console is running in a 8-bpp mode, the cmap substruct
201 ++of fb_image has to be filled appropriately: start should be set to 16 (first
202 ++16 colors are reserved for fbcon), len to a value <= 240 and red, green and
203 ++blue should point to valid cmap data. The transp field is ingored. The fields
204 ++dx, dy, bg_color, fg_color in fb_image are ignored as well.
205 ++
206 ++FBIOCONDECOR_SETCFG
207 ++description: sets the fbcondecor config for a virtual console
208 ++argument: struct fbcon_decor_iowrapper*; data: struct vc_decor*
209 ++notes: The structure has to be filled with valid data.
210 ++
211 ++FBIOCONDECOR_GETCFG
212 ++description: gets the fbcondecor config for a virtual console
213 ++argument: struct fbcon_decor_iowrapper*; data: struct vc_decor*
214 ++
215 ++FBIOCONDECOR_SETSTATE
216 ++description: sets the fbcondecor state for a virtual console
217 ++argument: struct fbcon_decor_iowrapper*; data: unsigned int*
218 ++ values: 0 = disabled, 1 = enabled.
219 ++
220 ++FBIOCONDECOR_GETSTATE
221 ++description: gets the fbcondecor state for a virtual console
222 ++argument: struct fbcon_decor_iowrapper*; data: unsigned int*
223 ++ values: as in FBIOCONDECOR_SETSTATE
224 ++
225 ++Info on used structures:
226 ++
227 ++Definition of struct vc_decor can be found in linux/console_decor.h. It's
228 ++heavily commented. Note that the 'theme' field should point to a string
229 ++no longer than FBCON_DECOR_THEME_LEN. When FBIOCONDECOR_GETCFG call is
230 ++performed, the theme field should point to a char buffer of length
231 ++FBCON_DECOR_THEME_LEN.
232 ++
233 ++Definition of struct fbcon_decor_iowrapper can be found in linux/fb.h.
234 ++The fields in this struct have the following meaning:
235 ++
236 ++vc:
237 ++Virtual console number.
238 ++
239 ++origin:
240 ++Specifies if the ioctl is performed as a response to a kernel request. The
241 ++fbcondecor helper should set this field to FBCON_DECOR_IO_ORIG_KERNEL, userspace
242 ++programs should set it to FBCON_DECOR_IO_ORIG_USER. This field is necessary to
243 ++avoid console semaphore deadlocks.
244 ++
245 ++data:
246 ++Pointer to a data structure appropriate for the performed ioctl. Type of
247 ++the data struct is specified in the ioctls description.
248 ++
249 ++*****************************************************************************
250 ++
251 ++Credit
252 ++------
253 ++
254 ++Original 'bootsplash' project & implementation by:
255 ++ Volker Poplawski <volker@×××××××××.de>, Stefan Reinauer <stepan@××××.de>,
256 ++ Steffen Winterfeldt <snwint@××××.de>, Michael Schroeder <mls@××××.de>,
257 ++ Ken Wimer <wimer@××××.de>.
258 ++
259 ++Fbcondecor, fbcondecor protocol design, current implementation & docs by:
260 ++ Michal Januszewski <michalj+fbcondecor@×××××.com>
261 ++
262 +diff --git a/drivers/Makefile b/drivers/Makefile
263 +index 53abb4a..1721aee 100644
264 +--- a/drivers/Makefile
265 ++++ b/drivers/Makefile
266 +@@ -17,6 +17,10 @@ obj-y += pwm/
267 + obj-$(CONFIG_PCI) += pci/
268 + obj-$(CONFIG_PARISC) += parisc/
269 + obj-$(CONFIG_RAPIDIO) += rapidio/
270 ++# tty/ comes before char/ so that the VT console is the boot-time
271 ++# default.
272 ++obj-y += tty/
273 ++obj-y += char/
274 + obj-y += video/
275 + obj-y += idle/
276 +
277 +@@ -45,11 +49,6 @@ obj-$(CONFIG_REGULATOR) += regulator/
278 + # reset controllers early, since gpu drivers might rely on them to initialize
279 + obj-$(CONFIG_RESET_CONTROLLER) += reset/
280 +
281 +-# tty/ comes before char/ so that the VT console is the boot-time
282 +-# default.
283 +-obj-y += tty/
284 +-obj-y += char/
285 +-
286 + # iommu/ comes before gpu as gpu are using iommu controllers
287 + obj-$(CONFIG_IOMMU_SUPPORT) += iommu/
288 +
289 +diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
290 +index 38da6e2..fe58152 100644
291 +--- a/drivers/video/console/Kconfig
292 ++++ b/drivers/video/console/Kconfig
293 +@@ -130,6 +130,19 @@ config FRAMEBUFFER_CONSOLE_ROTATION
294 + such that other users of the framebuffer will remain normally
295 + oriented.
296 +
297 ++config FB_CON_DECOR
298 ++ bool "Support for the Framebuffer Console Decorations"
299 ++ depends on FRAMEBUFFER_CONSOLE=y && !FB_TILEBLITTING
300 ++ default n
301 ++ ---help---
302 ++ This option enables support for framebuffer console decorations which
303 ++ makes it possible to display images in the background of the system
304 ++ consoles. Note that userspace utilities are necessary in order to take
305 ++ advantage of these features. Refer to Documentation/fb/fbcondecor.txt
306 ++ for more information.
307 ++
308 ++ If unsure, say N.
309 ++
310 + config STI_CONSOLE
311 + bool "STI text console"
312 + depends on PARISC
313 +diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile
314 +index 43bfa48..cc104b6 100644
315 +--- a/drivers/video/console/Makefile
316 ++++ b/drivers/video/console/Makefile
317 +@@ -16,4 +16,5 @@ obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon_rotate.o fbcon_cw.o fbcon_ud.o \
318 + fbcon_ccw.o
319 + endif
320 +
321 ++obj-$(CONFIG_FB_CON_DECOR) += fbcondecor.o cfbcondecor.o
322 + obj-$(CONFIG_FB_STI) += sticore.o
323 +diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
324 +index dbfe4ee..14da307 100644
325 +--- a/drivers/video/console/bitblit.c
326 ++++ b/drivers/video/console/bitblit.c
327 +@@ -18,6 +18,7 @@
328 + #include <linux/console.h>
329 + #include <asm/types.h>
330 + #include "fbcon.h"
331 ++#include "fbcondecor.h"
332 +
333 + /*
334 + * Accelerated handlers.
335 +@@ -55,6 +56,13 @@ static void bit_bmove(struct vc_data *vc, struct fb_info *info, int sy,
336 + area.height = height * vc->vc_font.height;
337 + area.width = width * vc->vc_font.width;
338 +
339 ++ if (fbcon_decor_active(info, vc)) {
340 ++ area.sx += vc->vc_decor.tx;
341 ++ area.sy += vc->vc_decor.ty;
342 ++ area.dx += vc->vc_decor.tx;
343 ++ area.dy += vc->vc_decor.ty;
344 ++ }
345 ++
346 + info->fbops->fb_copyarea(info, &area);
347 + }
348 +
349 +@@ -379,11 +387,15 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
350 + cursor.image.depth = 1;
351 + cursor.rop = ROP_XOR;
352 +
353 +- if (info->fbops->fb_cursor)
354 +- err = info->fbops->fb_cursor(info, &cursor);
355 ++ if (fbcon_decor_active(info, vc)) {
356 ++ fbcon_decor_cursor(info, &cursor);
357 ++ } else {
358 ++ if (info->fbops->fb_cursor)
359 ++ err = info->fbops->fb_cursor(info, &cursor);
360 +
361 +- if (err)
362 +- soft_cursor(info, &cursor);
363 ++ if (err)
364 ++ soft_cursor(info, &cursor);
365 ++ }
366 +
367 + ops->cursor_reset = 0;
368 + }
369 +diff --git a/drivers/video/console/cfbcondecor.c b/drivers/video/console/cfbcondecor.c
370 +new file mode 100644
371 +index 0000000..c262540
372 +--- /dev/null
373 ++++ b/drivers/video/console/cfbcondecor.c
374 +@@ -0,0 +1,473 @@
375 ++/*
376 ++ * linux/drivers/video/cfbcon_decor.c -- Framebuffer decor render functions
377 ++ *
378 ++ * Copyright (C) 2004 Michal Januszewski <michalj+fbcondecor@×××××.com>
379 ++ *
380 ++ * Code based upon "Bootdecor" (C) 2001-2003
381 ++ * Volker Poplawski <volker@×××××××××.de>,
382 ++ * Stefan Reinauer <stepan@××××.de>,
383 ++ * Steffen Winterfeldt <snwint@××××.de>,
384 ++ * Michael Schroeder <mls@××××.de>,
385 ++ * Ken Wimer <wimer@××××.de>.
386 ++ *
387 ++ * This file is subject to the terms and conditions of the GNU General Public
388 ++ * License. See the file COPYING in the main directory of this archive for
389 ++ * more details.
390 ++ */
391 ++#include <linux/module.h>
392 ++#include <linux/types.h>
393 ++#include <linux/fb.h>
394 ++#include <linux/selection.h>
395 ++#include <linux/slab.h>
396 ++#include <linux/vt_kern.h>
397 ++#include <asm/irq.h>
398 ++
399 ++#include "fbcon.h"
400 ++#include "fbcondecor.h"
401 ++
402 ++#define parse_pixel(shift, bpp, type) \
403 ++ do { \
404 ++ if (d & (0x80 >> (shift))) \
405 ++ dd2[(shift)] = fgx; \
406 ++ else \
407 ++ dd2[(shift)] = transparent ? *(type *)decor_src : bgx; \
408 ++ decor_src += (bpp); \
409 ++ } while (0) \
410 ++
411 ++extern int get_color(struct vc_data *vc, struct fb_info *info,
412 ++ u16 c, int is_fg);
413 ++
414 ++void fbcon_decor_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc)
415 ++{
416 ++ int i, j, k;
417 ++ int minlen = min(min(info->var.red.length, info->var.green.length),
418 ++ info->var.blue.length);
419 ++ u32 col;
420 ++
421 ++ for (j = i = 0; i < 16; i++) {
422 ++ k = color_table[i];
423 ++
424 ++ col = ((vc->vc_palette[j++] >> (8-minlen))
425 ++ << info->var.red.offset);
426 ++ col |= ((vc->vc_palette[j++] >> (8-minlen))
427 ++ << info->var.green.offset);
428 ++ col |= ((vc->vc_palette[j++] >> (8-minlen))
429 ++ << info->var.blue.offset);
430 ++ ((u32 *)info->pseudo_palette)[k] = col;
431 ++ }
432 ++}
433 ++
434 ++void fbcon_decor_renderc(struct fb_info *info, int ypos, int xpos, int height,
435 ++ int width, u8 *src, u32 fgx, u32 bgx, u8 transparent)
436 ++{
437 ++ unsigned int x, y;
438 ++ u32 dd;
439 ++ int bytespp = ((info->var.bits_per_pixel + 7) >> 3);
440 ++ unsigned int d = ypos * info->fix.line_length + xpos * bytespp;
441 ++ unsigned int ds = (ypos * info->var.xres + xpos) * bytespp;
442 ++ u16 dd2[4];
443 ++
444 ++ u8 *decor_src = (u8 *)(info->bgdecor.data + ds);
445 ++ u8 *dst = (u8 *)(info->screen_base + d);
446 ++
447 ++ if ((ypos + height) > info->var.yres || (xpos + width) > info->var.xres)
448 ++ return;
449 ++
450 ++ for (y = 0; y < height; y++) {
451 ++ switch (info->var.bits_per_pixel) {
452 ++
453 ++ case 32:
454 ++ for (x = 0; x < width; x++) {
455 ++
456 ++ if ((x & 7) == 0)
457 ++ d = *src++;
458 ++ if (d & 0x80)
459 ++ dd = fgx;
460 ++ else
461 ++ dd = transparent ?
462 ++ *(u32 *)decor_src : bgx;
463 ++
464 ++ d <<= 1;
465 ++ decor_src += 4;
466 ++ fb_writel(dd, dst);
467 ++ dst += 4;
468 ++ }
469 ++ break;
470 ++ case 24:
471 ++ for (x = 0; x < width; x++) {
472 ++
473 ++ if ((x & 7) == 0)
474 ++ d = *src++;
475 ++ if (d & 0x80)
476 ++ dd = fgx;
477 ++ else
478 ++ dd = transparent ?
479 ++ (*(u32 *)decor_src & 0xffffff) : bgx;
480 ++
481 ++ d <<= 1;
482 ++ decor_src += 3;
483 ++#ifdef __LITTLE_ENDIAN
484 ++ fb_writew(dd & 0xffff, dst);
485 ++ dst += 2;
486 ++ fb_writeb((dd >> 16), dst);
487 ++#else
488 ++ fb_writew(dd >> 8, dst);
489 ++ dst += 2;
490 ++ fb_writeb(dd & 0xff, dst);
491 ++#endif
492 ++ dst++;
493 ++ }
494 ++ break;
495 ++ case 16:
496 ++ for (x = 0; x < width; x += 2) {
497 ++ if ((x & 7) == 0)
498 ++ d = *src++;
499 ++
500 ++ parse_pixel(0, 2, u16);
501 ++ parse_pixel(1, 2, u16);
502 ++#ifdef __LITTLE_ENDIAN
503 ++ dd = dd2[0] | (dd2[1] << 16);
504 ++#else
505 ++ dd = dd2[1] | (dd2[0] << 16);
506 ++#endif
507 ++ d <<= 2;
508 ++ fb_writel(dd, dst);
509 ++ dst += 4;
510 ++ }
511 ++ break;
512 ++
513 ++ case 8:
514 ++ for (x = 0; x < width; x += 4) {
515 ++ if ((x & 7) == 0)
516 ++ d = *src++;
517 ++
518 ++ parse_pixel(0, 1, u8);
519 ++ parse_pixel(1, 1, u8);
520 ++ parse_pixel(2, 1, u8);
521 ++ parse_pixel(3, 1, u8);
522 ++
523 ++#ifdef __LITTLE_ENDIAN
524 ++ dd = dd2[0] | (dd2[1] << 8) | (dd2[2] << 16) | (dd2[3] << 24);
525 ++#else
526 ++ dd = dd2[3] | (dd2[2] << 8) | (dd2[1] << 16) | (dd2[0] << 24);
527 ++#endif
528 ++ d <<= 4;
529 ++ fb_writel(dd, dst);
530 ++ dst += 4;
531 ++ }
532 ++ }
533 ++
534 ++ dst += info->fix.line_length - width * bytespp;
535 ++ decor_src += (info->var.xres - width) * bytespp;
536 ++ }
537 ++}
538 ++
539 ++#define cc2cx(a) \
540 ++ ((info->fix.visual == FB_VISUAL_TRUECOLOR || \
541 ++ info->fix.visual == FB_VISUAL_DIRECTCOLOR) ? \
542 ++ ((u32 *)info->pseudo_palette)[a] : a)
543 ++
544 ++void fbcon_decor_putcs(struct vc_data *vc, struct fb_info *info,
545 ++ const unsigned short *s, int count, int yy, int xx)
546 ++{
547 ++ unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
548 ++ struct fbcon_ops *ops = info->fbcon_par;
549 ++ int fg_color, bg_color, transparent;
550 ++ u8 *src;
551 ++ u32 bgx, fgx;
552 ++ u16 c = scr_readw(s);
553 ++
554 ++ fg_color = get_color(vc, info, c, 1);
555 ++ bg_color = get_color(vc, info, c, 0);
556 ++
557 ++ /* Don't paint the background image if console is blanked */
558 ++ transparent = ops->blank_state ? 0 :
559 ++ (vc->vc_decor.bg_color == bg_color);
560 ++
561 ++ xx = xx * vc->vc_font.width + vc->vc_decor.tx;
562 ++ yy = yy * vc->vc_font.height + vc->vc_decor.ty;
563 ++
564 ++ fgx = cc2cx(fg_color);
565 ++ bgx = cc2cx(bg_color);
566 ++
567 ++ while (count--) {
568 ++ c = scr_readw(s++);
569 ++ src = vc->vc_font.data + (c & charmask) * vc->vc_font.height *
570 ++ ((vc->vc_font.width + 7) >> 3);
571 ++
572 ++ fbcon_decor_renderc(info, yy, xx, vc->vc_font.height,
573 ++ vc->vc_font.width, src, fgx, bgx, transparent);
574 ++ xx += vc->vc_font.width;
575 ++ }
576 ++}
577 ++
578 ++void fbcon_decor_cursor(struct fb_info *info, struct fb_cursor *cursor)
579 ++{
580 ++ int i;
581 ++ unsigned int dsize, s_pitch;
582 ++ struct fbcon_ops *ops = info->fbcon_par;
583 ++ struct vc_data *vc;
584 ++ u8 *src;
585 ++
586 ++ /* we really don't need any cursors while the console is blanked */
587 ++ if (info->state != FBINFO_STATE_RUNNING || ops->blank_state)
588 ++ return;
589 ++
590 ++ vc = vc_cons[ops->currcon].d;
591 ++
592 ++ src = kmalloc(64 + sizeof(struct fb_image), GFP_ATOMIC);
593 ++ if (!src)
594 ++ return;
595 ++
596 ++ s_pitch = (cursor->image.width + 7) >> 3;
597 ++ dsize = s_pitch * cursor->image.height;
598 ++ if (cursor->enable) {
599 ++ switch (cursor->rop) {
600 ++ case ROP_XOR:
601 ++ for (i = 0; i < dsize; i++)
602 ++ src[i] = cursor->image.data[i] ^ cursor->mask[i];
603 ++ break;
604 ++ case ROP_COPY:
605 ++ default:
606 ++ for (i = 0; i < dsize; i++)
607 ++ src[i] = cursor->image.data[i] & cursor->mask[i];
608 ++ break;
609 ++ }
610 ++ } else
611 ++ memcpy(src, cursor->image.data, dsize);
612 ++
613 ++ fbcon_decor_renderc(info,
614 ++ cursor->image.dy + vc->vc_decor.ty,
615 ++ cursor->image.dx + vc->vc_decor.tx,
616 ++ cursor->image.height,
617 ++ cursor->image.width,
618 ++ (u8 *)src,
619 ++ cc2cx(cursor->image.fg_color),
620 ++ cc2cx(cursor->image.bg_color),
621 ++ cursor->image.bg_color == vc->vc_decor.bg_color);
622 ++
623 ++ kfree(src);
624 ++}
625 ++
626 ++static void decorset(u8 *dst, int height, int width, int dstbytes,
627 ++ u32 bgx, int bpp)
628 ++{
629 ++ int i;
630 ++
631 ++ if (bpp == 8)
632 ++ bgx |= bgx << 8;
633 ++ if (bpp == 16 || bpp == 8)
634 ++ bgx |= bgx << 16;
635 ++
636 ++ while (height-- > 0) {
637 ++ u8 *p = dst;
638 ++
639 ++ switch (bpp) {
640 ++
641 ++ case 32:
642 ++ for (i = 0; i < width; i++) {
643 ++ fb_writel(bgx, p); p += 4;
644 ++ }
645 ++ break;
646 ++ case 24:
647 ++ for (i = 0; i < width; i++) {
648 ++#ifdef __LITTLE_ENDIAN
649 ++ fb_writew((bgx & 0xffff), (u16 *)p); p += 2;
650 ++ fb_writeb((bgx >> 16), p++);
651 ++#else
652 ++ fb_writew((bgx >> 8), (u16 *)p); p += 2;
653 ++ fb_writeb((bgx & 0xff), p++);
654 ++#endif
655 ++ }
656 ++ break;
657 ++ case 16:
658 ++ for (i = 0; i < width/4; i++) {
659 ++ fb_writel(bgx, p); p += 4;
660 ++ fb_writel(bgx, p); p += 4;
661 ++ }
662 ++ if (width & 2) {
663 ++ fb_writel(bgx, p); p += 4;
664 ++ }
665 ++ if (width & 1)
666 ++ fb_writew(bgx, (u16 *)p);
667 ++ break;
668 ++ case 8:
669 ++ for (i = 0; i < width/4; i++) {
670 ++ fb_writel(bgx, p); p += 4;
671 ++ }
672 ++
673 ++ if (width & 2) {
674 ++ fb_writew(bgx, p); p += 2;
675 ++ }
676 ++ if (width & 1)
677 ++ fb_writeb(bgx, (u8 *)p);
678 ++ break;
679 ++
680 ++ }
681 ++ dst += dstbytes;
682 ++ }
683 ++}
684 ++
685 ++void fbcon_decor_copy(u8 *dst, u8 *src, int height, int width, int linebytes,
686 ++ int srclinebytes, int bpp)
687 ++{
688 ++ int i;
689 ++
690 ++ while (height-- > 0) {
691 ++ u32 *p = (u32 *)dst;
692 ++ u32 *q = (u32 *)src;
693 ++
694 ++ switch (bpp) {
695 ++
696 ++ case 32:
697 ++ for (i = 0; i < width; i++)
698 ++ fb_writel(*q++, p++);
699 ++ break;
700 ++ case 24:
701 ++ for (i = 0; i < (width * 3 / 4); i++)
702 ++ fb_writel(*q++, p++);
703 ++ if ((width * 3) % 4) {
704 ++ if (width & 2) {
705 ++ fb_writeb(*(u8 *)q, (u8 *)p);
706 ++ } else if (width & 1) {
707 ++ fb_writew(*(u16 *)q, (u16 *)p);
708 ++ fb_writeb(*(u8 *)((u16 *)q + 1),
709 ++ (u8 *)((u16 *)p + 2));
710 ++ }
711 ++ }
712 ++ break;
713 ++ case 16:
714 ++ for (i = 0; i < width/4; i++) {
715 ++ fb_writel(*q++, p++);
716 ++ fb_writel(*q++, p++);
717 ++ }
718 ++ if (width & 2)
719 ++ fb_writel(*q++, p++);
720 ++ if (width & 1)
721 ++ fb_writew(*(u16 *)q, (u16 *)p);
722 ++ break;
723 ++ case 8:
724 ++ for (i = 0; i < width/4; i++)
725 ++ fb_writel(*q++, p++);
726 ++
727 ++ if (width & 2) {
728 ++ fb_writew(*(u16 *)q, (u16 *)p);
729 ++ q = (u32 *) ((u16 *)q + 1);
730 ++ p = (u32 *) ((u16 *)p + 1);
731 ++ }
732 ++ if (width & 1)
733 ++ fb_writeb(*(u8 *)q, (u8 *)p);
734 ++ break;
735 ++ }
736 ++
737 ++ dst += linebytes;
738 ++ src += srclinebytes;
739 ++ }
740 ++}
741 ++
742 ++static void decorfill(struct fb_info *info, int sy, int sx, int height,
743 ++ int width)
744 ++{
745 ++ int bytespp = ((info->var.bits_per_pixel + 7) >> 3);
746 ++ int d = sy * info->fix.line_length + sx * bytespp;
747 ++ int ds = (sy * info->var.xres + sx) * bytespp;
748 ++
749 ++ fbcon_decor_copy((u8 *)(info->screen_base + d), (u8 *)(info->bgdecor.data + ds),
750 ++ height, width, info->fix.line_length, info->var.xres * bytespp,
751 ++ info->var.bits_per_pixel);
752 ++}
753 ++
754 ++void fbcon_decor_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx,
755 ++ int height, int width)
756 ++{
757 ++ int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
758 ++ struct fbcon_ops *ops = info->fbcon_par;
759 ++ u8 *dst;
760 ++ int transparent, bg_color = attr_bgcol_ec(bgshift, vc, info);
761 ++
762 ++ transparent = (vc->vc_decor.bg_color == bg_color);
763 ++ sy = sy * vc->vc_font.height + vc->vc_decor.ty;
764 ++ sx = sx * vc->vc_font.width + vc->vc_decor.tx;
765 ++ height *= vc->vc_font.height;
766 ++ width *= vc->vc_font.width;
767 ++
768 ++ /* Don't paint the background image if console is blanked */
769 ++ if (transparent && !ops->blank_state) {
770 ++ decorfill(info, sy, sx, height, width);
771 ++ } else {
772 ++ dst = (u8 *)(info->screen_base + sy * info->fix.line_length +
773 ++ sx * ((info->var.bits_per_pixel + 7) >> 3));
774 ++ decorset(dst, height, width, info->fix.line_length, cc2cx(bg_color),
775 ++ info->var.bits_per_pixel);
776 ++ }
777 ++}
778 ++
779 ++void fbcon_decor_clear_margins(struct vc_data *vc, struct fb_info *info,
780 ++ int bottom_only)
781 ++{
782 ++ unsigned int tw = vc->vc_cols*vc->vc_font.width;
783 ++ unsigned int th = vc->vc_rows*vc->vc_font.height;
784 ++
785 ++ if (!bottom_only) {
786 ++ /* top margin */
787 ++ decorfill(info, 0, 0, vc->vc_decor.ty, info->var.xres);
788 ++ /* left margin */
789 ++ decorfill(info, vc->vc_decor.ty, 0, th, vc->vc_decor.tx);
790 ++ /* right margin */
791 ++ decorfill(info, vc->vc_decor.ty, vc->vc_decor.tx + tw, th,
792 ++ info->var.xres - vc->vc_decor.tx - tw);
793 ++ }
794 ++ decorfill(info, vc->vc_decor.ty + th, 0,
795 ++ info->var.yres - vc->vc_decor.ty - th, info->var.xres);
796 ++}
797 ++
798 ++void fbcon_decor_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y,
799 ++ int sx, int dx, int width)
800 ++{
801 ++ u16 *d = (u16 *) (vc->vc_origin + vc->vc_size_row * y + dx * 2);
802 ++ u16 *s = d + (dx - sx);
803 ++ u16 *start = d;
804 ++ u16 *ls = d;
805 ++ u16 *le = d + width;
806 ++ u16 c;
807 ++ int x = dx;
808 ++ u16 attr = 1;
809 ++
810 ++ do {
811 ++ c = scr_readw(d);
812 ++ if (attr != (c & 0xff00)) {
813 ++ attr = c & 0xff00;
814 ++ if (d > start) {
815 ++ fbcon_decor_putcs(vc, info, start, d - start, y, x);
816 ++ x += d - start;
817 ++ start = d;
818 ++ }
819 ++ }
820 ++ if (s >= ls && s < le && c == scr_readw(s)) {
821 ++ if (d > start) {
822 ++ fbcon_decor_putcs(vc, info, start, d - start, y, x);
823 ++ x += d - start + 1;
824 ++ start = d + 1;
825 ++ } else {
826 ++ x++;
827 ++ start++;
828 ++ }
829 ++ }
830 ++ s++;
831 ++ d++;
832 ++ } while (d < le);
833 ++ if (d > start)
834 ++ fbcon_decor_putcs(vc, info, start, d - start, y, x);
835 ++}
836 ++
837 ++void fbcon_decor_blank(struct vc_data *vc, struct fb_info *info, int blank)
838 ++{
839 ++ if (blank) {
840 ++ decorset((u8 *)info->screen_base, info->var.yres, info->var.xres,
841 ++ info->fix.line_length, 0, info->var.bits_per_pixel);
842 ++ } else {
843 ++ update_screen(vc);
844 ++ fbcon_decor_clear_margins(vc, info, 0);
845 ++ }
846 ++}
847 ++
848 +diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
849 +index b87f5cf..ce44538 100644
850 +--- a/drivers/video/console/fbcon.c
851 ++++ b/drivers/video/console/fbcon.c
852 +@@ -79,6 +79,7 @@
853 + #include <asm/irq.h>
854 +
855 + #include "fbcon.h"
856 ++#include "../console/fbcondecor.h"
857 +
858 + #ifdef FBCONDEBUG
859 + # define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
860 +@@ -94,7 +95,7 @@ enum {
861 +
862 + static struct display fb_display[MAX_NR_CONSOLES];
863 +
864 +-static signed char con2fb_map[MAX_NR_CONSOLES];
865 ++signed char con2fb_map[MAX_NR_CONSOLES];
866 + static signed char con2fb_map_boot[MAX_NR_CONSOLES];
867 +
868 + static int logo_lines;
869 +@@ -282,7 +283,7 @@ static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info)
870 + !vt_force_oops_output(vc);
871 + }
872 +
873 +-static int get_color(struct vc_data *vc, struct fb_info *info,
874 ++int get_color(struct vc_data *vc, struct fb_info *info,
875 + u16 c, int is_fg)
876 + {
877 + int depth = fb_get_color_depth(&info->var, &info->fix);
878 +@@ -546,6 +547,9 @@ static int do_fbcon_takeover(int show_logo)
879 + info_idx = -1;
880 + } else {
881 + fbcon_has_console_bind = 1;
882 ++#ifdef CONFIG_FB_CON_DECOR
883 ++ fbcon_decor_init();
884 ++#endif
885 + }
886 +
887 + return err;
888 +@@ -1005,6 +1009,12 @@ static const char *fbcon_startup(void)
889 + rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
890 + cols /= vc->vc_font.width;
891 + rows /= vc->vc_font.height;
892 ++
893 ++ if (fbcon_decor_active(info, vc)) {
894 ++ cols = vc->vc_decor.twidth / vc->vc_font.width;
895 ++ rows = vc->vc_decor.theight / vc->vc_font.height;
896 ++ }
897 ++
898 + vc_resize(vc, cols, rows);
899 +
900 + DPRINTK("mode: %s\n", info->fix.id);
901 +@@ -1034,7 +1044,7 @@ static void fbcon_init(struct vc_data *vc, int init)
902 + cap = info->flags;
903 +
904 + if (vc != svc || logo_shown == FBCON_LOGO_DONTSHOW ||
905 +- (info->fix.type == FB_TYPE_TEXT))
906 ++ (info->fix.type == FB_TYPE_TEXT) || fbcon_decor_active(info, vc))
907 + logo = 0;
908 +
909 + if (var_to_display(p, &info->var, info))
910 +@@ -1259,6 +1269,11 @@ static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height,
911 + fbcon_clear_margins(vc, 0);
912 + }
913 +
914 ++ if (fbcon_decor_active(info, vc)) {
915 ++ fbcon_decor_clear(vc, info, sy, sx, height, width);
916 ++ return;
917 ++ }
918 ++
919 + /* Split blits that cross physical y_wrap boundary */
920 +
921 + y_break = p->vrows - p->yscroll;
922 +@@ -1278,10 +1293,15 @@ static void fbcon_putcs(struct vc_data *vc, const unsigned short *s,
923 + struct display *p = &fb_display[vc->vc_num];
924 + struct fbcon_ops *ops = info->fbcon_par;
925 +
926 +- if (!fbcon_is_inactive(vc, info))
927 +- ops->putcs(vc, info, s, count, real_y(p, ypos), xpos,
928 +- get_color(vc, info, scr_readw(s), 1),
929 +- get_color(vc, info, scr_readw(s), 0));
930 ++ if (!fbcon_is_inactive(vc, info)) {
931 ++
932 ++ if (fbcon_decor_active(info, vc))
933 ++ fbcon_decor_putcs(vc, info, s, count, ypos, xpos);
934 ++ else
935 ++ ops->putcs(vc, info, s, count, real_y(p, ypos), xpos,
936 ++ get_color(vc, info, scr_readw(s), 1),
937 ++ get_color(vc, info, scr_readw(s), 0));
938 ++ }
939 + }
940 +
941 + static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos)
942 +@@ -1297,8 +1317,12 @@ static void fbcon_clear_margins(struct vc_data *vc, int bottom_only)
943 + struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
944 + struct fbcon_ops *ops = info->fbcon_par;
945 +
946 +- if (!fbcon_is_inactive(vc, info))
947 +- ops->clear_margins(vc, info, bottom_only);
948 ++ if (!fbcon_is_inactive(vc, info)) {
949 ++ if (fbcon_decor_active(info, vc))
950 ++ fbcon_decor_clear_margins(vc, info, bottom_only);
951 ++ else
952 ++ ops->clear_margins(vc, info, bottom_only);
953 ++ }
954 + }
955 +
956 + static void fbcon_cursor(struct vc_data *vc, int mode)
957 +@@ -1819,7 +1843,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
958 + count = vc->vc_rows;
959 + if (softback_top)
960 + fbcon_softback_note(vc, t, count);
961 +- if (logo_shown >= 0)
962 ++ if (logo_shown >= 0 || fbcon_decor_active(info, vc))
963 + goto redraw_up;
964 + switch (p->scrollmode) {
965 + case SCROLL_MOVE:
966 +@@ -1912,6 +1936,8 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
967 + count = vc->vc_rows;
968 + if (logo_shown >= 0)
969 + goto redraw_down;
970 ++ if (fbcon_decor_active(info, vc))
971 ++ goto redraw_down;
972 + switch (p->scrollmode) {
973 + case SCROLL_MOVE:
974 + fbcon_redraw_blit(vc, info, p, b - 1, b - t - count,
975 +@@ -2060,6 +2086,13 @@ static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int s
976 + }
977 + return;
978 + }
979 ++
980 ++ if (fbcon_decor_active(info, vc) && sy == dy && height == 1) {
981 ++ /* must use slower redraw bmove to keep background pic intact */
982 ++ fbcon_decor_bmove_redraw(vc, info, sy, sx, dx, width);
983 ++ return;
984 ++ }
985 ++
986 + ops->bmove(vc, info, real_y(p, sy), sx, real_y(p, dy), dx,
987 + height, width);
988 + }
989 +@@ -2130,8 +2163,8 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width,
990 + var.yres = virt_h * virt_fh;
991 + x_diff = info->var.xres - var.xres;
992 + y_diff = info->var.yres - var.yres;
993 +- if (x_diff < 0 || x_diff > virt_fw ||
994 +- y_diff < 0 || y_diff > virt_fh) {
995 ++ if ((x_diff < 0 || x_diff > virt_fw ||
996 ++ y_diff < 0 || y_diff > virt_fh) && !vc->vc_decor.state) {
997 + const struct fb_videomode *mode;
998 +
999 + DPRINTK("attempting resize %ix%i\n", var.xres, var.yres);
1000 +@@ -2167,6 +2200,22 @@ static int fbcon_switch(struct vc_data *vc)
1001 +
1002 + info = registered_fb[con2fb_map[vc->vc_num]];
1003 + ops = info->fbcon_par;
1004 ++ prev_console = ops->currcon;
1005 ++ if (prev_console != -1)
1006 ++ old_info = registered_fb[con2fb_map[prev_console]];
1007 ++
1008 ++#ifdef CONFIG_FB_CON_DECOR
1009 ++ if (!fbcon_decor_active_vc(vc) && info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
1010 ++ struct vc_data *vc_curr = vc_cons[prev_console].d;
1011 ++
1012 ++ if (vc_curr && fbcon_decor_active_vc(vc_curr)) {
1013 ++ // Clear the screen to avoid displaying funky colors
1014 ++ // during palette updates.
1015 ++ memset((u8 *)info->screen_base + info->fix.line_length * info->var.yoffset,
1016 ++ 0, info->var.yres * info->fix.line_length);
1017 ++ }
1018 ++ }
1019 ++#endif
1020 +
1021 + if (softback_top) {
1022 + if (softback_lines)
1023 +@@ -2185,9 +2234,6 @@ static int fbcon_switch(struct vc_data *vc)
1024 + logo_shown = FBCON_LOGO_CANSHOW;
1025 + }
1026 +
1027 +- prev_console = ops->currcon;
1028 +- if (prev_console != -1)
1029 +- old_info = registered_fb[con2fb_map[prev_console]];
1030 + /*
1031 + * FIXME: If we have multiple fbdev's loaded, we need to
1032 + * update all info->currcon. Perhaps, we can place this
1033 +@@ -2231,6 +2277,18 @@ static int fbcon_switch(struct vc_data *vc)
1034 + fbcon_del_cursor_timer(old_info);
1035 + }
1036 +
1037 ++ if (fbcon_decor_active_vc(vc)) {
1038 ++ struct vc_data *vc_curr = vc_cons[prev_console].d;
1039 ++
1040 ++ if (!vc_curr->vc_decor.theme ||
1041 ++ strcmp(vc->vc_decor.theme, vc_curr->vc_decor.theme) ||
1042 ++ (fbcon_decor_active_nores(info, vc_curr) &&
1043 ++ !fbcon_decor_active(info, vc_curr))) {
1044 ++ fbcon_decor_disable(vc, 0);
1045 ++ fbcon_decor_call_helper("modechange", vc->vc_num);
1046 ++ }
1047 ++ }
1048 ++
1049 + if (fbcon_is_inactive(vc, info) ||
1050 + ops->blank_state != FB_BLANK_UNBLANK)
1051 + fbcon_del_cursor_timer(info);
1052 +@@ -2339,15 +2397,20 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
1053 + }
1054 + }
1055 +
1056 +- if (!fbcon_is_inactive(vc, info)) {
1057 ++ if (!fbcon_is_inactive(vc, info)) {
1058 + if (ops->blank_state != blank) {
1059 + ops->blank_state = blank;
1060 + fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW);
1061 + ops->cursor_flash = (!blank);
1062 +
1063 +- if (!(info->flags & FBINFO_MISC_USEREVENT))
1064 +- if (fb_blank(info, blank))
1065 +- fbcon_generic_blank(vc, info, blank);
1066 ++ if (!(info->flags & FBINFO_MISC_USEREVENT)) {
1067 ++ if (fb_blank(info, blank)) {
1068 ++ if (fbcon_decor_active(info, vc))
1069 ++ fbcon_decor_blank(vc, info, blank);
1070 ++ else
1071 ++ fbcon_generic_blank(vc, info, blank);
1072 ++ }
1073 ++ }
1074 + }
1075 +
1076 + if (!blank)
1077 +@@ -2522,13 +2585,22 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
1078 + }
1079 +
1080 + if (resize) {
1081 ++ /* reset wrap/pan */
1082 + int cols, rows;
1083 +
1084 + cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
1085 + rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
1086 ++
1087 ++ if (fbcon_decor_active(info, vc)) {
1088 ++ info->var.xoffset = info->var.yoffset = p->yscroll = 0;
1089 ++ cols = vc->vc_decor.twidth;
1090 ++ rows = vc->vc_decor.theight;
1091 ++ }
1092 + cols /= w;
1093 + rows /= h;
1094 ++
1095 + vc_resize(vc, cols, rows);
1096 ++
1097 + if (con_is_visible(vc) && softback_buf)
1098 + fbcon_update_softback(vc);
1099 + } else if (con_is_visible(vc)
1100 +@@ -2657,7 +2729,11 @@ static void fbcon_set_palette(struct vc_data *vc, const unsigned char *table)
1101 + int i, j, k, depth;
1102 + u8 val;
1103 +
1104 +- if (fbcon_is_inactive(vc, info))
1105 ++ if (fbcon_is_inactive(vc, info)
1106 ++#ifdef CONFIG_FB_CON_DECOR
1107 ++ || vc->vc_num != fg_console
1108 ++#endif
1109 ++ )
1110 + return;
1111 +
1112 + if (!con_is_visible(vc))
1113 +@@ -2683,7 +2759,47 @@ static void fbcon_set_palette(struct vc_data *vc, const unsigned char *table)
1114 + } else
1115 + fb_copy_cmap(fb_default_cmap(1 << depth), &palette_cmap);
1116 +
1117 +- fb_set_cmap(&palette_cmap, info);
1118 ++ if (fbcon_decor_active(info, vc_cons[fg_console].d) &&
1119 ++ info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
1120 ++
1121 ++ u16 *red, *green, *blue;
1122 ++ int minlen = min(min(info->var.red.length, info->var.green.length),
1123 ++ info->var.blue.length);
1124 ++
1125 ++ struct fb_cmap cmap = {
1126 ++ .start = 0,
1127 ++ .len = (1 << minlen),
1128 ++ .red = NULL,
1129 ++ .green = NULL,
1130 ++ .blue = NULL,
1131 ++ .transp = NULL
1132 ++ };
1133 ++
1134 ++ red = kmalloc(256 * sizeof(u16) * 3, GFP_KERNEL);
1135 ++
1136 ++ if (!red)
1137 ++ goto out;
1138 ++
1139 ++ green = red + 256;
1140 ++ blue = green + 256;
1141 ++ cmap.red = red;
1142 ++ cmap.green = green;
1143 ++ cmap.blue = blue;
1144 ++
1145 ++ for (i = 0; i < cmap.len; i++)
1146 ++ red[i] = green[i] = blue[i] = (0xffff * i)/(cmap.len-1);
1147 ++
1148 ++ fb_set_cmap(&cmap, info);
1149 ++ fbcon_decor_fix_pseudo_pal(info, vc_cons[fg_console].d);
1150 ++ kfree(red);
1151 ++
1152 ++ return;
1153 ++
1154 ++ } else if (fbcon_decor_active(info, vc_cons[fg_console].d) &&
1155 ++ info->var.bits_per_pixel == 8 && info->bgdecor.cmap.red != NULL)
1156 ++ fb_set_cmap(&info->bgdecor.cmap, info);
1157 ++
1158 ++out: fb_set_cmap(&palette_cmap, info);
1159 + }
1160 +
1161 + static u16 *fbcon_screen_pos(struct vc_data *vc, int offset)
1162 +@@ -2908,7 +3024,14 @@ static void fbcon_modechanged(struct fb_info *info)
1163 + rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
1164 + cols /= vc->vc_font.width;
1165 + rows /= vc->vc_font.height;
1166 +- vc_resize(vc, cols, rows);
1167 ++
1168 ++ if (!fbcon_decor_active_nores(info, vc)) {
1169 ++ vc_resize(vc, cols, rows);
1170 ++ } else {
1171 ++ fbcon_decor_disable(vc, 0);
1172 ++ fbcon_decor_call_helper("modechange", vc->vc_num);
1173 ++ }
1174 ++
1175 + updatescrollmode(p, info, vc);
1176 + scrollback_max = 0;
1177 + scrollback_current = 0;
1178 +@@ -2953,7 +3076,8 @@ static void fbcon_set_all_vcs(struct fb_info *info)
1179 + rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
1180 + cols /= vc->vc_font.width;
1181 + rows /= vc->vc_font.height;
1182 +- vc_resize(vc, cols, rows);
1183 ++ if (!fbcon_decor_active_nores(info, vc))
1184 ++ vc_resize(vc, cols, rows);
1185 + }
1186 +
1187 + if (fg != -1)
1188 +@@ -3594,6 +3718,7 @@ static void fbcon_exit(void)
1189 + }
1190 + }
1191 +
1192 ++ fbcon_decor_exit();
1193 + fbcon_has_exited = 1;
1194 + }
1195 +
1196 +diff --git a/drivers/video/console/fbcondecor.c b/drivers/video/console/fbcondecor.c
1197 +new file mode 100644
1198 +index 0000000..65cc0d3
1199 +--- /dev/null
1200 ++++ b/drivers/video/console/fbcondecor.c
1201 +@@ -0,0 +1,549 @@
1202 ++/*
1203 ++ * linux/drivers/video/console/fbcondecor.c -- Framebuffer console decorations
1204 ++ *
1205 ++ * Copyright (C) 2004-2009 Michal Januszewski <michalj+fbcondecor@×××××.com>
1206 ++ *
1207 ++ * Code based upon "Bootsplash" (C) 2001-2003
1208 ++ * Volker Poplawski <volker@×××××××××.de>,
1209 ++ * Stefan Reinauer <stepan@××××.de>,
1210 ++ * Steffen Winterfeldt <snwint@××××.de>,
1211 ++ * Michael Schroeder <mls@××××.de>,
1212 ++ * Ken Wimer <wimer@××××.de>.
1213 ++ *
1214 ++ * Compat ioctl support by Thorsten Klein <TK@××××××××××××××.de>.
1215 ++ *
1216 ++ * This file is subject to the terms and conditions of the GNU General Public
1217 ++ * License. See the file COPYING in the main directory of this archive for
1218 ++ * more details.
1219 ++ *
1220 ++ */
1221 ++#include <linux/module.h>
1222 ++#include <linux/kernel.h>
1223 ++#include <linux/string.h>
1224 ++#include <linux/types.h>
1225 ++#include <linux/fb.h>
1226 ++#include <linux/vt_kern.h>
1227 ++#include <linux/vmalloc.h>
1228 ++#include <linux/unistd.h>
1229 ++#include <linux/syscalls.h>
1230 ++#include <linux/init.h>
1231 ++#include <linux/proc_fs.h>
1232 ++#include <linux/workqueue.h>
1233 ++#include <linux/kmod.h>
1234 ++#include <linux/miscdevice.h>
1235 ++#include <linux/device.h>
1236 ++#include <linux/fs.h>
1237 ++#include <linux/compat.h>
1238 ++#include <linux/console.h>
1239 ++
1240 ++#include <linux/uaccess.h>
1241 ++#include <asm/irq.h>
1242 ++
1243 ++#include "fbcon.h"
1244 ++#include "fbcondecor.h"
1245 ++
1246 ++extern signed char con2fb_map[];
1247 ++static int fbcon_decor_enable(struct vc_data *vc);
1248 ++
1249 ++static int initialized;
1250 ++
1251 ++char fbcon_decor_path[KMOD_PATH_LEN] = "/sbin/fbcondecor_helper";
1252 ++EXPORT_SYMBOL(fbcon_decor_path);
1253 ++
1254 ++int fbcon_decor_call_helper(char *cmd, unsigned short vc)
1255 ++{
1256 ++ char *envp[] = {
1257 ++ "HOME=/",
1258 ++ "PATH=/sbin:/bin",
1259 ++ NULL
1260 ++ };
1261 ++
1262 ++ char tfb[5];
1263 ++ char tcons[5];
1264 ++ unsigned char fb = (int) con2fb_map[vc];
1265 ++
1266 ++ char *argv[] = {
1267 ++ fbcon_decor_path,
1268 ++ "2",
1269 ++ cmd,
1270 ++ tcons,
1271 ++ tfb,
1272 ++ vc_cons[vc].d->vc_decor.theme,
1273 ++ NULL
1274 ++ };
1275 ++
1276 ++ snprintf(tfb, 5, "%d", fb);
1277 ++ snprintf(tcons, 5, "%d", vc);
1278 ++
1279 ++ return call_usermodehelper(fbcon_decor_path, argv, envp, UMH_WAIT_EXEC);
1280 ++}
1281 ++
1282 ++/* Disables fbcondecor on a virtual console; called with console sem held. */
1283 ++int fbcon_decor_disable(struct vc_data *vc, unsigned char redraw)
1284 ++{
1285 ++ struct fb_info *info;
1286 ++
1287 ++ if (!vc->vc_decor.state)
1288 ++ return -EINVAL;
1289 ++
1290 ++ info = registered_fb[(int) con2fb_map[vc->vc_num]];
1291 ++
1292 ++ if (info == NULL)
1293 ++ return -EINVAL;
1294 ++
1295 ++ vc->vc_decor.state = 0;
1296 ++ vc_resize(vc, info->var.xres / vc->vc_font.width,
1297 ++ info->var.yres / vc->vc_font.height);
1298 ++
1299 ++ if (fg_console == vc->vc_num && redraw) {
1300 ++ redraw_screen(vc, 0);
1301 ++ update_region(vc, vc->vc_origin +
1302 ++ vc->vc_size_row * vc->vc_top,
1303 ++ vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2);
1304 ++ }
1305 ++
1306 ++ printk(KERN_INFO "fbcondecor: switched decor state to 'off' on console %d\n",
1307 ++ vc->vc_num);
1308 ++
1309 ++ return 0;
1310 ++}
1311 ++
1312 ++/* Enables fbcondecor on a virtual console; called with console sem held. */
1313 ++static int fbcon_decor_enable(struct vc_data *vc)
1314 ++{
1315 ++ struct fb_info *info;
1316 ++
1317 ++ info = registered_fb[(int) con2fb_map[vc->vc_num]];
1318 ++
1319 ++ if (vc->vc_decor.twidth == 0 || vc->vc_decor.theight == 0 ||
1320 ++ info == NULL || vc->vc_decor.state || (!info->bgdecor.data &&
1321 ++ vc->vc_num == fg_console))
1322 ++ return -EINVAL;
1323 ++
1324 ++ vc->vc_decor.state = 1;
1325 ++ vc_resize(vc, vc->vc_decor.twidth / vc->vc_font.width,
1326 ++ vc->vc_decor.theight / vc->vc_font.height);
1327 ++
1328 ++ if (fg_console == vc->vc_num) {
1329 ++ redraw_screen(vc, 0);
1330 ++ update_region(vc, vc->vc_origin +
1331 ++ vc->vc_size_row * vc->vc_top,
1332 ++ vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2);
1333 ++ fbcon_decor_clear_margins(vc, info, 0);
1334 ++ }
1335 ++
1336 ++ printk(KERN_INFO "fbcondecor: switched decor state to 'on' on console %d\n",
1337 ++ vc->vc_num);
1338 ++
1339 ++ return 0;
1340 ++}
1341 ++
1342 ++static inline int fbcon_decor_ioctl_dosetstate(struct vc_data *vc, unsigned int state, unsigned char origin)
1343 ++{
1344 ++ int ret;
1345 ++
1346 ++ console_lock();
1347 ++ if (!state)
1348 ++ ret = fbcon_decor_disable(vc, 1);
1349 ++ else
1350 ++ ret = fbcon_decor_enable(vc);
1351 ++ console_unlock();
1352 ++
1353 ++ return ret;
1354 ++}
1355 ++
1356 ++static inline void fbcon_decor_ioctl_dogetstate(struct vc_data *vc, unsigned int *state)
1357 ++{
1358 ++ *state = vc->vc_decor.state;
1359 ++}
1360 ++
1361 ++static int fbcon_decor_ioctl_dosetcfg(struct vc_data *vc, struct vc_decor *cfg, unsigned char origin)
1362 ++{
1363 ++ struct fb_info *info;
1364 ++ int len;
1365 ++ char *tmp;
1366 ++
1367 ++ info = registered_fb[(int) con2fb_map[vc->vc_num]];
1368 ++
1369 ++ if (info == NULL || !cfg->twidth || !cfg->theight ||
1370 ++ cfg->tx + cfg->twidth > info->var.xres ||
1371 ++ cfg->ty + cfg->theight > info->var.yres)
1372 ++ return -EINVAL;
1373 ++
1374 ++ len = strlen_user(cfg->theme);
1375 ++ if (!len || len > FBCON_DECOR_THEME_LEN)
1376 ++ return -EINVAL;
1377 ++ tmp = kmalloc(len, GFP_KERNEL);
1378 ++ if (!tmp)
1379 ++ return -ENOMEM;
1380 ++ if (copy_from_user(tmp, (void __user *)cfg->theme, len))
1381 ++ return -EFAULT;
1382 ++ cfg->theme = tmp;
1383 ++ cfg->state = 0;
1384 ++
1385 ++ console_lock();
1386 ++ if (vc->vc_decor.state)
1387 ++ fbcon_decor_disable(vc, 1);
1388 ++ kfree(vc->vc_decor.theme);
1389 ++ vc->vc_decor = *cfg;
1390 ++ console_unlock();
1391 ++
1392 ++ printk(KERN_INFO "fbcondecor: console %d using theme '%s'\n",
1393 ++ vc->vc_num, vc->vc_decor.theme);
1394 ++ return 0;
1395 ++}
1396 ++
1397 ++static int fbcon_decor_ioctl_dogetcfg(struct vc_data *vc,
1398 ++ struct vc_decor *decor)
1399 ++{
1400 ++ char __user *tmp;
1401 ++
1402 ++ tmp = decor->theme;
1403 ++ *decor = vc->vc_decor;
1404 ++ decor->theme = tmp;
1405 ++
1406 ++ if (vc->vc_decor.theme) {
1407 ++ if (copy_to_user(tmp, vc->vc_decor.theme,
1408 ++ strlen(vc->vc_decor.theme) + 1))
1409 ++ return -EFAULT;
1410 ++ } else
1411 ++ if (put_user(0, tmp))
1412 ++ return -EFAULT;
1413 ++
1414 ++ return 0;
1415 ++}
1416 ++
1417 ++static int fbcon_decor_ioctl_dosetpic(struct vc_data *vc, struct fb_image *img,
1418 ++ unsigned char origin)
1419 ++{
1420 ++ struct fb_info *info;
1421 ++ int len;
1422 ++ u8 *tmp;
1423 ++
1424 ++ if (vc->vc_num != fg_console)
1425 ++ return -EINVAL;
1426 ++
1427 ++ info = registered_fb[(int) con2fb_map[vc->vc_num]];
1428 ++
1429 ++ if (info == NULL)
1430 ++ return -EINVAL;
1431 ++
1432 ++ if (img->width != info->var.xres || img->height != info->var.yres) {
1433 ++ printk(KERN_ERR "fbcondecor: picture dimensions mismatch\n");
1434 ++ printk(KERN_ERR "%dx%d vs %dx%d\n", img->width, img->height,
1435 ++ info->var.xres, info->var.yres);
1436 ++ return -EINVAL;
1437 ++ }
1438 ++
1439 ++ if (img->depth != info->var.bits_per_pixel) {
1440 ++ printk(KERN_ERR "fbcondecor: picture depth mismatch\n");
1441 ++ return -EINVAL;
1442 ++ }
1443 ++
1444 ++ if (img->depth == 8) {
1445 ++ if (!img->cmap.len || !img->cmap.red || !img->cmap.green ||
1446 ++ !img->cmap.blue)
1447 ++ return -EINVAL;
1448 ++
1449 ++ tmp = vmalloc(img->cmap.len * 3 * 2);
1450 ++ if (!tmp)
1451 ++ return -ENOMEM;
1452 ++
1453 ++ if (copy_from_user(tmp,
1454 ++ (void __user *)img->cmap.red,
1455 ++ (img->cmap.len << 1)) ||
1456 ++ copy_from_user(tmp + (img->cmap.len << 1),
1457 ++ (void __user *)img->cmap.green,
1458 ++ (img->cmap.len << 1)) ||
1459 ++ copy_from_user(tmp + (img->cmap.len << 2),
1460 ++ (void __user *)img->cmap.blue,
1461 ++ (img->cmap.len << 1))) {
1462 ++ vfree(tmp);
1463 ++ return -EFAULT;
1464 ++ }
1465 ++
1466 ++ img->cmap.transp = NULL;
1467 ++ img->cmap.red = (u16 *)tmp;
1468 ++ img->cmap.green = img->cmap.red + img->cmap.len;
1469 ++ img->cmap.blue = img->cmap.green + img->cmap.len;
1470 ++ } else {
1471 ++ img->cmap.red = NULL;
1472 ++ }
1473 ++
1474 ++ len = ((img->depth + 7) >> 3) * img->width * img->height;
1475 ++
1476 ++ /*
1477 ++ * Allocate an additional byte so that we never go outside of the
1478 ++ * buffer boundaries in the rendering functions in a 24 bpp mode.
1479 ++ */
1480 ++ tmp = vmalloc(len + 1);
1481 ++
1482 ++ if (!tmp)
1483 ++ goto out;
1484 ++
1485 ++ if (copy_from_user(tmp, (void __user *)img->data, len))
1486 ++ goto out;
1487 ++
1488 ++ img->data = tmp;
1489 ++
1490 ++ console_lock();
1491 ++
1492 ++ if (info->bgdecor.data)
1493 ++ vfree((u8 *)info->bgdecor.data);
1494 ++ if (info->bgdecor.cmap.red)
1495 ++ vfree(info->bgdecor.cmap.red);
1496 ++
1497 ++ info->bgdecor = *img;
1498 ++
1499 ++ if (fbcon_decor_active_vc(vc) && fg_console == vc->vc_num) {
1500 ++ redraw_screen(vc, 0);
1501 ++ update_region(vc, vc->vc_origin +
1502 ++ vc->vc_size_row * vc->vc_top,
1503 ++ vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2);
1504 ++ fbcon_decor_clear_margins(vc, info, 0);
1505 ++ }
1506 ++
1507 ++ console_unlock();
1508 ++
1509 ++ return 0;
1510 ++
1511 ++out:
1512 ++ if (img->cmap.red)
1513 ++ vfree(img->cmap.red);
1514 ++
1515 ++ if (tmp)
1516 ++ vfree(tmp);
1517 ++ return -ENOMEM;
1518 ++}
1519 ++
1520 ++static long fbcon_decor_ioctl(struct file *filp, u_int cmd, u_long arg)
1521 ++{
1522 ++ struct fbcon_decor_iowrapper __user *wrapper = (void __user *) arg;
1523 ++ struct vc_data *vc = NULL;
1524 ++ unsigned short vc_num = 0;
1525 ++ unsigned char origin = 0;
1526 ++ void __user *data = NULL;
1527 ++
1528 ++ if (!access_ok(VERIFY_READ, wrapper,
1529 ++ sizeof(struct fbcon_decor_iowrapper)))
1530 ++ return -EFAULT;
1531 ++
1532 ++ __get_user(vc_num, &wrapper->vc);
1533 ++ __get_user(origin, &wrapper->origin);
1534 ++ __get_user(data, &wrapper->data);
1535 ++
1536 ++ if (!vc_cons_allocated(vc_num))
1537 ++ return -EINVAL;
1538 ++
1539 ++ vc = vc_cons[vc_num].d;
1540 ++
1541 ++ switch (cmd) {
1542 ++ case FBIOCONDECOR_SETPIC:
1543 ++ {
1544 ++ struct fb_image img;
1545 ++
1546 ++ if (copy_from_user(&img, (struct fb_image __user *)data, sizeof(struct fb_image)))
1547 ++ return -EFAULT;
1548 ++
1549 ++ return fbcon_decor_ioctl_dosetpic(vc, &img, origin);
1550 ++ }
1551 ++ case FBIOCONDECOR_SETCFG:
1552 ++ {
1553 ++ struct vc_decor cfg;
1554 ++
1555 ++ if (copy_from_user(&cfg, (struct vc_decor __user *)data, sizeof(struct vc_decor)))
1556 ++ return -EFAULT;
1557 ++
1558 ++ return fbcon_decor_ioctl_dosetcfg(vc, &cfg, origin);
1559 ++ }
1560 ++ case FBIOCONDECOR_GETCFG:
1561 ++ {
1562 ++ int rval;
1563 ++ struct vc_decor cfg;
1564 ++
1565 ++ if (copy_from_user(&cfg, (struct vc_decor __user *)data, sizeof(struct vc_decor)))
1566 ++ return -EFAULT;
1567 ++
1568 ++ rval = fbcon_decor_ioctl_dogetcfg(vc, &cfg);
1569 ++
1570 ++ if (copy_to_user(data, &cfg, sizeof(struct vc_decor)))
1571 ++ return -EFAULT;
1572 ++ return rval;
1573 ++ }
1574 ++ case FBIOCONDECOR_SETSTATE:
1575 ++ {
1576 ++ unsigned int state = 0;
1577 ++
1578 ++ if (get_user(state, (unsigned int __user *)data))
1579 ++ return -EFAULT;
1580 ++ return fbcon_decor_ioctl_dosetstate(vc, state, origin);
1581 ++ }
1582 ++ case FBIOCONDECOR_GETSTATE:
1583 ++ {
1584 ++ unsigned int state = 0;
1585 ++
1586 ++ fbcon_decor_ioctl_dogetstate(vc, &state);
1587 ++ return put_user(state, (unsigned int __user *)data);
1588 ++ }
1589 ++
1590 ++ default:
1591 ++ return -ENOIOCTLCMD;
1592 ++ }
1593 ++}
1594 ++
1595 ++#ifdef CONFIG_COMPAT
1596 ++
1597 ++static long fbcon_decor_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
1598 ++{
1599 ++ struct fbcon_decor_iowrapper32 __user *wrapper = (void __user *)arg;
1600 ++ struct vc_data *vc = NULL;
1601 ++ unsigned short vc_num = 0;
1602 ++ unsigned char origin = 0;
1603 ++ compat_uptr_t data_compat = 0;
1604 ++ void __user *data = NULL;
1605 ++
1606 ++ if (!access_ok(VERIFY_READ, wrapper,
1607 ++ sizeof(struct fbcon_decor_iowrapper32)))
1608 ++ return -EFAULT;
1609 ++
1610 ++ __get_user(vc_num, &wrapper->vc);
1611 ++ __get_user(origin, &wrapper->origin);
1612 ++ __get_user(data_compat, &wrapper->data);
1613 ++ data = compat_ptr(data_compat);
1614 ++
1615 ++ if (!vc_cons_allocated(vc_num))
1616 ++ return -EINVAL;
1617 ++
1618 ++ vc = vc_cons[vc_num].d;
1619 ++
1620 ++ switch (cmd) {
1621 ++ case FBIOCONDECOR_SETPIC32:
1622 ++ {
1623 ++ struct fb_image32 img_compat;
1624 ++ struct fb_image img;
1625 ++
1626 ++ if (copy_from_user(&img_compat, (struct fb_image32 __user *)data, sizeof(struct fb_image32)))
1627 ++ return -EFAULT;
1628 ++
1629 ++ fb_image_from_compat(img, img_compat);
1630 ++
1631 ++ return fbcon_decor_ioctl_dosetpic(vc, &img, origin);
1632 ++ }
1633 ++
1634 ++ case FBIOCONDECOR_SETCFG32:
1635 ++ {
1636 ++ struct vc_decor32 cfg_compat;
1637 ++ struct vc_decor cfg;
1638 ++
1639 ++ if (copy_from_user(&cfg_compat, (struct vc_decor32 __user *)data, sizeof(struct vc_decor32)))
1640 ++ return -EFAULT;
1641 ++
1642 ++ vc_decor_from_compat(cfg, cfg_compat);
1643 ++
1644 ++ return fbcon_decor_ioctl_dosetcfg(vc, &cfg, origin);
1645 ++ }
1646 ++
1647 ++ case FBIOCONDECOR_GETCFG32:
1648 ++ {
1649 ++ int rval;
1650 ++ struct vc_decor32 cfg_compat;
1651 ++ struct vc_decor cfg;
1652 ++
1653 ++ if (copy_from_user(&cfg_compat, (struct vc_decor32 __user *)data, sizeof(struct vc_decor32)))
1654 ++ return -EFAULT;
1655 ++ cfg.theme = compat_ptr(cfg_compat.theme);
1656 ++
1657 ++ rval = fbcon_decor_ioctl_dogetcfg(vc, &cfg);
1658 ++
1659 ++ vc_decor_to_compat(cfg_compat, cfg);
1660 ++
1661 ++ if (copy_to_user((struct vc_decor32 __user *)data, &cfg_compat, sizeof(struct vc_decor32)))
1662 ++ return -EFAULT;
1663 ++ return rval;
1664 ++ }
1665 ++
1666 ++ case FBIOCONDECOR_SETSTATE32:
1667 ++ {
1668 ++ compat_uint_t state_compat = 0;
1669 ++ unsigned int state = 0;
1670 ++
1671 ++ if (get_user(state_compat, (compat_uint_t __user *)data))
1672 ++ return -EFAULT;
1673 ++
1674 ++ state = (unsigned int)state_compat;
1675 ++
1676 ++ return fbcon_decor_ioctl_dosetstate(vc, state, origin);
1677 ++ }
1678 ++
1679 ++ case FBIOCONDECOR_GETSTATE32:
1680 ++ {
1681 ++ compat_uint_t state_compat = 0;
1682 ++ unsigned int state = 0;
1683 ++
1684 ++ fbcon_decor_ioctl_dogetstate(vc, &state);
1685 ++ state_compat = (compat_uint_t)state;
1686 ++
1687 ++ return put_user(state_compat, (compat_uint_t __user *)data);
1688 ++ }
1689 ++
1690 ++ default:
1691 ++ return -ENOIOCTLCMD;
1692 ++ }
1693 ++}
1694 ++#else
1695 ++ #define fbcon_decor_compat_ioctl NULL
1696 ++#endif
1697 ++
1698 ++static struct file_operations fbcon_decor_ops = {
1699 ++ .owner = THIS_MODULE,
1700 ++ .unlocked_ioctl = fbcon_decor_ioctl,
1701 ++ .compat_ioctl = fbcon_decor_compat_ioctl
1702 ++};
1703 ++
1704 ++static struct miscdevice fbcon_decor_dev = {
1705 ++ .minor = MISC_DYNAMIC_MINOR,
1706 ++ .name = "fbcondecor",
1707 ++ .fops = &fbcon_decor_ops
1708 ++};
1709 ++
1710 ++void fbcon_decor_reset(void)
1711 ++{
1712 ++ int i;
1713 ++
1714 ++ for (i = 0; i < num_registered_fb; i++) {
1715 ++ registered_fb[i]->bgdecor.data = NULL;
1716 ++ registered_fb[i]->bgdecor.cmap.red = NULL;
1717 ++ }
1718 ++
1719 ++ for (i = 0; i < MAX_NR_CONSOLES && vc_cons[i].d; i++) {
1720 ++ vc_cons[i].d->vc_decor.state = vc_cons[i].d->vc_decor.twidth =
1721 ++ vc_cons[i].d->vc_decor.theight = 0;
1722 ++ vc_cons[i].d->vc_decor.theme = NULL;
1723 ++ }
1724 ++}
1725 ++
1726 ++int fbcon_decor_init(void)
1727 ++{
1728 ++ int i;
1729 ++
1730 ++ fbcon_decor_reset();
1731 ++
1732 ++ if (initialized)
1733 ++ return 0;
1734 ++
1735 ++ i = misc_register(&fbcon_decor_dev);
1736 ++ if (i) {
1737 ++ printk(KERN_ERR "fbcondecor: failed to register device\n");
1738 ++ return i;
1739 ++ }
1740 ++
1741 ++ fbcon_decor_call_helper("init", 0);
1742 ++ initialized = 1;
1743 ++ return 0;
1744 ++}
1745 ++
1746 ++int fbcon_decor_exit(void)
1747 ++{
1748 ++ fbcon_decor_reset();
1749 ++ return 0;
1750 ++}
1751 +diff --git a/drivers/video/console/fbcondecor.h b/drivers/video/console/fbcondecor.h
1752 +new file mode 100644
1753 +index 0000000..c49386c
1754 +--- /dev/null
1755 ++++ b/drivers/video/console/fbcondecor.h
1756 +@@ -0,0 +1,77 @@
1757 ++/*
1758 ++ * linux/drivers/video/console/fbcondecor.h -- Framebuffer Console Decoration headers
1759 ++ *
1760 ++ * Copyright (C) 2004 Michal Januszewski <michalj+fbcondecor@×××××.com>
1761 ++ *
1762 ++ */
1763 ++
1764 ++#ifndef __FBCON_DECOR_H
1765 ++#define __FBCON_DECOR_H
1766 ++
1767 ++#ifndef _LINUX_FB_H
1768 ++#include <linux/fb.h>
1769 ++#endif
1770 ++
1771 ++/* This is needed for vc_cons in fbcmap.c */
1772 ++#include <linux/vt_kern.h>
1773 ++
1774 ++struct fb_cursor;
1775 ++struct fb_info;
1776 ++struct vc_data;
1777 ++
1778 ++#ifdef CONFIG_FB_CON_DECOR
1779 ++/* fbcondecor.c */
1780 ++int fbcon_decor_init(void);
1781 ++int fbcon_decor_exit(void);
1782 ++int fbcon_decor_call_helper(char *cmd, unsigned short cons);
1783 ++int fbcon_decor_disable(struct vc_data *vc, unsigned char redraw);
1784 ++
1785 ++/* cfbcondecor.c */
1786 ++void fbcon_decor_putcs(struct vc_data *vc, struct fb_info *info, const unsigned short *s, int count, int yy, int xx);
1787 ++void fbcon_decor_cursor(struct fb_info *info, struct fb_cursor *cursor);
1788 ++void fbcon_decor_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx, int height, int width);
1789 ++void fbcon_decor_clear_margins(struct vc_data *vc, struct fb_info *info, int bottom_only);
1790 ++void fbcon_decor_blank(struct vc_data *vc, struct fb_info *info, int blank);
1791 ++void fbcon_decor_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y, int sx, int dx, int width);
1792 ++void fbcon_decor_copy(u8 *dst, u8 *src, int height, int width, int linebytes, int srclinesbytes, int bpp);
1793 ++void fbcon_decor_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc);
1794 ++
1795 ++/* vt.c */
1796 ++void acquire_console_sem(void);
1797 ++void release_console_sem(void);
1798 ++void do_unblank_screen(int entering_gfx);
1799 ++
1800 ++/* struct vc_data *y */
1801 ++#define fbcon_decor_active_vc(y) (y->vc_decor.state && y->vc_decor.theme)
1802 ++
1803 ++/* struct fb_info *x, struct vc_data *y */
1804 ++#define fbcon_decor_active_nores(x, y) (x->bgdecor.data && fbcon_decor_active_vc(y))
1805 ++
1806 ++/* struct fb_info *x, struct vc_data *y */
1807 ++#define fbcon_decor_active(x, y) (fbcon_decor_active_nores(x, y) && \
1808 ++ x->bgdecor.width == x->var.xres && \
1809 ++ x->bgdecor.height == x->var.yres && \
1810 ++ x->bgdecor.depth == x->var.bits_per_pixel)
1811 ++
1812 ++#else /* CONFIG_FB_CON_DECOR */
1813 ++
1814 ++static inline void fbcon_decor_putcs(struct vc_data *vc, struct fb_info *info, const unsigned short *s, int count, int yy, int xx) {}
1815 ++static inline void fbcon_decor_putc(struct vc_data *vc, struct fb_info *info, int c, int ypos, int xpos) {}
1816 ++static inline void fbcon_decor_cursor(struct fb_info *info, struct fb_cursor *cursor) {}
1817 ++static inline void fbcon_decor_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx, int height, int width) {}
1818 ++static inline void fbcon_decor_clear_margins(struct vc_data *vc, struct fb_info *info, int bottom_only) {}
1819 ++static inline void fbcon_decor_blank(struct vc_data *vc, struct fb_info *info, int blank) {}
1820 ++static inline void fbcon_decor_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y, int sx, int dx, int width) {}
1821 ++static inline void fbcon_decor_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc) {}
1822 ++static inline int fbcon_decor_call_helper(char *cmd, unsigned short cons) { return 0; }
1823 ++static inline int fbcon_decor_init(void) { return 0; }
1824 ++static inline int fbcon_decor_exit(void) { return 0; }
1825 ++static inline int fbcon_decor_disable(struct vc_data *vc, unsigned char redraw) { return 0; }
1826 ++
1827 ++#define fbcon_decor_active_vc(y) (0)
1828 ++#define fbcon_decor_active_nores(x, y) (0)
1829 ++#define fbcon_decor_active(x, y) (0)
1830 ++
1831 ++#endif /* CONFIG_FB_CON_DECOR */
1832 ++
1833 ++#endif /* __FBCON_DECOR_H */
1834 +diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
1835 +index 88b008f..c84113d 100644
1836 +--- a/drivers/video/fbdev/Kconfig
1837 ++++ b/drivers/video/fbdev/Kconfig
1838 +@@ -1216,7 +1216,6 @@ config FB_MATROX
1839 + select FB_CFB_FILLRECT
1840 + select FB_CFB_COPYAREA
1841 + select FB_CFB_IMAGEBLIT
1842 +- select FB_TILEBLITTING
1843 + select FB_MACMODES if PPC_PMAC
1844 + ---help---
1845 + Say Y here if you have a Matrox Millennium, Matrox Millennium II,
1846 +diff --git a/drivers/video/fbdev/core/fbcmap.c b/drivers/video/fbdev/core/fbcmap.c
1847 +index f89245b..c2c12ce 100644
1848 +--- a/drivers/video/fbdev/core/fbcmap.c
1849 ++++ b/drivers/video/fbdev/core/fbcmap.c
1850 +@@ -17,6 +17,8 @@
1851 + #include <linux/slab.h>
1852 + #include <linux/uaccess.h>
1853 +
1854 ++#include "../../console/fbcondecor.h"
1855 ++
1856 + static u16 red2[] __read_mostly = {
1857 + 0x0000, 0xaaaa
1858 + };
1859 +@@ -254,9 +256,12 @@ int fb_set_cmap(struct fb_cmap *cmap, struct fb_info *info)
1860 + break;
1861 + }
1862 + }
1863 +- if (rc == 0)
1864 ++ if (rc == 0) {
1865 + fb_copy_cmap(cmap, &info->cmap);
1866 +-
1867 ++ if (fbcon_decor_active(info, vc_cons[fg_console].d) &&
1868 ++ info->fix.visual == FB_VISUAL_DIRECTCOLOR)
1869 ++ fbcon_decor_fix_pseudo_pal(info, vc_cons[fg_console].d);
1870 ++ }
1871 + return rc;
1872 + }
1873 +
1874 +diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
1875 +index 76c1ad9..fafc0af 100644
1876 +--- a/drivers/video/fbdev/core/fbmem.c
1877 ++++ b/drivers/video/fbdev/core/fbmem.c
1878 +@@ -1251,15 +1251,6 @@ struct fb_fix_screeninfo32 {
1879 + u16 reserved[3];
1880 + };
1881 +
1882 +-struct fb_cmap32 {
1883 +- u32 start;
1884 +- u32 len;
1885 +- compat_caddr_t red;
1886 +- compat_caddr_t green;
1887 +- compat_caddr_t blue;
1888 +- compat_caddr_t transp;
1889 +-};
1890 +-
1891 + static int fb_getput_cmap(struct fb_info *info, unsigned int cmd,
1892 + unsigned long arg)
1893 + {
1894 +diff --git a/include/linux/console_decor.h b/include/linux/console_decor.h
1895 +new file mode 100644
1896 +index 0000000..1514355
1897 +--- /dev/null
1898 ++++ b/include/linux/console_decor.h
1899 +@@ -0,0 +1,46 @@
1900 ++#ifndef _LINUX_CONSOLE_DECOR_H_
1901 ++#define _LINUX_CONSOLE_DECOR_H_ 1
1902 ++
1903 ++/* A structure used by the framebuffer console decorations (drivers/video/console/fbcondecor.c) */
1904 ++struct vc_decor {
1905 ++ __u8 bg_color; /* The color that is to be treated as transparent */
1906 ++ __u8 state; /* Current decor state: 0 = off, 1 = on */
1907 ++ __u16 tx, ty; /* Top left corner coordinates of the text field */
1908 ++ __u16 twidth, theight; /* Width and height of the text field */
1909 ++ char *theme;
1910 ++};
1911 ++
1912 ++#ifdef __KERNEL__
1913 ++#ifdef CONFIG_COMPAT
1914 ++#include <linux/compat.h>
1915 ++
1916 ++struct vc_decor32 {
1917 ++ __u8 bg_color; /* The color that is to be treated as transparent */
1918 ++ __u8 state; /* Current decor state: 0 = off, 1 = on */
1919 ++ __u16 tx, ty; /* Top left corner coordinates of the text field */
1920 ++ __u16 twidth, theight; /* Width and height of the text field */
1921 ++ compat_uptr_t theme;
1922 ++};
1923 ++
1924 ++#define vc_decor_from_compat(to, from) \
1925 ++ (to).bg_color = (from).bg_color; \
1926 ++ (to).state = (from).state; \
1927 ++ (to).tx = (from).tx; \
1928 ++ (to).ty = (from).ty; \
1929 ++ (to).twidth = (from).twidth; \
1930 ++ (to).theight = (from).theight; \
1931 ++ (to).theme = compat_ptr((from).theme)
1932 ++
1933 ++#define vc_decor_to_compat(to, from) \
1934 ++ (to).bg_color = (from).bg_color; \
1935 ++ (to).state = (from).state; \
1936 ++ (to).tx = (from).tx; \
1937 ++ (to).ty = (from).ty; \
1938 ++ (to).twidth = (from).twidth; \
1939 ++ (to).theight = (from).theight; \
1940 ++ (to).theme = ptr_to_compat((from).theme)
1941 ++
1942 ++#endif /* CONFIG_COMPAT */
1943 ++#endif /* __KERNEL__ */
1944 ++
1945 ++#endif
1946 +diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h
1947 +index 6fd3c90..c649555 100644
1948 +--- a/include/linux/console_struct.h
1949 ++++ b/include/linux/console_struct.h
1950 +@@ -20,6 +20,7 @@ struct vt_struct;
1951 + struct uni_pagedir;
1952 +
1953 + #define NPAR 16
1954 ++#include <linux/console_decor.h>
1955 +
1956 + /*
1957 + * Example: vc_data of a console that was scrolled 3 lines down.
1958 +@@ -140,6 +141,8 @@ struct vc_data {
1959 + struct uni_pagedir *vc_uni_pagedir;
1960 + struct uni_pagedir **vc_uni_pagedir_loc; /* [!] Location of uni_pagedir variable for this console */
1961 + bool vc_panic_force_write; /* when oops/panic this VC can accept forced output/blanking */
1962 ++
1963 ++ struct vc_decor vc_decor;
1964 + /* additional information is in vt_kern.h */
1965 + };
1966 +
1967 +diff --git a/include/linux/fb.h b/include/linux/fb.h
1968 +index a964d07..672cc64 100644
1969 +--- a/include/linux/fb.h
1970 ++++ b/include/linux/fb.h
1971 +@@ -238,6 +238,34 @@ struct fb_deferred_io {
1972 + };
1973 + #endif
1974 +
1975 ++#ifdef __KERNEL__
1976 ++#ifdef CONFIG_COMPAT
1977 ++struct fb_image32 {
1978 ++ __u32 dx; /* Where to place image */
1979 ++ __u32 dy;
1980 ++ __u32 width; /* Size of image */
1981 ++ __u32 height;
1982 ++ __u32 fg_color; /* Only used when a mono bitmap */
1983 ++ __u32 bg_color;
1984 ++ __u8 depth; /* Depth of the image */
1985 ++ const compat_uptr_t data; /* Pointer to image data */
1986 ++ struct fb_cmap32 cmap; /* color map info */
1987 ++};
1988 ++
1989 ++#define fb_image_from_compat(to, from) \
1990 ++ (to).dx = (from).dx; \
1991 ++ (to).dy = (from).dy; \
1992 ++ (to).width = (from).width; \
1993 ++ (to).height = (from).height; \
1994 ++ (to).fg_color = (from).fg_color; \
1995 ++ (to).bg_color = (from).bg_color; \
1996 ++ (to).depth = (from).depth; \
1997 ++ (to).data = compat_ptr((from).data); \
1998 ++ fb_cmap_from_compat((to).cmap, (from).cmap)
1999 ++
2000 ++#endif /* CONFIG_COMPAT */
2001 ++#endif /* __KERNEL__ */
2002 ++
2003 + /*
2004 + * Frame buffer operations
2005 + *
2006 +@@ -508,6 +536,9 @@ struct fb_info {
2007 + #define FBINFO_STATE_SUSPENDED 1
2008 + u32 state; /* Hardware state i.e suspend */
2009 + void *fbcon_par; /* fbcon use-only private area */
2010 ++
2011 ++ struct fb_image bgdecor;
2012 ++
2013 + /* From here on everything is device dependent */
2014 + void *par;
2015 + /* we need the PCI or similar aperture base/size not
2016 +diff --git a/include/uapi/linux/fb.h b/include/uapi/linux/fb.h
2017 +index fb795c3..4b57c67 100644
2018 +--- a/include/uapi/linux/fb.h
2019 ++++ b/include/uapi/linux/fb.h
2020 +@@ -8,6 +8,23 @@
2021 +
2022 + #define FB_MAX 32 /* sufficient for now */
2023 +
2024 ++struct fbcon_decor_iowrapper {
2025 ++ unsigned short vc; /* Virtual console */
2026 ++ unsigned char origin; /* Point of origin of the request */
2027 ++ void *data;
2028 ++};
2029 ++
2030 ++#ifdef __KERNEL__
2031 ++#ifdef CONFIG_COMPAT
2032 ++#include <linux/compat.h>
2033 ++struct fbcon_decor_iowrapper32 {
2034 ++ unsigned short vc; /* Virtual console */
2035 ++ unsigned char origin; /* Point of origin of the request */
2036 ++ compat_uptr_t data;
2037 ++};
2038 ++#endif /* CONFIG_COMPAT */
2039 ++#endif /* __KERNEL__ */
2040 ++
2041 + /* ioctls
2042 + 0x46 is 'F' */
2043 + #define FBIOGET_VSCREENINFO 0x4600
2044 +@@ -35,6 +52,25 @@
2045 + #define FBIOGET_DISPINFO 0x4618
2046 + #define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
2047 +
2048 ++#define FBIOCONDECOR_SETCFG _IOWR('F', 0x19, struct fbcon_decor_iowrapper)
2049 ++#define FBIOCONDECOR_GETCFG _IOR('F', 0x1A, struct fbcon_decor_iowrapper)
2050 ++#define FBIOCONDECOR_SETSTATE _IOWR('F', 0x1B, struct fbcon_decor_iowrapper)
2051 ++#define FBIOCONDECOR_GETSTATE _IOR('F', 0x1C, struct fbcon_decor_iowrapper)
2052 ++#define FBIOCONDECOR_SETPIC _IOWR('F', 0x1D, struct fbcon_decor_iowrapper)
2053 ++#ifdef __KERNEL__
2054 ++#ifdef CONFIG_COMPAT
2055 ++#define FBIOCONDECOR_SETCFG32 _IOWR('F', 0x19, struct fbcon_decor_iowrapper32)
2056 ++#define FBIOCONDECOR_GETCFG32 _IOR('F', 0x1A, struct fbcon_decor_iowrapper32)
2057 ++#define FBIOCONDECOR_SETSTATE32 _IOWR('F', 0x1B, struct fbcon_decor_iowrapper32)
2058 ++#define FBIOCONDECOR_GETSTATE32 _IOR('F', 0x1C, struct fbcon_decor_iowrapper32)
2059 ++#define FBIOCONDECOR_SETPIC32 _IOWR('F', 0x1D, struct fbcon_decor_iowrapper32)
2060 ++#endif /* CONFIG_COMPAT */
2061 ++#endif /* __KERNEL__ */
2062 ++
2063 ++#define FBCON_DECOR_THEME_LEN 128 /* Maximum length of a theme name */
2064 ++#define FBCON_DECOR_IO_ORIG_KERNEL 0 /* Kernel ioctl origin */
2065 ++#define FBCON_DECOR_IO_ORIG_USER 1 /* User ioctl origin */
2066 ++
2067 + #define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */
2068 + #define FB_TYPE_PLANES 1 /* Non interleaved planes */
2069 + #define FB_TYPE_INTERLEAVED_PLANES 2 /* Interleaved planes */
2070 +@@ -277,6 +313,29 @@ struct fb_var_screeninfo {
2071 + __u32 reserved[4]; /* Reserved for future compatibility */
2072 + };
2073 +
2074 ++#ifdef __KERNEL__
2075 ++#ifdef CONFIG_COMPAT
2076 ++struct fb_cmap32 {
2077 ++ __u32 start;
2078 ++ __u32 len; /* Number of entries */
2079 ++ compat_uptr_t red; /* Red values */
2080 ++ compat_uptr_t green;
2081 ++ compat_uptr_t blue;
2082 ++ compat_uptr_t transp; /* transparency, can be NULL */
2083 ++};
2084 ++
2085 ++#define fb_cmap_from_compat(to, from) \
2086 ++ (to).start = (from).start; \
2087 ++ (to).len = (from).len; \
2088 ++ (to).red = compat_ptr((from).red); \
2089 ++ (to).green = compat_ptr((from).green); \
2090 ++ (to).blue = compat_ptr((from).blue); \
2091 ++ (to).transp = compat_ptr((from).transp)
2092 ++
2093 ++#endif /* CONFIG_COMPAT */
2094 ++#endif /* __KERNEL__ */
2095 ++
2096 ++
2097 + struct fb_cmap {
2098 + __u32 start; /* First entry */
2099 + __u32 len; /* Number of entries */
2100 +diff --git a/kernel/sysctl.c b/kernel/sysctl.c
2101 +index 6ee416e..d2c2425 100644
2102 +--- a/kernel/sysctl.c
2103 ++++ b/kernel/sysctl.c
2104 +@@ -149,6 +149,10 @@ static const int cap_last_cap = CAP_LAST_CAP;
2105 + static unsigned long hung_task_timeout_max = (LONG_MAX/HZ);
2106 + #endif
2107 +
2108 ++#ifdef CONFIG_FB_CON_DECOR
2109 ++extern char fbcon_decor_path[];
2110 ++#endif
2111 ++
2112 + #ifdef CONFIG_INOTIFY_USER
2113 + #include <linux/inotify.h>
2114 + #endif
2115 +@@ -266,6 +270,15 @@ static struct ctl_table sysctl_base_table[] = {
2116 + .mode = 0555,
2117 + .child = dev_table,
2118 + },
2119 ++#ifdef CONFIG_FB_CON_DECOR
2120 ++ {
2121 ++ .procname = "fbcondecor",
2122 ++ .data = &fbcon_decor_path,
2123 ++ .maxlen = KMOD_PATH_LEN,
2124 ++ .mode = 0644,
2125 ++ .proc_handler = &proc_dostring,
2126 ++ },
2127 ++#endif
2128 + { }
2129 + };
2130 +