2 * Copyright (c) 2000-2009 Apple 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@
29 * @OSF_FREE_COPYRIGHT@
33 * @APPLE_FREE_COPYRIGHT@
36 * NetBSD: ite.c,v 1.16 1995/07/17 01:24:34 briggs Exp
38 * Copyright (c) 1988 University of Utah.
39 * Copyright (c) 1990, 1993
40 * The Regents of the University of California. All rights reserved.
42 * This code is derived from software contributed to Berkeley by
43 * the Systems Programming Group of the University of Utah Computer
46 * Redistribution and use in source and binary forms, with or without
47 * modification, are permitted provided that the following conditions
49 * 1. Redistributions of source code must retain the above copyright
50 * notice, this list of conditions and the following disclaimer.
51 * 2. Redistributions in binary form must reproduce the above copyright
52 * notice, this list of conditions and the following disclaimer in the
53 * documentation and/or other materials provided with the distribution.
54 * 3. All advertising materials mentioning features or use of this software
55 * must display the following acknowledgement:
56 * This product includes software developed by the University of
57 * California, Berkeley and its contributors.
58 * 4. Neither the name of the University nor the names of its contributors
59 * may be used to endorse or promote products derived from this software
60 * without specific prior written permission.
62 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
63 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
64 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
65 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
66 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
67 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
68 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
69 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
70 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
71 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
74 * from: Utah $Hdr: ite.c 1.28 92/12/20$
76 * @(#)ite.c 8.2 (Berkeley) 1/12/94
82 * The ite module handles the system console; that is, stuff printed
83 * by the kernel and by user programs while "desktop" and X aren't
84 * running. Some (very small) parts are based on hp300's 4.4 ite.c,
85 * hence the above copyright.
87 * -- Brad and Lawrence, June 26th, 1994
91 #include <console/video_console.h>
92 #include <console/serial_protos.h>
94 #include <kern/kern_types.h>
95 #include <kern/kalloc.h>
96 #include <kern/debug.h>
98 #include <kern/thread_call.h>
101 #include <vm/vm_kern.h>
102 #include <machine/io_map_entries.h>
103 #include <machine/machine_cpu.h>
105 #include <pexpert/pexpert.h>
106 #include <sys/kdebug.h>
108 #include "iso_font.c"
110 #include "progress_meter_data.c"
113 #include "sys/msgbuf.h"
116 * Generic Console (Front-End)
117 * ---------------------------
120 struct vc_info vinfo
;
122 void noroot_icon_test(void);
125 extern int disableConsoleOutput
;
126 static boolean_t gc_enabled
= FALSE
;
127 static boolean_t gc_initialized
= FALSE
;
128 static boolean_t vm_initialized
= FALSE
;
131 void (*initialize
)(struct vc_info
* info
);
132 void (*enable
)(boolean_t enable
);
133 void (*paint_char
)(unsigned int xx
, unsigned int yy
, unsigned char ch
,
134 int attrs
, unsigned char ch_previous
,
136 void (*clear_screen
)(unsigned int xx
, unsigned int yy
, unsigned int top
,
137 unsigned int bottom
, int which
);
138 void (*scroll_down
)(int num
, unsigned int top
, unsigned int bottom
);
139 void (*scroll_up
)(int num
, unsigned int top
, unsigned int bottom
);
140 void (*hide_cursor
)(unsigned int xx
, unsigned int yy
);
141 void (*show_cursor
)(unsigned int xx
, unsigned int yy
);
142 void (*update_color
)(int color
, boolean_t fore
);
145 static unsigned char *gc_buffer_attributes
;
146 static unsigned char *gc_buffer_characters
;
147 static unsigned char *gc_buffer_colorcodes
;
148 static unsigned char *gc_buffer_tab_stops
;
149 static uint32_t gc_buffer_columns
;
150 static uint32_t gc_buffer_rows
;
151 static uint32_t gc_buffer_size
;
153 #if defined(__i386__) || defined(__x86_64__)
154 decl_simple_lock_data(static, vcputc_lock
);
156 #define VCPUTC_LOCK_INIT() \
158 simple_lock_init(&vcputc_lock, 0); \
161 #define VCPUTC_LOCK_LOCK() \
163 boolean_t istate = ml_get_interrupts_enabled(); \
164 while (!simple_lock_try(&vcputc_lock)) \
167 handle_pending_TLB_flushes(); \
172 #define VCPUTC_LOCK_UNLOCK() \
174 simple_unlock(&vcputc_lock); \
177 static hw_lock_data_t vcputc_lock
;
179 #define VCPUTC_LOCK_INIT() \
181 hw_lock_init(&vcputc_lock); \
184 #define VCPUTC_LOCK_LOCK() \
186 if (!hw_lock_to(&vcputc_lock, ~0U))\
188 panic("VCPUTC_LOCK_LOCK"); \
192 #define VCPUTC_LOCK_UNLOCK() \
194 hw_lock_unlock(&vcputc_lock); \
200 # 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed
202 # 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white
203 # Background color codes:
204 # 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white
210 #define ATTR_REVERSE 4
212 #define COLOR_BACKGROUND 0
213 #define COLOR_FOREGROUND 7
215 #define COLOR_CODE_GET(code, fore) (((code) & ((fore) ? 0xF0 : 0x0F)) >> ((fore) ? 4 : 0))
216 #define COLOR_CODE_SET(code, color, fore) (((code) & ((fore) ? 0x0F : 0xF0)) | ((color) << ((fore) ? 4 : 0)))
218 static unsigned char gc_color_code
;
222 static unsigned int gc_x
, gc_y
, gc_savex
, gc_savey
;
223 static unsigned int gc_par
[MAXPARS
], gc_numpars
, gc_hanging_cursor
, gc_attr
, gc_saveattr
;
225 /* VT100 scroll region */
226 static unsigned int gc_scrreg_top
, gc_scrreg_bottom
;
229 ESnormal
, /* Nothing yet */
231 ESsquare
, /* Got ESC [ */
232 ESgetpars
, /* About to get or getting the parameters */
233 ESgotpars
, /* Finished getting the parameters */
234 ESfunckey
, /* Function key */
235 EShash
, /* DEC-specific stuff (screen align, etc.) */
236 ESsetG0
, /* Specify the G0 character set */
237 ESsetG1
, /* Specify the G1 character set */
240 ESignore
/* Ignore this sequence */
241 } gc_vt100state
= ESnormal
;
247 kProgressAcquireDelay
= 0,
249 kProgressReacquireDelay
= 5,
251 kProgressReacquireDelay
= 5,
255 static int8_t vc_rotate_matr
[4][2][2] = {
266 static int gc_wrap_mode
= 1, gc_relative_origin
= 0;
267 static int gc_charset_select
= 0, gc_save_charset_s
= 0;
268 static int gc_charset
[2] = { 0, 0 };
269 static int gc_charset_save
[2] = { 0, 0 };
271 static void gc_clear_line(unsigned int xx
, unsigned int yy
, int which
);
272 static void gc_clear_screen(unsigned int xx
, unsigned int yy
, int top
,
273 unsigned int bottom
, int which
);
274 static void gc_enable(boolean_t enable
);
275 static void gc_hide_cursor(unsigned int xx
, unsigned int yy
);
276 static void gc_initialize(struct vc_info
* info
);
277 static boolean_t
gc_is_tab_stop(unsigned int column
);
278 static void gc_paint_char(unsigned int xx
, unsigned int yy
, unsigned char ch
,
280 static void gc_putchar(char ch
);
281 static void gc_putc_askcmd(unsigned char ch
);
282 static void gc_putc_charsetcmd(int charset
, unsigned char ch
);
283 static void gc_putc_charsizecmd(unsigned char ch
);
284 static void gc_putc_esc(unsigned char ch
);
285 static void gc_putc_getpars(unsigned char ch
);
286 static void gc_putc_gotpars(unsigned char ch
);
287 static void gc_putc_normal(unsigned char ch
);
288 static void gc_putc_square(unsigned char ch
);
289 static void gc_reset_screen(void);
290 static void gc_reset_tabs(void);
291 static void gc_reset_vt100(void);
292 static void gc_scroll_down(int num
, unsigned int top
, unsigned int bottom
);
293 static void gc_scroll_up(int num
, unsigned int top
, unsigned int bottom
);
294 static void gc_set_tab_stop(unsigned int column
, boolean_t enabled
);
295 static void gc_show_cursor(unsigned int xx
, unsigned int yy
);
296 static void gc_update_color(int color
, boolean_t fore
);
299 gc_clear_line(unsigned int xx
, unsigned int yy
, int which
)
301 unsigned int start
, end
, i
;
304 * This routine runs extremely slowly. I don't think it's
305 * used all that often, except for To end of line. I'll go
306 * back and speed this up when I speed up the whole vc
311 case 0: /* To end of line */
313 end
= vinfo
.v_columns
-1;
315 case 1: /* To start of line */
319 case 2: /* Whole line */
321 end
= vinfo
.v_columns
-1;
327 for (i
= start
; i
<= end
; i
++) {
328 gc_paint_char(i
, yy
, ' ', ATTR_NONE
);
333 gc_clear_screen(unsigned int xx
, unsigned int yy
, int top
, unsigned int bottom
,
336 if (!gc_buffer_size
) return;
338 if ( xx
< gc_buffer_columns
&& yy
< gc_buffer_rows
&& bottom
<= gc_buffer_rows
)
343 case 0: /* To end of screen */
344 start
= (yy
* gc_buffer_columns
) + xx
;
345 end
= (bottom
* gc_buffer_columns
) - 1;
347 case 1: /* To start of screen */
348 start
= (top
* gc_buffer_columns
);
349 end
= (yy
* gc_buffer_columns
) + xx
;
351 case 2: /* Whole screen */
352 start
= (top
* gc_buffer_columns
);
353 end
= (bottom
* gc_buffer_columns
) - 1;
361 memset(gc_buffer_attributes
+ start
, ATTR_NONE
, end
- start
+ 1);
362 memset(gc_buffer_characters
+ start
, ' ', end
- start
+ 1);
363 memset(gc_buffer_colorcodes
+ start
, gc_color_code
, end
- start
+ 1);
366 gc_ops
.clear_screen(xx
, yy
, top
, bottom
, which
);
370 gc_enable( boolean_t enable
)
372 unsigned char *buffer_attributes
= NULL
;
373 unsigned char *buffer_characters
= NULL
;
374 unsigned char *buffer_colorcodes
= NULL
;
375 unsigned char *buffer_tab_stops
= NULL
;
376 uint32_t buffer_columns
= 0;
377 uint32_t buffer_rows
= 0;
378 uint32_t buffer_size
= 0;
381 if ( enable
== FALSE
)
383 // only disable console output if it goes to the graphics console
384 if ( console_is_serial() == FALSE
)
385 disableConsoleOutput
= TRUE
;
387 gc_ops
.enable(FALSE
);
393 if ( gc_buffer_size
)
395 buffer_attributes
= gc_buffer_attributes
;
396 buffer_characters
= gc_buffer_characters
;
397 buffer_colorcodes
= gc_buffer_colorcodes
;
398 buffer_tab_stops
= gc_buffer_tab_stops
;
399 buffer_columns
= gc_buffer_columns
;
400 buffer_rows
= gc_buffer_rows
;
401 buffer_size
= gc_buffer_size
;
403 gc_buffer_attributes
= NULL
;
404 gc_buffer_characters
= NULL
;
405 gc_buffer_colorcodes
= NULL
;
406 gc_buffer_tab_stops
= NULL
;
407 gc_buffer_columns
= 0;
411 VCPUTC_LOCK_UNLOCK( );
414 kfree( buffer_attributes
, buffer_size
);
415 kfree( buffer_characters
, buffer_size
);
416 kfree( buffer_colorcodes
, buffer_size
);
417 kfree( buffer_tab_stops
, buffer_columns
);
421 VCPUTC_LOCK_UNLOCK( );
427 if ( vm_initialized
)
429 buffer_columns
= vinfo
.v_columns
;
430 buffer_rows
= vinfo
.v_rows
;
431 buffer_size
= buffer_columns
* buffer_rows
;
435 buffer_attributes
= (unsigned char *) kalloc( buffer_size
);
436 buffer_characters
= (unsigned char *) kalloc( buffer_size
);
437 buffer_colorcodes
= (unsigned char *) kalloc( buffer_size
);
438 buffer_tab_stops
= (unsigned char *) kalloc( buffer_columns
);
440 if ( buffer_attributes
== NULL
||
441 buffer_characters
== NULL
||
442 buffer_colorcodes
== NULL
||
443 buffer_tab_stops
== NULL
)
445 if ( buffer_attributes
) kfree( buffer_attributes
, buffer_size
);
446 if ( buffer_characters
) kfree( buffer_characters
, buffer_size
);
447 if ( buffer_colorcodes
) kfree( buffer_colorcodes
, buffer_size
);
448 if ( buffer_tab_stops
) kfree( buffer_tab_stops
, buffer_columns
);
450 buffer_attributes
= NULL
;
451 buffer_characters
= NULL
;
452 buffer_colorcodes
= NULL
;
453 buffer_tab_stops
= NULL
;
460 memset( buffer_attributes
, ATTR_NONE
, buffer_size
);
461 memset( buffer_characters
, ' ', buffer_size
);
462 memset( buffer_colorcodes
, COLOR_CODE_SET( 0, COLOR_FOREGROUND
, TRUE
), buffer_size
);
463 memset( buffer_tab_stops
, 0, buffer_columns
);
471 gc_buffer_attributes
= buffer_attributes
;
472 gc_buffer_characters
= buffer_characters
;
473 gc_buffer_colorcodes
= buffer_colorcodes
;
474 gc_buffer_tab_stops
= buffer_tab_stops
;
475 gc_buffer_columns
= buffer_columns
;
476 gc_buffer_rows
= buffer_rows
;
477 gc_buffer_size
= buffer_size
;
481 VCPUTC_LOCK_UNLOCK( );
484 gc_ops
.clear_screen(gc_x
, gc_y
, 0, vinfo
.v_rows
, 2);
485 gc_ops
.show_cursor(gc_x
, gc_y
);
489 disableConsoleOutput
= FALSE
;
494 gc_hide_cursor(unsigned int xx
, unsigned int yy
)
496 if ( xx
< gc_buffer_columns
&& yy
< gc_buffer_rows
)
498 uint32_t index
= (yy
* gc_buffer_columns
) + xx
;
499 unsigned char attribute
= gc_buffer_attributes
[index
];
500 unsigned char character
= gc_buffer_characters
[index
];
501 unsigned char colorcode
= gc_buffer_colorcodes
[index
];
502 unsigned char colorcodesave
= gc_color_code
;
504 gc_update_color(COLOR_CODE_GET(colorcode
, TRUE
), TRUE
);
505 gc_update_color(COLOR_CODE_GET(colorcode
, FALSE
), FALSE
);
507 gc_ops
.paint_char(xx
, yy
, character
, attribute
, 0, 0);
509 gc_update_color(COLOR_CODE_GET(colorcodesave
, TRUE
), TRUE
);
510 gc_update_color(COLOR_CODE_GET(colorcodesave
, FALSE
), FALSE
);
514 gc_ops
.hide_cursor(xx
, yy
);
519 gc_initialize(struct vc_info
* info
)
521 if ( gc_initialized
== FALSE
)
526 gc_initialized
= TRUE
;
529 gc_ops
.initialize(info
);
536 gc_paint_char(unsigned int xx
, unsigned int yy
, unsigned char ch
, int attrs
)
538 if ( xx
< gc_buffer_columns
&& yy
< gc_buffer_rows
)
540 uint32_t index
= (yy
* gc_buffer_columns
) + xx
;
542 gc_buffer_attributes
[index
] = attrs
;
543 gc_buffer_characters
[index
] = ch
;
544 gc_buffer_colorcodes
[index
] = gc_color_code
;
547 gc_ops
.paint_char(xx
, yy
, ch
, attrs
, 0, 0);
554 return; /* ignore null characters */
556 switch (gc_vt100state
) {
557 default:gc_vt100state
= ESnormal
; /* FALLTHROUGH */
577 gc_putc_charsizecmd(ch
);
580 gc_putc_charsetcmd(0, ch
);
583 gc_putc_charsetcmd(1, ch
);
587 if (gc_x
>= vinfo
.v_columns
) {
588 if (0 == vinfo
.v_columns
)
591 gc_x
= vinfo
.v_columns
- 1;
593 if (gc_y
>= vinfo
.v_rows
) {
594 if (0 == vinfo
.v_rows
)
597 gc_y
= vinfo
.v_rows
- 1;
602 gc_putc_askcmd(unsigned char ch
)
604 if (ch
>= '0' && ch
<= '9') {
605 gc_par
[gc_numpars
] = (10*gc_par
[gc_numpars
]) + (ch
-'0');
608 gc_vt100state
= ESnormal
;
612 gc_relative_origin
= ch
== 'h';
614 case 7: /* wrap around mode h=1, l=0*/
615 gc_wrap_mode
= ch
== 'h';
624 gc_putc_charsetcmd(int charset
, unsigned char ch
)
626 gc_vt100state
= ESnormal
;
632 gc_charset
[charset
] = 0;
634 case '0' : /* Graphic characters */
636 gc_charset
[charset
] = 0x21;
643 gc_putc_charsizecmd(unsigned char ch
)
645 gc_vt100state
= ESnormal
;
653 case '8' : /* fill 'E's */
656 for (yy
= 0; yy
< vinfo
.v_rows
; yy
++)
657 for (xx
= 0; xx
< vinfo
.v_columns
; xx
++)
658 gc_paint_char(xx
, yy
, 'E', ATTR_NONE
);
666 gc_putc_esc(unsigned char ch
)
668 gc_vt100state
= ESnormal
;
672 gc_vt100state
= ESsquare
;
674 case 'c': /* Reset terminal */
676 gc_clear_screen(gc_x
, gc_y
, 0, vinfo
.v_rows
, 2);
679 case 'D': /* Line feed */
681 if (gc_y
>= gc_scrreg_bottom
-1) {
682 gc_scroll_up(1, gc_scrreg_top
, gc_scrreg_bottom
);
683 gc_y
= gc_scrreg_bottom
- 1;
687 if (ch
== 'E') gc_x
= 0;
689 case 'H': /* Set tab stop */
690 gc_set_tab_stop(gc_x
, TRUE
);
692 case 'M': /* Cursor up */
693 if (gc_y
<= gc_scrreg_top
) {
694 gc_scroll_down(1, gc_scrreg_top
, gc_scrreg_bottom
);
695 gc_y
= gc_scrreg_top
;
703 case '7': /* Save cursor */
706 gc_saveattr
= gc_attr
;
707 gc_save_charset_s
= gc_charset_select
;
708 gc_charset_save
[0] = gc_charset
[0];
709 gc_charset_save
[1] = gc_charset
[1];
711 case '8': /* Restore cursor */
714 gc_attr
= gc_saveattr
;
715 gc_charset_select
= gc_save_charset_s
;
716 gc_charset
[0] = gc_charset_save
[0];
717 gc_charset
[1] = gc_charset_save
[1];
719 case 'Z': /* return terminal ID */
721 case '#': /* change characters height */
722 gc_vt100state
= EScharsize
;
725 gc_vt100state
= ESsetG0
;
727 case ')': /* character set sequence */
728 gc_vt100state
= ESsetG1
;
733 /* Rest not supported */
740 gc_putc_getpars(unsigned char ch
)
743 gc_vt100state
= ESask
;
747 gc_vt100state
= ESnormal
;
751 if (ch
== ';' && gc_numpars
< MAXPARS
- 1) {
754 if (ch
>= '0' && ch
<= '9') {
755 gc_par
[gc_numpars
] *= 10;
756 gc_par
[gc_numpars
] += ch
- '0';
759 gc_vt100state
= ESgotpars
;
765 gc_putc_gotpars(unsigned char ch
)
770 /* special case for vttest for handling cursor
771 movement in escape sequences */
773 gc_vt100state
= ESgotpars
;
776 gc_vt100state
= ESnormal
;
779 gc_y
-= gc_par
[0] ? gc_par
[0] : 1;
780 if (gc_y
< gc_scrreg_top
)
781 gc_y
= gc_scrreg_top
;
784 gc_y
+= gc_par
[0] ? gc_par
[0] : 1;
785 if (gc_y
>= gc_scrreg_bottom
)
786 gc_y
= gc_scrreg_bottom
- 1;
788 case 'C': /* Right */
789 gc_x
+= gc_par
[0] ? gc_par
[0] : 1;
790 if (gc_x
>= vinfo
.v_columns
)
791 gc_x
= vinfo
.v_columns
-1;
794 if (gc_par
[0] > gc_x
)
801 case 'H': /* Set cursor position */
803 gc_x
= gc_par
[1] ? gc_par
[1] - 1 : 0;
804 gc_y
= gc_par
[0] ? gc_par
[0] - 1 : 0;
805 if (gc_relative_origin
)
806 gc_y
+= gc_scrreg_top
;
807 gc_hanging_cursor
= 0;
809 case 'X': /* clear p1 characters */
811 for (i
= gc_x
; i
< gc_x
+ gc_par
[0]; i
++)
812 gc_paint_char(i
, gc_y
, ' ', ATTR_NONE
);
815 case 'J': /* Clear part of screen */
816 gc_clear_screen(gc_x
, gc_y
, 0, vinfo
.v_rows
, gc_par
[0]);
818 case 'K': /* Clear part of line */
819 gc_clear_line(gc_x
, gc_y
, gc_par
[0]);
821 case 'g': /* tab stops */
824 case 2: /* reset tab stops */
825 /* gc_reset_tabs(); */
827 case 3: /* Clear every tabs */
829 for (i
= 0; i
<= vinfo
.v_columns
; i
++)
830 gc_set_tab_stop(i
, FALSE
);
834 gc_set_tab_stop(gc_x
, FALSE
);
838 case 'm': /* Set attribute */
839 for (i
= 0; i
< gc_numpars
; i
++) {
843 gc_update_color(COLOR_BACKGROUND
, FALSE
);
844 gc_update_color(COLOR_FOREGROUND
, TRUE
);
847 gc_attr
|= ATTR_BOLD
;
850 gc_attr
|= ATTR_UNDER
;
853 gc_attr
|= ATTR_REVERSE
;
856 gc_attr
&= ~ATTR_BOLD
;
859 gc_attr
&= ~ATTR_UNDER
;
862 gc_attr
&= ~ATTR_REVERSE
;
865 case 25: /* blink/no blink */
868 if (gc_par
[i
] >= 30 && gc_par
[i
] <= 37)
869 gc_update_color(gc_par
[i
] - 30, TRUE
);
870 if (gc_par
[i
] >= 40 && gc_par
[i
] <= 47)
871 gc_update_color(gc_par
[i
] - 40, FALSE
);
876 case 'r': /* Set scroll region */
878 /* ensure top < bottom, and both within limits */
879 if ((gc_numpars
> 0) && (gc_par
[0] < vinfo
.v_rows
)) {
880 gc_scrreg_top
= gc_par
[0] ? gc_par
[0] - 1 : 0;
884 if ((gc_numpars
> 1) && (gc_par
[1] <= vinfo
.v_rows
) && (gc_par
[1] > gc_par
[0])) {
885 gc_scrreg_bottom
= gc_par
[1];
886 if (gc_scrreg_bottom
> vinfo
.v_rows
)
887 gc_scrreg_bottom
= vinfo
.v_rows
;
889 gc_scrreg_bottom
= vinfo
.v_rows
;
891 if (gc_relative_origin
)
892 gc_y
= gc_scrreg_top
;
899 gc_putc_normal(unsigned char ch
)
902 case '\a': /* Beep */
904 case 127: /* Delete */
905 case '\b': /* Backspace */
906 if (gc_hanging_cursor
) {
907 gc_hanging_cursor
= 0;
914 if (gc_buffer_tab_stops
) while (gc_x
< vinfo
.v_columns
&& !gc_is_tab_stop(++gc_x
));
916 if (gc_x
>= vinfo
.v_columns
)
917 gc_x
= vinfo
.v_columns
-1;
921 case '\n': /* Line feed */
922 if (gc_y
>= gc_scrreg_bottom
-1 ) {
923 gc_scroll_up(1, gc_scrreg_top
, gc_scrreg_bottom
);
924 gc_y
= gc_scrreg_bottom
- 1;
929 case '\r': /* Carriage return */
931 gc_hanging_cursor
= 0;
933 case 0x0e: /* Select G1 charset (Control-N) */
934 gc_charset_select
= 1;
936 case 0x0f: /* Select G0 charset (Control-O) */
937 gc_charset_select
= 0;
939 case 0x18 : /* CAN : cancel */
940 case 0x1A : /* like cancel */
941 /* well, i do nothing here, may be later */
943 case '\033': /* Escape */
944 gc_vt100state
= ESesc
;
945 gc_hanging_cursor
= 0;
949 if (gc_hanging_cursor
) {
951 if (gc_y
>= gc_scrreg_bottom
-1 ) {
952 gc_scroll_up(1, gc_scrreg_top
, gc_scrreg_bottom
);
953 gc_y
= gc_scrreg_bottom
- 1;
957 gc_hanging_cursor
= 0;
959 gc_paint_char(gc_x
, gc_y
, (ch
>= 0x60 && ch
<= 0x7f) ? ch
+ gc_charset
[gc_charset_select
]
961 if (gc_x
== vinfo
.v_columns
- 1) {
962 gc_hanging_cursor
= gc_wrap_mode
;
973 gc_putc_square(unsigned char ch
)
977 for (i
= 0; i
< MAXPARS
; i
++) {
982 gc_vt100state
= ESgetpars
;
989 gc_reset_screen(void)
1000 if (!gc_buffer_tab_stops
) return;
1002 for (i
= 0; i
< vinfo
.v_columns
; i
++) {
1003 gc_buffer_tab_stops
[i
] = ((i
% 8) == 0);
1009 gc_set_tab_stop(unsigned int column
, boolean_t enabled
)
1011 if (gc_buffer_tab_stops
&& (column
< vinfo
.v_columns
)) {
1012 gc_buffer_tab_stops
[column
] = enabled
;
1016 static boolean_t
gc_is_tab_stop(unsigned int column
)
1018 if (gc_buffer_tab_stops
== NULL
)
1019 return ((column
% 8) == 0);
1020 if (column
< vinfo
.v_columns
)
1021 return gc_buffer_tab_stops
[column
];
1027 gc_reset_vt100(void)
1031 gc_scrreg_bottom
= vinfo
.v_rows
;
1032 gc_attr
= ATTR_NONE
;
1033 gc_charset
[0] = gc_charset
[1] = 0;
1034 gc_charset_select
= 0;
1036 gc_relative_origin
= 0;
1037 gc_update_color(COLOR_BACKGROUND
, FALSE
);
1038 gc_update_color(COLOR_FOREGROUND
, TRUE
);
1042 gc_scroll_down(int num
, unsigned int top
, unsigned int bottom
)
1044 if (!gc_buffer_size
) return;
1046 if ( bottom
<= gc_buffer_rows
)
1048 unsigned char colorcodesave
= gc_color_code
;
1049 uint32_t column
, row
;
1050 uint32_t index
, jump
;
1052 jump
= num
* gc_buffer_columns
;
1054 for ( row
= bottom
- 1 ; row
>= top
+ num
; row
-- )
1056 index
= row
* gc_buffer_columns
;
1058 for ( column
= 0 ; column
< gc_buffer_columns
; index
++, column
++ )
1060 if ( gc_buffer_attributes
[index
] != gc_buffer_attributes
[index
- jump
] ||
1061 gc_buffer_characters
[index
] != gc_buffer_characters
[index
- jump
] ||
1062 gc_buffer_colorcodes
[index
] != gc_buffer_colorcodes
[index
- jump
] )
1064 if ( gc_color_code
!= gc_buffer_colorcodes
[index
- jump
] )
1066 gc_update_color(COLOR_CODE_GET(gc_buffer_colorcodes
[index
- jump
], TRUE
), TRUE
);
1067 gc_update_color(COLOR_CODE_GET(gc_buffer_colorcodes
[index
- jump
], FALSE
), FALSE
);
1070 if ( gc_buffer_colorcodes
[index
] != gc_buffer_colorcodes
[index
- jump
] )
1072 gc_ops
.paint_char( /* xx */ column
,
1074 /* ch */ gc_buffer_characters
[index
- jump
],
1075 /* attrs */ gc_buffer_attributes
[index
- jump
],
1076 /* ch_previous */ 0,
1077 /* attrs_previous */ 0 );
1081 gc_ops
.paint_char( /* xx */ column
,
1083 /* ch */ gc_buffer_characters
[index
- jump
],
1084 /* attrs */ gc_buffer_attributes
[index
- jump
],
1085 /* ch_previous */ gc_buffer_characters
[index
],
1086 /* attrs_previous */ gc_buffer_attributes
[index
] );
1089 gc_buffer_attributes
[index
] = gc_buffer_attributes
[index
- jump
];
1090 gc_buffer_characters
[index
] = gc_buffer_characters
[index
- jump
];
1091 gc_buffer_colorcodes
[index
] = gc_buffer_colorcodes
[index
- jump
];
1096 if ( colorcodesave
!= gc_color_code
)
1098 gc_update_color(COLOR_CODE_GET(colorcodesave
, TRUE
), TRUE
);
1099 gc_update_color(COLOR_CODE_GET(colorcodesave
, FALSE
), FALSE
);
1102 /* Now set the freed up lines to the background colour */
1104 for ( row
= top
; row
< top
+ num
; row
++ )
1106 index
= row
* gc_buffer_columns
;
1108 for ( column
= 0 ; column
< gc_buffer_columns
; index
++, column
++ )
1110 if ( gc_buffer_attributes
[index
] != ATTR_NONE
||
1111 gc_buffer_characters
[index
] != ' ' ||
1112 gc_buffer_colorcodes
[index
] != gc_color_code
)
1114 if ( gc_buffer_colorcodes
[index
] != gc_color_code
)
1116 gc_ops
.paint_char( /* xx */ column
,
1119 /* attrs */ ATTR_NONE
,
1120 /* ch_previous */ 0,
1121 /* attrs_previous */ 0 );
1125 gc_ops
.paint_char( /* xx */ column
,
1128 /* attrs */ ATTR_NONE
,
1129 /* ch_previous */ gc_buffer_characters
[index
],
1130 /* attrs_previous */ gc_buffer_attributes
[index
] );
1133 gc_buffer_attributes
[index
] = ATTR_NONE
;
1134 gc_buffer_characters
[index
] = ' ';
1135 gc_buffer_colorcodes
[index
] = gc_color_code
;
1142 gc_ops
.scroll_down(num
, top
, bottom
);
1144 /* Now set the freed up lines to the background colour */
1146 gc_clear_screen(vinfo
.v_columns
- 1, top
+ num
- 1, top
, bottom
, 1);
1151 gc_scroll_up(int num
, unsigned int top
, unsigned int bottom
)
1153 if (!gc_buffer_size
) return;
1155 if ( bottom
<= gc_buffer_rows
)
1157 unsigned char colorcodesave
= gc_color_code
;
1158 uint32_t column
, row
;
1159 uint32_t index
, jump
;
1161 jump
= num
* gc_buffer_columns
;
1163 for ( row
= top
; row
< bottom
- num
; row
++ )
1165 index
= row
* gc_buffer_columns
;
1167 for ( column
= 0 ; column
< gc_buffer_columns
; index
++, column
++ )
1169 if ( gc_buffer_attributes
[index
] != gc_buffer_attributes
[index
+ jump
] ||
1170 gc_buffer_characters
[index
] != gc_buffer_characters
[index
+ jump
] ||
1171 gc_buffer_colorcodes
[index
] != gc_buffer_colorcodes
[index
+ jump
] )
1173 if ( gc_color_code
!= gc_buffer_colorcodes
[index
+ jump
] )
1175 gc_update_color(COLOR_CODE_GET(gc_buffer_colorcodes
[index
+ jump
], TRUE
), TRUE
);
1176 gc_update_color(COLOR_CODE_GET(gc_buffer_colorcodes
[index
+ jump
], FALSE
), FALSE
);
1179 if ( gc_buffer_colorcodes
[index
] != gc_buffer_colorcodes
[index
+ jump
] )
1181 gc_ops
.paint_char( /* xx */ column
,
1183 /* ch */ gc_buffer_characters
[index
+ jump
],
1184 /* attrs */ gc_buffer_attributes
[index
+ jump
],
1185 /* ch_previous */ 0,
1186 /* attrs_previous */ 0 );
1190 gc_ops
.paint_char( /* xx */ column
,
1192 /* ch */ gc_buffer_characters
[index
+ jump
],
1193 /* attrs */ gc_buffer_attributes
[index
+ jump
],
1194 /* ch_previous */ gc_buffer_characters
[index
],
1195 /* attrs_previous */ gc_buffer_attributes
[index
] );
1198 gc_buffer_attributes
[index
] = gc_buffer_attributes
[index
+ jump
];
1199 gc_buffer_characters
[index
] = gc_buffer_characters
[index
+ jump
];
1200 gc_buffer_colorcodes
[index
] = gc_buffer_colorcodes
[index
+ jump
];
1205 if ( colorcodesave
!= gc_color_code
)
1207 gc_update_color(COLOR_CODE_GET(colorcodesave
, TRUE
), TRUE
);
1208 gc_update_color(COLOR_CODE_GET(colorcodesave
, FALSE
), FALSE
);
1211 /* Now set the freed up lines to the background colour */
1213 for ( row
= bottom
- num
; row
< bottom
; row
++ )
1215 index
= row
* gc_buffer_columns
;
1217 for ( column
= 0 ; column
< gc_buffer_columns
; index
++, column
++ )
1219 if ( gc_buffer_attributes
[index
] != ATTR_NONE
||
1220 gc_buffer_characters
[index
] != ' ' ||
1221 gc_buffer_colorcodes
[index
] != gc_color_code
)
1223 if ( gc_buffer_colorcodes
[index
] != gc_color_code
)
1225 gc_ops
.paint_char( /* xx */ column
,
1228 /* attrs */ ATTR_NONE
,
1229 /* ch_previous */ 0,
1230 /* attrs_previous */ 0 );
1234 gc_ops
.paint_char( /* xx */ column
,
1237 /* attrs */ ATTR_NONE
,
1238 /* ch_previous */ gc_buffer_characters
[index
],
1239 /* attrs_previous */ gc_buffer_attributes
[index
] );
1242 gc_buffer_attributes
[index
] = ATTR_NONE
;
1243 gc_buffer_characters
[index
] = ' ';
1244 gc_buffer_colorcodes
[index
] = gc_color_code
;
1251 gc_ops
.scroll_up(num
, top
, bottom
);
1253 /* Now set the freed up lines to the background colour */
1255 gc_clear_screen(0, bottom
- num
, top
, bottom
, 0);
1260 gc_show_cursor(unsigned int xx
, unsigned int yy
)
1262 if ( xx
< gc_buffer_columns
&& yy
< gc_buffer_rows
)
1264 uint32_t index
= (yy
* gc_buffer_columns
) + xx
;
1265 unsigned char attribute
= gc_buffer_attributes
[index
];
1266 unsigned char character
= gc_buffer_characters
[index
];
1267 unsigned char colorcode
= gc_buffer_colorcodes
[index
];
1268 unsigned char colorcodesave
= gc_color_code
;
1270 gc_update_color(COLOR_CODE_GET(colorcode
, FALSE
), TRUE
);
1271 gc_update_color(COLOR_CODE_GET(colorcode
, TRUE
), FALSE
);
1273 gc_ops
.paint_char(xx
, yy
, character
, attribute
, 0, 0);
1275 gc_update_color(COLOR_CODE_GET(colorcodesave
, TRUE
), TRUE
);
1276 gc_update_color(COLOR_CODE_GET(colorcodesave
, FALSE
), FALSE
);
1280 gc_ops
.show_cursor(xx
, yy
);
1285 gc_update_color(int color
, boolean_t fore
)
1287 assert(gc_ops
.update_color
);
1289 gc_color_code
= COLOR_CODE_SET(gc_color_code
, color
, fore
);
1290 gc_ops
.update_color(color
, fore
);
1294 vcputc(__unused
int l
, __unused
int u
, int c
)
1296 if ( gc_initialized
&& gc_enabled
)
1301 #if defined(__i386__) || defined(__x86_64__)
1302 x86_filter_TLB_coherency_interrupts(TRUE
);
1307 gc_hide_cursor(gc_x
, gc_y
);
1309 gc_show_cursor(gc_x
, gc_y
);
1311 VCPUTC_LOCK_UNLOCK();
1312 #if defined(__i386__) || defined(__x86_64__)
1313 x86_filter_TLB_coherency_interrupts(FALSE
);
1320 * Video Console (Back-End)
1321 * ------------------------
1325 * For the color support (Michel Pollet)
1327 static unsigned char vc_color_index_table
[33] =
1328 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1329 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 2 };
1331 static uint32_t vc_colors
[8][4] = {
1332 { 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000 }, /* black */
1333 { 0x23232323, 0x7C007C00, 0x00FF0000, 0x3FF00000 }, /* red */
1334 { 0xb9b9b9b9, 0x03e003e0, 0x0000FF00, 0x000FFC00 }, /* green */
1335 { 0x05050505, 0x7FE07FE0, 0x00FFFF00, 0x3FFFFC00 }, /* yellow */
1336 { 0xd2d2d2d2, 0x001f001f, 0x000000FF, 0x000003FF }, /* blue */
1337 // { 0x80808080, 0x31933193, 0x00666699, 0x00000000 }, /* blue */
1338 { 0x18181818, 0x7C1F7C1F, 0x00FF00FF, 0x3FF003FF }, /* magenta */
1339 { 0xb4b4b4b4, 0x03FF03FF, 0x0000FFFF, 0x000FFFFF }, /* cyan */
1340 { 0x00000000, 0x7FFF7FFF, 0x00FFFFFF, 0x3FFFFFFF } /* white */
1343 static uint32_t vc_color_fore
= 0;
1344 static uint32_t vc_color_back
= 0;
1347 * New Rendering code from Michel Pollet
1350 /* Rendered Font Buffer */
1351 static unsigned char *vc_rendered_font
= NULL
;
1353 /* Rendered Font Size */
1354 static uint32_t vc_rendered_font_size
= 0;
1356 /* Size of a character in the table (bytes) */
1357 static int vc_rendered_char_size
= 0;
1359 #define REN_MAX_DEPTH 32
1360 static unsigned char vc_rendered_char
[ISO_CHAR_HEIGHT
* ((REN_MAX_DEPTH
/ 8) * ISO_CHAR_WIDTH
)];
1362 #if !CONFIG_EMBEDDED
1364 internal_set_progressmeter(int new_value
);
1366 internal_enable_progressmeter(int new_value
);
1370 kProgressMeterOff
= FALSE
,
1371 kProgressMeterUser
= TRUE
,
1372 kProgressMeterKernel
= 3,
1376 kProgressMeterMax
= 1024,
1377 kProgressMeterEnd
= 512,
1380 #endif /* !CONFIG_EMBEDDED */
1382 static boolean_t vc_progress_white
=
1383 #ifdef CONFIG_VC_PROGRESS_WHITE
1385 #else /* !CONFIG_VC_PROGRESS_WHITE */
1387 #endif /* !CONFIG_VC_PROGRESS_WHITE */
1389 static int vc_acquire_delay
= kProgressAcquireDelay
;
1392 vc_clear_screen(unsigned int xx
, unsigned int yy
, unsigned int scrreg_top
,
1393 unsigned int scrreg_bottom
, int which
)
1395 uint32_t *p
, *endp
, *row
;
1397 int rowline
, rowlongs
;
1402 linelongs
= vinfo
.v_rowbytes
* (ISO_CHAR_HEIGHT
>> 2);
1403 rowline
= vinfo
.v_rowscanbytes
>> 2;
1404 rowlongs
= vinfo
.v_rowbytes
>> 2;
1406 p
= (uint32_t*) vinfo
.v_baseaddr
;
1407 endp
= (uint32_t*) vinfo
.v_baseaddr
;
1410 case 0: /* To end of screen */
1411 gc_clear_line(xx
, yy
, 0);
1412 if (yy
< scrreg_bottom
- 1) {
1413 p
+= (yy
+ 1) * linelongs
;
1414 endp
+= scrreg_bottom
* linelongs
;
1417 case 1: /* To start of screen */
1418 gc_clear_line(xx
, yy
, 1);
1419 if (yy
> scrreg_top
) {
1420 p
+= scrreg_top
* linelongs
;
1421 endp
+= yy
* linelongs
;
1424 case 2: /* Whole screen */
1425 p
+= scrreg_top
* linelongs
;
1426 if (scrreg_bottom
== vinfo
.v_rows
) {
1427 endp
+= rowlongs
* vinfo
.v_height
;
1429 endp
+= scrreg_bottom
* linelongs
;
1434 for (row
= p
; row
< endp
; row
+= rowlongs
) {
1435 for (col
= 0; col
< rowline
; col
++)
1436 *(row
+col
) = vc_color_back
;
1441 vc_render_char(unsigned char ch
, unsigned char *renderptr
, short newdepth
)
1444 unsigned char *charptr
;
1445 unsigned short *shortptr
;
1447 } current
; /* current place in rendered font, multiple types. */
1448 unsigned char *theChar
; /* current char in iso_font */
1451 current
.charptr
= renderptr
;
1452 theChar
= iso_font
+ (ch
* ISO_CHAR_HEIGHT
);
1454 for (line
= 0; line
< ISO_CHAR_HEIGHT
; line
++) {
1455 unsigned char mask
= 1;
1459 *current
.charptr
++ = (*theChar
& mask
) ? 0xFF : 0;
1462 *current
.shortptr
++ = (*theChar
& mask
) ? 0xFFFF : 0;
1467 *current
.longptr
++ = (*theChar
& mask
) ? 0xFFFFFFFF : 0;
1471 } while (mask
); /* while the single bit drops to the right */
1477 vc_paint_char_8(unsigned int xx
, unsigned int yy
, unsigned char ch
, int attrs
,
1478 __unused
unsigned char ch_previous
, __unused
int attrs_previous
)
1484 if (vc_rendered_font
) {
1485 theChar
= (uint32_t*)(vc_rendered_font
+ (ch
* vc_rendered_char_size
));
1487 vc_render_char(ch
, vc_rendered_char
, 8);
1488 theChar
= (uint32_t*)(vc_rendered_char
);
1490 where
= (uint32_t*)(vinfo
.v_baseaddr
+
1491 (yy
* ISO_CHAR_HEIGHT
* vinfo
.v_rowbytes
) +
1492 (xx
* ISO_CHAR_WIDTH
));
1494 if (!attrs
) for (i
= 0; i
< ISO_CHAR_HEIGHT
; i
++) { /* No attr? FLY !*/
1495 uint32_t *store
= where
;
1497 for (x
= 0; x
< 2; x
++) {
1498 uint32_t val
= *theChar
++;
1499 val
= (vc_color_back
& ~val
) | (vc_color_fore
& val
);
1503 where
= (uint32_t*)(((unsigned char*)where
)+vinfo
.v_rowbytes
);
1504 } else for (i
= 0; i
< ISO_CHAR_HEIGHT
; i
++) { /* a little slower */
1505 uint32_t *store
= where
, lastpixel
= 0;
1507 for (x
= 0 ; x
< 2; x
++) {
1508 uint32_t val
= *theChar
++, save
= val
;
1509 if (attrs
& ATTR_BOLD
) { /* bold support */
1510 if (lastpixel
&& !(save
& 0xFF000000))
1512 if ((save
& 0xFFFF0000) == 0xFF000000)
1514 if ((save
& 0x00FFFF00) == 0x00FF0000)
1516 if ((save
& 0x0000FFFF) == 0x0000FF00)
1519 if (attrs
& ATTR_REVERSE
) val
= ~val
;
1520 if (attrs
& ATTR_UNDER
&& i
== ISO_CHAR_HEIGHT
-1) val
= ~val
;
1522 val
= (vc_color_back
& ~val
) | (vc_color_fore
& val
);
1524 lastpixel
= save
& 0xff;
1527 where
= (uint32_t*)(((unsigned char*)where
)+vinfo
.v_rowbytes
);
1533 vc_paint_char_16(unsigned int xx
, unsigned int yy
, unsigned char ch
, int attrs
,
1534 __unused
unsigned char ch_previous
,
1535 __unused
int attrs_previous
)
1541 if (vc_rendered_font
) {
1542 theChar
= (uint32_t*)(vc_rendered_font
+ (ch
* vc_rendered_char_size
));
1544 vc_render_char(ch
, vc_rendered_char
, 16);
1545 theChar
= (uint32_t*)(vc_rendered_char
);
1547 where
= (uint32_t*)(vinfo
.v_baseaddr
+
1548 (yy
* ISO_CHAR_HEIGHT
* vinfo
.v_rowbytes
) +
1549 (xx
* ISO_CHAR_WIDTH
* 2));
1551 if (!attrs
) for (i
= 0; i
< ISO_CHAR_HEIGHT
; i
++) { /* No attrs ? FLY ! */
1552 uint32_t *store
= where
;
1554 for (x
= 0; x
< 4; x
++) {
1555 uint32_t val
= *theChar
++;
1556 val
= (vc_color_back
& ~val
) | (vc_color_fore
& val
);
1560 where
= (uint32_t*)(((unsigned char*)where
)+vinfo
.v_rowbytes
);
1561 } else for (i
= 0; i
< ISO_CHAR_HEIGHT
; i
++) { /* a little bit slower */
1562 uint32_t *store
= where
, lastpixel
= 0;
1564 for (x
= 0 ; x
< 4; x
++) {
1565 uint32_t val
= *theChar
++, save
= val
;
1566 if (attrs
& ATTR_BOLD
) { /* bold support */
1567 if (save
== 0xFFFF0000) val
|= 0xFFFF;
1568 else if (lastpixel
&& !(save
& 0xFFFF0000))
1571 if (attrs
& ATTR_REVERSE
) val
= ~val
;
1572 if (attrs
& ATTR_UNDER
&& i
== ISO_CHAR_HEIGHT
-1) val
= ~val
;
1574 val
= (vc_color_back
& ~val
) | (vc_color_fore
& val
);
1577 lastpixel
= save
& 0x7fff;
1580 where
= (uint32_t*)(((unsigned char*)where
)+vinfo
.v_rowbytes
);
1586 vc_paint_char_32(unsigned int xx
, unsigned int yy
, unsigned char ch
, int attrs
,
1587 unsigned char ch_previous
, int attrs_previous
)
1590 uint32_t *theCharPrevious
;
1594 if (vc_rendered_font
) {
1595 theChar
= (uint32_t*)(vc_rendered_font
+ (ch
* vc_rendered_char_size
));
1596 theCharPrevious
= (uint32_t*)(vc_rendered_font
+ (ch_previous
* vc_rendered_char_size
));
1598 vc_render_char(ch
, vc_rendered_char
, 32);
1599 theChar
= (uint32_t*)(vc_rendered_char
);
1600 theCharPrevious
= NULL
;
1603 theCharPrevious
= NULL
;
1605 if (attrs_previous
) {
1606 theCharPrevious
= NULL
;
1608 where
= (uint32_t*)(vinfo
.v_baseaddr
+
1609 (yy
* ISO_CHAR_HEIGHT
* vinfo
.v_rowbytes
) +
1610 (xx
* ISO_CHAR_WIDTH
* 4));
1612 if (!attrs
) for (i
= 0; i
< ISO_CHAR_HEIGHT
; i
++) { /* No attrs ? FLY ! */
1613 uint32_t *store
= where
;
1615 for (x
= 0; x
< 8; x
++) {
1616 uint32_t val
= *theChar
++;
1617 if (theCharPrevious
== NULL
|| val
!= *theCharPrevious
++ ) {
1618 val
= (vc_color_back
& ~val
) | (vc_color_fore
& val
);
1625 where
= (uint32_t *)(((unsigned char*)where
)+vinfo
.v_rowbytes
);
1626 } else for (i
= 0; i
< ISO_CHAR_HEIGHT
; i
++) { /* a little slower */
1627 uint32_t *store
= where
, lastpixel
= 0;
1629 for (x
= 0 ; x
< 8; x
++) {
1630 uint32_t val
= *theChar
++, save
= val
;
1631 if (attrs
& ATTR_BOLD
) { /* bold support */
1632 if (lastpixel
&& !save
)
1635 if (attrs
& ATTR_REVERSE
) val
= ~val
;
1636 if (attrs
& ATTR_UNDER
&& i
== ISO_CHAR_HEIGHT
-1) val
= ~val
;
1638 val
= (vc_color_back
& ~val
) | (vc_color_fore
& val
);
1643 where
= (uint32_t*)(((unsigned char*)where
)+vinfo
.v_rowbytes
);
1649 vc_paint_char(unsigned int xx
, unsigned int yy
, unsigned char ch
, int attrs
,
1650 unsigned char ch_previous
, int attrs_previous
)
1655 switch(vinfo
.v_depth
) {
1657 vc_paint_char_8(xx
, yy
, ch
, attrs
, ch_previous
, attrs_previous
);
1660 vc_paint_char_16(xx
, yy
, ch
, attrs
, ch_previous
,
1665 vc_paint_char_32(xx
, yy
, ch
, attrs
, ch_previous
,
1672 vc_render_font(short newdepth
)
1674 static short olddepth
= 0;
1676 int charindex
; /* index in ISO font */
1677 unsigned char *rendered_font
;
1678 unsigned int rendered_font_size
;
1679 int rendered_char_size
;
1682 if (vm_initialized
== FALSE
) {
1683 return; /* nothing to do */
1685 if (olddepth
== newdepth
&& vc_rendered_font
) {
1686 return; /* nothing to do */
1692 rendered_font
= vc_rendered_font
;
1693 rendered_font_size
= vc_rendered_font_size
;
1694 rendered_char_size
= vc_rendered_char_size
;
1696 vc_rendered_font
= NULL
;
1697 vc_rendered_font_size
= 0;
1698 vc_rendered_char_size
= 0;
1700 VCPUTC_LOCK_UNLOCK();
1703 if (rendered_font
) {
1704 kfree(rendered_font
, rendered_font_size
);
1705 rendered_font
= NULL
;
1709 rendered_char_size
= ISO_CHAR_HEIGHT
* (((newdepth
+ 7) / 8) * ISO_CHAR_WIDTH
);
1710 rendered_font_size
= (ISO_CHAR_MAX
-ISO_CHAR_MIN
+1) * rendered_char_size
;
1711 rendered_font
= (unsigned char *) kalloc(rendered_font_size
);
1714 if (rendered_font
== NULL
) {
1718 for (charindex
= ISO_CHAR_MIN
; charindex
<= ISO_CHAR_MAX
; charindex
++) {
1719 vc_render_char(charindex
, rendered_font
+ (charindex
* rendered_char_size
), newdepth
);
1722 olddepth
= newdepth
;
1727 vc_rendered_font
= rendered_font
;
1728 vc_rendered_font_size
= rendered_font_size
;
1729 vc_rendered_char_size
= rendered_char_size
;
1731 VCPUTC_LOCK_UNLOCK();
1736 vc_enable(boolean_t enable
)
1738 vc_render_font(enable
? vinfo
.v_depth
: 0);
1742 vc_reverse_cursor(unsigned int xx
, unsigned int yy
)
1750 where
= (uint32_t*)(vinfo
.v_baseaddr
+
1751 (yy
* ISO_CHAR_HEIGHT
* vinfo
.v_rowbytes
) +
1752 (xx
/** ISO_CHAR_WIDTH*/ * vinfo
.v_depth
));
1753 for (line
= 0; line
< ISO_CHAR_HEIGHT
; line
++) {
1754 switch (vinfo
.v_depth
) {
1756 where
[0] = ~where
[0];
1757 where
[1] = ~where
[1];
1760 for (col
= 0; col
< 4; col
++)
1761 where
[col
] = ~where
[col
];
1764 for (col
= 0; col
< 8; col
++)
1765 where
[col
] = ~where
[col
];
1768 where
= (uint32_t*)(((unsigned char*)where
)+vinfo
.v_rowbytes
);
1773 vc_scroll_down(int num
, unsigned int scrreg_top
, unsigned int scrreg_bottom
)
1775 uint32_t *from
, *to
, linelongs
, i
, line
, rowline
, rowscanline
;
1780 linelongs
= vinfo
.v_rowbytes
* (ISO_CHAR_HEIGHT
>> 2);
1781 rowline
= vinfo
.v_rowbytes
>> 2;
1782 rowscanline
= vinfo
.v_rowscanbytes
>> 2;
1784 to
= (uint32_t *) vinfo
.v_baseaddr
+ (linelongs
* scrreg_bottom
)
1785 - (rowline
- rowscanline
);
1786 from
= to
- (linelongs
* num
); /* handle multiple line scroll (Michel Pollet) */
1788 i
= (scrreg_bottom
- scrreg_top
) - num
;
1791 for (line
= 0; line
< ISO_CHAR_HEIGHT
; line
++) {
1793 * Only copy what is displayed
1795 video_scroll_down(from
,
1796 (from
-(vinfo
.v_rowscanbytes
>> 2)),
1806 vc_scroll_up(int num
, unsigned int scrreg_top
, unsigned int scrreg_bottom
)
1808 uint32_t *from
, *to
, linelongs
, i
, line
, rowline
, rowscanline
;
1813 linelongs
= vinfo
.v_rowbytes
* (ISO_CHAR_HEIGHT
>> 2);
1814 rowline
= vinfo
.v_rowbytes
>> 2;
1815 rowscanline
= vinfo
.v_rowscanbytes
>> 2;
1817 to
= (uint32_t *) vinfo
.v_baseaddr
+ (scrreg_top
* linelongs
);
1818 from
= to
+ (linelongs
* num
); /* handle multiple line scroll (Michel Pollet) */
1820 i
= (scrreg_bottom
- scrreg_top
) - num
;
1823 for (line
= 0; line
< ISO_CHAR_HEIGHT
; line
++) {
1825 * Only copy what is displayed
1827 video_scroll_up(from
,
1828 (from
+(vinfo
.v_rowscanbytes
>> 2)),
1838 vc_update_color(int color
, boolean_t fore
)
1843 vc_color_fore
= vc_colors
[color
][vc_color_index_table
[vinfo
.v_depth
]];
1845 vc_color_back
= vc_colors
[color
][vc_color_index_table
[vinfo
.v_depth
]];
1850 * Video Console (Back-End): Icon Control
1851 * --------------------------------------
1854 static vc_progress_element
* vc_progress
;
1855 enum { kMaxProgressData
= 3 };
1856 static const unsigned char * vc_progress_data
[kMaxProgressData
];
1857 static const unsigned char * vc_progress_alpha
;
1858 static boolean_t vc_progress_enable
;
1859 static const unsigned char * vc_clut
;
1860 static const unsigned char * vc_clut8
;
1861 static unsigned char vc_revclut8
[256];
1862 static uint32_t vc_progress_interval
;
1863 static uint32_t vc_progress_count
;
1864 static uint32_t vc_progress_angle
;
1865 static uint64_t vc_progress_deadline
;
1866 static thread_call_data_t vc_progress_call
;
1867 static boolean_t vc_needsave
;
1868 static void * vc_saveunder
;
1869 static vm_size_t vc_saveunder_len
;
1870 static int8_t vc_uiscale
= 1;
1871 vc_progress_user_options vc_progress_options
;
1872 vc_progress_user_options vc_user_options
;
1874 decl_simple_lock_data(,vc_progress_lock
)
1876 #if !CONFIG_EMBEDDED
1877 static int vc_progress_withmeter
= 3;
1878 int vc_progressmeter_enable
;
1879 static int vc_progressmeter_drawn
;
1880 int vc_progressmeter_value
;
1881 static uint32_t vc_progressmeter_count
;
1882 static uint32_t vc_progress_meter_start
;
1883 static uint32_t vc_progress_meter_end
;
1884 static uint64_t vc_progressmeter_interval
;
1885 static uint64_t vc_progressmeter_deadline
;
1886 static thread_call_data_t vc_progressmeter_call
;
1887 static void * vc_progressmeter_backbuffer
;
1888 static boolean_t vc_progressmeter_hold
;
1889 static uint32_t vc_progressmeter_diskspeed
= 256;
1891 #endif /* !CONFIG_EMBEDDED */
1895 kDataIndexed
= 0x20,
1905 static void vc_blit_rect(int x
, int y
, int bx
,
1906 int width
, int height
,
1907 int sourceRow
, int backRow
,
1908 const unsigned char * dataPtr
,
1910 unsigned int flags
);
1911 static void vc_blit_rect_8(int x
, int y
, int bx
,
1912 int width
, int height
,
1913 int sourceRow
, int backRow
,
1914 const unsigned char * dataPtr
,
1915 unsigned char * backBuffer
,
1916 unsigned int flags
);
1917 static void vc_blit_rect_16(int x
, int y
, int bx
,
1918 int width
, int height
,
1919 int sourceRow
, int backRow
,
1920 const unsigned char * dataPtr
,
1921 unsigned short * backBuffer
,
1922 unsigned int flags
);
1923 static void vc_blit_rect_32(int x
, int y
, int bx
,
1924 int width
, int height
,
1925 int sourceRow
, int backRow
,
1926 const unsigned char * dataPtr
,
1927 unsigned int * backBuffer
,
1928 unsigned int flags
);
1929 static void vc_blit_rect_30(int x
, int y
, int bx
,
1930 int width
, int height
,
1931 int sourceRow
, int backRow
,
1932 const unsigned char * dataPtr
,
1933 unsigned int * backBuffer
,
1934 unsigned int flags
);
1935 static void vc_progress_task( void * arg0
, void * arg
);
1936 #if !CONFIG_EMBEDDED
1937 static void vc_progressmeter_task( void * arg0
, void * arg
);
1938 #endif /* !CONFIG_EMBEDDED */
1940 static void vc_blit_rect(int x
, int y
, int bx
,
1941 int width
, int height
,
1942 int sourceRow
, int backRow
,
1943 const unsigned char * dataPtr
,
1947 if (!vinfo
.v_depth
) return;
1948 if (((unsigned int)(x
+ width
)) > vinfo
.v_width
) return;
1949 if (((unsigned int)(y
+ height
)) > vinfo
.v_height
) return;
1951 switch( vinfo
.v_depth
) {
1953 if( vc_clut8
== vc_clut
)
1954 vc_blit_rect_8( x
, y
, bx
, width
, height
, sourceRow
, backRow
, dataPtr
, (unsigned char *) backBuffer
, flags
);
1957 vc_blit_rect_16( x
, y
, bx
, width
, height
, sourceRow
, backRow
, dataPtr
, (unsigned short *) backBuffer
, flags
);
1960 vc_blit_rect_32( x
, y
, bx
, width
, height
, sourceRow
, backRow
, dataPtr
, (unsigned int *) backBuffer
, flags
);
1963 vc_blit_rect_30( x
, y
, bx
, width
, height
, sourceRow
, backRow
, dataPtr
, (unsigned int *) backBuffer
, flags
);
1969 vc_blit_rect_8(int x
, int y
, __unused
int bx
,
1970 int width
, int height
,
1971 int sourceRow
, __unused
int backRow
,
1972 const unsigned char * dataPtr
,
1973 __unused
unsigned char * backBuffer
,
1974 __unused
unsigned int flags
)
1976 volatile unsigned short * dst
;
1978 unsigned int data
= 0, out
= 0;
1979 int sx
, sy
, a
, b
, c
, d
;
1980 int scale
= 0x10000;
1982 a
= vc_rotate_matr
[kDataRotate
& flags
][0][0] * scale
;
1983 b
= vc_rotate_matr
[kDataRotate
& flags
][0][1] * scale
;
1984 c
= vc_rotate_matr
[kDataRotate
& flags
][1][0] * scale
;
1985 d
= vc_rotate_matr
[kDataRotate
& flags
][1][1] * scale
;
1986 sx
= ((a
+ b
) < 0) ? ((width
* scale
) - 0x8000) : 0;
1987 sy
= ((c
+ d
) < 0) ? ((height
* scale
) - 0x8000) : 0;
1989 if (!sourceRow
) data
= (unsigned int)(uintptr_t)dataPtr
;
1990 else if (1 == sourceRow
) a
= 0;
1992 dst
= (volatile unsigned short *) (vinfo
.v_baseaddr
+
1993 (y
* vinfo
.v_rowbytes
) +
1996 for( line
= 0; line
< height
; line
++)
1998 for( col
= 0; col
< width
; col
++)
2000 if (sourceRow
) data
= dataPtr
[((sx
+ (col
* a
) + (line
* b
)) >> 16)
2001 + sourceRow
* (((sy
+ (col
* c
) + (line
* d
)) >> 16))];
2002 if (kDataAlpha
& flags
)
2003 out
= vc_revclut8
[data
];
2008 dst
= (volatile unsigned short *) (((volatile char*)dst
) + vinfo
.v_rowbytes
);
2012 /* For ARM, 16-bit is 565 (RGB); it is 1555 (XRGB) on other platforms */
2015 #define CLUT_MASK_R 0xf8
2016 #define CLUT_MASK_G 0xfc
2017 #define CLUT_MASK_B 0xf8
2018 #define CLUT_SHIFT_R << 8
2019 #define CLUT_SHIFT_G << 3
2020 #define CLUT_SHIFT_B >> 3
2021 #define MASK_R 0xf800
2022 #define MASK_G 0x07e0
2023 #define MASK_B 0x001f
2024 #define MASK_R_8 0x7f800
2025 #define MASK_G_8 0x01fe0
2026 #define MASK_B_8 0x000ff
2028 #define CLUT_MASK_R 0xf8
2029 #define CLUT_MASK_G 0xf8
2030 #define CLUT_MASK_B 0xf8
2031 #define CLUT_SHIFT_R << 7
2032 #define CLUT_SHIFT_G << 2
2033 #define CLUT_SHIFT_B >> 3
2034 #define MASK_R 0x7c00
2035 #define MASK_G 0x03e0
2036 #define MASK_B 0x001f
2037 #define MASK_R_8 0x3fc00
2038 #define MASK_G_8 0x01fe0
2039 #define MASK_B_8 0x000ff
2042 static void vc_blit_rect_16( int x
, int y
, int bx
,
2043 int width
, int height
,
2044 int sourceRow
, int backRow
,
2045 const unsigned char * dataPtr
,
2046 unsigned short * backPtr
,
2049 volatile unsigned short * dst
;
2051 unsigned int data
= 0, out
= 0, back
= 0;
2052 int sx
, sy
, a
, b
, c
, d
;
2053 int scale
= 0x10000;
2055 a
= vc_rotate_matr
[kDataRotate
& flags
][0][0] * scale
;
2056 b
= vc_rotate_matr
[kDataRotate
& flags
][0][1] * scale
;
2057 c
= vc_rotate_matr
[kDataRotate
& flags
][1][0] * scale
;
2058 d
= vc_rotate_matr
[kDataRotate
& flags
][1][1] * scale
;
2059 sx
= ((a
+ b
) < 0) ? ((width
* scale
) - 0x8000) : 0;
2060 sy
= ((c
+ d
) < 0) ? ((height
* scale
) - 0x8000) : 0;
2062 if (!sourceRow
) data
= (unsigned int)(uintptr_t)dataPtr
;
2063 else if (1 == sourceRow
) a
= 0;
2067 dst
= (volatile unsigned short *) (vinfo
.v_baseaddr
+
2068 (y
* vinfo
.v_rowbytes
) +
2071 for( line
= 0; line
< height
; line
++)
2073 for( col
= 0; col
< width
; col
++)
2075 if (sourceRow
) data
= dataPtr
[((sx
+ (col
* a
) + (line
* b
)) >> 16)
2076 + sourceRow
* (((sy
+ (col
* c
) + (line
* d
)) >> 16))];
2078 if (kSave
& flags
) {
2079 back
= *(dst
+ col
);
2084 if (kDataIndexed
& flags
) {
2085 out
= ( (CLUT_MASK_R
& (vc_clut
[data
*3 + 0])) CLUT_SHIFT_R
)
2086 | ( (CLUT_MASK_G
& (vc_clut
[data
*3 + 1])) CLUT_SHIFT_G
)
2087 | ( (CLUT_MASK_B
& (vc_clut
[data
*3 + 2])) CLUT_SHIFT_B
);
2088 } else if (kDataAlpha
& flags
) {
2089 out
= (((((back
& MASK_R
) * data
) + MASK_R_8
) >> 8) & MASK_R
)
2090 | (((((back
& MASK_G
) * data
) + MASK_G_8
) >> 8) & MASK_G
)
2091 | (((((back
& MASK_B
) * data
) + MASK_B_8
) >> 8) & MASK_B
);
2092 if (vc_progress_white
) out
+= (((0xff - data
) & CLUT_MASK_R
) CLUT_SHIFT_R
)
2093 | (((0xff - data
) & CLUT_MASK_G
) CLUT_SHIFT_G
)
2094 | (((0xff - data
) & CLUT_MASK_B
) CLUT_SHIFT_B
);
2095 } else if (kDataBack
& flags
)
2101 dst
= (volatile unsigned short *) (((volatile char*)dst
) + vinfo
.v_rowbytes
);
2103 backPtr
+= backRow
- width
;
2108 static void vc_blit_rect_32(int x
, int y
, int bx
,
2109 int width
, int height
,
2110 int sourceRow
, int backRow
,
2111 const unsigned char * dataPtr
,
2112 unsigned int * backPtr
,
2115 volatile unsigned int * dst
;
2117 unsigned int data
= 0, out
= 0, back
= 0;
2118 int sx
, sy
, a
, b
, c
, d
;
2119 int scale
= 0x10000;
2121 a
= vc_rotate_matr
[kDataRotate
& flags
][0][0] * scale
;
2122 b
= vc_rotate_matr
[kDataRotate
& flags
][0][1] * scale
;
2123 c
= vc_rotate_matr
[kDataRotate
& flags
][1][0] * scale
;
2124 d
= vc_rotate_matr
[kDataRotate
& flags
][1][1] * scale
;
2125 sx
= ((a
+ b
) < 0) ? ((width
* scale
) - 0x8000) : 0;
2126 sy
= ((c
+ d
) < 0) ? ((height
* scale
) - 0x8000) : 0;
2128 if (!sourceRow
) data
= (unsigned int)(uintptr_t)dataPtr
;
2129 else if (1 == sourceRow
) a
= 0;
2133 dst
= (volatile unsigned int *) (vinfo
.v_baseaddr
+
2134 (y
* vinfo
.v_rowbytes
) +
2137 for( line
= 0; line
< height
; line
++)
2139 for( col
= 0; col
< width
; col
++)
2141 if (sourceRow
) data
= dataPtr
[((sx
+ (col
* a
) + (line
* b
)) >> 16)
2142 + sourceRow
* (((sy
+ (col
* c
) + (line
* d
)) >> 16))];
2144 if (kSave
& flags
) {
2145 back
= *(dst
+ col
);
2150 if (kDataIndexed
& flags
) {
2151 out
= (vc_clut
[data
*3 + 0] << 16)
2152 | (vc_clut
[data
*3 + 1] << 8)
2153 | (vc_clut
[data
*3 + 2]);
2154 } else if (kDataAlpha
& flags
) {
2155 out
= (((((back
& 0x00ff00ff) * data
) + 0x00ff00ff) >> 8) & 0x00ff00ff)
2156 | (((((back
& 0x0000ff00) * data
) + 0x0000ff00) >> 8) & 0x0000ff00);
2157 if (vc_progress_white
) out
+= ((0xff - data
) << 16)
2158 | ((0xff - data
) << 8)
2160 } else if (kDataBack
& flags
)
2166 dst
= (volatile unsigned int *) (((volatile char*)dst
) + vinfo
.v_rowbytes
);
2168 backPtr
+= backRow
- width
;
2172 static void vc_blit_rect_30(int x
, int y
, int bx
,
2173 int width
, int height
,
2174 int sourceRow
, int backRow
,
2175 const unsigned char * dataPtr
,
2176 unsigned int * backPtr
,
2179 volatile unsigned int * dst
;
2181 unsigned int data
= 0, out
= 0, back
= 0;
2182 unsigned long long exp
;
2183 int sx
, sy
, a
, b
, c
, d
;
2184 int scale
= 0x10000;
2186 a
= vc_rotate_matr
[kDataRotate
& flags
][0][0] * scale
;
2187 b
= vc_rotate_matr
[kDataRotate
& flags
][0][1] * scale
;
2188 c
= vc_rotate_matr
[kDataRotate
& flags
][1][0] * scale
;
2189 d
= vc_rotate_matr
[kDataRotate
& flags
][1][1] * scale
;
2190 sx
= ((a
+ b
) < 0) ? ((width
* scale
) - 0x8000) : 0;
2191 sy
= ((c
+ d
) < 0) ? ((height
* scale
) - 0x8000) : 0;
2193 if (!sourceRow
) data
= (unsigned int)(uintptr_t)dataPtr
;
2194 else if (1 == sourceRow
) a
= 0;
2198 dst
= (volatile unsigned int *) (vinfo
.v_baseaddr
+
2199 (y
* vinfo
.v_rowbytes
) +
2202 for( line
= 0; line
< height
; line
++)
2204 for( col
= 0; col
< width
; col
++)
2206 if (sourceRow
) data
= dataPtr
[((sx
+ (col
* a
) + (line
* b
)) >> 16)
2207 + sourceRow
* (((sy
+ (col
* c
) + (line
* d
)) >> 16))];
2209 if (kSave
& flags
) {
2210 back
= *(dst
+ col
);
2215 if (kDataIndexed
& flags
) {
2216 out
= (vc_clut
[data
*3 + 0] << 22)
2217 | (vc_clut
[data
*3 + 1] << 12)
2218 | (vc_clut
[data
*3 + 2] << 2);
2219 } else if (kDataAlpha
& flags
) {
2221 exp
= (((((exp
& 0x3FF003FF) * data
) + 0x0FF000FF) >> 8) & 0x3FF003FF)
2222 | (((((exp
& 0x000FFC00) * data
) + 0x0003FC00) >> 8) & 0x000FFC00);
2223 out
= (unsigned int)exp
;
2224 if (vc_progress_white
) out
+= ((0xFF - data
) << 22)
2225 | ((0xFF - data
) << 12)
2226 | ((0xFF - data
) << 2);
2227 } else if (kDataBack
& flags
)
2233 dst
= (volatile unsigned int *) (((volatile char*)dst
) + vinfo
.v_rowbytes
);
2235 backPtr
+= backRow
- width
;
2239 static void vc_clean_boot_graphics(void)
2241 #if !CONFIG_EMBEDDED
2242 // clean up possible FDE login graphics
2243 vc_progress_set(FALSE
, 0);
2244 const unsigned char *
2245 color
= (typeof(color
))(uintptr_t)(vc_progress_white
? 0x00000000 : 0xBFBFBFBF);
2246 vc_blit_rect(0, 0, 0, vinfo
.v_width
, vinfo
.v_height
, 0, 0, color
, NULL
, 0);
2251 * Routines to render the lzss image format
2254 struct lzss_image_state
{
2259 uint32_t bytes_per_row
;
2260 volatile uint32_t * row_start
;
2261 const uint8_t* clut
;
2263 typedef struct lzss_image_state lzss_image_state
;
2265 // returns 0 if OK, 1 if error
2267 vc_decompress_lzss_next_pixel (int next_data
, lzss_image_state
* state
)
2269 uint32_t palette_index
= 0;
2270 uint32_t pixel_value
= 0;
2272 palette_index
= next_data
* 3;
2274 pixel_value
= ( (uint32_t) state
->clut
[palette_index
+ 0] << 16)
2275 | ( (uint32_t) state
->clut
[palette_index
+ 1] << 8)
2276 | ( (uint32_t) state
->clut
[palette_index
+ 2]);
2278 *(state
->row_start
+ state
->col
) = pixel_value
;
2280 if (++state
->col
>= state
->width
) {
2282 if (++state
->row
>= state
->height
) {
2285 state
->row_start
= (volatile uint32_t *) (((uintptr_t)state
->row_start
) + state
->bytes_per_row
);
2292 * Blit an lzss compressed image to the framebuffer
2293 * Assumes 32 bit screen (which is everything we ship at the moment)
2294 * The function vc_display_lzss_icon was copied from libkern/mkext.c, then modified.
2298 * TODO: Does lzss use too much stack? 4096 plus bytes...
2299 * Can probably chop it down by 1/2.
2302 /**************************************************************
2303 LZSS.C -- A Data Compression Program
2304 ***************************************************************
2305 4/6/1989 Haruhiko Okumura
2306 Use, distribute, and modify this program freely.
2307 Please send me your improved versions.
2309 NIFTY-Serve PAF01022
2310 CompuServe 74050,1022
2312 **************************************************************/
2314 #define N 4096 /* size of ring buffer - must be power of 2 */
2315 #define F 18 /* upper limit for match_length */
2316 #define THRESHOLD 2 /* encode string into position and length
2317 if match_length is greater than this */
2319 // returns 0 if OK, 1 if error
2320 // x and y indicate upper left corner of image location on screen
2322 vc_display_lzss_icon(uint32_t dst_x
, uint32_t dst_y
,
2323 uint32_t image_width
, uint32_t image_height
,
2324 const uint8_t *compressed_image
,
2325 uint32_t compressed_size
,
2326 const uint8_t *clut
)
2328 uint32_t* image_start
;
2329 uint32_t bytes_per_pixel
= 4;
2330 uint32_t bytes_per_row
= vinfo
.v_rowbytes
;
2332 vc_clean_boot_graphics();
2334 image_start
= (uint32_t *) (vinfo
.v_baseaddr
+ (dst_y
* bytes_per_row
) + (dst_x
* bytes_per_pixel
));
2336 lzss_image_state state
= {0, 0, image_width
, image_height
, bytes_per_row
, image_start
, clut
};
2340 const uint8_t *src
= compressed_image
;
2341 uint32_t srclen
= compressed_size
;
2343 /* ring buffer of size N, with extra F-1 bytes to aid string comparison */
2344 uint8_t text_buf
[N
+ F
- 1];
2345 const uint8_t *srcend
= src
+ srclen
;
2349 srcend
= src
+ srclen
;
2350 for (i
= 0; i
< N
- F
; i
++)
2355 if (((flags
>>= 1) & 0x100) == 0) {
2356 if (src
< srcend
) c
= *src
++; else break;
2357 flags
= c
| 0xFF00; /* uses higher byte cleverly */
2358 } /* to count eight */
2360 if (src
< srcend
) c
= *src
++; else break;
2361 rval
= vc_decompress_lzss_next_pixel(c
, &state
);
2367 if (src
< srcend
) i
= *src
++; else break;
2368 if (src
< srcend
) j
= *src
++; else break;
2369 i
|= ((j
& 0xF0) << 4);
2370 j
= (j
& 0x0F) + THRESHOLD
;
2371 for (k
= 0; k
<= j
; k
++) {
2372 c
= text_buf
[(i
+ k
) & (N
- 1)];
2373 rval
= vc_decompress_lzss_next_pixel(c
, &state
);
2384 void noroot_icon_test(void) {
2385 boolean_t o_vc_progress_enable
= vc_progress_enable
;
2387 vc_progress_enable
= 1;
2389 PE_display_icon( 0, "noroot");
2391 vc_progress_enable
= o_vc_progress_enable
;
2395 void vc_display_icon( vc_progress_element
* desc
,
2396 const unsigned char * data
)
2398 int x
, y
, width
, height
;
2400 if( vc_progress_enable
&& vc_clut
) {
2402 vc_clean_boot_graphics();
2404 width
= desc
->width
;
2405 height
= desc
->height
;
2408 if( 1 & desc
->flags
) {
2409 x
+= ((vinfo
.v_width
- width
) / 2);
2410 y
+= ((vinfo
.v_height
- height
) / 2);
2412 vc_blit_rect( x
, y
, 0, width
, height
, width
, 0, data
, NULL
, kDataIndexed
);
2417 vc_progress_initialize( vc_progress_element
* desc
,
2418 const unsigned char * data1x
,
2419 const unsigned char * data2x
,
2420 const unsigned char * data3x
,
2421 const unsigned char * clut
)
2425 if( (!clut
) || (!desc
) || (!data1x
))
2431 vc_progress_data
[0] = data1x
;
2432 vc_progress_data
[1] = data2x
;
2433 vc_progress_data
[2] = data3x
;
2434 if( 2 & vc_progress
->flags
)
2435 vc_progress_alpha
= data1x
2436 + vc_progress
->count
* vc_progress
->width
* vc_progress
->height
;
2438 vc_progress_alpha
= NULL
;
2440 thread_call_setup(&vc_progress_call
, vc_progress_task
, NULL
);
2441 clock_interval_to_absolutetime_interval(vc_progress
->time
, 1000 * 1000, &abstime
);
2442 vc_progress_interval
= (uint32_t)abstime
;
2444 #if !CONFIG_EMBEDDED
2445 thread_call_setup(&vc_progressmeter_call
, vc_progressmeter_task
, NULL
);
2446 clock_interval_to_absolutetime_interval(1000 / 8, 1000 * 1000, &abstime
);
2447 vc_progressmeter_interval
= (uint32_t)abstime
;
2448 #endif /* !CONFIG_EMBEDDED */
2453 vc_progress_set(boolean_t enable
, uint32_t vc_delay
)
2456 void *saveBuf
= NULL
;
2457 vm_size_t saveLen
= 0;
2460 unsigned char pdata8
;
2461 unsigned short pdata16
;
2462 unsigned short * buf16
;
2463 unsigned int pdata32
;
2464 unsigned int * buf32
;
2466 #if !CONFIG_EMBEDDED
2468 if (kBootArgsFlagBlack
& ((boot_args
*) PE_state
.bootArgs
)->flags
) return;
2470 if (1 & vc_progress_withmeter
)
2472 if (enable
) internal_enable_progressmeter(kProgressMeterKernel
);
2475 simple_lock(&vc_progress_lock
);
2477 if( vc_progress_enable
!= enable
) {
2478 vc_progress_enable
= enable
;
2481 vc_progressmeter_count
= 0;
2482 clock_interval_to_deadline(vc_delay
,
2483 1000 * 1000 * 1000 /*second scale*/,
2484 &vc_progressmeter_deadline
);
2485 thread_call_enter_delayed(&vc_progressmeter_call
, vc_progressmeter_deadline
);
2487 else thread_call_cancel(&vc_progressmeter_call
);
2490 simple_unlock(&vc_progress_lock
);
2493 if (!enable
) internal_enable_progressmeter(kProgressMeterOff
);
2497 #endif /* !CONFIG_EMBEDDED */
2499 if(!vc_progress
) return;
2502 saveLen
= (vc_progress
->width
* vc_uiscale
) * (vc_progress
->height
* vc_uiscale
) * ((vinfo
.v_depth
+ 7) / 8);
2503 saveBuf
= kalloc( saveLen
);
2505 switch( vinfo
.v_depth
) {
2507 for( count
= 0; count
< 256; count
++) {
2508 vc_revclut8
[count
] = vc_clut
[0x01 * 3];
2509 pdata8
= (vc_clut
[0x01 * 3] * count
+ 0x0ff) >> 8;
2510 for( index
= 0; index
< 256; index
++) {
2511 if( (pdata8
== vc_clut
[index
* 3 + 0]) &&
2512 (pdata8
== vc_clut
[index
* 3 + 1]) &&
2513 (pdata8
== vc_clut
[index
* 3 + 2])) {
2514 vc_revclut8
[count
] = index
;
2519 memset( saveBuf
, 0x01, saveLen
);
2523 buf16
= (unsigned short *) saveBuf
;
2524 pdata16
= ((vc_clut
[0x01 * 3 + 0] & CLUT_MASK_R
) CLUT_SHIFT_R
)
2525 | ((vc_clut
[0x01 * 3 + 0] & CLUT_MASK_G
) CLUT_SHIFT_G
)
2526 | ((vc_clut
[0x01 * 3 + 0] & CLUT_MASK_B
) CLUT_SHIFT_B
);
2527 for( count
= 0; count
< saveLen
/ 2; count
++)
2528 buf16
[count
] = pdata16
;
2532 buf32
= (unsigned int *) saveBuf
;
2533 pdata32
= ((vc_clut
[0x01 * 3 + 0] & 0xff) << 16)
2534 | ((vc_clut
[0x01 * 3 + 1] & 0xff) << 8)
2535 | ((vc_clut
[0x01 * 3 + 2] & 0xff) << 0);
2536 for( count
= 0; count
< saveLen
/ 4; count
++)
2537 buf32
[count
] = pdata32
;
2543 simple_lock(&vc_progress_lock
);
2545 if( vc_progress_enable
!= enable
) {
2546 vc_progress_enable
= enable
;
2549 vc_saveunder
= saveBuf
;
2550 vc_saveunder_len
= saveLen
;
2553 vc_progress_count
= 0;
2554 vc_progress_angle
= 0;
2556 clock_interval_to_deadline(vc_delay
,
2557 1000 * 1000 * 1000 /*second scale*/,
2558 &vc_progress_deadline
);
2559 thread_call_enter_delayed(&vc_progress_call
, vc_progress_deadline
);
2563 saveBuf
= vc_saveunder
;
2564 saveLen
= vc_saveunder_len
;
2565 vc_saveunder
= NULL
;
2566 vc_saveunder_len
= 0;
2569 thread_call_cancel(&vc_progress_call
);
2573 simple_unlock(&vc_progress_lock
);
2577 kfree( saveBuf
, saveLen
);
2580 #if !CONFIG_EMBEDDED
2582 static uint32_t vc_progressmeter_range(uint32_t pos
)
2586 if (pos
> kProgressMeterEnd
) pos
= kProgressMeterEnd
;
2587 ret
= vc_progress_meter_start
2588 + ((pos
* (vc_progress_meter_end
- vc_progress_meter_start
)) / kProgressMeterEnd
);
2594 vc_progressmeter_task(__unused
void *arg0
, __unused
void *arg
)
2600 simple_lock(&vc_progress_lock
);
2601 if (vc_progressmeter_enable
)
2603 uint32_t pos
= (vc_progressmeter_count
>> 13);
2604 internal_set_progressmeter(vc_progressmeter_range(pos
));
2605 if (pos
< kProgressMeterEnd
)
2607 static uint16_t incr
[8] = { 10000, 10000, 8192, 4096, 2048, 384, 384, 64 };
2608 vc_progressmeter_count
+= incr
[(pos
* 8) / kProgressMeterEnd
];
2610 interval
= vc_progressmeter_interval
;
2611 interval
= ((interval
* 256) / vc_progressmeter_diskspeed
);
2613 clock_deadline_for_periodic_event(interval
, mach_absolute_time(), &vc_progressmeter_deadline
);
2614 thread_call_enter_delayed(&vc_progressmeter_call
, vc_progressmeter_deadline
);
2617 simple_unlock(&vc_progress_lock
);
2621 void vc_progress_setdiskspeed(uint32_t speed
)
2623 vc_progressmeter_diskspeed
= speed
;
2626 #endif /* !CONFIG_EMBEDDED */
2629 vc_progress_task(__unused
void *arg0
, __unused
void *arg
)
2632 int x
, y
, width
, height
;
2633 uint64_t x_pos
, y_pos
;
2634 const unsigned char * data
;
2637 simple_lock(&vc_progress_lock
);
2639 if( vc_progress_enable
) do {
2641 vc_progress_count
++;
2642 if( vc_progress_count
>= vc_progress
->count
) {
2643 vc_progress_count
= 0;
2644 vc_progress_angle
++;
2647 width
= (vc_progress
->width
* vc_uiscale
);
2648 height
= (vc_progress
->height
* vc_uiscale
);
2649 data
= vc_progress_data
[vc_uiscale
- 1];
2652 if (kVCUsePosition
& vc_progress_options
.options
) {
2653 /* Rotation: 0:normal, 1:right 90, 2:left 180, 3:left 90 */
2654 switch (3 & vinfo
.v_rotate
) {
2656 x_pos
= vc_progress_options
.x_pos
;
2657 y_pos
= vc_progress_options
.y_pos
;
2660 x_pos
= 0xFFFFFFFF - vc_progress_options
.x_pos
;
2661 y_pos
= 0xFFFFFFFF - vc_progress_options
.y_pos
;
2664 x_pos
= 0xFFFFFFFF - vc_progress_options
.y_pos
;
2665 y_pos
= vc_progress_options
.x_pos
;
2668 x_pos
= vc_progress_options
.y_pos
;
2669 y_pos
= 0xFFFFFFFF - vc_progress_options
.x_pos
;
2672 x
= (uint32_t)((x_pos
* (uint64_t) vinfo
.v_width
) / 0xFFFFFFFFULL
);
2673 y
= (uint32_t)((y_pos
* (uint64_t) vinfo
.v_height
) / 0xFFFFFFFFULL
);
2677 x
= (vc_progress
->dx
* vc_uiscale
);
2678 y
= (vc_progress
->dy
* vc_uiscale
);
2679 if( 1 & vc_progress
->flags
) {
2680 x
+= ((vinfo
.v_width
- width
) / 2);
2681 y
+= ((vinfo
.v_height
- height
) / 2);
2685 if ((x
+ width
) > (int)vinfo
.v_width
) break;
2686 if ((y
+ height
) > (int)vinfo
.v_height
) break;
2688 data
+= vc_progress_count
* width
* height
;
2690 vc_blit_rect( x
, y
, 0,
2691 width
, height
, width
, width
,
2694 | (vc_progress_angle
& kDataRotate
)
2695 | (vc_needsave
? kSave
: 0) );
2696 vc_needsave
= FALSE
;
2698 clock_deadline_for_periodic_event(vc_progress_interval
, mach_absolute_time(), &vc_progress_deadline
);
2699 thread_call_enter_delayed(&vc_progress_call
, vc_progress_deadline
);
2702 simple_unlock(&vc_progress_lock
);
2707 * Generic Console (Front-End): Master Control
2708 * -------------------------------------------
2711 #if defined (__i386__) || defined (__x86_64__)
2712 #include <pexpert/i386/boot.h>
2715 static boolean_t gc_acquired
= FALSE
;
2716 static boolean_t gc_graphics_boot
= FALSE
;
2717 static boolean_t gc_desire_text
= FALSE
;
2718 static boolean_t gc_paused_progress
;
2720 static vm_offset_t lastVideoVirt
= 0;
2721 static vm_size_t lastVideoMapSize
= 0;
2722 static boolean_t lastVideoMapKmap
= FALSE
;
2725 gc_pause( boolean_t pause
, boolean_t graphics_now
)
2730 VCPUTC_LOCK_LOCK( );
2732 disableConsoleOutput
= (pause
&& !console_is_serial());
2733 gc_enabled
= (!pause
&& !graphics_now
);
2735 VCPUTC_LOCK_UNLOCK( );
2737 simple_lock(&vc_progress_lock
);
2741 gc_paused_progress
= vc_progress_enable
;
2742 vc_progress_enable
= FALSE
;
2744 else vc_progress_enable
= gc_paused_progress
;
2746 if (vc_progress_enable
)
2748 #if !CONFIG_EMBEDDED
2749 if (1 & vc_progress_withmeter
) thread_call_enter_delayed(&vc_progressmeter_call
, vc_progressmeter_deadline
);
2751 #endif /* !CONFIG_EMBEDDED */
2752 thread_call_enter_delayed(&vc_progress_call
, vc_progress_deadline
);
2755 simple_unlock(&vc_progress_lock
);
2760 vc_initialize(__unused
struct vc_info
* vinfo_p
)
2763 unsigned long cnt
, data16
, data32
;
2765 if (vinfo
.v_depth
== 16) {
2766 for (cnt
= 0; cnt
< 8; cnt
++) {
2767 data32
= vc_colors
[cnt
][2];
2768 data16
= (data32
& 0x0000F8) << 8;
2769 data16
|= (data32
& 0x00FC00) >> 5;
2770 data16
|= (data32
& 0xF80000) >> 19;
2771 data16
|= data16
<< 16;
2772 vc_colors
[cnt
][1] = data16
;
2777 vinfo
.v_rows
= vinfo
.v_height
/ ISO_CHAR_HEIGHT
;
2778 vinfo
.v_columns
= vinfo
.v_width
/ ISO_CHAR_WIDTH
;
2779 vinfo
.v_rowscanbytes
= ((vinfo
.v_depth
+ 7) / 8) * vinfo
.v_width
;
2780 vc_uiscale
= vinfo
.v_scale
;
2781 if (vc_uiscale
> kMaxProgressData
) vc_uiscale
= kMaxProgressData
;
2782 else if (!vc_uiscale
) vc_uiscale
= 1;
2786 initialize_screen(PE_Video
* boot_vinfo
, unsigned int op
)
2788 unsigned int newMapSize
= 0;
2789 vm_offset_t newVideoVirt
= 0;
2790 boolean_t graphics_now
;
2795 struct vc_info new_vinfo
= vinfo
;
2796 boolean_t makeMapping
= FALSE
;
2801 if (kPEBaseAddressChange
!= op
)
2803 new_vinfo
.v_width
= (unsigned int)boot_vinfo
->v_width
;
2804 new_vinfo
.v_height
= (unsigned int)boot_vinfo
->v_height
;
2805 new_vinfo
.v_depth
= (unsigned int)boot_vinfo
->v_depth
;
2806 new_vinfo
.v_rowbytes
= (unsigned int)boot_vinfo
->v_rowBytes
;
2807 if (kernel_map
== VM_MAP_NULL
) {
2808 // only booter supplies HW rotation
2809 new_vinfo
.v_rotate
= (unsigned int)boot_vinfo
->v_rotate
;
2811 #if defined(__i386__) || defined(__x86_64__)
2812 new_vinfo
.v_type
= (unsigned int)boot_vinfo
->v_display
;
2814 new_vinfo
.v_type
= 0;
2816 unsigned int scale
= (unsigned int)boot_vinfo
->v_scale
;
2817 if (scale
== kPEScaleFactor1x
)
2818 new_vinfo
.v_scale
= kPEScaleFactor1x
;
2819 else if (scale
== kPEScaleFactor2x
)
2820 new_vinfo
.v_scale
= kPEScaleFactor2x
;
2821 else /* Scale factor not set, default to 1x */
2822 new_vinfo
.v_scale
= kPEScaleFactor1x
;
2824 new_vinfo
.v_name
[0] = 0;
2825 new_vinfo
.v_physaddr
= 0;
2828 * Check if we are have to map the framebuffer
2829 * If VM is up, we are given a virtual address, unless b0 is set to indicate physical.
2831 newVideoVirt
= boot_vinfo
->v_baseAddr
;
2832 makeMapping
= (kernel_map
== VM_MAP_NULL
) || (0 != (1 & newVideoVirt
));
2836 new_vinfo
.v_physaddr
= boot_vinfo
->v_baseAddr
& ~3UL; /* Get the physical address */
2838 new_vinfo
.v_physaddr
|= (((uint64_t) boot_vinfo
->v_baseAddrHigh
) << 32);
2840 kprintf("initialize_screen: b=%08llX, w=%08X, h=%08X, r=%08X, d=%08X\n", /* (BRINGUP) */
2841 new_vinfo
.v_physaddr
, new_vinfo
.v_width
, new_vinfo
.v_height
, new_vinfo
.v_rowbytes
, new_vinfo
.v_type
); /* (BRINGUP) */
2844 if (!newVideoVirt
&& !new_vinfo
.v_physaddr
) /* Check to see if we have a framebuffer */
2846 kprintf("initialize_screen: No video - forcing serial mode\n"); /* (BRINGUP) */
2847 new_vinfo
.v_depth
= 0; /* vc routines are nop */
2848 (void)switch_to_serial_console(); /* Switch into serial mode */
2849 gc_graphics_boot
= FALSE
; /* Say we are not in graphics mode */
2850 disableConsoleOutput
= FALSE
; /* Allow printfs to happen */
2857 unsigned int flags
= VM_WIMG_IO
;
2858 if (boot_vinfo
->v_length
!= 0)
2859 newMapSize
= (unsigned int) round_page(boot_vinfo
->v_length
);
2861 newMapSize
= (unsigned int) round_page(new_vinfo
.v_height
* new_vinfo
.v_rowbytes
); /* Remember size */
2862 newVideoVirt
= io_map_spec((vm_map_offset_t
)new_vinfo
.v_physaddr
, newMapSize
, flags
); /* Allocate address space for framebuffer */
2864 new_vinfo
.v_baseaddr
= newVideoVirt
+ boot_vinfo
->v_offset
; /* Set the new framebuffer address */
2867 #if defined(__x86_64__)
2868 // Adjust the video buffer pointer to point to where it is in high virtual (above the hole)
2869 new_vinfo
.v_baseaddr
|= (VM_MIN_KERNEL_ADDRESS
& ~LOW_4GB_MASK
);
2872 /* Update the vinfo structure atomically with respect to the vc_progress task if running */
2875 simple_lock(&vc_progress_lock
);
2877 simple_unlock(&vc_progress_lock
);
2884 // If we changed the virtual address, remove the old mapping
2885 if (newVideoVirt
!= 0)
2887 if (lastVideoVirt
&& lastVideoMapSize
) /* Was the framebuffer mapped before? */
2889 /* XXX why only !4K? */
2890 if (!TEST_PAGE_SIZE_4K
&& lastVideoMapSize
)
2892 pmap_remove(kernel_pmap
, trunc_page_64(lastVideoVirt
),
2893 round_page_64(lastVideoVirt
+ lastVideoMapSize
)); /* Toss mappings */
2895 /* Was this not a special pre-VM mapping? */
2896 if (lastVideoMapKmap
)
2898 kmem_free(kernel_map
, lastVideoVirt
, lastVideoMapSize
); /* Toss kernel addresses */
2901 lastVideoMapKmap
= (NULL
!= kernel_map
); /* Remember how mapped */
2902 lastVideoMapSize
= newMapSize
; /* Remember the size */
2903 lastVideoVirt
= newVideoVirt
; /* Remember the virtual framebuffer address */
2906 if (kPEBaseAddressChange
!= op
)
2908 // Graphics mode setup by the booter.
2910 gc_ops
.initialize
= vc_initialize
;
2911 gc_ops
.enable
= vc_enable
;
2912 gc_ops
.paint_char
= vc_paint_char
;
2913 gc_ops
.scroll_down
= vc_scroll_down
;
2914 gc_ops
.scroll_up
= vc_scroll_up
;
2915 gc_ops
.clear_screen
= vc_clear_screen
;
2916 gc_ops
.hide_cursor
= vc_reverse_cursor
;
2917 gc_ops
.show_cursor
= vc_reverse_cursor
;
2918 gc_ops
.update_color
= vc_update_color
;
2919 gc_initialize(&vinfo
);
2923 graphics_now
= gc_graphics_boot
&& !gc_desire_text
;
2926 case kPEGraphicsMode
:
2927 gc_graphics_boot
= TRUE
;
2928 gc_desire_text
= FALSE
;
2932 gc_graphics_boot
= FALSE
;
2935 case kPEAcquireScreen
:
2936 if ( gc_acquired
) break;
2938 vc_progress_options
= vc_user_options
;
2939 bzero(&vc_user_options
, sizeof(vc_user_options
));
2941 if (kVCAcquireImmediate
& vc_progress_options
.options
) delay
= 0;
2942 else if (kVCDarkReboot
& vc_progress_options
.options
) delay
= 120;
2943 else delay
= vc_acquire_delay
;
2945 if (kVCDarkBackground
& vc_progress_options
.options
) vc_progress_white
= TRUE
;
2946 else if (kVCLightBackground
& vc_progress_options
.options
) vc_progress_white
= FALSE
;
2948 #if !defined(XNU_TARGET_OS_BRIDGE)
2949 vc_progress_set( graphics_now
, delay
);
2950 #endif /* !defined(XNU_TARGET_OS_BRIDGE) */
2951 gc_enable( !graphics_now
);
2953 gc_desire_text
= FALSE
;
2956 case kPEDisableScreen
:
2959 gc_pause( TRUE
, graphics_now
);
2963 case kPEEnableScreen
:
2966 gc_pause( FALSE
, graphics_now
);
2971 if ( console_is_serial() ) break;
2973 if ( gc_acquired
== FALSE
)
2975 gc_desire_text
= TRUE
;
2978 if ( gc_graphics_boot
== FALSE
) break;
2980 vc_progress_set( FALSE
, 0 );
2981 #if !CONFIG_EMBEDDED
2982 vc_enable_progressmeter( FALSE
);
2987 case kPEReleaseScreen
:
2988 gc_acquired
= FALSE
;
2989 gc_desire_text
= FALSE
;
2991 if ( gc_graphics_boot
== FALSE
) break;
2993 vc_progress_set( FALSE
, 0 );
2994 vc_acquire_delay
= kProgressReacquireDelay
;
2995 vc_progress_white
= TRUE
;
2996 #if !CONFIG_EMBEDDED
2997 vc_enable_progressmeter(FALSE
);
2998 vc_progress_withmeter
&= ~1;
3004 #if !CONFIG_EMBEDDED
3005 case kPERefreshBootGraphics
:
3010 if (kBootArgsFlagBlack
& ((boot_args
*) PE_state
.bootArgs
)->flags
) break;
3012 save
= vc_progress_white
;
3013 vc_progress_white
= (0 != (kBootArgsFlagBlackBg
& ((boot_args
*) PE_state
.bootArgs
)->flags
));
3015 internal_enable_progressmeter(kProgressMeterKernel
);
3018 simple_lock(&vc_progress_lock
);
3020 vc_progressmeter_drawn
= 0;
3021 internal_set_progressmeter(vc_progressmeter_range(vc_progressmeter_count
>> 13));
3023 simple_unlock(&vc_progress_lock
);
3026 internal_enable_progressmeter(kProgressMeterOff
);
3027 vc_progress_white
= save
;
3033 void vcattach(void); /* XXX gcc 4 warning cleanup */
3038 vm_initialized
= TRUE
;
3040 #if !CONFIG_EMBEDDED
3041 const boot_args
* bootargs
= (typeof(bootargs
)) PE_state
.bootArgs
;
3043 vc_progress_white
= (0 != ((kBootArgsFlagBlackBg
| kBootArgsFlagLoginUI
)
3044 & bootargs
->flags
));
3045 PE_parse_boot_argn("meter", &vc_progress_withmeter
, sizeof(vc_progress_withmeter
));
3047 if (kBootArgsFlagInstallUI
& bootargs
->flags
)
3049 vc_progress_meter_start
= (bootargs
->bootProgressMeterStart
* kProgressMeterMax
) / 65535;
3050 vc_progress_meter_end
= (bootargs
->bootProgressMeterEnd
* kProgressMeterMax
) / 65535;
3054 vc_progress_meter_start
= 0;
3055 vc_progress_meter_end
= kProgressMeterMax
;
3058 simple_lock_init(&vc_progress_lock
, 0);
3060 if ( gc_graphics_boot
== FALSE
)
3066 initialize_screen(NULL
, kPEReleaseScreen
);
3069 initialize_screen(NULL
, kPEAcquireScreen
);
3071 for ( index
= 0 ; index
< msgbufp
->msg_bufx
; index
++ )
3073 if (msgbufp
->msg_bufc
[index
] == '\0') {
3077 vcputc( 0, 0, msgbufp
->msg_bufc
[index
] );
3079 if ( msgbufp
->msg_bufc
[index
] == '\n' )
3081 vcputc( 0, 0,'\r' );
3087 #if !CONFIG_EMBEDDED
3089 // redraw progress meter between pixels x1, x2, position at x3
3091 vc_draw_progress_meter(unsigned int flags
, int x1
, int x2
, int x3
)
3093 const unsigned char * data
;
3098 // 1 rounded fill, 0 square end
3099 int style
= (0 == (2 & vc_progress_withmeter
));
3101 ox
= ((vinfo
.v_width
- (kProgressBarWidth
* vc_uiscale
)) / 2);
3102 oy
= vinfo
.v_height
- (vinfo
.v_height
/ 3) - ((kProgressBarHeight
* vc_uiscale
) / 2);
3104 if (kDataBack
== flags
)
3106 // restore back bits
3107 vc_blit_rect(ox
+ x1
, oy
, x1
,
3108 x2
, (kProgressBarHeight
* vc_uiscale
), 0, (kProgressBarWidth
* vc_uiscale
),
3109 NULL
, vc_progressmeter_backbuffer
, flags
);
3113 for (x
= x1
; x
< x2
; x
+= w
)
3116 endCapPos
= ((style
&& onoff
) ? x3
: (kProgressBarWidth
* vc_uiscale
));
3117 if (x
< (kProgressBarCapWidth
* vc_uiscale
))
3119 if (x2
< (kProgressBarCapWidth
* vc_uiscale
))
3122 w
= (kProgressBarCapWidth
* vc_uiscale
) - x
;
3123 data
= progressmeter_leftcap
[vc_uiscale
>= 2][onoff
];
3125 vc_blit_rect(ox
+ x
, oy
, x
, w
,
3126 (kProgressBarHeight
* vc_uiscale
),
3127 (kProgressBarCapWidth
* vc_uiscale
),
3128 (kProgressBarWidth
* vc_uiscale
),
3129 data
, vc_progressmeter_backbuffer
, flags
);
3131 else if (x
< (endCapPos
- (kProgressBarCapWidth
* vc_uiscale
)))
3133 if (x2
< (endCapPos
- (kProgressBarCapWidth
* vc_uiscale
)))
3136 w
= (endCapPos
- (kProgressBarCapWidth
* vc_uiscale
)) - x
;
3137 data
= progressmeter_middle
[vc_uiscale
>= 2][onoff
];
3138 vc_blit_rect(ox
+ x
, oy
, x
, w
,
3139 (kProgressBarHeight
* vc_uiscale
),
3141 (kProgressBarWidth
* vc_uiscale
),
3142 data
, vc_progressmeter_backbuffer
, flags
);
3147 data
= progressmeter_rightcap
[vc_uiscale
>= 2][onoff
];
3148 data
+= x
- (endCapPos
- (kProgressBarCapWidth
* vc_uiscale
));
3149 vc_blit_rect(ox
+ x
, oy
, x
, w
,
3150 (kProgressBarHeight
* vc_uiscale
),
3151 (kProgressBarCapWidth
* vc_uiscale
),
3152 (kProgressBarWidth
* vc_uiscale
),
3153 data
, vc_progressmeter_backbuffer
, flags
);
3158 extern void IORecordProgressBackbuffer(void * buffer
, size_t size
, uint32_t theme
);
3161 internal_enable_progressmeter(int new_value
)
3165 boolean_t stashBackbuffer
;
3167 stashBackbuffer
= FALSE
;
3171 new_buffer
= kalloc((kProgressBarWidth
* vc_uiscale
)
3172 * (kProgressBarHeight
* vc_uiscale
) * sizeof(int));
3176 simple_lock(&vc_progress_lock
);
3178 if (kProgressMeterUser
== new_value
)
3180 if (gc_enabled
|| !gc_acquired
|| !gc_graphics_boot
3181 || (kProgressMeterKernel
== vc_progressmeter_enable
)) new_value
= vc_progressmeter_enable
;
3184 if (new_value
!= vc_progressmeter_enable
)
3188 if (kProgressMeterOff
== vc_progressmeter_enable
)
3190 vc_progressmeter_backbuffer
= new_buffer
;
3191 vc_draw_progress_meter(kDataAlpha
| kSave
, 0, (kProgressBarWidth
* vc_uiscale
), 0);
3193 vc_progressmeter_drawn
= 0;
3195 vc_progressmeter_enable
= new_value
;
3197 else if (vc_progressmeter_backbuffer
)
3199 if (kProgressMeterUser
== vc_progressmeter_enable
)
3201 vc_draw_progress_meter(kDataBack
, 0, (kProgressBarWidth
* vc_uiscale
), vc_progressmeter_drawn
);
3203 else stashBackbuffer
= TRUE
;
3204 new_buffer
= vc_progressmeter_backbuffer
;
3205 vc_progressmeter_backbuffer
= NULL
;
3206 vc_progressmeter_enable
= FALSE
;
3210 simple_unlock(&vc_progress_lock
);
3215 if (stashBackbuffer
) IORecordProgressBackbuffer(new_buffer
,
3216 (kProgressBarWidth
* vc_uiscale
)
3217 * (kProgressBarHeight
* vc_uiscale
)
3220 kfree(new_buffer
, (kProgressBarWidth
* vc_uiscale
)
3221 * (kProgressBarHeight
* vc_uiscale
) * sizeof(int));
3226 internal_set_progressmeter(int new_value
)
3230 // 1 rounded fill, 0 square end
3231 int style
= (0 == (2 & vc_progress_withmeter
));
3233 if ((new_value
< 0) || (new_value
> kProgressMeterMax
)) return;
3235 if (vc_progressmeter_enable
)
3237 vc_progressmeter_value
= new_value
;
3239 capRedraw
= (style
? (kProgressBarCapWidth
* vc_uiscale
) : 0);
3240 x3
= (((kProgressBarWidth
* vc_uiscale
) - 2 * capRedraw
) * vc_progressmeter_value
) / kProgressMeterMax
;
3241 x3
+= (2 * capRedraw
);
3243 if (x3
> vc_progressmeter_drawn
)
3246 if (x1
> vc_progressmeter_drawn
) x1
= vc_progressmeter_drawn
;
3247 vc_draw_progress_meter(kDataAlpha
, vc_progressmeter_drawn
- x1
, x3
, x3
);
3251 vc_draw_progress_meter(kDataAlpha
, x3
- capRedraw
, vc_progressmeter_drawn
, x3
);
3253 vc_progressmeter_drawn
= x3
;
3258 vc_enable_progressmeter(int new_value
)
3260 if (kProgressMeterKernel
== vc_progressmeter_enable
)
3262 vc_progressmeter_hold
= new_value
;
3266 internal_enable_progressmeter(new_value
? kProgressMeterUser
: kProgressMeterOff
);
3271 vc_set_progressmeter(int new_value
)
3276 simple_lock(&vc_progress_lock
);
3278 if (vc_progressmeter_enable
&& (kProgressMeterKernel
!= vc_progressmeter_enable
))
3280 internal_set_progressmeter((new_value
* kProgressMeterMax
) / 100);
3283 simple_unlock(&vc_progress_lock
);
3287 #endif /* !CONFIG_EMBEDDED */