source: npl/kernel/linux_src/fbcondecor-5.10.patch

Last change on this file was 1ebb340, checked in by Edwin Eefting <edwin@datux.nl>, 4 years ago

kernel 5.10

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