2 * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
24 #include <console/video_console.h>
25 #include <libkern/OSByteOrder.h>
26 #include <kdp/kdp_udp.h>
27 #include <kern/debug.h>
28 #include <mach/mach_time.h>
29 #include <sys/errno.h>
33 extern struct vc_info vinfo
;
34 extern boolean_t panicDialogDesired
;
36 #include "panic_image.c"
38 void panic_ui_initialize(const unsigned char * system_clut
);
39 int panic_dialog_set_image( const unsigned char * ptr
, unsigned int size
);
40 void panic_dialog_get_image( unsigned char ** ptr
, unsigned int * size
);
41 void draw_panic_dialog( void );
42 void panic_dialog_test( void );
44 static int panic_dialog_verify( const struct panicimage
* data
, unsigned int size
);
45 static int pixels_needed_to_blit_digit( int digit
);
46 static void blit_digit( int digit
);
47 static char * strnstr(const char * s
, const char * find
, size_t slen
);
48 static void dim_screen(void);
49 static void panic_blit_rect(unsigned int x
, unsigned int y
, unsigned int width
, unsigned int height
,
50 int transparent
, unsigned char * dataPtr
);
52 static int panic_info_x
;
53 static int panic_info_y
;
55 static const unsigned char * active_clut
= NULL
; /* This is a copy of the active clut */
57 static boolean_t panicDialogDrawn
= FALSE
;
59 static const struct panicimage
* panic_dialog
= NULL
; /* the active panic dialog */
60 static const unsigned char * panic_dialog_data
= NULL
; /* where the image data starts */
61 static const unsigned char * panic_dialog_clut
= NULL
; /* where the clut used for the image starts */
63 static unsigned char * curr_image_ptr
= NULL
; /* If NULL, the default panic dialog is active */
64 static unsigned int curr_image_size
= 0;
67 #define FONT_HEIGHT 16
68 static unsigned short rendered_font
[FONT_HEIGHT
][FONT_WIDTH
];
70 static char versionbuf
[20]; /* ####.###~###\0 */
72 #define isdigit(d) ((d) >= '0' && (d) <= '9')
74 #define CLUT_ENTRIES 256
75 #define CLUT_SIZE (CLUT_ENTRIES * 3)
79 * This routine sets up the default panic dialog
82 extern unsigned char iso_font
[];
83 extern const char version
[];
84 extern unsigned int panic_caller
;
87 panic_ui_initialize(const unsigned char * system_clut
)
92 panic_dialog_set_image( NULL
, 0 );
94 active_clut
= system_clut
;
96 strcpy(vstr
, "custom");
98 /* Convert xnu-####.###.obj~### into ####.###~### */
101 char * versionpos
= strnstr(version
, "xnu-", 20);
108 for (i
=0,len
=4;len
<20;len
++) {
109 if (isdigit(versionpos
[len
]) || versionpos
[len
] == '.') { /* extract ####.###. */
110 vstr
[i
++] = versionpos
[len
];
116 if ( versionpos
[len
-1] == '.' ) /* remove trailing period if present */
119 for (;len
<20;len
++) { /* skip to next digit if present */
120 if ( !isdigit(versionpos
[len
]) )
125 if ( versionpos
[len
-1] == '~' ) { /* extract ~### if present */
126 vstr
[i
++] = versionpos
[len
-1];
127 for (;len
<20;len
++) { /* extract ### */
128 if ( isdigit(versionpos
[len
]) ) {
129 vstr
[i
++] = versionpos
[len
];
140 strcpy(versionbuf
, vstr
);
146 panic_dialog_test( void )
148 boolean_t o_panicDialogDrawn
= panicDialogDrawn
;
149 boolean_t o_panicDialogDesired
= panicDialogDesired
;
150 unsigned int o_logPanicDataToScreen
= logPanicDataToScreen
;
151 unsigned int o_panic_caller
= panic_caller
;
152 unsigned int o_panicDebugging
= panicDebugging
;
155 panicDebugging
= TRUE
;
156 panic_caller
= (unsigned int) __builtin_return_address(0);
157 logPanicDataToScreen
= FALSE
;
158 panicDialogDesired
= TRUE
;
159 panicDialogDrawn
= FALSE
;
163 panicDebugging
= o_panicDebugging
;
164 panic_caller
= o_panic_caller
;
165 logPanicDataToScreen
= o_logPanicDataToScreen
;
166 panicDialogDesired
= o_panicDialogDesired
;
167 panicDialogDrawn
= o_panicDialogDrawn
;
172 draw_panic_dialog( void )
174 if (!panicDialogDrawn
&& panicDialogDesired
) {
175 if ( !logPanicDataToScreen
) {
177 int count
, nibble
, indx
;
178 struct ether_addr kdp_mac_addr
;
179 unsigned int panic_dialog_count
, ip_addr
;
180 char panic_num_chars
[13+8+1], mac_addr_chars
[17+1], ip_addr_chars
[15+1];
184 } panic_dialog_info
[3];
187 /* dim the screen 50% before putting up panic dialog */
190 /* set up to draw background box */
191 /* by locating where the upper left corner is placed */
193 pd_x
= (vinfo
.v_width
/2) - panic_dialog
->pd_width
/2;
194 pd_y
= (vinfo
.v_height
/2) - panic_dialog
->pd_height
/2;
196 /* draw panic dialog at pd_x/pd_y */
197 panic_blit_rect( pd_x
, pd_y
, panic_dialog
->pd_width
, panic_dialog
->pd_height
,
198 0, (unsigned char*) panic_dialog_data
);
200 panic_dialog_count
= 0; /* number of info items to display at the bottom of dialog */
202 if (panicDebugging
) {
208 * don't display the panic caller if it is 0
212 if ( panic_caller
!= 0 ) {
213 /* Calculate the pixels need to generate the panic number */
214 panic_dialog_info
[panic_dialog_count
].pixels
= 0;
216 for ( indx
=1, count
=0; count
< 13; count
++ ) {
217 if ( versionbuf
[count
] == '\0' )
220 panic_num_chars
[indx
++] = versionbuf
[count
];
221 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( versionbuf
[count
] );
224 panic_num_chars
[indx
++] = ':';
225 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( ':' );
227 for ( count
=8; count
!= 0; count
-- ) {
228 nibble
= (panic_caller
>> ((count
-1)<<2)) &0xF;
229 panic_num_chars
[indx
++] = nibble
;
230 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( nibble
);
233 panic_num_chars
[0] = indx
;
234 panic_dialog_info
[panic_dialog_count
].chars
= panic_num_chars
;
235 panic_dialog_count
++;
241 * if the mac address is not available, then use ff:ff:ff:ff:ff:ff
245 kdp_mac_addr
= kdp_get_mac_addr();
247 /* If no mac_addr has been set, then force to -1 */
248 if( ! (kdp_mac_addr
.ether_addr_octet
[0] || kdp_mac_addr
.ether_addr_octet
[1] || kdp_mac_addr
.ether_addr_octet
[2]
249 || kdp_mac_addr
.ether_addr_octet
[3] || kdp_mac_addr
.ether_addr_octet
[4] || kdp_mac_addr
.ether_addr_octet
[5])) {
250 for (count
= 0; count
< 6; count
++ )
251 kdp_mac_addr
.ether_addr_octet
[count
] = -1;
254 panic_dialog_info
[panic_dialog_count
].pixels
= 0;
256 for (indx
=1, count
=0; count
< 6; count
++ ) {
257 nibble
= (kdp_mac_addr
.ether_addr_octet
[count
] & 0xf0) >> 4;
258 mac_addr_chars
[indx
++] = nibble
;
259 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( nibble
);
261 nibble
= kdp_mac_addr
.ether_addr_octet
[count
] & 0xf;
262 mac_addr_chars
[indx
++] = nibble
;
263 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( nibble
);
266 mac_addr_chars
[indx
++] = ':';
267 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( ':' );
271 mac_addr_chars
[0] = indx
;
272 panic_dialog_info
[panic_dialog_count
].chars
= mac_addr_chars
;
273 panic_dialog_count
++;
278 * do not display the ip addresses if the machine isn't attachable.
279 * there's no sense in possibly confusing people.
282 if ( (ip_addr
= (unsigned int) ntohl(kdp_get_ip_address())) != 0 ) {
285 panic_dialog_info
[panic_dialog_count
].pixels
= 0;
287 for ( indx
=1, count
=0; count
< 4; count
++ ) {
288 nibble
= (ip_addr
& 0xff000000 ) >> 24;
290 d3
= (nibble
% 10) ; nibble
= nibble
/ 10;
291 d2
= (nibble
% 10) ; nibble
= nibble
/ 10;
295 ip_addr_chars
[indx
++] = d1
;
296 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( d1
);
299 ip_addr_chars
[indx
++] = d2
;
300 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( d2
);
302 ip_addr_chars
[indx
++] = d3
;
303 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( d3
);
306 ip_addr_chars
[indx
++] = '.';
307 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( '.' );
311 ip_addr
= ip_addr
<< 8;
314 ip_addr_chars
[0] = indx
;
315 panic_dialog_info
[panic_dialog_count
].chars
= ip_addr_chars
;
316 panic_dialog_count
++;
320 /* vertical alignment for information to be displayed */
321 panic_info_y
= (vinfo
.v_height
/2) + panic_dialog
->pd_height
/2 - (panic_dialog
->pd_info_height
);
323 /* blit out all the information we gathered */
325 switch ( panic_dialog_count
) {
326 case 1 : /* one item is centered */
327 panic_info_x
= (vinfo
.v_width
/2) - (panic_dialog_info
[0].pixels
/2);
328 for (indx
=1; indx
< panic_dialog_info
[0].chars
[0]; indx
++)
329 blit_digit(panic_dialog_info
[0].chars
[indx
]);
333 case 2 : /* left centered and right centered */
334 x1
= ((panic_dialog
->pd_width
/2) - panic_dialog_info
[0].pixels
)/2;
335 panic_info_x
= ((vinfo
.v_width
/2) - (panic_dialog
->pd_width
/2)) + x1
;
337 for (indx
=1; indx
< panic_dialog_info
[0].chars
[0]; indx
++)
338 blit_digit(panic_dialog_info
[0].chars
[indx
]);
340 x2
= ((panic_dialog
->pd_width
/2) - panic_dialog_info
[1].pixels
)/2;
341 panic_info_x
= (vinfo
.v_width
/2) + x2
;
343 for (indx
=1; indx
< panic_dialog_info
[1].chars
[0]; indx
++)
344 blit_digit(panic_dialog_info
[1].chars
[indx
]);
348 case 3 : /* left centered, middle and right centered */
349 x1
= ((panic_dialog
->pd_width
/2) - panic_dialog_info
[0].pixels
- (panic_dialog_info
[1].pixels
/2))/2;
350 panic_info_x
= ((vinfo
.v_width
/2) - (panic_dialog
->pd_width
/2)) + x1
;
352 for (indx
=1; indx
< panic_dialog_info
[0].chars
[0]; indx
++)
353 blit_digit(panic_dialog_info
[0].chars
[indx
]);
355 panic_info_x
= (vinfo
.v_width
/2) - (panic_dialog_info
[1].pixels
/2);
357 for (indx
=1; indx
< panic_dialog_info
[1].chars
[0]; indx
++)
358 blit_digit(panic_dialog_info
[1].chars
[indx
]);
360 x2
= ((panic_dialog
->pd_width
/2) - panic_dialog_info
[2].pixels
- (panic_dialog_info
[1].pixels
/2))/2;
361 panic_info_x
= (vinfo
.v_width
/2) + x2
+ (panic_dialog_info
[1].pixels
/2);
363 for (indx
=1; indx
< panic_dialog_info
[2].chars
[0]; indx
++)
364 blit_digit(panic_dialog_info
[2].chars
[indx
]);
368 default : /* nothing */
372 } /* if panic_deugging */
373 } /* if ! logPanicDataToScreen */
374 } /* if ! panicDialogDrawn && ! panicDialogDesired */
376 panicDialogDrawn
= TRUE
;
377 panicDialogDesired
= FALSE
;
382 * This routine installs a new panic dialog
383 * If ptr is NULL, then the default "built-in" panic dialog will be installed.
384 * note: It is the caller that must take care of deallocating memory used for the previous panic dialog
388 panic_dialog_set_image( const unsigned char * ptr
, unsigned int size
)
391 unsigned int newsize
;
392 const struct panicimage
* newimage
;
394 /* if ptr is NULL, restore panic image to built-in default */
396 newimage
= &panic_dialog_default
;
397 newsize
= sizeof(struct panicimage
) + newimage
->pd_dataSize
;
400 newimage
= (struct panicimage
*) ptr
;
404 if ( (error
= panic_dialog_verify( newimage
, newsize
)) )
407 panic_dialog
= newimage
;
408 panic_dialog_data
= &panic_dialog
->data
[0];
409 panic_dialog_clut
= &panic_dialog
->data
[panic_dialog
->pd_dataSize
-CLUT_SIZE
];
411 curr_image_ptr
= (unsigned char *) ptr
;
412 curr_image_size
= size
;
419 * This routines returns the current address of the panic dialog
420 * If the default panic dialog is active, then *ptr will be NULL
424 panic_dialog_get_image( unsigned char ** ptr
, unsigned int * size
)
426 *ptr
= curr_image_ptr
;
427 *size
= curr_image_size
;
432 * This routine verifies the panic dialog image is valid.
436 panic_dialog_verify( const struct panicimage
* newimage
, unsigned int size
)
440 if ( size
< (sizeof(struct panicimage
) + newimage
->pd_dataSize
) )
443 if ( newimage
->pd_tag
!= 'RNMp' )
446 size
= newimage
->pd_dataSize
-CLUT_SIZE
;
447 for (sum
=0,i
=0; i
<size
; i
++) {
448 sum
+= newimage
->data
[i
];
452 if ( sum
!= newimage
->pd_sum
)
460 * Service Routines for managing the panic dialog
464 static const struct rendered_num
* find_rendered_digit( int digit
);
465 static void panic_blit_rect_8( unsigned int x
, unsigned int y
, unsigned int width
, unsigned int height
,
466 int transparent
, unsigned char * dataPtr
);
467 static void panic_blit_rect_16( unsigned int x
, unsigned int y
, unsigned int width
, unsigned int height
,
468 int transparent
, unsigned char * dataPtr
);
469 static void panic_blit_rect_32( unsigned int x
, unsigned int y
, unsigned int width
, unsigned int height
,
470 int transparent
, unsigned char * dataPtr
);
471 static int decode_rle( unsigned char * dataPtr
, unsigned int * quantity
, unsigned int * depth
, unsigned char ** value
);
474 /* Utilities to convert 8 bit/gray */
475 static unsigned int make24bitcolor( unsigned int index
, const unsigned char * clut
);
476 static unsigned char findIndexMatch( unsigned char index
);
477 static unsigned char color24togray8( unsigned int color24
);
478 static unsigned char findbestgray( unsigned int color24
);
479 static int isActiveClutOK( void );
482 pixels_needed_to_blit_digit( int digit
)
488 static const struct rendered_num
*
489 find_rendered_digit( int digit
)
491 //extern unsigned char iso_font[];
492 const struct rendered_num
*digitPtr
;
501 digitPtr
= (const struct rendered_num
*) &iso_font
[digit
* 16];
507 blit_digit( int digit
)
509 unsigned char * raw_data
= (unsigned char *) find_rendered_digit( digit
);
510 unsigned width
= FONT_WIDTH
, height
= FONT_HEIGHT
;
513 for (row
=0; row
<FONT_HEIGHT
; row
++) {
517 bits
= raw_data
[row
];
518 for( j
=FONT_WIDTH
-1; j
>=0; j
--) {
521 rendered_font
[row
][j
] = OSSwapBigToHostInt16(0x0100 | panic_dialog
->pd_info_color
[0]);
523 rendered_font
[row
][j
] = OSSwapBigToHostInt16(0x0100 | panic_dialog
->pd_info_color
[1]);
528 panic_blit_rect( panic_info_x
, panic_info_y
, width
, height
, 255, (unsigned char *) rendered_font
);
529 panic_info_x
+= width
;
534 panic_blit_rect( unsigned int x
, unsigned int y
,
535 unsigned int width
, unsigned int height
,
536 int transparent
, unsigned char * dataPtr
)
541 switch( vinfo
.v_depth
) {
543 panic_blit_rect_8( x
, y
, width
, height
, transparent
, dataPtr
);
546 panic_blit_rect_16( x
, y
, width
, height
, transparent
, dataPtr
);
549 panic_blit_rect_32( x
, y
, width
, height
, transparent
, dataPtr
);
555 * panic_blit_rect_8 decodes the RLE encoded image data on the fly, looks up the
556 * color by indexing into the clut, or attempts to find the best index.
560 panic_blit_rect_8( unsigned int x
, unsigned int y
,
561 unsigned int width
, unsigned int height
,
562 int transparent
, unsigned char * dataPtr
)
564 volatile unsigned char * dst
;
565 unsigned int line
, col
, i
;
566 static int clutOK
= -1;
567 unsigned int data
, quantity
, depth
;
568 unsigned char * value
;
572 clutOK
= isActiveClutOK();
574 dst
= (volatile unsigned char *) (vinfo
.v_baseaddr
+
575 (y
* vinfo
.v_rowbytes
) +
581 for( line
= 0; line
< height
; line
++) {
582 for( col
= 0; col
< width
; col
++) {
585 dataPtr
+= decode_rle(dataPtr
, &quantity
, &depth
, &value
);
592 data
= findIndexMatch( value
[i
++] );
602 dst
= (volatile unsigned char *) (((int)dst
) + vinfo
.v_rowbytes
);
607 * panic_blit_rect_16 decodes the RLE encoded image data on the fly, looks up the
608 * color by indexing into the clut, uses the top 5 bits to fill in each of the three
609 * pixel values (RGB) and writes each pixel to the screen.
613 panic_blit_rect_16( unsigned int x
, unsigned int y
,
614 unsigned int width
, unsigned int height
,
615 int transparent
, unsigned char * dataPtr
)
618 volatile unsigned short * dst
;
619 unsigned int line
, col
, i
;
620 unsigned int quantity
, index
, data
, depth
;
621 unsigned char * value
;
623 dst
= (volatile unsigned short *) (vinfo
.v_baseaddr
+
624 (y
* vinfo
.v_rowbytes
) +
630 for( line
= 0; line
< height
; line
++) {
631 for( col
= 0; col
< width
; col
++) {
634 dataPtr
+= decode_rle(dataPtr
, &quantity
, &depth
, &value
);
638 index
= value
[i
++] * 3;
640 data
= ( (unsigned short) (0xf8 & (panic_dialog_clut
[index
+ 0])) << 7)
641 | ( (unsigned short) (0xf8 & (panic_dialog_clut
[index
+ 1])) << 2)
642 | ( (unsigned short) (0xf8 & (panic_dialog_clut
[index
+ 2])) >> 3);
652 dst
= (volatile unsigned short *) (((int)dst
) + vinfo
.v_rowbytes
);
657 * panic_blit_rect_32 decodes the RLE encoded image data on the fly, and fills
658 * in each of the three pixel values from the clut (RGB) for each pixel and
659 * writes it to the screen.
663 panic_blit_rect_32( unsigned int x
, unsigned int y
,
664 unsigned int width
, unsigned int height
,
665 int transparent
, unsigned char * dataPtr
)
667 volatile unsigned int * dst
;
668 unsigned int line
, col
, i
;
669 unsigned int quantity
, index
, data
, depth
;
670 unsigned char * value
;
673 dst
= (volatile unsigned int *) (vinfo
.v_baseaddr
+
674 (y
* vinfo
.v_rowbytes
) +
680 for( line
= 0; line
< height
; line
++) {
681 for( col
= 0; col
< width
; col
++) {
684 dataPtr
+= decode_rle(dataPtr
, &quantity
, &depth
, &value
);
688 index
= value
[i
++] * 3;
690 data
= ( (unsigned int) panic_dialog_clut
[index
+ 0] << 16)
691 | ( (unsigned int) panic_dialog_clut
[index
+ 1] << 8)
692 | ( (unsigned int) panic_dialog_clut
[index
+ 2]);
702 dst
= (volatile unsigned int *) (((int)dst
) + vinfo
.v_rowbytes
);
707 decode_rle decodes a single quantity/value run of a "modified-RLE" encoded
708 image. The encoding works as follows:
710 The run is described in the first byte. If the MSB is zero, then the next seven bits
711 are the quantity of bytes that follow that make up the run of value bytes. (see case 0)
713 If the MSB is set, bits 0-3 are the quantity's least significant 4 bits. If bit 5 is set,
714 then the quantity is further described in the next byte, where an additional 7 bits (4-10)
715 worth of quantity will be found. If the MSB of this byte is set, then an additional
716 7 bits (11-17) worth of quantity will be found in the next byte. This repeats until the MSB of
717 a quantity byte is zero, thus ending the run of quantity bytes.
719 Bits 5/6 of the first byte, describe the number of bytes in the value run following the quantity run.
720 These bits describe value runs of 1 to 4 bytes. And the quantity describe the number of value runs.
723 encodings are: (q = quantity, v = value, c = quantity continues)
725 case 0: [ 0 q6-q0 ] [ v7-v0 ] ... [ v7-v0 ]
726 case 1: [ 1 0 0 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ]
727 case 2: [ 1 0 1 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ]
728 case 3: [ 1 1 0 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ]
729 case 4: [ 1 1 1 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ]
733 decode_rle( unsigned char * dataPtr
, unsigned int * quantity
, unsigned int * depth
, unsigned char ** value
)
736 int i
, runlen
, runsize
;
739 mask
= dataPtr
[i
] & 0xF0;
742 runsize
= ((mask
& 0x60) >> 5) + 1;
743 runlen
= dataPtr
[i
++] & 0x0F;
749 mask
= dataPtr
[i
] & 0x80;
750 runlen
|= ((dataPtr
[i
++] & 0x7F) << shift
);
756 runsize
= dataPtr
[i
++];
761 *value
= &dataPtr
[i
];
770 unsigned long *p
, *endp
, *row
;
771 int col
, rowline
, rowlongs
;
772 register unsigned long mask
;
777 if ( vinfo
.v_depth
== 32 )
779 else if ( vinfo
.v_depth
== 16 )
784 rowline
= vinfo
.v_rowscanbytes
/ 4;
785 rowlongs
= vinfo
.v_rowbytes
/ 4;
787 p
= (unsigned long*) vinfo
.v_baseaddr
;
788 endp
= p
+ (rowlongs
* vinfo
.v_height
);
790 for (row
= p
; row
< endp
; row
+= rowlongs
) {
791 for (p
= &row
[0], col
= 0; col
< rowline
; col
++) {
792 *p
++ = (*p
>> 1) & mask
;
798 /* From user mode Libc - this ought to be in a library */
800 strnstr(const char * s
, const char * find
, size_t slen
)
805 if ((c
= *find
++) != '\0') {
809 if ((sc
= *s
++) == '\0' || slen
-- < 1)
814 } while (strncmp(s
, find
, len
) != 0);
821 * these routines are for converting a color into grayscale
822 * in 8-bit mode, if the active clut is different than the
823 * clut used to create the panic dialog, then we must convert to gray
827 make24bitcolor( unsigned int index
, const unsigned char * clut
)
829 unsigned int color24
= 0;
832 color24
|= clut
[i
+0] << 16;
833 color24
|= clut
[i
+1] << 8;
834 color24
|= clut
[i
+2];
841 findbestgray( unsigned int color24
)
843 unsigned int c24
, rel
, bestindex
=-1, bestgray
= -1;
844 unsigned char gray8
, c8
;
846 #define abs(v) ((v) > 0)?(v):-(v)
848 gray8
= color24togray8( color24
); /* convert the original color into grayscale */
850 for (i
=0; i
<CLUT_ENTRIES
; i
++) {
851 c24
= make24bitcolor( i
, active_clut
);
852 if ( (((c24
>>16)&0xff) != ((c24
>>8)&0xff)) || ((c24
>>8)&0xff) != (c24
& 0xff) )
853 continue; /* only match against grays */
855 c8
= c24
& 0xFF; /* isolate the gray */
857 /* find the gray with the smallest difference */
858 rel
= abs( gray8
- c8
);
859 if ( rel
< bestgray
) {
865 /* Did we fail to find any grays ? */
866 if ( bestindex
== -1 ) {
867 /* someday we should look for the best color match */
868 /* but for now just return the gray as the index */
869 /* at least there might be something readble on the display */
880 color24togray8( unsigned int color24
)
886 R
= (color24
& 0xFF0000) >> 16 ;
887 G
= (color24
& 0xFF00) >> 8 ;
888 B
= (color24
& 0xFF);
890 Gray
= (R
*30) + (G
*59) + (B
*11);
891 gray8
= (unsigned char) ((Gray
+ 50) / 100);
897 findIndexMatch( unsigned char index
)
899 static unsigned int last_in_index
= -1;
900 static unsigned char last_index
;
903 if ( index
== last_in_index
)
906 last_in_index
= index
;
907 sc
= make24bitcolor( index
, panic_dialog_clut
);
908 last_index
= findbestgray( sc
); /* find the nearest matching gray in the active clut */
914 isActiveClutOK( void )
917 int r
= 1; /* assume OK */
919 for (i
=0; i
<CLUT_ENTRIES
; i
++) {
920 if ( panic_dialog_clut
[i
] == active_clut
[i
] ) continue;