2 * Copyright (c) 2002-2006 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>
37 #include <machine/machlimits.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(const 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 const 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
,
56 unsigned int height
, int transparent
,
57 const unsigned char * dataPtr
);
59 static int panic_info_x
;
60 static int panic_info_y
;
62 static const unsigned char * active_clut
= NULL
; /* This is a copy of the active clut */
64 static boolean_t panicDialogDrawn
= FALSE
;
66 static const struct panicimage
* panic_dialog
= NULL
; /* the active panic dialog */
67 static const unsigned char * panic_dialog_data
= NULL
; /* where the image data starts */
68 static const unsigned char * panic_dialog_clut
= NULL
; /* where the clut used for the image starts */
70 static const unsigned char *curr_image_ptr
; /* If NULL, the default panic
72 static unsigned int curr_image_size
= 0;
75 #define FONT_HEIGHT 16
76 static unsigned short rendered_font
[FONT_HEIGHT
][FONT_WIDTH
];
78 #define VERSIONBUF_LEN 20
79 static char versionbuf
[VERSIONBUF_LEN
]; /* ####.###~###\0 */
81 #define isdigit(d) ((d) >= '0' && (d) <= '9')
83 #define CLUT_ENTRIES 256
84 #define CLUT_SIZE (CLUT_ENTRIES * 3)
88 * This routine sets up the default panic dialog
91 extern unsigned char iso_font
[];
92 extern const char version
[];
95 panic_ui_initialize(const unsigned char * system_clut
)
97 char vstr
[VERSIONBUF_LEN
];
99 panic_dialog_set_image( NULL
, 0 );
101 active_clut
= system_clut
;
103 strlcpy(vstr
, "custom", VERSIONBUF_LEN
);
105 /* Convert xnu-####.###.obj~### into ####.###~### */
108 const char *versionpos
= strnstr(version
, "xnu-", VERSIONBUF_LEN
);
115 for (i
= 0, len
= 4; len
< VERSIONBUF_LEN
; len
++) {
116 if (isdigit(versionpos
[len
]) || versionpos
[len
] == '.') { /* extract ####.###. */
117 vstr
[i
++] = versionpos
[len
];
123 if ( versionpos
[len
-1] == '.' ) /* remove trailing period if present */
126 for (; len
< VERSIONBUF_LEN
; len
++) { /* skip to next digit if present */
127 if ( !isdigit(versionpos
[len
]) )
132 if ( versionpos
[len
-1] == '~' ) { /* extract ~### if present */
133 vstr
[i
++] = versionpos
[len
-1];
134 for (; len
< VERSIONBUF_LEN
; len
++) { /* extract ### */
135 if ( isdigit(versionpos
[len
]) ) {
136 vstr
[i
++] = versionpos
[len
];
147 strlcpy(versionbuf
, vstr
, VERSIONBUF_LEN
);
153 panic_dialog_test( void )
155 boolean_t o_panicDialogDrawn
= panicDialogDrawn
;
156 boolean_t o_panicDialogDesired
= panicDialogDesired
;
157 unsigned int o_logPanicDataToScreen
= logPanicDataToScreen
;
158 unsigned long o_panic_caller
= panic_caller
;
159 unsigned int o_panicDebugging
= panicDebugging
;
162 panicDebugging
= TRUE
;
163 panic_caller
= (unsigned long)(char *)__builtin_return_address(0);
164 logPanicDataToScreen
= FALSE
;
165 panicDialogDesired
= TRUE
;
166 panicDialogDrawn
= FALSE
;
170 panicDebugging
= o_panicDebugging
;
171 panic_caller
= o_panic_caller
;
172 logPanicDataToScreen
= o_logPanicDataToScreen
;
173 panicDialogDesired
= o_panicDialogDesired
;
174 panicDialogDrawn
= o_panicDialogDrawn
;
179 draw_panic_dialog( void )
181 if (!panicDialogDrawn
&& panicDialogDesired
) {
182 if ( !logPanicDataToScreen
) {
184 int count
, nibble
, indx
;
185 struct ether_addr kdp_mac_addr
;
186 unsigned int panic_dialog_count
, ip_addr
;
187 char panic_num_chars
[13+8+1], mac_addr_chars
[17+1], ip_addr_chars
[15+1];
191 } panic_dialog_info
[3];
194 /* dim the screen 50% before putting up panic dialog */
197 /* set up to draw background box */
198 /* by locating where the upper left corner is placed */
200 pd_x
= (vinfo
.v_width
/2) - panic_dialog
->pd_width
/2;
201 pd_y
= (vinfo
.v_height
/2) - panic_dialog
->pd_height
/2;
203 /* draw panic dialog at pd_x/pd_y */
204 panic_blit_rect(pd_x
, pd_y
, panic_dialog
->pd_width
,
205 panic_dialog
->pd_height
, 0,
208 panic_dialog_count
= 0; /* number of info items to display at the bottom of dialog */
210 if (panicDebugging
) {
216 * don't display the panic caller if it is 0
220 if ( panic_caller
!= 0 ) {
221 /* Calculate the pixels need to generate the panic number */
222 panic_dialog_info
[panic_dialog_count
].pixels
= 0;
224 for ( indx
=1, count
=0; count
< 13; count
++ ) {
225 if ( versionbuf
[count
] == '\0' )
228 panic_num_chars
[indx
++] = versionbuf
[count
];
229 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( versionbuf
[count
] );
232 panic_num_chars
[indx
++] = ':';
233 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( ':' );
235 for ( count
=8; count
!= 0; count
-- ) {
236 nibble
= (panic_caller
>> ((count
-1)<<2)) &0xF;
237 panic_num_chars
[indx
++] = nibble
;
238 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( nibble
);
241 panic_num_chars
[0] = indx
;
242 panic_dialog_info
[panic_dialog_count
].chars
= panic_num_chars
;
243 panic_dialog_count
++;
249 * if the mac address is not available, then use ff:ff:ff:ff:ff:ff
253 kdp_mac_addr
= kdp_get_mac_addr();
255 /* If no mac_addr has been set, then force to -1 */
256 if( ! (kdp_mac_addr
.ether_addr_octet
[0] || kdp_mac_addr
.ether_addr_octet
[1] || kdp_mac_addr
.ether_addr_octet
[2]
257 || kdp_mac_addr
.ether_addr_octet
[3] || kdp_mac_addr
.ether_addr_octet
[4] || kdp_mac_addr
.ether_addr_octet
[5])) {
258 for (count
= 0; count
< 6; count
++ )
259 kdp_mac_addr
.ether_addr_octet
[count
] = -1;
262 panic_dialog_info
[panic_dialog_count
].pixels
= 0;
264 for (indx
=1, count
=0; count
< 6; count
++ ) {
265 nibble
= (kdp_mac_addr
.ether_addr_octet
[count
] & 0xf0) >> 4;
266 mac_addr_chars
[indx
++] = nibble
;
267 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( nibble
);
269 nibble
= kdp_mac_addr
.ether_addr_octet
[count
] & 0xf;
270 mac_addr_chars
[indx
++] = nibble
;
271 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( nibble
);
274 mac_addr_chars
[indx
++] = ':';
275 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( ':' );
279 mac_addr_chars
[0] = indx
;
280 panic_dialog_info
[panic_dialog_count
].chars
= mac_addr_chars
;
281 panic_dialog_count
++;
286 * do not display the ip addresses if the machine isn't attachable.
287 * there's no sense in possibly confusing people.
290 if ( (ip_addr
= (unsigned int) ntohl(kdp_get_ip_address())) != 0 ) {
293 panic_dialog_info
[panic_dialog_count
].pixels
= 0;
295 for ( indx
=1, count
=0; count
< 4; count
++ ) {
296 nibble
= (ip_addr
& 0xff000000 ) >> 24;
298 d3
= (nibble
% 10) ; nibble
= nibble
/ 10;
299 d2
= (nibble
% 10) ; nibble
= nibble
/ 10;
303 ip_addr_chars
[indx
++] = d1
;
304 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( d1
);
307 ip_addr_chars
[indx
++] = d2
;
308 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( d2
);
310 ip_addr_chars
[indx
++] = d3
;
311 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( d3
);
314 ip_addr_chars
[indx
++] = '.';
315 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( '.' );
319 ip_addr
= ip_addr
<< 8;
322 ip_addr_chars
[0] = indx
;
323 panic_dialog_info
[panic_dialog_count
].chars
= ip_addr_chars
;
324 panic_dialog_count
++;
328 /* vertical alignment for information to be displayed */
329 panic_info_y
= (vinfo
.v_height
/2) + panic_dialog
->pd_height
/2 - (panic_dialog
->pd_info_height
);
331 /* blit out all the information we gathered */
333 switch ( panic_dialog_count
) {
334 case 1 : /* one item is centered */
335 panic_info_x
= (vinfo
.v_width
/2) - (panic_dialog_info
[0].pixels
/2);
336 for (indx
=1; indx
< panic_dialog_info
[0].chars
[0]; indx
++)
337 blit_digit(panic_dialog_info
[0].chars
[indx
]);
341 case 2 : /* left centered and right centered */
342 x1
= ((panic_dialog
->pd_width
/2) - panic_dialog_info
[0].pixels
)/2;
343 panic_info_x
= ((vinfo
.v_width
/2) - (panic_dialog
->pd_width
/2)) + x1
;
345 for (indx
=1; indx
< panic_dialog_info
[0].chars
[0]; indx
++)
346 blit_digit(panic_dialog_info
[0].chars
[indx
]);
348 x2
= ((panic_dialog
->pd_width
/2) - panic_dialog_info
[1].pixels
)/2;
349 panic_info_x
= (vinfo
.v_width
/2) + x2
;
351 for (indx
=1; indx
< panic_dialog_info
[1].chars
[0]; indx
++)
352 blit_digit(panic_dialog_info
[1].chars
[indx
]);
356 case 3 : /* left centered, middle and right centered */
357 x1
= ((panic_dialog
->pd_width
/2) - panic_dialog_info
[0].pixels
- (panic_dialog_info
[1].pixels
/2))/2;
358 panic_info_x
= ((vinfo
.v_width
/2) - (panic_dialog
->pd_width
/2)) + x1
;
360 for (indx
=1; indx
< panic_dialog_info
[0].chars
[0]; indx
++)
361 blit_digit(panic_dialog_info
[0].chars
[indx
]);
363 panic_info_x
= (vinfo
.v_width
/2) - (panic_dialog_info
[1].pixels
/2);
365 for (indx
=1; indx
< panic_dialog_info
[1].chars
[0]; indx
++)
366 blit_digit(panic_dialog_info
[1].chars
[indx
]);
368 x2
= ((panic_dialog
->pd_width
/2) - panic_dialog_info
[2].pixels
- (panic_dialog_info
[1].pixels
/2))/2;
369 panic_info_x
= (vinfo
.v_width
/2) + x2
+ (panic_dialog_info
[1].pixels
/2);
371 for (indx
=1; indx
< panic_dialog_info
[2].chars
[0]; indx
++)
372 blit_digit(panic_dialog_info
[2].chars
[indx
]);
376 default : /* nothing */
380 } /* if panic_deugging */
381 } /* if ! logPanicDataToScreen */
382 } /* if ! panicDialogDrawn && ! panicDialogDesired */
384 panicDialogDrawn
= TRUE
;
385 panicDialogDesired
= FALSE
;
390 * This routine installs a new panic dialog
391 * If ptr is NULL, then the default "built-in" panic dialog will be installed.
392 * note: It is the caller that must take care of deallocating memory used for the previous panic dialog
396 panic_dialog_set_image( const unsigned char * ptr
, unsigned int size
)
399 unsigned int newsize
;
400 const struct panicimage
* newimage
;
402 /* if ptr is NULL, restore panic image to built-in default */
404 newimage
= &panic_dialog_default
;
405 newsize
= sizeof(struct panicimage
) + newimage
->pd_dataSize
;
408 newimage
= (const struct panicimage
*)ptr
;
412 if ( (error
= panic_dialog_verify( newimage
, newsize
)) )
415 panic_dialog
= newimage
;
416 panic_dialog_data
= &panic_dialog
->data
[0];
417 panic_dialog_clut
= &panic_dialog
->data
[panic_dialog
->pd_dataSize
-CLUT_SIZE
];
419 curr_image_ptr
= ptr
;
420 curr_image_size
= size
;
427 * This routines returns the current address of the panic dialog
428 * If the default panic dialog is active, then *ptr will be NULL
432 panic_dialog_get_image(const unsigned char ** ptr
, unsigned int * size
)
434 *ptr
= curr_image_ptr
;
435 *size
= curr_image_size
;
440 * This routine verifies the panic dialog image is valid.
444 panic_dialog_verify( const struct panicimage
* newimage
, unsigned int size
)
448 if ( size
< (sizeof(struct panicimage
) + newimage
->pd_dataSize
) )
451 if ( newimage
->pd_tag
!= 'RNMp' )
454 size
= newimage
->pd_dataSize
-CLUT_SIZE
;
455 for (sum
=0,i
=0; i
<size
; i
++) {
456 sum
+= newimage
->data
[i
];
460 if ( sum
!= newimage
->pd_sum
)
468 * Service Routines for managing the panic dialog
472 static const struct rendered_num
* find_rendered_digit( int digit
);
473 static void panic_blit_rect_8(unsigned int x
, unsigned int y
,
474 unsigned int width
, unsigned int height
,
475 int transparent
, const unsigned char *dataPtr
);
476 static void panic_blit_rect_16(unsigned int x
, unsigned int y
,
477 unsigned int width
, unsigned int height
,
478 int transparent
, const unsigned char *dataPtr
);
479 static void panic_blit_rect_32(unsigned int x
, unsigned int y
,
480 unsigned int width
, unsigned int height
,
481 int transparent
, const unsigned char *dataPtr
);
482 static int decode_rle(const unsigned char *dataPtr
,
483 unsigned int *quantity
, unsigned int *depth
,
484 const unsigned char **value
);
487 /* Utilities to convert 8 bit/gray */
488 static unsigned int make24bitcolor( unsigned int index
, const unsigned char * clut
);
489 static unsigned char findIndexMatch( unsigned char index
);
490 static unsigned char color24togray8( unsigned int color24
);
491 static unsigned char findbestgray( unsigned int color24
);
492 static int isActiveClutOK( void );
495 pixels_needed_to_blit_digit(__unused
int digit
)
501 static const struct rendered_num
*
502 find_rendered_digit( int digit
)
504 //extern unsigned char iso_font[];
505 const struct rendered_num
*digitPtr
;
514 digitPtr
= (const struct rendered_num
*) &iso_font
[digit
* 16];
520 blit_digit( int digit
)
522 const unsigned char *raw_data
=
523 (const unsigned char *)find_rendered_digit(digit
);
524 unsigned width
= FONT_WIDTH
, height
= FONT_HEIGHT
;
527 for (row
=0; row
<FONT_HEIGHT
; row
++) {
531 bits
= raw_data
[row
];
532 for( j
=FONT_WIDTH
-1; j
>=0; j
--) {
535 rendered_font
[row
][j
] = OSSwapBigToHostInt16(0x0100 | panic_dialog
->pd_info_color
[0]);
537 rendered_font
[row
][j
] = OSSwapBigToHostInt16(0x0100 | panic_dialog
->pd_info_color
[1]);
542 panic_blit_rect( panic_info_x
, panic_info_y
, width
, height
, 255, (unsigned char *) rendered_font
);
543 panic_info_x
+= width
;
548 panic_blit_rect(unsigned int x
, unsigned int y
, unsigned int width
,
549 unsigned int height
, int transparent
,
550 const unsigned char *dataPtr
)
555 switch( vinfo
.v_depth
) {
557 panic_blit_rect_8( x
, y
, width
, height
, transparent
, dataPtr
);
560 panic_blit_rect_16( x
, y
, width
, height
, transparent
, dataPtr
);
563 panic_blit_rect_32( x
, y
, width
, height
, transparent
, dataPtr
);
569 * panic_blit_rect_8 decodes the RLE encoded image data on the fly, looks up the
570 * color by indexing into the clut, or attempts to find the best index.
574 panic_blit_rect_8(unsigned int x
, unsigned int y
, unsigned int width
,
575 unsigned int height
, __unused
int transparent
,
576 const unsigned char * dataPtr
)
578 volatile unsigned char * dst
;
579 unsigned int line
, col
, i
;
580 static int clutOK
= -1;
581 unsigned int data
, quantity
, depth
;
582 const unsigned char *value
;
586 clutOK
= isActiveClutOK();
588 dst
= (volatile unsigned char *) (vinfo
.v_baseaddr
+
589 (y
* vinfo
.v_rowbytes
) +
595 for( line
= 0; line
< height
; line
++) {
596 for( col
= 0; col
< width
; col
++) {
599 dataPtr
+= decode_rle(dataPtr
, &quantity
, &depth
, &value
);
606 data
= findIndexMatch( value
[i
++] );
616 dst
= (volatile unsigned char *) (((int)dst
) + vinfo
.v_rowbytes
);
621 * panic_blit_rect_16 decodes the RLE encoded image data on the fly, looks up the
622 * color by indexing into the clut, uses the top 5 bits to fill in each of the three
623 * pixel values (RGB) and writes each pixel to the screen.
627 panic_blit_rect_16(unsigned int x
, unsigned int y
, unsigned int width
,
628 unsigned int height
, __unused
int transparent
,
629 const unsigned char *dataPtr
)
632 volatile unsigned short * dst
;
633 unsigned int line
, col
, i
;
634 unsigned int quantity
, index
, data
, depth
;
635 const unsigned char *value
;
637 dst
= (volatile unsigned short *) (vinfo
.v_baseaddr
+
638 (y
* vinfo
.v_rowbytes
) +
644 for( line
= 0; line
< height
; line
++) {
645 for( col
= 0; col
< width
; col
++) {
648 dataPtr
+= decode_rle(dataPtr
, &quantity
, &depth
, &value
);
652 index
= value
[i
++] * 3;
654 data
= ( (unsigned short) (0xf8 & (panic_dialog_clut
[index
+ 0])) << 7)
655 | ( (unsigned short) (0xf8 & (panic_dialog_clut
[index
+ 1])) << 2)
656 | ( (unsigned short) (0xf8 & (panic_dialog_clut
[index
+ 2])) >> 3);
666 dst
= (volatile unsigned short *) (((int)dst
) + vinfo
.v_rowbytes
);
671 * panic_blit_rect_32 decodes the RLE encoded image data on the fly, and fills
672 * in each of the three pixel values from the clut (RGB) for each pixel and
673 * writes it to the screen.
677 panic_blit_rect_32(unsigned int x
, unsigned int y
, unsigned int width
,
678 unsigned int height
, __unused
int transparent
,
679 const unsigned char *dataPtr
)
681 volatile unsigned int * dst
;
682 unsigned int line
, col
, i
;
683 unsigned int quantity
, index
, data
, depth
;
684 const unsigned char *value
;
687 dst
= (volatile unsigned int *) (vinfo
.v_baseaddr
+
688 (y
* vinfo
.v_rowbytes
) +
694 for( line
= 0; line
< height
; line
++) {
695 for( col
= 0; col
< width
; col
++) {
698 dataPtr
+= decode_rle(dataPtr
, &quantity
, &depth
, &value
);
702 index
= value
[i
++] * 3;
704 data
= ( (unsigned int) panic_dialog_clut
[index
+ 0] << 16)
705 | ( (unsigned int) panic_dialog_clut
[index
+ 1] << 8)
706 | ( (unsigned int) panic_dialog_clut
[index
+ 2]);
716 dst
= (volatile unsigned int *) (((int)dst
) + vinfo
.v_rowbytes
);
721 decode_rle decodes a single quantity/value run of a "modified-RLE" encoded
722 image. The encoding works as follows:
724 The run is described in the first byte. If the MSB is zero, then the next seven bits
725 are the quantity of bytes that follow that make up the run of value bytes. (see case 0)
727 If the MSB is set, bits 0-3 are the quantity's least significant 4 bits. If bit 5 is set,
728 then the quantity is further described in the next byte, where an additional 7 bits (4-10)
729 worth of quantity will be found. If the MSB of this byte is set, then an additional
730 7 bits (11-17) worth of quantity will be found in the next byte. This repeats until the MSB of
731 a quantity byte is zero, thus ending the run of quantity bytes.
733 Bits 5/6 of the first byte, describe the number of bytes in the value run following the quantity run.
734 These bits describe value runs of 1 to 4 bytes. And the quantity describe the number of value runs.
737 encodings are: (q = quantity, v = value, c = quantity continues)
739 case 0: [ 0 q6-q0 ] [ v7-v0 ] ... [ v7-v0 ]
740 case 1: [ 1 0 0 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ]
741 case 2: [ 1 0 1 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ]
742 case 3: [ 1 1 0 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ]
743 case 4: [ 1 1 1 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ]
747 decode_rle(const unsigned char *dataPtr
, unsigned int *quantity
,
748 unsigned int *depth
, const unsigned char **value
)
751 int i
, runlen
, runsize
;
754 mask
= dataPtr
[i
] & 0xF0;
757 runsize
= ((mask
& 0x60) >> 5) + 1;
758 runlen
= dataPtr
[i
++] & 0x0F;
764 mask
= dataPtr
[i
] & 0x80;
765 runlen
|= ((dataPtr
[i
++] & 0x7F) << shift
);
771 runsize
= dataPtr
[i
++];
776 *value
= &dataPtr
[i
];
785 unsigned long *p
, *endp
, *row
;
786 int col
, rowline
, rowlongs
;
787 register unsigned long mask
;
792 if ( vinfo
.v_depth
== 32 )
794 else if ( vinfo
.v_depth
== 16 )
799 rowline
= vinfo
.v_rowscanbytes
/ 4;
800 rowlongs
= vinfo
.v_rowbytes
/ 4;
802 p
= (unsigned long*) vinfo
.v_baseaddr
;
803 endp
= p
+ (rowlongs
* vinfo
.v_height
);
805 for (row
= p
; row
< endp
; row
+= rowlongs
) {
806 for (p
= &row
[0], col
= 0; col
< rowline
; col
++) {
807 *p
= (*p
>> 1) & mask
;
814 /* From user mode Libc - this ought to be in a library */
816 strnstr(const char * s
, const char * find
, size_t slen
)
821 if ((c
= *find
++) != '\0') {
825 if ((sc
= *s
++) == '\0' || slen
-- < 1)
830 } while (strncmp(s
, find
, len
) != 0);
837 * these routines are for converting a color into grayscale
838 * in 8-bit mode, if the active clut is different than the
839 * clut used to create the panic dialog, then we must convert to gray
843 make24bitcolor( unsigned int index
, const unsigned char * clut
)
845 unsigned int color24
= 0;
848 color24
|= clut
[i
+0] << 16;
849 color24
|= clut
[i
+1] << 8;
850 color24
|= clut
[i
+2];
857 findbestgray( unsigned int color24
)
859 unsigned int c24
, rel
, bestindex
=-1, bestgray
= -1;
860 unsigned char gray8
, c8
;
862 #define abs(v) ((v) > 0)?(v):-(v)
864 gray8
= color24togray8( color24
); /* convert the original color into grayscale */
866 for (i
=0; i
<CLUT_ENTRIES
; i
++) {
867 c24
= make24bitcolor( i
, active_clut
);
868 if ( (((c24
>>16)&0xff) != ((c24
>>8)&0xff)) || ((c24
>>8)&0xff) != (c24
& 0xff) )
869 continue; /* only match against grays */
871 c8
= c24
& 0xFF; /* isolate the gray */
873 /* find the gray with the smallest difference */
874 rel
= abs( gray8
- c8
);
875 if ( rel
< bestgray
) {
881 /* Did we fail to find any grays ? */
882 if (ULONG_MAX
== bestindex
) {
883 /* someday we should look for the best color match */
884 /* but for now just return the gray as the index */
885 /* at least there might be something readble on the display */
896 color24togray8( unsigned int color24
)
902 R
= (color24
& 0xFF0000) >> 16 ;
903 G
= (color24
& 0xFF00) >> 8 ;
904 B
= (color24
& 0xFF);
906 Gray
= (R
*30) + (G
*59) + (B
*11);
907 gray8
= (unsigned char) ((Gray
+ 50) / 100);
913 findIndexMatch( unsigned char index
)
915 static unsigned int last_in_index
= -1;
916 static unsigned char last_index
;
919 if ( index
== last_in_index
)
922 last_in_index
= index
;
923 sc
= make24bitcolor( index
, panic_dialog_clut
);
924 last_index
= findbestgray( sc
); /* find the nearest matching gray in the active clut */
930 isActiveClutOK( void )
933 int r
= 1; /* assume OK */
935 for (i
=0; i
<CLUT_ENTRIES
; i
++) {
936 if ( panic_dialog_clut
[i
] == active_clut
[i
] ) continue;