]>
Commit | Line | Data |
---|---|---|
8cc4a74e | 1 | diff -Nur --exclude '*.orig' linux-2.6.5-rc2.org/drivers/char/keyboard.c linux-2.6.5-rc2/drivers/char/keyboard.c |
2 | --- linux-2.6.5-rc2.org/drivers/char/keyboard.c 2004-03-20 00:12:22.000000000 +0000 | |
3 | +++ linux-2.6.5-rc2/drivers/char/keyboard.c 2004-03-23 10:00:22.000000000 +0000 | |
4 | @@ -1059,6 +1059,14 @@ | |
5 | if (keycode < BTN_MISC) | |
6 | printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode); | |
7 | ||
8 | +#ifdef CONFIG_BOOTSPLASH | |
9 | + /* This code has to be redone for some non-x86 platforms */ | |
10 | + if (down == 1 && (keycode == 0x3c || keycode == 0x01)) { /* F2 and ESC on PC keyboard */ | |
11 | + extern int splash_verbose(void); | |
12 | + if (splash_verbose()) | |
13 | + return; | |
14 | + } | |
15 | +#endif | |
16 | #ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */ | |
17 | if (keycode == KEY_SYSRQ && (sysrq_down || (down == 1 && sysrq_alt))) { | |
18 | sysrq_down = down; | |
19 | diff -Nur --exclude '*.orig' linux-2.6.5-rc2.org/drivers/char/n_tty.c linux-2.6.5-rc2/drivers/char/n_tty.c | |
20 | --- linux-2.6.5-rc2.org/drivers/char/n_tty.c 2004-03-20 00:11:01.000000000 +0000 | |
21 | +++ linux-2.6.5-rc2/drivers/char/n_tty.c 2004-03-23 10:00:22.000000000 +0000 | |
22 | @@ -994,6 +994,16 @@ | |
23 | return -EIO; | |
24 | } | |
25 | ||
26 | +#ifdef CONFIG_BOOTSPLASH | |
27 | + if (file->f_dentry->d_inode->i_rdev == MKDEV(TTY_MAJOR,0) || | |
28 | + file->f_dentry->d_inode->i_rdev == MKDEV(TTY_MAJOR,1) || | |
29 | + file->f_dentry->d_inode->i_rdev == MKDEV(TTYAUX_MAJOR,0) || | |
30 | + file->f_dentry->d_inode->i_rdev == MKDEV(TTYAUX_MAJOR,1)) { | |
31 | + extern int splash_verbose(void); | |
32 | + (void)splash_verbose(); | |
33 | + } | |
34 | +#endif | |
35 | + | |
36 | /* Job control check -- must be done at start and after | |
37 | every sleep (POSIX.1 7.1.1.4). */ | |
38 | /* NOTE: not yet done after every sleep pending a thorough | |
39 | diff -Nur --exclude '*.orig' linux-2.6.5-rc2.org/drivers/char/vt.c linux-2.6.5-rc2/drivers/char/vt.c | |
40 | --- linux-2.6.5-rc2.org/drivers/char/vt.c 2004-03-23 10:45:29.000000000 +0000 | |
41 | +++ linux-2.6.5-rc2/drivers/char/vt.c 2004-03-23 10:00:22.000000000 +0000 | |
42 | @@ -3142,6 +3142,31 @@ | |
43 | return 0; | |
44 | } | |
45 | ||
46 | +#ifdef CONFIG_BOOTSPLASH | |
47 | +void con_remap_def_color(int currcons, int new_color) | |
48 | +{ | |
49 | + unsigned short *sbuf = screenbuf; | |
50 | + unsigned c, len = screenbuf_size >> 1; | |
51 | + int old_color; | |
52 | + | |
53 | + if (sbuf) { | |
54 | + old_color = def_color << 8; | |
55 | + new_color <<= 8; | |
56 | + while(len--) { | |
57 | + c = *sbuf; | |
58 | + if (((c ^ old_color) & 0xf000) == 0) | |
59 | + *sbuf ^= (old_color ^ new_color) & 0xf000; | |
60 | + if (((c ^ old_color) & 0x0f00) == 0) | |
61 | + *sbuf ^= (old_color ^ new_color) & 0x0f00; | |
62 | + sbuf++; | |
63 | + } | |
64 | + new_color >>= 8; | |
65 | + } | |
66 | + def_color = color = new_color; | |
67 | + update_attr(currcons); | |
68 | +} | |
69 | +#endif | |
70 | + | |
71 | /* | |
72 | * Visible symbols for modules | |
73 | */ | |
74 | diff -Nur --exclude '*.orig' linux-2.6.5-rc2.org/drivers/video/Kconfig linux-2.6.5-rc2/drivers/video/Kconfig | |
75 | --- linux-2.6.5-rc2.org/drivers/video/Kconfig 2004-03-20 00:11:01.000000000 +0000 | |
76 | +++ linux-2.6.5-rc2/drivers/video/Kconfig 2004-03-23 10:00:22.000000000 +0000 | |
77 | @@ -909,5 +909,9 @@ | |
78 | source "drivers/video/logo/Kconfig" | |
79 | endif | |
80 | ||
81 | +if FB | |
82 | + source "drivers/video/bootsplash/Kconfig" | |
83 | +endif | |
84 | + | |
85 | endmenu | |
86 | ||
87 | diff -Nur --exclude '*.orig' linux-2.6.5-rc2.org/drivers/video/Makefile linux-2.6.5-rc2/drivers/video/Makefile | |
88 | --- linux-2.6.5-rc2.org/drivers/video/Makefile 2004-03-20 00:11:02.000000000 +0000 | |
89 | +++ linux-2.6.5-rc2/drivers/video/Makefile 2004-03-23 10:00:22.000000000 +0000 | |
90 | @@ -6,6 +6,7 @@ | |
91 | ||
92 | obj-$(CONFIG_VT) += console/ | |
93 | obj-$(CONFIG_LOGO) += logo/ | |
94 | +obj-$(CONFIG_BOOTSPLASH) += bootsplash/ | |
95 | ||
96 | obj-$(CONFIG_FB) += fbmem.o fbmon.o fbcmap.o fbsysfs.o modedb.o softcursor.o | |
97 | # Only include macmodes.o if we have FB support and are PPC | |
98 | diff -Nur --exclude '*.orig' linux-2.6.5-rc2.org/drivers/video/bootsplash/Kconfig linux-2.6.5-rc2/drivers/video/bootsplash/Kconfig | |
99 | --- linux-2.6.5-rc2.org/drivers/video/bootsplash/Kconfig 1970-01-01 00:00:00.000000000 +0000 | |
100 | +++ linux-2.6.5-rc2/drivers/video/bootsplash/Kconfig 2004-03-23 10:00:22.000000000 +0000 | |
101 | @@ -0,0 +1,17 @@ | |
102 | +# | |
103 | +# Bootsplash configuration | |
104 | +# | |
105 | + | |
106 | +menu "Bootsplash configuration" | |
107 | + | |
108 | +config BOOTSPLASH | |
109 | + bool "Bootup splash screen" | |
110 | + depends on FRAMEBUFFER_CONSOLE | |
111 | + default n | |
112 | + ---help--- | |
113 | + This option enables the Linux bootsplash screen. For more | |
114 | + information on the bootsplash screen have a look at | |
115 | + http://www.bootsplash.org/. | |
116 | + If you are unsure, say N | |
117 | +endmenu | |
118 | + | |
119 | diff -Nur --exclude '*.orig' linux-2.6.5-rc2.org/drivers/video/bootsplash/Makefile linux-2.6.5-rc2/drivers/video/bootsplash/Makefile | |
120 | --- linux-2.6.5-rc2.org/drivers/video/bootsplash/Makefile 1970-01-01 00:00:00.000000000 +0000 | |
121 | +++ linux-2.6.5-rc2/drivers/video/bootsplash/Makefile 2004-03-23 10:00:22.000000000 +0000 | |
122 | @@ -0,0 +1,5 @@ | |
123 | +# Makefile for the Linux bootsplash | |
124 | + | |
125 | +obj-$(CONFIG_BOOTSPLASH) += bootsplash.o | |
126 | +obj-$(CONFIG_BOOTSPLASH) += decode-jpg.o | |
127 | +obj-$(CONFIG_BOOTSPLASH) += render.o | |
128 | diff -Nur --exclude '*.orig' linux-2.6.5-rc2.org/drivers/video/bootsplash/bootsplash.c linux-2.6.5-rc2/drivers/video/bootsplash/bootsplash.c | |
129 | --- linux-2.6.5-rc2.org/drivers/video/bootsplash/bootsplash.c 1970-01-01 00:00:00.000000000 +0000 | |
130 | +++ linux-2.6.5-rc2/drivers/video/bootsplash/bootsplash.c 2004-03-23 10:00:22.000000000 +0000 | |
131 | @@ -0,0 +1,909 @@ | |
132 | +/* | |
133 | + * linux/drivers/video/bootsplash/bootsplash.c - | |
134 | + * splash screen handling functions. | |
135 | + * | |
136 | + * (w) 2001-2003 by Volker Poplawski, <volker@poplawski.de>, | |
137 | + * Stefan Reinauer, <stepan@suse.de>, | |
138 | + * Steffen Winterfeldt, <snwint@suse.de>, | |
139 | + * Michael Schroeder <mls@suse.de> | |
140 | + * | |
141 | + * Ideas & SuSE screen work by Ken Wimer, <wimer@suse.de> | |
142 | + * | |
143 | + * For more information on this code check http://www.bootsplash.org/ | |
144 | + */ | |
145 | + | |
146 | +#include <linux/config.h> | |
147 | +#include <linux/module.h> | |
148 | +#include <linux/types.h> | |
149 | +#include <linux/fb.h> | |
150 | +#include <linux/vt_kern.h> | |
151 | +#include <linux/vmalloc.h> | |
152 | +#include <linux/unistd.h> | |
153 | + | |
154 | +#include <asm/irq.h> | |
155 | +#include <asm/system.h> | |
156 | + | |
157 | +#include "../console/fbcon.h" | |
158 | +#include "bootsplash.h" | |
159 | +#include "decode-jpg.h" | |
160 | + | |
161 | +extern struct fb_ops vesafb_ops; | |
162 | + | |
163 | +#define SPLASH_VERSION "3.1.3-2003/11/14" | |
164 | + | |
165 | +/* These errors have to match fbcon-jpegdec.h */ | |
166 | +static unsigned char *jpg_errors[] = { | |
167 | + "no SOI found", | |
168 | + "not 8 bit", | |
169 | + "height mismatch", | |
170 | + "width mismatch", | |
171 | + "bad width or height", | |
172 | + "too many COMPPs", | |
173 | + "illegal HV", | |
174 | + "quant table selector", | |
175 | + "picture is not YCBCR 221111", | |
176 | + "unknow CID in scan", | |
177 | + "dct not sequential", | |
178 | + "wrong marker", | |
179 | + "no EOI", | |
180 | + "bad tables", | |
181 | + "depth mismatch" | |
182 | +}; | |
183 | + | |
184 | +static struct jpeg_decdata *decdata = 0; /* private decoder data */ | |
185 | + | |
186 | +static int splash_registered = 0; | |
187 | +static int splash_usesilent = 0; /* shall we display the silentjpeg? */ | |
188 | +int splash_default = 0xf01; | |
189 | + | |
190 | +static int splash_check_jpeg(unsigned char *jpeg, int width, int height, int depth); | |
191 | + | |
192 | +static int __init splash_setup(char *options) | |
193 | +{ | |
194 | + if(!strncmp("silent", options, 6)) { | |
195 | + printk(KERN_INFO "bootsplash: silent mode.\n"); | |
196 | + splash_usesilent = 1; | |
197 | + /* skip "silent," */ | |
198 | + if (strlen(options) == 6) | |
199 | + return 0; | |
200 | + options += 7; | |
201 | + } | |
202 | + if(!strncmp("verbose", options, 7)) { | |
203 | + printk(KERN_INFO "bootsplash: verbose mode.\n"); | |
204 | + splash_usesilent = 0; | |
205 | + return 0; | |
206 | + } | |
207 | + splash_default = simple_strtoul(options, NULL, 0); | |
208 | + return 0; | |
209 | +} | |
210 | + | |
211 | +__setup("splash=", splash_setup); | |
212 | + | |
213 | + | |
214 | +static int splash_hasinter(unsigned char *buf, int num) | |
215 | +{ | |
216 | + unsigned char *bufend = buf + num * 12; | |
217 | + while(buf < bufend) { | |
218 | + if (buf[1] > 127) /* inter? */ | |
219 | + return 1; | |
220 | + buf += buf[3] > 127 ? 24 : 12; /* blend? */ | |
221 | + } | |
222 | + return 0; | |
223 | +} | |
224 | + | |
225 | +static int boxextract(unsigned char *buf, unsigned short *dp, unsigned char *cols, int *blendp) | |
226 | +{ | |
227 | + dp[0] = buf[0] | buf[1] << 8; | |
228 | + dp[1] = buf[2] | buf[3] << 8; | |
229 | + dp[2] = buf[4] | buf[5] << 8; | |
230 | + dp[3] = buf[6] | buf[7] << 8; | |
231 | + *(unsigned int *)(cols + 0) = | |
232 | + *(unsigned int *)(cols + 4) = | |
233 | + *(unsigned int *)(cols + 8) = | |
234 | + *(unsigned int *)(cols + 12) = *(unsigned int *)(buf + 8); | |
235 | + if (dp[1] > 32767) { | |
236 | + dp[1] = ~dp[1]; | |
237 | + *(unsigned int *)(cols + 4) = *(unsigned int *)(buf + 12); | |
238 | + *(unsigned int *)(cols + 8) = *(unsigned int *)(buf + 16); | |
239 | + *(unsigned int *)(cols + 12) = *(unsigned int *)(buf + 20); | |
240 | + *blendp = 1; | |
241 | + return 24; | |
242 | + } | |
243 | + return 12; | |
244 | +} | |
245 | + | |
246 | +static void boxit(unsigned char *pic, int bytes, unsigned char *buf, int num, int percent, int overpaint) | |
247 | +{ | |
248 | + int x, y, i, p, doblend, r, g, b, a, add; | |
249 | + unsigned short data1[4]; | |
250 | + unsigned char cols1[16]; | |
251 | + unsigned short data2[4]; | |
252 | + unsigned char cols2[16]; | |
253 | + unsigned char *bufend; | |
254 | + unsigned short *picp; | |
255 | + unsigned int stipple[32], sti, stin, stinn, stixs, stixe, stiys, stiye; | |
256 | + int xs, xe, ys, ye, xo, yo; | |
257 | + | |
258 | + if (num == 0) | |
259 | + return; | |
260 | + bufend = buf + num * 12; | |
261 | + stipple[0] = 0xffffffff; | |
262 | + stin = 1; | |
263 | + stinn = 0; | |
264 | + stixs = stixe = 0; | |
265 | + stiys = stiye = 0; | |
266 | + while(buf < bufend) { | |
267 | + doblend = 0; | |
268 | + buf += boxextract(buf, data1, cols1, &doblend); | |
269 | + if (data1[0] == 32767 && data1[1] == 32767) { | |
270 | + /* box stipple */ | |
271 | + if (stinn == 32) | |
272 | + continue; | |
273 | + if (stinn == 0) { | |
274 | + stixs = data1[2]; | |
275 | + stixe = data1[3]; | |
276 | + stiys = stiye = 0; | |
277 | + } else if (stinn == 4) { | |
278 | + stiys = data1[2]; | |
279 | + stiye = data1[3]; | |
280 | + } | |
281 | + stipple[stinn++] = (cols1[ 0] << 24) | (cols1[ 1] << 16) | (cols1[ 2] << 8) | cols1[ 3] ; | |
282 | + stipple[stinn++] = (cols1[ 4] << 24) | (cols1[ 5] << 16) | (cols1[ 6] << 8) | cols1[ 7] ; | |
283 | + stipple[stinn++] = (cols1[ 8] << 24) | (cols1[ 9] << 16) | (cols1[10] << 8) | cols1[11] ; | |
284 | + stipple[stinn++] = (cols1[12] << 24) | (cols1[13] << 16) | (cols1[14] << 8) | cols1[15] ; | |
285 | + stin = stinn; | |
286 | + continue; | |
287 | + } | |
288 | + stinn = 0; | |
289 | + if (data1[0] > 32767) | |
290 | + buf += boxextract(buf, data2, cols2, &doblend); | |
291 | + if (data1[0] == 32767 && data1[1] == 32766) { | |
292 | + /* box copy */ | |
293 | + i = 12 * (short)data1[3]; | |
294 | + doblend = 0; | |
295 | + i += boxextract(buf + i, data1, cols1, &doblend); | |
296 | + if (data1[0] > 32767) | |
297 | + boxextract(buf + i, data2, cols2, &doblend); | |
298 | + } | |
299 | + if (data1[0] == 32767) | |
300 | + continue; | |
301 | + if (data1[2] > 32767) { | |
302 | + if (overpaint) | |
303 | + continue; | |
304 | + data1[2] = ~data1[2]; | |
305 | + } | |
306 | + if (data1[3] > 32767) { | |
307 | + if (percent == 65536) | |
308 | + continue; | |
309 | + data1[3] = ~data1[3]; | |
310 | + } | |
311 | + if (data1[0] > 32767) { | |
312 | + data1[0] = ~data1[0]; | |
313 | + for (i = 0; i < 4; i++) | |
314 | + data1[i] = (data1[i] * (65536 - percent) + data2[i] * percent) >> 16; | |
315 | + for (i = 0; i < 16; i++) | |
316 | + cols1[i] = (cols1[i] * (65536 - percent) + cols2[i] * percent) >> 16; | |
317 | + } | |
318 | + *(unsigned int *)cols2 = *(unsigned int *)cols1; | |
319 | + a = cols2[3]; | |
320 | + if (a == 0 && !doblend) | |
321 | + continue; | |
322 | + | |
323 | + if (stixs >= 32768) { | |
324 | + xo = xs = (stixs ^ 65535) + data1[0]; | |
325 | + xe = stixe ? stixe + data1[0] : data1[2]; | |
326 | + } else if (stixe >= 32768) { | |
327 | + xs = stixs ? data1[2] - stixs : data1[0]; | |
328 | + xe = data1[2] - (stixe ^ 65535); | |
329 | + xo = xe + 1; | |
330 | + } else { | |
331 | + xo = xs = stixs; | |
332 | + xe = stixe ? stixe : data1[2]; | |
333 | + } | |
334 | + if (stiys >= 32768) { | |
335 | + yo = ys = (stiys ^ 65535) + data1[1]; | |
336 | + ye = stiye ? stiye + data1[1] : data1[3]; | |
337 | + } else if (stiye >= 32768) { | |
338 | + ys = stiys ? data1[3] - stiys : data1[1]; | |
339 | + ye = data1[3] - (stiye ^ 65535); | |
340 | + yo = ye + 1; | |
341 | + } else { | |
342 | + yo = ys = stiys; | |
343 | + ye = stiye ? stiye : data1[3]; | |
344 | + } | |
345 | + xo = 32 - (xo & 31); | |
346 | + yo = stin - (yo % stin); | |
347 | + if (xs < data1[0]) | |
348 | + xs = data1[0]; | |
349 | + if (xe > data1[2]) | |
350 | + xe = data1[2]; | |
351 | + if (ys < data1[1]) | |
352 | + ys = data1[1]; | |
353 | + if (ye > data1[3]) | |
354 | + ye = data1[3]; | |
355 | + | |
356 | + for (y = ys; y <= ye; y++) { | |
357 | + sti = stipple[(y + yo) % stin]; | |
358 | + x = (xs + xo) & 31; | |
359 | + if (x) | |
360 | + sti = (sti << x) | (sti >> (32 - x)); | |
361 | + if (doblend) { | |
362 | + if ((p = data1[3] - data1[1]) != 0) | |
363 | + p = ((y - data1[1]) << 16) / p; | |
364 | + for (i = 0; i < 8; i++) | |
365 | + cols2[i + 8] = (cols1[i] * (65536 - p) + cols1[i + 8] * p) >> 16; | |
366 | + } | |
367 | + add = (xs & 1); | |
368 | + add ^= (add ^ y) & 1 ? 1 : 3; /* 2x2 ordered dithering */ | |
369 | + picp = (unsigned short *)(pic + xs * 2 + y * bytes); | |
370 | + for (x = xs; x <= xe; x++) { | |
371 | + if (!(sti & 0x80000000)) { | |
372 | + sti <<= 1; | |
373 | + picp++; | |
374 | + add ^= 3; | |
375 | + continue; | |
376 | + } | |
377 | + sti = (sti << 1) | 1; | |
378 | + if (doblend) { | |
379 | + if ((p = data1[2] - data1[0]) != 0) | |
380 | + p = ((x - data1[0]) << 16) / p; | |
381 | + for (i = 0; i < 4; i++) | |
382 | + cols2[i] = (cols2[i + 8] * (65536 - p) + cols2[i + 12] * p) >> 16; | |
383 | + a = cols2[3]; | |
384 | + } | |
385 | + r = cols2[0]; | |
386 | + g = cols2[1]; | |
387 | + b = cols2[2]; | |
388 | + if (a != 255) { | |
389 | + i = *picp; | |
390 | + r = ((i >> 8 & 0xf8) * (255 - a) + r * a) / 255; | |
391 | + g = ((i >> 3 & 0xfc) * (255 - a) + g * a) / 255; | |
392 | + b = ((i << 3 & 0xf8) * (255 - a) + b * a) / 255; | |
393 | + } | |
394 | + #define CLAMP(x) ((x) >= 256 ? 255 : (x)) | |
395 | + i = ((CLAMP(r + add*2+1) & 0xf8) << 8) | | |
396 | + ((CLAMP(g + add ) & 0xfc) << 3) | | |
397 | + ((CLAMP(b + add*2+1) ) >> 3); | |
398 | + *picp++ = i; | |
399 | + add ^= 3; | |
400 | + } | |
401 | + } | |
402 | + } | |
403 | +} | |
404 | + | |
405 | +static int splash_check_jpeg(unsigned char *jpeg, int width, int height, int depth) | |
406 | +{ | |
407 | + int size, err; | |
408 | + unsigned char *mem; | |
409 | + | |
410 | + size = ((width + 15) & ~15) * ((height + 15) & ~15) * (depth >> 3); | |
411 | + mem = vmalloc(size); | |
412 | + if (!mem) { | |
413 | + printk(KERN_INFO "bootsplash: no memory for decoded picture.\n"); | |
414 | + return -1; | |
415 | + } | |
416 | + if (!decdata) | |
417 | + decdata = vmalloc(sizeof(*decdata)); | |
418 | + if ((err = jpeg_decode(jpeg, mem, ((width + 15) & ~15), ((height + 15) & ~15), depth, decdata))) | |
419 | + printk(KERN_INFO "bootsplash: error while decompressing picture: %s (%d)\n",jpg_errors[err - 1], err); | |
420 | + vfree(mem); | |
421 | + return err ? -1 : 0; | |
422 | +} | |
423 | + | |
424 | +static void splash_free(struct vc_data *vc, struct fb_info *info) | |
425 | +{ | |
426 | + if (!vc->vc_splash_data) | |
427 | + return; | |
428 | + if (info->silent_screen_base) | |
429 | + info->screen_base = info->silent_screen_base; | |
430 | + info->silent_screen_base = 0; | |
431 | + if (vc->vc_splash_data->splash_silentjpeg) | |
432 | + vfree(vc->vc_splash_data->splash_sboxes); | |
433 | + vfree(vc->vc_splash_data); | |
434 | + vc->vc_splash_data = 0; | |
435 | + info->splash_data = 0; | |
436 | +} | |
437 | + | |
438 | +static int splash_mkpenguin(struct splash_data *data, int pxo, int pyo, int pwi, int phe, int pr, int pg, int pb) | |
439 | +{ | |
440 | + unsigned char *buf; | |
441 | + int i; | |
442 | + | |
443 | + if (pwi ==0 || phe == 0) | |
444 | + return 0; | |
445 | + buf = (unsigned char *)data + sizeof(*data); | |
446 | + pwi += pxo - 1; | |
447 | + phe += pyo - 1; | |
448 | + *buf++ = pxo; | |
449 | + *buf++ = pxo >> 8; | |
450 | + *buf++ = pyo; | |
451 | + *buf++ = pyo >> 8; | |
452 | + *buf++ = pwi; | |
453 | + *buf++ = pwi >> 8; | |
454 | + *buf++ = phe; | |
455 | + *buf++ = phe >> 8; | |
456 | + *buf++ = pr; | |
457 | + *buf++ = pg; | |
458 | + *buf++ = pb; | |
459 | + *buf++ = 0; | |
460 | + for (i = 0; i < 12; i++, buf++) | |
461 | + *buf = buf[-12]; | |
462 | + buf[-24] ^= 0xff; | |
463 | + buf[-23] ^= 0xff; | |
464 | + buf[-1] = 0xff; | |
465 | + return 2; | |
466 | +} | |
467 | + | |
468 | +static const int splash_offsets[3][16] = { | |
469 | + /* len, unit, size, state, fgcol, col, xo, yo, wi, he | |
470 | + boxcnt, ssize, sboxcnt, percent, overok, palcnt */ | |
471 | + /* V1 */ | |
472 | + { 20, -1, 16, -1, -1, -1, 8, 10, 12, 14, | |
473 | + -1, -1, -1, -1, -1, -1 }, | |
474 | + /* V2 */ | |
475 | + { 35, 8, 12, 9, 10, 11, 16, 18, 20, 22, | |
476 | + -1, -1, -1, -1, -1, -1 }, | |
477 | + /* V3 */ | |
478 | + { 38, 8, 12, 9, 10, 11, 16, 18, 20, 22, | |
479 | + 24, 28, 32, 34, 36, 37 }, | |
480 | +}; | |
481 | + | |
482 | +#define SPLASH_OFF_LEN offsets[0] | |
483 | +#define SPLASH_OFF_UNIT offsets[1] | |
484 | +#define SPLASH_OFF_SIZE offsets[2] | |
485 | +#define SPLASH_OFF_STATE offsets[3] | |
486 | +#define SPLASH_OFF_FGCOL offsets[4] | |
487 | +#define SPLASH_OFF_COL offsets[5] | |
488 | +#define SPLASH_OFF_XO offsets[6] | |
489 | +#define SPLASH_OFF_YO offsets[7] | |
490 | +#define SPLASH_OFF_WI offsets[8] | |
491 | +#define SPLASH_OFF_HE offsets[9] | |
492 | +#define SPLASH_OFF_BOXCNT offsets[10] | |
493 | +#define SPLASH_OFF_SSIZE offsets[11] | |
494 | +#define SPLASH_OFF_SBOXCNT offsets[12] | |
495 | +#define SPLASH_OFF_PERCENT offsets[13] | |
496 | +#define SPLASH_OFF_OVEROK offsets[14] | |
497 | +#define SPLASH_OFF_PALCNT offsets[15] | |
498 | + | |
499 | +static inline int splash_getb(unsigned char *pos, int off) | |
500 | +{ | |
501 | + return off == -1 ? 0 : pos[off]; | |
502 | +} | |
503 | + | |
504 | +static inline int splash_gets(unsigned char *pos, int off) | |
505 | +{ | |
506 | + return off == -1 ? 0 : pos[off] | pos[off + 1] << 8; | |
507 | +} | |
508 | + | |
509 | +static inline int splash_geti(unsigned char *pos, int off) | |
510 | +{ | |
511 | + return off == -1 ? 0 : | |
512 | + pos[off] | pos[off + 1] << 8 | pos[off + 2] << 16 | pos[off + 3] << 24; | |
513 | +} | |
514 | + | |
515 | +static int splash_getraw(unsigned char *start, unsigned char *end) | |
516 | +{ | |
517 | + unsigned char *ndata; | |
518 | + int version; | |
519 | + int splash_size; | |
520 | + int unit; | |
521 | + int width, height; | |
522 | + int silentsize; | |
523 | + int boxcnt; | |
524 | + int sboxcnt; | |
525 | + int palcnt; | |
526 | + int i, len; | |
527 | + const int *offsets; | |
528 | + struct vc_data *vc; | |
529 | + struct fb_info *info; | |
530 | + struct splash_data *sd; | |
531 | + | |
532 | + printk(KERN_INFO "bootsplash %s: looking for picture...", SPLASH_VERSION); | |
533 | + | |
534 | + for (ndata = start; ndata < end; ndata++) { | |
535 | + if (ndata[0] != 'B' || ndata[1] != 'O' || ndata[2] != 'O' || ndata[3] != 'T') | |
536 | + continue; | |
537 | + if (ndata[4] != 'S' || ndata[5] != 'P' || ndata[6] != 'L' || ndata[7] < '1' || ndata[7] > '3') | |
538 | + continue; | |
539 | + printk("."); | |
540 | + version = ndata[7] - '0'; | |
541 | + offsets = splash_offsets[version - 1]; | |
542 | + len = SPLASH_OFF_LEN; | |
543 | + unit = splash_getb(ndata, SPLASH_OFF_UNIT); | |
544 | + if (unit >= MAX_NR_CONSOLES) | |
545 | + continue; | |
546 | + if (unit) | |
547 | + vc_allocate(unit); | |
548 | + vc = vc_cons[unit].d; | |
549 | + info = registered_fb[(int)con2fb_map[unit]]; | |
550 | + width = info->var.xres; | |
551 | + height = info->var.yres; | |
552 | + splash_size = splash_geti(ndata, SPLASH_OFF_SIZE); | |
553 | + if (splash_size == (int)0xffffffff && version > 1) { | |
554 | + printk(" found, updating values.\n"); | |
555 | + if ((sd = vc->vc_splash_data) != 0) { | |
556 | + i = splash_getb(ndata, SPLASH_OFF_STATE); | |
557 | + if (i != 255) | |
558 | + sd->splash_state = i; | |
559 | + i = splash_getb(ndata, SPLASH_OFF_FGCOL); | |
560 | + if (i != 255) | |
561 | + sd->splash_fg_color = i; | |
562 | + i = splash_getb(ndata, SPLASH_OFF_COL); | |
563 | + if (i != 255) | |
564 | + sd->splash_color = i; | |
565 | + } | |
566 | + return unit; | |
567 | + } | |
568 | + if (splash_size == 0) { | |
569 | + printk(" found, freeing memory.\n"); | |
570 | + if (vc->vc_splash_data) | |
571 | + splash_free(vc, info); | |
572 | + return unit; | |
573 | + } | |
574 | + boxcnt = splash_gets(ndata, SPLASH_OFF_BOXCNT); | |
575 | + palcnt = 3 * splash_getb(ndata, SPLASH_OFF_PALCNT); | |
576 | + if (ndata + len + splash_size > end) { | |
577 | + printk(" found, but truncated!\n"); | |
578 | + return -1; | |
579 | + } | |
580 | + if (!jpeg_check_size(ndata + len + boxcnt * 12 + palcnt, width, height)) { | |
581 | + ndata += len + splash_size - 1; | |
582 | + continue; | |
583 | + } | |
584 | + if (splash_check_jpeg(ndata + len + boxcnt * 12 + palcnt, width, height, info->var.bits_per_pixel)) | |
585 | + return -1; | |
586 | + silentsize = splash_geti(ndata, SPLASH_OFF_SSIZE); | |
587 | + if (silentsize) | |
588 | + printk(" silentjpeg size %d bytes,", silentsize); | |
589 | + if (silentsize >= splash_size) { | |
590 | + printk(" bigger than splashsize!\n"); | |
591 | + return -1; | |
592 | + } | |
593 | + splash_size -= silentsize; | |
594 | + if (!splash_usesilent) | |
595 | + silentsize = 0; | |
596 | + else if (height * 2 * info->fix.line_length > info->fix.smem_len) { | |
597 | + printk(" does not fit into framebuffer.\n"); | |
598 | + silentsize = 0; | |
599 | + } | |
600 | + sboxcnt = splash_gets(ndata, SPLASH_OFF_SBOXCNT); | |
601 | + if (silentsize) { | |
602 | + unsigned char *simage = ndata + len + splash_size + 12 * sboxcnt; | |
603 | + if (!jpeg_check_size(simage, width, height) || | |
604 | + splash_check_jpeg(simage, width, height, info->var.bits_per_pixel)) { | |
605 | + printk(" error in silent jpeg.\n"); | |
606 | + silentsize = 0; | |
607 | + } | |
608 | + } | |
609 | + if (vc->vc_splash_data) | |
610 | + splash_free(vc, info); | |
611 | + vc->vc_splash_data = sd = vmalloc(sizeof(*sd) + splash_size + (version < 3 ? 2 * 12 : 0)); | |
612 | + if (!sd) | |
613 | + break; | |
614 | + sd->splash_silentjpeg = 0; | |
615 | + sd->splash_sboxes = 0; | |
616 | + sd->splash_sboxcount = 0; | |
617 | + if (silentsize) { | |
618 | + sd->splash_silentjpeg = vmalloc(silentsize); | |
619 | + if (sd->splash_silentjpeg) { | |
620 | + memcpy(sd->splash_silentjpeg, ndata + len + splash_size, silentsize); | |
621 | + sd->splash_sboxes = vc->vc_splash_data->splash_silentjpeg; | |
622 | + sd->splash_silentjpeg += 12 * sboxcnt; | |
623 | + sd->splash_sboxcount = sboxcnt; | |
624 | + } | |
625 | + } | |
626 | + sd->splash_state = splash_getb(ndata, SPLASH_OFF_STATE); | |
627 | + sd->splash_fg_color = splash_getb(ndata, SPLASH_OFF_FGCOL); | |
628 | + sd->splash_color = splash_getb(ndata, SPLASH_OFF_COL); | |
629 | + sd->splash_overpaintok = splash_getb(ndata, SPLASH_OFF_OVEROK); | |
630 | + sd->splash_text_xo = splash_gets(ndata, SPLASH_OFF_XO); | |
631 | + sd->splash_text_yo = splash_gets(ndata, SPLASH_OFF_YO); | |
632 | + sd->splash_text_wi = splash_gets(ndata, SPLASH_OFF_WI); | |
633 | + sd->splash_text_he = splash_gets(ndata, SPLASH_OFF_HE); | |
634 | + sd->splash_percent = splash_gets(ndata, SPLASH_OFF_PERCENT); | |
635 | + if (version == 1) { | |
636 | + sd->splash_text_xo *= 8; | |
637 | + sd->splash_text_wi *= 8; | |
638 | + sd->splash_text_yo *= 16; | |
639 | + sd->splash_text_he *= 16; | |
640 | + sd->splash_color = (splash_default >> 8) & 0x0f; | |
641 | + sd->splash_fg_color = (splash_default >> 4) & 0x0f; | |
642 | + sd->splash_state = splash_default & 1; | |
643 | + } | |
644 | + if (sd->splash_text_xo + sd->splash_text_wi > width || sd->splash_text_yo + sd->splash_text_he > height) { | |
645 | + splash_free(vc, info); | |
646 | + printk(" found, but has oversized text area!\n"); | |
647 | + return -1; | |
648 | + } | |
649 | + if (!vc_cons[unit].d || info->fbops != &vesafb_ops) { | |
650 | + splash_free(vc, info); | |
651 | + printk(" found, but framebuffer can't handle it!\n"); | |
652 | + return -1; | |
653 | + } | |
654 | + printk(" found (%dx%d, %d bytes, v%d).\n", width, height, splash_size, version); | |
655 | + if (version == 1) { | |
656 | + printk(KERN_WARNING "bootsplash: Using deprecated v1 header. Updating your splash utility recommended.\n"); | |
657 | + printk(KERN_INFO "bootsplash: Find the latest version at http://www.bootsplash.org/\n"); | |
658 | + } | |
659 | + | |
660 | + /* fake penguin box for older formats */ | |
661 | + if (version == 1) | |
662 | + boxcnt = splash_mkpenguin(sd, sd->splash_text_xo + 10, sd->splash_text_yo + 10, sd->splash_text_wi - 20, sd->splash_text_he - 20, 0xf0, 0xf0, 0xf0); | |
663 | + else if (version == 2) | |
664 | + boxcnt = splash_mkpenguin(sd, splash_gets(ndata, 24), splash_gets(ndata, 26), splash_gets(ndata, 28), splash_gets(ndata, 30), splash_getb(ndata, 32), splash_getb(ndata, 33), splash_getb(ndata, 34)); | |
665 | + | |
666 | + memcpy((char *)sd + sizeof(*sd) + (version < 3 ? boxcnt * 12 : 0), ndata + len, splash_size); | |
667 | + sd->splash_boxcount = boxcnt; | |
668 | + sd->splash_boxes = (unsigned char *)sd + sizeof(*sd); | |
669 | + sd->splash_palette = sd->splash_boxes + boxcnt * 12; | |
670 | + sd->splash_jpeg = sd->splash_palette + palcnt; | |
671 | + sd->splash_palcnt = palcnt / 3; | |
672 | + sd->splash_dosilent = sd->splash_silentjpeg != 0; | |
673 | + return unit; | |
674 | + } | |
675 | + printk(" no good signature found.\n"); | |
676 | + return -1; | |
677 | +} | |
678 | + | |
679 | +int splash_verbose(void) | |
680 | +{ | |
681 | + struct vc_data *vc; | |
682 | + struct fb_info *info; | |
683 | + | |
684 | + if (!splash_usesilent) | |
685 | + return 0; | |
686 | + | |
687 | + vc = vc_cons[0].d; | |
688 | + | |
689 | + if (!vc || !vc->vc_splash_data || !vc->vc_splash_data->splash_state) | |
690 | + return 0; | |
691 | + if (fg_console != vc->vc_num) | |
692 | + return 0; | |
693 | + if (!vc->vc_splash_data->splash_silentjpeg || !vc->vc_splash_data->splash_dosilent) | |
694 | + return 0; | |
695 | + vc->vc_splash_data->splash_dosilent = 0; | |
696 | + info = registered_fb[(int)con2fb_map[0]]; | |
697 | + if (!info->silent_screen_base) | |
698 | + return 0; | |
699 | + splashcopy(info->silent_screen_base, info->screen_base, info->var.yres, info->var.xres, info->fix.line_length, info->fix.line_length); | |
700 | + info->screen_base = info->silent_screen_base; | |
701 | + info->silent_screen_base = 0; | |
702 | + return 1; | |
703 | +} | |
704 | + | |
705 | +static void splash_off(struct fb_info *info) | |
706 | +{ | |
707 | + if (info->silent_screen_base) | |
708 | + info->screen_base = info->silent_screen_base; | |
709 | + info->silent_screen_base = 0; | |
710 | + info->splash_data = 0; | |
711 | + if (info->splash_pic) | |
712 | + vfree(info->splash_pic); | |
713 | + info->splash_pic = 0; | |
714 | + info->splash_pic_size = 0; | |
715 | +} | |
716 | + | |
717 | +int splash_prepare(struct vc_data *vc, struct fb_info *info) | |
718 | +{ | |
719 | + int err; | |
720 | + int width, height, depth, size, sbytes; | |
721 | + | |
722 | + if (!vc->vc_splash_data || !vc->vc_splash_data->splash_state) { | |
723 | + if (decdata) | |
724 | + vfree(decdata); | |
725 | + decdata = 0; | |
726 | + splash_off(info); | |
727 | + return -1; | |
728 | + } | |
729 | + | |
730 | + width = info->var.xres; | |
731 | + height = info->var.yres; | |
732 | + depth = info->var.bits_per_pixel; | |
733 | + if (depth != 16) { /* Other targets might need fixing */ | |
734 | + splash_off(info); | |
735 | + return -2; | |
736 | + } | |
737 | + | |
738 | + sbytes = ((width + 15) & ~15) * (depth >> 3); | |
739 | + size = sbytes * ((height + 15) & ~15); | |
740 | + if (size != info->splash_pic_size) | |
741 | + splash_off(info); | |
742 | + if (!info->splash_pic) | |
743 | + info->splash_pic = vmalloc(size); | |
744 | + | |
745 | + if (!info->splash_pic) { | |
746 | + printk(KERN_INFO "bootsplash: not enough memory.\n"); | |
747 | + splash_off(info); | |
748 | + return -3; | |
749 | + } | |
750 | + | |
751 | + if (!decdata) | |
752 | + decdata = vmalloc(sizeof(*decdata)); | |
753 | + | |
754 | + if (vc->vc_splash_data->splash_silentjpeg && vc->vc_splash_data->splash_dosilent) { | |
755 | + /* fill area after framebuffer with other jpeg */ | |
756 | + if ((err = jpeg_decode(vc->vc_splash_data->splash_silentjpeg, info->splash_pic, | |
757 | + ((width + 15) & ~15), ((height + 15) & ~15), depth, decdata))) { | |
758 | + printk(KERN_INFO "bootsplash: error while decompressing silent picture: %s (%d)\n", jpg_errors[err - 1], err); | |
759 | + if (info->silent_screen_base) | |
760 | + info->screen_base = info->silent_screen_base; | |
761 | + vc->vc_splash_data->splash_dosilent = 0; | |
762 | + } else { | |
763 | + if (vc->vc_splash_data->splash_sboxcount) | |
764 | + boxit(info->splash_pic, sbytes, vc->vc_splash_data->splash_sboxes, | |
765 | + vc->vc_splash_data->splash_sboxcount, vc->vc_splash_data->splash_percent, 0); | |
766 | + | |
767 | + if (!info->silent_screen_base) | |
768 | + info->silent_screen_base = info->screen_base; | |
769 | + splashcopy(info->silent_screen_base, info->splash_pic, info->var.yres, info->var.xres, info->fix.line_length, sbytes); | |
770 | + info->screen_base = info->silent_screen_base + info->fix.line_length * info->var.yres; | |
771 | + } | |
772 | + } else if (info->silent_screen_base) | |
773 | + info->screen_base = info->silent_screen_base; | |
774 | + | |
775 | + if ((err = jpeg_decode(vc->vc_splash_data->splash_jpeg, info->splash_pic, | |
776 | + ((width + 15) & ~15), ((height + 15) & ~15), depth, decdata))) { | |
777 | + printk(KERN_INFO "bootsplash: error while decompressing picture: %s (%d) .\n", jpg_errors[err - 1], err); | |
778 | + splash_off(info); | |
779 | + return -4; | |
780 | + } | |
781 | + info->splash_pic_size = size; | |
782 | + info->splash_bytes = sbytes; | |
783 | + if (vc->vc_splash_data->splash_boxcount) | |
784 | + boxit(info->splash_pic, sbytes, vc->vc_splash_data->splash_boxes, vc->vc_splash_data->splash_boxcount, vc->vc_splash_data->splash_percent, 0); | |
785 | + if (vc->vc_splash_data->splash_state) | |
786 | + info->splash_data = vc->vc_splash_data; | |
787 | + else | |
788 | + splash_off(info); | |
789 | + return 0; | |
790 | +} | |
791 | + | |
792 | + | |
793 | +#ifdef CONFIG_PROC_FS | |
794 | + | |
795 | +#include <linux/proc_fs.h> | |
796 | + | |
797 | +static int splash_read_proc(char *buffer, char **start, off_t offset, int size, | |
798 | + int *eof, void *data); | |
799 | +static int splash_write_proc(struct file *file, const char *buffer, | |
800 | + unsigned long count, void *data); | |
801 | +static int splash_status(struct vc_data *vc); | |
802 | +static int splash_recolor(struct vc_data *vc); | |
803 | +static int splash_proc_register(void); | |
804 | + | |
805 | +static struct proc_dir_entry *proc_splash; | |
806 | + | |
807 | +static int splash_recolor(struct vc_data *vc) | |
808 | +{ | |
809 | + if (!vc->vc_splash_data) | |
810 | + return -1; | |
811 | + if (!vc->vc_splash_data->splash_state) | |
812 | + return 0; | |
813 | + con_remap_def_color(vc->vc_num, vc->vc_splash_data->splash_color << 4 | vc->vc_splash_data->splash_fg_color); | |
814 | + if (fg_console == vc->vc_num) { | |
815 | + update_region(fg_console, | |
816 | + vc->vc_origin + vc->vc_size_row * vc->vc_top, | |
817 | + vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2); | |
818 | + } | |
819 | + return 0; | |
820 | +} | |
821 | + | |
822 | +static int splash_status(struct vc_data *vc) | |
823 | +{ | |
824 | + struct fb_info *info; | |
825 | + printk(KERN_INFO "bootsplash: status on console %d changed to %s\n", vc->vc_num, vc->vc_splash_data && vc->vc_splash_data->splash_state ? "on" : "off"); | |
826 | + | |
827 | + info = registered_fb[(int) con2fb_map[vc->vc_num]]; | |
828 | + if (fg_console == vc->vc_num) | |
829 | + splash_prepare(vc, info); | |
830 | + if (vc->vc_splash_data && vc->vc_splash_data->splash_state) { | |
831 | + con_remap_def_color(vc->vc_num, vc->vc_splash_data->splash_color << 4 | vc->vc_splash_data->splash_fg_color); | |
832 | + /* vc_resize also calls con_switch which resets yscroll */ | |
833 | + vc_resize(vc->vc_num, vc->vc_splash_data->splash_text_wi / vc->vc_font.width, vc->vc_splash_data->splash_text_he / vc->vc_font.height); | |
834 | + if (fg_console == vc->vc_num) { | |
835 | + update_region(fg_console, | |
836 | + vc->vc_origin + vc->vc_size_row * vc->vc_top, | |
837 | + vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2); | |
838 | + splash_clear_margins(vc->vc_splash_data, vc, info, 0); | |
839 | + } | |
840 | + } else { | |
841 | + /* Switch bootsplash off */ | |
842 | + con_remap_def_color(vc->vc_num, 0x07); | |
843 | + vc_resize(vc->vc_num, info->var.xres / vc->vc_font.width, info->var.yres / vc->vc_font.height); | |
844 | + } | |
845 | + return 0; | |
846 | +} | |
847 | + | |
848 | +static int splash_read_proc(char *buffer, char **start, off_t offset, int size, | |
849 | + int *eof, void *data) | |
850 | +{ | |
851 | + int len = 0; | |
852 | + off_t begin = 0; | |
853 | + struct vc_data *vc = vc_cons[0].d; | |
854 | + struct fb_info *info = registered_fb[(int)con2fb_map[0]]; | |
855 | + int color = vc->vc_splash_data ? vc->vc_splash_data->splash_color << 4 | | |
856 | + vc->vc_splash_data->splash_fg_color : splash_default >> 4; | |
857 | + int status = vc->vc_splash_data ? vc->vc_splash_data->splash_state & 1 : 0; | |
858 | + len += sprintf(buffer + len, "Splash screen v%s (0x%02x, %dx%d%s): %s\n", | |
859 | + SPLASH_VERSION, color, info->var.xres, info->var.yres, | |
860 | + (vc->vc_splash_data ? vc->vc_splash_data->splash_dosilent : 0)? ", silent" : "", | |
861 | + status ? "on" : "off"); | |
862 | + if (offset >= begin + len) | |
863 | + return 0; | |
864 | + | |
865 | + *start = buffer + (begin - offset); | |
866 | + | |
867 | + return (size < begin + len - offset ? size : begin + len - offset); | |
868 | +} | |
869 | + | |
870 | +static int splash_write_proc(struct file *file, const char *buffer, | |
871 | + unsigned long count, void *data) | |
872 | +{ | |
873 | + int new, unit; | |
874 | + struct vc_data *vc; | |
875 | + | |
876 | + if (!buffer || !splash_default) | |
877 | + return count; | |
878 | + | |
879 | + if (!strncmp(buffer, "show", 4) || !strncmp(buffer, "hide", 4)) { | |
880 | + int pe, oldpe; | |
881 | + | |
882 | + vc = vc_cons[0].d; | |
883 | + if (buffer[4] == ' ' && buffer[5] == 'p') | |
884 | + pe = 0; | |
885 | + else if (buffer[4] == '\n') | |
886 | + pe = 65535; | |
887 | + else | |
888 | + pe = simple_strtoul(buffer + 5, NULL, 0); | |
889 | + if (pe < 0) | |
890 | + pe = 0; | |
891 | + if (pe > 65535) | |
892 | + pe = 65535; | |
893 | + if (*buffer == 'h') | |
894 | + pe = 65535 - pe; | |
895 | + pe += pe > 32767; | |
896 | + if (vc->vc_splash_data && vc->vc_splash_data->splash_percent != pe) { | |
897 | + struct fb_info *info; | |
898 | + | |
899 | + oldpe = vc->vc_splash_data->splash_percent; | |
900 | + vc->vc_splash_data->splash_percent = pe; | |
901 | + if (fg_console != 0 || !vc->vc_splash_data->splash_state) | |
902 | + return count; | |
903 | + info = registered_fb[(int) con2fb_map[vc->vc_num]]; | |
904 | + if (!vc->vc_splash_data->splash_overpaintok || pe == 65536 || pe < oldpe) { | |
905 | + if (splash_hasinter(vc->vc_splash_data->splash_boxes, vc->vc_splash_data->splash_boxcount)) | |
906 | + splash_status(vc); | |
907 | + else | |
908 | + splash_prepare(vc, info); | |
909 | + } else { | |
910 | + if (vc->vc_splash_data->splash_silentjpeg && vc->vc_splash_data->splash_dosilent && info->silent_screen_base) | |
911 | + boxit(info->silent_screen_base, info->fix.line_length, vc->vc_splash_data->splash_sboxes, vc->vc_splash_data->splash_sboxcount, vc->vc_splash_data->splash_percent, 1); | |
912 | + boxit(info->screen_base, info->fix.line_length, vc->vc_splash_data->splash_boxes, vc->vc_splash_data->splash_boxcount, vc->vc_splash_data->splash_percent, 1); | |
913 | + } | |
914 | + } | |
915 | + return count; | |
916 | + } | |
917 | + if (!strncmp(buffer,"silent\n",7) || !strncmp(buffer,"verbose\n",8)) { | |
918 | + vc = vc_cons[0].d; | |
919 | + if (vc->vc_splash_data && vc->vc_splash_data->splash_silentjpeg) { | |
920 | + if (vc->vc_splash_data->splash_dosilent != (buffer[0] == 's')) { | |
921 | + vc->vc_splash_data->splash_dosilent = buffer[0] == 's'; | |
922 | + splash_status(vc); | |
923 | + } | |
924 | + } | |
925 | + return count; | |
926 | + } | |
927 | + if (!strncmp(buffer,"freesilent\n",11)) { | |
928 | + vc = vc_cons[0].d; | |
929 | + if (vc->vc_splash_data && vc->vc_splash_data->splash_silentjpeg) { | |
930 | + printk(KERN_INFO "bootsplash: freeing silent jpeg\n"); | |
931 | + vc->vc_splash_data->splash_silentjpeg = 0; | |
932 | + vfree(vc->vc_splash_data->splash_sboxes); | |
933 | + vc->vc_splash_data->splash_sboxes = 0; | |
934 | + vc->vc_splash_data->splash_sboxcount = 0; | |
935 | + if (vc->vc_splash_data->splash_dosilent) | |
936 | + splash_status(vc); | |
937 | + vc->vc_splash_data->splash_dosilent = 0; | |
938 | + } | |
939 | + return count; | |
940 | + } | |
941 | + | |
942 | + if (!strncmp(buffer, "BOOTSPL", 7)) { | |
943 | + unit = splash_getraw((unsigned char *)buffer, (unsigned char *)buffer + count); | |
944 | + if (unit >= 0) { | |
945 | + vc = vc_cons[unit].d; | |
946 | + splash_status(vc); | |
947 | + } | |
948 | + return count; | |
949 | + } | |
950 | + vc = vc_cons[0].d; | |
951 | + if (!vc->vc_splash_data) | |
952 | + return count; | |
953 | + if (buffer[0] == 't') { | |
954 | + vc->vc_splash_data->splash_state ^= 1; | |
955 | + splash_status(vc); | |
956 | + return count; | |
957 | + } | |
958 | + new = simple_strtoul(buffer, NULL, 0); | |
959 | + if (new > 1) { | |
960 | + /* expert user */ | |
961 | + vc->vc_splash_data->splash_color = new >> 8 & 0xff; | |
962 | + vc->vc_splash_data->splash_fg_color = new >> 4 & 0x0f; | |
963 | + } | |
964 | + if ((new & 1) == vc->vc_splash_data->splash_state) | |
965 | + splash_recolor(vc); | |
966 | + else { | |
967 | + vc->vc_splash_data->splash_state = new & 1; | |
968 | + splash_status(vc); | |
969 | + } | |
970 | + return count; | |
971 | +} | |
972 | + | |
973 | +static int splash_proc_register(void) | |
974 | +{ | |
975 | + if ((proc_splash = create_proc_entry("splash", 0, 0))) { | |
976 | + proc_splash->read_proc = splash_read_proc; | |
977 | + proc_splash->write_proc = splash_write_proc; | |
978 | + return 0; | |
979 | + } | |
980 | + return 1; | |
981 | +} | |
982 | + | |
983 | +# if 0 | |
984 | +static int splash_proc_unregister(void) | |
985 | +{ | |
986 | + if (proc_splash) | |
987 | + remove_proc_entry("splash", 0); | |
988 | + return 0; | |
989 | +} | |
990 | +# endif | |
991 | +#endif /* CONFIG_PROC_FS */ | |
992 | + | |
993 | +asmlinkage long sys_lseek(int fd, off_t offset, unsigned int origin); | |
994 | +asmlinkage long sys_read(int fd, char *buf, size_t count); | |
995 | +asmlinkage long sys_unlink(const char *name); | |
996 | + | |
997 | +void splash_init(void) | |
998 | +{ | |
999 | + struct fb_info *info; | |
1000 | + struct vc_data *vc; | |
1001 | + int isramfs = 1; | |
1002 | + int fd; | |
1003 | + int len; | |
1004 | + char *mem; | |
1005 | + | |
1006 | + if (splash_registered) | |
1007 | + return; | |
1008 | + vc = vc_cons[0].d; | |
1009 | + info = registered_fb[0]; | |
1010 | + if (!vc || !info || info->var.bits_per_pixel != 16) | |
1011 | + return; | |
1012 | +#ifdef CONFIG_PROC_FS | |
1013 | + splash_proc_register(); | |
1014 | +#endif | |
1015 | + splash_registered = 1; | |
1016 | + if (vc->vc_splash_data) | |
1017 | + return; | |
1018 | + if ((fd = sys_open("/bootsplash", O_RDONLY, 0)) < 0) { | |
1019 | + isramfs = 0; | |
1020 | + fd = sys_open("/initrd.image", O_RDONLY, 0); | |
1021 | + } | |
1022 | + if (fd < 0) | |
1023 | + return; | |
1024 | + if ((len = (int)sys_lseek(fd, (off_t)0, 2)) <= 0) { | |
1025 | + sys_close(fd); | |
1026 | + return; | |
1027 | + } | |
1028 | + sys_lseek(fd, (off_t)0, 0); | |
1029 | + mem = vmalloc(len); | |
1030 | + if (mem) { | |
1031 | + if ((int)sys_read(fd, mem, len) == len && splash_getraw((unsigned char *)mem, (unsigned char *)mem + len) == 0 && vc->vc_splash_data) | |
1032 | + vc->vc_splash_data->splash_state = splash_default & 1; | |
1033 | + vfree(mem); | |
1034 | + } | |
1035 | + sys_close(fd); | |
1036 | + if (isramfs) | |
1037 | + sys_unlink("/bootsplash"); | |
1038 | + return; | |
1039 | +} | |
1040 | + | |
1041 | diff -Nur --exclude '*.orig' linux-2.6.5-rc2.org/drivers/video/bootsplash/bootsplash.h linux-2.6.5-rc2/drivers/video/bootsplash/bootsplash.h | |
1042 | --- linux-2.6.5-rc2.org/drivers/video/bootsplash/bootsplash.h 1970-01-01 00:00:00.000000000 +0000 | |
1043 | +++ linux-2.6.5-rc2/drivers/video/bootsplash/bootsplash.h 2004-03-23 10:00:22.000000000 +0000 | |
1044 | @@ -0,0 +1,41 @@ | |
1045 | +/* | |
1046 | + * linux/drivers/video/bootsplash/bootsplash.h - splash screen definition. | |
1047 | + * | |
1048 | + * (w) 2001-2003 by Volker Poplawski, <volker@poplawski.de> | |
1049 | + * Stefan Reinauer, <stepan@suse.de> | |
1050 | + * | |
1051 | + * | |
1052 | + * idea and SuSE screen work by Ken Wimer, <wimer@suse.de> | |
1053 | + */ | |
1054 | + | |
1055 | +#ifndef __BOOTSPLASH_H | |
1056 | +#define __BOOTSPLASH_H | |
1057 | + | |
1058 | +struct fb_info; | |
1059 | + | |
1060 | +/* splash.c */ | |
1061 | +extern int splash_prepare(struct vc_data *, struct fb_info *); | |
1062 | +extern void splash_init(void); | |
1063 | + | |
1064 | +/* splash_render.c */ | |
1065 | +extern void splash_putcs(struct splash_data *sd, struct vc_data *vc, struct fb_info *info, | |
1066 | + const unsigned short *s, int count, int ypos, int xpos); | |
1067 | +extern void splash_putc(struct splash_data *sd, struct vc_data *vc, struct fb_info *info, | |
1068 | + int c, int ypos, int xpos); | |
1069 | +extern void splashcopy(u8 *dst, u8 *src, int height, int width, int dstbytes, int srcbytes); | |
1070 | +extern void splash_clear(struct splash_data *sd, struct vc_data *vc, struct fb_info *info, int sy, | |
1071 | + int sx, int height, int width); | |
1072 | +extern void splash_bmove(struct splash_data *sd, struct vc_data *vc, struct fb_info *info, int sy, | |
1073 | + int sx, int dy, int dx, int height, int width); | |
1074 | +extern void splash_clear_margins(struct splash_data *sd, struct vc_data *vc, struct fb_info *info, | |
1075 | + int bottom_only); | |
1076 | +extern void splash_cursor(struct splash_data *sd, struct fb_info *info, struct fb_cursor *cursor); | |
1077 | +extern void splash_bmove_redraw(struct splash_data *sd, struct vc_data *vc, struct fb_info *info, | |
1078 | + int y, int sx, int dx, int width); | |
1079 | +extern void splash_blank(struct splash_data *sd, struct vc_data *vc, struct fb_info *info, | |
1080 | + int blank); | |
1081 | + | |
1082 | +/* vt.c */ | |
1083 | +extern void con_remap_def_color(int currcons, int new_color); | |
1084 | + | |
1085 | +#endif | |
1086 | diff -Nur --exclude '*.orig' linux-2.6.5-rc2.org/drivers/video/bootsplash/decode-jpg.c linux-2.6.5-rc2/drivers/video/bootsplash/decode-jpg.c | |
1087 | --- linux-2.6.5-rc2.org/drivers/video/bootsplash/decode-jpg.c 1970-01-01 00:00:00.000000000 +0000 | |
1088 | +++ linux-2.6.5-rc2/drivers/video/bootsplash/decode-jpg.c 2004-03-23 10:00:22.000000000 +0000 | |
1089 | @@ -0,0 +1,958 @@ | |
1090 | +/* | |
1091 | + * linux/drivers/video/bootsplash/decode-jpg.c - a tiny jpeg decoder. | |
1092 | + * | |
1093 | + * (w) August 2001 by Michael Schroeder, <mls@suse.de> | |
1094 | + * | |
1095 | + */ | |
1096 | + | |
1097 | +#include <linux/config.h> | |
1098 | +#include <linux/string.h> | |
1099 | +#include <asm/byteorder.h> | |
1100 | + | |
1101 | +#include "decode-jpg.h" | |
1102 | + | |
1103 | +#define ISHIFT 11 | |
1104 | + | |
1105 | +#define IFIX(a) ((int)((a) * (1 << ISHIFT) + .5)) | |
1106 | +#define IMULT(a, b) (((a) * (b)) >> ISHIFT) | |
1107 | +#define ITOINT(a) ((a) >> ISHIFT) | |
1108 | + | |
1109 | +#ifndef __P | |
1110 | +# define __P(x) x | |
1111 | +#endif | |
1112 | + | |
1113 | +/* special markers */ | |
1114 | +#define M_BADHUFF -1 | |
1115 | +#define M_EOF 0x80 | |
1116 | + | |
1117 | +struct in { | |
1118 | + unsigned char *p; | |
1119 | + unsigned int bits; | |
1120 | + int left; | |
1121 | + int marker; | |
1122 | + | |
1123 | + int (*func) __P((void *)); | |
1124 | + void *data; | |
1125 | +}; | |
1126 | + | |
1127 | +/*********************************/ | |
1128 | +struct dec_hufftbl; | |
1129 | +struct enc_hufftbl; | |
1130 | + | |
1131 | +union hufftblp { | |
1132 | + struct dec_hufftbl *dhuff; | |
1133 | + struct enc_hufftbl *ehuff; | |
1134 | +}; | |
1135 | + | |
1136 | +struct scan { | |
1137 | + int dc; /* old dc value */ | |
1138 | + | |
1139 | + union hufftblp hudc; | |
1140 | + union hufftblp huac; | |
1141 | + int next; /* when to switch to next scan */ | |
1142 | + | |
1143 | + int cid; /* component id */ | |
1144 | + int hv; /* horiz/vert, copied from comp */ | |
1145 | + int tq; /* quant tbl, copied from comp */ | |
1146 | +}; | |
1147 | + | |
1148 | +/*********************************/ | |
1149 | + | |
1150 | +#define DECBITS 10 /* seems to be the optimum */ | |
1151 | + | |
1152 | +struct dec_hufftbl { | |
1153 | + int maxcode[17]; | |
1154 | + int valptr[16]; | |
1155 | + unsigned char vals[256]; | |
1156 | + unsigned int llvals[1 << DECBITS]; | |
1157 | +}; | |
1158 | + | |
1159 | +static void decode_mcus __P((struct in *, int *, int, struct scan *, int *)); | |
1160 | +static int dec_readmarker __P((struct in *)); | |
1161 | +static void dec_makehuff __P((struct dec_hufftbl *, int *, unsigned char *)); | |
1162 | + | |
1163 | +static void setinput __P((struct in *, unsigned char *)); | |
1164 | +/*********************************/ | |
1165 | + | |
1166 | +#undef PREC | |
1167 | +#define PREC int | |
1168 | + | |
1169 | +static void idctqtab __P((unsigned char *, PREC *)); | |
1170 | +static void idct __P((int *, int *, PREC *, PREC, int)); | |
1171 | +static void scaleidctqtab __P((PREC *, PREC)); | |
1172 | + | |
1173 | +/*********************************/ | |
1174 | + | |
1175 | +static void initcol __P((PREC[][64])); | |
1176 | + | |
1177 | +static void col221111 __P((int *, unsigned char *, int)); | |
1178 | +static void col221111_16 __P((int *, unsigned char *, int)); | |
1179 | + | |
1180 | +/*********************************/ | |
1181 | + | |
1182 | +#define M_SOI 0xd8 | |
1183 | +#define M_APP0 0xe0 | |
1184 | +#define M_DQT 0xdb | |
1185 | +#define M_SOF0 0xc0 | |
1186 | +#define M_DHT 0xc4 | |
1187 | +#define M_DRI 0xdd | |
1188 | +#define M_SOS 0xda | |
1189 | +#define M_RST0 0xd0 | |
1190 | +#define M_EOI 0xd9 | |
1191 | +#define M_COM 0xfe | |
1192 | + | |
1193 | +static unsigned char *datap; | |
1194 | + | |
1195 | +static int getbyte(void) | |
1196 | +{ | |
1197 | + return *datap++; | |
1198 | +} | |
1199 | + | |
1200 | +static int getword(void) | |
1201 | +{ | |
1202 | + int c1, c2; | |
1203 | + c1 = *datap++; | |
1204 | + c2 = *datap++; | |
1205 | + return c1 << 8 | c2; | |
1206 | +} | |
1207 | + | |
1208 | +struct comp { | |
1209 | + int cid; | |
1210 | + int hv; | |
1211 | + int tq; | |
1212 | +}; | |
1213 | + | |
1214 | +#define MAXCOMP 4 | |
1215 | +struct jpginfo { | |
1216 | + int nc; /* number of components */ | |
1217 | + int ns; /* number of scans */ | |
1218 | + int dri; /* restart interval */ | |
1219 | + int nm; /* mcus til next marker */ | |
1220 | + int rm; /* next restart marker */ | |
1221 | +}; | |
1222 | + | |
1223 | +static struct jpginfo info; | |
1224 | +static struct comp comps[MAXCOMP]; | |
1225 | + | |
1226 | +static struct scan dscans[MAXCOMP]; | |
1227 | + | |
1228 | +static unsigned char quant[4][64]; | |
1229 | + | |
1230 | +static struct dec_hufftbl dhuff[4]; | |
1231 | + | |
1232 | +#define dec_huffdc (dhuff + 0) | |
1233 | +#define dec_huffac (dhuff + 2) | |
1234 | + | |
1235 | +static struct in in; | |
1236 | + | |
1237 | +static int readtables(int till) | |
1238 | +{ | |
1239 | + int m, l, i, j, lq, pq, tq; | |
1240 | + int tc, th, tt; | |
1241 | + | |
1242 | + for (;;) { | |
1243 | + if (getbyte() != 0xff) | |
1244 | + return -1; | |
1245 | + if ((m = getbyte()) == till) | |
1246 | + break; | |
1247 | + | |
1248 | + switch (m) { | |
1249 | + case 0xc2: | |
1250 | + return 0; | |
1251 | + | |
1252 | + case M_DQT: | |
1253 | + lq = getword(); | |
1254 | + while (lq > 2) { | |
1255 | + pq = getbyte(); | |
1256 | + tq = pq & 15; | |
1257 | + if (tq > 3) | |
1258 | + return -1; | |
1259 | + pq >>= 4; | |
1260 | + if (pq != 0) | |
1261 | + return -1; | |
1262 | + for (i = 0; i < 64; i++) | |
1263 | + quant[tq][i] = getbyte(); | |
1264 | + lq -= 64 + 1; | |
1265 | + } | |
1266 | + break; | |
1267 | + | |
1268 | + case M_DHT: | |
1269 | + l = getword(); | |
1270 | + while (l > 2) { | |
1271 | + int hufflen[16], k; | |
1272 | + unsigned char huffvals[256]; | |
1273 | + | |
1274 | + tc = getbyte(); | |
1275 | + th = tc & 15; | |
1276 | + tc >>= 4; | |
1277 | + tt = tc * 2 + th; | |
1278 | + if (tc > 1 || th > 1) | |
1279 | + return -1; | |
1280 | + for (i = 0; i < 16; i++) | |
1281 | + hufflen[i] = getbyte(); | |
1282 | + l -= 1 + 16; | |
1283 | + k = 0; | |
1284 | + for (i = 0; i < 16; i++) { | |
1285 | + for (j = 0; j < hufflen[i]; j++) | |
1286 | + huffvals[k++] = getbyte(); | |
1287 | + l -= hufflen[i]; | |
1288 | + } | |
1289 | + dec_makehuff(dhuff + tt, hufflen, | |
1290 | + huffvals); | |
1291 | + } | |
1292 | + break; | |
1293 | + | |
1294 | + case M_DRI: | |
1295 | + l = getword(); | |
1296 | + info.dri = getword(); | |
1297 | + break; | |
1298 | + | |
1299 | + default: | |
1300 | + l = getword(); | |
1301 | + while (l-- > 2) | |
1302 | + getbyte(); | |
1303 | + break; | |
1304 | + } | |
1305 | + } | |
1306 | + return 0; | |
1307 | +} | |
1308 | + | |
1309 | +static void dec_initscans(void) | |
1310 | +{ | |
1311 | + int i; | |
1312 | + | |
1313 | + info.nm = info.dri + 1; | |
1314 | + info.rm = M_RST0; | |
1315 | + for (i = 0; i < info.ns; i++) | |
1316 | + dscans[i].dc = 0; | |
1317 | +} | |
1318 | + | |
1319 | +static int dec_checkmarker(void) | |
1320 | +{ | |
1321 | + int i; | |
1322 | + | |
1323 | + if (dec_readmarker(&in) != info.rm) | |
1324 | + return -1; | |
1325 | + info.nm = info.dri; | |
1326 | + info.rm = (info.rm + 1) & ~0x08; | |
1327 | + for (i = 0; i < info.ns; i++) | |
1328 | + dscans[i].dc = 0; | |
1329 | + return 0; | |
1330 | +} | |
1331 | + | |
1332 | +int jpeg_check_size(unsigned char *buf, int width, int height) | |
1333 | +{ | |
1334 | + datap = buf; | |
1335 | + getbyte(); | |
1336 | + getbyte(); | |
1337 | + readtables(M_SOF0); | |
1338 | + getword(); | |
1339 | + getbyte(); | |
1340 | + if (height != getword() || width != getword()) | |
1341 | + return 0; | |
1342 | + return 1; | |
1343 | +} | |
1344 | + | |
1345 | +int jpeg_decode(buf, pic, width, height, depth, decdata) | |
1346 | +unsigned char *buf, *pic; | |
1347 | +int width, height, depth; | |
1348 | +struct jpeg_decdata *decdata; | |
1349 | +{ | |
1350 | + int i, j, m, tac, tdc; | |
1351 | + int mcusx, mcusy, mx, my; | |
1352 | + int max[6]; | |
1353 | + | |
1354 | + if (!decdata) | |
1355 | + return -1; | |
1356 | + datap = buf; | |
1357 | + if (getbyte() != 0xff) | |
1358 | + return ERR_NO_SOI; | |
1359 | + if (getbyte() != M_SOI) | |
1360 | + return ERR_NO_SOI; | |
1361 | + if (readtables(M_SOF0)) | |
1362 | + return ERR_BAD_TABLES; | |
1363 | + getword(); | |
1364 | + i = getbyte(); | |
1365 | + if (i != 8) | |
1366 | + return ERR_NOT_8BIT; | |
1367 | + if (((getword() + 15) & ~15) != height) | |
1368 | + return ERR_HEIGHT_MISMATCH; | |
1369 | + if (((getword() + 15) & ~15) != width) | |
1370 | + return ERR_WIDTH_MISMATCH; | |
1371 | + if ((height & 15) || (width & 15)) | |
1372 | + return ERR_BAD_WIDTH_OR_HEIGHT; | |
1373 | + info.nc = getbyte(); | |
1374 | + if (info.nc > MAXCOMP) | |
1375 | + return ERR_TOO_MANY_COMPPS; | |
1376 | + for (i = 0; i < info.nc; i++) { | |
1377 | + int h, v; | |
1378 | + comps[i].cid = getbyte(); | |
1379 | + comps[i].hv = getbyte(); | |
1380 | + v = comps[i].hv & 15; | |
1381 | + h = comps[i].hv >> 4; | |
1382 | + comps[i].tq = getbyte(); | |
1383 | + if (h > 3 || v > 3) | |
1384 | + return ERR_ILLEGAL_HV; | |
1385 | + if (comps[i].tq > 3) | |
1386 | + return ERR_QUANT_TABLE_SELECTOR; | |
1387 | + } | |
1388 | + if (readtables(M_SOS)) | |
1389 | + return ERR_BAD_TABLES; | |
1390 | + getword(); | |
1391 | + info.ns = getbyte(); | |
1392 | + if (info.ns != 3) | |
1393 | + return ERR_NOT_YCBCR_221111; | |
1394 | + for (i = 0; i < 3; i++) { | |
1395 | + dscans[i].cid = getbyte(); | |
1396 | + tdc = getbyte(); | |
1397 | + tac = tdc & 15; | |
1398 | + tdc >>= 4; | |
1399 | + if (tdc > 1 || tac > 1) | |
1400 | + return ERR_QUANT_TABLE_SELECTOR; | |
1401 | + for (j = 0; j < info.nc; j++) | |
1402 | + if (comps[j].cid == dscans[i].cid) | |
1403 | + break; | |
1404 | + if (j == info.nc) | |
1405 | + return ERR_UNKNOWN_CID_IN_SCAN; | |
1406 | + dscans[i].hv = comps[j].hv; | |
1407 | + dscans[i].tq = comps[j].tq; | |
1408 | + dscans[i].hudc.dhuff = dec_huffdc + tdc; | |
1409 | + dscans[i].huac.dhuff = dec_huffac + tac; | |
1410 | + } | |
1411 | + | |
1412 | + i = getbyte(); | |
1413 | + j = getbyte(); | |
1414 | + m = getbyte(); | |
1415 | + | |
1416 | + if (i != 0 || j != 63 || m != 0) | |
1417 | + return ERR_NOT_SEQUENTIAL_DCT; | |
1418 | + | |
1419 | + if (dscans[0].cid != 1 || dscans[1].cid != 2 || dscans[2].cid != 3) | |
1420 | + return ERR_NOT_YCBCR_221111; | |
1421 | + | |
1422 | + if (dscans[0].hv != 0x22 || dscans[1].hv != 0x11 || dscans[2].hv != 0x11) | |
1423 | + return ERR_NOT_YCBCR_221111; | |
1424 | + | |
1425 | + mcusx = width >> 4; | |
1426 | + mcusy = height >> 4; | |
1427 | + | |
1428 | + | |
1429 | + idctqtab(quant[dscans[0].tq], decdata->dquant[0]); | |
1430 | + idctqtab(quant[dscans[1].tq], decdata->dquant[1]); | |
1431 | + idctqtab(quant[dscans[2].tq], decdata->dquant[2]); | |
1432 | + initcol(decdata->dquant); | |
1433 | + setinput(&in, datap); | |
1434 | + | |
1435 | +#if 0 | |
1436 | + /* landing zone */ | |
1437 | + img[len] = 0; | |
1438 | + img[len + 1] = 0xff; | |
1439 | + img[len + 2] = M_EOF; | |
1440 | +#endif | |
1441 | + | |
1442 | + dec_initscans(); | |
1443 | + | |
1444 | + dscans[0].next = 6 - 4; | |
1445 | + dscans[1].next = 6 - 4 - 1; | |
1446 | + dscans[2].next = 6 - 4 - 1 - 1; /* 411 encoding */ | |
1447 | + for (my = 0; my < mcusy; my++) { | |
1448 | + for (mx = 0; mx < mcusx; mx++) { | |
1449 | + if (info.dri && !--info.nm) | |
1450 | + if (dec_checkmarker()) | |
1451 | + return ERR_WRONG_MARKER; | |
1452 | + | |
1453 | + decode_mcus(&in, decdata->dcts, 6, dscans, max); | |
1454 | + idct(decdata->dcts, decdata->out, decdata->dquant[0], IFIX(128.5), max[0]); | |
1455 | + idct(decdata->dcts + 64, decdata->out + 64, decdata->dquant[0], IFIX(128.5), max[1]); | |
1456 | + idct(decdata->dcts + 128, decdata->out + 128, decdata->dquant[0], IFIX(128.5), max[2]); | |
1457 | + idct(decdata->dcts + 192, decdata->out + 192, decdata->dquant[0], IFIX(128.5), max[3]); | |
1458 | + idct(decdata->dcts + 256, decdata->out + 256, decdata->dquant[1], IFIX(0.5), max[4]); | |
1459 | + idct(decdata->dcts + 320, decdata->out + 320, decdata->dquant[2], IFIX(0.5), max[5]); | |
1460 | + | |
1461 | + switch (depth) { | |
1462 | + case 24: | |
1463 | + col221111(decdata->out, pic + (my * 16 * mcusx + mx) * 16 * 3, mcusx * 16 * 3); | |
1464 | + break; | |
1465 | + case 16: | |
1466 | + col221111_16(decdata->out, pic + (my * 16 * mcusx + mx) * (16 * 2), mcusx * (16 * 2)); | |
1467 | + break; | |
1468 | + default: | |
1469 | + return ERR_DEPTH_MISMATCH; | |
1470 | + break; | |
1471 | + } | |
1472 | + } | |
1473 | + } | |
1474 | + | |
1475 | + m = dec_readmarker(&in); | |
1476 | + if (m != M_EOI) | |
1477 | + return ERR_NO_EOI; | |
1478 | + | |
1479 | + return 0; | |
1480 | +} | |
1481 | + | |
1482 | +/****************************************************************/ | |
1483 | +/************** huffman decoder ***************/ | |
1484 | +/****************************************************************/ | |
1485 | + | |
1486 | +static int fillbits __P((struct in *, int, unsigned int)); | |
1487 | +static int dec_rec2 | |
1488 | +__P((struct in *, struct dec_hufftbl *, int *, int, int)); | |
1489 | + | |
1490 | +static void setinput(in, p) | |
1491 | +struct in *in; | |
1492 | +unsigned char *p; | |
1493 | +{ | |
1494 | + in->p = p; | |
1495 | + in->left = 0; | |
1496 | + in->bits = 0; | |
1497 | + in->marker = 0; | |
1498 | +} | |
1499 | + | |
1500 | +static int fillbits(in, le, bi) | |
1501 | +struct in *in; | |
1502 | +int le; | |
1503 | +unsigned int bi; | |
1504 | +{ | |
1505 | + int b, m; | |
1506 | + | |
1507 | + if (in->marker) { | |
1508 | + if (le <= 16) | |
1509 | + in->bits = bi << 16, le += 16; | |
1510 | + return le; | |
1511 | + } | |
1512 | + while (le <= 24) { | |
1513 | + b = *in->p++; | |
1514 | + if (b == 0xff && (m = *in->p++) != 0) { | |
1515 | + if (m == M_EOF) { | |
1516 | + if (in->func && (m = in->func(in->data)) == 0) | |
1517 | + continue; | |
1518 | + } | |
1519 | + in->marker = m; | |
1520 | + if (le <= 16) | |
1521 | + bi = bi << 16, le += 16; | |
1522 | + break; | |
1523 | + } | |
1524 | + bi = bi << 8 | b; | |
1525 | + le += 8; | |
1526 | + } | |
1527 | + in->bits = bi; /* tmp... 2 return values needed */ | |
1528 | + return le; | |
1529 | +} | |
1530 | + | |
1531 | +static int dec_readmarker(in) | |
1532 | +struct in *in; | |
1533 | +{ | |
1534 | + int m; | |
1535 | + | |
1536 | + in->left = fillbits(in, in->left, in->bits); | |
1537 | + if ((m = in->marker) == 0) | |
1538 | + return 0; | |
1539 | + in->left = 0; | |
1540 | + in->marker = 0; | |
1541 | + return m; | |
1542 | +} | |
1543 | + | |
1544 | +#define LEBI_DCL int le, bi | |
1545 | +#define LEBI_GET(in) (le = in->left, bi = in->bits) | |
1546 | +#define LEBI_PUT(in) (in->left = le, in->bits = bi) | |
1547 | + | |
1548 | +#define GETBITS(in, n) ( \ | |
1549 | + (le < (n) ? le = fillbits(in, le, bi), bi = in->bits : 0), \ | |
1550 | + (le -= (n)), \ | |
1551 | + bi >> le & ((1 << (n)) - 1) \ | |
1552 | +) | |
1553 | + | |
1554 | +#define UNGETBITS(in, n) ( \ | |
1555 | + le += (n) \ | |
1556 | +) | |
1557 | + | |
1558 | + | |
1559 | +static int dec_rec2(in, hu, runp, c, i) | |
1560 | +struct in *in; | |
1561 | +struct dec_hufftbl *hu; | |
1562 | +int *runp; | |
1563 | +int c, i; | |
1564 | +{ | |
1565 | + LEBI_DCL; | |
1566 | + | |
1567 | + LEBI_GET(in); | |
1568 | + if (i) { | |
1569 | + UNGETBITS(in, i & 127); | |
1570 | + *runp = i >> 8 & 15; | |
1571 | + i >>= 16; | |
1572 | + } else { | |
1573 | + for (i = DECBITS; (c = ((c << 1) | GETBITS(in, 1))) >= (hu->maxcode[i]); i++); | |
1574 | + if (i >= 16) { | |
1575 | + in->marker = M_BADHUFF; | |
1576 | + return 0; | |
1577 | + } | |
1578 | + i = hu->vals[hu->valptr[i] + c - hu->maxcode[i - 1] * 2]; | |
1579 | + *runp = i >> 4; | |
1580 | + i &= 15; | |
1581 | + } | |
1582 | + if (i == 0) { /* sigh, 0xf0 is 11 bit */ | |
1583 | + LEBI_PUT(in); | |
1584 | + return 0; | |
1585 | + } | |
1586 | + /* receive part */ | |
1587 | + c = GETBITS(in, i); | |
1588 | + if (c < (1 << (i - 1))) | |
1589 | + c += (-1 << i) + 1; | |
1590 | + LEBI_PUT(in); | |
1591 | + return c; | |
1592 | +} | |
1593 | + | |
1594 | +#define DEC_REC(in, hu, r, i) ( \ | |
1595 | + r = GETBITS(in, DECBITS), \ | |
1596 | + i = hu->llvals[r], \ | |
1597 | + i & 128 ? \ | |
1598 | + ( \ | |
1599 | + UNGETBITS(in, i & 127), \ | |
1600 | + r = i >> 8 & 15, \ | |
1601 | + i >> 16 \ | |
1602 | + ) \ | |
1603 | + : \ | |
1604 | + ( \ | |
1605 | + LEBI_PUT(in), \ | |
1606 | + i = dec_rec2(in, hu, &r, r, i), \ | |
1607 | + LEBI_GET(in), \ | |
1608 | + i \ | |
1609 | + ) \ | |
1610 | +) | |
1611 | + | |
1612 | +static void decode_mcus(in, dct, n, sc, maxp) | |
1613 | +struct in *in; | |
1614 | +int *dct; | |
1615 | +int n; | |
1616 | +struct scan *sc; | |
1617 | +int *maxp; | |
1618 | +{ | |
1619 | + struct dec_hufftbl *hu; | |
1620 | + int i, r, t; | |
1621 | + LEBI_DCL; | |
1622 | + | |
1623 | + memset(dct, 0, n * 64 * sizeof(*dct)); | |
1624 | + LEBI_GET(in); | |
1625 | + while (n-- > 0) { | |
1626 | + hu = sc->hudc.dhuff; | |
1627 | + *dct++ = (sc->dc += DEC_REC(in, hu, r, t)); | |
1628 | + | |
1629 | + hu = sc->huac.dhuff; | |
1630 | + i = 63; | |
1631 | + while (i > 0) { | |
1632 | + t = DEC_REC(in, hu, r, t); | |
1633 | + if (t == 0 && r == 0) { | |
1634 | + dct += i; | |
1635 | + break; | |
1636 | + } | |
1637 | + dct += r; | |
1638 | + *dct++ = t; | |
1639 | + i -= r + 1; | |
1640 | + } | |
1641 | + *maxp++ = 64 - i; | |
1642 | + if (n == sc->next) | |
1643 | + sc++; | |
1644 | + } | |
1645 | + LEBI_PUT(in); | |
1646 | +} | |
1647 | + | |
1648 | +static void dec_makehuff(hu, hufflen, huffvals) | |
1649 | +struct dec_hufftbl *hu; | |
1650 | +int *hufflen; | |
1651 | +unsigned char *huffvals; | |
1652 | +{ | |
1653 | + int code, k, i, j, d, x, c, v; | |
1654 | + for (i = 0; i < (1 << DECBITS); i++) | |
1655 | + hu->llvals[i] = 0; | |
1656 | + | |
1657 | +/* | |
1658 | + * llvals layout: | |
1659 | + * | |
1660 | + * value v already known, run r, backup u bits: | |
1661 | + * vvvvvvvvvvvvvvvv 0000 rrrr 1 uuuuuuu | |
1662 | + * value unknown, size b bits, run r, backup u bits: | |
1663 | + * 000000000000bbbb 0000 rrrr 0 uuuuuuu | |
1664 | + * value and size unknown: | |
1665 | + * 0000000000000000 0000 0000 0 0000000 | |
1666 | + */ | |
1667 | + code = 0; | |
1668 | + k = 0; | |
1669 | + for (i = 0; i < 16; i++, code <<= 1) { /* sizes */ | |
1670 | + hu->valptr[i] = k; | |
1671 | + for (j = 0; j < hufflen[i]; j++) { | |
1672 | + hu->vals[k] = *huffvals++; | |
1673 | + if (i < DECBITS) { | |
1674 | + c = code << (DECBITS - 1 - i); | |
1675 | + v = hu->vals[k] & 0x0f; /* size */ | |
1676 | + for (d = 1 << (DECBITS - 1 - i); --d >= 0;) { | |
1677 | + if (v + i < DECBITS) { /* both fit in table */ | |
1678 | + x = d >> (DECBITS - 1 - v - | |
1679 | + i); | |
1680 | + if (v && x < (1 << (v - 1))) | |
1681 | + x += (-1 << v) + 1; | |
1682 | + x = x << 16 | (hu-> vals[k] & 0xf0) << 4 | | |
1683 | + (DECBITS - (i + 1 + v)) | 128; | |
1684 | + } else | |
1685 | + x = v << 16 | (hu-> vals[k] & 0xf0) << 4 | | |
1686 | + (DECBITS - (i + 1)); | |
1687 | + hu->llvals[c | d] = x; | |
1688 | + } | |
1689 | + } | |
1690 | + code++; | |
1691 | + k++; | |
1692 | + } | |
1693 | + hu->maxcode[i] = code; | |
1694 | + } | |
1695 | + hu->maxcode[16] = 0x20000; /* always terminate decode */ | |
1696 | +} | |
1697 | + | |
1698 | +/****************************************************************/ | |
1699 | +/************** idct ***************/ | |
1700 | +/****************************************************************/ | |
1701 | + | |
1702 | +#define ONE ((PREC)IFIX(1.)) | |
1703 | +#define S2 ((PREC)IFIX(0.382683432)) | |
1704 | +#define C2 ((PREC)IFIX(0.923879532)) | |
1705 | +#define C4 ((PREC)IFIX(0.707106781)) | |
1706 | + | |
1707 | +#define S22 ((PREC)IFIX(2 * 0.382683432)) | |
1708 | +#define C22 ((PREC)IFIX(2 * 0.923879532)) | |
1709 | +#define IC4 ((PREC)IFIX(1 / 0.707106781)) | |
1710 | + | |
1711 | +#define C3IC1 ((PREC)IFIX(0.847759065)) /* c3/c1 */ | |
1712 | +#define C5IC1 ((PREC)IFIX(0.566454497)) /* c5/c1 */ | |
1713 | +#define C7IC1 ((PREC)IFIX(0.198912367)) /* c7/c1 */ | |
1714 | + | |
1715 | +#define XPP(a,b) (t = a + b, b = a - b, a = t) | |
1716 | +#define XMP(a,b) (t = a - b, b = a + b, a = t) | |
1717 | +#define XPM(a,b) (t = a + b, b = b - a, a = t) | |
1718 | + | |
1719 | +#define ROT(a,b,s,c) ( t = IMULT(a + b, s), \ | |
1720 | + a = IMULT(a, c - s) + t, \ | |
1721 | + b = IMULT(b, c + s) - t) | |
1722 | + | |
1723 | +#define IDCT \ | |
1724 | +( \ | |
1725 | + XPP(t0, t1), \ | |
1726 | + XMP(t2, t3), \ | |
1727 | + t2 = IMULT(t2, IC4) - t3, \ | |
1728 | + XPP(t0, t3), \ | |
1729 | + XPP(t1, t2), \ | |
1730 | + XMP(t4, t7), \ | |
1731 | + XPP(t5, t6), \ | |
1732 | + XMP(t5, t7), \ | |
1733 | + t5 = IMULT(t5, IC4), \ | |
1734 | + ROT(t4, t6, S22, C22),\ | |
1735 | + t6 -= t7, \ | |
1736 | + t5 -= t6, \ | |
1737 | + t4 -= t5, \ | |
1738 | + XPP(t0, t7), \ | |
1739 | + XPP(t1, t6), \ | |
1740 | + XPP(t2, t5), \ | |
1741 | + XPP(t3, t4) \ | |
1742 | +) | |
1743 | + | |
1744 | +static unsigned char zig2[64] = { | |
1745 | + 0, 2, 3, 9, 10, 20, 21, 35, | |
1746 | + 14, 16, 25, 31, 39, 46, 50, 57, | |
1747 | + 5, 7, 12, 18, 23, 33, 37, 48, | |
1748 | + 27, 29, 41, 44, 52, 55, 59, 62, | |
1749 | + 15, 26, 30, 40, 45, 51, 56, 58, | |
1750 | + 1, 4, 8, 11, 19, 22, 34, 36, | |
1751 | + 28, 42, 43, 53, 54, 60, 61, 63, | |
1752 | + 6, 13, 17, 24, 32, 38, 47, 49 | |
1753 | +}; | |
1754 | + | |
1755 | +void idct(in, out, quant, off, max) | |
1756 | +int *in; | |
1757 | +int *out; | |
1758 | +PREC *quant; | |
1759 | +PREC off; | |
1760 | +int max; | |
1761 | +{ | |
1762 | + PREC t0, t1, t2, t3, t4, t5, t6, t7, t; | |
1763 | + PREC tmp[64], *tmpp; | |
1764 | + int i, j; | |
1765 | + unsigned char *zig2p; | |
1766 | + | |
1767 | + t0 = off; | |
1768 | + if (max == 1) { | |
1769 | + t0 += in[0] * quant[0]; | |
1770 | + for (i = 0; i < 64; i++) | |
1771 | + out[i] = ITOINT(t0); | |
1772 | + return; | |
1773 | + } | |
1774 | + zig2p = zig2; | |
1775 | + tmpp = tmp; | |
1776 | + for (i = 0; i < 8; i++) { | |
1777 | + j = *zig2p++; | |
1778 | + t0 += in[j] * quant[j]; | |
1779 | + j = *zig2p++; | |
1780 | + t5 = in[j] * quant[j]; | |
1781 | + j = *zig2p++; | |
1782 | + t2 = in[j] * quant[j]; | |
1783 | + j = *zig2p++; | |
1784 | + t7 = in[j] * quant[j]; | |
1785 | + j = *zig2p++; | |
1786 | + t1 = in[j] * quant[j]; | |
1787 | + j = *zig2p++; | |
1788 | + t4 = in[j] * quant[j]; | |
1789 | + j = *zig2p++; | |
1790 | + t3 = in[j] * quant[j]; | |
1791 | + j = *zig2p++; | |
1792 | + t6 = in[j] * quant[j]; | |
1793 | + IDCT; | |
1794 | + tmpp[0 * 8] = t0; | |
1795 | + tmpp[1 * 8] = t1; | |
1796 | + tmpp[2 * 8] = t2; | |
1797 | + tmpp[3 * 8] = t3; | |
1798 | + tmpp[4 * 8] = t4; | |
1799 | + tmpp[5 * 8] = t5; | |
1800 | + tmpp[6 * 8] = t6; | |
1801 | + tmpp[7 * 8] = t7; | |
1802 | + tmpp++; | |
1803 | + t0 = 0; | |
1804 | + } | |
1805 | + for (i = 0; i < 8; i++) { | |
1806 | + t0 = tmp[8 * i + 0]; | |
1807 | + t1 = tmp[8 * i + 1]; | |
1808 | + t2 = tmp[8 * i + 2]; | |
1809 | + t3 = tmp[8 * i + 3]; | |
1810 | + t4 = tmp[8 * i + 4]; | |
1811 | + t5 = tmp[8 * i + 5]; | |
1812 | + t6 = tmp[8 * i + 6]; | |
1813 | + t7 = tmp[8 * i + 7]; | |
1814 | + IDCT; | |
1815 | + out[8 * i + 0] = ITOINT(t0); | |
1816 | + out[8 * i + 1] = ITOINT(t1); | |
1817 | + out[8 * i + 2] = ITOINT(t2); | |
1818 | + out[8 * i + 3] = ITOINT(t3); | |
1819 | + out[8 * i + 4] = ITOINT(t4); | |
1820 | + out[8 * i + 5] = ITOINT(t5); | |
1821 | + out[8 * i + 6] = ITOINT(t6); | |
1822 | + out[8 * i + 7] = ITOINT(t7); | |
1823 | + } | |
1824 | +} | |
1825 | + | |
1826 | +static unsigned char zig[64] = { | |
1827 | + 0, 1, 5, 6, 14, 15, 27, 28, | |
1828 | + 2, 4, 7, 13, 16, 26, 29, 42, | |
1829 | + 3, 8, 12, 17, 25, 30, 41, 43, | |
1830 | + 9, 11, 18, 24, 31, 40, 44, 53, | |
1831 | + 10, 19, 23, 32, 39, 45, 52, 54, | |
1832 | + 20, 22, 33, 38, 46, 51, 55, 60, | |
1833 | + 21, 34, 37, 47, 50, 56, 59, 61, | |
1834 | + 35, 36, 48, 49, 57, 58, 62, 63 | |
1835 | +}; | |
1836 | + | |
1837 | +static PREC aaidct[8] = { | |
1838 | + IFIX(0.3535533906), IFIX(0.4903926402), | |
1839 | + IFIX(0.4619397663), IFIX(0.4157348062), | |
1840 | + IFIX(0.3535533906), IFIX(0.2777851165), | |
1841 | + IFIX(0.1913417162), IFIX(0.0975451610) | |
1842 | +}; | |
1843 | + | |
1844 | + | |
1845 | +static void idctqtab(qin, qout) | |
1846 | +unsigned char *qin; | |
1847 | +PREC *qout; | |
1848 | +{ | |
1849 | + int i, j; | |
1850 | + | |
1851 | + for (i = 0; i < 8; i++) | |
1852 | + for (j = 0; j < 8; j++) | |
1853 | + qout[zig[i * 8 + j]] = qin[zig[i * 8 + j]] * | |
1854 | + IMULT(aaidct[i], aaidct[j]); | |
1855 | +} | |
1856 | + | |
1857 | +static void scaleidctqtab(q, sc) | |
1858 | +PREC *q; | |
1859 | +PREC sc; | |
1860 | +{ | |
1861 | + int i; | |
1862 | + | |
1863 | + for (i = 0; i < 64; i++) | |
1864 | + q[i] = IMULT(q[i], sc); | |
1865 | +} | |
1866 | + | |
1867 | +/****************************************************************/ | |
1868 | +/************** color decoder ***************/ | |
1869 | +/****************************************************************/ | |
1870 | + | |
1871 | +#define ROUND | |
1872 | + | |
1873 | +/* | |
1874 | + * YCbCr Color transformation: | |
1875 | + * | |
1876 | + * y:0..255 Cb:-128..127 Cr:-128..127 | |
1877 | + * | |
1878 | + * R = Y + 1.40200 * Cr | |
1879 | + * G = Y - 0.34414 * Cb - 0.71414 * Cr | |
1880 | + * B = Y + 1.77200 * Cb | |
1881 | + * | |
1882 | + * => | |
1883 | + * Cr *= 1.40200; | |
1884 | + * Cb *= 1.77200; | |
1885 | + * Cg = 0.19421 * Cb + .50937 * Cr; | |
1886 | + * R = Y + Cr; | |
1887 | + * G = Y - Cg; | |
1888 | + * B = Y + Cb; | |
1889 | + * | |
1890 | + * => | |
1891 | + * Cg = (50 * Cb + 130 * Cr + 128) >> 8; | |
1892 | + */ | |
1893 | + | |
1894 | +static void initcol(q) | |
1895 | +PREC q[][64]; | |
1896 | +{ | |
1897 | + scaleidctqtab(q[1], IFIX(1.77200)); | |
1898 | + scaleidctqtab(q[2], IFIX(1.40200)); | |
1899 | +} | |
1900 | + | |
1901 | +/* This is optimized for the stupid sun SUNWspro compiler. */ | |
1902 | +#define STORECLAMP(a,x) \ | |
1903 | +( \ | |
1904 | + (a) = (x), \ | |
1905 | + (unsigned int)(x) >= 256 ? \ | |
1906 | + ((a) = (x) < 0 ? 0 : 255) \ | |
1907 | + : \ | |
1908 | + 0 \ | |
1909 | +) | |
1910 | + | |
1911 | +#define CLAMP(x) ((unsigned int)(x) >= 256 ? ((x) < 0 ? 0 : 255) : (x)) | |
1912 | + | |
1913 | +#ifdef ROUND | |
1914 | + | |
1915 | +#define CBCRCG(yin, xin) \ | |
1916 | +( \ | |
1917 | + cb = outc[0 +yin*8+xin], \ | |
1918 | + cr = outc[64+yin*8+xin], \ | |
1919 | + cg = (50 * cb + 130 * cr + 128) >> 8 \ | |
1920 | +) | |
1921 | + | |
1922 | +#else | |
1923 | + | |
1924 | +#define CBCRCG(yin, xin) \ | |
1925 | +( \ | |
1926 | + cb = outc[0 +yin*8+xin], \ | |
1927 | + cr = outc[64+yin*8+xin], \ | |
1928 | + cg = (3 * cb + 8 * cr) >> 4 \ | |
1929 | +) | |
1930 | + | |
1931 | +#endif | |
1932 | + | |
1933 | +#define PIC(yin, xin, p, xout) \ | |
1934 | +( \ | |
1935 | + y = outy[(yin) * 8 + xin], \ | |
1936 | + STORECLAMP(p[(xout) * 3 + 0], y + cr), \ | |
1937 | + STORECLAMP(p[(xout) * 3 + 1], y - cg), \ | |
1938 | + STORECLAMP(p[(xout) * 3 + 2], y + cb) \ | |
1939 | +) | |
1940 | + | |
1941 | +#ifdef __LITTLE_ENDIAN | |
1942 | +#define PIC_16(yin, xin, p, xout, add) \ | |
1943 | +( \ | |
1944 | + y = outy[(yin) * 8 + xin], \ | |
1945 | + y = ((CLAMP(y + cr + add*2+1) & 0xf8) << 8) | \ | |
1946 | + ((CLAMP(y - cg + add ) & 0xfc) << 3) | \ | |
1947 | + ((CLAMP(y + cb + add*2+1) ) >> 3), \ | |
1948 | + p[(xout) * 2 + 0] = y & 0xff, \ | |
1949 | + p[(xout) * 2 + 1] = y >> 8 \ | |
1950 | +) | |
1951 | +#else | |
1952 | +#ifdef CONFIG_PPC | |
1953 | +#define PIC_16(yin, xin, p, xout, add) \ | |
1954 | +( \ | |
1955 | + y = outy[(yin) * 8 + xin], \ | |
1956 | + y = ((CLAMP(y + cr + add*2+1) & 0xf8) << 7) | \ | |
1957 | + ((CLAMP(y - cg + add*2+1) & 0xf8) << 2) | \ | |
1958 | + ((CLAMP(y + cb + add*2+1) ) >> 3), \ | |
1959 | + p[(xout) * 2 + 0] = y >> 8, \ | |
1960 | + p[(xout) * 2 + 1] = y & 0xff \ | |
1961 | +) | |
1962 | +#else | |
1963 | +#define PIC_16(yin, xin, p, xout, add) \ | |
1964 | +( \ | |
1965 | + y = outy[(yin) * 8 + xin], \ | |
1966 | + y = ((CLAMP(y + cr + add*2+1) & 0xf8) << 8) | \ | |
1967 | + ((CLAMP(y - cg + add ) & 0xfc) << 3) | \ | |
1968 | + ((CLAMP(y + cb + add*2+1) ) >> 3), \ | |
1969 | + p[(xout) * 2 + 0] = y >> 8, \ | |
1970 | + p[(xout) * 2 + 1] = y & 0xff \ | |
1971 | +) | |
1972 | +#endif | |
1973 | +#endif | |
1974 | + | |
1975 | +#define PIC221111(xin) \ | |
1976 | +( \ | |
1977 | + CBCRCG(0, xin), \ | |
1978 | + PIC(xin / 4 * 8 + 0, (xin & 3) * 2 + 0, pic0, xin * 2 + 0), \ | |
1979 | + PIC(xin / 4 * 8 + 0, (xin & 3) * 2 + 1, pic0, xin * 2 + 1), \ | |
1980 | + PIC(xin / 4 * 8 + 1, (xin & 3) * 2 + 0, pic1, xin * 2 + 0), \ | |
1981 | + PIC(xin / 4 * 8 + 1, (xin & 3) * 2 + 1, pic1, xin * 2 + 1) \ | |
1982 | +) | |
1983 | + | |
1984 | +#define PIC221111_16(xin) \ | |
1985 | +( \ | |
1986 | + CBCRCG(0, xin), \ | |
1987 | + PIC_16(xin / 4 * 8 + 0, (xin & 3) * 2 + 0, pic0, xin * 2 + 0, 3), \ | |
1988 | + PIC_16(xin / 4 * 8 + 0, (xin & 3) * 2 + 1, pic0, xin * 2 + 1, 0), \ | |
1989 | + PIC_16(xin / 4 * 8 + 1, (xin & 3) * 2 + 0, pic1, xin * 2 + 0, 1), \ | |
1990 | + PIC_16(xin / 4 * 8 + 1, (xin & 3) * 2 + 1, pic1, xin * 2 + 1, 2) \ | |
1991 | +) | |
1992 | + | |
1993 | +static void col221111(out, pic, width) | |
1994 | +int *out; | |
1995 | +unsigned char *pic; | |
1996 | +int width; | |
1997 | +{ | |
1998 | + int i, j, k; | |
1999 | + unsigned char *pic0, *pic1; | |
2000 | + int *outy, *outc; | |
2001 | + int cr, cg, cb, y; | |
2002 | + | |
2003 | + pic0 = pic; | |
2004 | + pic1 = pic + width; | |
2005 | + outy = out; | |
2006 | + outc = out + 64 * 4; | |
2007 | + for (i = 2; i > 0; i--) { | |
2008 | + for (j = 4; j > 0; j--) { | |
2009 | + for (k = 0; k < 8; k++) { | |
2010 | + PIC221111(k); | |
2011 | + } | |
2012 | + outc += 8; | |
2013 | + outy += 16; | |
2014 | + pic0 += 2 * width; | |
2015 | + pic1 += 2 * width; | |
2016 | + } | |
2017 | + outy += 64 * 2 - 16 * 4; | |
2018 | + } | |
2019 | +} | |
2020 | + | |
2021 | +static void col221111_16(out, pic, width) | |
2022 | +int *out; | |
2023 | +unsigned char *pic; | |
2024 | +int width; | |
2025 | +{ | |
2026 | + int i, j, k; | |
2027 | + unsigned char *pic0, *pic1; | |
2028 | + int *outy, *outc; | |
2029 | + int cr, cg, cb, y; | |
2030 | + | |
2031 | + pic0 = pic; | |
2032 | + pic1 = pic + width; | |
2033 | + outy = out; | |
2034 | + outc = out + 64 * 4; | |
2035 | + for (i = 2; i > 0; i--) { | |
2036 | + for (j = 4; j > 0; j--) { | |
2037 | + for (k = 0; k < 8; k++) { | |
2038 | + PIC221111_16(k); | |
2039 | + } | |
2040 | + outc += 8; | |
2041 | + outy += 16; | |
2042 | + pic0 += 2 * width; | |
2043 | + pic1 += 2 * width; | |
2044 | + } | |
2045 | + outy += 64 * 2 - 16 * 4; | |
2046 | + } | |
2047 | +} | |
2048 | diff -Nur --exclude '*.orig' linux-2.6.5-rc2.org/drivers/video/bootsplash/decode-jpg.h linux-2.6.5-rc2/drivers/video/bootsplash/decode-jpg.h | |
2049 | --- linux-2.6.5-rc2.org/drivers/video/bootsplash/decode-jpg.h 1970-01-01 00:00:00.000000000 +0000 | |
2050 | +++ linux-2.6.5-rc2/drivers/video/bootsplash/decode-jpg.h 2004-03-23 10:00:22.000000000 +0000 | |
2051 | @@ -0,0 +1,35 @@ | |
2052 | +/* | |
2053 | + * linux/drivers/video/bootsplash/decode-jpg.h - a tiny jpeg decoder. | |
2054 | + * | |
2055 | + * (w) August 2001 by Michael Schroeder, <mls@suse.de> | |
2056 | + */ | |
2057 | + | |
2058 | +#ifndef __DECODE_JPG_H | |
2059 | +#define __DECODE_JPG_H | |
2060 | + | |
2061 | +#define ERR_NO_SOI 1 | |
2062 | +#define ERR_NOT_8BIT 2 | |
2063 | +#define ERR_HEIGHT_MISMATCH 3 | |
2064 | +#define ERR_WIDTH_MISMATCH 4 | |
2065 | +#define ERR_BAD_WIDTH_OR_HEIGHT 5 | |
2066 | +#define ERR_TOO_MANY_COMPPS 6 | |
2067 | +#define ERR_ILLEGAL_HV 7 | |
2068 | +#define ERR_QUANT_TABLE_SELECTOR 8 | |
2069 | +#define ERR_NOT_YCBCR_221111 9 | |
2070 | +#define ERR_UNKNOWN_CID_IN_SCAN 10 | |
2071 | +#define ERR_NOT_SEQUENTIAL_DCT 11 | |
2072 | +#define ERR_WRONG_MARKER 12 | |
2073 | +#define ERR_NO_EOI 13 | |
2074 | +#define ERR_BAD_TABLES 14 | |
2075 | +#define ERR_DEPTH_MISMATCH 15 | |
2076 | + | |
2077 | +struct jpeg_decdata { | |
2078 | + int dcts[6 * 64 + 16]; | |
2079 | + int out[64 * 6]; | |
2080 | + int dquant[3][64]; | |
2081 | +}; | |
2082 | + | |
2083 | +extern int jpeg_decode(unsigned char *, unsigned char *, int, int, int, struct jpeg_decdata *); | |
2084 | +extern int jpeg_check_size(unsigned char *, int, int); | |
2085 | + | |
2086 | +#endif | |
2087 | diff -Nur --exclude '*.orig' linux-2.6.5-rc2.org/drivers/video/bootsplash/render.c linux-2.6.5-rc2/drivers/video/bootsplash/render.c | |
2088 | --- linux-2.6.5-rc2.org/drivers/video/bootsplash/render.c 1970-01-01 00:00:00.000000000 +0000 | |
2089 | +++ linux-2.6.5-rc2/drivers/video/bootsplash/render.c 2004-03-23 10:00:22.000000000 +0000 | |
2090 | @@ -0,0 +1,330 @@ | |
2091 | +/* | |
2092 | + * linux/drivers/video/bootsplash/render.c - splash screen render functions. | |
2093 | + */ | |
2094 | + | |
2095 | +#include <linux/config.h> | |
2096 | +#include <linux/module.h> | |
2097 | +#include <linux/types.h> | |
2098 | +#include <linux/fb.h> | |
2099 | +#include <linux/vt_kern.h> | |
2100 | +#include <asm/irq.h> | |
2101 | +#include <asm/system.h> | |
2102 | + | |
2103 | +#include "../console/fbcon.h" | |
2104 | +#include "bootsplash.h" | |
2105 | + | |
2106 | +void splash_putcs(struct splash_data *sd, struct vc_data *vc, struct fb_info *info, | |
2107 | + const unsigned short *s, int count, int ypos, int xpos) | |
2108 | +{ | |
2109 | + unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; | |
2110 | + int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | |
2111 | + int fgshift = (vc->vc_hi_font_mask) ? 9 : 8; | |
2112 | + u8 *src; | |
2113 | + u8 *dst, *splashsrc; | |
2114 | + unsigned int d, x, y; | |
2115 | + u32 dd, fgx, bgx; | |
2116 | + u16 c = scr_readw(s); | |
2117 | + | |
2118 | + int fg_color, bg_color, transparent; | |
2119 | + fg_color = attr_fgcol(fgshift, c); | |
2120 | + bg_color = attr_bgcol(bgshift, c); | |
2121 | + transparent = sd->splash_color == bg_color; | |
2122 | + xpos = xpos * vc->vc_font.width + sd->splash_text_xo; | |
2123 | + ypos = ypos * vc->vc_font.height + sd->splash_text_yo; | |
2124 | + splashsrc = (u8 *)(info->splash_pic + ypos * info->splash_bytes + xpos * 2); | |
2125 | + dst = (u8 *)(info->screen_base + ypos * info->fix.line_length + xpos * 2); | |
2126 | + | |
2127 | + fgx = ((u32 *)info->pseudo_palette)[fg_color]; | |
2128 | + if (transparent && sd->splash_color == 15) { | |
2129 | + if (fgx == 0xffea) | |
2130 | + fgx = 0xfe4a; | |
2131 | + else if (fgx == 0x57ea) | |
2132 | + fgx = 0x0540; | |
2133 | + else if (fgx == 0xffff) | |
2134 | + fgx = 0x52aa; | |
2135 | + } | |
2136 | + bgx = ((u32 *)info->pseudo_palette)[bg_color]; | |
2137 | + d = 0; | |
2138 | + | |
2139 | + while (count--) { | |
2140 | + c = scr_readw(s++); | |
2141 | + src = vc->vc_font.data + (c & charmask) * vc->vc_font.height * ((vc->vc_font.width + 7) >> 3); | |
2142 | + | |
2143 | + for (y = 0; y < vc->vc_font.height; y++) { | |
2144 | + for (x = 0; x < vc->vc_font.width; x += 2) { | |
2145 | + if ((x & 7) == 0) | |
2146 | + d = *src++; | |
2147 | + if (d & 0x80) | |
2148 | + dd = fgx; | |
2149 | + else | |
2150 | + dd = transparent ? *(u16 *)splashsrc : bgx; | |
2151 | + splashsrc += 2; | |
2152 | + if (d & 0x40) | |
2153 | + dd |= fgx << 16; | |
2154 | + else | |
2155 | + dd |= (transparent ? *(u16 *)splashsrc : bgx) << 16; | |
2156 | + splashsrc += 2; | |
2157 | + d <<= 2; | |
2158 | + fb_writel(dd, dst); | |
2159 | + dst += 4; | |
2160 | + } | |
2161 | + dst += info->fix.line_length - vc->vc_font.width * 2; | |
2162 | + splashsrc += info->splash_bytes - vc->vc_font.width * 2; | |
2163 | + } | |
2164 | + dst -= info->fix.line_length * vc->vc_font.height - vc->vc_font.width * 2; | |
2165 | + splashsrc -= info->splash_bytes * vc->vc_font.height - vc->vc_font.width * 2; | |
2166 | + } | |
2167 | +} | |
2168 | + | |
2169 | +static void splash_renderc(struct splash_data *sd, struct fb_info *info, int fg_color, int bg_color, u8 *src, int ypos, int xpos, int height, int width) | |
2170 | +{ | |
2171 | + int transparent = sd->splash_color == bg_color; | |
2172 | + u32 dd, fgx, bgx; | |
2173 | + u8 *dst, *splashsrc; | |
2174 | + unsigned int d, x, y; | |
2175 | + | |
2176 | + splashsrc = (u8 *)(info->splash_pic + ypos * info->splash_bytes + xpos * 2); | |
2177 | + dst = (u8 *)(info->screen_base + ypos * info->fix.line_length + xpos * 2); | |
2178 | + fgx = ((u32 *)info->pseudo_palette)[fg_color]; | |
2179 | + if (transparent && sd->splash_color == 15) { | |
2180 | + if (fgx == 0xffea) | |
2181 | + fgx = 0xfe4a; | |
2182 | + else if (fgx == 0x57ea) | |
2183 | + fgx = 0x0540; | |
2184 | + else if (fgx == 0xffff) | |
2185 | + fgx = 0x52aa; | |
2186 | + } | |
2187 | + bgx = ((u32 *)info->pseudo_palette)[bg_color]; | |
2188 | + d = 0; | |
2189 | + for (y = 0; y < height; y++) { | |
2190 | + for (x = 0; x < width; x += 2) { | |
2191 | + if ((x & 7) == 0) | |
2192 | + d = *src++; | |
2193 | + if (d & 0x80) | |
2194 | + dd = fgx; | |
2195 | + else | |
2196 | + dd = transparent ? *(u16 *)splashsrc : bgx; | |
2197 | + splashsrc += 2; | |
2198 | + if (d & 0x40) | |
2199 | + dd |= fgx << 16; | |
2200 | + else | |
2201 | + dd |= (transparent ? *(u16 *)splashsrc : bgx) << 16; | |
2202 | + splashsrc += 2; | |
2203 | + d <<= 2; | |
2204 | + fb_writel(dd, dst); | |
2205 | + dst += 4; | |
2206 | + } | |
2207 | + dst += info->fix.line_length - width * 2; | |
2208 | + splashsrc += info->splash_bytes - width * 2; | |
2209 | + } | |
2210 | +} | |
2211 | + | |
2212 | +void splash_putc(struct splash_data *sd, struct vc_data *vc, struct fb_info *info, | |
2213 | + int c, int ypos, int xpos) | |
2214 | +{ | |
2215 | + unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; | |
2216 | + int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | |
2217 | + int fgshift = (vc->vc_hi_font_mask) ? 9 : 8; | |
2218 | + u8 *src = vc->vc_font.data + (c & charmask) * vc->vc_font.height * ((vc->vc_font.width + 7) >> 3); | |
2219 | + xpos = xpos * vc->vc_font.width + sd->splash_text_xo; | |
2220 | + ypos = ypos * vc->vc_font.height + sd->splash_text_yo; | |
2221 | + splash_renderc(sd, info, attr_fgcol(fgshift, c), attr_bgcol(bgshift, c), src, ypos, xpos, vc->vc_font.height, vc->vc_font.width); | |
2222 | +} | |
2223 | + | |
2224 | +void splashcopy(u8 *dst, u8 *src, int height, int width, int dstbytes, int srcbytes) | |
2225 | +{ | |
2226 | + int i; | |
2227 | + | |
2228 | + while (height-- > 0) { | |
2229 | + u32 *p = (u32 *)dst; | |
2230 | + u32 *q = (u32 *)src; | |
2231 | + for (i=0; i < width/4; i++) { | |
2232 | + fb_writel(*q++,p++); | |
2233 | + fb_writel(*q++,p++); | |
2234 | + } | |
2235 | + if (width & 2) | |
2236 | + fb_writel(*q++,p++); | |
2237 | + if (width & 1) | |
2238 | + fb_writew(*(u16*)q,(u16*)p); | |
2239 | + dst += dstbytes; | |
2240 | + src += srcbytes; | |
2241 | + } | |
2242 | +} | |
2243 | + | |
2244 | +static void splashset(u8 *dst, int height, int width, int dstbytes, u32 bgx) { | |
2245 | + int i; | |
2246 | + | |
2247 | + bgx |= bgx << 16; | |
2248 | + while (height-- > 0) { | |
2249 | + u32 *p = (u32 *)dst; | |
2250 | + for (i=0; i < width/4; i++) { | |
2251 | + fb_writel(bgx,p++); | |
2252 | + fb_writel(bgx,p++); | |
2253 | + } | |
2254 | + if (width & 2) | |
2255 | + fb_writel(bgx,p++); | |
2256 | + if (width & 1) | |
2257 | + fb_writew(bgx,(u16*)p); | |
2258 | + dst += dstbytes; | |
2259 | + } | |
2260 | +} | |
2261 | + | |
2262 | +static void splashfill(struct fb_info *info, int sy, int sx, int height, int width) { | |
2263 | + splashcopy((u8 *)(info->screen_base + sy * info->fix.line_length + sx * 2), (u8 *)(info->splash_pic + sy * info->splash_bytes + sx * 2), height, width, info->fix.line_length, info->splash_bytes); | |
2264 | +} | |
2265 | + | |
2266 | +void splash_clear(struct splash_data *sd, struct vc_data *vc, struct fb_info *info, int sy, | |
2267 | + int sx, int height, int width) | |
2268 | +{ | |
2269 | + int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | |
2270 | + int bg_color = attr_bgcol_ec(bgshift, vc); | |
2271 | + int transparent = sd->splash_color == bg_color; | |
2272 | + u32 bgx; | |
2273 | + u8 *dst; | |
2274 | + | |
2275 | + sy = sy * vc->vc_font.height + sd->splash_text_yo; | |
2276 | + sx = sx * vc->vc_font.width + sd->splash_text_xo; | |
2277 | + height *= vc->vc_font.height; | |
2278 | + width *= vc->vc_font.width; | |
2279 | + if (transparent) { | |
2280 | + splashfill(info, sy, sx, height, width); | |
2281 | + return; | |
2282 | + } | |
2283 | + dst = (u8 *)(info->screen_base + sy * info->fix.line_length + sx * 2); | |
2284 | + bgx = ((u32 *)info->pseudo_palette)[bg_color]; | |
2285 | + splashset(dst, height, width, info->fix.line_length, bgx); | |
2286 | +} | |
2287 | + | |
2288 | +void splash_bmove(struct splash_data *sd, struct vc_data *vc, struct fb_info *info, int sy, | |
2289 | + int sx, int dy, int dx, int height, int width) | |
2290 | +{ | |
2291 | + struct fb_copyarea area; | |
2292 | + | |
2293 | + area.sx = sx * vc->vc_font.width; | |
2294 | + area.sy = sy * vc->vc_font.height; | |
2295 | + area.dx = dx * vc->vc_font.width; | |
2296 | + area.dy = dy * vc->vc_font.height; | |
2297 | + area.sx += sd->splash_text_xo; | |
2298 | + area.sy += sd->splash_text_yo; | |
2299 | + area.dx += sd->splash_text_xo; | |
2300 | + area.dy += sd->splash_text_yo; | |
2301 | + area.height = height * vc->vc_font.height; | |
2302 | + area.width = width * vc->vc_font.width; | |
2303 | + | |
2304 | + info->fbops->fb_copyarea(info, &area); | |
2305 | +} | |
2306 | + | |
2307 | +void splash_clear_margins(struct splash_data *sd, struct vc_data *vc, struct fb_info *info, | |
2308 | + int bottom_only) | |
2309 | +{ | |
2310 | + unsigned int tw = vc->vc_cols*vc->vc_font.width; | |
2311 | + unsigned int th = vc->vc_rows*vc->vc_font.height; | |
2312 | + | |
2313 | + if (!bottom_only) { | |
2314 | + /* top margin */ | |
2315 | + splashfill(info, 0, 0, sd->splash_text_yo, info->var.xres); | |
2316 | + /* left margin */ | |
2317 | + splashfill(info, sd->splash_text_yo, 0, th, sd->splash_text_xo); | |
2318 | + /* right margin */ | |
2319 | + splashfill(info, sd->splash_text_yo, sd->splash_text_xo + tw, th, info->var.xres - sd->splash_text_xo - tw); | |
2320 | + | |
2321 | + } | |
2322 | + splashfill(info, sd->splash_text_yo + th, 0, info->var.yres - sd->splash_text_yo - th, info->var.xres); | |
2323 | +} | |
2324 | + | |
2325 | +void splash_cursor(struct splash_data *sd, struct fb_info *info, struct fb_cursor *cursor) | |
2326 | +{ | |
2327 | + int i; | |
2328 | + unsigned int dsize, s_pitch; | |
2329 | + | |
2330 | + if (cursor->set & FB_CUR_SETSIZE) { | |
2331 | + info->cursor.image.height = cursor->image.height; | |
2332 | + info->cursor.image.width = cursor->image.width; | |
2333 | + } | |
2334 | + if (cursor->set & FB_CUR_SETPOS) { | |
2335 | + info->cursor.image.dx = cursor->image.dx; | |
2336 | + info->cursor.image.dy = cursor->image.dy; | |
2337 | + } | |
2338 | + if (cursor->set & FB_CUR_SETHOT) | |
2339 | + info->cursor.hot = cursor->hot; | |
2340 | + if (cursor->set & FB_CUR_SETCMAP) { | |
2341 | + if (cursor->image.depth == 1) { | |
2342 | + info->cursor.image.bg_color = cursor->image.bg_color; | |
2343 | + info->cursor.image.fg_color = cursor->image.fg_color; | |
2344 | + } else { | |
2345 | + if (cursor->image.cmap.len) | |
2346 | + fb_copy_cmap(&cursor->image.cmap, &info->cursor.image.cmap, 0); | |
2347 | + } | |
2348 | + info->cursor.image.depth = cursor->image.depth; | |
2349 | + } | |
2350 | + s_pitch = (info->cursor.image.width + 7) >> 3; | |
2351 | + dsize = s_pitch * info->cursor.image.height; | |
2352 | + if (info->cursor.enable) { | |
2353 | + switch (info->cursor.rop) { | |
2354 | + case ROP_XOR: | |
2355 | + for (i = 0; i < dsize; i++) | |
2356 | + info->fb_cursordata[i] = cursor->image.data[i] ^ info->cursor.mask[i]; | |
2357 | + break; | |
2358 | + case ROP_COPY: | |
2359 | + default: | |
2360 | + for (i = 0; i < dsize; i++) | |
2361 | + info->fb_cursordata[i] = cursor->image.data[i] & info->cursor.mask[i]; | |
2362 | + break; | |
2363 | + } | |
2364 | + } else if (info->fb_cursordata != cursor->image.data) | |
2365 | + memcpy(info->fb_cursordata, cursor->image.data, dsize); | |
2366 | + info->cursor.image.data = info->fb_cursordata; | |
2367 | + splash_renderc(sd, info, info->cursor.image.fg_color, info->cursor.image.bg_color, (u8 *)info->fb_cursordata, info->cursor.image.dy + sd->splash_text_yo, info->cursor.image.dx + sd->splash_text_xo, info->cursor.image.height, info->cursor.image.width); | |
2368 | +} | |
2369 | + | |
2370 | +void splash_bmove_redraw(struct splash_data *sd, struct vc_data *vc, struct fb_info *info, int y, int sx, int dx, int width) | |
2371 | +{ | |
2372 | + unsigned short *d = (unsigned short *) (vc->vc_origin + vc->vc_size_row * y + dx * 2); | |
2373 | + unsigned short *s = d + (dx - sx); | |
2374 | + unsigned short *start = d; | |
2375 | + unsigned short *ls = d; | |
2376 | + unsigned short *le = d + width; | |
2377 | + unsigned short c; | |
2378 | + int x = dx; | |
2379 | + unsigned short attr = 1; | |
2380 | + | |
2381 | + do { | |
2382 | + c = scr_readw(d); | |
2383 | + if (attr != (c & 0xff00)) { | |
2384 | + attr = c & 0xff00; | |
2385 | + if (d > start) { | |
2386 | + splash_putcs(sd, vc, info, start, d - start, y, x); | |
2387 | + x += d - start; | |
2388 | + start = d; | |
2389 | + } | |
2390 | + } | |
2391 | + if (s >= ls && s < le && c == scr_readw(s)) { | |
2392 | + if (d > start) { | |
2393 | + splash_putcs(sd, vc, info, start, d - start, y, x); | |
2394 | + x += d - start + 1; | |
2395 | + start = d + 1; | |
2396 | + } else { | |
2397 | + x++; | |
2398 | + start++; | |
2399 | + } | |
2400 | + } | |
2401 | + s++; | |
2402 | + d++; | |
2403 | + } while (d < le); | |
2404 | + if (d > start) | |
2405 | + splash_putcs(sd, vc, info, start, d - start, y, x); | |
2406 | +} | |
2407 | + | |
2408 | +void splash_blank(struct splash_data *sd, struct vc_data *vc, struct fb_info *info, int blank) | |
2409 | +{ | |
2410 | + if (blank) { | |
2411 | + if (info->silent_screen_base) | |
2412 | + splashset((u8 *)info->silent_screen_base, info->var.yres, info->var.xres, info->fix.line_length, 0); | |
2413 | + splashset((u8 *)info->screen_base, info->var.yres, info->var.xres, info->fix.line_length, 0); | |
2414 | + } else { | |
2415 | + if (info->silent_screen_base) | |
2416 | + splash_prepare(vc, info); | |
2417 | + update_screen(vc->vc_num); | |
2418 | + splash_clear_margins(vc->vc_splash_data, vc, info, 0); | |
2419 | + } | |
2420 | +} | |
2421 | diff -Nur --exclude '*.orig' linux-2.6.5-rc2.org/drivers/video/console/fbcon.c linux-2.6.5-rc2/drivers/video/console/fbcon.c | |
2422 | --- linux-2.6.5-rc2.org/drivers/video/console/fbcon.c 2004-03-20 00:11:33.000000000 +0000 | |
2423 | +++ linux-2.6.5-rc2/drivers/video/console/fbcon.c 2004-03-23 10:43:03.000000000 +0000 | |
2424 | @@ -93,6 +93,9 @@ | |
2425 | #endif | |
2426 | ||
2427 | #include "fbcon.h" | |
2428 | +#ifdef CONFIG_BOOTSPLASH | |
2429 | +#include "../bootsplash/bootsplash.h" | |
2430 | +#endif | |
2431 | ||
2432 | #ifdef FBCONDEBUG | |
2433 | # define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) | |
2434 | @@ -200,6 +203,12 @@ | |
2435 | return; | |
2436 | acquire_console_sem(); | |
2437 | info->cursor.enable ^= 1; | |
2438 | +#ifdef CONFIG_BOOTSPLASH | |
2439 | + if (info->splash_data) { | |
2440 | + splash_cursor(info->splash_data, info, &info->cursor); | |
2441 | + return; | |
2442 | + } | |
2443 | +#endif | |
2444 | info->fbops->fb_cursor(info, &info->cursor); | |
2445 | release_console_sem(); | |
2446 | } | |
2447 | @@ -316,6 +325,14 @@ | |
2448 | { | |
2449 | struct fb_copyarea area; | |
2450 | ||
2451 | +#ifdef CONFIG_BOOTSPLASH | |
2452 | + if (info->splash_data) { | |
2453 | + splash_bmove(info->splash_data, vc, info, | |
2454 | + sy, sx, dy, dx, height, width); | |
2455 | + return; | |
2456 | + } | |
2457 | +#endif | |
2458 | + | |
2459 | area.sx = sx * vc->vc_font.width; | |
2460 | area.sy = sy * vc->vc_font.height; | |
2461 | area.dx = dx * vc->vc_font.width; | |
2462 | @@ -332,6 +349,13 @@ | |
2463 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | |
2464 | struct fb_fillrect region; | |
2465 | ||
2466 | +#ifdef CONFIG_BOOTSPLASH | |
2467 | + if (info->splash_data) { | |
2468 | + splash_clear(info->splash_data, vc, info, | |
2469 | + sy, sx, height, width); | |
2470 | + return; | |
2471 | + } | |
2472 | +#endif | |
2473 | region.color = attr_bgcol_ec(bgshift, vc); | |
2474 | region.dx = sx * vc->vc_font.width; | |
2475 | region.dy = sy * vc->vc_font.height; | |
2476 | @@ -360,6 +384,13 @@ | |
2477 | u16 c = scr_readw(s); | |
2478 | u8 *src, *dst, *dst0; | |
2479 | ||
2480 | +#ifdef CONFIG_BOOTSPLASH | |
2481 | + if (info->splash_data) { | |
2482 | + splash_putcs(info->splash_data, vc, info, s, count, yy, xx); | |
2483 | + return; | |
2484 | + } | |
2485 | +#endif | |
2486 | + | |
2487 | image.fg_color = attr_fgcol(fgshift, c); | |
2488 | image.bg_color = attr_bgcol(bgshift, c); | |
2489 | image.dx = xx * vc->vc_font.width; | |
2490 | @@ -416,6 +447,13 @@ | |
2491 | unsigned int bs = info->var.yres - bh; | |
2492 | struct fb_fillrect region; | |
2493 | ||
2494 | +#ifdef CONFIG_BOOTSPLASH | |
2495 | + if (info->splash_data) { | |
2496 | + splash_clear_margins(info->splash_data, vc, info, bottom_only); | |
2497 | + return; | |
2498 | + } | |
2499 | +#endif | |
2500 | + | |
2501 | region.color = attr_bgcol_ec(bgshift, vc); | |
2502 | region.rop = ROP_COPY; | |
2503 | ||
2504 | @@ -694,6 +732,14 @@ | |
2505 | nr_cols = info->var.xres / vc->vc_font.width; | |
2506 | nr_rows = info->var.yres / vc->vc_font.height; | |
2507 | ||
2508 | +#ifdef CONFIG_BOOTSPLASH | |
2509 | + if (vc->vc_splash_data && vc->vc_splash_data->splash_state) { | |
2510 | + nr_cols = vc->vc_splash_data->splash_text_wi / vc->vc_font.width; | |
2511 | + nr_rows = vc->vc_splash_data->splash_text_he / vc->vc_font.height; | |
2512 | + logo = 0; | |
2513 | + } | |
2514 | +#endif | |
2515 | + | |
2516 | if (logo) { | |
2517 | /* Need to make room for the logo */ | |
2518 | int cnt; | |
2519 | @@ -769,6 +815,12 @@ | |
2520 | vc->vc_complement_mask <<= 1; | |
2521 | } | |
2522 | ||
2523 | +#ifdef CONFIG_BOOTSPLASH | |
2524 | + if(vc->vc_splash_data && vc->vc_splash_data->splash_state) { | |
2525 | + con_remap_def_color(vc->vc_num, vc->vc_splash_data->splash_color << 4 | vc->vc_splash_data->splash_fg_color); | |
2526 | + } | |
2527 | +#endif | |
2528 | + | |
2529 | if (!init) { | |
2530 | if (vc->vc_cols != nr_cols || vc->vc_rows != nr_rows) | |
2531 | vc_resize(vc->vc_num, nr_cols, nr_rows); | |
2532 | @@ -896,6 +948,13 @@ | |
2533 | if (vt_cons[vc->vc_num]->vc_mode != KD_TEXT) | |
2534 | return; | |
2535 | ||
2536 | +#ifdef CONFIG_BOOTSPLASH | |
2537 | + if (info->splash_data) { | |
2538 | + splash_putc(info->splash_data, vc, info, c, ypos, xpos); | |
2539 | + return; | |
2540 | + } | |
2541 | +#endif | |
2542 | + | |
2543 | image.dx = xpos * vc->vc_font.width; | |
2544 | image.dy = real_y(p, ypos) * vc->vc_font.height; | |
2545 | image.width = vc->vc_font.width; | |
2546 | @@ -970,6 +1029,12 @@ | |
2547 | if (info->cursor.rop == ROP_XOR) { | |
2548 | info->cursor.enable = 0; | |
2549 | info->cursor.rop = ROP_COPY; | |
2550 | +#ifdef CONFIG_BOOTSPLASH | |
2551 | + if (info->splash_data) { | |
2552 | + splash_cursor(info->splash_data, info, &cursor); | |
2553 | + break; | |
2554 | + } | |
2555 | +#endif | |
2556 | info->fbops->fb_cursor(info, &cursor); | |
2557 | } | |
2558 | break; | |
2559 | @@ -1045,6 +1110,13 @@ | |
2560 | mask[i++] = 0xff; | |
2561 | } | |
2562 | info->cursor.rop = ROP_XOR; | |
2563 | +#ifdef CONFIG_BOOTSPLASH | |
2564 | + if (info->splash_data) { | |
2565 | + splash_cursor(info->splash_data, info, &cursor); | |
2566 | + vbl_cursor_cnt = CURSOR_DRAW_DELAY; | |
2567 | + break; | |
2568 | + } | |
2569 | +#endif | |
2570 | info->fbops->fb_cursor(info, &cursor); | |
2571 | vbl_cursor_cnt = CURSOR_DRAW_DELAY; | |
2572 | break; | |
2573 | @@ -1348,6 +1420,10 @@ | |
2574 | fbcon_softback_note(vc, t, count); | |
2575 | if (logo_shown >= 0) | |
2576 | goto redraw_up; | |
2577 | +#ifdef CONFIG_BOOTSPLASH | |
2578 | + if (info->splash_data) | |
2579 | + goto redraw_up; | |
2580 | +#endif | |
2581 | switch (p->scrollmode & __SCROLL_YMASK) { | |
2582 | case __SCROLL_YMOVE: | |
2583 | accel_bmove(vc, info, t + count, 0, t, 0, | |
2584 | @@ -1415,6 +1491,10 @@ | |
2585 | case SM_DOWN: | |
2586 | if (count > vc->vc_rows) /* Maximum realistic size */ | |
2587 | count = vc->vc_rows; | |
2588 | +#ifdef CONFIG_BOOTSPLASH | |
2589 | + if (info->splash_data) | |
2590 | + goto redraw_down; | |
2591 | +#endif | |
2592 | switch (p->scrollmode & __SCROLL_YMASK) { | |
2593 | case __SCROLL_YMOVE: | |
2594 | accel_bmove(vc, info, t, 0, t + count, 0, | |
2595 | @@ -1540,6 +1620,13 @@ | |
2596 | } | |
2597 | return; | |
2598 | } | |
2599 | +#ifdef CONFIG_BOOTSPLASH | |
2600 | + if (info->splash_data && sy == dy && height == 1) { | |
2601 | + /* must use slower redraw bmove to keep background pic intact */ | |
2602 | + splash_bmove_redraw(info->splash_data, vc, info, sy, sx, dx, width); | |
2603 | + return; | |
2604 | + } | |
2605 | +#endif | |
2606 | accel_bmove(vc, info, real_y(p, sy), sx, real_y(p, dy), dx, | |
2607 | height, width); | |
2608 | } | |
2609 | @@ -1580,6 +1667,10 @@ | |
2610 | struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]]; | |
2611 | struct display *p = &fb_display[vc->vc_num]; | |
2612 | ||
2613 | +#ifdef CONFIG_BOOTSPLASH | |
2614 | + splash_prepare(vc, info); | |
2615 | +#endif | |
2616 | + | |
2617 | if (softback_top) { | |
2618 | int l = fbcon_softback_size / vc->vc_size_row; | |
2619 | if (softback_lines) | |
2620 | @@ -1663,6 +1754,12 @@ | |
2621 | fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW); | |
2622 | ||
2623 | if (!info->fbops->fb_blank) { | |
2624 | +#ifdef CONFIG_BOOTSPLASH | |
2625 | + if (info->splash_data) { | |
2626 | + splash_blank(info->splash_data, vc, info, blank); | |
2627 | + return 0; | |
2628 | + } | |
2629 | +#endif | |
2630 | if (blank) { | |
2631 | unsigned short oldc; | |
2632 | u_int height; | |
2633 | @@ -1839,19 +1936,26 @@ | |
2634 | } | |
2635 | ||
2636 | if (resize) { | |
2637 | + u32 xres = info->var.xres, yres = info->var.yres; | |
2638 | /* reset wrap/pan */ | |
2639 | info->var.xoffset = info->var.yoffset = p->yscroll = 0; | |
2640 | p->vrows = info->var.yres_virtual / h; | |
2641 | ||
2642 | +#ifdef CONFIG_BOOTSPLASH | |
2643 | + if (info->splash_data) { | |
2644 | + xres = info->splash_data->splash_text_wi; | |
2645 | + yres = info->splash_data->splash_text_he; | |
2646 | + } | |
2647 | +#endif | |
2648 | #if 0 /* INCOMPLETE - let the console gurus handle this */ | |
2649 | - if(info->var.yres > (h * (vc->vc_rows + 1)) | |
2650 | - p->vrows -= (info->var.yres - (h * vc->vc_rows)) / h; | |
2651 | + if(yres > (h * (vc->vc_rows + 1)) | |
2652 | + p->vrows -= (yres - (h * vc->vc_rows)) / h; | |
2653 | #endif | |
2654 | - if ((info->var.yres % h) | |
2655 | + if ((yres % h) | |
2656 | && (info->var.yres_virtual % h < info->var.yres % h)) | |
2657 | p->vrows--; | |
2658 | updatescrollmode(p, vc); | |
2659 | - vc_resize(vc->vc_num, info->var.xres / w, info->var.yres / h); | |
2660 | + vc_resize(vc->vc_num, xres / w, yres / h); | |
2661 | if (CON_IS_VISIBLE(vc) && softback_buf) { | |
2662 | int l = fbcon_softback_size / vc->vc_size_row; | |
2663 | if (l > 5) | |
2664 | @@ -2290,6 +2394,9 @@ | |
2665 | { | |
2666 | if (!num_registered_fb) | |
2667 | return -ENODEV; | |
2668 | +#ifdef CONFIG_BOOTSPLASH | |
2669 | + splash_init(); | |
2670 | +#endif | |
2671 | ||
2672 | take_over_console(&fb_con, first_fb_vc, last_fb_vc, fbcon_is_default); | |
2673 | acquire_console_sem(); | |
2674 | diff -Nur --exclude '*.orig' linux-2.6.5-rc2.org/drivers/video/console/fbcon.h linux-2.6.5-rc2/drivers/video/console/fbcon.h | |
2675 | --- linux-2.6.5-rc2.org/drivers/video/console/fbcon.h 2004-03-20 00:11:33.000000000 +0000 | |
2676 | +++ linux-2.6.5-rc2/drivers/video/console/fbcon.h 2004-03-23 10:00:22.000000000 +0000 | |
2677 | @@ -23,6 +23,34 @@ | |
2678 | * low-level frame buffer device | |
2679 | */ | |
2680 | ||
2681 | +#ifdef CONFIG_BOOTSPLASH | |
2682 | +struct splash_data { | |
2683 | + int splash_state; /* show splash? */ | |
2684 | + int splash_color; /* transparent color */ | |
2685 | + int splash_fg_color; /* foreground color */ | |
2686 | + int splash_width; /* width of image */ | |
2687 | + int splash_height; /* height of image */ | |
2688 | + int splash_text_xo; /* text area origin */ | |
2689 | + int splash_text_yo; | |
2690 | + int splash_text_wi; /* text area size */ | |
2691 | + int splash_text_he; | |
2692 | + int splash_showtext; /* silent/verbose mode */ | |
2693 | + int splash_boxcount; | |
2694 | + int splash_percent; | |
2695 | + int splash_overpaintok; /* is it ok to overpaint boxes */ | |
2696 | + int splash_palcnt; | |
2697 | + char *oldscreen_base; /* pointer to top of virtual screen */ | |
2698 | + unsigned char *splash_boxes; | |
2699 | + unsigned char *splash_jpeg; /* jpeg */ | |
2700 | + unsigned char *splash_palette; /* palette for 8-bit */ | |
2701 | + | |
2702 | + int splash_dosilent; /* show silent jpeg */ | |
2703 | + unsigned char *splash_silentjpeg; | |
2704 | + unsigned char *splash_sboxes; | |
2705 | + int splash_sboxcount; | |
2706 | +}; | |
2707 | +#endif | |
2708 | + | |
2709 | struct display { | |
2710 | /* Filled in by the frame buffer device */ | |
2711 | u_short inverse; /* != 0 text black on white as default */ | |
2712 | diff -Nur --exclude '*.orig' linux-2.6.5-rc2.org/drivers/video/vesafb.c linux-2.6.5-rc2/drivers/video/vesafb.c | |
2713 | --- linux-2.6.5-rc2.org/drivers/video/vesafb.c 2004-03-20 00:11:02.000000000 +0000 | |
2714 | +++ linux-2.6.5-rc2/drivers/video/vesafb.c 2004-03-23 10:00:22.000000000 +0000 | |
2715 | @@ -174,7 +174,10 @@ | |
2716 | return 0; | |
2717 | } | |
2718 | ||
2719 | -static struct fb_ops vesafb_ops = { | |
2720 | +#ifndef CONFIG_BOOTSPLASH | |
2721 | +static | |
2722 | +#endif | |
2723 | +struct fb_ops vesafb_ops = { | |
2724 | .owner = THIS_MODULE, | |
2725 | .fb_setcolreg = vesafb_setcolreg, | |
2726 | .fb_pan_display = vesafb_pan_display, | |
2727 | diff -Nur --exclude '*.orig' linux-2.6.5-rc2.org/include/linux/console_struct.h linux-2.6.5-rc2/include/linux/console_struct.h | |
2728 | --- linux-2.6.5-rc2.org/include/linux/console_struct.h 2004-03-20 00:11:00.000000000 +0000 | |
2729 | +++ linux-2.6.5-rc2/include/linux/console_struct.h 2004-03-23 10:00:22.000000000 +0000 | |
2730 | @@ -87,6 +87,9 @@ | |
2731 | struct vc_data **vc_display_fg; /* [!] Ptr to var holding fg console for this display */ | |
2732 | unsigned long vc_uni_pagedir; | |
2733 | unsigned long *vc_uni_pagedir_loc; /* [!] Location of uni_pagedir variable for this console */ | |
2734 | +#ifdef CONFIG_BOOTSPLASH | |
2735 | + struct splash_data *vc_splash_data; | |
2736 | +#endif | |
2737 | /* additional information is in vt_kern.h */ | |
2738 | }; | |
2739 | ||
2740 | diff -Nur --exclude '*.orig' linux-2.6.5-rc2.org/include/linux/fb.h linux-2.6.5-rc2/include/linux/fb.h | |
2741 | --- linux-2.6.5-rc2.org/include/linux/fb.h 2004-03-20 00:11:04.000000000 +0000 | |
2742 | +++ linux-2.6.5-rc2/include/linux/fb.h 2004-03-23 10:00:22.000000000 +0000 | |
2743 | @@ -522,6 +522,14 @@ | |
2744 | #define FBINFO_STATE_RUNNING 0 | |
2745 | #define FBINFO_STATE_SUSPENDED 1 | |
2746 | u32 state; /* Hardware state i.e suspend */ | |
2747 | +#ifdef CONFIG_BOOTSPLASH | |
2748 | + struct splash_data *splash_data; | |
2749 | + unsigned char *splash_pic; | |
2750 | + int splash_pic_size; | |
2751 | + int splash_bytes; | |
2752 | + char *silent_screen_base; /* real screen base */ | |
2753 | + char fb_cursordata[64]; | |
2754 | +#endif | |
2755 | ||
2756 | /* From here on everything is device dependent */ | |
2757 | void *par; | |
2758 | diff -Nur --exclude '*.orig' linux-2.6.5-rc2.org/kernel/panic.c linux-2.6.5-rc2/kernel/panic.c | |
2759 | --- linux-2.6.5-rc2.org/kernel/panic.c 2004-03-20 00:11:51.000000000 +0000 | |
2760 | +++ linux-2.6.5-rc2/kernel/panic.c 2004-03-23 10:00:22.000000000 +0000 | |
2761 | @@ -82,6 +82,12 @@ | |
2762 | * We can't use the "normal" timers since we just panicked.. | |
2763 | */ | |
2764 | printk(KERN_EMERG "Rebooting in %d seconds..",panic_timeout); | |
2765 | +#ifdef CONFIG_BOOTSPLASH | |
2766 | + { | |
2767 | + extern int splash_verbose(void); | |
2768 | + (void)splash_verbose(); | |
2769 | + } | |
2770 | +#endif | |
2771 | for (i = 0; i < panic_timeout; i++) { | |
2772 | touch_nmi_watchdog(); | |
2773 | mdelay(1000); | |
2774 | @@ -105,6 +111,12 @@ | |
2775 | disabled_wait(caller); | |
2776 | #endif | |
2777 | local_irq_enable(); | |
2778 | +#ifdef CONFIG_BOOTSPLASH | |
2779 | + { | |
2780 | + extern int splash_verbose(void); | |
2781 | + (void)splash_verbose(); | |
2782 | + } | |
2783 | +#endif | |
2784 | for (;;) | |
2785 | ; | |
2786 | } |