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