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