1/*
2 * Copyright (c) 2000-2009 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*
29 * @OSF_FREE_COPYRIGHT@
30 *
31 */
32/*
33 * @APPLE_FREE_COPYRIGHT@
34 */
35/*
36 * NetBSD: ite.c,v 1.16 1995/07/17 01:24:34 briggs Exp
37 *
38 * Copyright (c) 1988 University of Utah.
39 * Copyright (c) 1990, 1993
40 * The Regents of the University of California. All rights reserved.
41 *
42 * This code is derived from software contributed to Berkeley by
43 * the Systems Programming Group of the University of Utah Computer
44 * Science Department.
45 *
46 * Redistribution and use in source and binary forms, with or without
47 * modification, are permitted provided that the following conditions
48 * are met:
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.
61 *
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
72 * SUCH DAMAGE.
73 *
74 * from: Utah $Hdr: ite.c 1.28 92/12/20$
75 *
76 * @(#)ite.c 8.2 (Berkeley) 1/12/94
77 */
78
79/*
80 * ite.c
81 *
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.
86 *
87 * -- Brad and Lawrence, June 26th, 1994
88 *
89 */
90
91#include <console/video_console.h>
92#include <console/serial_protos.h>
93
94#include <kern/kern_types.h>
95#include <kern/kalloc.h>
96#include <kern/debug.h>
97#include <kern/spl.h>
98#include <kern/thread_call.h>
99
100#include <vm/pmap.h>
101#include <vm/vm_kern.h>
102#include <machine/io_map_entries.h>
103#include <machine/machine_cpu.h>
104
105#include <pexpert/pexpert.h>
106#include <sys/kdebug.h>
107
108#include "iso_font.c"
109#if !CONFIG_EMBEDDED
110#include "progress_meter_data.c"
111#endif
112
113#include "sys/msgbuf.h"
114
115/*
116 * Generic Console (Front-End)
117 * ---------------------------
118 */
119
120struct vc_info vinfo;
121
122void noroot_icon_test(void);
123
124
125extern int disableConsoleOutput;
126static boolean_t gc_enabled = FALSE;
127static boolean_t gc_initialized = FALSE;
128static boolean_t vm_initialized = FALSE;
129
130static struct {
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,
135 int attrs_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);
143} gc_ops;
144
145static unsigned char *gc_buffer_attributes;
146static unsigned char *gc_buffer_characters;
147static unsigned char *gc_buffer_colorcodes;
148static unsigned char *gc_buffer_tab_stops;
149static uint32_t gc_buffer_columns;
150static uint32_t gc_buffer_rows;
151static uint32_t gc_buffer_size;
152
153#if defined(__i386__) || defined(__x86_64__)
154decl_simple_lock_data(static, vcputc_lock);
155
156#define VCPUTC_LOCK_INIT() \
157MACRO_BEGIN \
158 simple_lock_init(&vcputc_lock, 0); \
159MACRO_END
160
161#define VCPUTC_LOCK_LOCK() \
162MACRO_BEGIN \
163 boolean_t istate = ml_get_interrupts_enabled(); \
164 while (!simple_lock_try(&vcputc_lock)) \
165 { \
166 if (!istate) \
167 handle_pending_TLB_flushes(); \
168 cpu_pause(); \
169 } \
170MACRO_END
171
172#define VCPUTC_LOCK_UNLOCK() \
173MACRO_BEGIN \
174 simple_unlock(&vcputc_lock); \
175MACRO_END
176#else
177static hw_lock_data_t vcputc_lock;
178
179#define VCPUTC_LOCK_INIT() \
180MACRO_BEGIN \
181 hw_lock_init(&vcputc_lock); \
182MACRO_END
183
184#define VCPUTC_LOCK_LOCK() \
185MACRO_BEGIN \
186 if (!hw_lock_to(&vcputc_lock, ~0U))\
187 { \
188 panic("VCPUTC_LOCK_LOCK"); \
189 } \
190MACRO_END
191
192#define VCPUTC_LOCK_UNLOCK() \
193MACRO_BEGIN \
194 hw_lock_unlock(&vcputc_lock); \
195MACRO_END
196#endif
197
198/*
199# Attribute codes:
200# 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed
201# Text color codes:
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
205*/
206
207#define ATTR_NONE 0
208#define ATTR_BOLD 1
209#define ATTR_UNDER 2
210#define ATTR_REVERSE 4
211
212#define COLOR_BACKGROUND 0
213#define COLOR_FOREGROUND 7
214
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)))
217
218static unsigned char gc_color_code;
219
220/* VT100 state: */
221#define MAXPARS 16
222static unsigned int gc_x, gc_y, gc_savex, gc_savey;
223static unsigned int gc_par[MAXPARS], gc_numpars, gc_hanging_cursor, gc_attr, gc_saveattr;
224
225/* VT100 scroll region */
226static unsigned int gc_scrreg_top, gc_scrreg_bottom;
227
228enum vt100state_e {
229 ESnormal, /* Nothing yet */
230 ESesc, /* Got ESC */
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 */
238 ESask,
239 EScharsize,
240 ESignore /* Ignore this sequence */
241} gc_vt100state = ESnormal;
242
243
244enum
245{
246 /* secs */
247 kProgressAcquireDelay = 0,
248#if CONFIG_EMBEDDED
249 kProgressReacquireDelay = 5,
250#else
251 kProgressReacquireDelay = 5,
252#endif
253};
254
255static int8_t vc_rotate_matr[4][2][2] = {
256 { { 1, 0 },
257 { 0, 1 } },
258 { { 0, 1 },
259 { -1, 0 } },
260 { { -1, 0 },
261 { 0, -1 } },
262 { { 0, -1 },
263 { 1, 0 } }
264};
265
266static int gc_wrap_mode = 1, gc_relative_origin = 0;
267static int gc_charset_select = 0, gc_save_charset_s = 0;
268static int gc_charset[2] = { 0, 0 };
269static int gc_charset_save[2] = { 0, 0 };
270
271static void gc_clear_line(unsigned int xx, unsigned int yy, int which);
272static void gc_clear_screen(unsigned int xx, unsigned int yy, int top,
273 unsigned int bottom, int which);
274static void gc_enable(boolean_t enable);
275static void gc_hide_cursor(unsigned int xx, unsigned int yy);
276static void gc_initialize(struct vc_info * info);
277static boolean_t gc_is_tab_stop(unsigned int column);
278static void gc_paint_char(unsigned int xx, unsigned int yy, unsigned char ch,
279 int attrs);
280static void gc_putchar(char ch);
281static void gc_putc_askcmd(unsigned char ch);
282static void gc_putc_charsetcmd(int charset, unsigned char ch);
283static void gc_putc_charsizecmd(unsigned char ch);
284static void gc_putc_esc(unsigned char ch);
285static void gc_putc_getpars(unsigned char ch);
286static void gc_putc_gotpars(unsigned char ch);
287static void gc_putc_normal(unsigned char ch);
288static void gc_putc_square(unsigned char ch);
289static void gc_reset_screen(void);
290static void gc_reset_tabs(void);
291static void gc_reset_vt100(void);
292static void gc_scroll_down(int num, unsigned int top, unsigned int bottom);
293static void gc_scroll_up(int num, unsigned int top, unsigned int bottom);
294static void gc_set_tab_stop(unsigned int column, boolean_t enabled);
295static void gc_show_cursor(unsigned int xx, unsigned int yy);
296static void gc_update_color(int color, boolean_t fore);
297
298static void
299gc_clear_line(unsigned int xx, unsigned int yy, int which)
300{
301 unsigned int start, end, i;
302
303 /*
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
307 * module. --LK
308 */
309
310 switch (which) {
311 case 0: /* To end of line */
312 start = xx;
313 end = vinfo.v_columns-1;
314 break;
315 case 1: /* To start of line */
316 start = 0;
317 end = xx;
318 break;
319 case 2: /* Whole line */
320 start = 0;
321 end = vinfo.v_columns-1;
322 break;
323 default:
324 return;
325 }
326
327 for (i = start; i <= end; i++) {
328 gc_paint_char(i, yy, ' ', ATTR_NONE);
329 }
330}
331
332static void
333gc_clear_screen(unsigned int xx, unsigned int yy, int top, unsigned int bottom,
334 int which)
335{
336 if (!gc_buffer_size) return;
337
338 if ( xx < gc_buffer_columns && yy < gc_buffer_rows && bottom <= gc_buffer_rows )
339 {
340 uint32_t start, end;
341
342 switch (which) {
343 case 0: /* To end of screen */
344 start = (yy * gc_buffer_columns) + xx;
345 end = (bottom * gc_buffer_columns) - 1;
346 break;
347 case 1: /* To start of screen */
348 start = (top * gc_buffer_columns);
349 end = (yy * gc_buffer_columns) + xx;
350 break;
351 case 2: /* Whole screen */
352 start = (top * gc_buffer_columns);
353 end = (bottom * gc_buffer_columns) - 1;
354 break;
355 default:
356 start = 0;
357 end = 0;
358 break;
359 }
360
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);
364 }
365
366 gc_ops.clear_screen(xx, yy, top, bottom, which);
367}
368
369static void
370gc_enable( boolean_t enable )
371{
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;
379 spl_t s;
380
381 if ( enable == FALSE )
382 {
383 // only disable console output if it goes to the graphics console
384 if ( console_is_serial() == FALSE )
385 disableConsoleOutput = TRUE;
386 gc_enabled = FALSE;
387 gc_ops.enable(FALSE);
388 }
389
390 s = splhigh( );
391 VCPUTC_LOCK_LOCK( );
392
393 if ( gc_buffer_size )
394 {
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;
402
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;
408 gc_buffer_rows = 0;
409 gc_buffer_size = 0;
410
411 VCPUTC_LOCK_UNLOCK( );
412 splx( s );
413
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 );
418 }
419 else
420 {
421 VCPUTC_LOCK_UNLOCK( );
422 splx( s );
423 }
424
425 if ( enable )
426 {
427 if ( vm_initialized )
428 {
429 buffer_columns = vinfo.v_columns;
430 buffer_rows = vinfo.v_rows;
431 buffer_size = buffer_columns * buffer_rows;
432
433 if ( buffer_size )
434 {
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 );
439
440 if ( buffer_attributes == NULL ||
441 buffer_characters == NULL ||
442 buffer_colorcodes == NULL ||
443 buffer_tab_stops == NULL )
444 {
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 );
449
450 buffer_attributes = NULL;
451 buffer_characters = NULL;
452 buffer_colorcodes = NULL;
453 buffer_tab_stops = NULL;
454 buffer_columns = 0;
455 buffer_rows = 0;
456 buffer_size = 0;
457 }
458 else
459 {
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 );
464 }
465 }
466 }
467
468 s = splhigh( );
469 VCPUTC_LOCK_LOCK( );
470
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;
478
479 gc_reset_screen();
480
481 VCPUTC_LOCK_UNLOCK( );
482 splx( s );
483
484 gc_ops.clear_screen(gc_x, gc_y, 0, vinfo.v_rows, 2);
485 gc_ops.show_cursor(gc_x, gc_y);
486
487 gc_ops.enable(TRUE);
488 gc_enabled = TRUE;
489 disableConsoleOutput = FALSE;
490 }
491}
492
493static void
494gc_hide_cursor(unsigned int xx, unsigned int yy)
495{
496 if ( xx < gc_buffer_columns && yy < gc_buffer_rows )
497 {
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;
503
504 gc_update_color(COLOR_CODE_GET(colorcode, TRUE ), TRUE );
505 gc_update_color(COLOR_CODE_GET(colorcode, FALSE), FALSE);
506
507 gc_ops.paint_char(xx, yy, character, attribute, 0, 0);
508
509 gc_update_color(COLOR_CODE_GET(colorcodesave, TRUE ), TRUE );
510 gc_update_color(COLOR_CODE_GET(colorcodesave, FALSE), FALSE);
511 }
512 else
513 {
514 gc_ops.hide_cursor(xx, yy);
515 }
516}
517
518static void
519gc_initialize(struct vc_info * info)
520{
521 if ( gc_initialized == FALSE )
522 {
523 /* Init our lock */
524 VCPUTC_LOCK_INIT();
525
526 gc_initialized = TRUE;
527 }
528
529 gc_ops.initialize(info);
530
531 gc_reset_vt100();
532 gc_x = gc_y = 0;
533}
534
535static void
536gc_paint_char(unsigned int xx, unsigned int yy, unsigned char ch, int attrs)
537{
538 if ( xx < gc_buffer_columns && yy < gc_buffer_rows )
539 {
540 uint32_t index = (yy * gc_buffer_columns) + xx;
541
542 gc_buffer_attributes[index] = attrs;
543 gc_buffer_characters[index] = ch;
544 gc_buffer_colorcodes[index] = gc_color_code;
545 }
546
547 gc_ops.paint_char(xx, yy, ch, attrs, 0, 0);
548}
549
550static void
551gc_putchar(char ch)
552{
553 if (!ch) {
554 return; /* ignore null characters */
555 }
556 switch (gc_vt100state) {
557 default:gc_vt100state = ESnormal; /* FALLTHROUGH */
558 case ESnormal:
559 gc_putc_normal(ch);
560 break;
561 case ESesc:
562 gc_putc_esc(ch);
563 break;
564 case ESsquare:
565 gc_putc_square(ch);
566 break;
567 case ESgetpars:
568 gc_putc_getpars(ch);
569 break;
570 case ESgotpars:
571 gc_putc_gotpars(ch);
572 break;
573 case ESask:
574 gc_putc_askcmd(ch);
575 break;
576 case EScharsize:
577 gc_putc_charsizecmd(ch);
578 break;
579 case ESsetG0:
580 gc_putc_charsetcmd(0, ch);
581 break;
582 case ESsetG1:
583 gc_putc_charsetcmd(1, ch);
584 break;
585 }
586
587 if (gc_x >= vinfo.v_columns) {
588 if (0 == vinfo.v_columns)
589 gc_x = 0;
590 else
591 gc_x = vinfo.v_columns - 1;
592 }
593 if (gc_y >= vinfo.v_rows) {
594 if (0 == vinfo.v_rows)
595 gc_y = 0;
596 else
597 gc_y = vinfo.v_rows - 1;
598 }
599}
600
601static void
602gc_putc_askcmd(unsigned char ch)
603{
604 if (ch >= '0' && ch <= '9') {
605 gc_par[gc_numpars] = (10*gc_par[gc_numpars]) + (ch-'0');
606 return;
607 }
608 gc_vt100state = ESnormal;
609
610 switch (gc_par[0]) {
611 case 6:
612 gc_relative_origin = ch == 'h';
613 break;
614 case 7: /* wrap around mode h=1, l=0*/
615 gc_wrap_mode = ch == 'h';
616 break;
617 default:
618 break;
619 }
620
621}
622
623static void
624gc_putc_charsetcmd(int charset, unsigned char ch)
625{
626 gc_vt100state = ESnormal;
627
628 switch (ch) {
629 case 'A' :
630 case 'B' :
631 default:
632 gc_charset[charset] = 0;
633 break;
634 case '0' : /* Graphic characters */
635 case '2' :
636 gc_charset[charset] = 0x21;
637 break;
638 }
639
640}
641
642static void
643gc_putc_charsizecmd(unsigned char ch)
644{
645 gc_vt100state = ESnormal;
646
647 switch (ch) {
648 case '3' :
649 case '4' :
650 case '5' :
651 case '6' :
652 break;
653 case '8' : /* fill 'E's */
654 {
655 unsigned int xx, yy;
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);
659 }
660 break;
661 }
662
663}
664
665static void
666gc_putc_esc(unsigned char ch)
667{
668 gc_vt100state = ESnormal;
669
670 switch (ch) {
671 case '[':
672 gc_vt100state = ESsquare;
673 break;
674 case 'c': /* Reset terminal */
675 gc_reset_vt100();
676 gc_clear_screen(gc_x, gc_y, 0, vinfo.v_rows, 2);
677 gc_x = gc_y = 0;
678 break;
679 case 'D': /* Line feed */
680 case 'E':
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;
684 } else {
685 gc_y++;
686 }
687 if (ch == 'E') gc_x = 0;
688 break;
689 case 'H': /* Set tab stop */
690 gc_set_tab_stop(gc_x, TRUE);
691 break;
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;
696 } else {
697 gc_y--;
698 }
699 break;
700 case '>':
701 gc_reset_vt100();
702 break;
703 case '7': /* Save cursor */
704 gc_savex = gc_x;
705 gc_savey = gc_y;
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];
710 break;
711 case '8': /* Restore cursor */
712 gc_x = gc_savex;
713 gc_y = gc_savey;
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];
718 break;
719 case 'Z': /* return terminal ID */
720 break;
721 case '#': /* change characters height */
722 gc_vt100state = EScharsize;
723 break;
724 case '(':
725 gc_vt100state = ESsetG0;
726 break;
727 case ')': /* character set sequence */
728 gc_vt100state = ESsetG1;
729 break;
730 case '=':
731 break;
732 default:
733 /* Rest not supported */
734 break;
735 }
736
737}
738
739static void
740gc_putc_getpars(unsigned char ch)
741{
742 if (ch == '?') {
743 gc_vt100state = ESask;
744 return;
745 }
746 if (ch == '[') {
747 gc_vt100state = ESnormal;
748 /* Not supported */
749 return;
750 }
751 if (ch == ';' && gc_numpars < MAXPARS - 1) {
752 gc_numpars++;
753 } else
754 if (ch >= '0' && ch <= '9') {
755 gc_par[gc_numpars] *= 10;
756 gc_par[gc_numpars] += ch - '0';
757 } else {
758 gc_numpars++;
759 gc_vt100state = ESgotpars;
760 gc_putc_gotpars(ch);
761 }
762}
763
764static void
765gc_putc_gotpars(unsigned char ch)
766{
767 unsigned int i;
768
769 if (ch < ' ') {
770 /* special case for vttest for handling cursor
771 movement in escape sequences */
772 gc_putc_normal(ch);
773 gc_vt100state = ESgotpars;
774 return;
775 }
776 gc_vt100state = ESnormal;
777 switch (ch) {
778 case 'A': /* Up */
779 gc_y -= gc_par[0] ? gc_par[0] : 1;
780 if (gc_y < gc_scrreg_top)
781 gc_y = gc_scrreg_top;
782 break;
783 case 'B': /* Down */
784 gc_y += gc_par[0] ? gc_par[0] : 1;
785 if (gc_y >= gc_scrreg_bottom)
786 gc_y = gc_scrreg_bottom - 1;
787 break;
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;
792 break;
793 case 'D': /* Left */
794 if (gc_par[0] > gc_x)
795 gc_x = 0;
796 else if (gc_par[0])
797 gc_x -= gc_par[0];
798 else if (gc_x)
799 --gc_x;
800 break;
801 case 'H': /* Set cursor position */
802 case 'f':
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;
808 break;
809 case 'X': /* clear p1 characters */
810 if (gc_numpars) {
811 for (i = gc_x; i < gc_x + gc_par[0]; i++)
812 gc_paint_char(i, gc_y, ' ', ATTR_NONE);
813 }
814 break;
815 case 'J': /* Clear part of screen */
816 gc_clear_screen(gc_x, gc_y, 0, vinfo.v_rows, gc_par[0]);
817 break;
818 case 'K': /* Clear part of line */
819 gc_clear_line(gc_x, gc_y, gc_par[0]);
820 break;
821 case 'g': /* tab stops */
822 switch (gc_par[0]) {
823 case 1:
824 case 2: /* reset tab stops */
825 /* gc_reset_tabs(); */
826 break;
827 case 3: /* Clear every tabs */
828 {
829 for (i = 0; i <= vinfo.v_columns; i++)
830 gc_set_tab_stop(i, FALSE);
831 }
832 break;
833 case 0:
834 gc_set_tab_stop(gc_x, FALSE);
835 break;
836 }
837 break;
838 case 'm': /* Set attribute */
839 for (i = 0; i < gc_numpars; i++) {
840 switch (gc_par[i]) {
841 case 0:
842 gc_attr = ATTR_NONE;
843 gc_update_color(COLOR_BACKGROUND, FALSE);
844 gc_update_color(COLOR_FOREGROUND, TRUE );
845 break;
846 case 1:
847 gc_attr |= ATTR_BOLD;
848 break;
849 case 4:
850 gc_attr |= ATTR_UNDER;
851 break;
852 case 7:
853 gc_attr |= ATTR_REVERSE;
854 break;
855 case 22:
856 gc_attr &= ~ATTR_BOLD;
857 break;
858 case 24:
859 gc_attr &= ~ATTR_UNDER;
860 break;
861 case 27:
862 gc_attr &= ~ATTR_REVERSE;
863 break;
864 case 5:
865 case 25: /* blink/no blink */
866 break;
867 default:
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);
872 break;
873 }
874 }
875 break;
876 case 'r': /* Set scroll region */
877 gc_x = gc_y = 0;
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;
881 } else {
882 gc_scrreg_top = 0;
883 }
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;
888 } else {
889 gc_scrreg_bottom = vinfo.v_rows;
890 }
891 if (gc_relative_origin)
892 gc_y = gc_scrreg_top;
893 break;
894 }
895
896}
897
898static void
899gc_putc_normal(unsigned char ch)
900{
901 switch (ch) {
902 case '\a': /* Beep */
903 break;
904 case 127: /* Delete */
905 case '\b': /* Backspace */
906 if (gc_hanging_cursor) {
907 gc_hanging_cursor = 0;
908 } else
909 if (gc_x > 0) {
910 gc_x--;
911 }
912 break;
913 case '\t': /* Tab */
914 if (gc_buffer_tab_stops) while (gc_x < vinfo.v_columns && !gc_is_tab_stop(++gc_x));
915
916 if (gc_x >= vinfo.v_columns)
917 gc_x = vinfo.v_columns-1;
918 break;
919 case 0x0b:
920 case 0x0c:
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;
925 } else {
926 gc_y++;
927 }
928 break;
929 case '\r': /* Carriage return */
930 gc_x = 0;
931 gc_hanging_cursor = 0;
932 break;
933 case 0x0e: /* Select G1 charset (Control-N) */
934 gc_charset_select = 1;
935 break;
936 case 0x0f: /* Select G0 charset (Control-O) */
937 gc_charset_select = 0;
938 break;
939 case 0x18 : /* CAN : cancel */
940 case 0x1A : /* like cancel */
941 /* well, i do nothing here, may be later */
942 break;
943 case '\033': /* Escape */
944 gc_vt100state = ESesc;
945 gc_hanging_cursor = 0;
946 break;
947 default:
948 if (ch >= ' ') {
949 if (gc_hanging_cursor) {
950 gc_x = 0;
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;
954 } else {
955 gc_y++;
956 }
957 gc_hanging_cursor = 0;
958 }
959 gc_paint_char(gc_x, gc_y, (ch >= 0x60 && ch <= 0x7f) ? ch + gc_charset[gc_charset_select]
960 : ch, gc_attr);
961 if (gc_x == vinfo.v_columns - 1) {
962 gc_hanging_cursor = gc_wrap_mode;
963 } else {
964 gc_x++;
965 }
966 }
967 break;
968 }
969
970}
971
972static void
973gc_putc_square(unsigned char ch)
974{
975 int i;
976
977 for (i = 0; i < MAXPARS; i++) {
978 gc_par[i] = 0;
979 }
980
981 gc_numpars = 0;
982 gc_vt100state = ESgetpars;
983
984 gc_putc_getpars(ch);
985
986}
987
988static void
989gc_reset_screen(void)
990{
991 gc_reset_vt100();
992 gc_x = gc_y = 0;
993}
994
995static void
996gc_reset_tabs(void)
997{
998 unsigned int i;
999
1000 if (!gc_buffer_tab_stops) return;
1001
1002 for (i = 0; i < vinfo.v_columns; i++) {
1003 gc_buffer_tab_stops[i] = ((i % 8) == 0);
1004 }
1005
1006}
1007
1008static void
1009gc_set_tab_stop(unsigned int column, boolean_t enabled)
1010{
1011 if (gc_buffer_tab_stops && (column < vinfo.v_columns)) {
1012 gc_buffer_tab_stops[column] = enabled;
1013 }
1014}
1015
1016static boolean_t gc_is_tab_stop(unsigned int column)
1017{
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];
1022 else
1023 return FALSE;
1024}
1025
1026static void
1027gc_reset_vt100(void)
1028{
1029 gc_reset_tabs();
1030 gc_scrreg_top = 0;
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;
1035 gc_wrap_mode = 1;
1036 gc_relative_origin = 0;
1037 gc_update_color(COLOR_BACKGROUND, FALSE);
1038 gc_update_color(COLOR_FOREGROUND, TRUE);
1039}
1040
1041static void
1042gc_scroll_down(int num, unsigned int top, unsigned int bottom)
1043{
1044 if (!gc_buffer_size) return;
1045
1046 if ( bottom <= gc_buffer_rows )
1047 {
1048 unsigned char colorcodesave = gc_color_code;
1049 uint32_t column, row;
1050 uint32_t index, jump;
1051
1052 jump = num * gc_buffer_columns;
1053
1054 for ( row = bottom - 1 ; row >= top + num ; row-- )
1055 {
1056 index = row * gc_buffer_columns;
1057
1058 for ( column = 0 ; column < gc_buffer_columns ; index++, column++ )
1059 {
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] )
1063 {
1064 if ( gc_color_code != gc_buffer_colorcodes[index - jump] )
1065 {
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);
1068 }
1069
1070 if ( gc_buffer_colorcodes[index] != gc_buffer_colorcodes[index - jump] )
1071 {
1072 gc_ops.paint_char( /* xx */ column,
1073 /* yy */ row,
1074 /* ch */ gc_buffer_characters[index - jump],
1075 /* attrs */ gc_buffer_attributes[index - jump],
1076 /* ch_previous */ 0,
1077 /* attrs_previous */ 0 );
1078 }
1079 else
1080 {
1081 gc_ops.paint_char( /* xx */ column,
1082 /* yy */ row,
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] );
1087 }
1088
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];
1092 }
1093 }
1094 }
1095
1096 if ( colorcodesave != gc_color_code )
1097 {
1098 gc_update_color(COLOR_CODE_GET(colorcodesave, TRUE ), TRUE );
1099 gc_update_color(COLOR_CODE_GET(colorcodesave, FALSE), FALSE);
1100 }
1101
1102 /* Now set the freed up lines to the background colour */
1103
1104 for ( row = top ; row < top + num ; row++ )
1105 {
1106 index = row * gc_buffer_columns;
1107
1108 for ( column = 0 ; column < gc_buffer_columns ; index++, column++ )
1109 {
1110 if ( gc_buffer_attributes[index] != ATTR_NONE ||
1111 gc_buffer_characters[index] != ' ' ||
1112 gc_buffer_colorcodes[index] != gc_color_code )
1113 {
1114 if ( gc_buffer_colorcodes[index] != gc_color_code )
1115 {
1116 gc_ops.paint_char( /* xx */ column,
1117 /* yy */ row,
1118 /* ch */ ' ',
1119 /* attrs */ ATTR_NONE,
1120 /* ch_previous */ 0,
1121 /* attrs_previous */ 0 );
1122 }
1123 else
1124 {
1125 gc_ops.paint_char( /* xx */ column,
1126 /* yy */ row,
1127 /* ch */ ' ',
1128 /* attrs */ ATTR_NONE,
1129 /* ch_previous */ gc_buffer_characters[index],
1130 /* attrs_previous */ gc_buffer_attributes[index] );
1131 }
1132
1133 gc_buffer_attributes[index] = ATTR_NONE;
1134 gc_buffer_characters[index] = ' ';
1135 gc_buffer_colorcodes[index] = gc_color_code;
1136 }
1137 }
1138 }
1139 }
1140 else
1141 {
1142 gc_ops.scroll_down(num, top, bottom);
1143
1144 /* Now set the freed up lines to the background colour */
1145
1146 gc_clear_screen(vinfo.v_columns - 1, top + num - 1, top, bottom, 1);
1147 }
1148}
1149
1150static void
1151gc_scroll_up(int num, unsigned int top, unsigned int bottom)
1152{
1153 if (!gc_buffer_size) return;
1154
1155 if ( bottom <= gc_buffer_rows )
1156 {
1157 unsigned char colorcodesave = gc_color_code;
1158 uint32_t column, row;
1159 uint32_t index, jump;
1160
1161 jump = num * gc_buffer_columns;
1162
1163 for ( row = top ; row < bottom - num ; row++ )
1164 {
1165 index = row * gc_buffer_columns;
1166
1167 for ( column = 0 ; column < gc_buffer_columns ; index++, column++ )
1168 {
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] )
1172 {
1173 if ( gc_color_code != gc_buffer_colorcodes[index + jump] )
1174 {
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);
1177 }
1178
1179 if ( gc_buffer_colorcodes[index] != gc_buffer_colorcodes[index + jump] )
1180 {
1181 gc_ops.paint_char( /* xx */ column,
1182 /* yy */ row,
1183 /* ch */ gc_buffer_characters[index + jump],
1184 /* attrs */ gc_buffer_attributes[index + jump],
1185 /* ch_previous */ 0,
1186 /* attrs_previous */ 0 );
1187 }
1188 else
1189 {
1190 gc_ops.paint_char( /* xx */ column,
1191 /* yy */ row,
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] );
1196 }
1197
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];
1201 }
1202 }
1203 }
1204
1205 if ( colorcodesave != gc_color_code )
1206 {
1207 gc_update_color(COLOR_CODE_GET(colorcodesave, TRUE ), TRUE );
1208 gc_update_color(COLOR_CODE_GET(colorcodesave, FALSE), FALSE);
1209 }
1210
1211 /* Now set the freed up lines to the background colour */
1212
1213 for ( row = bottom - num ; row < bottom ; row++ )
1214 {
1215 index = row * gc_buffer_columns;
1216
1217 for ( column = 0 ; column < gc_buffer_columns ; index++, column++ )
1218 {
1219 if ( gc_buffer_attributes[index] != ATTR_NONE ||
1220 gc_buffer_characters[index] != ' ' ||
1221 gc_buffer_colorcodes[index] != gc_color_code )
1222 {
1223 if ( gc_buffer_colorcodes[index] != gc_color_code )
1224 {
1225 gc_ops.paint_char( /* xx */ column,
1226 /* yy */ row,
1227 /* ch */ ' ',
1228 /* attrs */ ATTR_NONE,
1229 /* ch_previous */ 0,
1230 /* attrs_previous */ 0 );
1231 }
1232 else
1233 {
1234 gc_ops.paint_char( /* xx */ column,
1235 /* yy */ row,
1236 /* ch */ ' ',
1237 /* attrs */ ATTR_NONE,
1238 /* ch_previous */ gc_buffer_characters[index],
1239 /* attrs_previous */ gc_buffer_attributes[index] );
1240 }
1241
1242 gc_buffer_attributes[index] = ATTR_NONE;
1243 gc_buffer_characters[index] = ' ';
1244 gc_buffer_colorcodes[index] = gc_color_code;
1245 }
1246 }
1247 }
1248 }
1249 else
1250 {
1251 gc_ops.scroll_up(num, top, bottom);
1252
1253 /* Now set the freed up lines to the background colour */
1254
1255 gc_clear_screen(0, bottom - num, top, bottom, 0);
1256 }
1257}
1258
1259static void
1260gc_show_cursor(unsigned int xx, unsigned int yy)
1261{
1262 if ( xx < gc_buffer_columns && yy < gc_buffer_rows )
1263 {
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;
1269
1270 gc_update_color(COLOR_CODE_GET(colorcode, FALSE), TRUE );
1271 gc_update_color(COLOR_CODE_GET(colorcode, TRUE ), FALSE);
1272
1273 gc_ops.paint_char(xx, yy, character, attribute, 0, 0);
1274
1275 gc_update_color(COLOR_CODE_GET(colorcodesave, TRUE ), TRUE );
1276 gc_update_color(COLOR_CODE_GET(colorcodesave, FALSE), FALSE);
1277 }
1278 else
1279 {
1280 gc_ops.show_cursor(xx, yy);
1281 }
1282}
1283
1284static void
1285gc_update_color(int color, boolean_t fore)
1286{
1287 assert(gc_ops.update_color);
1288
1289 gc_color_code = COLOR_CODE_SET(gc_color_code, color, fore);
1290 gc_ops.update_color(color, fore);
1291}
1292
1293void
1294vcputc(__unused int l, __unused int u, int c)
1295{
1296 if ( gc_initialized && gc_enabled )
1297 {
1298 spl_t s;
1299
1300 s = splhigh();
1301#if defined(__i386__) || defined(__x86_64__)
1302 x86_filter_TLB_coherency_interrupts(TRUE);
1303#endif
1304 VCPUTC_LOCK_LOCK();
1305 if ( gc_enabled )
1306 {
1307 gc_hide_cursor(gc_x, gc_y);
1308 gc_putchar(c);
1309 gc_show_cursor(gc_x, gc_y);
1310 }
1311 VCPUTC_LOCK_UNLOCK();
1312#if defined(__i386__) || defined(__x86_64__)
1313 x86_filter_TLB_coherency_interrupts(FALSE);
1314#endif
1315 splx(s);
1316 }
1317}
1318
1319/*
1320 * Video Console (Back-End)
1321 * ------------------------
1322 */
1323
1324/*
1325 * For the color support (Michel Pollet)
1326 */
1327static 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 };
1330
1331static 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 */
1341};
1342
1343static uint32_t vc_color_fore = 0;
1344static uint32_t vc_color_back = 0;
1345
1346/*
1347 * New Rendering code from Michel Pollet
1348 */
1349
1350/* Rendered Font Buffer */
1351static unsigned char *vc_rendered_font = NULL;
1352
1353/* Rendered Font Size */
1354static uint32_t vc_rendered_font_size = 0;
1355
1356/* Size of a character in the table (bytes) */
1357static int vc_rendered_char_size = 0;
1358
1359#define REN_MAX_DEPTH 32
1360static unsigned char vc_rendered_char[ISO_CHAR_HEIGHT * ((REN_MAX_DEPTH / 8) * ISO_CHAR_WIDTH)];
1361
1362#if !CONFIG_EMBEDDED
1363static void
1364internal_set_progressmeter(int new_value);
1365static void
1366internal_enable_progressmeter(int new_value);
1367
1368enum
1369{
1370 kProgressMeterOff = FALSE,
1371 kProgressMeterUser = TRUE,
1372 kProgressMeterKernel = 3,
1373};
1374enum
1375{
1376 kProgressMeterMax = 1024,
1377 kProgressMeterEnd = 512,
1378};
1379
1380#endif /* !CONFIG_EMBEDDED */
1381
1382static boolean_t vc_progress_white =
1383#ifdef CONFIG_VC_PROGRESS_WHITE
1384 TRUE;
1385#else /* !CONFIG_VC_PROGRESS_WHITE */
1386 FALSE;
1387#endif /* !CONFIG_VC_PROGRESS_WHITE */
1388
1389static int vc_acquire_delay = kProgressAcquireDelay;
1390
1391static void
1392vc_clear_screen(unsigned int xx, unsigned int yy, unsigned int scrreg_top,
1393 unsigned int scrreg_bottom, int which)
1394{
1395 uint32_t *p, *endp, *row;
1396 int linelongs, col;
1397 int rowline, rowlongs;
1398
1399 if(!vinfo.v_depth)
1400 return;
1401
1402 linelongs = vinfo.v_rowbytes * (ISO_CHAR_HEIGHT >> 2);
1403 rowline = vinfo.v_rowscanbytes >> 2;
1404 rowlongs = vinfo.v_rowbytes >> 2;
1405
1406 p = (uint32_t*) vinfo.v_baseaddr;
1407 endp = (uint32_t*) vinfo.v_baseaddr;
1408
1409 switch (which) {
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;
1415 }
1416 break;
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;
1422 }
1423 break;
1424 case 2: /* Whole screen */
1425 p += scrreg_top * linelongs;
1426 if (scrreg_bottom == vinfo.v_rows) {
1427 endp += rowlongs * vinfo.v_height;
1428 } else {
1429 endp += scrreg_bottom * linelongs;
1430 }
1431 break;
1432 }
1433
1434 for (row = p ; row < endp ; row += rowlongs) {
1435 for (col = 0; col < rowline; col++)
1436 *(row+col) = vc_color_back;
1437 }
1438}
1439
1440static void
1441vc_render_char(unsigned char ch, unsigned char *renderptr, short newdepth)
1442{
1443 union {
1444 unsigned char *charptr;
1445 unsigned short *shortptr;
1446 uint32_t *longptr;
1447 } current; /* current place in rendered font, multiple types. */
1448 unsigned char *theChar; /* current char in iso_font */
1449 int line;
1450
1451 current.charptr = renderptr;
1452 theChar = iso_font + (ch * ISO_CHAR_HEIGHT);
1453
1454 for (line = 0; line < ISO_CHAR_HEIGHT; line++) {
1455 unsigned char mask = 1;
1456 do {
1457 switch (newdepth) {
1458 case 8:
1459 *current.charptr++ = (*theChar & mask) ? 0xFF : 0;
1460 break;
1461 case 16:
1462 *current.shortptr++ = (*theChar & mask) ? 0xFFFF : 0;
1463 break;
1464
1465 case 30:
1466 case 32:
1467 *current.longptr++ = (*theChar & mask) ? 0xFFFFFFFF : 0;
1468 break;
1469 }
1470 mask <<= 1;
1471 } while (mask); /* while the single bit drops to the right */
1472 theChar++;
1473 }
1474}
1475
1476static void
1477vc_paint_char_8(unsigned int xx, unsigned int yy, unsigned char ch, int attrs,
1478 __unused unsigned char ch_previous, __unused int attrs_previous)
1479{
1480 uint32_t *theChar;
1481 uint32_t *where;
1482 int i;
1483
1484 if (vc_rendered_font) {
1485 theChar = (uint32_t*)(vc_rendered_font + (ch * vc_rendered_char_size));
1486 } else {
1487 vc_render_char(ch, vc_rendered_char, 8);
1488 theChar = (uint32_t*)(vc_rendered_char);
1489 }
1490 where = (uint32_t*)(vinfo.v_baseaddr +
1491 (yy * ISO_CHAR_HEIGHT * vinfo.v_rowbytes) +
1492 (xx * ISO_CHAR_WIDTH));
1493
1494 if (!attrs) for (i = 0; i < ISO_CHAR_HEIGHT; i++) { /* No attr? FLY !*/
1495 uint32_t *store = where;
1496 int x;
1497 for (x = 0; x < 2; x++) {
1498 uint32_t val = *theChar++;
1499 val = (vc_color_back & ~val) | (vc_color_fore & val);
1500 *store++ = val;
1501 }
1502
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;
1506 int x;
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))
1511 val |= 0xff000000;
1512 if ((save & 0xFFFF0000) == 0xFF000000)
1513 val |= 0x00FF0000;
1514 if ((save & 0x00FFFF00) == 0x00FF0000)
1515 val |= 0x0000FF00;
1516 if ((save & 0x0000FFFF) == 0x0000FF00)
1517 val |= 0x000000FF;
1518 }
1519 if (attrs & ATTR_REVERSE) val = ~val;
1520 if (attrs & ATTR_UNDER && i == ISO_CHAR_HEIGHT-1) val = ~val;
1521
1522 val = (vc_color_back & ~val) | (vc_color_fore & val);
1523 *store++ = val;
1524 lastpixel = save & 0xff;
1525 }
1526
1527 where = (uint32_t*)(((unsigned char*)where)+vinfo.v_rowbytes);
1528 }
1529
1530}
1531
1532static void
1533vc_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)
1536{
1537 uint32_t *theChar;
1538 uint32_t *where;
1539 int i;
1540
1541 if (vc_rendered_font) {
1542 theChar = (uint32_t*)(vc_rendered_font + (ch * vc_rendered_char_size));
1543 } else {
1544 vc_render_char(ch, vc_rendered_char, 16);
1545 theChar = (uint32_t*)(vc_rendered_char);
1546 }
1547 where = (uint32_t*)(vinfo.v_baseaddr +
1548 (yy * ISO_CHAR_HEIGHT * vinfo.v_rowbytes) +
1549 (xx * ISO_CHAR_WIDTH * 2));
1550
1551 if (!attrs) for (i = 0; i < ISO_CHAR_HEIGHT; i++) { /* No attrs ? FLY ! */
1552 uint32_t *store = where;
1553 int x;
1554 for (x = 0; x < 4; x++) {
1555 uint32_t val = *theChar++;
1556 val = (vc_color_back & ~val) | (vc_color_fore & val);
1557 *store++ = val;
1558 }
1559
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;
1563 int x;
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))
1569 val |= 0xFFFF0000;
1570 }
1571 if (attrs & ATTR_REVERSE) val = ~val;
1572 if (attrs & ATTR_UNDER && i == ISO_CHAR_HEIGHT-1) val = ~val;
1573
1574 val = (vc_color_back & ~val) | (vc_color_fore & val);
1575
1576 *store++ = val;
1577 lastpixel = save & 0x7fff;
1578 }
1579
1580 where = (uint32_t*)(((unsigned char*)where)+vinfo.v_rowbytes);
1581 }
1582
1583}
1584
1585static void
1586vc_paint_char_32(unsigned int xx, unsigned int yy, unsigned char ch, int attrs,
1587 unsigned char ch_previous, int attrs_previous)
1588{
1589 uint32_t *theChar;
1590 uint32_t *theCharPrevious;
1591 uint32_t *where;
1592 int i;
1593
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));
1597 } else {
1598 vc_render_char(ch, vc_rendered_char, 32);
1599 theChar = (uint32_t*)(vc_rendered_char);
1600 theCharPrevious = NULL;
1601 }
1602 if (!ch_previous) {
1603 theCharPrevious = NULL;
1604 }
1605 if (attrs_previous) {
1606 theCharPrevious = NULL;
1607 }
1608 where = (uint32_t*)(vinfo.v_baseaddr +
1609 (yy * ISO_CHAR_HEIGHT * vinfo.v_rowbytes) +
1610 (xx * ISO_CHAR_WIDTH * 4));
1611
1612 if (!attrs) for (i = 0; i < ISO_CHAR_HEIGHT; i++) { /* No attrs ? FLY ! */
1613 uint32_t *store = where;
1614 int x;
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);
1619 *store++ = val;
1620 } else {
1621 store++;
1622 }
1623 }
1624
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;
1628 int x;
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)
1633 val = 0xFFFFFFFF;
1634 }
1635 if (attrs & ATTR_REVERSE) val = ~val;
1636 if (attrs & ATTR_UNDER && i == ISO_CHAR_HEIGHT-1) val = ~val;
1637
1638 val = (vc_color_back & ~val) | (vc_color_fore & val);
1639 *store++ = val;
1640 lastpixel = save;
1641 }
1642
1643 where = (uint32_t*)(((unsigned char*)where)+vinfo.v_rowbytes);
1644 }
1645
1646}
1647
1648static void
1649vc_paint_char(unsigned int xx, unsigned int yy, unsigned char ch, int attrs,
1650 unsigned char ch_previous, int attrs_previous)
1651{
1652 if(!vinfo.v_depth)
1653 return;
1654
1655 switch(vinfo.v_depth) {
1656 case 8:
1657 vc_paint_char_8(xx, yy, ch, attrs, ch_previous, attrs_previous);
1658 break;
1659 case 16:
1660 vc_paint_char_16(xx, yy, ch, attrs, ch_previous,
1661 attrs_previous);
1662 break;
1663 case 30:
1664 case 32:
1665 vc_paint_char_32(xx, yy, ch, attrs, ch_previous,
1666 attrs_previous);
1667 break;
1668 }
1669}
1670
1671static void
1672vc_render_font(short newdepth)
1673{
1674 static short olddepth = 0;
1675
1676 int charindex; /* index in ISO font */
1677 unsigned char *rendered_font;
1678 unsigned int rendered_font_size;
1679 int rendered_char_size;
1680 spl_t s;
1681
1682 if (vm_initialized == FALSE) {
1683 return; /* nothing to do */
1684 }
1685 if (olddepth == newdepth && vc_rendered_font) {
1686 return; /* nothing to do */
1687 }
1688
1689 s = splhigh();
1690 VCPUTC_LOCK_LOCK();
1691
1692 rendered_font = vc_rendered_font;
1693 rendered_font_size = vc_rendered_font_size;
1694 rendered_char_size = vc_rendered_char_size;
1695
1696 vc_rendered_font = NULL;
1697 vc_rendered_font_size = 0;
1698 vc_rendered_char_size = 0;
1699
1700 VCPUTC_LOCK_UNLOCK();
1701 splx(s);
1702
1703 if (rendered_font) {
1704 kfree(rendered_font, rendered_font_size);
1705 rendered_font = NULL;
1706 }
1707
1708 if (newdepth) {
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);
1712 }
1713
1714 if (rendered_font == NULL) {
1715 return;
1716 }
1717
1718 for (charindex = ISO_CHAR_MIN; charindex <= ISO_CHAR_MAX; charindex++) {
1719 vc_render_char(charindex, rendered_font + (charindex * rendered_char_size), newdepth);
1720 }
1721
1722 olddepth = newdepth;
1723
1724 s = splhigh();
1725 VCPUTC_LOCK_LOCK();
1726
1727 vc_rendered_font = rendered_font;
1728 vc_rendered_font_size = rendered_font_size;
1729 vc_rendered_char_size = rendered_char_size;
1730
1731 VCPUTC_LOCK_UNLOCK();
1732 splx(s);
1733}
1734
1735static void
1736vc_enable(boolean_t enable)
1737{
1738 vc_render_font(enable ? vinfo.v_depth : 0);
1739}
1740
1741static void
1742vc_reverse_cursor(unsigned int xx, unsigned int yy)
1743{
1744 uint32_t *where;
1745 int line, col;
1746
1747 if(!vinfo.v_depth)
1748 return;
1749
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) {
1755 case 8:
1756 where[0] = ~where[0];
1757 where[1] = ~where[1];
1758 break;
1759 case 16:
1760 for (col = 0; col < 4; col++)
1761 where[col] = ~where[col];
1762 break;
1763 case 32:
1764 for (col = 0; col < 8; col++)
1765 where[col] = ~where[col];
1766 break;
1767 }
1768 where = (uint32_t*)(((unsigned char*)where)+vinfo.v_rowbytes);
1769 }
1770}
1771
1772static void
1773vc_scroll_down(int num, unsigned int scrreg_top, unsigned int scrreg_bottom)
1774{
1775 uint32_t *from, *to, linelongs, i, line, rowline, rowscanline;
1776
1777 if(!vinfo.v_depth)
1778 return;
1779
1780 linelongs = vinfo.v_rowbytes * (ISO_CHAR_HEIGHT >> 2);
1781 rowline = vinfo.v_rowbytes >> 2;
1782 rowscanline = vinfo.v_rowscanbytes >> 2;
1783
1784 to = (uint32_t *) vinfo.v_baseaddr + (linelongs * scrreg_bottom)
1785 - (rowline - rowscanline);
1786 from = to - (linelongs * num); /* handle multiple line scroll (Michel Pollet) */
1787
1788 i = (scrreg_bottom - scrreg_top) - num;
1789
1790 while (i-- > 0) {
1791 for (line = 0; line < ISO_CHAR_HEIGHT; line++) {
1792 /*
1793 * Only copy what is displayed
1794 */
1795 video_scroll_down(from,
1796 (from-(vinfo.v_rowscanbytes >> 2)),
1797 to);
1798
1799 from -= rowline;
1800 to -= rowline;
1801 }
1802 }
1803}
1804
1805static void
1806vc_scroll_up(int num, unsigned int scrreg_top, unsigned int scrreg_bottom)
1807{
1808 uint32_t *from, *to, linelongs, i, line, rowline, rowscanline;
1809
1810 if(!vinfo.v_depth)
1811 return;
1812
1813 linelongs = vinfo.v_rowbytes * (ISO_CHAR_HEIGHT >> 2);
1814 rowline = vinfo.v_rowbytes >> 2;
1815 rowscanline = vinfo.v_rowscanbytes >> 2;
1816
1817 to = (uint32_t *) vinfo.v_baseaddr + (scrreg_top * linelongs);
1818 from = to + (linelongs * num); /* handle multiple line scroll (Michel Pollet) */
1819
1820 i = (scrreg_bottom - scrreg_top) - num;
1821
1822 while (i-- > 0) {
1823 for (line = 0; line < ISO_CHAR_HEIGHT; line++) {
1824 /*
1825 * Only copy what is displayed
1826 */
1827 video_scroll_up(from,
1828 (from+(vinfo.v_rowscanbytes >> 2)),
1829 to);
1830
1831 from += rowline;
1832 to += rowline;
1833 }
1834 }
1835}
1836
1837static void
1838vc_update_color(int color, boolean_t fore)
1839{
1840 if (!vinfo.v_depth)
1841 return;
1842 if (fore) {
1843 vc_color_fore = vc_colors[color][vc_color_index_table[vinfo.v_depth]];
1844 } else {
1845 vc_color_back = vc_colors[color][vc_color_index_table[vinfo.v_depth]];
1846 }
1847}
1848
1849/*
1850 * Video Console (Back-End): Icon Control
1851 * --------------------------------------
1852 */
1853
1854static vc_progress_element * vc_progress;
1855enum { kMaxProgressData = 3 };
1856static const unsigned char * vc_progress_data[kMaxProgressData];
1857static const unsigned char * vc_progress_alpha;
1858static boolean_t vc_progress_enable;
1859static const unsigned char * vc_clut;
1860static const unsigned char * vc_clut8;
1861static unsigned char vc_revclut8[256];
1862static uint32_t vc_progress_interval;
1863static uint32_t vc_progress_count;
1864static uint32_t vc_progress_angle;
1865static uint64_t vc_progress_deadline;
1866static thread_call_data_t vc_progress_call;
1867static boolean_t vc_needsave;
1868static void * vc_saveunder;
1869static vm_size_t vc_saveunder_len;
1870static int8_t vc_uiscale = 1;
1871vc_progress_user_options vc_progress_options;
1872vc_progress_user_options vc_user_options;
1873
1874decl_simple_lock_data(,vc_progress_lock)
1875
1876#if !CONFIG_EMBEDDED
1877static int vc_progress_withmeter = 3;
1878int vc_progressmeter_enable;
1879static int vc_progressmeter_drawn;
1880int vc_progressmeter_value;
1881static uint32_t vc_progressmeter_count;
1882static uint32_t vc_progress_meter_start;
1883static uint32_t vc_progress_meter_end;
1884static uint64_t vc_progressmeter_interval;
1885static uint64_t vc_progressmeter_deadline;
1886static thread_call_data_t vc_progressmeter_call;
1887static void * vc_progressmeter_backbuffer;
1888static boolean_t vc_progressmeter_hold;
1889static uint32_t vc_progressmeter_diskspeed = 256;
1890
1891#endif /* !CONFIG_EMBEDDED */
1892
1893enum {
1894 kSave = 0x10,
1895 kDataIndexed = 0x20,
1896 kDataAlpha = 0x40,
1897 kDataBack = 0x80,
1898 kDataRotate = 0x03,
1899 kDataRotate0 = 0,
1900 kDataRotate90 = 1,
1901 kDataRotate180 = 2,
1902 kDataRotate270 = 3
1903};
1904
1905static 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,
1909 void * backBuffer,
1910 unsigned int flags);
1911static 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);
1917static 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);
1923static 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);
1929static 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);
1935static void vc_progress_task( void * arg0, void * arg );
1936#if !CONFIG_EMBEDDED
1937static void vc_progressmeter_task( void * arg0, void * arg );
1938#endif /* !CONFIG_EMBEDDED */
1939
1940static 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,
1944 void * backBuffer,
1945 unsigned int flags)
1946{
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;
1950
1951 switch( vinfo.v_depth) {
1952 case 8:
1953 if( vc_clut8 == vc_clut)
1954 vc_blit_rect_8( x, y, bx, width, height, sourceRow, backRow, dataPtr, (unsigned char *) backBuffer, flags );
1955 break;
1956 case 16:
1957 vc_blit_rect_16( x, y, bx, width, height, sourceRow, backRow, dataPtr, (unsigned short *) backBuffer, flags );
1958 break;
1959 case 32:
1960 vc_blit_rect_32( x, y, bx, width, height, sourceRow, backRow, dataPtr, (unsigned int *) backBuffer, flags );
1961 break;
1962 case 30:
1963 vc_blit_rect_30( x, y, bx, width, height, sourceRow, backRow, dataPtr, (unsigned int *) backBuffer, flags );
1964 break;
1965 }
1966}
1967
1968static void
1969vc_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)
1975{
1976 volatile unsigned short * dst;
1977 int line, col;
1978 unsigned int data = 0, out = 0;
1979 int sx, sy, a, b, c, d;
1980 int scale = 0x10000;
1981
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;
1988
1989 if (!sourceRow) data = (unsigned int)(uintptr_t)dataPtr;
1990 else if (1 == sourceRow) a = 0;
1991
1992 dst = (volatile unsigned short *) (vinfo.v_baseaddr +
1993 (y * vinfo.v_rowbytes) +
1994 (x * 4));
1995
1996 for( line = 0; line < height; line++)
1997 {
1998 for( col = 0; col < width; col++)
1999 {
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];
2004 else
2005 out = data;
2006 *(dst + col) = out;
2007 }
2008 dst = (volatile unsigned short *) (((volatile char*)dst) + vinfo.v_rowbytes);
2009 }
2010}
2011
2012/* For ARM, 16-bit is 565 (RGB); it is 1555 (XRGB) on other platforms */
2013
2014#ifdef __arm__
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
2027#else
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
2040#endif
2041
2042static 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,
2047 unsigned int flags)
2048{
2049 volatile unsigned short * dst;
2050 int line, col;
2051 unsigned int data = 0, out = 0, back = 0;
2052 int sx, sy, a, b, c, d;
2053 int scale = 0x10000;
2054
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;
2061
2062 if (!sourceRow) data = (unsigned int)(uintptr_t)dataPtr;
2063 else if (1 == sourceRow) a = 0;
2064
2065 if (backPtr)
2066 backPtr += bx;
2067 dst = (volatile unsigned short *) (vinfo.v_baseaddr +
2068 (y * vinfo.v_rowbytes) +
2069 (x * 2));
2070
2071 for( line = 0; line < height; line++)
2072 {
2073 for( col = 0; col < width; col++)
2074 {
2075 if (sourceRow) data = dataPtr[((sx + (col * a) + (line * b)) >> 16)
2076 + sourceRow * (((sy + (col * c) + (line * d)) >> 16))];
2077 if (backPtr) {
2078 if (kSave & flags) {
2079 back = *(dst + col);
2080 *backPtr++ = back;
2081 } else
2082 back = *backPtr++;
2083 }
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)
2096 out = back;
2097 else
2098 out = data;
2099 *(dst + col) = out;
2100 }
2101 dst = (volatile unsigned short *) (((volatile char*)dst) + vinfo.v_rowbytes);
2102 if (backPtr)
2103 backPtr += backRow - width;
2104 }
2105}
2106
2107
2108static 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,
2113 unsigned int flags)
2114{
2115 volatile unsigned int * dst;
2116 int line, col;
2117 unsigned int data = 0, out = 0, back = 0;
2118 int sx, sy, a, b, c, d;
2119 int scale = 0x10000;
2120
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;
2127
2128 if (!sourceRow) data = (unsigned int)(uintptr_t)dataPtr;
2129 else if (1 == sourceRow) a = 0;
2130
2131 if (backPtr)
2132 backPtr += bx;
2133 dst = (volatile unsigned int *) (vinfo.v_baseaddr +
2134 (y * vinfo.v_rowbytes) +
2135 (x * 4));
2136
2137 for( line = 0; line < height; line++)
2138 {
2139 for( col = 0; col < width; col++)
2140 {
2141 if (sourceRow) data = dataPtr[((sx + (col * a) + (line * b)) >> 16)
2142 + sourceRow * (((sy + (col * c) + (line * d)) >> 16))];
2143 if (backPtr) {
2144 if (kSave & flags) {
2145 back = *(dst + col);
2146 *backPtr++ = back;
2147 } else
2148 back = *backPtr++;
2149 }
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)
2159 | (0xff - data);
2160 } else if (kDataBack & flags)
2161 out = back;
2162 else
2163 out = data;
2164 *(dst + col) = out;
2165 }
2166 dst = (volatile unsigned int *) (((volatile char*)dst) + vinfo.v_rowbytes);
2167 if (backPtr)
2168 backPtr += backRow - width;
2169 }
2170}
2171
2172static 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,
2177 unsigned int flags)
2178{
2179 volatile unsigned int * dst;
2180 int line, col;
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;
2185
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;
2192
2193 if (!sourceRow) data = (unsigned int)(uintptr_t)dataPtr;
2194 else if (1 == sourceRow) a = 0;
2195
2196 if (backPtr)
2197 backPtr += bx;
2198 dst = (volatile unsigned int *) (vinfo.v_baseaddr +
2199 (y * vinfo.v_rowbytes) +
2200 (x * 4));
2201
2202 for( line = 0; line < height; line++)
2203 {
2204 for( col = 0; col < width; col++)
2205 {
2206 if (sourceRow) data = dataPtr[((sx + (col * a) + (line * b)) >> 16)
2207 + sourceRow * (((sy + (col * c) + (line * d)) >> 16))];
2208 if (backPtr) {
2209 if (kSave & flags) {
2210 back = *(dst + col);
2211 *backPtr++ = back;
2212 } else
2213 back = *backPtr++;
2214 }
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) {
2220 exp = back;
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)
2228 out = back;
2229 else
2230 out = data;
2231 *(dst + col) = out;
2232 }
2233 dst = (volatile unsigned int *) (((volatile char*)dst) + vinfo.v_rowbytes);
2234 if (backPtr)
2235 backPtr += backRow - width;
2236 }
2237}
2238
2239static void vc_clean_boot_graphics(void)
2240{
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);
2247#endif
2248}
2249
2250/*
2251 * Routines to render the lzss image format
2252 */
2253
2254struct lzss_image_state {
2255 uint32_t col;
2256 uint32_t row;
2257 uint32_t width;
2258 uint32_t height;
2259 uint32_t bytes_per_row;
2260 volatile uint32_t * row_start;
2261 const uint8_t* clut;
2262};
2263typedef struct lzss_image_state lzss_image_state;
2264
2265// returns 0 if OK, 1 if error
2266static inline int
2267vc_decompress_lzss_next_pixel (int next_data, lzss_image_state* state)
2268{
2269 uint32_t palette_index = 0;
2270 uint32_t pixel_value = 0;
2271
2272 palette_index = next_data * 3;
2273
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]);
2277
2278 *(state->row_start + state->col) = pixel_value;
2279
2280 if (++state->col >= state->width) {
2281 state->col = 0;
2282 if (++state->row >= state->height) {
2283 return 1;
2284 }
2285 state->row_start = (volatile uint32_t *) (((uintptr_t)state->row_start) + state->bytes_per_row);
2286 }
2287 return 0;
2288}
2289
2290
2291/*
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.
2295 */
2296
2297/*
2298 * TODO: Does lzss use too much stack? 4096 plus bytes...
2299 * Can probably chop it down by 1/2.
2300 */
2301
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.
2308 PC-VAN SCIENCE
2309 NIFTY-Serve PAF01022
2310 CompuServe 74050,1022
2311
2312**************************************************************/
2313
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 */
2318
2319// returns 0 if OK, 1 if error
2320// x and y indicate upper left corner of image location on screen
2321int
2322vc_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)
2327{
2328 uint32_t* image_start;
2329 uint32_t bytes_per_pixel = 4;
2330 uint32_t bytes_per_row = vinfo.v_rowbytes;
2331
2332 vc_clean_boot_graphics();
2333
2334 image_start = (uint32_t *) (vinfo.v_baseaddr + (dst_y * bytes_per_row) + (dst_x * bytes_per_pixel));
2335
2336 lzss_image_state state = {0, 0, image_width, image_height, bytes_per_row, image_start, clut};
2337
2338 int rval = 0;
2339
2340 const uint8_t *src = compressed_image;
2341 uint32_t srclen = compressed_size;
2342
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;
2346 int i, j, k, r, c;
2347 unsigned int flags;
2348
2349 srcend = src + srclen;
2350 for (i = 0; i < N - F; i++)
2351 text_buf[i] = ' ';
2352 r = N - F;
2353 flags = 0;
2354 for ( ; ; ) {
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 */
2359 if (flags & 1) {
2360 if (src < srcend) c = *src++; else break;
2361 rval = vc_decompress_lzss_next_pixel(c, &state);
2362 if (rval != 0)
2363 return rval;
2364 text_buf[r++] = c;
2365 r &= (N - 1);
2366 } else {
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);
2374 if (rval != 0 )
2375 return rval;
2376 text_buf[r++] = c;
2377 r &= (N - 1);
2378 }
2379 }
2380 }
2381 return 0;
2382}
2383
2384void noroot_icon_test(void) {
2385 boolean_t o_vc_progress_enable = vc_progress_enable;
2386
2387 vc_progress_enable = 1;
2388
2389 PE_display_icon( 0, "noroot");
2390
2391 vc_progress_enable = o_vc_progress_enable;
2392}
2393
2394
2395void vc_display_icon( vc_progress_element * desc,
2396 const unsigned char * data )
2397{
2398 int x, y, width, height;
2399
2400 if( vc_progress_enable && vc_clut) {
2401
2402 vc_clean_boot_graphics();
2403
2404 width = desc->width;
2405 height = desc->height;
2406 x = desc->dx;
2407 y = desc->dy;
2408 if( 1 & desc->flags) {
2409 x += ((vinfo.v_width - width) / 2);
2410 y += ((vinfo.v_height - height) / 2);
2411 }
2412 vc_blit_rect( x, y, 0, width, height, width, 0, data, NULL, kDataIndexed );
2413 }
2414}
2415
2416void
2417vc_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 )
2422{
2423 uint64_t abstime;
2424
2425 if( (!clut) || (!desc) || (!data1x))
2426 return;
2427 vc_clut = clut;
2428 vc_clut8 = clut;
2429
2430 vc_progress = desc;
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;
2437 else
2438 vc_progress_alpha = NULL;
2439
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;
2443
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 */
2449
2450}
2451
2452void
2453vc_progress_set(boolean_t enable, uint32_t vc_delay)
2454{
2455 spl_t s;
2456 void *saveBuf = NULL;
2457 vm_size_t saveLen = 0;
2458 unsigned int count;
2459 unsigned int index;
2460 unsigned char pdata8;
2461 unsigned short pdata16;
2462 unsigned short * buf16;
2463 unsigned int pdata32;
2464 unsigned int * buf32;
2465
2466#if !CONFIG_EMBEDDED
2467
2468 if (kBootArgsFlagBlack & ((boot_args *) PE_state.bootArgs)->flags) return;
2469
2470 if (1 & vc_progress_withmeter)
2471 {
2472 if (enable) internal_enable_progressmeter(kProgressMeterKernel);
2473
2474 s = splhigh();
2475 simple_lock(&vc_progress_lock);
2476
2477 if( vc_progress_enable != enable) {
2478 vc_progress_enable = enable;
2479 if( enable)
2480 {
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);
2486 }
2487 else thread_call_cancel(&vc_progressmeter_call);
2488 }
2489
2490 simple_unlock(&vc_progress_lock);
2491 splx(s);
2492
2493 if (!enable) internal_enable_progressmeter(kProgressMeterOff);
2494 return;
2495 }
2496
2497#endif /* !CONFIG_EMBEDDED */
2498
2499 if(!vc_progress) return;
2500
2501 if( enable) {
2502 saveLen = (vc_progress->width * vc_uiscale) * (vc_progress->height * vc_uiscale) * ((vinfo.v_depth + 7) / 8);
2503 saveBuf = kalloc( saveLen );
2504
2505 switch( vinfo.v_depth) {
2506 case 8 :
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;
2515 break;
2516 }
2517 }
2518 }
2519 memset( saveBuf, 0x01, saveLen );
2520 break;
2521
2522 case 16 :
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;
2529 break;
2530
2531 case 32 :
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;
2538 break;
2539 }
2540 }
2541
2542 s = splhigh();
2543 simple_lock(&vc_progress_lock);
2544
2545 if( vc_progress_enable != enable) {
2546 vc_progress_enable = enable;
2547 if( enable) {
2548 vc_needsave = TRUE;
2549 vc_saveunder = saveBuf;
2550 vc_saveunder_len = saveLen;
2551 saveBuf = NULL;
2552 saveLen = 0;
2553 vc_progress_count = 0;
2554 vc_progress_angle = 0;
2555
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);
2560
2561 } else {
2562 if( vc_saveunder) {
2563 saveBuf = vc_saveunder;
2564 saveLen = vc_saveunder_len;
2565 vc_saveunder = NULL;
2566 vc_saveunder_len = 0;
2567 }
2568
2569 thread_call_cancel(&vc_progress_call);
2570 }
2571 }
2572
2573 simple_unlock(&vc_progress_lock);
2574 splx(s);
2575
2576 if( saveBuf)
2577 kfree( saveBuf, saveLen );
2578}
2579
2580#if !CONFIG_EMBEDDED
2581
2582static uint32_t vc_progressmeter_range(uint32_t pos)
2583{
2584 uint32_t ret;
2585
2586 if (pos > kProgressMeterEnd) pos = kProgressMeterEnd;
2587 ret = vc_progress_meter_start
2588 + ((pos * (vc_progress_meter_end - vc_progress_meter_start)) / kProgressMeterEnd);
2589
2590 return (ret);
2591}
2592
2593static void
2594vc_progressmeter_task(__unused void *arg0, __unused void *arg)
2595{
2596 spl_t s;
2597 uint64_t interval;
2598
2599 s = splhigh();
2600 simple_lock(&vc_progress_lock);
2601 if (vc_progressmeter_enable)
2602 {
2603 uint32_t pos = (vc_progressmeter_count >> 13);
2604 internal_set_progressmeter(vc_progressmeter_range(pos));
2605 if (pos < kProgressMeterEnd)
2606 {
2607 static uint16_t incr[8] = { 10000, 10000, 8192, 4096, 2048, 384, 384, 64 };
2608 vc_progressmeter_count += incr[(pos * 8) / kProgressMeterEnd];
2609
2610 interval = vc_progressmeter_interval;
2611 interval = ((interval * 256) / vc_progressmeter_diskspeed);
2612
2613 clock_deadline_for_periodic_event(interval, mach_absolute_time(), &vc_progressmeter_deadline);
2614 thread_call_enter_delayed(&vc_progressmeter_call, vc_progressmeter_deadline);
2615 }
2616 }
2617 simple_unlock(&vc_progress_lock);
2618 splx(s);
2619}
2620
2621void vc_progress_setdiskspeed(uint32_t speed)
2622{
2623 vc_progressmeter_diskspeed = speed;
2624}
2625
2626#endif /* !CONFIG_EMBEDDED */
2627
2628static void
2629vc_progress_task(__unused void *arg0, __unused void *arg)
2630{
2631 spl_t s;
2632 int x, y, width, height;
2633 uint64_t x_pos, y_pos;
2634 const unsigned char * data;
2635
2636 s = splhigh();
2637 simple_lock(&vc_progress_lock);
2638
2639 if( vc_progress_enable) do {
2640
2641 vc_progress_count++;
2642 if( vc_progress_count >= vc_progress->count) {
2643 vc_progress_count = 0;
2644 vc_progress_angle++;
2645 }
2646
2647 width = (vc_progress->width * vc_uiscale);
2648 height = (vc_progress->height * vc_uiscale);
2649 data = vc_progress_data[vc_uiscale - 1];
2650 if (!data) break;
2651
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) {
2655 case 0:
2656 x_pos = vc_progress_options.x_pos;
2657 y_pos = vc_progress_options.y_pos;
2658 break;
2659 case 2:
2660 x_pos = 0xFFFFFFFF - vc_progress_options.x_pos;
2661 y_pos = 0xFFFFFFFF - vc_progress_options.y_pos;
2662 break;
2663 case 1:
2664 x_pos = 0xFFFFFFFF - vc_progress_options.y_pos;
2665 y_pos = vc_progress_options.x_pos;
2666 break;
2667 case 3:
2668 x_pos = vc_progress_options.y_pos;
2669 y_pos = 0xFFFFFFFF - vc_progress_options.x_pos;
2670 break;
2671 }
2672 x = (uint32_t)((x_pos * (uint64_t) vinfo.v_width) / 0xFFFFFFFFULL);
2673 y = (uint32_t)((y_pos * (uint64_t) vinfo.v_height) / 0xFFFFFFFFULL);
2674 x -= (width / 2);
2675 y -= (height / 2);
2676 } else {
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);
2682 }
2683 }
2684
2685 if ((x + width) > (int)vinfo.v_width) break;
2686 if ((y + height) > (int)vinfo.v_height) break;
2687
2688 data += vc_progress_count * width * height;
2689
2690 vc_blit_rect( x, y, 0,
2691 width, height, width, width,
2692 data, vc_saveunder,
2693 kDataAlpha
2694 | (vc_progress_angle & kDataRotate)
2695 | (vc_needsave ? kSave : 0) );
2696 vc_needsave = FALSE;
2697
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);
2700 }
2701 while (FALSE);
2702 simple_unlock(&vc_progress_lock);
2703 splx(s);
2704}
2705
2706/*
2707 * Generic Console (Front-End): Master Control
2708 * -------------------------------------------
2709 */
2710
2711#if defined (__i386__) || defined (__x86_64__)
2712#include <pexpert/i386/boot.h>
2713#endif
2714
2715static boolean_t gc_acquired = FALSE;
2716static boolean_t gc_graphics_boot = FALSE;
2717static boolean_t gc_desire_text = FALSE;
2718static boolean_t gc_paused_progress;
2719
2720static vm_offset_t lastVideoVirt = 0;
2721static vm_size_t lastVideoMapSize = 0;
2722static boolean_t lastVideoMapKmap = FALSE;
2723
2724static void
2725gc_pause( boolean_t pause, boolean_t graphics_now )
2726{
2727 spl_t s;
2728
2729 s = splhigh( );
2730 VCPUTC_LOCK_LOCK( );
2731
2732 disableConsoleOutput = (pause && !console_is_serial());
2733 gc_enabled = (!pause && !graphics_now);
2734
2735 VCPUTC_LOCK_UNLOCK( );
2736
2737 simple_lock(&vc_progress_lock);
2738
2739 if (pause)
2740 {
2741 gc_paused_progress = vc_progress_enable;
2742 vc_progress_enable = FALSE;
2743 }
2744 else vc_progress_enable = gc_paused_progress;
2745
2746 if (vc_progress_enable)
2747 {
2748#if !CONFIG_EMBEDDED
2749 if (1 & vc_progress_withmeter) thread_call_enter_delayed(&vc_progressmeter_call, vc_progressmeter_deadline);
2750 else
2751#endif /* !CONFIG_EMBEDDED */
2752 thread_call_enter_delayed(&vc_progress_call, vc_progress_deadline);
2753 }
2754
2755 simple_unlock(&vc_progress_lock);
2756 splx(s);
2757}
2758
2759static void
2760vc_initialize(__unused struct vc_info * vinfo_p)
2761{
2762#ifdef __arm__
2763 unsigned long cnt, data16, data32;
2764
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;
2773 }
2774 }
2775#endif
2776
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;
2783}
2784
2785void
2786initialize_screen(PE_Video * boot_vinfo, unsigned int op)
2787{
2788 unsigned int newMapSize = 0;
2789 vm_offset_t newVideoVirt = 0;
2790 boolean_t graphics_now;
2791 uint32_t delay;
2792
2793 if ( boot_vinfo )
2794 {
2795 struct vc_info new_vinfo = vinfo;
2796 boolean_t makeMapping = FALSE;
2797
2798 /*
2799 * Copy parameters
2800 */
2801 if (kPEBaseAddressChange != op)
2802 {
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;
2810 }
2811#if defined(__i386__) || defined(__x86_64__)
2812 new_vinfo.v_type = (unsigned int)boot_vinfo->v_display;
2813#else
2814 new_vinfo.v_type = 0;
2815#endif
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;
2823 }
2824 new_vinfo.v_name[0] = 0;
2825 new_vinfo.v_physaddr = 0;
2826
2827 /*
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.
2830 */
2831 newVideoVirt = boot_vinfo->v_baseAddr;
2832 makeMapping = (kernel_map == VM_MAP_NULL) || (0 != (1 & newVideoVirt));
2833 if (makeMapping)
2834 {
2835 newVideoVirt = 0;
2836 new_vinfo.v_physaddr = boot_vinfo->v_baseAddr & ~3UL; /* Get the physical address */
2837#ifndef __LP64__
2838 new_vinfo.v_physaddr |= (((uint64_t) boot_vinfo->v_baseAddrHigh) << 32);
2839#endif
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) */
2842 }
2843
2844 if (!newVideoVirt && !new_vinfo.v_physaddr) /* Check to see if we have a framebuffer */
2845 {
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 */
2851 gc_acquired = TRUE;
2852 }
2853 else
2854 {
2855 if (makeMapping)
2856 {
2857 unsigned int flags = VM_WIMG_IO;
2858 if (boot_vinfo->v_length != 0)
2859 newMapSize = (unsigned int) round_page(boot_vinfo->v_length);
2860 else
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 */
2863 }
2864 new_vinfo.v_baseaddr = newVideoVirt + boot_vinfo->v_offset; /* Set the new framebuffer address */
2865 }
2866
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);
2870#endif
2871
2872 /* Update the vinfo structure atomically with respect to the vc_progress task if running */
2873 if (vc_progress)
2874 {
2875 simple_lock(&vc_progress_lock);
2876 vinfo = new_vinfo;
2877 simple_unlock(&vc_progress_lock);
2878 }
2879 else
2880 {
2881 vinfo = new_vinfo;
2882 }
2883
2884 // If we changed the virtual address, remove the old mapping
2885 if (newVideoVirt != 0)
2886 {
2887 if (lastVideoVirt && lastVideoMapSize) /* Was the framebuffer mapped before? */
2888 {
2889 /* XXX why only !4K? */
2890 if (!TEST_PAGE_SIZE_4K && lastVideoMapSize)
2891 {
2892 pmap_remove(kernel_pmap, trunc_page_64(lastVideoVirt),
2893 round_page_64(lastVideoVirt + lastVideoMapSize)); /* Toss mappings */
2894 }
2895 /* Was this not a special pre-VM mapping? */
2896 if (lastVideoMapKmap)
2897 {
2898 kmem_free(kernel_map, lastVideoVirt, lastVideoMapSize); /* Toss kernel addresses */
2899 }
2900 }
2901 lastVideoMapKmap = (NULL != kernel_map); /* Remember how mapped */
2902 lastVideoMapSize = newMapSize; /* Remember the size */
2903 lastVideoVirt = newVideoVirt; /* Remember the virtual framebuffer address */
2904 }
2905
2906 if (kPEBaseAddressChange != op)
2907 {
2908 // Graphics mode setup by the booter.
2909
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);
2920 }
2921 }
2922
2923 graphics_now = gc_graphics_boot && !gc_desire_text;
2924 switch ( op )
2925 {
2926 case kPEGraphicsMode:
2927 gc_graphics_boot = TRUE;
2928 gc_desire_text = FALSE;
2929 break;
2930
2931 case kPETextMode:
2932 gc_graphics_boot = FALSE;
2933 break;
2934
2935 case kPEAcquireScreen:
2936 if ( gc_acquired ) break;
2937
2938 vc_progress_options = vc_user_options;
2939 bzero(&vc_user_options, sizeof(vc_user_options));
2940
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;
2944
2945 if (kVCDarkBackground & vc_progress_options.options) vc_progress_white = TRUE;
2946 else if (kVCLightBackground & vc_progress_options.options) vc_progress_white = FALSE;
2947
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 );
2952 gc_acquired = TRUE;
2953 gc_desire_text = FALSE;
2954 break;
2955
2956 case kPEDisableScreen:
2957 if (gc_acquired)
2958 {
2959 gc_pause( TRUE, graphics_now );
2960 }
2961 break;
2962
2963 case kPEEnableScreen:
2964 if (gc_acquired)
2965 {
2966 gc_pause( FALSE, graphics_now );
2967 }
2968 break;
2969
2970 case kPETextScreen:
2971 if ( console_is_serial() ) break;
2972
2973 if ( gc_acquired == FALSE )
2974 {
2975 gc_desire_text = TRUE;
2976 break;
2977 }
2978 if ( gc_graphics_boot == FALSE ) break;
2979
2980 vc_progress_set( FALSE, 0 );
2981#if !CONFIG_EMBEDDED
2982 vc_enable_progressmeter( FALSE );
2983#endif
2984 gc_enable( TRUE );
2985 break;
2986
2987 case kPEReleaseScreen:
2988 gc_acquired = FALSE;
2989 gc_desire_text = FALSE;
2990 gc_enable( FALSE );
2991 if ( gc_graphics_boot == FALSE ) break;
2992
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;
2999#endif
3000 vc_clut8 = NULL;
3001 break;
3002
3003
3004#if !CONFIG_EMBEDDED
3005 case kPERefreshBootGraphics:
3006 {
3007 spl_t s;
3008 boolean_t save;
3009
3010 if (kBootArgsFlagBlack & ((boot_args *) PE_state.bootArgs)->flags) break;
3011
3012 save = vc_progress_white;
3013 vc_progress_white = (0 != (kBootArgsFlagBlackBg & ((boot_args *) PE_state.bootArgs)->flags));
3014
3015 internal_enable_progressmeter(kProgressMeterKernel);
3016
3017 s = splhigh();
3018 simple_lock(&vc_progress_lock);
3019
3020 vc_progressmeter_drawn = 0;
3021 internal_set_progressmeter(vc_progressmeter_range(vc_progressmeter_count >> 13));
3022
3023 simple_unlock(&vc_progress_lock);
3024 splx(s);
3025
3026 internal_enable_progressmeter(kProgressMeterOff);
3027 vc_progress_white = save;
3028 }
3029#endif
3030 }
3031}
3032
3033void vcattach(void); /* XXX gcc 4 warning cleanup */
3034
3035void
3036vcattach(void)
3037{
3038 vm_initialized = TRUE;
3039
3040#if !CONFIG_EMBEDDED
3041 const boot_args * bootargs = (typeof(bootargs)) PE_state.bootArgs;
3042
3043 vc_progress_white = (0 != ((kBootArgsFlagBlackBg | kBootArgsFlagLoginUI)
3044 & bootargs->flags));
3045 PE_parse_boot_argn("meter", &vc_progress_withmeter, sizeof(vc_progress_withmeter));
3046
3047 if (kBootArgsFlagInstallUI & bootargs->flags)
3048 {
3049 vc_progress_meter_start = (bootargs->bootProgressMeterStart * kProgressMeterMax) / 65535;
3050 vc_progress_meter_end = (bootargs->bootProgressMeterEnd * kProgressMeterMax) / 65535;
3051 }
3052 else
3053 {
3054 vc_progress_meter_start = 0;
3055 vc_progress_meter_end = kProgressMeterMax;
3056 }
3057#endif
3058 simple_lock_init(&vc_progress_lock, 0);
3059
3060 if ( gc_graphics_boot == FALSE )
3061 {
3062 long index;
3063
3064 if ( gc_acquired )
3065 {
3066 initialize_screen(NULL, kPEReleaseScreen);
3067 }
3068
3069 initialize_screen(NULL, kPEAcquireScreen);
3070
3071 for ( index = 0 ; index < msgbufp->msg_bufx ; index++ )
3072 {
3073 if (msgbufp->msg_bufc[index] == '\0') {
3074 continue;
3075 }
3076
3077 vcputc( 0, 0, msgbufp->msg_bufc[index] );
3078
3079 if ( msgbufp->msg_bufc[index] == '\n' )
3080 {
3081 vcputc( 0, 0,'\r' );
3082 }
3083 }
3084 }
3085}
3086
3087#if !CONFIG_EMBEDDED
3088
3089// redraw progress meter between pixels x1, x2, position at x3
3090static void
3091vc_draw_progress_meter(unsigned int flags, int x1, int x2, int x3)
3092{
3093 const unsigned char * data;
3094 int x, w;
3095 int ox, oy;
3096 int endCapPos;
3097 int onoff;
3098 // 1 rounded fill, 0 square end
3099 int style = (0 == (2 & vc_progress_withmeter));
3100
3101 ox = ((vinfo.v_width - (kProgressBarWidth * vc_uiscale)) / 2);
3102 oy = vinfo.v_height - (vinfo.v_height / 3) - ((kProgressBarHeight * vc_uiscale) / 2);
3103
3104 if (kDataBack == flags)
3105 {
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);
3110 return;
3111 }
3112
3113 for (x = x1; x < x2; x += w)
3114 {
3115 onoff = (x < x3);
3116 endCapPos = ((style && onoff) ? x3 : (kProgressBarWidth * vc_uiscale));
3117 if (x < (kProgressBarCapWidth * vc_uiscale))
3118 {
3119 if (x2 < (kProgressBarCapWidth * vc_uiscale))
3120 w = x2 - x;
3121 else
3122 w = (kProgressBarCapWidth * vc_uiscale) - x;
3123 data = progressmeter_leftcap[vc_uiscale >= 2][onoff];
3124 data += x;
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);
3130 }
3131 else if (x < (endCapPos - (kProgressBarCapWidth * vc_uiscale)))
3132 {
3133 if (x2 < (endCapPos - (kProgressBarCapWidth * vc_uiscale)))
3134 w = x2 - x;
3135 else
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),
3140 1,
3141 (kProgressBarWidth * vc_uiscale),
3142 data, vc_progressmeter_backbuffer, flags);
3143 }
3144 else
3145 {
3146 w = endCapPos - x;
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);
3154 }
3155 }
3156}
3157
3158extern void IORecordProgressBackbuffer(void * buffer, size_t size, uint32_t theme);
3159
3160static void
3161internal_enable_progressmeter(int new_value)
3162{
3163 spl_t s;
3164 void * new_buffer;
3165 boolean_t stashBackbuffer;
3166
3167 stashBackbuffer = FALSE;
3168 new_buffer = NULL;
3169 if (new_value)
3170 {
3171 new_buffer = kalloc((kProgressBarWidth * vc_uiscale)
3172 * (kProgressBarHeight * vc_uiscale) * sizeof(int));
3173 }
3174
3175 s = splhigh();
3176 simple_lock(&vc_progress_lock);
3177
3178 if (kProgressMeterUser == new_value)
3179 {
3180 if (gc_enabled || !gc_acquired || !gc_graphics_boot
3181 || (kProgressMeterKernel == vc_progressmeter_enable)) new_value = vc_progressmeter_enable;
3182 }
3183
3184 if (new_value != vc_progressmeter_enable)
3185 {
3186 if (new_value)
3187 {
3188 if (kProgressMeterOff == vc_progressmeter_enable)
3189 {
3190 vc_progressmeter_backbuffer = new_buffer;
3191 vc_draw_progress_meter(kDataAlpha | kSave, 0, (kProgressBarWidth * vc_uiscale), 0);
3192 new_buffer = NULL;
3193 vc_progressmeter_drawn = 0;
3194 }
3195 vc_progressmeter_enable = new_value;
3196 }
3197 else if (vc_progressmeter_backbuffer)
3198 {
3199 if (kProgressMeterUser == vc_progressmeter_enable)
3200 {
3201 vc_draw_progress_meter(kDataBack, 0, (kProgressBarWidth * vc_uiscale), vc_progressmeter_drawn);
3202 }
3203 else stashBackbuffer = TRUE;
3204 new_buffer = vc_progressmeter_backbuffer;
3205 vc_progressmeter_backbuffer = NULL;
3206 vc_progressmeter_enable = FALSE;
3207 }
3208 }
3209
3210 simple_unlock(&vc_progress_lock);
3211 splx(s);
3212
3213 if (new_buffer)
3214 {
3215 if (stashBackbuffer) IORecordProgressBackbuffer(new_buffer,
3216 (kProgressBarWidth * vc_uiscale)
3217 * (kProgressBarHeight * vc_uiscale)
3218 * sizeof(int),
3219 vc_progress_white);
3220 kfree(new_buffer, (kProgressBarWidth * vc_uiscale)
3221 * (kProgressBarHeight * vc_uiscale) * sizeof(int));
3222 }
3223}
3224
3225static void
3226internal_set_progressmeter(int new_value)
3227{
3228 int x1, x3;
3229 int capRedraw;
3230 // 1 rounded fill, 0 square end
3231 int style = (0 == (2 & vc_progress_withmeter));
3232
3233 if ((new_value < 0) || (new_value > kProgressMeterMax)) return;
3234
3235 if (vc_progressmeter_enable)
3236 {
3237 vc_progressmeter_value = new_value;
3238
3239 capRedraw = (style ? (kProgressBarCapWidth * vc_uiscale) : 0);
3240 x3 = (((kProgressBarWidth * vc_uiscale) - 2 * capRedraw) * vc_progressmeter_value) / kProgressMeterMax;
3241 x3 += (2 * capRedraw);
3242
3243 if (x3 > vc_progressmeter_drawn)
3244 {
3245 x1 = capRedraw;
3246 if (x1 > vc_progressmeter_drawn) x1 = vc_progressmeter_drawn;
3247 vc_draw_progress_meter(kDataAlpha, vc_progressmeter_drawn - x1, x3, x3);
3248 }
3249 else
3250 {
3251 vc_draw_progress_meter(kDataAlpha, x3 - capRedraw, vc_progressmeter_drawn, x3);
3252 }
3253 vc_progressmeter_drawn = x3;
3254 }
3255}
3256
3257void
3258vc_enable_progressmeter(int new_value)
3259{
3260 if (kProgressMeterKernel == vc_progressmeter_enable)
3261 {
3262 vc_progressmeter_hold = new_value;
3263 }
3264 else
3265 {
3266 internal_enable_progressmeter(new_value ? kProgressMeterUser : kProgressMeterOff);
3267 }
3268}
3269
3270void
3271vc_set_progressmeter(int new_value)
3272{
3273 spl_t s;
3274
3275 s = splhigh();
3276 simple_lock(&vc_progress_lock);
3277
3278 if (vc_progressmeter_enable && (kProgressMeterKernel != vc_progressmeter_enable))
3279 {
3280 internal_set_progressmeter((new_value * kProgressMeterMax) / 100);
3281 }
3282
3283 simple_unlock(&vc_progress_lock);
3284 splx(s);
3285}
3286
3287#endif /* !CONFIG_EMBEDDED */
3288
3289
3290
3291