2 * Copyright (c) 2000-2020 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"
109 #if defined(XNU_TARGET_OS_OSX)
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
;
154 LCK_GRP_DECLARE(vconsole_lck_grp
, "vconsole");
155 static lck_ticket_t vcputc_lock
;
158 #define VCPUTC_LOCK_INIT() \
160 lck_ticket_init(&vcputc_lock, &vconsole_lck_grp); \
163 #define VCPUTC_LOCK_LOCK() \
165 lck_ticket_lock(&vcputc_lock, &vconsole_lck_grp); \
168 #define VCPUTC_LOCK_UNLOCK() \
170 lck_ticket_unlock(&vcputc_lock); \
176 # 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed
178 # 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white
179 # Background color codes:
180 # 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white
186 #define ATTR_REVERSE 4
188 #define COLOR_BACKGROUND 0
189 #define COLOR_FOREGROUND 7
191 #define COLOR_CODE_GET(code, fore) (((code) & ((fore) ? 0xF0 : 0x0F)) >> ((fore) ? 4 : 0))
192 #define COLOR_CODE_SET(code, color, fore) (((code) & ((fore) ? 0x0F : 0xF0)) | ((color) << ((fore) ? 4 : 0)))
194 static unsigned char gc_color_code
;
198 static unsigned int gc_x
, gc_y
, gc_savex
, gc_savey
;
199 static unsigned int gc_par
[MAXPARS
], gc_numpars
, gc_hanging_cursor
, gc_attr
, gc_saveattr
;
201 /* VT100 scroll region */
202 static unsigned int gc_scrreg_top
, gc_scrreg_bottom
;
205 ESnormal
, /* Nothing yet */
207 ESsquare
, /* Got ESC [ */
208 ESgetpars
, /* About to get or getting the parameters */
209 ESgotpars
, /* Finished getting the parameters */
210 ESfunckey
, /* Function key */
211 EShash
, /* DEC-specific stuff (screen align, etc.) */
212 ESsetG0
, /* Specify the G0 character set */
213 ESsetG1
, /* Specify the G1 character set */
216 ESignore
/* Ignore this sequence */
217 } gc_vt100state
= ESnormal
;
222 kProgressAcquireDelay
= 0,
223 #if !defined(XNU_TARGET_OS_OSX)
224 kProgressReacquireDelay
= 5,
226 kProgressReacquireDelay
= 5,
230 static int8_t vc_rotate_matr
[4][2][2] = {
241 static int gc_wrap_mode
= 1, gc_relative_origin
= 0;
242 static int gc_charset_select
= 0, gc_save_charset_s
= 0;
243 static int gc_charset
[2] = { 0, 0 };
244 static int gc_charset_save
[2] = { 0, 0 };
246 static void gc_clear_line(unsigned int xx
, unsigned int yy
, int which
);
247 static void gc_clear_screen(unsigned int xx
, unsigned int yy
, int top
,
248 unsigned int bottom
, int which
);
249 static void gc_enable(boolean_t enable
);
250 static void gc_hide_cursor(unsigned int xx
, unsigned int yy
);
251 static void gc_initialize(struct vc_info
* info
);
252 static boolean_t
gc_is_tab_stop(unsigned int column
);
253 static void gc_paint_char(unsigned int xx
, unsigned int yy
, unsigned char ch
,
255 static void gc_putchar(char ch
);
256 static void gc_putc_askcmd(unsigned char ch
);
257 static void gc_putc_charsetcmd(int charset
, unsigned char ch
);
258 static void gc_putc_charsizecmd(unsigned char ch
);
259 static void gc_putc_esc(unsigned char ch
);
260 static void gc_putc_getpars(unsigned char ch
);
261 static void gc_putc_gotpars(unsigned char ch
);
262 static void gc_putc_normal(unsigned char ch
);
263 static void gc_putc_square(unsigned char ch
);
264 static void gc_reset_screen(void);
265 static void gc_reset_tabs(void);
266 static void gc_reset_vt100(void);
267 static void gc_scroll_down(int num
, unsigned int top
, unsigned int bottom
);
268 static void gc_scroll_up(int num
, unsigned int top
, unsigned int bottom
);
269 static void gc_set_tab_stop(unsigned int column
, boolean_t enabled
);
270 static void gc_show_cursor(unsigned int xx
, unsigned int yy
);
271 static void gc_update_color(int color
, boolean_t fore
);
274 gc_clear_line(unsigned int xx
, unsigned int yy
, int which
)
276 unsigned int start
, end
, i
;
279 * This routine runs extremely slowly. I don't think it's
280 * used all that often, except for To end of line. I'll go
281 * back and speed this up when I speed up the whole vc
286 case 0: /* To end of line */
288 end
= vinfo
.v_columns
- 1;
290 case 1: /* To start of line */
294 case 2: /* Whole line */
296 end
= vinfo
.v_columns
- 1;
302 for (i
= start
; i
<= end
; i
++) {
303 gc_paint_char(i
, yy
, ' ', ATTR_NONE
);
308 gc_clear_screen(unsigned int xx
, unsigned int yy
, int top
, unsigned int bottom
,
311 if (!gc_buffer_size
) {
315 if (xx
< gc_buffer_columns
&& yy
< gc_buffer_rows
&& bottom
<= gc_buffer_rows
) {
319 case 0: /* To end of screen */
320 start
= (yy
* gc_buffer_columns
) + xx
;
321 end
= (bottom
* gc_buffer_columns
) - 1;
323 case 1: /* To start of screen */
324 start
= (top
* gc_buffer_columns
);
325 end
= (yy
* gc_buffer_columns
) + xx
;
327 case 2: /* Whole screen */
328 start
= (top
* gc_buffer_columns
);
329 end
= (bottom
* gc_buffer_columns
) - 1;
337 memset(gc_buffer_attributes
+ start
, ATTR_NONE
, end
- start
+ 1);
338 memset(gc_buffer_characters
+ start
, ' ', end
- start
+ 1);
339 memset(gc_buffer_colorcodes
+ start
, gc_color_code
, end
- start
+ 1);
342 gc_ops
.clear_screen(xx
, yy
, top
, bottom
, which
);
346 gc_enable( boolean_t enable
)
348 unsigned char *buffer_attributes
= NULL
;
349 unsigned char *buffer_characters
= NULL
;
350 unsigned char *buffer_colorcodes
= NULL
;
351 unsigned char *buffer_tab_stops
= NULL
;
352 uint32_t buffer_columns
= 0;
353 uint32_t buffer_rows
= 0;
354 uint32_t buffer_size
= 0;
357 if (enable
== FALSE
) {
358 // only disable console output if it goes to the graphics console
359 if (console_is_serial() == FALSE
) {
360 disableConsoleOutput
= TRUE
;
363 gc_ops
.enable(FALSE
);
369 if (gc_buffer_size
) {
370 buffer_attributes
= gc_buffer_attributes
;
371 buffer_characters
= gc_buffer_characters
;
372 buffer_colorcodes
= gc_buffer_colorcodes
;
373 buffer_tab_stops
= gc_buffer_tab_stops
;
374 buffer_columns
= gc_buffer_columns
;
375 buffer_rows
= gc_buffer_rows
;
376 buffer_size
= gc_buffer_size
;
378 gc_buffer_attributes
= NULL
;
379 gc_buffer_characters
= NULL
;
380 gc_buffer_colorcodes
= NULL
;
381 gc_buffer_tab_stops
= NULL
;
382 gc_buffer_columns
= 0;
386 VCPUTC_LOCK_UNLOCK();
389 kheap_free( KHEAP_DATA_BUFFERS
, buffer_attributes
, buffer_size
);
390 kheap_free( KHEAP_DATA_BUFFERS
, buffer_characters
, buffer_size
);
391 kheap_free( KHEAP_DATA_BUFFERS
, buffer_colorcodes
, buffer_size
);
392 kheap_free( KHEAP_DATA_BUFFERS
, buffer_tab_stops
, buffer_columns
);
394 VCPUTC_LOCK_UNLOCK();
399 if (vm_initialized
) {
400 buffer_columns
= vinfo
.v_columns
;
401 buffer_rows
= vinfo
.v_rows
;
402 buffer_size
= buffer_columns
* buffer_rows
;
405 buffer_attributes
= kheap_alloc( KHEAP_DATA_BUFFERS
, buffer_size
, Z_WAITOK
);
406 buffer_characters
= kheap_alloc( KHEAP_DATA_BUFFERS
, buffer_size
, Z_WAITOK
);
407 buffer_colorcodes
= kheap_alloc( KHEAP_DATA_BUFFERS
, buffer_size
, Z_WAITOK
);
408 buffer_tab_stops
= kheap_alloc( KHEAP_DATA_BUFFERS
, buffer_columns
, Z_WAITOK
);
410 if (buffer_attributes
== NULL
||
411 buffer_characters
== NULL
||
412 buffer_colorcodes
== NULL
||
413 buffer_tab_stops
== NULL
) {
414 if (buffer_attributes
) {
415 kheap_free( KHEAP_DATA_BUFFERS
, buffer_attributes
, buffer_size
);
417 if (buffer_characters
) {
418 kheap_free( KHEAP_DATA_BUFFERS
, buffer_characters
, buffer_size
);
420 if (buffer_colorcodes
) {
421 kheap_free( KHEAP_DATA_BUFFERS
, buffer_colorcodes
, buffer_size
);
423 if (buffer_tab_stops
) {
424 kheap_free( KHEAP_DATA_BUFFERS
, buffer_tab_stops
, buffer_columns
);
427 buffer_attributes
= NULL
;
428 buffer_characters
= NULL
;
429 buffer_colorcodes
= NULL
;
430 buffer_tab_stops
= NULL
;
435 memset( buffer_attributes
, ATTR_NONE
, buffer_size
);
436 memset( buffer_characters
, ' ', buffer_size
);
437 memset( buffer_colorcodes
, COLOR_CODE_SET( 0, COLOR_FOREGROUND
, TRUE
), buffer_size
);
438 memset( buffer_tab_stops
, 0, buffer_columns
);
446 gc_buffer_attributes
= buffer_attributes
;
447 gc_buffer_characters
= buffer_characters
;
448 gc_buffer_colorcodes
= buffer_colorcodes
;
449 gc_buffer_tab_stops
= buffer_tab_stops
;
450 gc_buffer_columns
= buffer_columns
;
451 gc_buffer_rows
= buffer_rows
;
452 gc_buffer_size
= buffer_size
;
456 VCPUTC_LOCK_UNLOCK();
459 gc_ops
.clear_screen(gc_x
, gc_y
, 0, vinfo
.v_rows
, 2);
460 gc_ops
.show_cursor(gc_x
, gc_y
);
464 disableConsoleOutput
= FALSE
;
469 gc_hide_cursor(unsigned int xx
, unsigned int yy
)
471 if (xx
< gc_buffer_columns
&& yy
< gc_buffer_rows
) {
472 uint32_t index
= (yy
* gc_buffer_columns
) + xx
;
473 unsigned char attribute
= gc_buffer_attributes
[index
];
474 unsigned char character
= gc_buffer_characters
[index
];
475 unsigned char colorcode
= gc_buffer_colorcodes
[index
];
476 unsigned char colorcodesave
= gc_color_code
;
478 gc_update_color(COLOR_CODE_GET(colorcode
, TRUE
), TRUE
);
479 gc_update_color(COLOR_CODE_GET(colorcode
, FALSE
), FALSE
);
481 gc_ops
.paint_char(xx
, yy
, character
, attribute
, 0, 0);
483 gc_update_color(COLOR_CODE_GET(colorcodesave
, TRUE
), TRUE
);
484 gc_update_color(COLOR_CODE_GET(colorcodesave
, FALSE
), FALSE
);
486 gc_ops
.hide_cursor(xx
, yy
);
491 gc_initialize(struct vc_info
* info
)
493 if (gc_initialized
== FALSE
) {
497 gc_initialized
= TRUE
;
500 gc_ops
.initialize(info
);
507 gc_paint_char(unsigned int xx
, unsigned int yy
, unsigned char ch
, int attrs
)
509 if (xx
< gc_buffer_columns
&& yy
< gc_buffer_rows
) {
510 uint32_t index
= (yy
* gc_buffer_columns
) + xx
;
512 gc_buffer_attributes
[index
] = attrs
;
513 gc_buffer_characters
[index
] = ch
;
514 gc_buffer_colorcodes
[index
] = gc_color_code
;
517 gc_ops
.paint_char(xx
, yy
, ch
, attrs
, 0, 0);
524 return; /* ignore null characters */
526 switch (gc_vt100state
) {
528 gc_vt100state
= ESnormal
;
549 gc_putc_charsizecmd(ch
);
552 gc_putc_charsetcmd(0, ch
);
555 gc_putc_charsetcmd(1, ch
);
559 if (gc_x
>= vinfo
.v_columns
) {
560 if (0 == vinfo
.v_columns
) {
563 gc_x
= vinfo
.v_columns
- 1;
566 if (gc_y
>= vinfo
.v_rows
) {
567 if (0 == vinfo
.v_rows
) {
570 gc_y
= vinfo
.v_rows
- 1;
576 gc_putc_askcmd(unsigned char ch
)
578 if (ch
>= '0' && ch
<= '9') {
579 gc_par
[gc_numpars
] = (10 * gc_par
[gc_numpars
]) + (ch
- '0');
582 gc_vt100state
= ESnormal
;
586 gc_relative_origin
= ch
== 'h';
588 case 7: /* wrap around mode h=1, l=0*/
589 gc_wrap_mode
= ch
== 'h';
597 gc_putc_charsetcmd(int charset
, unsigned char ch
)
599 gc_vt100state
= ESnormal
;
605 gc_charset
[charset
] = 0;
607 case '0': /* Graphic characters */
609 gc_charset
[charset
] = 0x21;
615 gc_putc_charsizecmd(unsigned char ch
)
617 gc_vt100state
= ESnormal
;
625 case '8': /* fill 'E's */
628 for (yy
= 0; yy
< vinfo
.v_rows
; yy
++) {
629 for (xx
= 0; xx
< vinfo
.v_columns
; xx
++) {
630 gc_paint_char(xx
, yy
, 'E', ATTR_NONE
);
639 gc_putc_esc(unsigned char ch
)
641 gc_vt100state
= ESnormal
;
645 gc_vt100state
= ESsquare
;
647 case 'c': /* Reset terminal */
649 gc_clear_screen(gc_x
, gc_y
, 0, vinfo
.v_rows
, 2);
652 case 'D': /* Line feed */
654 if (gc_y
>= gc_scrreg_bottom
- 1) {
655 gc_scroll_up(1, gc_scrreg_top
, gc_scrreg_bottom
);
656 gc_y
= gc_scrreg_bottom
- 1;
664 case 'H': /* Set tab stop */
665 gc_set_tab_stop(gc_x
, TRUE
);
667 case 'M': /* Cursor up */
668 if (gc_y
<= gc_scrreg_top
) {
669 gc_scroll_down(1, gc_scrreg_top
, gc_scrreg_bottom
);
670 gc_y
= gc_scrreg_top
;
678 case '7': /* Save cursor */
681 gc_saveattr
= gc_attr
;
682 gc_save_charset_s
= gc_charset_select
;
683 gc_charset_save
[0] = gc_charset
[0];
684 gc_charset_save
[1] = gc_charset
[1];
686 case '8': /* Restore cursor */
689 gc_attr
= gc_saveattr
;
690 gc_charset_select
= gc_save_charset_s
;
691 gc_charset
[0] = gc_charset_save
[0];
692 gc_charset
[1] = gc_charset_save
[1];
694 case 'Z': /* return terminal ID */
696 case '#': /* change characters height */
697 gc_vt100state
= EScharsize
;
700 gc_vt100state
= ESsetG0
;
702 case ')': /* character set sequence */
703 gc_vt100state
= ESsetG1
;
708 /* Rest not supported */
714 gc_putc_getpars(unsigned char ch
)
717 gc_vt100state
= ESask
;
721 gc_vt100state
= ESnormal
;
725 if (ch
== ';' && gc_numpars
< MAXPARS
- 1) {
727 } else if (ch
>= '0' && ch
<= '9') {
728 gc_par
[gc_numpars
] *= 10;
729 gc_par
[gc_numpars
] += ch
- '0';
732 gc_vt100state
= ESgotpars
;
738 gc_putc_gotpars(unsigned char ch
)
743 /* special case for vttest for handling cursor
744 * movement in escape sequences */
746 gc_vt100state
= ESgotpars
;
749 gc_vt100state
= ESnormal
;
752 gc_y
-= gc_par
[0] ? gc_par
[0] : 1;
753 if (gc_y
< gc_scrreg_top
) {
754 gc_y
= gc_scrreg_top
;
758 gc_y
+= gc_par
[0] ? gc_par
[0] : 1;
759 if (gc_y
>= gc_scrreg_bottom
) {
760 gc_y
= gc_scrreg_bottom
- 1;
763 case 'C': /* Right */
764 gc_x
+= gc_par
[0] ? gc_par
[0] : 1;
765 if (gc_x
>= vinfo
.v_columns
) {
766 gc_x
= vinfo
.v_columns
- 1;
770 if (gc_par
[0] > gc_x
) {
772 } else if (gc_par
[0]) {
778 case 'H': /* Set cursor position */
780 gc_x
= gc_par
[1] ? gc_par
[1] - 1 : 0;
781 gc_y
= gc_par
[0] ? gc_par
[0] - 1 : 0;
782 if (gc_relative_origin
) {
783 gc_y
+= gc_scrreg_top
;
785 gc_hanging_cursor
= 0;
787 case 'X': /* clear p1 characters */
789 for (i
= gc_x
; i
< gc_x
+ gc_par
[0]; i
++) {
790 gc_paint_char(i
, gc_y
, ' ', ATTR_NONE
);
794 case 'J': /* Clear part of screen */
795 gc_clear_screen(gc_x
, gc_y
, 0, vinfo
.v_rows
, gc_par
[0]);
797 case 'K': /* Clear part of line */
798 gc_clear_line(gc_x
, gc_y
, gc_par
[0]);
800 case 'g': /* tab stops */
803 case 2: /* reset tab stops */
804 /* gc_reset_tabs(); */
806 case 3: /* Clear every tabs */
808 for (i
= 0; i
<= vinfo
.v_columns
; i
++) {
809 gc_set_tab_stop(i
, FALSE
);
814 gc_set_tab_stop(gc_x
, FALSE
);
818 case 'm': /* Set attribute */
819 for (i
= 0; i
< gc_numpars
; i
++) {
823 gc_update_color(COLOR_BACKGROUND
, FALSE
);
824 gc_update_color(COLOR_FOREGROUND
, TRUE
);
827 gc_attr
|= ATTR_BOLD
;
830 gc_attr
|= ATTR_UNDER
;
833 gc_attr
|= ATTR_REVERSE
;
836 gc_attr
&= ~ATTR_BOLD
;
839 gc_attr
&= ~ATTR_UNDER
;
842 gc_attr
&= ~ATTR_REVERSE
;
845 case 25: /* blink/no blink */
848 if (gc_par
[i
] >= 30 && gc_par
[i
] <= 37) {
849 gc_update_color(gc_par
[i
] - 30, TRUE
);
851 if (gc_par
[i
] >= 40 && gc_par
[i
] <= 47) {
852 gc_update_color(gc_par
[i
] - 40, FALSE
);
858 case 'r': /* Set scroll region */
860 /* ensure top < bottom, and both within limits */
861 if ((gc_numpars
> 0) && (gc_par
[0] < vinfo
.v_rows
)) {
862 gc_scrreg_top
= gc_par
[0] ? gc_par
[0] - 1 : 0;
866 if ((gc_numpars
> 1) && (gc_par
[1] <= vinfo
.v_rows
) && (gc_par
[1] > gc_par
[0])) {
867 gc_scrreg_bottom
= gc_par
[1];
868 if (gc_scrreg_bottom
> vinfo
.v_rows
) {
869 gc_scrreg_bottom
= vinfo
.v_rows
;
872 gc_scrreg_bottom
= vinfo
.v_rows
;
874 if (gc_relative_origin
) {
875 gc_y
= gc_scrreg_top
;
882 gc_putc_normal(unsigned char ch
)
885 case '\a': /* Beep */
887 case 127: /* Delete */
888 case '\b': /* Backspace */
889 if (gc_hanging_cursor
) {
890 gc_hanging_cursor
= 0;
891 } else if (gc_x
> 0) {
896 if (gc_buffer_tab_stops
) {
897 while (gc_x
< vinfo
.v_columns
&& !gc_is_tab_stop(++gc_x
)) {
902 if (gc_x
>= vinfo
.v_columns
) {
903 gc_x
= vinfo
.v_columns
- 1;
908 case '\n': /* Line feed */
909 if (gc_y
>= gc_scrreg_bottom
- 1) {
910 gc_scroll_up(1, gc_scrreg_top
, gc_scrreg_bottom
);
911 gc_y
= gc_scrreg_bottom
- 1;
916 case '\r': /* Carriage return */
918 gc_hanging_cursor
= 0;
920 case 0x0e: /* Select G1 charset (Control-N) */
921 gc_charset_select
= 1;
923 case 0x0f: /* Select G0 charset (Control-O) */
924 gc_charset_select
= 0;
926 case 0x18: /* CAN : cancel */
927 case 0x1A: /* like cancel */
928 /* well, i do nothing here, may be later */
930 case '\033': /* Escape */
931 gc_vt100state
= ESesc
;
932 gc_hanging_cursor
= 0;
936 if (gc_hanging_cursor
) {
938 if (gc_y
>= gc_scrreg_bottom
- 1) {
939 gc_scroll_up(1, gc_scrreg_top
, gc_scrreg_bottom
);
940 gc_y
= gc_scrreg_bottom
- 1;
944 gc_hanging_cursor
= 0;
946 gc_paint_char(gc_x
, gc_y
, (ch
>= 0x60 && ch
<= 0x7f) ? ch
+ gc_charset
[gc_charset_select
]
948 if (gc_x
== vinfo
.v_columns
- 1) {
949 gc_hanging_cursor
= gc_wrap_mode
;
959 gc_putc_square(unsigned char ch
)
963 for (i
= 0; i
< MAXPARS
; i
++) {
968 gc_vt100state
= ESgetpars
;
974 gc_reset_screen(void)
985 if (!gc_buffer_tab_stops
) {
989 for (i
= 0; i
< vinfo
.v_columns
; i
++) {
990 gc_buffer_tab_stops
[i
] = ((i
% 8) == 0);
995 gc_set_tab_stop(unsigned int column
, boolean_t enabled
)
997 if (gc_buffer_tab_stops
&& (column
< vinfo
.v_columns
)) {
998 gc_buffer_tab_stops
[column
] = enabled
;
1003 gc_is_tab_stop(unsigned int column
)
1005 if (gc_buffer_tab_stops
== NULL
) {
1006 return (column
% 8) == 0;
1008 if (column
< vinfo
.v_columns
) {
1009 return gc_buffer_tab_stops
[column
];
1016 gc_reset_vt100(void)
1020 gc_scrreg_bottom
= vinfo
.v_rows
;
1021 gc_attr
= ATTR_NONE
;
1022 gc_charset
[0] = gc_charset
[1] = 0;
1023 gc_charset_select
= 0;
1025 gc_relative_origin
= 0;
1026 gc_update_color(COLOR_BACKGROUND
, FALSE
);
1027 gc_update_color(COLOR_FOREGROUND
, TRUE
);
1031 gc_scroll_down(int num
, unsigned int top
, unsigned int bottom
)
1033 if (!gc_buffer_size
) {
1037 if (bottom
<= gc_buffer_rows
) {
1038 unsigned char colorcodesave
= gc_color_code
;
1039 uint32_t column
, row
;
1040 uint32_t index
, jump
;
1042 jump
= num
* gc_buffer_columns
;
1044 for (row
= bottom
- 1; row
>= top
+ num
; row
--) {
1045 index
= row
* gc_buffer_columns
;
1047 for (column
= 0; column
< gc_buffer_columns
; index
++, column
++) {
1048 if (gc_buffer_attributes
[index
] != gc_buffer_attributes
[index
- jump
] ||
1049 gc_buffer_characters
[index
] != gc_buffer_characters
[index
- jump
] ||
1050 gc_buffer_colorcodes
[index
] != gc_buffer_colorcodes
[index
- jump
]) {
1051 if (gc_color_code
!= gc_buffer_colorcodes
[index
- jump
]) {
1052 gc_update_color(COLOR_CODE_GET(gc_buffer_colorcodes
[index
- jump
], TRUE
), TRUE
);
1053 gc_update_color(COLOR_CODE_GET(gc_buffer_colorcodes
[index
- jump
], FALSE
), FALSE
);
1056 if (gc_buffer_colorcodes
[index
] != gc_buffer_colorcodes
[index
- jump
]) {
1057 gc_ops
.paint_char( /* xx */ column
,
1059 /* ch */ gc_buffer_characters
[index
- jump
],
1060 /* attrs */ gc_buffer_attributes
[index
- jump
],
1061 /* ch_previous */ 0,
1062 /* attrs_previous */ 0 );
1064 gc_ops
.paint_char( /* xx */ column
,
1066 /* ch */ gc_buffer_characters
[index
- jump
],
1067 /* attrs */ gc_buffer_attributes
[index
- jump
],
1068 /* ch_previous */ gc_buffer_characters
[index
],
1069 /* attrs_previous */ gc_buffer_attributes
[index
] );
1072 gc_buffer_attributes
[index
] = gc_buffer_attributes
[index
- jump
];
1073 gc_buffer_characters
[index
] = gc_buffer_characters
[index
- jump
];
1074 gc_buffer_colorcodes
[index
] = gc_buffer_colorcodes
[index
- jump
];
1079 if (colorcodesave
!= gc_color_code
) {
1080 gc_update_color(COLOR_CODE_GET(colorcodesave
, TRUE
), TRUE
);
1081 gc_update_color(COLOR_CODE_GET(colorcodesave
, FALSE
), FALSE
);
1084 /* Now set the freed up lines to the background colour */
1086 for (row
= top
; row
< top
+ num
; row
++) {
1087 index
= row
* gc_buffer_columns
;
1089 for (column
= 0; column
< gc_buffer_columns
; index
++, column
++) {
1090 if (gc_buffer_attributes
[index
] != ATTR_NONE
||
1091 gc_buffer_characters
[index
] != ' ' ||
1092 gc_buffer_colorcodes
[index
] != gc_color_code
) {
1093 if (gc_buffer_colorcodes
[index
] != gc_color_code
) {
1094 gc_ops
.paint_char( /* xx */ column
,
1097 /* attrs */ ATTR_NONE
,
1098 /* ch_previous */ 0,
1099 /* attrs_previous */ 0 );
1101 gc_ops
.paint_char( /* xx */ column
,
1104 /* attrs */ ATTR_NONE
,
1105 /* ch_previous */ gc_buffer_characters
[index
],
1106 /* attrs_previous */ gc_buffer_attributes
[index
] );
1109 gc_buffer_attributes
[index
] = ATTR_NONE
;
1110 gc_buffer_characters
[index
] = ' ';
1111 gc_buffer_colorcodes
[index
] = gc_color_code
;
1116 gc_ops
.scroll_down(num
, top
, bottom
);
1118 /* Now set the freed up lines to the background colour */
1120 gc_clear_screen(vinfo
.v_columns
- 1, top
+ num
- 1, top
, bottom
, 1);
1125 gc_scroll_up(int num
, unsigned int top
, unsigned int bottom
)
1127 if (!gc_buffer_size
) {
1131 if (bottom
<= gc_buffer_rows
) {
1132 unsigned char colorcodesave
= gc_color_code
;
1133 uint32_t column
, row
;
1134 uint32_t index
, jump
;
1136 jump
= num
* gc_buffer_columns
;
1138 for (row
= top
; row
< bottom
- num
; row
++) {
1139 index
= row
* gc_buffer_columns
;
1141 for (column
= 0; column
< gc_buffer_columns
; index
++, column
++) {
1142 if (gc_buffer_attributes
[index
] != gc_buffer_attributes
[index
+ jump
] ||
1143 gc_buffer_characters
[index
] != gc_buffer_characters
[index
+ jump
] ||
1144 gc_buffer_colorcodes
[index
] != gc_buffer_colorcodes
[index
+ jump
]) {
1145 if (gc_color_code
!= gc_buffer_colorcodes
[index
+ jump
]) {
1146 gc_update_color(COLOR_CODE_GET(gc_buffer_colorcodes
[index
+ jump
], TRUE
), TRUE
);
1147 gc_update_color(COLOR_CODE_GET(gc_buffer_colorcodes
[index
+ jump
], FALSE
), FALSE
);
1150 if (gc_buffer_colorcodes
[index
] != gc_buffer_colorcodes
[index
+ jump
]) {
1151 gc_ops
.paint_char( /* xx */ column
,
1153 /* ch */ gc_buffer_characters
[index
+ jump
],
1154 /* attrs */ gc_buffer_attributes
[index
+ jump
],
1155 /* ch_previous */ 0,
1156 /* attrs_previous */ 0 );
1158 gc_ops
.paint_char( /* xx */ column
,
1160 /* ch */ gc_buffer_characters
[index
+ jump
],
1161 /* attrs */ gc_buffer_attributes
[index
+ jump
],
1162 /* ch_previous */ gc_buffer_characters
[index
],
1163 /* attrs_previous */ gc_buffer_attributes
[index
] );
1166 gc_buffer_attributes
[index
] = gc_buffer_attributes
[index
+ jump
];
1167 gc_buffer_characters
[index
] = gc_buffer_characters
[index
+ jump
];
1168 gc_buffer_colorcodes
[index
] = gc_buffer_colorcodes
[index
+ jump
];
1173 if (colorcodesave
!= gc_color_code
) {
1174 gc_update_color(COLOR_CODE_GET(colorcodesave
, TRUE
), TRUE
);
1175 gc_update_color(COLOR_CODE_GET(colorcodesave
, FALSE
), FALSE
);
1178 /* Now set the freed up lines to the background colour */
1180 for (row
= bottom
- num
; row
< bottom
; row
++) {
1181 index
= row
* gc_buffer_columns
;
1183 for (column
= 0; column
< gc_buffer_columns
; index
++, column
++) {
1184 if (gc_buffer_attributes
[index
] != ATTR_NONE
||
1185 gc_buffer_characters
[index
] != ' ' ||
1186 gc_buffer_colorcodes
[index
] != gc_color_code
) {
1187 if (gc_buffer_colorcodes
[index
] != gc_color_code
) {
1188 gc_ops
.paint_char( /* xx */ column
,
1191 /* attrs */ ATTR_NONE
,
1192 /* ch_previous */ 0,
1193 /* attrs_previous */ 0 );
1195 gc_ops
.paint_char( /* xx */ column
,
1198 /* attrs */ ATTR_NONE
,
1199 /* ch_previous */ gc_buffer_characters
[index
],
1200 /* attrs_previous */ gc_buffer_attributes
[index
] );
1203 gc_buffer_attributes
[index
] = ATTR_NONE
;
1204 gc_buffer_characters
[index
] = ' ';
1205 gc_buffer_colorcodes
[index
] = gc_color_code
;
1210 gc_ops
.scroll_up(num
, top
, bottom
);
1212 /* Now set the freed up lines to the background colour */
1214 gc_clear_screen(0, bottom
- num
, top
, bottom
, 0);
1219 gc_show_cursor(unsigned int xx
, unsigned int yy
)
1221 if (xx
< gc_buffer_columns
&& yy
< gc_buffer_rows
) {
1222 uint32_t index
= (yy
* gc_buffer_columns
) + xx
;
1223 unsigned char attribute
= gc_buffer_attributes
[index
];
1224 unsigned char character
= gc_buffer_characters
[index
];
1225 unsigned char colorcode
= gc_buffer_colorcodes
[index
];
1226 unsigned char colorcodesave
= gc_color_code
;
1228 gc_update_color(COLOR_CODE_GET(colorcode
, FALSE
), TRUE
);
1229 gc_update_color(COLOR_CODE_GET(colorcode
, TRUE
), FALSE
);
1231 gc_ops
.paint_char(xx
, yy
, character
, attribute
, 0, 0);
1233 gc_update_color(COLOR_CODE_GET(colorcodesave
, TRUE
), TRUE
);
1234 gc_update_color(COLOR_CODE_GET(colorcodesave
, FALSE
), FALSE
);
1236 gc_ops
.show_cursor(xx
, yy
);
1241 gc_update_color(int color
, boolean_t fore
)
1243 assert(gc_ops
.update_color
);
1245 gc_color_code
= COLOR_CODE_SET(gc_color_code
, color
, fore
);
1246 gc_ops
.update_color(color
, fore
);
1250 vcputc(__unused
int l
, __unused
int u
, int c
)
1252 if (gc_initialized
&& gc_enabled
) {
1255 gc_hide_cursor(gc_x
, gc_y
);
1257 gc_show_cursor(gc_x
, gc_y
);
1259 VCPUTC_LOCK_UNLOCK();
1264 * Video Console (Back-End)
1265 * ------------------------
1269 * For the color support (Michel Pollet)
1271 static unsigned char vc_color_index_table
[33] =
1272 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1273 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 2 };
1275 static uint32_t vc_colors
[8][4] = {
1276 { 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000 }, /* black */
1277 { 0x23232323, 0x7C007C00, 0x00FF0000, 0x3FF00000 }, /* red */
1278 { 0xb9b9b9b9, 0x03e003e0, 0x0000FF00, 0x000FFC00 }, /* green */
1279 { 0x05050505, 0x7FE07FE0, 0x00FFFF00, 0x3FFFFC00 }, /* yellow */
1280 { 0xd2d2d2d2, 0x001f001f, 0x000000FF, 0x000003FF }, /* blue */
1281 // { 0x80808080, 0x31933193, 0x00666699, 0x00000000 }, /* blue */
1282 { 0x18181818, 0x7C1F7C1F, 0x00FF00FF, 0x3FF003FF }, /* magenta */
1283 { 0xb4b4b4b4, 0x03FF03FF, 0x0000FFFF, 0x000FFFFF }, /* cyan */
1284 { 0x00000000, 0x7FFF7FFF, 0x00FFFFFF, 0x3FFFFFFF } /* white */
1287 static uint32_t vc_color_fore
= 0;
1288 static uint32_t vc_color_back
= 0;
1291 * New Rendering code from Michel Pollet
1294 /* Rendered Font Buffer */
1295 static unsigned char *vc_rendered_font
= NULL
;
1297 /* Rendered Font Size */
1298 static uint32_t vc_rendered_font_size
= 0;
1300 /* Size of a character in the table (bytes) */
1301 static int vc_rendered_char_size
= 0;
1303 #define REN_MAX_DEPTH 32
1304 static unsigned char vc_rendered_char
[ISO_CHAR_HEIGHT
* ((REN_MAX_DEPTH
/ 8) * ISO_CHAR_WIDTH
)];
1306 #if defined(XNU_TARGET_OS_OSX)
1307 #define CONFIG_VC_PROGRESS_METER_SUPPORT 1
1308 #endif /* XNU_TARGET_OS_OSX */
1310 #if defined(XNU_TARGET_OS_OSX)
1312 internal_set_progressmeter(int new_value
);
1314 internal_enable_progressmeter(int new_value
);
1317 kProgressMeterOff
= FALSE
,
1318 kProgressMeterUser
= TRUE
,
1319 kProgressMeterKernel
= 3,
1322 kProgressMeterMax
= 1024,
1323 kProgressMeterEnd
= 512,
1326 #endif /* defined(XNU_TARGET_OS_OSX) */
1328 static boolean_t vc_progress_white
=
1329 #ifdef CONFIG_VC_PROGRESS_WHITE
1331 #else /* !CONFIG_VC_PROGRESS_WHITE */
1333 #endif /* !CONFIG_VC_PROGRESS_WHITE */
1335 static int vc_acquire_delay
= kProgressAcquireDelay
;
1338 vc_clear_screen(unsigned int xx
, unsigned int yy
, unsigned int scrreg_top
,
1339 unsigned int scrreg_bottom
, int which
)
1341 uint32_t *p
, *endp
, *row
;
1343 int rowline
, rowlongs
;
1345 if (!vinfo
.v_depth
) {
1349 linelongs
= vinfo
.v_rowbytes
* (ISO_CHAR_HEIGHT
>> 2);
1350 rowline
= vinfo
.v_rowscanbytes
>> 2;
1351 rowlongs
= vinfo
.v_rowbytes
>> 2;
1353 p
= (uint32_t*) vinfo
.v_baseaddr
;
1354 endp
= (uint32_t*) vinfo
.v_baseaddr
;
1357 case 0: /* To end of screen */
1358 gc_clear_line(xx
, yy
, 0);
1359 if (yy
< scrreg_bottom
- 1) {
1360 p
+= (yy
+ 1) * linelongs
;
1361 endp
+= scrreg_bottom
* linelongs
;
1364 case 1: /* To start of screen */
1365 gc_clear_line(xx
, yy
, 1);
1366 if (yy
> scrreg_top
) {
1367 p
+= scrreg_top
* linelongs
;
1368 endp
+= yy
* linelongs
;
1371 case 2: /* Whole screen */
1372 p
+= scrreg_top
* linelongs
;
1373 if (scrreg_bottom
== vinfo
.v_rows
) {
1374 endp
+= rowlongs
* vinfo
.v_height
;
1376 endp
+= scrreg_bottom
* linelongs
;
1381 for (row
= p
; row
< endp
; row
+= rowlongs
) {
1382 for (col
= 0; col
< rowline
; col
++) {
1383 *(row
+ col
) = vc_color_back
;
1389 vc_render_char(unsigned char ch
, unsigned char *renderptr
, short newdepth
)
1392 unsigned char *charptr
;
1393 unsigned short *shortptr
;
1395 } current
; /* current place in rendered font, multiple types. */
1396 unsigned char *theChar
; /* current char in iso_font */
1399 current
.charptr
= renderptr
;
1400 theChar
= iso_font
+ (ch
* ISO_CHAR_HEIGHT
);
1402 for (line
= 0; line
< ISO_CHAR_HEIGHT
; line
++) {
1403 unsigned char mask
= 1;
1407 *current
.charptr
++ = (*theChar
& mask
) ? 0xFF : 0;
1410 *current
.shortptr
++ = (*theChar
& mask
) ? 0xFFFF : 0;
1415 *current
.longptr
++ = (*theChar
& mask
) ? 0xFFFFFFFF : 0;
1419 } while (mask
); /* while the single bit drops to the right */
1425 vc_paint_char_8(unsigned int xx
, unsigned int yy
, unsigned char ch
, int attrs
,
1426 __unused
unsigned char ch_previous
, __unused
int attrs_previous
)
1432 if (vc_rendered_font
) {
1433 theChar
= (uint32_t*)(vc_rendered_font
+ (ch
* vc_rendered_char_size
));
1435 vc_render_char(ch
, vc_rendered_char
, 8);
1436 theChar
= (uint32_t*)(vc_rendered_char
);
1438 where
= (uint32_t*)(vinfo
.v_baseaddr
+
1439 (yy
* ISO_CHAR_HEIGHT
* vinfo
.v_rowbytes
) +
1440 (xx
* ISO_CHAR_WIDTH
));
1443 for (i
= 0; i
< ISO_CHAR_HEIGHT
; i
++) { /* No attr? FLY !*/
1444 uint32_t *store
= where
;
1446 for (x
= 0; x
< 2; x
++) {
1447 uint32_t val
= *theChar
++;
1448 val
= (vc_color_back
& ~val
) | (vc_color_fore
& val
);
1452 where
= (uint32_t*)(((unsigned char*)where
) + vinfo
.v_rowbytes
);
1455 for (i
= 0; i
< ISO_CHAR_HEIGHT
; i
++) { /* a little slower */
1456 uint32_t *store
= where
, lastpixel
= 0;
1458 for (x
= 0; x
< 2; x
++) {
1459 uint32_t val
= *theChar
++, save
= val
;
1460 if (attrs
& ATTR_BOLD
) { /* bold support */
1461 if (lastpixel
&& !(save
& 0xFF000000)) {
1464 if ((save
& 0xFFFF0000) == 0xFF000000) {
1467 if ((save
& 0x00FFFF00) == 0x00FF0000) {
1470 if ((save
& 0x0000FFFF) == 0x0000FF00) {
1474 if (attrs
& ATTR_REVERSE
) {
1477 if (attrs
& ATTR_UNDER
&& i
== ISO_CHAR_HEIGHT
- 1) {
1481 val
= (vc_color_back
& ~val
) | (vc_color_fore
& val
);
1483 lastpixel
= save
& 0xff;
1486 where
= (uint32_t*)(((unsigned char*)where
) + vinfo
.v_rowbytes
);
1492 vc_paint_char_16(unsigned int xx
, unsigned int yy
, unsigned char ch
, int attrs
,
1493 __unused
unsigned char ch_previous
,
1494 __unused
int attrs_previous
)
1500 if (vc_rendered_font
) {
1501 theChar
= (uint32_t*)(vc_rendered_font
+ (ch
* vc_rendered_char_size
));
1503 vc_render_char(ch
, vc_rendered_char
, 16);
1504 theChar
= (uint32_t*)(vc_rendered_char
);
1506 where
= (uint32_t*)(vinfo
.v_baseaddr
+
1507 (yy
* ISO_CHAR_HEIGHT
* vinfo
.v_rowbytes
) +
1508 (xx
* ISO_CHAR_WIDTH
* 2));
1511 for (i
= 0; i
< ISO_CHAR_HEIGHT
; i
++) { /* No attrs ? FLY ! */
1512 uint32_t *store
= where
;
1514 for (x
= 0; x
< 4; x
++) {
1515 uint32_t val
= *theChar
++;
1516 val
= (vc_color_back
& ~val
) | (vc_color_fore
& val
);
1520 where
= (uint32_t*)(((unsigned char*)where
) + vinfo
.v_rowbytes
);
1523 for (i
= 0; i
< ISO_CHAR_HEIGHT
; i
++) { /* a little bit slower */
1524 uint32_t *store
= where
, lastpixel
= 0;
1526 for (x
= 0; x
< 4; x
++) {
1527 uint32_t val
= *theChar
++, save
= val
;
1528 if (attrs
& ATTR_BOLD
) { /* bold support */
1529 if (save
== 0xFFFF0000) {
1531 } else if (lastpixel
&& !(save
& 0xFFFF0000)) {
1535 if (attrs
& ATTR_REVERSE
) {
1538 if (attrs
& ATTR_UNDER
&& i
== ISO_CHAR_HEIGHT
- 1) {
1542 val
= (vc_color_back
& ~val
) | (vc_color_fore
& val
);
1545 lastpixel
= save
& 0x7fff;
1548 where
= (uint32_t*)(((unsigned char*)where
) + vinfo
.v_rowbytes
);
1554 vc_paint_char_32(unsigned int xx
, unsigned int yy
, unsigned char ch
, int attrs
,
1555 unsigned char ch_previous
, int attrs_previous
)
1558 uint32_t *theCharPrevious
;
1562 if (vc_rendered_font
) {
1563 theChar
= (uint32_t*)(vc_rendered_font
+ (ch
* vc_rendered_char_size
));
1564 theCharPrevious
= (uint32_t*)(vc_rendered_font
+ (ch_previous
* vc_rendered_char_size
));
1566 vc_render_char(ch
, vc_rendered_char
, 32);
1567 theChar
= (uint32_t*)(vc_rendered_char
);
1568 theCharPrevious
= NULL
;
1571 theCharPrevious
= NULL
;
1573 if (attrs_previous
) {
1574 theCharPrevious
= NULL
;
1576 where
= (uint32_t*)(vinfo
.v_baseaddr
+
1577 (yy
* ISO_CHAR_HEIGHT
* vinfo
.v_rowbytes
) +
1578 (xx
* ISO_CHAR_WIDTH
* 4));
1581 for (i
= 0; i
< ISO_CHAR_HEIGHT
; i
++) { /* No attrs ? FLY ! */
1582 uint32_t *store
= where
;
1584 for (x
= 0; x
< 8; x
++) {
1585 uint32_t val
= *theChar
++;
1586 if (theCharPrevious
== NULL
|| val
!= *theCharPrevious
++) {
1587 val
= (vc_color_back
& ~val
) | (vc_color_fore
& val
);
1594 where
= (uint32_t *)(((unsigned char*)where
) + vinfo
.v_rowbytes
);
1597 for (i
= 0; i
< ISO_CHAR_HEIGHT
; i
++) { /* a little slower */
1598 uint32_t *store
= where
, lastpixel
= 0;
1600 for (x
= 0; x
< 8; x
++) {
1601 uint32_t val
= *theChar
++, save
= val
;
1602 if (attrs
& ATTR_BOLD
) { /* bold support */
1603 if (lastpixel
&& !save
) {
1607 if (attrs
& ATTR_REVERSE
) {
1610 if (attrs
& ATTR_UNDER
&& i
== ISO_CHAR_HEIGHT
- 1) {
1614 val
= (vc_color_back
& ~val
) | (vc_color_fore
& val
);
1619 where
= (uint32_t*)(((unsigned char*)where
) + vinfo
.v_rowbytes
);
1625 vc_paint_char(unsigned int xx
, unsigned int yy
, unsigned char ch
, int attrs
,
1626 unsigned char ch_previous
, int attrs_previous
)
1628 if (!vinfo
.v_depth
) {
1632 switch (vinfo
.v_depth
) {
1634 vc_paint_char_8(xx
, yy
, ch
, attrs
, ch_previous
, attrs_previous
);
1637 vc_paint_char_16(xx
, yy
, ch
, attrs
, ch_previous
,
1642 vc_paint_char_32(xx
, yy
, ch
, attrs
, ch_previous
,
1649 vc_render_font(short newdepth
)
1651 static short olddepth
= 0;
1653 int charindex
; /* index in ISO font */
1654 unsigned char *rendered_font
;
1655 unsigned int rendered_font_size
;
1656 int rendered_char_size
;
1659 if (vm_initialized
== FALSE
) {
1660 return; /* nothing to do */
1662 if (olddepth
== newdepth
&& vc_rendered_font
) {
1663 return; /* nothing to do */
1669 rendered_font
= vc_rendered_font
;
1670 rendered_font_size
= vc_rendered_font_size
;
1671 rendered_char_size
= vc_rendered_char_size
;
1673 vc_rendered_font
= NULL
;
1674 vc_rendered_font_size
= 0;
1675 vc_rendered_char_size
= 0;
1677 VCPUTC_LOCK_UNLOCK();
1680 if (rendered_font
) {
1681 kheap_free(KHEAP_DATA_BUFFERS
, rendered_font
, rendered_font_size
);
1682 rendered_font
= NULL
;
1686 rendered_char_size
= ISO_CHAR_HEIGHT
* (((newdepth
+ 7) / 8) * ISO_CHAR_WIDTH
);
1687 rendered_font_size
= (ISO_CHAR_MAX
- ISO_CHAR_MIN
+ 1) * rendered_char_size
;
1688 rendered_font
= kheap_alloc(KHEAP_DATA_BUFFERS
, rendered_font_size
, Z_WAITOK
);
1691 if (rendered_font
== NULL
) {
1695 for (charindex
= ISO_CHAR_MIN
; charindex
<= ISO_CHAR_MAX
; charindex
++) {
1696 vc_render_char(charindex
, rendered_font
+ (charindex
* rendered_char_size
), newdepth
);
1699 olddepth
= newdepth
;
1704 vc_rendered_font
= rendered_font
;
1705 vc_rendered_font_size
= rendered_font_size
;
1706 vc_rendered_char_size
= rendered_char_size
;
1708 VCPUTC_LOCK_UNLOCK();
1713 vc_enable(boolean_t enable
)
1715 vc_render_font(enable
? vinfo
.v_depth
: 0);
1719 vc_reverse_cursor(unsigned int xx
, unsigned int yy
)
1724 if (!vinfo
.v_depth
) {
1728 where
= (uint32_t*)(vinfo
.v_baseaddr
+
1729 (yy
* ISO_CHAR_HEIGHT
* vinfo
.v_rowbytes
) +
1730 (xx
/** ISO_CHAR_WIDTH*/ * vinfo
.v_depth
));
1731 for (line
= 0; line
< ISO_CHAR_HEIGHT
; line
++) {
1732 switch (vinfo
.v_depth
) {
1734 where
[0] = ~where
[0];
1735 where
[1] = ~where
[1];
1738 for (col
= 0; col
< 4; col
++) {
1739 where
[col
] = ~where
[col
];
1743 for (col
= 0; col
< 8; col
++) {
1744 where
[col
] = ~where
[col
];
1748 where
= (uint32_t*)(((unsigned char*)where
) + vinfo
.v_rowbytes
);
1753 vc_scroll_down(int num
, unsigned int scrreg_top
, unsigned int scrreg_bottom
)
1755 uint32_t *from
, *to
, linelongs
, i
, line
, rowline
, rowscanline
;
1757 if (!vinfo
.v_depth
) {
1761 linelongs
= vinfo
.v_rowbytes
* (ISO_CHAR_HEIGHT
>> 2);
1762 rowline
= vinfo
.v_rowbytes
>> 2;
1763 rowscanline
= vinfo
.v_rowscanbytes
>> 2;
1765 to
= (uint32_t *) vinfo
.v_baseaddr
+ (linelongs
* scrreg_bottom
)
1766 - (rowline
- rowscanline
);
1767 from
= to
- (linelongs
* num
); /* handle multiple line scroll (Michel Pollet) */
1769 i
= (scrreg_bottom
- scrreg_top
) - num
;
1772 for (line
= 0; line
< ISO_CHAR_HEIGHT
; line
++) {
1774 * Only copy what is displayed
1776 video_scroll_down(from
,
1777 (from
- (vinfo
.v_rowscanbytes
>> 2)),
1787 vc_scroll_up(int num
, unsigned int scrreg_top
, unsigned int scrreg_bottom
)
1789 uint32_t *from
, *to
, linelongs
, i
, line
, rowline
, rowscanline
;
1791 if (!vinfo
.v_depth
) {
1795 linelongs
= vinfo
.v_rowbytes
* (ISO_CHAR_HEIGHT
>> 2);
1796 rowline
= vinfo
.v_rowbytes
>> 2;
1797 rowscanline
= vinfo
.v_rowscanbytes
>> 2;
1799 to
= (uint32_t *) vinfo
.v_baseaddr
+ (scrreg_top
* linelongs
);
1800 from
= to
+ (linelongs
* num
); /* handle multiple line scroll (Michel Pollet) */
1802 i
= (scrreg_bottom
- scrreg_top
) - num
;
1805 for (line
= 0; line
< ISO_CHAR_HEIGHT
; line
++) {
1807 * Only copy what is displayed
1809 video_scroll_up(from
,
1810 (from
+ (vinfo
.v_rowscanbytes
>> 2)),
1820 vc_update_color(int color
, boolean_t fore
)
1822 if (!vinfo
.v_depth
) {
1826 vc_color_fore
= vc_colors
[color
][vc_color_index_table
[vinfo
.v_depth
]];
1828 vc_color_back
= vc_colors
[color
][vc_color_index_table
[vinfo
.v_depth
]];
1833 * Video Console (Back-End): Icon Control
1834 * --------------------------------------
1837 static vc_progress_element
* vc_progress
;
1838 enum { kMaxProgressData
= 3 };
1839 static const unsigned char * vc_progress_data
[kMaxProgressData
];
1840 static const unsigned char * vc_progress_alpha
;
1841 static boolean_t vc_progress_enable
;
1842 static const unsigned char * vc_clut
;
1843 static const unsigned char * vc_clut8
;
1844 static unsigned char vc_revclut8
[256];
1845 static uint32_t vc_progress_interval
;
1846 static uint32_t vc_progress_count
;
1847 static uint32_t vc_progress_angle
;
1848 static uint64_t vc_progress_deadline
;
1849 static thread_call_data_t vc_progress_call
;
1850 static boolean_t vc_needsave
;
1851 static void * vc_saveunder
;
1852 static vm_size_t vc_saveunder_len
;
1853 static int8_t vc_uiscale
= 1;
1854 vc_progress_user_options vc_progress_options
;
1855 vc_progress_user_options vc_user_options
;
1857 decl_simple_lock_data(, vc_progress_lock
);
1859 #if defined(XNU_TARGET_OS_OSX)
1860 static int vc_progress_withmeter
= 3;
1861 int vc_progressmeter_enable
;
1862 static int vc_progressmeter_drawn
;
1863 int vc_progressmeter_value
;
1864 static uint32_t vc_progressmeter_count
;
1865 static uint32_t vc_progress_meter_start
;
1866 static uint32_t vc_progress_meter_end
;
1867 static uint64_t vc_progressmeter_interval
;
1868 static uint64_t vc_progressmeter_deadline
;
1869 static thread_call_data_t vc_progressmeter_call
;
1870 static void * vc_progressmeter_backbuffer
;
1871 static uint32_t vc_progressmeter_diskspeed
= 256;
1873 #endif /* defined(XNU_TARGET_OS_OSX) */
1877 kDataIndexed
= 0x20,
1883 static void vc_blit_rect(int x
, int y
, int bx
,
1884 int width
, int height
,
1885 int sourceWidth
, int sourceHeight
,
1886 int sourceRow
, int backRow
,
1887 const unsigned char * dataPtr
,
1889 unsigned int flags
);
1890 static void vc_blit_rect_8(int x
, int y
, int bx
,
1891 int width
, int height
,
1892 int sourceWidth
, int sourceHeight
,
1893 int sourceRow
, int backRow
,
1894 const unsigned char * dataPtr
,
1895 unsigned char * backBuffer
,
1896 unsigned int flags
);
1897 static void vc_blit_rect_16(int x
, int y
, int bx
,
1898 int width
, int height
,
1899 int sourceWidth
, int sourceHeight
,
1900 int sourceRow
, int backRow
,
1901 const unsigned char * dataPtr
,
1902 unsigned short * backBuffer
,
1903 unsigned int flags
);
1904 static void vc_blit_rect_32(int x
, int y
, int bx
,
1905 int width
, int height
,
1906 int sourceWidth
, int sourceHeight
,
1907 int sourceRow
, int backRow
,
1908 const unsigned char * dataPtr
,
1909 unsigned int * backBuffer
,
1910 unsigned int flags
);
1911 static void vc_blit_rect_30(int x
, int y
, int bx
,
1912 int width
, int height
,
1913 int sourceWidth
, int sourceHeight
,
1914 int sourceRow
, int backRow
,
1915 const unsigned char * dataPtr
,
1916 unsigned int * backBuffer
,
1917 unsigned int flags
);
1918 static void vc_progress_task( void * arg0
, void * arg
);
1919 #if defined(XNU_TARGET_OS_OSX)
1920 static void vc_progressmeter_task( void * arg0
, void * arg
);
1921 #endif /* defined(XNU_TARGET_OS_OSX) */
1924 vc_blit_rect(int x
, int y
, int bx
,
1925 int width
, int height
,
1926 int sourceWidth
, int sourceHeight
,
1927 int sourceRow
, int backRow
,
1928 const unsigned char * dataPtr
,
1932 if (!vinfo
.v_depth
) {
1935 if (((unsigned int)(x
+ width
)) > vinfo
.v_width
) {
1938 if (((unsigned int)(y
+ height
)) > vinfo
.v_height
) {
1942 switch (vinfo
.v_depth
) {
1944 if (vc_clut8
== vc_clut
) {
1945 vc_blit_rect_8( x
, y
, bx
, width
, height
, sourceWidth
, sourceHeight
, sourceRow
, backRow
, dataPtr
, (unsigned char *) backBuffer
, flags
);
1949 vc_blit_rect_16( x
, y
, bx
, width
, height
, sourceWidth
, sourceHeight
, sourceRow
, backRow
, dataPtr
, (unsigned short *) backBuffer
, flags
);
1952 vc_blit_rect_32( x
, y
, bx
, width
, height
, sourceWidth
, sourceHeight
, sourceRow
, backRow
, dataPtr
, (unsigned int *) backBuffer
, flags
);
1955 vc_blit_rect_30( x
, y
, bx
, width
, height
, sourceWidth
, sourceHeight
, sourceRow
, backRow
, dataPtr
, (unsigned int *) backBuffer
, flags
);
1961 vc_blit_rect_8(int x
, int y
, __unused
int bx
,
1962 int width
, int height
,
1963 int sourceWidth
, int sourceHeight
,
1964 int sourceRow
, __unused
int backRow
,
1965 const unsigned char * dataPtr
,
1966 __unused
unsigned char * backBuffer
,
1967 __unused
unsigned int flags
)
1969 volatile unsigned short * dst
;
1971 unsigned int data
= 0, out
= 0;
1972 int sx
, sy
, a
, b
, c
, d
;
1973 int scale
= 0x10000;
1975 a
= (sourceRow
== 1) ? 0 : vc_rotate_matr
[kDataRotate
& flags
][0][0] * scale
;
1976 b
= (sourceRow
== 1) ? 0 : vc_rotate_matr
[kDataRotate
& flags
][0][1] * scale
;
1977 c
= vc_rotate_matr
[kDataRotate
& flags
][1][0] * scale
;
1978 d
= vc_rotate_matr
[kDataRotate
& flags
][1][1] * scale
;
1980 sx
= ((a
+ b
) < 0) ? ((sourceWidth
* scale
) - 0x8000) : 0;
1981 sy
= ((c
+ d
) < 0) ? ((sourceHeight
* scale
) - 0x8000) : 0;
1984 data
= (unsigned int)(uintptr_t)dataPtr
;
1987 dst
= (volatile unsigned short *) (vinfo
.v_baseaddr
+
1988 (y
* vinfo
.v_rowbytes
) +
1991 for (line
= 0; line
< height
; line
++) {
1992 for (col
= 0; col
< width
; col
++) {
1994 data
= dataPtr
[((sx
+ (col
* a
) + (line
* b
)) >> 16)
1995 + sourceRow
* (((sy
+ (col
* c
) + (line
* d
)) >> 16))];
1997 if (kDataAlpha
& flags
) {
1998 out
= vc_revclut8
[data
];
2004 dst
= (volatile unsigned short *) (((volatile char*)dst
) + vinfo
.v_rowbytes
);
2008 /* For ARM, 16-bit is 565 (RGB); it is 1555 (XRGB) on other platforms */
2011 #define CLUT_MASK_R 0xf8
2012 #define CLUT_MASK_G 0xfc
2013 #define CLUT_MASK_B 0xf8
2014 #define CLUT_SHIFT_R << 8
2015 #define CLUT_SHIFT_G << 3
2016 #define CLUT_SHIFT_B >> 3
2017 #define MASK_R 0xf800
2018 #define MASK_G 0x07e0
2019 #define MASK_B 0x001f
2020 #define MASK_R_8 0x7f800
2021 #define MASK_G_8 0x01fe0
2022 #define MASK_B_8 0x000ff
2024 #define CLUT_MASK_R 0xf8
2025 #define CLUT_MASK_G 0xf8
2026 #define CLUT_MASK_B 0xf8
2027 #define CLUT_SHIFT_R << 7
2028 #define CLUT_SHIFT_G << 2
2029 #define CLUT_SHIFT_B >> 3
2030 #define MASK_R 0x7c00
2031 #define MASK_G 0x03e0
2032 #define MASK_B 0x001f
2033 #define MASK_R_8 0x3fc00
2034 #define MASK_G_8 0x01fe0
2035 #define MASK_B_8 0x000ff
2039 vc_blit_rect_16( int x
, int y
, int bx
,
2040 int width
, int height
,
2041 int sourceWidth
, int sourceHeight
,
2042 int sourceRow
, int backRow
,
2043 const unsigned char * dataPtr
,
2044 unsigned short * backPtr
,
2047 volatile unsigned short * dst
;
2049 unsigned int data
= 0, out
= 0, back
= 0;
2050 int sx
, sy
, a
, b
, c
, d
;
2051 int scale
= 0x10000;
2053 a
= (sourceRow
== 1) ? 0 : vc_rotate_matr
[kDataRotate
& flags
][0][0] * scale
;
2054 b
= (sourceRow
== 1) ? 0 : vc_rotate_matr
[kDataRotate
& flags
][0][1] * scale
;
2055 c
= vc_rotate_matr
[kDataRotate
& flags
][1][0] * scale
;
2056 d
= vc_rotate_matr
[kDataRotate
& flags
][1][1] * scale
;
2058 sx
= ((a
+ b
) < 0) ? ((sourceWidth
* scale
) - 0x8000) : 0;
2059 sy
= ((c
+ d
) < 0) ? ((sourceHeight
* scale
) - 0x8000) : 0;
2062 data
= (unsigned int)(uintptr_t)dataPtr
;
2068 dst
= (volatile unsigned short *) (vinfo
.v_baseaddr
+
2069 (y
* vinfo
.v_rowbytes
) +
2072 for (line
= 0; line
< height
; line
++) {
2073 for (col
= 0; col
< width
; col
++) {
2075 data
= dataPtr
[((sx
+ (col
* a
) + (line
* b
)) >> 16)
2076 + sourceRow
* (((sy
+ (col
* c
) + (line
* d
)) >> 16))];
2079 if (kSave
& flags
) {
2080 back
= *(dst
+ col
);
2086 if (kDataIndexed
& flags
) {
2087 out
= ((CLUT_MASK_R
& (vc_clut
[data
* 3 + 0]))CLUT_SHIFT_R
)
2088 | ((CLUT_MASK_G
& (vc_clut
[data
* 3 + 1]))CLUT_SHIFT_G
)
2089 | ((CLUT_MASK_B
& (vc_clut
[data
* 3 + 2]))CLUT_SHIFT_B
);
2090 } else if (kDataAlpha
& flags
) {
2091 out
= (((((back
& MASK_R
) * data
) + MASK_R_8
) >> 8) & MASK_R
)
2092 | (((((back
& MASK_G
) * data
) + MASK_G_8
) >> 8) & MASK_G
)
2093 | (((((back
& MASK_B
) * data
) + MASK_B_8
) >> 8) & MASK_B
);
2094 if (vc_progress_white
) {
2095 out
+= (((0xff - data
) & CLUT_MASK_R
)CLUT_SHIFT_R
)
2096 | (((0xff - data
) & CLUT_MASK_G
)CLUT_SHIFT_G
)
2097 | (((0xff - data
) & CLUT_MASK_B
)CLUT_SHIFT_B
);
2099 } else if (kDataBack
& flags
) {
2106 dst
= (volatile unsigned short *) (((volatile char*)dst
) + vinfo
.v_rowbytes
);
2108 backPtr
+= backRow
- width
;
2115 vc_blit_rect_32(int x
, int y
, int bx
,
2116 int width
, int height
,
2117 int sourceWidth
, int sourceHeight
,
2118 int sourceRow
, int backRow
,
2119 const unsigned char * dataPtr
,
2120 unsigned int * backPtr
,
2123 volatile unsigned int * dst
;
2125 unsigned int data
= 0, out
= 0, back
= 0;
2126 int sx
, sy
, a
, b
, c
, d
;
2127 int scale
= 0x10000;
2129 a
= (sourceRow
== 1) ? 0 : vc_rotate_matr
[kDataRotate
& flags
][0][0] * scale
;
2130 b
= (sourceRow
== 1) ? 0 : vc_rotate_matr
[kDataRotate
& flags
][0][1] * scale
;
2131 c
= vc_rotate_matr
[kDataRotate
& flags
][1][0] * scale
;
2132 d
= vc_rotate_matr
[kDataRotate
& flags
][1][1] * scale
;
2134 sx
= ((a
+ b
) < 0) ? ((sourceWidth
* scale
) - 0x8000) : 0;
2135 sy
= ((c
+ d
) < 0) ? ((sourceHeight
* scale
) - 0x8000) : 0;
2138 data
= (unsigned int)(uintptr_t)dataPtr
;
2144 dst
= (volatile unsigned int *) (vinfo
.v_baseaddr
+
2145 (y
* vinfo
.v_rowbytes
) +
2148 for (line
= 0; line
< height
; line
++) {
2149 for (col
= 0; col
< width
; col
++) {
2151 data
= dataPtr
[((sx
+ (col
* a
) + (line
* b
)) >> 16)
2152 + sourceRow
* (((sy
+ (col
* c
) + (line
* d
)) >> 16))];
2155 if (kSave
& flags
) {
2156 back
= *(dst
+ col
);
2162 if (kDataIndexed
& flags
) {
2163 out
= (vc_clut
[data
* 3 + 0] << 16)
2164 | (vc_clut
[data
* 3 + 1] << 8)
2165 | (vc_clut
[data
* 3 + 2]);
2166 } else if (kDataAlpha
& flags
) {
2167 out
= (((((back
& 0x00ff00ff) * data
) + 0x00ff00ff) >> 8) & 0x00ff00ff)
2168 | (((((back
& 0x0000ff00) * data
) + 0x0000ff00) >> 8) & 0x0000ff00);
2169 if (vc_progress_white
) {
2170 out
+= ((0xff - data
) << 16)
2171 | ((0xff - data
) << 8)
2174 } else if (kDataBack
& flags
) {
2181 dst
= (volatile unsigned int *) (((volatile char*)dst
) + vinfo
.v_rowbytes
);
2183 backPtr
+= backRow
- width
;
2189 vc_blit_rect_30(int x
, int y
, int bx
,
2190 int width
, int height
,
2191 int sourceWidth
, int sourceHeight
,
2192 int sourceRow
, int backRow
,
2193 const unsigned char * dataPtr
,
2194 unsigned int * backPtr
,
2197 volatile unsigned int * dst
;
2199 unsigned int data
= 0, out
= 0, back
= 0;
2200 unsigned long long exp
;
2201 int sx
, sy
, a
, b
, c
, d
;
2202 int scale
= 0x10000;
2204 a
= (sourceRow
== 1) ? 0 : vc_rotate_matr
[kDataRotate
& flags
][0][0] * scale
;
2205 b
= (sourceRow
== 1) ? 0 : vc_rotate_matr
[kDataRotate
& flags
][0][1] * scale
;
2206 c
= vc_rotate_matr
[kDataRotate
& flags
][1][0] * scale
;
2207 d
= vc_rotate_matr
[kDataRotate
& flags
][1][1] * scale
;
2209 sx
= ((a
+ b
) < 0) ? ((sourceWidth
* scale
) - 0x8000) : 0;
2210 sy
= ((c
+ d
) < 0) ? ((sourceHeight
* scale
) - 0x8000) : 0;
2213 data
= (unsigned int)(uintptr_t)dataPtr
;
2219 dst
= (volatile unsigned int *) (vinfo
.v_baseaddr
+
2220 (y
* vinfo
.v_rowbytes
) +
2223 for (line
= 0; line
< height
; line
++) {
2224 for (col
= 0; col
< width
; col
++) {
2226 data
= dataPtr
[((sx
+ (col
* a
) + (line
* b
)) >> 16)
2227 + sourceRow
* (((sy
+ (col
* c
) + (line
* d
)) >> 16))];
2230 if (kSave
& flags
) {
2231 back
= *(dst
+ col
);
2237 if (kDataIndexed
& flags
) {
2238 out
= (vc_clut
[data
* 3 + 0] << 22)
2239 | (vc_clut
[data
* 3 + 1] << 12)
2240 | (vc_clut
[data
* 3 + 2] << 2);
2241 } else if (kDataAlpha
& flags
) {
2243 exp
= (((((exp
& 0x3FF003FF) * data
) + 0x0FF000FF) >> 8) & 0x3FF003FF)
2244 | (((((exp
& 0x000FFC00) * data
) + 0x0003FC00) >> 8) & 0x000FFC00);
2245 out
= (unsigned int)exp
;
2246 if (vc_progress_white
) {
2247 out
+= ((0xFF - data
) << 22)
2248 | ((0xFF - data
) << 12)
2249 | ((0xFF - data
) << 2);
2251 } else if (kDataBack
& flags
) {
2258 dst
= (volatile unsigned int *) (((volatile char*)dst
) + vinfo
.v_rowbytes
);
2260 backPtr
+= backRow
- width
;
2266 vc_clean_boot_graphics(void)
2268 #if defined(XNU_TARGET_OS_OSX)
2269 // clean up possible FDE login graphics
2270 vc_progress_set(FALSE
, 0);
2271 const unsigned char *
2272 color
= (typeof(color
))(uintptr_t)(vc_progress_white
? 0x00000000 : 0xBFBFBFBF);
2273 vc_blit_rect(0, 0, 0, vinfo
.v_width
, vinfo
.v_height
, vinfo
.v_width
, vinfo
.v_height
, 0, 0, color
, NULL
, 0);
2278 * Routines to render the lzss image format
2281 struct lzss_image_state
{
2286 uint32_t bytes_per_row
;
2287 volatile uint32_t * row_start
;
2288 const uint8_t* clut
;
2290 typedef struct lzss_image_state lzss_image_state
;
2292 // returns 0 if OK, 1 if error
2294 vc_decompress_lzss_next_pixel(int next_data
, lzss_image_state
* state
)
2296 uint32_t palette_index
= 0;
2297 uint32_t pixel_value
= 0;
2299 palette_index
= next_data
* 3;
2301 pixel_value
= ((uint32_t) state
->clut
[palette_index
+ 0] << 16)
2302 | ((uint32_t) state
->clut
[palette_index
+ 1] << 8)
2303 | ((uint32_t) state
->clut
[palette_index
+ 2]);
2305 *(state
->row_start
+ state
->col
) = pixel_value
;
2307 if (++state
->col
>= state
->width
) {
2309 if (++state
->row
>= state
->height
) {
2312 state
->row_start
= (volatile uint32_t *) (((uintptr_t)state
->row_start
) + state
->bytes_per_row
);
2319 * Blit an lzss compressed image to the framebuffer
2320 * Assumes 32 bit screen (which is everything we ship at the moment)
2321 * The function vc_display_lzss_icon was copied from libkern/mkext.c, then modified.
2325 * TODO: Does lzss use too much stack? 4096 plus bytes...
2326 * Can probably chop it down by 1/2.
2329 /**************************************************************
2330 * LZSS.C -- A Data Compression Program
2331 ***************************************************************
2332 * 4/6/1989 Haruhiko Okumura
2333 * Use, distribute, and modify this program freely.
2334 * Please send me your improved versions.
2336 * NIFTY-Serve PAF01022
2337 * CompuServe 74050,1022
2339 **************************************************************/
2341 #define N 4096 /* size of ring buffer - must be power of 2 */
2342 #define F 18 /* upper limit for match_length */
2343 #define THRESHOLD 2 /* encode string into position and length
2344 * if match_length is greater than this */
2346 // returns 0 if OK, 1 if error
2347 // x and y indicate upper left corner of image location on screen
2349 vc_display_lzss_icon(uint32_t dst_x
, uint32_t dst_y
,
2350 uint32_t image_width
, uint32_t image_height
,
2351 const uint8_t *compressed_image
,
2352 uint32_t compressed_size
,
2353 const uint8_t *clut
)
2355 uint32_t* image_start
;
2356 uint32_t bytes_per_pixel
= 4;
2357 uint32_t bytes_per_row
= vinfo
.v_rowbytes
;
2359 vc_clean_boot_graphics();
2361 image_start
= (uint32_t *) (vinfo
.v_baseaddr
+ (dst_y
* bytes_per_row
) + (dst_x
* bytes_per_pixel
));
2363 lzss_image_state state
= {0, 0, image_width
, image_height
, bytes_per_row
, image_start
, clut
};
2367 const uint8_t *src
= compressed_image
;
2368 uint32_t srclen
= compressed_size
;
2370 /* ring buffer of size N, with extra F-1 bytes to aid string comparison */
2371 uint8_t text_buf
[N
+ F
- 1];
2372 const uint8_t *srcend
= src
+ srclen
;
2376 srcend
= src
+ srclen
;
2377 for (i
= 0; i
< N
- F
; i
++) {
2383 if (((flags
>>= 1) & 0x100) == 0) {
2389 flags
= c
| 0xFF00; /* uses higher byte cleverly */
2390 } /* to count eight */
2397 rval
= vc_decompress_lzss_next_pixel(c
, &state
);
2414 i
|= ((j
& 0xF0) << 4);
2415 j
= (j
& 0x0F) + THRESHOLD
;
2416 for (k
= 0; k
<= j
; k
++) {
2417 c
= text_buf
[(i
+ k
) & (N
- 1)];
2418 rval
= vc_decompress_lzss_next_pixel(c
, &state
);
2431 noroot_icon_test(void)
2433 boolean_t o_vc_progress_enable
= vc_progress_enable
;
2435 vc_progress_enable
= 1;
2437 PE_display_icon( 0, "noroot");
2439 vc_progress_enable
= o_vc_progress_enable
;
2444 vc_display_icon( vc_progress_element
* desc
,
2445 const unsigned char * data
)
2447 int x
, y
, width
, height
;
2449 if (vc_progress_enable
&& vc_clut
) {
2450 vc_clean_boot_graphics();
2452 width
= desc
->width
;
2453 height
= desc
->height
;
2456 if (1 & desc
->flags
) {
2457 x
+= ((vinfo
.v_width
- width
) / 2);
2458 y
+= ((vinfo
.v_height
- height
) / 2);
2460 vc_blit_rect( x
, y
, 0, width
, height
, width
, height
, width
, 0, data
, NULL
, kDataIndexed
);
2465 vc_progress_initialize( vc_progress_element
* desc
,
2466 const unsigned char * data1x
,
2467 const unsigned char * data2x
,
2468 const unsigned char * data3x
,
2469 const unsigned char * clut
)
2473 if ((!clut
) || (!desc
) || (!data1x
)) {
2480 vc_progress_data
[0] = data1x
;
2481 vc_progress_data
[1] = data2x
;
2482 vc_progress_data
[2] = data3x
;
2483 if (2 & vc_progress
->flags
) {
2484 vc_progress_alpha
= data1x
2485 + vc_progress
->count
* vc_progress
->width
* vc_progress
->height
;
2487 vc_progress_alpha
= NULL
;
2490 thread_call_setup(&vc_progress_call
, vc_progress_task
, NULL
);
2491 clock_interval_to_absolutetime_interval(vc_progress
->time
, 1000 * 1000, &abstime
);
2492 vc_progress_interval
= (uint32_t)abstime
;
2494 #if defined(XNU_TARGET_OS_OSX)
2495 thread_call_setup(&vc_progressmeter_call
, vc_progressmeter_task
, NULL
);
2496 clock_interval_to_absolutetime_interval(1000 / 8, 1000 * 1000, &abstime
);
2497 vc_progressmeter_interval
= (uint32_t)abstime
;
2498 #endif /* defined(XNU_TARGET_OS_OSX) */
2502 vc_progress_set(boolean_t enable
, uint32_t vc_delay
)
2505 void *saveBuf
= NULL
;
2506 vm_size_t saveLen
= 0;
2509 unsigned char pdata8
;
2510 unsigned short pdata16
;
2511 unsigned short * buf16
;
2512 unsigned int pdata32
;
2513 unsigned int * buf32
;
2519 #if defined(CONFIG_VC_PROGRESS_METER_SUPPORT)
2521 #if defined (__x86_64__)
2522 if (kBootArgsFlagBlack
& ((boot_args
*) PE_state
.bootArgs
)->flags
) {
2525 #endif /* defined (__x86_64__) */
2527 if (1 & vc_progress_withmeter
) {
2529 internal_enable_progressmeter(kProgressMeterKernel
);
2533 simple_lock(&vc_progress_lock
, LCK_GRP_NULL
);
2535 if (vc_progress_enable
!= enable
) {
2536 vc_progress_enable
= enable
;
2538 vc_progressmeter_count
= 0;
2539 clock_interval_to_deadline(vc_delay
,
2540 1000 * 1000 * 1000 /*second scale*/,
2541 &vc_progressmeter_deadline
);
2542 thread_call_enter_delayed(&vc_progressmeter_call
, vc_progressmeter_deadline
);
2544 thread_call_cancel(&vc_progressmeter_call
);
2548 simple_unlock(&vc_progress_lock
);
2552 internal_enable_progressmeter(kProgressMeterOff
);
2557 #endif /* defined(CONFIG_VC_PROGRESS_METER_SUPPORT) */
2560 saveLen
= (vc_progress
->width
* vc_uiscale
) * (vc_progress
->height
* vc_uiscale
) * ((vinfo
.v_depth
+ 7) / 8);
2561 saveBuf
= kheap_alloc( KHEAP_DATA_BUFFERS
, saveLen
, Z_WAITOK
);
2563 switch (vinfo
.v_depth
) {
2565 for (count
= 0; count
< 256; count
++) {
2566 vc_revclut8
[count
] = vc_clut
[0x01 * 3];
2567 pdata8
= (vc_clut
[0x01 * 3] * count
+ 0x0ff) >> 8;
2568 for (index
= 0; index
< 256; index
++) {
2569 if ((pdata8
== vc_clut
[index
* 3 + 0]) &&
2570 (pdata8
== vc_clut
[index
* 3 + 1]) &&
2571 (pdata8
== vc_clut
[index
* 3 + 2])) {
2572 vc_revclut8
[count
] = index
;
2577 memset( saveBuf
, 0x01, saveLen
);
2581 buf16
= (unsigned short *) saveBuf
;
2582 pdata16
= ((vc_clut
[0x01 * 3 + 0] & CLUT_MASK_R
)CLUT_SHIFT_R
)
2583 | ((vc_clut
[0x01 * 3 + 0] & CLUT_MASK_G
)CLUT_SHIFT_G
)
2584 | ((vc_clut
[0x01 * 3 + 0] & CLUT_MASK_B
)CLUT_SHIFT_B
);
2585 for (count
= 0; count
< saveLen
/ 2; count
++) {
2586 buf16
[count
] = pdata16
;
2591 buf32
= (unsigned int *) saveBuf
;
2592 pdata32
= ((vc_clut
[0x01 * 3 + 0] & 0xff) << 16)
2593 | ((vc_clut
[0x01 * 3 + 1] & 0xff) << 8)
2594 | ((vc_clut
[0x01 * 3 + 2] & 0xff) << 0);
2595 for (count
= 0; count
< saveLen
/ 4; count
++) {
2596 buf32
[count
] = pdata32
;
2603 simple_lock(&vc_progress_lock
, LCK_GRP_NULL
);
2605 if (vc_progress_enable
!= enable
) {
2606 vc_progress_enable
= enable
;
2609 vc_saveunder
= saveBuf
;
2610 vc_saveunder_len
= saveLen
;
2613 vc_progress_count
= 0;
2614 vc_progress_angle
= 0;
2616 clock_interval_to_deadline(vc_delay
,
2617 1000 * 1000 * 1000 /*second scale*/,
2618 &vc_progress_deadline
);
2619 thread_call_enter_delayed(&vc_progress_call
, vc_progress_deadline
);
2622 saveBuf
= vc_saveunder
;
2623 saveLen
= vc_saveunder_len
;
2624 vc_saveunder
= NULL
;
2625 vc_saveunder_len
= 0;
2628 thread_call_cancel(&vc_progress_call
);
2632 simple_unlock(&vc_progress_lock
);
2636 kheap_free( KHEAP_DATA_BUFFERS
, saveBuf
, saveLen
);
2640 #if defined(XNU_TARGET_OS_OSX)
2643 vc_progressmeter_range(uint32_t pos
)
2647 if (pos
> kProgressMeterEnd
) {
2648 pos
= kProgressMeterEnd
;
2650 ret
= vc_progress_meter_start
2651 + ((pos
* (vc_progress_meter_end
- vc_progress_meter_start
)) / kProgressMeterEnd
);
2657 vc_progressmeter_task(__unused
void *arg0
, __unused
void *arg
)
2663 simple_lock(&vc_progress_lock
, LCK_GRP_NULL
);
2664 if (kProgressMeterKernel
== vc_progressmeter_enable
) {
2665 uint32_t pos
= (vc_progressmeter_count
>> 13);
2666 internal_set_progressmeter(vc_progressmeter_range(pos
));
2667 if (pos
< kProgressMeterEnd
) {
2668 static uint16_t incr
[8] = { 10000, 10000, 8192, 4096, 2048, 384, 384, 64 };
2669 vc_progressmeter_count
+= incr
[(pos
* 8) / kProgressMeterEnd
];
2671 interval
= vc_progressmeter_interval
;
2672 interval
= ((interval
* 256) / vc_progressmeter_diskspeed
);
2674 clock_deadline_for_periodic_event(interval
, mach_absolute_time(), &vc_progressmeter_deadline
);
2675 thread_call_enter_delayed(&vc_progressmeter_call
, vc_progressmeter_deadline
);
2678 simple_unlock(&vc_progress_lock
);
2683 vc_progress_setdiskspeed(uint32_t speed
)
2685 vc_progressmeter_diskspeed
= speed
;
2688 #endif /* defined(XNU_TARGET_OS_OSX) */
2691 vc_progress_task(__unused
void *arg0
, __unused
void *arg
)
2694 int x
, y
, width
, height
;
2695 uint64_t x_pos
, y_pos
;
2696 const unsigned char * data
;
2699 simple_lock(&vc_progress_lock
, LCK_GRP_NULL
);
2701 if (vc_progress_enable
) {
2703 vc_progress_count
++;
2704 if (vc_progress_count
>= vc_progress
->count
) {
2705 vc_progress_count
= 0;
2706 vc_progress_angle
++;
2709 width
= (vc_progress
->width
* vc_uiscale
);
2710 height
= (vc_progress
->height
* vc_uiscale
);
2711 data
= vc_progress_data
[vc_uiscale
- 1];
2716 if (kVCUsePosition
& vc_progress_options
.options
) {
2717 /* Rotation: 0:normal, 1:right 90, 2:left 180, 3:left 90 */
2718 switch (3 & vinfo
.v_rotate
) {
2720 x_pos
= vc_progress_options
.x_pos
;
2721 y_pos
= vc_progress_options
.y_pos
;
2723 case kDataRotate180
:
2724 x_pos
= 0xFFFFFFFF - vc_progress_options
.x_pos
;
2725 y_pos
= 0xFFFFFFFF - vc_progress_options
.y_pos
;
2728 x_pos
= 0xFFFFFFFF - vc_progress_options
.y_pos
;
2729 y_pos
= vc_progress_options
.x_pos
;
2731 case kDataRotate270
:
2732 x_pos
= vc_progress_options
.y_pos
;
2733 y_pos
= 0xFFFFFFFF - vc_progress_options
.x_pos
;
2736 x
= (uint32_t)((x_pos
* (uint64_t) vinfo
.v_width
) / 0xFFFFFFFFULL
);
2737 y
= (uint32_t)((y_pos
* (uint64_t) vinfo
.v_height
) / 0xFFFFFFFFULL
);
2741 x
= (vc_progress
->dx
* vc_uiscale
);
2742 y
= (vc_progress
->dy
* vc_uiscale
);
2743 if (1 & vc_progress
->flags
) {
2744 x
+= ((vinfo
.v_width
- width
) / 2);
2745 y
+= ((vinfo
.v_height
- height
) / 2);
2749 if ((x
+ width
) > (int)vinfo
.v_width
) {
2752 if ((y
+ height
) > (int)vinfo
.v_height
) {
2756 data
+= vc_progress_count
* width
* height
;
2758 vc_blit_rect( x
, y
, 0,
2759 width
, height
, width
, height
, width
, width
,
2762 | (vc_progress_angle
& kDataRotate
)
2763 | (vc_needsave
? kSave
: 0));
2764 vc_needsave
= FALSE
;
2766 clock_deadline_for_periodic_event(vc_progress_interval
, mach_absolute_time(), &vc_progress_deadline
);
2767 thread_call_enter_delayed(&vc_progress_call
, vc_progress_deadline
);
2770 simple_unlock(&vc_progress_lock
);
2775 * Generic Console (Front-End): Master Control
2776 * -------------------------------------------
2779 #if defined (__i386__) || defined (__x86_64__)
2780 #include <pexpert/i386/boot.h>
2783 static boolean_t gc_acquired
= FALSE
;
2784 static boolean_t gc_graphics_boot
= FALSE
;
2785 static boolean_t gc_desire_text
= FALSE
;
2786 static boolean_t gc_paused_progress
;
2788 static vm_offset_t lastVideoVirt
= 0;
2789 static vm_size_t lastVideoMapSize
= 0;
2790 static boolean_t lastVideoMapKmap
= FALSE
;
2793 gc_pause( boolean_t pause
, boolean_t graphics_now
)
2800 disableConsoleOutput
= (pause
&& !console_is_serial());
2801 gc_enabled
= (!pause
&& !graphics_now
);
2803 VCPUTC_LOCK_UNLOCK();
2805 simple_lock(&vc_progress_lock
, LCK_GRP_NULL
);
2808 gc_paused_progress
= vc_progress_enable
;
2809 vc_progress_enable
= FALSE
;
2811 vc_progress_enable
= gc_paused_progress
;
2814 if (vc_progress_enable
) {
2815 #if defined(XNU_TARGET_OS_OSX)
2816 if (1 & vc_progress_withmeter
) {
2817 thread_call_enter_delayed(&vc_progressmeter_call
, vc_progressmeter_deadline
);
2819 #endif /* defined(XNU_TARGET_OS_OSX) */
2820 thread_call_enter_delayed(&vc_progress_call
, vc_progress_deadline
);
2823 simple_unlock(&vc_progress_lock
);
2828 vc_initialize(__unused
struct vc_info
* vinfo_p
)
2831 unsigned long cnt
, data16
, data32
;
2833 if (vinfo
.v_depth
== 16) {
2834 for (cnt
= 0; cnt
< 8; cnt
++) {
2835 data32
= vc_colors
[cnt
][2];
2836 data16
= (data32
& 0x0000F8) << 8;
2837 data16
|= (data32
& 0x00FC00) >> 5;
2838 data16
|= (data32
& 0xF80000) >> 19;
2839 data16
|= data16
<< 16;
2840 vc_colors
[cnt
][1] = data16
;
2845 vinfo
.v_rows
= vinfo
.v_height
/ ISO_CHAR_HEIGHT
;
2846 vinfo
.v_columns
= vinfo
.v_width
/ ISO_CHAR_WIDTH
;
2847 vinfo
.v_rowscanbytes
= ((vinfo
.v_depth
+ 7) / 8) * vinfo
.v_width
;
2848 vc_uiscale
= vinfo
.v_scale
;
2849 if (vc_uiscale
> kMaxProgressData
) {
2850 vc_uiscale
= kMaxProgressData
;
2851 } else if (!vc_uiscale
) {
2857 initialize_screen(PE_Video
* boot_vinfo
, unsigned int op
)
2859 unsigned int newMapSize
= 0;
2860 vm_offset_t newVideoVirt
= 0;
2861 boolean_t graphics_now
;
2865 struct vc_info new_vinfo
= vinfo
;
2866 boolean_t makeMapping
= FALSE
;
2871 if (kPEBaseAddressChange
!= op
) {
2872 new_vinfo
.v_width
= (unsigned int)boot_vinfo
->v_width
;
2873 new_vinfo
.v_height
= (unsigned int)boot_vinfo
->v_height
;
2874 new_vinfo
.v_depth
= (unsigned int)boot_vinfo
->v_depth
;
2875 new_vinfo
.v_rowbytes
= (unsigned int)boot_vinfo
->v_rowBytes
;
2876 if (kernel_map
== VM_MAP_NULL
) {
2877 // only booter supplies HW rotation
2878 new_vinfo
.v_rotate
= (unsigned int)boot_vinfo
->v_rotate
;
2880 #if defined(__i386__) || defined(__x86_64__)
2881 new_vinfo
.v_type
= (unsigned int)boot_vinfo
->v_display
;
2883 new_vinfo
.v_type
= 0;
2885 unsigned int scale
= (unsigned int)boot_vinfo
->v_scale
;
2886 if (scale
== kPEScaleFactor1x
) {
2887 new_vinfo
.v_scale
= kPEScaleFactor1x
;
2888 } else if (scale
== kPEScaleFactor2x
) {
2889 new_vinfo
.v_scale
= kPEScaleFactor2x
;
2891 else { /* Scale factor not set, default to 1x */
2892 new_vinfo
.v_scale
= kPEScaleFactor1x
;
2895 new_vinfo
.v_name
[0] = 0;
2896 new_vinfo
.v_physaddr
= 0;
2899 * Check if we are have to map the framebuffer
2900 * If VM is up, we are given a virtual address, unless b0 is set to indicate physical.
2902 newVideoVirt
= boot_vinfo
->v_baseAddr
;
2903 makeMapping
= (kernel_map
== VM_MAP_NULL
) || (0 != (1 & newVideoVirt
));
2906 new_vinfo
.v_physaddr
= boot_vinfo
->v_baseAddr
& ~3UL; /* Get the physical address */
2908 new_vinfo
.v_physaddr
|= (((uint64_t) boot_vinfo
->v_baseAddrHigh
) << 32);
2910 kprintf("initialize_screen: b=%08llX, w=%08X, h=%08X, r=%08X, d=%08X\n", /* (BRINGUP) */
2911 new_vinfo
.v_physaddr
, new_vinfo
.v_width
, new_vinfo
.v_height
, new_vinfo
.v_rowbytes
, new_vinfo
.v_type
); /* (BRINGUP) */
2914 if (!newVideoVirt
&& !new_vinfo
.v_physaddr
) { /* Check to see if we have a framebuffer */
2915 kprintf("initialize_screen: No video - forcing serial mode\n"); /* (BRINGUP) */
2916 new_vinfo
.v_depth
= 0; /* vc routines are nop */
2917 (void)switch_to_serial_console(); /* Switch into serial mode */
2918 gc_graphics_boot
= FALSE
; /* Say we are not in graphics mode */
2919 disableConsoleOutput
= FALSE
; /* Allow printfs to happen */
2923 unsigned int flags
= VM_WIMG_IO
;
2924 if (boot_vinfo
->v_length
!= 0) {
2925 newMapSize
= (unsigned int) round_page(boot_vinfo
->v_length
);
2927 newMapSize
= (unsigned int) round_page(new_vinfo
.v_height
* new_vinfo
.v_rowbytes
); /* Remember size */
2929 newVideoVirt
= io_map_spec((vm_map_offset_t
)new_vinfo
.v_physaddr
, newMapSize
, flags
); /* Allocate address space for framebuffer */
2931 new_vinfo
.v_baseaddr
= newVideoVirt
+ boot_vinfo
->v_offset
; /* Set the new framebuffer address */
2934 #if defined(__x86_64__)
2935 // Adjust the video buffer pointer to point to where it is in high virtual (above the hole)
2936 new_vinfo
.v_baseaddr
|= (VM_MIN_KERNEL_ADDRESS
& ~LOW_4GB_MASK
);
2939 /* Update the vinfo structure atomically with respect to the vc_progress task if running */
2941 simple_lock(&vc_progress_lock
, LCK_GRP_NULL
);
2943 simple_unlock(&vc_progress_lock
);
2948 // If we changed the virtual address, remove the old mapping
2949 if (newVideoVirt
!= 0) {
2950 if (lastVideoVirt
&& lastVideoMapSize
) { /* Was the framebuffer mapped before? */
2951 /* XXX why only !4K? */
2952 if (!TEST_PAGE_SIZE_4K
&& lastVideoMapSize
) {
2953 pmap_remove(kernel_pmap
, trunc_page_64(lastVideoVirt
),
2954 round_page_64(lastVideoVirt
+ lastVideoMapSize
)); /* Toss mappings */
2956 /* Was this not a special pre-VM mapping? */
2957 if (lastVideoMapKmap
) {
2958 kmem_free(kernel_map
, lastVideoVirt
, lastVideoMapSize
); /* Toss kernel addresses */
2961 lastVideoMapKmap
= (NULL
!= kernel_map
); /* Remember how mapped */
2962 lastVideoMapSize
= newMapSize
; /* Remember the size */
2963 lastVideoVirt
= newVideoVirt
; /* Remember the virtual framebuffer address */
2966 if (kPEBaseAddressChange
!= op
) {
2967 // Graphics mode setup by the booter.
2969 gc_ops
.initialize
= vc_initialize
;
2970 gc_ops
.enable
= vc_enable
;
2971 gc_ops
.paint_char
= vc_paint_char
;
2972 gc_ops
.scroll_down
= vc_scroll_down
;
2973 gc_ops
.scroll_up
= vc_scroll_up
;
2974 gc_ops
.clear_screen
= vc_clear_screen
;
2975 gc_ops
.hide_cursor
= vc_reverse_cursor
;
2976 gc_ops
.show_cursor
= vc_reverse_cursor
;
2977 gc_ops
.update_color
= vc_update_color
;
2978 gc_initialize(&vinfo
);
2982 graphics_now
= gc_graphics_boot
&& !gc_desire_text
;
2984 case kPEGraphicsMode
:
2985 gc_graphics_boot
= TRUE
;
2986 gc_desire_text
= FALSE
;
2990 gc_graphics_boot
= FALSE
;
2993 case kPEAcquireScreen
:
2998 vc_progress_options
= vc_user_options
;
2999 bzero(&vc_user_options
, sizeof(vc_user_options
));
3001 if (kVCAcquireImmediate
& vc_progress_options
.options
) {
3003 } else if (kVCDarkReboot
& vc_progress_options
.options
) {
3006 delay
= vc_acquire_delay
;
3009 if (kVCDarkBackground
& vc_progress_options
.options
) {
3010 vc_progress_white
= TRUE
;
3011 } else if (kVCLightBackground
& vc_progress_options
.options
) {
3012 vc_progress_white
= FALSE
;
3015 #if !defined(XNU_TARGET_OS_BRIDGE)
3016 vc_progress_set( graphics_now
, delay
);
3017 #endif /* !defined(XNU_TARGET_OS_BRIDGE) */
3018 gc_enable( !graphics_now
);
3020 gc_desire_text
= FALSE
;
3023 case kPEDisableScreen
:
3025 gc_pause( TRUE
, graphics_now
);
3029 case kPEEnableScreen
:
3031 gc_pause( FALSE
, graphics_now
);
3036 if (console_is_serial()) {
3040 if (gc_acquired
== FALSE
) {
3041 gc_desire_text
= TRUE
;
3044 if (gc_graphics_boot
== FALSE
) {
3048 vc_progress_set( FALSE
, 0 );
3049 #if defined(XNU_TARGET_OS_OSX)
3050 vc_enable_progressmeter( FALSE
);
3055 case kPEReleaseScreen
:
3056 gc_acquired
= FALSE
;
3057 gc_desire_text
= FALSE
;
3059 if (gc_graphics_boot
== FALSE
) {
3063 vc_progress_set( FALSE
, 0 );
3064 vc_acquire_delay
= kProgressReacquireDelay
;
3065 vc_progress_white
= TRUE
;
3066 #if defined(XNU_TARGET_OS_OSX)
3067 vc_enable_progressmeter(FALSE
);
3068 vc_progress_withmeter
&= ~1;
3074 #if defined(__x86_64__)
3075 case kPERefreshBootGraphics
:
3080 if (kBootArgsFlagBlack
& ((boot_args
*) PE_state
.bootArgs
)->flags
) {
3084 save
= vc_progress_white
;
3085 vc_progress_white
= (0 != (kBootArgsFlagBlackBg
& ((boot_args
*) PE_state
.bootArgs
)->flags
));
3087 internal_enable_progressmeter(kProgressMeterKernel
);
3090 simple_lock(&vc_progress_lock
, LCK_GRP_NULL
);
3092 vc_progressmeter_drawn
= 0;
3093 internal_set_progressmeter(vc_progressmeter_range(vc_progressmeter_count
>> 13));
3095 simple_unlock(&vc_progress_lock
);
3098 internal_enable_progressmeter(kProgressMeterOff
);
3099 vc_progress_white
= save
;
3105 void vcattach(void); /* XXX gcc 4 warning cleanup */
3110 vm_initialized
= TRUE
;
3112 #if defined(CONFIG_VC_PROGRESS_METER_SUPPORT)
3113 const boot_args
* bootargs
= (typeof(bootargs
))PE_state
.bootArgs
;
3115 PE_parse_boot_argn("meter", &vc_progress_withmeter
, sizeof(vc_progress_withmeter
));
3117 #if defined(__x86_64__)
3118 vc_progress_white
= (0 != ((kBootArgsFlagBlackBg
| kBootArgsFlagLoginUI
)
3119 & bootargs
->flags
));
3120 if (kBootArgsFlagInstallUI
& bootargs
->flags
) {
3121 vc_progress_meter_start
= (bootargs
->bootProgressMeterStart
* kProgressMeterMax
) / 65535;
3122 vc_progress_meter_end
= (bootargs
->bootProgressMeterEnd
* kProgressMeterMax
) / 65535;
3124 vc_progress_meter_start
= 0;
3125 vc_progress_meter_end
= kProgressMeterEnd
;
3128 vc_progress_meter_start
= 0;
3129 vc_progress_meter_end
= kProgressMeterEnd
;
3130 #endif /* defined(__x86_64__ */
3131 #endif /* defined(CONFIG_VC_PROGRESS_METER_SUPPORT) */
3132 simple_lock_init(&vc_progress_lock
, 0);
3134 if (gc_graphics_boot
== FALSE
) {
3138 initialize_screen(NULL
, kPEReleaseScreen
);
3141 initialize_screen(NULL
, kPEAcquireScreen
);
3143 for (index
= 0; index
< msgbufp
->msg_bufx
; index
++) {
3144 if (msgbufp
->msg_bufc
[index
] == '\0') {
3148 vcputc( 0, 0, msgbufp
->msg_bufc
[index
] );
3150 if (msgbufp
->msg_bufc
[index
] == '\n') {
3151 vcputc( 0, 0, '\r' );
3157 #if defined(XNU_TARGET_OS_OSX)
3159 // redraw progress meter between pixels start, end, position at pos,
3160 // options (including rotation) passed in flags
3162 vc_draw_progress_meter(unsigned int flags
, int start
, int end
, int pos
)
3164 const unsigned char *data
;
3165 int i
, width
, bx
, srcRow
, backRow
;
3166 int rectX
, rectY
, rectW
, rectH
;
3167 int endCapPos
, endCapStart
;
3168 int barWidth
= kProgressBarWidth
* vc_uiscale
;
3169 int barHeight
= kProgressBarHeight
* vc_uiscale
;
3170 int capWidth
= kProgressBarCapWidth
* vc_uiscale
;
3171 // 1 rounded fill, 0 square end
3172 int style
= (0 == (2 & vc_progress_withmeter
));
3173 // 1 white, 0 greyed out
3176 for (i
= start
; i
< end
; i
+= width
) {
3178 endCapPos
= ((style
&& onoff
) ? pos
: barWidth
);
3179 endCapStart
= endCapPos
- capWidth
;
3180 if (flags
& kDataBack
) { // restore back bits
3181 width
= end
;// loop done after this iteration
3184 } else if (i
< capWidth
) { // drawing the left cap
3185 width
= (end
< capWidth
) ? (end
- i
) : (capWidth
- i
);
3186 data
= progressmeter_leftcap
[vc_uiscale
>= 2][onoff
];
3189 } else if (i
< endCapStart
) { // drawing the middle
3190 width
= (end
< endCapStart
) ? (end
- i
) : (endCapStart
- i
);
3191 data
= progressmeter_middle
[vc_uiscale
>= 2][onoff
];
3193 } else { // drawing the right cap
3194 width
= endCapPos
- i
;
3195 data
= progressmeter_rightcap
[vc_uiscale
>= 2][onoff
];
3196 data
+= i
- endCapStart
;
3200 switch (flags
& kDataRotate
) {
3201 case kDataRotate90
: // left middle, bar goes down
3204 rectX
= ((vinfo
.v_width
/ 3) - (barHeight
/ 2));
3205 rectY
= ((vinfo
.v_height
- barWidth
) / 2) + i
;
3207 backRow
= barHeight
;
3209 case kDataRotate180
: // middle upper, bar goes left
3212 rectX
= ((vinfo
.v_width
- barWidth
) / 2) + barWidth
- width
- i
;
3213 rectY
= (vinfo
.v_height
/ 3) - (barHeight
/ 2);
3214 bx
= barWidth
- width
- i
;
3217 case kDataRotate270
: // right middle, bar goes up
3220 rectX
= (vinfo
.v_width
- (vinfo
.v_width
/ 3) - (barHeight
/ 2));
3221 rectY
= ((vinfo
.v_height
- barWidth
) / 2) + barWidth
- width
- i
;
3222 bx
= (barWidth
- width
- i
) * barHeight
;
3223 backRow
= barHeight
;
3226 case kDataRotate0
: // middle lower, bar goes right
3229 rectX
= ((vinfo
.v_width
- barWidth
) / 2) + i
;
3230 rectY
= vinfo
.v_height
- (vinfo
.v_height
/ 3) - (barHeight
/ 2);
3235 vc_blit_rect(rectX
, rectY
, bx
, rectW
, rectH
, width
, barHeight
,
3236 srcRow
, backRow
, data
, vc_progressmeter_backbuffer
, flags
);
3240 extern void IORecordProgressBackbuffer(void * buffer
, size_t size
, uint32_t theme
);
3243 internal_enable_progressmeter(int new_value
)
3247 boolean_t stashBackbuffer
;
3248 int flags
= vinfo
.v_rotate
;
3250 stashBackbuffer
= FALSE
;
3253 new_buffer
= kheap_alloc(KHEAP_DATA_BUFFERS
,
3254 (kProgressBarWidth
* vc_uiscale
) *
3255 (kProgressBarHeight
* vc_uiscale
) * sizeof(int), Z_WAITOK
);
3259 simple_lock(&vc_progress_lock
, LCK_GRP_NULL
);
3261 if (kProgressMeterUser
== new_value
) {
3262 if (gc_enabled
|| !gc_acquired
|| !gc_graphics_boot
) {
3263 new_value
= vc_progressmeter_enable
;
3267 if (new_value
!= vc_progressmeter_enable
) {
3269 if (kProgressMeterOff
== vc_progressmeter_enable
) {
3270 vc_progressmeter_backbuffer
= new_buffer
;
3271 vc_draw_progress_meter(kDataAlpha
| kSave
| flags
, 0, (kProgressBarWidth
* vc_uiscale
), 0);
3273 vc_progressmeter_drawn
= 0;
3275 vc_progressmeter_enable
= new_value
;
3276 } else if (vc_progressmeter_backbuffer
) {
3277 if (kProgressMeterUser
== vc_progressmeter_enable
) {
3278 vc_draw_progress_meter(kDataBack
| flags
, 0, (kProgressBarWidth
* vc_uiscale
), vc_progressmeter_drawn
);
3280 stashBackbuffer
= TRUE
;
3282 new_buffer
= vc_progressmeter_backbuffer
;
3283 vc_progressmeter_backbuffer
= NULL
;
3284 vc_progressmeter_enable
= FALSE
;
3288 simple_unlock(&vc_progress_lock
);
3292 if (stashBackbuffer
) {
3293 IORecordProgressBackbuffer(new_buffer
,
3294 (kProgressBarWidth
* vc_uiscale
)
3295 * (kProgressBarHeight
* vc_uiscale
)
3299 kheap_free(KHEAP_DATA_BUFFERS
, new_buffer
,
3300 (kProgressBarWidth
* vc_uiscale
) *
3301 (kProgressBarHeight
* vc_uiscale
) * sizeof(int));
3306 internal_set_progressmeter(int new_value
)
3310 // 1 rounded fill, 0 square end
3311 int style
= (0 == (2 & vc_progress_withmeter
));
3312 int flags
= kDataAlpha
| vinfo
.v_rotate
;
3314 if ((new_value
< 0) || (new_value
> kProgressMeterMax
)) {
3318 if (vc_progressmeter_enable
) {
3319 vc_progressmeter_value
= new_value
;
3321 capRedraw
= (style
? (kProgressBarCapWidth
* vc_uiscale
) : 0);
3322 x3
= (((kProgressBarWidth
* vc_uiscale
) - 2 * capRedraw
) * vc_progressmeter_value
) / kProgressMeterMax
;
3323 x3
+= (2 * capRedraw
);
3325 if (x3
> vc_progressmeter_drawn
) {
3327 if (x1
> vc_progressmeter_drawn
) {
3328 x1
= vc_progressmeter_drawn
;
3330 vc_draw_progress_meter(flags
, vc_progressmeter_drawn
- x1
, x3
, x3
);
3332 vc_draw_progress_meter(flags
, x3
- capRedraw
, vc_progressmeter_drawn
, x3
);
3334 vc_progressmeter_drawn
= x3
;
3339 vc_enable_progressmeter(int new_value
)
3341 internal_enable_progressmeter(new_value
? kProgressMeterUser
: kProgressMeterOff
);
3345 vc_set_progressmeter(int new_value
)
3350 simple_lock(&vc_progress_lock
, LCK_GRP_NULL
);
3352 if (vc_progressmeter_enable
) {
3353 if (kProgressMeterKernel
!= vc_progressmeter_enable
) {
3354 internal_set_progressmeter(new_value
);
3357 vc_progressmeter_value
= new_value
;
3360 simple_unlock(&vc_progress_lock
);
3364 #endif /* defined(XNU_TARGET_OS_OSX) */