2 * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
30 #include <console/video_console.h>
31 #include <libkern/OSByteOrder.h>
32 #include <kdp/kdp_udp.h>
33 #include <kern/debug.h>
34 #include <mach/mach_time.h>
35 #include <sys/errno.h>
39 extern struct vc_info vinfo
;
40 extern boolean_t panicDialogDesired
;
42 #include "panic_image.c"
44 void panic_ui_initialize(const unsigned char * system_clut
);
45 int panic_dialog_set_image( const unsigned char * ptr
, unsigned int size
);
46 void panic_dialog_get_image( unsigned char ** ptr
, unsigned int * size
);
47 void draw_panic_dialog( void );
48 void panic_dialog_test( void );
50 static int panic_dialog_verify( const struct panicimage
* data
, unsigned int size
);
51 static int pixels_needed_to_blit_digit( int digit
);
52 static void blit_digit( int digit
);
53 static char * strnstr(const char * s
, const char * find
, size_t slen
);
54 static void dim_screen(void);
55 static void panic_blit_rect(unsigned int x
, unsigned int y
, unsigned int width
, unsigned int height
,
56 int transparent
, unsigned char * dataPtr
);
58 static int panic_info_x
;
59 static int panic_info_y
;
61 static const unsigned char * active_clut
= NULL
; /* This is a copy of the active clut */
63 static boolean_t panicDialogDrawn
= FALSE
;
65 static const struct panicimage
* panic_dialog
= NULL
; /* the active panic dialog */
66 static const unsigned char * panic_dialog_data
= NULL
; /* where the image data starts */
67 static const unsigned char * panic_dialog_clut
= NULL
; /* where the clut used for the image starts */
69 static unsigned char * curr_image_ptr
= NULL
; /* If NULL, the default panic dialog is active */
70 static unsigned int curr_image_size
= 0;
73 #define FONT_HEIGHT 16
74 static unsigned short rendered_font
[FONT_HEIGHT
][FONT_WIDTH
];
76 static char versionbuf
[20]; /* ####.###~###\0 */
78 #define isdigit(d) ((d) >= '0' && (d) <= '9')
80 #define CLUT_ENTRIES 256
81 #define CLUT_SIZE (CLUT_ENTRIES * 3)
85 * This routine sets up the default panic dialog
88 extern unsigned char iso_font
[];
89 extern const char version
[];
90 extern unsigned int panic_caller
;
93 panic_ui_initialize(const unsigned char * system_clut
)
98 panic_dialog_set_image( NULL
, 0 );
100 active_clut
= system_clut
;
102 strcpy(vstr
, "custom");
104 /* Convert xnu-####.###.obj~### into ####.###~### */
107 char * versionpos
= strnstr(version
, "xnu-", 20);
114 for (i
=0,len
=4;len
<20;len
++) {
115 if (isdigit(versionpos
[len
]) || versionpos
[len
] == '.') { /* extract ####.###. */
116 vstr
[i
++] = versionpos
[len
];
122 if ( versionpos
[len
-1] == '.' ) /* remove trailing period if present */
125 for (;len
<20;len
++) { /* skip to next digit if present */
126 if ( !isdigit(versionpos
[len
]) )
131 if ( versionpos
[len
-1] == '~' ) { /* extract ~### if present */
132 vstr
[i
++] = versionpos
[len
-1];
133 for (;len
<20;len
++) { /* extract ### */
134 if ( isdigit(versionpos
[len
]) ) {
135 vstr
[i
++] = versionpos
[len
];
146 strcpy(versionbuf
, vstr
);
152 panic_dialog_test( void )
154 boolean_t o_panicDialogDrawn
= panicDialogDrawn
;
155 boolean_t o_panicDialogDesired
= panicDialogDesired
;
156 unsigned int o_logPanicDataToScreen
= logPanicDataToScreen
;
157 unsigned int o_panic_caller
= panic_caller
;
158 unsigned int o_panicDebugging
= panicDebugging
;
161 panicDebugging
= TRUE
;
162 panic_caller
= (unsigned int) __builtin_return_address(0);
163 logPanicDataToScreen
= FALSE
;
164 panicDialogDesired
= TRUE
;
165 panicDialogDrawn
= FALSE
;
169 panicDebugging
= o_panicDebugging
;
170 panic_caller
= o_panic_caller
;
171 logPanicDataToScreen
= o_logPanicDataToScreen
;
172 panicDialogDesired
= o_panicDialogDesired
;
173 panicDialogDrawn
= o_panicDialogDrawn
;
178 draw_panic_dialog( void )
180 if (!panicDialogDrawn
&& panicDialogDesired
) {
181 if ( !logPanicDataToScreen
) {
183 int count
, nibble
, indx
;
184 struct ether_addr kdp_mac_addr
;
185 unsigned int panic_dialog_count
, ip_addr
;
186 char panic_num_chars
[13+8+1], mac_addr_chars
[17+1], ip_addr_chars
[15+1];
190 } panic_dialog_info
[3];
193 /* dim the screen 50% before putting up panic dialog */
196 /* set up to draw background box */
197 /* by locating where the upper left corner is placed */
199 pd_x
= (vinfo
.v_width
/2) - panic_dialog
->pd_width
/2;
200 pd_y
= (vinfo
.v_height
/2) - panic_dialog
->pd_height
/2;
202 /* draw panic dialog at pd_x/pd_y */
203 panic_blit_rect( pd_x
, pd_y
, panic_dialog
->pd_width
, panic_dialog
->pd_height
,
204 0, (unsigned char*) panic_dialog_data
);
206 panic_dialog_count
= 0; /* number of info items to display at the bottom of dialog */
208 if (panicDebugging
) {
214 * don't display the panic caller if it is 0
218 if ( panic_caller
!= 0 ) {
219 /* Calculate the pixels need to generate the panic number */
220 panic_dialog_info
[panic_dialog_count
].pixels
= 0;
222 for ( indx
=1, count
=0; count
< 13; count
++ ) {
223 if ( versionbuf
[count
] == '\0' )
226 panic_num_chars
[indx
++] = versionbuf
[count
];
227 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( versionbuf
[count
] );
230 panic_num_chars
[indx
++] = ':';
231 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( ':' );
233 for ( count
=8; count
!= 0; count
-- ) {
234 nibble
= (panic_caller
>> ((count
-1)<<2)) &0xF;
235 panic_num_chars
[indx
++] = nibble
;
236 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( nibble
);
239 panic_num_chars
[0] = indx
;
240 panic_dialog_info
[panic_dialog_count
].chars
= panic_num_chars
;
241 panic_dialog_count
++;
247 * if the mac address is not available, then use ff:ff:ff:ff:ff:ff
251 kdp_mac_addr
= kdp_get_mac_addr();
253 /* If no mac_addr has been set, then force to -1 */
254 if( ! (kdp_mac_addr
.ether_addr_octet
[0] || kdp_mac_addr
.ether_addr_octet
[1] || kdp_mac_addr
.ether_addr_octet
[2]
255 || kdp_mac_addr
.ether_addr_octet
[3] || kdp_mac_addr
.ether_addr_octet
[4] || kdp_mac_addr
.ether_addr_octet
[5])) {
256 for (count
= 0; count
< 6; count
++ )
257 kdp_mac_addr
.ether_addr_octet
[count
] = -1;
260 panic_dialog_info
[panic_dialog_count
].pixels
= 0;
262 for (indx
=1, count
=0; count
< 6; count
++ ) {
263 nibble
= (kdp_mac_addr
.ether_addr_octet
[count
] & 0xf0) >> 4;
264 mac_addr_chars
[indx
++] = nibble
;
265 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( nibble
);
267 nibble
= kdp_mac_addr
.ether_addr_octet
[count
] & 0xf;
268 mac_addr_chars
[indx
++] = nibble
;
269 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( nibble
);
272 mac_addr_chars
[indx
++] = ':';
273 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( ':' );
277 mac_addr_chars
[0] = indx
;
278 panic_dialog_info
[panic_dialog_count
].chars
= mac_addr_chars
;
279 panic_dialog_count
++;
284 * do not display the ip addresses if the machine isn't attachable.
285 * there's no sense in possibly confusing people.
288 if ( (ip_addr
= (unsigned int) ntohl(kdp_get_ip_address())) != 0 ) {
291 panic_dialog_info
[panic_dialog_count
].pixels
= 0;
293 for ( indx
=1, count
=0; count
< 4; count
++ ) {
294 nibble
= (ip_addr
& 0xff000000 ) >> 24;
296 d3
= (nibble
% 10) ; nibble
= nibble
/ 10;
297 d2
= (nibble
% 10) ; nibble
= nibble
/ 10;
301 ip_addr_chars
[indx
++] = d1
;
302 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( d1
);
305 ip_addr_chars
[indx
++] = d2
;
306 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( d2
);
308 ip_addr_chars
[indx
++] = d3
;
309 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( d3
);
312 ip_addr_chars
[indx
++] = '.';
313 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( '.' );
317 ip_addr
= ip_addr
<< 8;
320 ip_addr_chars
[0] = indx
;
321 panic_dialog_info
[panic_dialog_count
].chars
= ip_addr_chars
;
322 panic_dialog_count
++;
326 /* vertical alignment for information to be displayed */
327 panic_info_y
= (vinfo
.v_height
/2) + panic_dialog
->pd_height
/2 - (panic_dialog
->pd_info_height
);
329 /* blit out all the information we gathered */
331 switch ( panic_dialog_count
) {
332 case 1 : /* one item is centered */
333 panic_info_x
= (vinfo
.v_width
/2) - (panic_dialog_info
[0].pixels
/2);
334 for (indx
=1; indx
< panic_dialog_info
[0].chars
[0]; indx
++)
335 blit_digit(panic_dialog_info
[0].chars
[indx
]);
339 case 2 : /* left centered and right centered */
340 x1
= ((panic_dialog
->pd_width
/2) - panic_dialog_info
[0].pixels
)/2;
341 panic_info_x
= ((vinfo
.v_width
/2) - (panic_dialog
->pd_width
/2)) + x1
;
343 for (indx
=1; indx
< panic_dialog_info
[0].chars
[0]; indx
++)
344 blit_digit(panic_dialog_info
[0].chars
[indx
]);
346 x2
= ((panic_dialog
->pd_width
/2) - panic_dialog_info
[1].pixels
)/2;
347 panic_info_x
= (vinfo
.v_width
/2) + x2
;
349 for (indx
=1; indx
< panic_dialog_info
[1].chars
[0]; indx
++)
350 blit_digit(panic_dialog_info
[1].chars
[indx
]);
354 case 3 : /* left centered, middle and right centered */
355 x1
= ((panic_dialog
->pd_width
/2) - panic_dialog_info
[0].pixels
- (panic_dialog_info
[1].pixels
/2))/2;
356 panic_info_x
= ((vinfo
.v_width
/2) - (panic_dialog
->pd_width
/2)) + x1
;
358 for (indx
=1; indx
< panic_dialog_info
[0].chars
[0]; indx
++)
359 blit_digit(panic_dialog_info
[0].chars
[indx
]);
361 panic_info_x
= (vinfo
.v_width
/2) - (panic_dialog_info
[1].pixels
/2);
363 for (indx
=1; indx
< panic_dialog_info
[1].chars
[0]; indx
++)
364 blit_digit(panic_dialog_info
[1].chars
[indx
]);
366 x2
= ((panic_dialog
->pd_width
/2) - panic_dialog_info
[2].pixels
- (panic_dialog_info
[1].pixels
/2))/2;
367 panic_info_x
= (vinfo
.v_width
/2) + x2
+ (panic_dialog_info
[1].pixels
/2);
369 for (indx
=1; indx
< panic_dialog_info
[2].chars
[0]; indx
++)
370 blit_digit(panic_dialog_info
[2].chars
[indx
]);
374 default : /* nothing */
378 } /* if panic_deugging */
379 } /* if ! logPanicDataToScreen */
380 } /* if ! panicDialogDrawn && ! panicDialogDesired */
382 panicDialogDrawn
= TRUE
;
383 panicDialogDesired
= FALSE
;
388 * This routine installs a new panic dialog
389 * If ptr is NULL, then the default "built-in" panic dialog will be installed.
390 * note: It is the caller that must take care of deallocating memory used for the previous panic dialog
394 panic_dialog_set_image( const unsigned char * ptr
, unsigned int size
)
397 unsigned int newsize
;
398 const struct panicimage
* newimage
;
400 /* if ptr is NULL, restore panic image to built-in default */
402 newimage
= &panic_dialog_default
;
403 newsize
= sizeof(struct panicimage
) + newimage
->pd_dataSize
;
406 newimage
= (struct panicimage
*) ptr
;
410 if ( (error
= panic_dialog_verify( newimage
, newsize
)) )
413 panic_dialog
= newimage
;
414 panic_dialog_data
= &panic_dialog
->data
[0];
415 panic_dialog_clut
= &panic_dialog
->data
[panic_dialog
->pd_dataSize
-CLUT_SIZE
];
417 curr_image_ptr
= (unsigned char *) ptr
;
418 curr_image_size
= size
;
425 * This routines returns the current address of the panic dialog
426 * If the default panic dialog is active, then *ptr will be NULL
430 panic_dialog_get_image( unsigned char ** ptr
, unsigned int * size
)
432 *ptr
= curr_image_ptr
;
433 *size
= curr_image_size
;
438 * This routine verifies the panic dialog image is valid.
442 panic_dialog_verify( const struct panicimage
* newimage
, unsigned int size
)
446 if ( size
< (sizeof(struct panicimage
) + newimage
->pd_dataSize
) )
449 if ( newimage
->pd_tag
!= 'RNMp' )
452 size
= newimage
->pd_dataSize
-CLUT_SIZE
;
453 for (sum
=0,i
=0; i
<size
; i
++) {
454 sum
+= newimage
->data
[i
];
458 if ( sum
!= newimage
->pd_sum
)
466 * Service Routines for managing the panic dialog
470 static const struct rendered_num
* find_rendered_digit( int digit
);
471 static void panic_blit_rect_8( unsigned int x
, unsigned int y
, unsigned int width
, unsigned int height
,
472 int transparent
, unsigned char * dataPtr
);
473 static void panic_blit_rect_16( unsigned int x
, unsigned int y
, unsigned int width
, unsigned int height
,
474 int transparent
, unsigned char * dataPtr
);
475 static void panic_blit_rect_32( unsigned int x
, unsigned int y
, unsigned int width
, unsigned int height
,
476 int transparent
, unsigned char * dataPtr
);
477 static int decode_rle( unsigned char * dataPtr
, unsigned int * quantity
, unsigned int * depth
, unsigned char ** value
);
480 /* Utilities to convert 8 bit/gray */
481 static unsigned int make24bitcolor( unsigned int index
, const unsigned char * clut
);
482 static unsigned char findIndexMatch( unsigned char index
);
483 static unsigned char color24togray8( unsigned int color24
);
484 static unsigned char findbestgray( unsigned int color24
);
485 static int isActiveClutOK( void );
488 pixels_needed_to_blit_digit( int digit
)
494 static const struct rendered_num
*
495 find_rendered_digit( int digit
)
497 //extern unsigned char iso_font[];
498 const struct rendered_num
*digitPtr
;
507 digitPtr
= (const struct rendered_num
*) &iso_font
[digit
* 16];
513 blit_digit( int digit
)
515 unsigned char * raw_data
= (unsigned char *) find_rendered_digit( digit
);
516 unsigned width
= FONT_WIDTH
, height
= FONT_HEIGHT
;
519 for (row
=0; row
<FONT_HEIGHT
; row
++) {
523 bits
= raw_data
[row
];
524 for( j
=FONT_WIDTH
-1; j
>=0; j
--) {
527 rendered_font
[row
][j
] = OSSwapBigToHostInt16(0x0100 | panic_dialog
->pd_info_color
[0]);
529 rendered_font
[row
][j
] = OSSwapBigToHostInt16(0x0100 | panic_dialog
->pd_info_color
[1]);
534 panic_blit_rect( panic_info_x
, panic_info_y
, width
, height
, 255, (unsigned char *) rendered_font
);
535 panic_info_x
+= width
;
540 panic_blit_rect( unsigned int x
, unsigned int y
,
541 unsigned int width
, unsigned int height
,
542 int transparent
, unsigned char * dataPtr
)
547 switch( vinfo
.v_depth
) {
549 panic_blit_rect_8( x
, y
, width
, height
, transparent
, dataPtr
);
552 panic_blit_rect_16( x
, y
, width
, height
, transparent
, dataPtr
);
555 panic_blit_rect_32( x
, y
, width
, height
, transparent
, dataPtr
);
561 * panic_blit_rect_8 decodes the RLE encoded image data on the fly, looks up the
562 * color by indexing into the clut, or attempts to find the best index.
566 panic_blit_rect_8( unsigned int x
, unsigned int y
,
567 unsigned int width
, unsigned int height
,
568 int transparent
, unsigned char * dataPtr
)
570 volatile unsigned char * dst
;
571 unsigned int line
, col
, i
;
572 static int clutOK
= -1;
573 unsigned int data
, quantity
, depth
;
574 unsigned char * value
;
578 clutOK
= isActiveClutOK();
580 dst
= (volatile unsigned char *) (vinfo
.v_baseaddr
+
581 (y
* vinfo
.v_rowbytes
) +
587 for( line
= 0; line
< height
; line
++) {
588 for( col
= 0; col
< width
; col
++) {
591 dataPtr
+= decode_rle(dataPtr
, &quantity
, &depth
, &value
);
598 data
= findIndexMatch( value
[i
++] );
608 dst
= (volatile unsigned char *) (((int)dst
) + vinfo
.v_rowbytes
);
613 * panic_blit_rect_16 decodes the RLE encoded image data on the fly, looks up the
614 * color by indexing into the clut, uses the top 5 bits to fill in each of the three
615 * pixel values (RGB) and writes each pixel to the screen.
619 panic_blit_rect_16( unsigned int x
, unsigned int y
,
620 unsigned int width
, unsigned int height
,
621 int transparent
, unsigned char * dataPtr
)
624 volatile unsigned short * dst
;
625 unsigned int line
, col
, i
;
626 unsigned int quantity
, index
, data
, depth
;
627 unsigned char * value
;
629 dst
= (volatile unsigned short *) (vinfo
.v_baseaddr
+
630 (y
* vinfo
.v_rowbytes
) +
636 for( line
= 0; line
< height
; line
++) {
637 for( col
= 0; col
< width
; col
++) {
640 dataPtr
+= decode_rle(dataPtr
, &quantity
, &depth
, &value
);
644 index
= value
[i
++] * 3;
646 data
= ( (unsigned short) (0xf8 & (panic_dialog_clut
[index
+ 0])) << 7)
647 | ( (unsigned short) (0xf8 & (panic_dialog_clut
[index
+ 1])) << 2)
648 | ( (unsigned short) (0xf8 & (panic_dialog_clut
[index
+ 2])) >> 3);
658 dst
= (volatile unsigned short *) (((int)dst
) + vinfo
.v_rowbytes
);
663 * panic_blit_rect_32 decodes the RLE encoded image data on the fly, and fills
664 * in each of the three pixel values from the clut (RGB) for each pixel and
665 * writes it to the screen.
669 panic_blit_rect_32( unsigned int x
, unsigned int y
,
670 unsigned int width
, unsigned int height
,
671 int transparent
, unsigned char * dataPtr
)
673 volatile unsigned int * dst
;
674 unsigned int line
, col
, i
;
675 unsigned int quantity
, index
, data
, depth
;
676 unsigned char * value
;
679 dst
= (volatile unsigned int *) (vinfo
.v_baseaddr
+
680 (y
* vinfo
.v_rowbytes
) +
686 for( line
= 0; line
< height
; line
++) {
687 for( col
= 0; col
< width
; col
++) {
690 dataPtr
+= decode_rle(dataPtr
, &quantity
, &depth
, &value
);
694 index
= value
[i
++] * 3;
696 data
= ( (unsigned int) panic_dialog_clut
[index
+ 0] << 16)
697 | ( (unsigned int) panic_dialog_clut
[index
+ 1] << 8)
698 | ( (unsigned int) panic_dialog_clut
[index
+ 2]);
708 dst
= (volatile unsigned int *) (((int)dst
) + vinfo
.v_rowbytes
);
713 decode_rle decodes a single quantity/value run of a "modified-RLE" encoded
714 image. The encoding works as follows:
716 The run is described in the first byte. If the MSB is zero, then the next seven bits
717 are the quantity of bytes that follow that make up the run of value bytes. (see case 0)
719 If the MSB is set, bits 0-3 are the quantity's least significant 4 bits. If bit 5 is set,
720 then the quantity is further described in the next byte, where an additional 7 bits (4-10)
721 worth of quantity will be found. If the MSB of this byte is set, then an additional
722 7 bits (11-17) worth of quantity will be found in the next byte. This repeats until the MSB of
723 a quantity byte is zero, thus ending the run of quantity bytes.
725 Bits 5/6 of the first byte, describe the number of bytes in the value run following the quantity run.
726 These bits describe value runs of 1 to 4 bytes. And the quantity describe the number of value runs.
729 encodings are: (q = quantity, v = value, c = quantity continues)
731 case 0: [ 0 q6-q0 ] [ v7-v0 ] ... [ v7-v0 ]
732 case 1: [ 1 0 0 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ]
733 case 2: [ 1 0 1 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ]
734 case 3: [ 1 1 0 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ]
735 case 4: [ 1 1 1 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ]
739 decode_rle( unsigned char * dataPtr
, unsigned int * quantity
, unsigned int * depth
, unsigned char ** value
)
742 int i
, runlen
, runsize
;
745 mask
= dataPtr
[i
] & 0xF0;
748 runsize
= ((mask
& 0x60) >> 5) + 1;
749 runlen
= dataPtr
[i
++] & 0x0F;
755 mask
= dataPtr
[i
] & 0x80;
756 runlen
|= ((dataPtr
[i
++] & 0x7F) << shift
);
762 runsize
= dataPtr
[i
++];
767 *value
= &dataPtr
[i
];
776 unsigned long *p
, *endp
, *row
;
777 int col
, rowline
, rowlongs
;
778 register unsigned long mask
;
783 if ( vinfo
.v_depth
== 32 )
785 else if ( vinfo
.v_depth
== 16 )
790 rowline
= vinfo
.v_rowscanbytes
/ 4;
791 rowlongs
= vinfo
.v_rowbytes
/ 4;
793 p
= (unsigned long*) vinfo
.v_baseaddr
;
794 endp
= p
+ (rowlongs
* vinfo
.v_height
);
796 for (row
= p
; row
< endp
; row
+= rowlongs
) {
797 for (p
= &row
[0], col
= 0; col
< rowline
; col
++) {
798 *p
++ = (*p
>> 1) & mask
;
804 /* From user mode Libc - this ought to be in a library */
806 strnstr(const char * s
, const char * find
, size_t slen
)
811 if ((c
= *find
++) != '\0') {
815 if ((sc
= *s
++) == '\0' || slen
-- < 1)
820 } while (strncmp(s
, find
, len
) != 0);
827 * these routines are for converting a color into grayscale
828 * in 8-bit mode, if the active clut is different than the
829 * clut used to create the panic dialog, then we must convert to gray
833 make24bitcolor( unsigned int index
, const unsigned char * clut
)
835 unsigned int color24
= 0;
838 color24
|= clut
[i
+0] << 16;
839 color24
|= clut
[i
+1] << 8;
840 color24
|= clut
[i
+2];
847 findbestgray( unsigned int color24
)
849 unsigned int c24
, rel
, bestindex
=-1, bestgray
= -1;
850 unsigned char gray8
, c8
;
852 #define abs(v) ((v) > 0)?(v):-(v)
854 gray8
= color24togray8( color24
); /* convert the original color into grayscale */
856 for (i
=0; i
<CLUT_ENTRIES
; i
++) {
857 c24
= make24bitcolor( i
, active_clut
);
858 if ( (((c24
>>16)&0xff) != ((c24
>>8)&0xff)) || ((c24
>>8)&0xff) != (c24
& 0xff) )
859 continue; /* only match against grays */
861 c8
= c24
& 0xFF; /* isolate the gray */
863 /* find the gray with the smallest difference */
864 rel
= abs( gray8
- c8
);
865 if ( rel
< bestgray
) {
871 /* Did we fail to find any grays ? */
872 if ( bestindex
== -1 ) {
873 /* someday we should look for the best color match */
874 /* but for now just return the gray as the index */
875 /* at least there might be something readble on the display */
886 color24togray8( unsigned int color24
)
892 R
= (color24
& 0xFF0000) >> 16 ;
893 G
= (color24
& 0xFF00) >> 8 ;
894 B
= (color24
& 0xFF);
896 Gray
= (R
*30) + (G
*59) + (B
*11);
897 gray8
= (unsigned char) ((Gray
+ 50) / 100);
903 findIndexMatch( unsigned char index
)
905 static unsigned int last_in_index
= -1;
906 static unsigned char last_index
;
909 if ( index
== last_in_index
)
912 last_in_index
= index
;
913 sc
= make24bitcolor( index
, panic_dialog_clut
);
914 last_index
= findbestgray( sc
); /* find the nearest matching gray in the active clut */
920 isActiveClutOK( void )
923 int r
= 1; /* assume OK */
925 for (i
=0; i
<CLUT_ENTRIES
; i
++) {
926 if ( panic_dialog_clut
[i
] == active_clut
[i
] ) continue;